[alsa-devel] [PATCH 00/11] ARM/ASoC: OMAP McBSP device tree support
Hello,
in order to be able to add DT support for the McBSP driver which is used on all OMAP platforms (OMAP1/2/3/4/5) I needed to make some cleanups to the stack: - Removing callbacks used by the driver for - clock re-parenting (code moved to sound driver) - FSR/CLKR mux configuration (from now on it need to be done at board level) This mux is board specific and depends on the wiring. - OMAP3 sidetone ICLK workaround has been reimplemented using the SYSCONFIG register's SIDLEMODE filed to prevent ICLK gating while ST is running. - Replaced the cpu_is_omap* checks with future proof check. - The FIFO was not enabled on OMAP2430 SoC
It has been tested on BeagleBoard (with legacy and DT boot).
The series changes McBSP related files mostly. It would be great if the whole series could go via audio tree (if the patches are OK and it is fine by Tony).
Regards, Peter --- Peter Ujfalusi (11): ARM/ASoC: omap-mcbsp: Move OMAP2+ clock parenting code to ASoC driver ARM: OMAP2+: McBSP: Do not create legacy devices when booting with DT data ARM: OMAP: mcbsp: Enable FIFO use for OMAP2430 ARM: OMAP: board-am3517evm: Configure McBSP1 CLKR/FSR signal source ASoC: am3517evm: Do not configure McBSP1 CLKR/FSR signal muxing ARM/ASoC: omap-mcbsp: Remove CLKR/FSR mux configuration code ASoC: omap-mcbsp: Sidetone: Use SIDLE bits in SYSCONFIG register to select noidle mode ARM: OMAP3: Remove callback for McBSP sidetone ICLK workaround ASoC: omap-mcbsp: Remove unused defines ASoC: omap-mcbsp: Remove cpu_is_omap* checks from the code ASoC: omap-mcbsp: Add device tree bindings
.../devicetree/bindings/sound/omap-mcbsp.txt | 45 ++++++ arch/arm/mach-omap2/board-am3517evm.c | 13 ++ arch/arm/mach-omap2/mcbsp.c | 152 +------------------- arch/arm/plat-omap/include/plat/mcbsp.h | 3 - sound/soc/omap/am3517evm.c | 20 +--- sound/soc/omap/mcbsp.c | 72 +++++----- sound/soc/omap/mcbsp.h | 4 +- sound/soc/omap/omap-mcbsp.c | 106 ++++++++++----- sound/soc/omap/omap-mcbsp.h | 20 --- 9 files changed, 177 insertions(+), 258 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/omap-mcbsp.txt
Move the McBSP CLKS re-parenting code to ASoC driver from arch/arm/mach-omap2. The call fort the re-parenting has been already limited to OMAP2+ SoC in the ASoC driver. There is no longer need to have callback function for it.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- arch/arm/mach-omap2/mcbsp.c | 40 ------------------------------- arch/arm/plat-omap/include/plat/mcbsp.h | 1 - sound/soc/omap/mcbsp.c | 31 ++++++++++++++++++++---- 3 files changed, 26 insertions(+), 46 deletions(-)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 577cb77..ebc801e 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -101,45 +101,6 @@ static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal, return 0; }
-/* McBSP CLKS source switching function */ -static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk, - const char *src) -{ - struct clk *fck_src; - char *fck_src_name; - int r; - - if (!strcmp(src, "clks_ext")) - fck_src_name = "pad_fck"; - else if (!strcmp(src, "clks_fclk")) - fck_src_name = "prcm_fck"; - else - return -EINVAL; - - fck_src = clk_get(dev, fck_src_name); - if (IS_ERR_OR_NULL(fck_src)) { - pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks", - fck_src_name); - return -EINVAL; - } - - pm_runtime_put_sync(dev); - - r = clk_set_parent(clk, fck_src); - if (IS_ERR_VALUE(r)) { - pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n", - "clks", fck_src_name); - clk_put(fck_src); - return -EINVAL; - } - - pm_runtime_get_sync(dev); - - clk_put(fck_src); - - return 0; -} - static int omap3_enable_st_clock(unsigned int id, bool enable) { unsigned int w; @@ -181,7 +142,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->reg_size = 4; pdata->has_ccr = true; } - pdata->set_clk_src = omap2_mcbsp_set_clk_src;
/* On OMAP2/3 the McBSP1 port has 6 pin configuration */ if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4) diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index 1881412..0a7d5ca 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -47,7 +47,6 @@ struct omap_mcbsp_platform_data { bool has_wakeup; /* Wakeup capability */ bool has_ccr; /* Transceiver has configuration control registers */ int (*enable_st_clock)(unsigned int, bool); - int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src); int (*mux_signal)(struct device *dev, const char *signal, const char *src); };
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index d33c48b..d901fc0 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -24,6 +24,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/pm_runtime.h>
#include <plat/mcbsp.h>
@@ -726,19 +727,39 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx)
int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) { + struct clk *fck_src; const char *src; + int r;
if (fck_src_id == MCBSP_CLKS_PAD_SRC) - src = "clks_ext"; + src = "pad_fck"; else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) - src = "clks_fclk"; + src = "prcm_fck"; else return -EINVAL;
- if (mcbsp->pdata->set_clk_src) - return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src); - else + fck_src = clk_get(mcbsp->dev, src); + if (IS_ERR_OR_NULL(fck_src)) { + dev_err(mcbsp->dev, "CLKS: could not clk_get() %s\n", src); return -EINVAL; + } + + pm_runtime_put_sync(mcbsp->dev); + + r = clk_set_parent(mcbsp->fclk, fck_src); + if (r) { + dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n", + src); + clk_put(fck_src); + return r; + } + + pm_runtime_get_sync(mcbsp->dev); + + clk_put(fck_src); + + return 0; + }
int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux)
Only create the devices in a legacy way if we do not have the DT data.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- arch/arm/mach-omap2/mcbsp.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index ebc801e..57bd7ef 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -15,6 +15,7 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h>
@@ -187,7 +188,8 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
static int __init omap2_mcbsp_init(void) { - omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL); + if (!of_have_populated_dt()) + omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
return 0; }
On OMAP2430 all McBSP ports have 128 word long buffer, enable the use of the FIFO for the audio stack.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- arch/arm/mach-omap2/mcbsp.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 57bd7ef..43899b6 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -152,7 +152,10 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4) pdata->mux_signal = omap4_mcbsp4_mux_rx_clk;
- if (oh->class->rev == MCBSP_CONFIG_TYPE3) { + if (oh->class->rev == MCBSP_CONFIG_TYPE2) { + /* The FIFO has 128 locations */ + pdata->buffer_size = 0x80; + } else if (oh->class->rev == MCBSP_CONFIG_TYPE3) { if (id == 2) /* The FIFO has 1024 + 256 locations */ pdata->buffer_size = 0x500;
am3517evm board uses McBSP1 for audio with 4pin configuration. The CLKR/FSR signals need to be connected to CLKX/FSX pin of the SoC in this case.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- arch/arm/mach-omap2/board-am3517evm.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 18f6010..592812a 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -264,6 +264,16 @@ static __init void am3517_evm_musb_init(void) usb_musb_init(&musb_board_data); }
+static __init void am3517_evm_mcbsp1_init(void) +{ + u32 devconf0; + + /* McBSP1 CLKR/FSR signal to be connected to CLKX/FSX pin */ + devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); + devconf0 |= OMAP2_MCBSP1_CLKR_MASK | OMAP2_MCBSP1_FSR_MASK; + omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0); +} + static const struct usbhs_omap_board_data usbhs_bdata __initconst = { .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \ @@ -373,6 +383,9 @@ static void __init am3517_evm_init(void) /* MUSB */ am3517_evm_musb_init();
+ /* McBSP1 */ + am3517_evm_mcbsp1_init(); + /* MMC init function */ omap_hsmmc_init(mmc); }
The muxing is done at board level, no need to do it in the ASoC machine driver.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/omap/am3517evm.c | 20 ++------------------ 1 files changed, 2 insertions(+), 18 deletions(-)
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 009533a..a997988 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -47,26 +47,10 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, /* Set the codec system clock for DAC and ADC */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN); - if (ret < 0) { + if (ret < 0) printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n"); - return ret; - }
- snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); - return ret; - } - - return 0; + return ret; }
static struct snd_soc_ops am3517evm_ops = {
Remove the feature to configure the CLKR/FSR mux on McBSP port with 6pin configuration. When moving to devicetree these callback can no longer be used in a clean way anymore. If a board require to change the 6pin port to work in 4pin setup it needs to set up the mux in the board file. For OMAP2/3: u32 devconf0;
/* McBSP1 CLKR/FSR signal to be connected to CLKX/FSX pin */ devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); devconf0 |= OMAP2_MCBSP1_CLKR_MASK | OMAP2_MCBSP1_FSR_MASK; omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0);
For OMAP4: u32 mcbsp_pad;
/* McBSP4 CLKR/FSR signal to be connected to CLKX/FSX pin */ mcbsp_pad = omap4_ctrl_pad_readl(OMAP2_CONTROL_DEVCONF0); mcbsp_pad |= ((1 << 31) | (1 << 30)); omap4_ctrl_pad_writel(mcbsp_pad, OMAP2_CONTROL_DEVCONF0);
In case when the kernel is booted with DT blob the pinctrl-single will be provided as soon as it is enabled on the platform.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- arch/arm/mach-omap2/mcbsp.c | 77 ------------------------------- arch/arm/plat-omap/include/plat/mcbsp.h | 1 - sound/soc/omap/mcbsp.c | 31 ------------ sound/soc/omap/mcbsp.h | 3 - sound/soc/omap/omap-mcbsp.c | 32 +------------ sound/soc/omap/omap-mcbsp.h | 4 -- 6 files changed, 3 insertions(+), 145 deletions(-)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 43899b6..d57a357 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -26,8 +26,6 @@ #include <plat/omap_device.h> #include <linux/pm_runtime.h>
-#include "control.h" - /* * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle. * Sidetone needs non-gated ICLK and sidetone autoidle is broken. @@ -35,73 +33,6 @@ #include "cm2xxx_3xxx.h" #include "cm-regbits-34xx.h"
-/* McBSP1 internal signal muxing function for OMAP2/3 */ -static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal, - const char *src) -{ - u32 v; - - v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - - if (!strcmp(signal, "clkr")) { - if (!strcmp(src, "clkr")) - v &= ~OMAP2_MCBSP1_CLKR_MASK; - else if (!strcmp(src, "clkx")) - v |= OMAP2_MCBSP1_CLKR_MASK; - else - return -EINVAL; - } else if (!strcmp(signal, "fsr")) { - if (!strcmp(src, "fsr")) - v &= ~OMAP2_MCBSP1_FSR_MASK; - else if (!strcmp(src, "fsx")) - v |= OMAP2_MCBSP1_FSR_MASK; - else - return -EINVAL; - } else { - return -EINVAL; - } - - omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); - - return 0; -} - -/* McBSP4 internal signal muxing function for OMAP4 */ -#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX (1 << 31) -#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX (1 << 30) -static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal, - const char *src) -{ - u32 v; - - /* - * In CONTROL_MCBSPLP register only bit 30 (CLKR mux), and bit 31 (FSR - * mux) is used */ - v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); - - if (!strcmp(signal, "clkr")) { - if (!strcmp(src, "clkr")) - v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; - else if (!strcmp(src, "clkx")) - v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; - else - return -EINVAL; - } else if (!strcmp(signal, "fsr")) { - if (!strcmp(src, "fsr")) - v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; - else if (!strcmp(src, "fsx")) - v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; - else - return -EINVAL; - } else { - return -EINVAL; - } - - omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); - - return 0; -} - static int omap3_enable_st_clock(unsigned int id, bool enable) { unsigned int w; @@ -144,14 +75,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->has_ccr = true; }
- /* On OMAP2/3 the McBSP1 port has 6 pin configuration */ - if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4) - pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; - - /* On OMAP4 the McBSP4 port has 6 pin configuration */ - if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4) - pdata->mux_signal = omap4_mcbsp4_mux_rx_clk; - if (oh->class->rev == MCBSP_CONFIG_TYPE2) { /* The FIFO has 128 locations */ pdata->buffer_size = 0x80; diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index 0a7d5ca..c78d90b 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -47,7 +47,6 @@ struct omap_mcbsp_platform_data { bool has_wakeup; /* Wakeup capability */ bool has_ccr; /* Transceiver has configuration control registers */ int (*enable_st_clock)(unsigned int, bool); - int (*mux_signal)(struct device *dev, const char *signal, const char *src); };
/** diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index d901fc0..c870023 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -762,37 +762,6 @@ int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
}
-int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) -{ - const char *signal, *src; - - if (!mcbsp->pdata->mux_signal) - return -EINVAL; - - switch (mux) { - case CLKR_SRC_CLKR: - signal = "clkr"; - src = "clkr"; - break; - case CLKR_SRC_CLKX: - signal = "clkr"; - src = "clkx"; - break; - case FSR_SRC_FSR: - signal = "fsr"; - src = "fsr"; - break; - case FSR_SRC_FSX: - signal = "fsr"; - src = "fsx"; - break; - default: - return -EINVAL; - } - - return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src); -} - #define max_thres(m) (mcbsp->pdata->buffer_size) #define valid_threshold(m, val) ((val) <= max_thres(m)) #define THRESHOLD_PROP_BUILDER(prop) \ diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index 262a615..49a6725 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h @@ -334,9 +334,6 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx); /* McBSP functional clock source changing function */ int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id);
-/* McBSP signal muxing API */ -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux); - /* Sidetone specific API */ int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 1046083..5061594 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -516,21 +516,9 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, return -EBUSY; }
- if (clk_id == OMAP_MCBSP_SYSCLK_CLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) { - mcbsp->in_freq = freq; - regs->srgr2 &= ~CLKSM; - regs->pcr0 &= ~SCLKME; - } else if (cpu_class_is_omap1()) { - /* - * McBSP CLKR/FSR signal muxing functions are only available on - * OMAP2 or newer versions - */ - return -EINVAL; - } + mcbsp->in_freq = freq; + regs->srgr2 &= ~CLKSM; + regs->pcr0 &= ~SCLKME;
switch (clk_id) { case OMAP_MCBSP_SYSCLK_CLK: @@ -558,20 +546,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, case OMAP_MCBSP_SYSCLK_CLKR_EXT: regs->pcr0 |= SCLKME; break; - - - case OMAP_MCBSP_CLKR_SRC_CLKR: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR); - break; - case OMAP_MCBSP_CLKR_SRC_CLKX: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX); - break; - case OMAP_MCBSP_FSR_SRC_FSR: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR); - break; - case OMAP_MCBSP_FSR_SRC_FSX: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX); - break; default: err = -ENODEV; } diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index f877b16..baebcee 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -32,10 +32,6 @@ enum omap_mcbsp_clksrg_clk { OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */ - OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */ - OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */ };
/* McBSP dividers */
Instead of the callback (which modifies control module register) use the McBSP module's SYSCONFIG register to disable smart-idle mode when the sidetone is enabled. Store the original SIDLEMODE configuration and restore it when the sidetone has been disabled.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/omap/mcbsp.c | 18 ++++++++++++++---- sound/soc/omap/mcbsp.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index c870023..e008898 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -257,8 +257,15 @@ static void omap_st_on(struct omap_mcbsp *mcbsp) { unsigned int w;
- if (mcbsp->pdata->enable_st_clock) - mcbsp->pdata->enable_st_clock(mcbsp->id, 1); + /* + * Sidetone uses McBSP ICLK - which must not idle when sidetones + * are enabled or sidetones start sounding ugly. + */ + w = MCBSP_READ(mcbsp, SYSCON); + mcbsp->st_data->mcbsp_sidle = (w >> 3) & 0x3; + w &= ~SIDLEMODE(0x3); + w |= SIDLEMODE(0x1); + MCBSP_WRITE(mcbsp, SYSCON, w);
/* Enable McBSP Sidetone */ w = MCBSP_READ(mcbsp, SSELCR); @@ -279,8 +286,11 @@ static void omap_st_off(struct omap_mcbsp *mcbsp) w = MCBSP_READ(mcbsp, SSELCR); MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
- if (mcbsp->pdata->enable_st_clock) - mcbsp->pdata->enable_st_clock(mcbsp->id, 0); + /* Restore the SIDLEMODE as it was before the ST has been started */ + w = MCBSP_READ(mcbsp, SYSCON); + w &= ~SIDLEMODE(0x3); + w |= SIDLEMODE(mcbsp->st_data->mcbsp_sidle); + MCBSP_WRITE(mcbsp, SYSCON, w); }
static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index 49a6725..ba82846 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h @@ -280,6 +280,7 @@ struct omap_mcbsp_st_data { int nr_taps; /* Number of filter coefficients in use */ s16 ch0gain; s16 ch1gain; + unsigned int mcbsp_sidle; };
struct omap_mcbsp {
On 08/08/2012 04:11 AM, Peter Ujfalusi wrote:
Instead of the callback (which modifies control module register) use the McBSP module's SYSCONFIG register to disable smart-idle mode when the sidetone is enabled. Store the original SIDLEMODE configuration and restore it when the sidetone has been disabled.
Is this another case in which it is required to change the idle-mode on a per-use-case basis? In the past I was trying to do the same with HDMI [1]. In that case it was decided to add the HWMOD_SWSUP_SIDLE to hwmod data with the drawback of using no-idle/force-idle rather than smart-idle[2][3].
[1] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg60226.html [2] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70463.html [3] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70653.html
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com
sound/soc/omap/mcbsp.c | 18 ++++++++++++++---- sound/soc/omap/mcbsp.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index c870023..e008898 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -257,8 +257,15 @@ static void omap_st_on(struct omap_mcbsp *mcbsp) { unsigned int w;
- if (mcbsp->pdata->enable_st_clock)
mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
- /*
* Sidetone uses McBSP ICLK - which must not idle when sidetones
* are enabled or sidetones start sounding ugly.
*/
- w = MCBSP_READ(mcbsp, SYSCON);
- mcbsp->st_data->mcbsp_sidle = (w >> 3) & 0x3;
- w &= ~SIDLEMODE(0x3);
- w |= SIDLEMODE(0x1);
- MCBSP_WRITE(mcbsp, SYSCON, w);
Wouldn't this create a mismatch between the SYSCONFIG register and McBSP omap_hwmod._sysc_cache? Perhaps this could be done with a future omap_hwmod API?
Ricardo
/* Enable McBSP Sidetone */ w = MCBSP_READ(mcbsp, SSELCR); @@ -279,8 +286,11 @@ static void omap_st_off(struct omap_mcbsp *mcbsp) w = MCBSP_READ(mcbsp, SSELCR); MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
- if (mcbsp->pdata->enable_st_clock)
mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
/* Restore the SIDLEMODE as it was before the ST has been started */
w = MCBSP_READ(mcbsp, SYSCON);
w &= ~SIDLEMODE(0x3);
w |= SIDLEMODE(mcbsp->st_data->mcbsp_sidle);
MCBSP_WRITE(mcbsp, SYSCON, w); }
static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index 49a6725..ba82846 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h @@ -280,6 +280,7 @@ struct omap_mcbsp_st_data { int nr_taps; /* Number of filter coefficients in use */ s16 ch0gain; s16 ch1gain;
unsigned int mcbsp_sidle; };
struct omap_mcbsp {
Hi Ricardo,
On 08/09/2012 01:12 AM, Ricardo Neri wrote:
Is this another case in which it is required to change the idle-mode on a per-use-case basis? In the past I was trying to do the same with HDMI [1]. In that case it was decided to add the HWMOD_SWSUP_SIDLE to hwmod data with the drawback of using no-idle/force-idle rather than smart-idle[2][3].
This only concerns use case on OMAP3 when the sidetone is in use. In all other use cases we want to use smart-idle (music playback, FM TX/RX, etc). The main problem here is that the sidetone block have broken sidle line, it can not prevent McBSP iclk to be gated. The sidetone block is using the ICLK of the McBSP port (OMAP3 has ST block attached to McBSP2 and 3 ports only).
[1] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg60226.html [2] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70463.html [3] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70653.html
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com
sound/soc/omap/mcbsp.c | 18 ++++++++++++++---- sound/soc/omap/mcbsp.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index c870023..e008898 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -257,8 +257,15 @@ static void omap_st_on(struct omap_mcbsp *mcbsp) { unsigned int w;
- if (mcbsp->pdata->enable_st_clock)
mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
- /*
* Sidetone uses McBSP ICLK - which must not idle when sidetones
* are enabled or sidetones start sounding ugly.
*/
- w = MCBSP_READ(mcbsp, SYSCON);
- mcbsp->st_data->mcbsp_sidle = (w >> 3) & 0x3;
- w &= ~SIDLEMODE(0x3);
- w |= SIDLEMODE(0x1);
- MCBSP_WRITE(mcbsp, SYSCON, w);
Wouldn't this create a mismatch between the SYSCONFIG register and McBSP omap_hwmod._sysc_cache?
We modify the bits runtime (if the ST is enabled), after the hwmod already configured the McBSP port to s-idle. We change the McBSP port's s-idle mode back to it's original before pm_runtime_put().
Previously we did the same thing in PRCM level which was as ugly as this workaround with the penalty of a callback function to mach-omap2 since we can only got access to PRCM register API there.
Perhaps this could be done with a future omap_hwmod API?
But there's no such an API and I'm not aware any ongoing effort to have one. Still the issue mostly remains since we need to modify other block's s-idle mode. If sidetone block is enabled we need to change the McBSP port's s-idle mode to no-idle.
In most of the use cases the McBSP need to be in smart-idle mode since it provides significant power saving.
Hi Peter,
On 08/09/2012 02:05 AM, Peter Ujfalusi wrote:
Hi Ricardo,
On 08/09/2012 01:12 AM, Ricardo Neri wrote:
Is this another case in which it is required to change the idle-mode on a per-use-case basis? In the past I was trying to do the same with HDMI [1]. In that case it was decided to add the HWMOD_SWSUP_SIDLE to hwmod data with the drawback of using no-idle/force-idle rather than smart-idle[2][3].
This only concerns use case on OMAP3 when the sidetone is in use. In all other use cases we want to use smart-idle (music playback, FM TX/RX, etc). The main problem here is that the sidetone block have broken sidle line, it can not prevent McBSP iclk to be gated. The sidetone block is using the ICLK of the McBSP port (OMAP3 has ST block attached to McBSP2 and 3 ports only).
The situation was similar with HDMI. We need no-idle only when playing audio and smart-idle in all other use cases. With HWMOD_SWSUP_SIDLE we are in no-idle/force-idle all the time. :/
[1] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg60226.html [2] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70463.html [3] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70653.html
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com
sound/soc/omap/mcbsp.c | 18 ++++++++++++++---- sound/soc/omap/mcbsp.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index c870023..e008898 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -257,8 +257,15 @@ static void omap_st_on(struct omap_mcbsp *mcbsp) { unsigned int w;
- if (mcbsp->pdata->enable_st_clock)
mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
- /*
* Sidetone uses McBSP ICLK - which must not idle when sidetones
* are enabled or sidetones start sounding ugly.
*/
- w = MCBSP_READ(mcbsp, SYSCON);
- mcbsp->st_data->mcbsp_sidle = (w >> 3) & 0x3;
- w &= ~SIDLEMODE(0x3);
- w |= SIDLEMODE(0x1);
- MCBSP_WRITE(mcbsp, SYSCON, w);
Wouldn't this create a mismatch between the SYSCONFIG register and McBSP omap_hwmod._sysc_cache?
We modify the bits runtime (if the ST is enabled), after the hwmod already configured the McBSP port to s-idle. We change the McBSP port's s-idle mode back to it's original before pm_runtime_put().
Previously we did the same thing in PRCM level which was as ugly as this workaround with the penalty of a callback function to mach-omap2 since we can only got access to PRCM register API there.
Perhaps this could be done with a future omap_hwmod API?
But there's no such an API and I'm not aware any ongoing effort to have one. Still the issue mostly remains since we need to modify other block's s-idle mode. If sidetone block is enabled we need to change the McBSP port's s-idle mode to no-idle.
Would omap_hwmod_set_slave_idlemode make the workaround look less ugly? In this case you are changing other block's idle-mode, though.
In most of the use cases the McBSP need to be in smart-idle mode since it provides significant power saving.
Yes, I was just trying to use this case to justify the need of a driver to be able to set the idle-mode for particular use cases. It would be nice to be able to use an API (present or future) to set to no-idle if required by a particular use-case and still be able to take advantage of smart-idle in other use cases.
Ricardo
We can achieve the same result with SIDLEMODE field within McBSP SYSCONFIG register. The ASoC driver has been modified to use this method and we can now remove the workaround using the control module register.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- arch/arm/mach-omap2/mcbsp.c | 26 -------------------------- arch/arm/plat-omap/include/plat/mcbsp.h | 1 - 2 files changed, 0 insertions(+), 27 deletions(-)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index d57a357..996a15f 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -26,31 +26,6 @@ #include <plat/omap_device.h> #include <linux/pm_runtime.h>
-/* - * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle. - * Sidetone needs non-gated ICLK and sidetone autoidle is broken. - */ -#include "cm2xxx_3xxx.h" -#include "cm-regbits-34xx.h" - -static int omap3_enable_st_clock(unsigned int id, bool enable) -{ - unsigned int w; - - /* - * Sidetone uses McBSP ICLK - which must not idle when sidetones - * are enabled or sidetones start sounding ugly. - */ - w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); - if (enable) - w &= ~(1 << (id - 2)); - else - w |= 1 << (id - 2); - omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); - - return 0; -} - static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) { int id, count = 1; @@ -98,7 +73,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) if (oh->dev_attr) { oh_device[1] = omap_hwmod_lookup(( (struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone); - pdata->enable_st_clock = omap3_enable_st_clock; count++; } pdev = omap_device_build_ss(name, id, oh_device, count, pdata, diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h index c78d90b..698ccd8 100644 --- a/arch/arm/plat-omap/include/plat/mcbsp.h +++ b/arch/arm/plat-omap/include/plat/mcbsp.h @@ -46,7 +46,6 @@ struct omap_mcbsp_platform_data { /* McBSP platform and instance specific features */ bool has_wakeup; /* Wakeup capability */ bool has_ccr; /* Transceiver has configuration control registers */ - int (*enable_st_clock)(unsigned int, bool); };
/**
On 08/08/2012 12:11 PM, Peter Ujfalusi wrote:
We can achieve the same result with SIDLEMODE field within McBSP SYSCONFIG register. The ASoC driver has been modified to use this method and we can now remove the workaround using the control module register.
Are you sure it works without any changes to sidetone audio quality or current consumption? What I remember idlemode was broken at least on 3430 and caused bad sidetone audio if autoidle was set and a little bit higher current consumption (something like 2-3 mA higher where reference consumption was around 10 mA) when McBSP was set to no-idle.
Here's the old thread:
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg52024.html
I think I tested all of this by using arecord >/dev/null | aplay /dev/zero with threshold based DMA transfers with all bells and whistles set for dynamic retention idle in order to hear only McBSP sidetone while measuring current consumption.
But I guess 2-3 mA higher consumption is ok if it simplifies SW a lot and base consumption is anyway much higher than 10 mA when sidetone is in real use (my test above was artificial where actual use is under a phone call with heavy consumption from cellular modem etc).
Hi Jarkko,
On 08/08/2012 04:25 PM, Jarkko Nikula wrote:
On 08/08/2012 12:11 PM, Peter Ujfalusi wrote:
We can achieve the same result with SIDLEMODE field within McBSP SYSCONFIG register. The ASoC driver has been modified to use this method and we can now remove the workaround using the control module register.
Are you sure it works without any changes to sidetone audio quality or current consumption? What I remember idlemode was broken at least on 3430 and caused bad sidetone audio if autoidle was set and a little bit higher current consumption (something like 2-3 mA higher where reference consumption was around 10 mA) when McBSP was set to no-idle.
Yes, the idelmode settings are still broken in the sidetone block. However we are toggling the SIDLEMODE of the corresponding McBSP instance where the ST block is attached. This should have the same effect as doing the same down in PRCM level since the McBSP SIDLEMODE does work correctly preventing ICLK to be gated when it is set to no-idle.
Unfortunately I can not get my BeagleBoard to start gating iclk even if I remove the ICLK gating prevention (on top of 3.6-rc1). So I can not really say for 100% this is equivalent to the the PRCM level workaround. However I have also spend long time hacking around in McBSP, and I know that the SIDLEMODE in McBSP is working correctly. Do you know how can I get OMAP3 to start gating the clocks (to idle)?
Here's the old thread:
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg52024.html
I think I tested all of this by using arecord >/dev/null | aplay /dev/zero with threshold based DMA transfers with all bells and whistles set for dynamic retention idle in order to hear only McBSP sidetone while measuring current consumption.
I'm doing the same test on BeagleBoard, but this thing does not want to hit retention despite all the effort :(
But I guess 2-3 mA higher consumption is ok if it simplifies SW a lot and base consumption is anyway much higher than 10 mA when sidetone is in real use (my test above was artificial where actual use is under a phone call with heavy consumption from cellular modem etc).
Well 2-3 mA is quite big number in my book... I'm still not sure if I ever measured the difference between the PRCM level autoidle prevention compared to the McBSP SIDLEMODE(no_idle).
Having said that, it is suspicious how we ended up doing the ICLK fixup in PRCM level...
Hi Peter
On 08/08/2012 05:00 PM, Peter Ujfalusi wrote:
Are you sure it works without any changes to sidetone audio quality or current consumption? What I remember idlemode was broken at least on 3430 and caused bad sidetone audio if autoidle was set and a little bit higher current consumption (something like 2-3 mA higher where reference consumption was around 10 mA) when McBSP was set to no-idle.
Yes, the idelmode settings are still broken in the sidetone block. However we are toggling the SIDLEMODE of the corresponding McBSP instance where the ST block is attached. This should have the same effect as doing the same down in PRCM level since the McBSP SIDLEMODE does work correctly preventing ICLK to be gated when it is set to no-idle.
Unfortunately I can not get my BeagleBoard to start gating iclk even if I remove the ICLK gating prevention (on top of 3.6-rc1). So I can not really say for 100% this is equivalent to the the PRCM level workaround. However I have also spend long time hacking around in McBSP, and I know that the SIDLEMODE in McBSP is working correctly. Do you know how can I get OMAP3 to start gating the clocks (to idle)?
I got some odd current consumption results from Beagle to really compare different kernel versions but I was able get sensible results from N900.
I tested your set on top of 196973c of sound.git.
First consumption when using threshold based transfer has remained the same between 2.6.38-3.6.0-rc1 (wau!). Active sidetone under "arecord -f dat >/dev/null |aplay -f dat /dev/zero" test increases consumption from plain playback about 17 mA in 3.4 and 3.6.0-rc1.
With your set applied consumption increases 28 mA when the sidetone is active (i.e. +11 mA higher than on top of 196973c). Plain threshold based playback remains still the same.
I'm doing the same test on BeagleBoard, but this thing does not want to hit retention despite all the effort :(
Could it be display subsystem which keeps it active? At least on N900 I need to get DSS drivers activated in order to be able to blank the display after bootloader and thus be able to reach the retention idle.
Hi Jarkko,
On 08/10/2012 04:00 PM, Jarkko Nikula wrote:
I got some odd current consumption results from Beagle to really compare different kernel versions but I was able get sensible results from N900.
I still use my n900 as a main phone so I can not really hack on it :(
I tested your set on top of 196973c of sound.git.
First consumption when using threshold based transfer has remained the same between 2.6.38-3.6.0-rc1 (wau!).
Cool!
Active sidetone under "arecord -f dat >/dev/null |aplay -f dat /dev/zero" test increases consumption from plain playback about 17 mA in 3.4 and 3.6.0-rc1.
With your set applied consumption increases 28 mA when the sidetone is active (i.e. +11 mA higher than on top of 196973c). Plain threshold based playback remains still the same.
Oh. 11mA is huge... Really strange. I would expected smaller (actually zero) difference since in essence both workaround should be doing the same. Only if the OMAP pm core making different decisions runtime when it see that the no-idle is selected in the SYSCONFIG register of McBSP2. But the autogating of clocks should work without SW.
So it seams that we need to do this down at PRCM level?
I'm doing the same test on BeagleBoard, but this thing does not want to hit retention despite all the effort :(
Could it be display subsystem which keeps it active? At least on N900 I need to get DSS drivers activated in order to be able to blank the display after bootloader and thus be able to reach the retention idle.
I tried that as well, but nothing helps. It must be something else which I have overlooked...
NUM_LINKS is no longer in use by the code.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/omap/omap-mcbsp.h | 16 ---------------- 1 files changed, 0 insertions(+), 16 deletions(-)
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index baebcee..ba8386a 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -39,22 +39,6 @@ enum omap_mcbsp_div { OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ };
-#if defined(CONFIG_SOC_OMAP2420) -#define NUM_LINKS 2 -#endif -#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -#undef NUM_LINKS -#define NUM_LINKS 3 -#endif -#if defined(CONFIG_ARCH_OMAP4) -#undef NUM_LINKS -#define NUM_LINKS 4 -#endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430) -#undef NUM_LINKS -#define NUM_LINKS 5 -#endif - int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd);
#endif
We can use the has_ccr flag to replace the cpu_is_omap* checks. This provides future proof implementation and we do not need to update the code if new OMAP revision starts to use the McBSP driver.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/omap/omap-mcbsp.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 5061594..b9770ee 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -398,12 +398,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* Generic McBSP register settings */ regs->spcr2 |= XINTM(3) | FREE; regs->spcr1 |= RINTM(3); - /* RFIG and XFIG are not defined in 34xx */ - if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { + /* RFIG and XFIG are not defined in 2430 and on OMAP3+ */ + if (!mcbsp->pdata->has_ccr) { regs->rcr2 |= RFIG; regs->xcr2 |= XFIG; } - if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { + + /* Configure XCCR/RCCR only for revisions which have ccr registers */ + if (mcbsp->pdata->has_ccr) { regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; }
Device tree support for McBSP modules on OMAP2+ SoC.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- .../devicetree/bindings/sound/omap-mcbsp.txt | 45 +++++++++++++ sound/soc/omap/omap-mcbsp.c | 66 +++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/omap-mcbsp.txt
diff --git a/Documentation/devicetree/bindings/sound/omap-mcbsp.txt b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt new file mode 100644 index 0000000..447cb13 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt @@ -0,0 +1,45 @@ +* Texas Instruments OMAP2+ McBSP module + +Required properties: +- compatible: "ti,omap2420-mcbsp" for McBSP on OMAP2420 + "ti,omap2430-mcbsp" for McBSP on OMAP2430 + "ti,omap3-mcbsp" for McBSP on OMAP3 + "ti,omap4-mcbsp" for McBSP on OMAP4 and newer SoC +- reg: Register location and size, for OMAP4+ as an array: + <MPU access base address, size>, + <L3 interconnect address, size>; +- interrupts: Interrupt numbers for the McBSP port, as an array in case the + McBSP IP have more interrupt lines: + <OCP compliant irq>, + <TX irq>, + <RX irq>; +- interrupt-parent: The parent interrupt controller +- ti,buffer-size: Size of the FIFO on the port (OMAP2430 and newer SoC) +- ti,hwmods: Name of the hwmod associated to the McBSP port + +Sidetone support for OMAP3 McBSP2 and 3 ports: +- sidetone { }: Within this section the following parameters are required: +- reg: Register location and size for the ST block +- interrupts: The interrupt number for the ST block +- interrupt-parent: The parent interrupt controller for the ST block + +Example: + +mcbsp2: mcbsp@49022000 { + compatible = "ti,omap3-mcbsp"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x49022000 0xff>; + interrupts = <0 17 0x4>, /* OCP compliant interrup */ + <0 62 0x4>, /* TX interrup */ + <0 63 0x4>; /* RX interrup */ + interrupt-parent = <&intc>; + ti,buffer-size = <1280>; + ti,hwmods = "mcbsp2"; + + sidetone { + reg = <0x49028000 0xff>; + interrupts = <0 4 0x4>; + interrupt-parent = <&intc>; + }; +}; diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index b9770ee..2e1750e 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -26,6 +26,8 @@ #include <linux/module.h> #include <linux/device.h> #include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -737,13 +739,74 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) } EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
+static struct omap_mcbsp_platform_data omap2420_pdata = { + .reg_step = 4, + .reg_size = 2, +}; + +static struct omap_mcbsp_platform_data omap2430_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, +}; + +static struct omap_mcbsp_platform_data omap3_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, + .has_wakeup = true, +}; + +static struct omap_mcbsp_platform_data omap4_pdata = { + .reg_step = 4, + .reg_size = 4, + .has_ccr = true, + .has_wakeup = true, +}; + +static const struct of_device_id omap_mcbsp_of_match[] = { + { + .compatible = "ti,omap2420-mcbsp", + .data = &omap2420_pdata, + }, + { + .compatible = "ti,omap2430-mcbsp", + .data = &omap2430_pdata, + }, + { + .compatible = "ti,omap3-mcbsp", + .data = &omap3_pdata, + }, + { + .compatible = "ti,omap4-mcbsp", + .data = &omap4_pdata, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match); + static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) { struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); struct omap_mcbsp *mcbsp; + const struct of_device_id *match; int ret;
- if (!pdata) { + match = of_match_device(omap_mcbsp_of_match, &pdev->dev); + if (match) { + struct device_node *node = pdev->dev.of_node; + int buffer_size; + + pdata = devm_kzalloc(&pdev->dev, + sizeof(struct omap_mcbsp_platform_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + memcpy(pdata, match->data, sizeof(*pdata)); + if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size)) + pdata->buffer_size = buffer_size; + } else if (!pdata) { dev_err(&pdev->dev, "missing platform data.\n"); return -EINVAL; } @@ -785,6 +848,7 @@ static struct platform_driver asoc_mcbsp_driver = { .driver = { .name = "omap-mcbsp", .owner = THIS_MODULE, + .of_match_table = omap_mcbsp_of_match, },
.probe = asoc_mcbsp_probe,
On Wed, Aug 08, 2012 at 12:11:30PM +0300, Peter Ujfalusi wrote:
The series changes McBSP related files mostly. It would be great if the whole series could go via audio tree (if the patches are OK and it is fine by Tony).
I'm OK with all the patches, if Tony's happy with me applying them then I'll put them in a separate branch so they can easily be merged into the OMAP trees (or similarly if it's applied in an OMAP tree having a branch I can merge if needed would be good).
On 08/08/2012 02:21 PM, Mark Brown wrote:
On Wed, Aug 08, 2012 at 12:11:30PM +0300, Peter Ujfalusi wrote:
The series changes McBSP related files mostly. It would be great if the whole series could go via audio tree (if the patches are OK and it is fine by Tony).
I'm OK with all the patches, if Tony's happy with me applying them then I'll put them in a separate branch so they can easily be merged into the OMAP trees (or similarly if it's applied in an OMAP tree having a branch I can merge if needed would be good).
I suppose we could apply 1/11, 3-6/11 and 9-10 right away (2/11 perhaps should go near 11/11?) and apply 7-8/11 (sidetone patches that increase consumption) later?
My ack to patches 1, 3-6 and 9-10:
Acked-by: Jarkko Nikula jarkko.nikula@bitmer.com
participants (4)
-
Jarkko Nikula
-
Mark Brown
-
Peter Ujfalusi
-
Ricardo Neri