Message ID | 1466678715-19962-3-git-send-email-s.nawrocki@samsung.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Jun 23, 2016 at 12:45:11PM +0200, Sylwester Nawrocki wrote: > From: Inha Song <ideal.song@samsung.com> > > This patch adds LPASS driver. The LPASS (Low Power Audio Subsystem) > is a special subsystem that supports audio playback with low power > consumption. This is a minimal driver which prepares resources for > IP blocks like I2S, audio DMA and UART. > Also system power ops are added to ensure the Audio Subsystem is > operational after system suspend/resume cycle. This is so trivial that I'm wondering why you even need it, it does essentially nothing except for manage power on and off, and that isn't synced up with the rest of the audio subsystem in any discernable way. Previous Samsung SoCs have quite happily ignored their LPASS subsystems in mainline. As things stand I'm concerned that systems may get broken if more functionality is added without the joining up with the rest of the audio hardware via a card, there's not even the hooks which would allow that.
On 06/29/2016 11:57 PM, Mark Brown wrote: > On Thu, Jun 23, 2016 at 12:45:11PM +0200, Sylwester Nawrocki wrote: ... >> > This patch adds LPASS driver. The LPASS (Low Power Audio Subsystem) >> > is a special subsystem that supports audio playback with low power >> > consumption. This is a minimal driver which prepares resources for >> > IP blocks like I2S, audio DMA and UART. >> > Also system power ops are added to ensure the Audio Subsystem is >> > operational after system suspend/resume cycle. > > This is so trivial that I'm wondering why you even need it, it does > essentially nothing except for manage power on and off, and that isn't > synced up with the rest of the audio subsystem in any discernable way. > Previous Samsung SoCs have quite happily ignored their LPASS subsystems > in mainline. As things stand I'm concerned that systems may get broken > if more functionality is added without the joining up with the rest of > the audio hardware via a card, there's not even the hooks which would > allow that. Sorry, I didn't notice this e-mail earlier. With previous Exynos versions the LPASS (or AudioSS) was mainly about the embedded audio DSP processor (at least WRT to SFRs), which was not required for boards supported in the mainline kernel. Since e.g. Exynos5433 the LPASS SFR region contains also entries related to other IP blocks, like I2S or DMAC. Even though functionality covered by these registers is still rather trivial, like SW resets and unmasking interrupts, it's essential for the whole audio subsystem operation. The intention was to have in future the LPASS driver covering any functionality provided by the embedded audio dedicated MCU. I'm afraid we have to handle those power sequences in central place to ensure proper SoC operation. I would also rather avoid adding any exynos quirks to the PL330 DMAC driver. I agree this driver is currently detached from the rest, while it would be good at the card to ensure the required resources are prepared. How about making LPASS registering a component and then adding it at the card as aux_dev? I would move some parts to the component's probe() callback and with component's probe_order specified a proper initialization sequence could be ensured.
On 06/30/2016 07:16 PM, Sylwester Nawrocki wrote: > How about making LPASS registering a component and then adding it at > the card as aux_dev? I would move some parts to the component's probe() > callback and with component's probe_order specified a proper > initialization sequence could be ensured. I see now it's not a good idea since aux_devs is meant for something different.
On Thu, Jun 30, 2016 at 07:16:46PM +0200, Sylwester Nawrocki wrote: > Sorry, I didn't notice this e-mail earlier. With previous Exynos versions > the LPASS (or AudioSS) was mainly about the embedded audio DSP processor > (at least WRT to SFRs), which was not required for boards supported in > the mainline kernel. Since e.g. Exynos5433 the LPASS SFR region contains > also entries related to other IP blocks, like I2S or DMAC. Even though > functionality covered by these registers is still rather trivial, like > SW resets and unmasking interrupts, it's essential for the whole audio > subsystem operation. The intention was to have in future the LPASS driver > covering any functionality provided by the embedded audio dedicated MCU. > I'm afraid we have to handle those power sequences in central place to > ensure proper SoC operation. I would also rather avoid adding any exynos > quirks to the PL330 DMAC driver. Hrm. This is sounding a bit like a combination of a power domain and an interrupt controller, would something like that fit in perhaps? Depends on how many of these trivial bits there are I think...
On 07/01/2016 05:07 PM, Mark Brown wrote: > On Thu, Jun 30, 2016 at 07:16:46PM +0200, Sylwester Nawrocki wrote: > >> > Sorry, I didn't notice this e-mail earlier. With previous Exynos versions >> > the LPASS (or AudioSS) was mainly about the embedded audio DSP processor >> > (at least WRT to SFRs), which was not required for boards supported in >> > the mainline kernel. Since e.g. Exynos5433 the LPASS SFR region contains >> > also entries related to other IP blocks, like I2S or DMAC. Even though >> > functionality covered by these registers is still rather trivial, like >> > SW resets and unmasking interrupts, it's essential for the whole audio >> > subsystem operation. The intention was to have in future the LPASS driver >> > covering any functionality provided by the embedded audio dedicated MCU. >> > I'm afraid we have to handle those power sequences in central place to >> > ensure proper SoC operation. I would also rather avoid adding any exynos >> > quirks to the PL330 DMAC driver. > > Hrm. This is sounding a bit like a combination of a power domain and > an interrupt controller, would something like that fit in perhaps? > Depends on how many of these trivial bits there are I think... To me LPASS is somehow similar to the camera subsystem, it's a container/ manager for all the audio related sub-IP blocks. The LPASS (top) SFR region contains bits for resetting sub-blocks like: DMAC, SRAM, TIMER, WDT, I2S, UART. It also contains mask and status bits of interrupts from those IP blocks to the CPU or the embedded MCU (CA5). An (incomplete) list of registers can be seen at [1]. There are also entries for software triggered interrupts to the CPU/MCU, for the MCU reset vector control and general purpose register for CPU/MCU communication. In the SoC there is a dedicated power domain for the whole audio subsystem and LPASS also contains a VIC itself. We could try to decompose the LPASS top block into various subsystems but I seriously doubt it's a good way forward. I think LPASS should rather be some top level SoC platform entity. [1] https://goo.gl/JiYbaZ
On Fri, Jul 01, 2016 at 06:31:33PM +0200, Sylwester Nawrocki wrote: > In the SoC there is a dedicated power domain for the whole audio subsystem > and LPASS also contains a VIC itself. We could try to decompose the LPASS > top block into various subsystems but I seriously doubt it's a good way > forward. I think LPASS should rather be some top level SoC platform entity. So a MFD then?
On 07/02/2016 10:25 AM, Mark Brown wrote: > On Fri, Jul 01, 2016 at 06:31:33PM +0200, Sylwester Nawrocki wrote: > >> > In the SoC there is a dedicated power domain for the whole audio subsystem >> > and LPASS also contains a VIC itself. We could try to decompose the LPASS >> > top block into various subsystems but I seriously doubt it's a good way >> > forward. I think LPASS should rather be some top level SoC platform entity. > > So a MFD then? It might a best match, however I yet need to figure out what to do with the PL330 DMAC which is a child of the amba bus.
On Mon, Jul 04, 2016 at 06:16:55PM +0200, Sylwester Nawrocki wrote: > On 07/02/2016 10:25 AM, Mark Brown wrote: > > So a MFD then? > It might a best match, however I yet need to figure out what to do with > the PL330 DMAC which is a child of the amba bus. There should be nothing in principle that stops you registering AMBA devices like MFDs currently register platform devices, or you could perhaps add platform device registration in the PL330 to let it be registered with either platform or AMBA?
On 07/05/2016 04:25 PM, Mark Brown wrote: > There should be nothing in principle that stops you registering AMBA > devices like MFDs currently register platform devices, or you could > perhaps add platform device registration in the PL330 to let it be > registered with either platform or AMBA? As it turned out of_platform_populate() handles properly AMBA devices by looking at the compatible string. If compatible contains "arm,primecell" then an amba device instead of a platform device is created for a DT node. I used of_platform_populate() instead of mfd_add_devices() in the MFD driver's probe(). Additionally I had to rearrange exynos5433.dtsi and to make the LPASS devices specified as sub-nodes of the LPASS node. It all seems to work fine, I will post v4 so we can continue commenting on the actual patches.
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 5d03f5c..2b919d5 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -8,6 +8,7 @@ snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o snd-soc-samsung-spdif-objs := spdif.o snd-soc-pcm-objs := pcm.o snd-soc-i2s-objs := i2s.o +snd-soc-lpass-objs := lpass.o obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o @@ -18,6 +19,7 @@ obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o +obj-$(CONFIG_SND_SAMSUNG_AUDSS) += snd-soc-lpass.o # S3C24XX Machine Support snd-soc-jive-wm8750-objs := jive_wm8750.o diff --git a/sound/soc/samsung/lpass.c b/sound/soc/samsung/lpass.c new file mode 100644 index 0000000..57198cf --- /dev/null +++ b/sound/soc/samsung/lpass.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2015 - 2016 Samsung Electronics Co., Ltd. + * Inha Song <ideal.song@samsung.com> + * + * Low Power Audio Subsystem driver for Samsung Exynos + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <sound/soc.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> + +#include "lpass.h" + +#define EXYNOS5433_PAD_RETENTION_AUD_OPTION_OFFSET 0x3028 +#define EXYNOS5433_INITIATE_WAKEUP_FROM_LOWPWR_MASK BIT(28) + +struct lpass_info { + struct platform_device *pdev; + void __iomem *reg_sfr; + struct regmap *reg_pmu; +}; + +static void lpass_core_sw_reset(struct lpass_info *lpass, int bit) +{ + unsigned int val; + + val = readl(lpass->reg_sfr + SFR_LPASS_CORE_SW_RESET); + + val &= ~(1 << bit); + writel(val, lpass->reg_sfr + SFR_LPASS_CORE_SW_RESET); + + udelay(100); + + val |= 1 << bit; + writel(val, lpass->reg_sfr + SFR_LPASS_CORE_SW_RESET); +} + +static void lpass_enable(struct lpass_info *lpass) +{ + if (!lpass->reg_pmu) + return; + + /* Unmasks SFR, DMA, I2S Interrupt */ + writel(LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S, + lpass->reg_sfr + SFR_LPASS_INTR_CA5_MASK); + + writel(LPASS_INTR_DMA | LPASS_INTR_I2S | LPASS_INTR_SFR + | LPASS_INTR_UART, + lpass->reg_sfr + SFR_LPASS_INTR_CPU_MASK); + + /* Activate related PADs from retention state */ + regmap_write(lpass->reg_pmu, + EXYNOS5433_PAD_RETENTION_AUD_OPTION_OFFSET, + EXYNOS5433_INITIATE_WAKEUP_FROM_LOWPWR_MASK); + + lpass_core_sw_reset(lpass, SW_RESET_I2S); + lpass_core_sw_reset(lpass, SW_RESET_DMA); + lpass_core_sw_reset(lpass, SW_RESET_MEM); +} + +static void lpass_disable(struct lpass_info *lpass) +{ + if (!lpass->reg_pmu) + return; + + /* Masks SFR, DMA, I2S Interrupt */ + writel(0, lpass->reg_sfr + SFR_LPASS_INTR_CA5_MASK); + + writel(0, lpass->reg_sfr + SFR_LPASS_INTR_CPU_MASK); + + /* Deactivate related PADs from retention state */ + regmap_write(lpass->reg_pmu, + EXYNOS5433_PAD_RETENTION_AUD_OPTION_OFFSET, 0); +} + +static int lpass_probe(struct platform_device *pdev) +{ + struct lpass_info *lpass; + struct device *dev = &pdev->dev; + struct resource *res; + + if (!dev->of_node) { + dev_err(dev, "Failed to get DT node\n"); + return -ENODEV; + } + + lpass = devm_kzalloc(dev, sizeof(*lpass), GFP_KERNEL); + if (!lpass) + return -ENOMEM; + + lpass->pdev = pdev; + platform_set_drvdata(pdev, lpass); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + lpass->reg_sfr = devm_ioremap_resource(dev, res); + if (IS_ERR(lpass->reg_sfr)) + return PTR_ERR(lpass->reg_sfr); + + lpass->reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, + "samsung,pmu-syscon"); + if (IS_ERR(lpass->reg_pmu)) { + dev_err(dev, "Failed to lookup PMU regmap\n"); + return PTR_ERR(lpass->reg_pmu); + } + + lpass_enable(lpass); + + return 0; +} + +static int lpass_suspend(struct device *dev) +{ + struct lpass_info *lpass = dev_get_drvdata(dev); + + lpass_disable(lpass); + + return 0; +} + +static int lpass_resume(struct device *dev) +{ + struct lpass_info *lpass = dev_get_drvdata(dev); + + lpass_enable(lpass); + + return 0; +} + +static const struct of_device_id lpass_of_match[] = { + { .compatible = "samsung,exynos5433-lpass", }, + { }, +}; +MODULE_DEVICE_TABLE(of, lpass_of_match); + +static const struct dev_pm_ops lpass_pm_ops = { + .suspend = lpass_suspend, + .resume = lpass_resume, +}; + +static struct platform_driver lpass_driver = { + .driver = { + .name = "samsung-lpass", + .pm = &lpass_pm_ops, + .of_match_table = lpass_of_match, + }, + .probe = lpass_probe, +}; + +module_platform_driver(lpass_driver); + +MODULE_AUTHOR("Inha Song <ideal.song@samsung.com>"); +MODULE_DESCRIPTION("Samsung Low Power Audio Subsystem (LPASS) driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/samsung/lpass.h b/sound/soc/samsung/lpass.h new file mode 100644 index 0000000..59179d6 --- /dev/null +++ b/sound/soc/samsung/lpass.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 - 2016 Samsung Electronics Co., Ltd. + * Inha Song <ideal.song@samsung.com> + * + * Low Power Audio Subsystem driver for Samsung Exynos + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#ifndef SND_SOC_SAMSUNG_LPASS_H_ +#define SND_SOC_SAMSUNG_LPASS_H_ + +/* SFR */ +#define SFR_LPASS_CORE_SW_RESET (0x08) +#define SFR_LPASS_INTR_CA5_MASK (0x48) +#define SFR_LPASS_INTR_CPU_MASK (0x58) + +/* SW_RESET */ +#define LPASS_SW_RESET_CA5 (1 << 0) +#define LPASS_SW_RESET_SB (1 << 11) + +/* Interrupt mask */ +#define LPASS_INTR_APM (1 << 9) +#define LPASS_INTR_MIF (1 << 8) +#define LPASS_INTR_TIMER (1 << 7) +#define LPASS_INTR_DMA (1 << 6) +#define LPASS_INTR_GPIO (1 << 5) +#define LPASS_INTR_I2S (1 << 4) +#define LPASS_INTR_PCM (1 << 3) +#define LPASS_INTR_SB (1 << 2) +#define LPASS_INTR_UART (1 << 1) +#define LPASS_INTR_SFR (1 << 0) + +/* SW Reset bit */ +enum { + SW_RESET_DMA = 0, + SW_RESET_MEM, + SW_RESET_TIMER, + SW_RESET_I2S = 8, + SW_RESET_PCM, + SW_RESET_UART, + SW_RESET_SLIMBUS, +}; + +#endif /* SND_SOC_SAMSUNG_LPASS_H_ */