[alsa-devel] [PATCH 00/20] ASoC: add imx-sgtl5000 machine driver working with fsl_ssi
It's the full series adding imx-sgtl5000 machine driver which works with fsl_ssi driver on DT based imx platforms. - Patches 1 ~ 5: Convert audmux driver to a platform driver and move it into ASoC folder. - Patches 6 ~ 12: Merge ASoC imx and fsl folders. - Patches 13 ~17: Make fsl_ssi work for imx. - Patches 18 ~ 20: Add imx-sgtl5000 machine driver which supports DT only.
It's based on sound/for-next and tested on imx51-babbage board with necessary platform/dts changes, which will be posted separately after the ASoC changes get merged.
Regards, Shawn
Richard Zhao (2): ARM: imx: convert audmux to a platform driver ASoC: fsl: add dt support for imx-audmux
Shawn Guo (18): ASoC: imx: move eukrea audmux call into ASoC machine driver ASoC: imx: move phycore audmux call into ASoC machine driver ARM: imx: merge audmux-v1 and audmux-v2 ASoC: imx: move audmux driver into sound/soc/imx ASoC: imx: rename audmux prefix mxc to imx ASoC: imx: move SND_SOC_AC97_BUS selection down to machine driver ASoC: imx: initialize dma_params burstsize just in imx-ssi ASoC: imx: separate imx-pcm bits from imx-ssi driver ASoC: imx: add an explicit Kconfig option for imx-ssi driver ASoC: fsl: separate SSI and DMA Kconfig options ASoC: imx: merge sound/soc/imx into sound/soc/fsl ASoC: fsl: create fsl_utils to accommodate the common functions ASoC: fsl: check property 'compatible' for the machine name ASoC: fsl: make fsl_ssi driver compilable on ARM/IMX ASoC: fsl: remove the fatal error checking on codec-handle ASoC: fsl: let fsl_ssi work with imx pcm and machine drivers ASoC: rename sgtl5000 device tree binding document ASoC: fsl: add imx-sgtl5000 machine driver
.../bindings/sound/imx-audio-sgtl5000.txt | 24 +++ .../devicetree/bindings/sound/imx-audmux.txt | 13 ++ .../{soc/codecs/fsl-sgtl5000.txt => sgtl5000.txt} | 0 arch/arm/mach-imx/Kconfig | 6 - arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | 27 +-- arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c | 1 - arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 24 +-- arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 24 +-- arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 7 + arch/arm/mach-imx/mach-mx31ads.c | 6 + arch/arm/mach-imx/mach-pca100.c | 20 +-- arch/arm/mach-imx/mach-pcm043.c | 20 +-- arch/arm/plat-mxc/Kconfig | 6 - arch/arm/plat-mxc/Makefile | 2 - arch/arm/plat-mxc/audmux-v1.c | 64 ------ arch/arm/plat-mxc/include/mach/audmux.h | 60 ------ sound/soc/Kconfig | 1 - sound/soc/Makefile | 1 - sound/soc/fsl/Kconfig | 124 +++++++++++- sound/soc/fsl/Makefile | 29 +++- sound/soc/{imx => fsl}/eukrea-tlv320.c | 42 ++++- sound/soc/fsl/fsl_ssi.c | 146 ++++++++++---- sound/soc/fsl/fsl_utils.c | 135 +++++++++++++ sound/soc/fsl/fsl_utils.h | 27 +++ .../audmux-v2.c => sound/soc/fsl/imx-audmux.c | 185 +++++++++++++----- sound/soc/fsl/imx-audmux.h | 60 ++++++ sound/soc/{imx => fsl}/imx-pcm-dma-mx2.c | 7 +- sound/soc/{imx => fsl}/imx-pcm-fiq.c | 0 sound/soc/fsl/imx-pcm.c | 105 ++++++++++ sound/soc/fsl/imx-pcm.h | 32 +++ sound/soc/fsl/imx-sgtl5000.c | 210 ++++++++++++++++++++ sound/soc/{imx => fsl}/imx-ssi.c | 92 +--------- sound/soc/{imx => fsl}/imx-ssi.h | 16 +-- sound/soc/fsl/mpc8610_hpcd.c | 159 ++-------------- sound/soc/{imx => fsl}/mx27vis-aic32x4.c | 20 +- sound/soc/fsl/p1022_ds.c | 181 ++---------------- sound/soc/{imx => fsl}/phycore-ac97.c | 27 +++- sound/soc/{imx => fsl}/wm1133-ev1.c | 25 ++-- sound/soc/imx/Kconfig | 60 ------ sound/soc/imx/Makefile | 19 -- 40 files changed, 1163 insertions(+), 844 deletions(-)
It moves eukrea audmux configuration call from board file into ASoC machine driver eukrea-tlv320, so that it gets aligned wm1133-ev1 and mx27vis-aic32x4, and more importantly it will ease the moving of audmux into sound/soc/imx as a platform driver later.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | 20 ------------ arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 17 ---------- arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 17 ---------- sound/soc/imx/eukrea-tlv320.c | 40 +++++++++++++++++++++-- 4 files changed, 36 insertions(+), 58 deletions(-)
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c index 5db3e14..5f2f91d 100644 --- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c @@ -32,7 +32,6 @@ #include <mach/common.h> #include <mach/iomux-mx27.h> #include <mach/hardware.h> -#include <mach/audmux.h>
#include "devices-imx27.h"
@@ -306,25 +305,6 @@ void __init eukrea_mbimx27_baseboard_init(void) mxc_gpio_setup_multiple_pins(eukrea_mbimx27_pins, ARRAY_SIZE(eukrea_mbimx27_pins), "MBIMX27");
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320) \ - || defined(CONFIG_SND_SOC_EUKREA_TLV320_MODULE) - /* SSI unit master I2S codec connected to SSI_PINS_4*/ - mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - MXC_AUDMUX_V1_PCR_SYN | - MXC_AUDMUX_V1_PCR_TFSDIR | - MXC_AUDMUX_V1_PCR_TCLKDIR | - MXC_AUDMUX_V1_PCR_RFSDIR | - MXC_AUDMUX_V1_PCR_RCLKDIR | - MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | - MXC_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | - MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) - ); - mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4, - MXC_AUDMUX_V1_PCR_SYN | - MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) - ); -#endif - imx27_add_imx_uart1(&uart_pdata); imx27_add_imx_uart2(&uart_pdata); #if !defined(MACH_EUKREA_CPUIMX27_USEUART4) diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c index 66e8726..2cf603e 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c @@ -31,7 +31,6 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/mx25.h> -#include <mach/audmux.h>
#include "devices-imx25.h"
@@ -241,22 +240,6 @@ void __init eukrea_mbimxsd25_baseboard_init(void) ARRAY_SIZE(eukrea_mbimxsd_pads))) printk(KERN_ERR "error setting mbimxsd pads !\n");
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320) - /* SSI unit master I2S codec connected to SSI_AUD5*/ - mxc_audmux_v2_configure_port(0, - MXC_AUDMUX_V2_PTCR_SYN | - MXC_AUDMUX_V2_PTCR_TFSDIR | - MXC_AUDMUX_V2_PTCR_TFSEL(4) | - MXC_AUDMUX_V2_PTCR_TCLKDIR | - MXC_AUDMUX_V2_PTCR_TCSEL(4), - MXC_AUDMUX_V2_PDCR_RXDSEL(4) - ); - mxc_audmux_v2_configure_port(4, - MXC_AUDMUX_V2_PTCR_SYN, - MXC_AUDMUX_V2_PDCR_RXDSEL(0) - ); -#endif - imx25_add_imx_uart1(&uart_pdata); imx25_add_imx_fb(&eukrea_mximxsd_fb_pdata); imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata); diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c index 0f0af02..fd8bf8a 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c @@ -38,7 +38,6 @@ #include <mach/hardware.h> #include <mach/common.h> #include <mach/iomux-mx35.h> -#include <mach/audmux.h>
#include "devices-imx35.h"
@@ -252,22 +251,6 @@ void __init eukrea_mbimxsd35_baseboard_init(void) ARRAY_SIZE(eukrea_mbimxsd_pads))) printk(KERN_ERR "error setting mbimxsd pads !\n");
-#if defined(CONFIG_SND_SOC_EUKREA_TLV320) - /* SSI unit master I2S codec connected to SSI_AUD4 */ - mxc_audmux_v2_configure_port(0, - MXC_AUDMUX_V2_PTCR_SYN | - MXC_AUDMUX_V2_PTCR_TFSDIR | - MXC_AUDMUX_V2_PTCR_TFSEL(3) | - MXC_AUDMUX_V2_PTCR_TCLKDIR | - MXC_AUDMUX_V2_PTCR_TCSEL(3), - MXC_AUDMUX_V2_PDCR_RXDSEL(3) - ); - mxc_audmux_v2_configure_port(3, - MXC_AUDMUX_V2_PTCR_SYN, - MXC_AUDMUX_V2_PDCR_RXDSEL(0) - ); -#endif - imx35_add_imx_uart1(&uart_pdata); imx35_add_ipu_core(&mx3_ipu_data); imx35_add_mx3_sdc_fb(&mx3fb_pdata); diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index 1c1fdd1..bfcb6d9 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c @@ -23,6 +23,7 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <asm/mach-types.h> +#include <mach/audmux.h>
#include "../codecs/tlv320aic23.h" #include "imx-ssi.h" @@ -97,12 +98,43 @@ static struct platform_device *eukrea_tlv320_snd_device; static int __init eukrea_tlv320_init(void) { int ret; - - if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd() - && !machine_is_eukrea_cpuimx35sd() - && !machine_is_eukrea_cpuimx51sd()) + int int_port = 0, ext_port; + + if (machine_is_eukrea_cpuimx27()) { + mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, + MXC_AUDMUX_V1_PCR_SYN | + MXC_AUDMUX_V1_PCR_TFSDIR | + MXC_AUDMUX_V1_PCR_TCLKDIR | + MXC_AUDMUX_V1_PCR_RFSDIR | + MXC_AUDMUX_V1_PCR_RCLKDIR | + MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | + MXC_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | + MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) + ); + mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4, + MXC_AUDMUX_V1_PCR_SYN | + MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) + ); + } else if (machine_is_eukrea_cpuimx25sd() || + machine_is_eukrea_cpuimx35sd() || + machine_is_eukrea_cpuimx51sd()) { + ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3; + mxc_audmux_v2_configure_port(int_port, + MXC_AUDMUX_V2_PTCR_SYN | + MXC_AUDMUX_V2_PTCR_TFSDIR | + MXC_AUDMUX_V2_PTCR_TFSEL(ext_port) | + MXC_AUDMUX_V2_PTCR_TCLKDIR | + MXC_AUDMUX_V2_PTCR_TCSEL(ext_port), + MXC_AUDMUX_V2_PDCR_RXDSEL(ext_port) + ); + mxc_audmux_v2_configure_port(ext_port, + MXC_AUDMUX_V2_PTCR_SYN, + MXC_AUDMUX_V2_PDCR_RXDSEL(int_port) + ); + } else { /* return happy. We might run on a totally different machine */ return 0; + }
eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1); if (!eukrea_tlv320_snd_device)
It moves phycore audmux configuration call from board file into ASoC machine driver phycore-ac97 to ease converting audmux into a platform driver later. It moves phycore audmux configuration call from board file into ASoC machine driver phycore-ac97, so that it gets aligned with wm1133-ev1 and mx27vis-aic32x4, and more importantly it will ease the moving of audmux into sound/soc/imx as a platform driver later.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- arch/arm/mach-imx/mach-pca100.c | 13 ------------- arch/arm/mach-imx/mach-pcm043.c | 13 ------------- sound/soc/imx/phycore-ac97.c | 26 +++++++++++++++++++++++++- 3 files changed, 25 insertions(+), 27 deletions(-)
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index d3b9c6b..541152e 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -36,7 +36,6 @@ #include <mach/hardware.h> #include <mach/iomux-mx27.h> #include <asm/mach/time.h> -#include <mach/audmux.h> #include <mach/irqs.h> #include <mach/ulpi.h>
@@ -359,18 +358,6 @@ static void __init pca100_init(void)
imx27_soc_init();
- /* SSI unit */ - mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */ - MXC_AUDMUX_V1_PCR_TFCSEL(3) | - MXC_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */ - MXC_AUDMUX_V1_PCR_RXDSEL(3)); - mxc_audmux_v1_configure_port(3, - MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */ - MXC_AUDMUX_V1_PCR_TFCSEL(0) | - MXC_AUDMUX_V1_PCR_TFSDIR | - MXC_AUDMUX_V1_PCR_RXDSEL(0)); - ret = mxc_gpio_setup_multiple_pins(pca100_pins, ARRAY_SIZE(pca100_pins), "PCA100"); if (ret) diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 06dc106..237474f 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -37,7 +37,6 @@ #include <mach/common.h> #include <mach/iomux-mx35.h> #include <mach/ulpi.h> -#include <mach/audmux.h>
#include "devices-imx35.h"
@@ -362,18 +361,6 @@ static void __init pcm043_init(void)
mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
- mxc_audmux_v2_configure_port(3, - MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ - MXC_AUDMUX_V2_PTCR_TFSEL(0) | - MXC_AUDMUX_V2_PTCR_TFSDIR, - MXC_AUDMUX_V2_PDCR_RXDSEL(0)); - - mxc_audmux_v2_configure_port(0, - MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ - MXC_AUDMUX_V2_PTCR_TCSEL(3) | - MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */ - MXC_AUDMUX_V2_PDCR_RXDSEL(3)); - imx35_add_fec(NULL); platform_add_devices(devices, ARRAY_SIZE(devices)); imx35_add_imx2_wdt(NULL); diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c index 6ac1211..a59692e 100644 --- a/sound/soc/imx/phycore-ac97.c +++ b/sound/soc/imx/phycore-ac97.c @@ -18,6 +18,7 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <asm/mach-types.h> +#include <mach/audmux.h>
static struct snd_soc_card imx_phycore;
@@ -50,9 +51,32 @@ static int __init imx_phycore_init(void) { int ret;
- if (!machine_is_pcm043() && !machine_is_pca100()) + if (machine_is_pca100()) { + mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, + MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */ + MXC_AUDMUX_V1_PCR_TFCSEL(3) | + MXC_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */ + MXC_AUDMUX_V1_PCR_RXDSEL(3)); + mxc_audmux_v1_configure_port(3, + MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */ + MXC_AUDMUX_V1_PCR_TFCSEL(0) | + MXC_AUDMUX_V1_PCR_TFSDIR | + MXC_AUDMUX_V1_PCR_RXDSEL(0)); + } else if (machine_is_pcm043()) { + mxc_audmux_v2_configure_port(3, + MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ + MXC_AUDMUX_V2_PTCR_TFSEL(0) | + MXC_AUDMUX_V2_PTCR_TFSDIR, + MXC_AUDMUX_V2_PDCR_RXDSEL(0)); + mxc_audmux_v2_configure_port(0, + MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ + MXC_AUDMUX_V2_PTCR_TCSEL(3) | + MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */ + MXC_AUDMUX_V2_PDCR_RXDSEL(3)); + } else { /* return happy. We might run on a totally different machine */ return 0; + }
imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1); if (!imx_phycore_snd_ac97_device)
It merges audmux-v1 and audmux-v2 under arch/arm/plat-mxc into one.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- arch/arm/mach-imx/Kconfig | 12 +++--- arch/arm/plat-mxc/Kconfig | 5 +-- arch/arm/plat-mxc/Makefile | 3 +- arch/arm/plat-mxc/audmux-v1.c | 64 --------------------------- arch/arm/plat-mxc/{audmux-v2.c => audmux.c} | 29 +++++++++++- 5 files changed, 34 insertions(+), 79 deletions(-) delete mode 100644 arch/arm/plat-mxc/audmux-v1.c rename arch/arm/plat-mxc/{audmux-v2.c => audmux.c} (89%)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 4defb97..495a854 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -46,7 +46,7 @@ config SOC_IMX21 bool select MACH_MX21 select CPU_ARM926T - select ARCH_MXC_AUDMUX_V1 + select ARCH_MXC_AUDMUX select IMX_HAVE_DMA_V1 select IMX_HAVE_IOMUX_V1 select MXC_AVIC @@ -55,7 +55,7 @@ config SOC_IMX25 bool select ARCH_MX25 select CPU_ARM926T - select ARCH_MXC_AUDMUX_V2 + select ARCH_MXC_AUDMUX select ARCH_MXC_IOMUX_V3 select MXC_AVIC
@@ -63,7 +63,7 @@ config SOC_IMX27 bool select MACH_MX27 select CPU_ARM926T - select ARCH_MXC_AUDMUX_V1 + select ARCH_MXC_AUDMUX select IMX_HAVE_DMA_V1 select IMX_HAVE_IOMUX_V1 select MXC_AVIC @@ -72,7 +72,7 @@ config SOC_IMX31 bool select CPU_V6 select IMX_HAVE_PLATFORM_MXC_RNGA - select ARCH_MXC_AUDMUX_V2 + select ARCH_MXC_AUDMUX select MXC_AVIC select SMP_ON_UP if SMP
@@ -80,7 +80,7 @@ config SOC_IMX35 bool select CPU_V6 select ARCH_MXC_IOMUX_V3 - select ARCH_MXC_AUDMUX_V2 + select ARCH_MXC_AUDMUX select HAVE_EPIT select MXC_AVIC select SMP_ON_UP if SMP @@ -89,7 +89,7 @@ config SOC_IMX5 select CPU_V7 select MXC_TZIC select ARCH_MXC_IOMUX_V3 - select ARCH_MXC_AUDMUX_V2 + select ARCH_MXC_AUDMUX select ARCH_HAS_CPUFREQ select ARCH_MX5 bool diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index dcebb12..0461d16 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -88,10 +88,7 @@ config IMX_HAVE_IOMUX_V1 config ARCH_MXC_IOMUX_V3 bool
-config ARCH_MXC_AUDMUX_V1 - bool - -config ARCH_MXC_AUDMUX_V2 +config ARCH_MXC_AUDMUX bool
config IRAM_ALLOC diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index 076db84f..530c81d 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -14,8 +14,7 @@ obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o obj-$(CONFIG_MXC_PWM) += pwm.o obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_MXC_USE_EPIT) += epit.o -obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o -obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o +obj-$(CONFIG_ARCH_MXC_AUDMUX) += audmux.o obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o ifdef CONFIG_SND_IMX_SOC diff --git a/arch/arm/plat-mxc/audmux-v1.c b/arch/arm/plat-mxc/audmux-v1.c deleted file mode 100644 index 1180bef..0000000 --- a/arch/arm/plat-mxc/audmux-v1.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2009 Pengutronix, Sascha Hauer s.hauer@pengutronix.de - * - * Initial development of this code was funded by - * Phytec Messtechnik GmbH, http://www.phytec.de - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <mach/audmux.h> -#include <mach/hardware.h> - -static void __iomem *audmux_base; - -static unsigned char port_mapping[] = { - 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, -}; - -int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr) -{ - if (!audmux_base) { - printk("%s: not configured\n", __func__); - return -ENOSYS; - } - - if (port >= ARRAY_SIZE(port_mapping)) - return -EINVAL; - - writel(pcr, audmux_base + port_mapping[port]); - - return 0; -} -EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port); - -static int mxc_audmux_v1_init(void) -{ -#ifdef CONFIG_MACH_MX21 - if (cpu_is_mx21()) - audmux_base = MX21_IO_ADDRESS(MX21_AUDMUX_BASE_ADDR); - else -#endif -#ifdef CONFIG_MACH_MX27 - if (cpu_is_mx27()) - audmux_base = MX27_IO_ADDRESS(MX27_AUDMUX_BASE_ADDR); - else -#endif - (void)0; - - return 0; -} - -postcore_initcall(mxc_audmux_v1_init); diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux.c similarity index 89% rename from arch/arm/plat-mxc/audmux-v2.c rename to arch/arm/plat-mxc/audmux.c index 8cced35..f6dc536 100644 --- a/arch/arm/plat-mxc/audmux-v2.c +++ b/arch/arm/plat-mxc/audmux.c @@ -165,6 +165,24 @@ static inline void audmux_debugfs_init(void) } #endif
+static unsigned char port_mapping[] = { + 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, +}; + +int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr) +{ + if (!audmux_base) + return -ENOSYS; + + if (port >= ARRAY_SIZE(port_mapping)) + return -EINVAL; + + writel(pcr, audmux_base + port_mapping[port]); + + return 0; +} +EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port); + int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, unsigned int pdcr) { @@ -184,7 +202,7 @@ int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, } EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port);
-static int mxc_audmux_v2_init(void) +static int mxc_audmux_init(void) { int ret; if (cpu_is_mx51()) { @@ -209,11 +227,16 @@ static int mxc_audmux_v2_init(void) return ret; } audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR); + } else if (cpu_is_mx27()) { + audmux_base = MX27_IO_ADDRESS(MX27_AUDMUX_BASE_ADDR); + } else if (cpu_is_mx21()) { + audmux_base = MX21_IO_ADDRESS(MX21_AUDMUX_BASE_ADDR); }
- audmux_debugfs_init(); + if (!cpu_is_mx2()) + audmux_debugfs_init();
return 0; }
-postcore_initcall(mxc_audmux_v2_init); +postcore_initcall(mxc_audmux_init);
Shawn Guo wrote:
+static unsigned char port_mapping[] = {
- 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
+};
May as well make this a 'const' array while you're at it. And perhaps uint8_t is a better choice than "unsigned char".
On Mon, Mar 05, 2012 at 12:22:07AM +0000, Tabi Timur-B04825 wrote:
Shawn Guo wrote:
+static unsigned char port_mapping[] = {
- 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
+};
May as well make this a 'const' array while you're at it. And perhaps uint8_t is a better choice than "unsigned char".
Okay, will do.
From: Richard Zhao richard.zhao@linaro.org
It coverts audmux to a platform driver, so that it can be moved into sound/soc/imx and adopt device tree support later.
Signed-off-by: Richard Zhao richard.zhao@linaro.org Signed-off-by: Shawn Guo shawn.guo@linaro.org --- arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | 7 ++ arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 7 ++ arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 7 ++ arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 7 ++ arch/arm/mach-imx/mach-mx31ads.c | 6 + arch/arm/mach-imx/mach-pca100.c | 7 ++ arch/arm/mach-imx/mach-pcm043.c | 7 ++ arch/arm/plat-mxc/audmux.c | 127 +++++++++++++++++------- 8 files changed, 140 insertions(+), 35 deletions(-)
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c index 5f2f91d..11cd0a0 100644 --- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c @@ -294,6 +294,10 @@ struct imx_ssi_platform_data eukrea_mbimx27_ssi_pdata __initconst = { .flags = IMX_SSI_DMA | IMX_SSI_USE_I2S_SLAVE, };
+static const struct resource audmux_res[] __initconst = { + DEFINE_RES_MEM(MX27_AUDMUX_BASE_ADDR, SZ_4K), +}; + /* * system init for baseboard usage. Will be called by cpuimx27 init. * @@ -317,6 +321,9 @@ void __init eukrea_mbimx27_baseboard_init(void) i2c_register_board_info(0, eukrea_mbimx27_i2c_devices, ARRAY_SIZE(eukrea_mbimx27_i2c_devices));
+ /* imx27 has the imx21 version audmux */ + imx_add_platform_device("imx21-audmux", 0, audmux_res, + ARRAY_SIZE(audmux_res), NULL, 0); imx27_add_imx_ssi(0, &eukrea_mbimx27_ssi_pdata);
#if defined(CONFIG_TOUCHSCREEN_ADS7846) \ diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c index 2cf603e..2797da8 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c @@ -222,6 +222,10 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = { .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE, };
+static const struct resource audmux_res[] __initconst = { + DEFINE_RES_MEM(MX25_AUDMUX_BASE_ADDR, SZ_16K), +}; + static struct esdhc_platform_data sd1_pdata = { .cd_gpio = GPIO_SD1CD, .cd_type = ESDHC_CD_GPIO, @@ -242,6 +246,9 @@ void __init eukrea_mbimxsd25_baseboard_init(void)
imx25_add_imx_uart1(&uart_pdata); imx25_add_imx_fb(&eukrea_mximxsd_fb_pdata); + /* imx25 has the imx31 version audmux */ + imx_add_platform_device("imx31-audmux", 0, audmux_res, + ARRAY_SIZE(audmux_res), NULL, 0); imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
imx25_add_flexcan1(NULL); diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c index fd8bf8a..1878114 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c @@ -233,6 +233,10 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = { .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE, };
+static const struct resource audmux_res[] __initconst = { + DEFINE_RES_MEM(MX35_AUDMUX_BASE_ADDR, SZ_16K), +}; + static struct esdhc_platform_data sd1_pdata = { .cd_gpio = GPIO_SD1CD, .cd_type = ESDHC_CD_GPIO, @@ -255,6 +259,9 @@ void __init eukrea_mbimxsd35_baseboard_init(void) imx35_add_ipu_core(&mx3_ipu_data); imx35_add_mx3_sdc_fb(&mx3fb_pdata);
+ /* imx35 has the imx31 version audmux */ + imx_add_platform_device("imx31-audmux", 0, audmux_res, + ARRAY_SIZE(audmux_res), NULL, 0); imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
imx35_add_flexcan1(NULL); diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index c2766ae..8f03235 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -240,6 +240,10 @@ static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = { .flags = IMX_SSI_DMA | IMX_SSI_SYN, };
+static const struct resource audmux_res[] __initconst = { + DEFINE_RES_MEM(MX27_AUDMUX_BASE_ADDR, SZ_4K), +}; + static void __init visstrim_m10_board_init(void) { int ret; @@ -251,6 +255,9 @@ static void __init visstrim_m10_board_init(void) if (ret) pr_err("Failed to setup pins (%d)\n", ret);
+ /* imx27 has the imx21 version audmux */ + imx_add_platform_device("imx21-audmux", 0, audmux_res, + ARRAY_SIZE(audmux_res), NULL, 0); imx27_add_imx_ssi(0, &visstrim_m10_ssi_pdata); imx27_add_imx_uart0(&uart_pdata);
diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index 4917aab..f84bd46 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -486,8 +486,14 @@ static unsigned int ssi_pins[] = { MX31_PIN_STXD5__STXD5, };
+static const struct resource audmux_res[] __initconst = { + DEFINE_RES_MEM(MX31_AUDMUX_BASE_ADDR, SZ_16K), +}; + static void __init mxc_init_audio(void) { + imx_add_platform_device("imx31-audmux", 0, audmux_res, + ARRAY_SIZE(audmux_res), NULL, 0); imx31_add_imx_ssi(0, NULL); mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi"); } diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index 541152e..8a491b3 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -240,6 +240,10 @@ static const struct imx_ssi_platform_data pca100_ssi_pdata __initconst = { .flags = IMX_SSI_USE_AC97, };
+static const struct resource audmux_res[] __initconst = { + DEFINE_RES_MEM(MX27_AUDMUX_BASE_ADDR, SZ_4K), +}; + static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void *data) { @@ -363,6 +367,9 @@ static void __init pca100_init(void) if (ret) printk(KERN_ERR "pca100: Failed to setup pins (%d)\n", ret);
+ /* imx27 has the imx21 version audmux */ + imx_add_platform_device("imx21-audmux", 0, audmux_res, + ARRAY_SIZE(audmux_res), NULL, 0); imx27_add_imx_ssi(0, &pca100_ssi_pdata);
imx27_add_imx_uart0(&uart_pdata); diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 237474f..7d6a1e0 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -298,6 +298,10 @@ static const struct imx_ssi_platform_data pcm043_ssi_pdata __initconst = { .flags = IMX_SSI_USE_AC97, };
+static const struct resource audmux_res[] __initconst = { + DEFINE_RES_MEM(MX35_AUDMUX_BASE_ADDR, SZ_16K), +}; + static const struct mxc_nand_platform_data pcm037_nand_board_info __initconst = { .width = 1, @@ -367,6 +371,9 @@ static void __init pcm043_init(void)
imx35_add_imx_uart0(&uart_pdata); imx35_add_mxc_nand(&pcm037_nand_board_info); + /* imx35 has the imx31 version audmux */ + imx_add_platform_device("imx31-audmux", 0, audmux_res, + ARRAY_SIZE(audmux_res), NULL, 0); imx35_add_imx_ssi(0, &pcm043_ssi_pdata);
imx35_add_imx_uart1(&uart_pdata); diff --git a/arch/arm/plat-mxc/audmux.c b/arch/arm/plat-mxc/audmux.c index f6dc536..98f5656 100644 --- a/arch/arm/plat-mxc/audmux.c +++ b/arch/arm/plat-mxc/audmux.c @@ -1,4 +1,6 @@ /* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2012 Linaro Ltd. * Copyright 2009 Pengutronix, Sascha Hauer s.hauer@pengutronix.de * * Initial development of this code was funded by @@ -15,14 +17,16 @@ * GNU General Public License for more details. */
-#include <linux/module.h> -#include <linux/err.h> -#include <linux/io.h> #include <linux/clk.h> #include <linux/debugfs.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/slab.h> #include <mach/audmux.h> -#include <mach/hardware.h> + +#define DRIVER_NAME "imx-audmux"
static struct clk *audmux_clk; static void __iomem *audmux_base; @@ -140,7 +144,7 @@ static const struct file_operations audmux_debugfs_fops = { .llseek = default_llseek, };
-static void audmux_debugfs_init(void) +static void __init audmux_debugfs_init(void) { int i; char buf[20]; @@ -159,18 +163,48 @@ static void audmux_debugfs_init(void) i); } } + +static void __exit audmux_debugfs_remove(void) +{ + debugfs_remove_recursive(audmux_debugfs_root); +} #else static inline void audmux_debugfs_init(void) { } + +static inline void audmux_debugfs_remove(void) +{ +} #endif
+enum imx_audmux_type { + IMX21_AUDMUX, + IMX31_AUDMUX, +} audmux_type; + +static struct platform_device_id imx_audmux_ids[] = { + { + .name = "imx21-audmux", + .driver_data = IMX21_AUDMUX, + }, { + .name = "imx31-audmux", + .driver_data = IMX31_AUDMUX, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, imx_audmux_ids); + static unsigned char port_mapping[] = { 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, };
int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr) { + if (audmux_type != IMX21_AUDMUX) + return -EINVAL; + if (!audmux_base) return -ENOSYS;
@@ -186,6 +220,9 @@ EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port); int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, unsigned int pdcr) { + if (audmux_type != IMX31_AUDMUX) + return -EINVAL; + if (!audmux_base) return -ENOSYS;
@@ -202,41 +239,61 @@ int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, } EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port);
-static int mxc_audmux_init(void) +static int __init imx_audmux_probe(struct platform_device *pdev) { - int ret; - if (cpu_is_mx51()) { - audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR); - } else if (cpu_is_mx31()) { - audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR); - } else if (cpu_is_mx35()) { - audmux_clk = clk_get(NULL, "audmux"); - if (IS_ERR(audmux_clk)) { - ret = PTR_ERR(audmux_clk); - printk(KERN_ERR "%s: cannot get clock: %d\n", __func__, - ret); - return ret; - } - audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR); - } else if (cpu_is_mx25()) { - audmux_clk = clk_get(NULL, "audmux"); - if (IS_ERR(audmux_clk)) { - ret = PTR_ERR(audmux_clk); - printk(KERN_ERR "%s: cannot get clock: %d\n", __func__, - ret); - return ret; - } - audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR); - } else if (cpu_is_mx27()) { - audmux_base = MX27_IO_ADDRESS(MX27_AUDMUX_BASE_ADDR); - } else if (cpu_is_mx21()) { - audmux_base = MX21_IO_ADDRESS(MX21_AUDMUX_BASE_ADDR); + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + audmux_base = devm_request_and_ioremap(&pdev->dev, res); + if (!audmux_base) + return -EADDRNOTAVAIL; + + audmux_clk = clk_get(&pdev->dev, "audmux"); + if (IS_ERR(audmux_clk)) { + dev_dbg(&pdev->dev, "cannot get clock: %ld\n", + PTR_ERR(audmux_clk)); + audmux_clk = NULL; }
- if (!cpu_is_mx2()) + audmux_type = pdev->id_entry->driver_data; + if (audmux_type == IMX31_AUDMUX) audmux_debugfs_init();
return 0; }
-postcore_initcall(mxc_audmux_init); +static int __exit imx_audmux_remove(struct platform_device *pdev) +{ + if (audmux_type == IMX31_AUDMUX) + audmux_debugfs_remove(); + clk_put(audmux_clk); + + return 0; +} + +static struct platform_driver imx_audmux_driver = { + .probe = imx_audmux_probe, + .remove = __exit_p(imx_audmux_remove), + .id_table = imx_audmux_ids, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + } +}; + +static int __init imx_audmux_init(void) +{ + return platform_driver_register(&imx_audmux_driver); +} +subsys_initcall(imx_audmux_init); + +static void __exit imx_audmux_exit(void) +{ + platform_driver_unregister(&imx_audmux_driver); +} +module_exit(imx_audmux_exit); + +MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver"); +MODULE_AUTHOR("Sascha Hauer s.hauer@pengutronix.de"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME);
On Sat, Mar 03, 2012 at 11:19:45PM +0800, Shawn Guo wrote:
From: Richard Zhao richard.zhao@linaro.org
It coverts audmux to a platform driver, so that it can be moved into sound/soc/imx and adopt device tree support later.
Signed-off-by: Richard Zhao richard.zhao@linaro.org Signed-off-by: Shawn Guo shawn.guo@linaro.org
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | 7 ++ arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 7 ++ arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 7 ++ arch/arm/mach-imx/mach-imx27_visstrim_m10.c | 7 ++ arch/arm/mach-imx/mach-mx31ads.c | 6 + arch/arm/mach-imx/mach-pca100.c | 7 ++ arch/arm/mach-imx/mach-pcm043.c | 7 ++ arch/arm/plat-mxc/audmux.c | 127 +++++++++++++++++------- 8 files changed, 140 insertions(+), 35 deletions(-)
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c index 5f2f91d..11cd0a0 100644 --- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c @@ -294,6 +294,10 @@ struct imx_ssi_platform_data eukrea_mbimx27_ssi_pdata __initconst = { .flags = IMX_SSI_DMA | IMX_SSI_USE_I2S_SLAVE, };
+static const struct resource audmux_res[] __initconst = {
- DEFINE_RES_MEM(MX27_AUDMUX_BASE_ADDR, SZ_4K),
+};
/*
- system init for baseboard usage. Will be called by cpuimx27 init.
@@ -317,6 +321,9 @@ void __init eukrea_mbimx27_baseboard_init(void) i2c_register_board_info(0, eukrea_mbimx27_i2c_devices, ARRAY_SIZE(eukrea_mbimx27_i2c_devices));
- /* imx27 has the imx21 version audmux */
- imx_add_platform_device("imx21-audmux", 0, audmux_res,
ARRAY_SIZE(audmux_res), NULL, 0);
The audmux is a device completely internal to the i.MX and is registered without platform_data. I think we should do the device registration somewhere in the SoC specific code and not do it in each board. Also we now have platform_device_register_simple, we shouldn't use the imx_ variant in new code.
Sascha
On Sun, Mar 04, 2012 at 08:00:31PM +0100, Sascha Hauer wrote: ...
The audmux is a device completely internal to the i.MX and is registered without platform_data. I think we should do the device registration somewhere in the SoC specific code and not do it in each board. Also we now have platform_device_register_simple, we shouldn't use the imx_ variant in new code.
Good point. Then we do not need to add audmux device board by board.
As audmux becomes a platform driver and its callers are all ASoC machine drivers, there is no reason to keep it in arch folder, so move it to sound/soc/imx.
One bonus point would be those ASoC machine drivers stop including mach/audmux.h, since it's been moved to sound/soc/imx/imx-audmux.h. This should be a move to the right direction in terms of single kernel image goal.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- arch/arm/mach-imx/Kconfig | 6 ------ arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c | 1 - arch/arm/plat-mxc/Kconfig | 3 --- arch/arm/plat-mxc/Makefile | 1 - sound/soc/imx/Kconfig | 7 +++++++ sound/soc/imx/Makefile | 2 ++ sound/soc/imx/eukrea-tlv320.c | 2 +- .../audmux.c => sound/soc/imx/imx-audmux.c | 3 ++- .../mach/audmux.h => sound/soc/imx/imx-audmux.h | 6 +++--- sound/soc/imx/mx27vis-aic32x4.c | 2 +- sound/soc/imx/phycore-ac97.c | 3 ++- sound/soc/imx/wm1133-ev1.c | 3 +-- 12 files changed, 19 insertions(+), 20 deletions(-) rename arch/arm/plat-mxc/audmux.c => sound/soc/imx/imx-audmux.c (99%) rename arch/arm/plat-mxc/include/mach/audmux.h => sound/soc/imx/imx-audmux.h (96%)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 495a854..3919fba 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -46,7 +46,6 @@ config SOC_IMX21 bool select MACH_MX21 select CPU_ARM926T - select ARCH_MXC_AUDMUX select IMX_HAVE_DMA_V1 select IMX_HAVE_IOMUX_V1 select MXC_AVIC @@ -55,7 +54,6 @@ config SOC_IMX25 bool select ARCH_MX25 select CPU_ARM926T - select ARCH_MXC_AUDMUX select ARCH_MXC_IOMUX_V3 select MXC_AVIC
@@ -63,7 +61,6 @@ config SOC_IMX27 bool select MACH_MX27 select CPU_ARM926T - select ARCH_MXC_AUDMUX select IMX_HAVE_DMA_V1 select IMX_HAVE_IOMUX_V1 select MXC_AVIC @@ -72,7 +69,6 @@ config SOC_IMX31 bool select CPU_V6 select IMX_HAVE_PLATFORM_MXC_RNGA - select ARCH_MXC_AUDMUX select MXC_AVIC select SMP_ON_UP if SMP
@@ -80,7 +76,6 @@ config SOC_IMX35 bool select CPU_V6 select ARCH_MXC_IOMUX_V3 - select ARCH_MXC_AUDMUX select HAVE_EPIT select MXC_AVIC select SMP_ON_UP if SMP @@ -89,7 +84,6 @@ config SOC_IMX5 select CPU_V7 select MXC_TZIC select ARCH_MXC_IOMUX_V3 - select ARCH_MXC_AUDMUX select ARCH_HAS_CPUFREQ select ARCH_MX5 bool diff --git a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c index d817fc8..aaa592f 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c @@ -37,7 +37,6 @@ #include <mach/hardware.h> #include <mach/common.h> #include <mach/iomux-mx51.h> -#include <mach/audmux.h>
#include "devices-imx51.h"
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index 0461d16..c722f9c 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -88,9 +88,6 @@ config IMX_HAVE_IOMUX_V1 config ARCH_MXC_IOMUX_V3 bool
-config ARCH_MXC_AUDMUX - bool - config IRAM_ALLOC bool select GENERIC_ALLOCATOR diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index 530c81d..e81290c 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o obj-$(CONFIG_MXC_PWM) += pwm.o obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_MXC_USE_EPIT) += epit.o -obj-$(CONFIG_ARCH_MXC_AUDMUX) += audmux.o obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o ifdef CONFIG_SND_IMX_SOC diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 192861c..4025eee 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -17,11 +17,15 @@ config SND_MXC_SOC_MX2 select SND_SOC_DMAENGINE_PCM tristate
+config SND_SOC_IMX_AUDMUX + tristate + config SND_MXC_SOC_WM1133_EV1 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL select SND_SOC_WM8350 select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX help Enable support for audio on the i.MX31ADS with the WM1133-EV1 PMIC board with WM8835x fitted. @@ -31,6 +35,7 @@ config SND_SOC_MX27VIS_AIC32X4 depends on MACH_IMX27_VISSTRIM_M10 && I2C select SND_SOC_TLV320AIC32X4 select SND_MXC_SOC_MX2 + select SND_SOC_IMX_AUDMUX help Say Y if you want to add support for SoC audio on Visstrim SM10 board with TLV320AIC32X4 codec. @@ -40,6 +45,7 @@ config SND_SOC_PHYCORE_AC97 depends on MACH_PCM043 || MACH_PCA100 select SND_SOC_WM9712 select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX help Say Y if you want to add support for SoC audio on Phytec phyCORE and phyCARD boards in AC97 mode @@ -53,6 +59,7 @@ config SND_SOC_EUKREA_TLV320 depends on I2C select SND_SOC_TLV320AIC23 select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX help Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index d6d609b..5c40541 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -2,10 +2,12 @@ snd-soc-imx-objs := imx-ssi.o snd-soc-imx-fiq-objs := imx-pcm-fiq.o snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o +snd-soc-imx-audmux-objs := imx-audmux.o
obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o +obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
# i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index bfcb6d9..b375ed4 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c @@ -23,10 +23,10 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <asm/mach-types.h> -#include <mach/audmux.h>
#include "../codecs/tlv320aic23.h" #include "imx-ssi.h" +#include "imx-audmux.h"
#define CODEC_CLOCK 12000000
diff --git a/arch/arm/plat-mxc/audmux.c b/sound/soc/imx/imx-audmux.c similarity index 99% rename from arch/arm/plat-mxc/audmux.c rename to sound/soc/imx/imx-audmux.c index 98f5656..e0d8c4b 100644 --- a/arch/arm/plat-mxc/audmux.c +++ b/sound/soc/imx/imx-audmux.c @@ -24,7 +24,8 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <mach/audmux.h> + +#include "imx-audmux.h"
#define DRIVER_NAME "imx-audmux"
diff --git a/arch/arm/plat-mxc/include/mach/audmux.h b/sound/soc/imx/imx-audmux.h similarity index 96% rename from arch/arm/plat-mxc/include/mach/audmux.h rename to sound/soc/imx/imx-audmux.h index 6fda788..5136d948 100644 --- a/arch/arm/plat-mxc/include/mach/audmux.h +++ b/sound/soc/imx/imx-audmux.h @@ -1,5 +1,5 @@ -#ifndef __MACH_AUDMUX_H -#define __MACH_AUDMUX_H +#ifndef __IMX_AUDMUX_H +#define __IMX_AUDMUX_H
#define MX27_AUDMUX_HPCR1_SSI0 0 #define MX27_AUDMUX_HPCR2_SSI1 1 @@ -57,4 +57,4 @@ int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr); int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, unsigned int pdcr);
-#endif /* __MACH_AUDMUX_H */ +#endif /* __IMX_AUDMUX_H */ diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c index 155899c..dbfad0f 100644 --- a/sound/soc/imx/mx27vis-aic32x4.c +++ b/sound/soc/imx/mx27vis-aic32x4.c @@ -32,11 +32,11 @@ #include <sound/soc-dapm.h> #include <sound/tlv.h> #include <asm/mach-types.h> -#include <mach/audmux.h> #include <mach/iomux-mx27.h>
#include "../codecs/tlv320aic32x4.h" #include "imx-ssi.h" +#include "imx-audmux.h"
#define MX27VIS_AMP_GAIN 0 #define MX27VIS_AMP_MUTE 1 diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c index a59692e..7dab077 100644 --- a/sound/soc/imx/phycore-ac97.c +++ b/sound/soc/imx/phycore-ac97.c @@ -18,7 +18,8 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <asm/mach-types.h> -#include <mach/audmux.h> + +#include "imx-audmux.h"
static struct snd_soc_card imx_phycore;
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c index 37480c9..15056d6 100644 --- a/sound/soc/imx/wm1133-ev1.c +++ b/sound/soc/imx/wm1133-ev1.c @@ -21,10 +21,9 @@ #include <sound/pcm_params.h> #include <sound/soc.h>
-#include <mach/audmux.h> - #include "imx-ssi.h" #include "../codecs/wm8350.h" +#include "imx-audmux.h"
/* There is a silicon mic on the board optionally connected via a solder pad * SP1. Define this to enable it.
It renames the legacy name mxc used in audmux function and macro to imx.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/imx/eukrea-tlv320.c | 44 +++++++++++++++--------------- sound/soc/imx/imx-audmux.c | 30 ++++++++++---------- sound/soc/imx/imx-audmux.h | 58 +++++++++++++++++++------------------- sound/soc/imx/mx27vis-aic32x4.c | 18 ++++++------ sound/soc/imx/phycore-ac97.c | 40 +++++++++++++------------- sound/soc/imx/wm1133-ev1.c | 22 +++++++------- 6 files changed, 106 insertions(+), 106 deletions(-)
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index b375ed4..7d4475c 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c @@ -101,35 +101,35 @@ static int __init eukrea_tlv320_init(void) int int_port = 0, ext_port;
if (machine_is_eukrea_cpuimx27()) { - mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - MXC_AUDMUX_V1_PCR_SYN | - MXC_AUDMUX_V1_PCR_TFSDIR | - MXC_AUDMUX_V1_PCR_TCLKDIR | - MXC_AUDMUX_V1_PCR_RFSDIR | - MXC_AUDMUX_V1_PCR_RCLKDIR | - MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | - MXC_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | - MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) + imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, + IMX_AUDMUX_V1_PCR_SYN | + IMX_AUDMUX_V1_PCR_TFSDIR | + IMX_AUDMUX_V1_PCR_TCLKDIR | + IMX_AUDMUX_V1_PCR_RFSDIR | + IMX_AUDMUX_V1_PCR_RCLKDIR | + IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | + IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | + IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) ); - mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4, - MXC_AUDMUX_V1_PCR_SYN | - MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) + imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4, + IMX_AUDMUX_V1_PCR_SYN | + IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) ); } else if (machine_is_eukrea_cpuimx25sd() || machine_is_eukrea_cpuimx35sd() || machine_is_eukrea_cpuimx51sd()) { ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3; - mxc_audmux_v2_configure_port(int_port, - MXC_AUDMUX_V2_PTCR_SYN | - MXC_AUDMUX_V2_PTCR_TFSDIR | - MXC_AUDMUX_V2_PTCR_TFSEL(ext_port) | - MXC_AUDMUX_V2_PTCR_TCLKDIR | - MXC_AUDMUX_V2_PTCR_TCSEL(ext_port), - MXC_AUDMUX_V2_PDCR_RXDSEL(ext_port) + imx_audmux_v2_configure_port(int_port, + IMX_AUDMUX_V2_PTCR_SYN | + IMX_AUDMUX_V2_PTCR_TFSDIR | + IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) | + IMX_AUDMUX_V2_PTCR_TCLKDIR | + IMX_AUDMUX_V2_PTCR_TCSEL(ext_port), + IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port) ); - mxc_audmux_v2_configure_port(ext_port, - MXC_AUDMUX_V2_PTCR_SYN, - MXC_AUDMUX_V2_PDCR_RXDSEL(int_port) + imx_audmux_v2_configure_port(ext_port, + IMX_AUDMUX_V2_PTCR_SYN, + IMX_AUDMUX_V2_PDCR_RXDSEL(int_port) ); } else { /* return happy. We might run on a totally different machine */ diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/imx/imx-audmux.c index e0d8c4b..d7bf154 100644 --- a/sound/soc/imx/imx-audmux.c +++ b/sound/soc/imx/imx-audmux.c @@ -32,8 +32,8 @@ static struct clk *audmux_clk; static void __iomem *audmux_base;
-#define MXC_AUDMUX_V2_PTCR(x) ((x) * 8) -#define MXC_AUDMUX_V2_PDCR(x) ((x) * 8 + 4) +#define IMX_AUDMUX_V2_PTCR(x) ((x) * 8) +#define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4)
#ifdef CONFIG_DEBUG_FS static struct dentry *audmux_debugfs_root; @@ -80,8 +80,8 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, if (audmux_clk) clk_enable(audmux_clk);
- ptcr = readl(audmux_base + MXC_AUDMUX_V2_PTCR(port)); - pdcr = readl(audmux_base + MXC_AUDMUX_V2_PDCR(port)); + ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port)); + pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port));
if (audmux_clk) clk_disable(audmux_clk); @@ -89,7 +89,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n", pdcr, ptcr);
- if (ptcr & MXC_AUDMUX_V2_PTCR_TFSDIR) + if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR) ret += snprintf(buf + ret, PAGE_SIZE - ret, "TxFS output from %s, ", audmux_port_string((ptcr >> 27) & 0x7)); @@ -97,7 +97,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, ret += snprintf(buf + ret, PAGE_SIZE - ret, "TxFS input, ");
- if (ptcr & MXC_AUDMUX_V2_PTCR_TCLKDIR) + if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR) ret += snprintf(buf + ret, PAGE_SIZE - ret, "TxClk output from %s", audmux_port_string((ptcr >> 22) & 0x7)); @@ -107,11 +107,11 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
- if (ptcr & MXC_AUDMUX_V2_PTCR_SYN) { + if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) { ret += snprintf(buf + ret, PAGE_SIZE - ret, "Port is symmetric"); } else { - if (ptcr & MXC_AUDMUX_V2_PTCR_RFSDIR) + if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR) ret += snprintf(buf + ret, PAGE_SIZE - ret, "RxFS output from %s, ", audmux_port_string((ptcr >> 17) & 0x7)); @@ -119,7 +119,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, ret += snprintf(buf + ret, PAGE_SIZE - ret, "RxFS input, ");
- if (ptcr & MXC_AUDMUX_V2_PTCR_RCLKDIR) + if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR) ret += snprintf(buf + ret, PAGE_SIZE - ret, "RxClk output from %s", audmux_port_string((ptcr >> 12) & 0x7)); @@ -201,7 +201,7 @@ static unsigned char port_mapping[] = { 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, };
-int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr) +int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr) { if (audmux_type != IMX21_AUDMUX) return -EINVAL; @@ -216,9 +216,9 @@ int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
return 0; } -EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port); +EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port);
-int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, +int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, unsigned int pdcr) { if (audmux_type != IMX31_AUDMUX) @@ -230,15 +230,15 @@ int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, if (audmux_clk) clk_enable(audmux_clk);
- writel(ptcr, audmux_base + MXC_AUDMUX_V2_PTCR(port)); - writel(pdcr, audmux_base + MXC_AUDMUX_V2_PDCR(port)); + writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port)); + writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port));
if (audmux_clk) clk_disable(audmux_clk);
return 0; } -EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port); +EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
static int __init imx_audmux_probe(struct platform_device *pdev) { diff --git a/sound/soc/imx/imx-audmux.h b/sound/soc/imx/imx-audmux.h index 5136d948..04ebbab 100644 --- a/sound/soc/imx/imx-audmux.h +++ b/sound/soc/imx/imx-audmux.h @@ -24,37 +24,37 @@ #define MX51_AUDMUX_PORT7 6
/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */ -#define MXC_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff) -#define MXC_AUDMUX_V1_PCR_INMEN (1 << 8) -#define MXC_AUDMUX_V1_PCR_TXRXEN (1 << 10) -#define MXC_AUDMUX_V1_PCR_SYN (1 << 12) -#define MXC_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13) -#define MXC_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20) -#define MXC_AUDMUX_V1_PCR_RCLKDIR (1 << 24) -#define MXC_AUDMUX_V1_PCR_RFSDIR (1 << 25) -#define MXC_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26) -#define MXC_AUDMUX_V1_PCR_TCLKDIR (1 << 30) -#define MXC_AUDMUX_V1_PCR_TFSDIR (1 << 31) +#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff) +#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8) +#define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10) +#define IMX_AUDMUX_V1_PCR_SYN (1 << 12) +#define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13) +#define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20) +#define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24) +#define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25) +#define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26) +#define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30) +#define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31)
/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */ -#define MXC_AUDMUX_V2_PTCR_TFSDIR (1 << 31) -#define MXC_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27) -#define MXC_AUDMUX_V2_PTCR_TCLKDIR (1 << 26) -#define MXC_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22) -#define MXC_AUDMUX_V2_PTCR_RFSDIR (1 << 21) -#define MXC_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17) -#define MXC_AUDMUX_V2_PTCR_RCLKDIR (1 << 16) -#define MXC_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12) -#define MXC_AUDMUX_V2_PTCR_SYN (1 << 11) - -#define MXC_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13) -#define MXC_AUDMUX_V2_PDCR_TXRXEN (1 << 12) -#define MXC_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8) -#define MXC_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff) - -int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr); - -int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, +#define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31) +#define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27) +#define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26) +#define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22) +#define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21) +#define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17) +#define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16) +#define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12) +#define IMX_AUDMUX_V2_PTCR_SYN (1 << 11) + +#define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13) +#define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12) +#define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8) +#define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff) + +int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr); + +int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, unsigned int pdcr);
#endif /* __IMX_AUDMUX_H */ diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c index dbfad0f..976f857 100644 --- a/sound/soc/imx/mx27vis-aic32x4.c +++ b/sound/soc/imx/mx27vis-aic32x4.c @@ -207,16 +207,16 @@ static int __init mx27vis_aic32x4_init(void) }
/* Connect SSI0 as clock slave to SSI1 external pins */ - mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - MXC_AUDMUX_V1_PCR_SYN | - MXC_AUDMUX_V1_PCR_TFSDIR | - MXC_AUDMUX_V1_PCR_TCLKDIR | - MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | - MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) + imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, + IMX_AUDMUX_V1_PCR_SYN | + IMX_AUDMUX_V1_PCR_TFSDIR | + IMX_AUDMUX_V1_PCR_TCLKDIR | + IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | + IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) ); - mxc_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1, - MXC_AUDMUX_V1_PCR_SYN | - MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) + imx_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1, + IMX_AUDMUX_V1_PCR_SYN | + IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) );
ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins, diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c index 7dab077..f8da6dd 100644 --- a/sound/soc/imx/phycore-ac97.c +++ b/sound/soc/imx/phycore-ac97.c @@ -53,27 +53,27 @@ static int __init imx_phycore_init(void) int ret;
if (machine_is_pca100()) { - mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */ - MXC_AUDMUX_V1_PCR_TFCSEL(3) | - MXC_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */ - MXC_AUDMUX_V1_PCR_RXDSEL(3)); - mxc_audmux_v1_configure_port(3, - MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */ - MXC_AUDMUX_V1_PCR_TFCSEL(0) | - MXC_AUDMUX_V1_PCR_TFSDIR | - MXC_AUDMUX_V1_PCR_RXDSEL(0)); + imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, + IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */ + IMX_AUDMUX_V1_PCR_TFCSEL(3) | + IMX_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */ + IMX_AUDMUX_V1_PCR_RXDSEL(3)); + imx_audmux_v1_configure_port(3, + IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */ + IMX_AUDMUX_V1_PCR_TFCSEL(0) | + IMX_AUDMUX_V1_PCR_TFSDIR | + IMX_AUDMUX_V1_PCR_RXDSEL(0)); } else if (machine_is_pcm043()) { - mxc_audmux_v2_configure_port(3, - MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ - MXC_AUDMUX_V2_PTCR_TFSEL(0) | - MXC_AUDMUX_V2_PTCR_TFSDIR, - MXC_AUDMUX_V2_PDCR_RXDSEL(0)); - mxc_audmux_v2_configure_port(0, - MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ - MXC_AUDMUX_V2_PTCR_TCSEL(3) | - MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */ - MXC_AUDMUX_V2_PDCR_RXDSEL(3)); + imx_audmux_v2_configure_port(3, + IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ + IMX_AUDMUX_V2_PTCR_TFSEL(0) | + IMX_AUDMUX_V2_PTCR_TFSDIR, + IMX_AUDMUX_V2_PDCR_RXDSEL(0)); + imx_audmux_v2_configure_port(0, + IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ + IMX_AUDMUX_V2_PTCR_TCSEL(3) | + IMX_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */ + IMX_AUDMUX_V2_PDCR_RXDSEL(3)); } else { /* return happy. We might run on a totally different machine */ return 0; diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c index 15056d6..fe54a69 100644 --- a/sound/soc/imx/wm1133-ev1.c +++ b/sound/soc/imx/wm1133-ev1.c @@ -267,17 +267,17 @@ static int __init wm1133_ev1_audio_init(void) unsigned int ptcr, pdcr;
/* SSI0 mastered by port 5 */ - ptcr = MXC_AUDMUX_V2_PTCR_SYN | - MXC_AUDMUX_V2_PTCR_TFSDIR | - MXC_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) | - MXC_AUDMUX_V2_PTCR_TCLKDIR | - MXC_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); - pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); - mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr); - - ptcr = MXC_AUDMUX_V2_PTCR_SYN; - pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0); - mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr); + ptcr = IMX_AUDMUX_V2_PTCR_SYN | + IMX_AUDMUX_V2_PTCR_TFSDIR | + IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) | + IMX_AUDMUX_V2_PTCR_TCLKDIR | + IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); + pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); + imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr); + + ptcr = IMX_AUDMUX_V2_PTCR_SYN; + pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0); + imx_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1); if (!wm1133_ev1_snd_device)
SND_SOC_AC97_BUS is selected to enable the AC97 support in soc-core. Rather than selecting the option under SND_IMX_SOC, it's better to leave the selection to individual machine driver which knows if AC97 support is needed or not.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/imx/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 4025eee..d3b7166 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -1,7 +1,6 @@ menuconfig SND_IMX_SOC tristate "SoC Audio for Freescale i.MX CPUs" depends on ARCH_MXC - select SND_SOC_AC97_BUS help Say Y or M if you want to add support for codecs attached to the i.MX SSI interface. @@ -43,6 +42,7 @@ config SND_SOC_MX27VIS_AIC32X4 config SND_SOC_PHYCORE_AC97 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" depends on MACH_PCM043 || MACH_PCA100 + select SND_SOC_AC97_BUS select SND_SOC_WM9712 select SND_MXC_SOC_FIQ select SND_SOC_IMX_AUDMUX
On Sat, Mar 03, 2012 at 11:19:48PM +0800, Shawn Guo wrote:
SND_SOC_AC97_BUS is selected to enable the AC97 support in soc-core. Rather than selecting the option under SND_IMX_SOC, it's better to leave the selection to individual machine driver which knows if AC97 support is needed or not.
Applied.
It's not necessary for imx-pcm-dma-mx2 to access imx_ssi.dma_params for burstsize initialization. Instead, it can just be done in imx-ssi probe function once.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/imx/imx-pcm-dma-mx2.c | 5 ----- sound/soc/imx/imx-ssi.c | 2 +- 2 files changed, 1 insertions(+), 6 deletions(-)
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 4cd5462..471e221 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -149,11 +149,6 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
static int __devinit imx_soc_platform_probe(struct platform_device *pdev) { - struct imx_ssi *ssi = platform_get_drvdata(pdev); - - ssi->dma_params_tx.burstsize = 6; - ssi->dma_params_rx.burstsize = 4; - return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2); }
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index dac62b0..9af3a5b 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -668,7 +668,7 @@ static int imx_ssi_probe(struct platform_device *pdev) ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; ssi->dma_params_tx.dma_addr = res->start + SSI_STX0;
- ssi->dma_params_tx.burstsize = 4; + ssi->dma_params_tx.burstsize = 6; ssi->dma_params_rx.burstsize = 4;
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
On Sat, Mar 03, 2012 at 11:19:49PM +0800, Shawn Guo wrote:
It's not necessary for imx-pcm-dma-mx2 to access imx_ssi.dma_params for burstsize initialization. Instead, it can just be done in imx-ssi probe function once.
Applied, thanks.
Currently the imx-ssi.c[h] accommodates the imx-pcm common bits which are shared between imx-pcm-dma-mx2 and imx-pcm-fiq drivers. It assumes that imx-pcm-dma-mx2 and imx-pcm-fiq will always be used together with imx-ssi driver. However this becomes untrue when we see that driver sound/soc/fsl/fsl_ssi could possibly work with imx-pcm-dma-mx2 too.
The patch moves the imx-pcm common bits from imx-ssi.c[h] into new files imx-pcm.c[h], and let imx-pcm-dma-mx2 and imx-pcm-fiq drivers build it in, so that imx-pcm-dma-mx2 can work with no dependency on imx-ssi driver.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/imx/Kconfig | 7 ++- sound/soc/imx/Makefile | 9 ++-- sound/soc/imx/imx-pcm-dma-mx2.c | 2 +- sound/soc/imx/imx-pcm.c | 105 +++++++++++++++++++++++++++++++++++++++ sound/soc/imx/imx-pcm.h | 32 ++++++++++++ sound/soc/imx/imx-ssi.c | 88 -------------------------------- sound/soc/imx/imx-ssi.h | 16 +------ 7 files changed, 150 insertions(+), 109 deletions(-) create mode 100644 sound/soc/imx/imx-pcm.c create mode 100644 sound/soc/imx/imx-pcm.h
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index d3b7166..2566032 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -8,13 +8,18 @@ menuconfig SND_IMX_SOC
if SND_IMX_SOC
+config SND_SOC_IMX_PCM + tristate + config SND_MXC_SOC_FIQ - select FIQ tristate + select FIQ + select SND_SOC_IMX_PCM
config SND_MXC_SOC_MX2 select SND_SOC_DMAENGINE_PCM tristate + select SND_SOC_IMX_PCM
config SND_SOC_IMX_AUDMUX tristate diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index 5c40541..e9ed362 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -1,14 +1,15 @@ # i.MX Platform Support snd-soc-imx-objs := imx-ssi.o -snd-soc-imx-fiq-objs := imx-pcm-fiq.o -snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o snd-soc-imx-audmux-objs := imx-audmux.o
obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o -obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o -obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
+obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o +snd-soc-imx-pcm-y := imx-pcm.o +snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o +snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o + # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o snd-soc-phycore-ac97-objs := phycore-ac97.o diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 471e221..e43c8fa 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -31,7 +31,7 @@
#include <mach/dma.h>
-#include "imx-ssi.h" +#include "imx-pcm.h"
static bool filter(struct dma_chan *chan, void *param) { diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/imx/imx-pcm.c new file mode 100644 index 0000000..93dc360 --- /dev/null +++ b/sound/soc/imx/imx-pcm.c @@ -0,0 +1,105 @@ +/* + * Copyright 2009 Sascha Hauer s.hauer@pengutronix.de + * + * This code is based on code copyrighted by Freescale, + * Liam Girdwood, Javier Martin and probably others. + * + * 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/dma-mapping.h> +#include <linux/module.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include "imx-pcm.h" + +int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = dma_mmap_writecombine(substream->pcm->card->dev, vma, + runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); + + pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); + return ret; +} +EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); + +static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = IMX_SSI_DMABUF_SIZE; + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + buf->bytes = size; + + return 0; +} + +static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); + +int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + if (!card->dev->dma_mask) + card->dev->dma_mask = &imx_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = DMA_BIT_MASK(32); + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + ret = imx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + goto out; + } + + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ret = imx_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + goto out; + } + +out: + return ret; +} +EXPORT_SYMBOL_GPL(imx_pcm_new); + +void imx_pcm_free(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_writecombine(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + buf->area = NULL; + } +} +EXPORT_SYMBOL_GPL(imx_pcm_free); diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/imx/imx-pcm.h new file mode 100644 index 0000000..b5f5c3a --- /dev/null +++ b/sound/soc/imx/imx-pcm.h @@ -0,0 +1,32 @@ +/* + * Copyright 2009 Sascha Hauer s.hauer@pengutronix.de + * + * This code is based on code copyrighted by Freescale, + * Liam Girdwood, Javier Martin and probably others. + * + * 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 _IMX_PCM_H +#define _IMX_PCM_H + +/* + * Do not change this as the FIQ handler depends on this size + */ +#define IMX_SSI_DMABUF_SIZE (64 * 1024) + +struct imx_pcm_dma_params { + int dma; + unsigned long dma_addr; + int burstsize; +}; + +int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma); +int imx_pcm_new(struct snd_soc_pcm_runtime *rtd); +void imx_pcm_free(struct snd_pcm *pcm); + +#endif /* _IMX_PCM_H */ diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 9af3a5b..4f81ed4 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -363,94 +363,6 @@ static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { .trigger = imx_ssi_trigger, };
-int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); - - pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); - return ret; -} -EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); - -static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = IMX_SSI_DMABUF_SIZE; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - - return 0; -} - -static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); - -int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &imx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = imx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = imx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - -out: - return ret; -} -EXPORT_SYMBOL_GPL(imx_pcm_new); - -void imx_pcm_free(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} -EXPORT_SYMBOL_GPL(imx_pcm_free); - static int imx_ssi_dai_probe(struct snd_soc_dai *dai) { struct imx_ssi *ssi = dev_get_drvdata(dai->dev); diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index 1072dfb..5744e86 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h @@ -187,12 +187,7 @@
#include <linux/dmaengine.h> #include <mach/dma.h> - -struct imx_pcm_dma_params { - int dma; - unsigned long dma_addr; - int burstsize; -}; +#include "imx-pcm.h"
struct imx_ssi { struct platform_device *ac97_dev; @@ -218,13 +213,4 @@ struct imx_ssi { struct platform_device *soc_platform_pdev_fiq; };
-int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); -int imx_pcm_new(struct snd_soc_pcm_runtime *rtd); -void imx_pcm_free(struct snd_pcm *pcm); - -/* - * Do not change this as the FIQ handler depends on this size - */ -#define IMX_SSI_DMABUF_SIZE (64 * 1024) - #endif /* _IMX_SSI_H */
On Sat, Mar 03, 2012 at 11:19:50PM +0800, Shawn Guo wrote:
Currently the imx-ssi.c[h] accommodates the imx-pcm common bits which are shared between imx-pcm-dma-mx2 and imx-pcm-fiq drivers. It assumes that imx-pcm-dma-mx2 and imx-pcm-fiq will always be used together with imx-ssi driver. However this becomes untrue when we see that driver sound/soc/fsl/fsl_ssi could possibly work with imx-pcm-dma-mx2 too.
I was going to apply this and the next patch but they depend on the audmux stuff so they'll at least have to wait until that gets applied.
Currently ASoC:imx uses menuconfig option SND_IMX_SOC selects imx-ssi driver, and it works because all the machine driver covered by the menuconfig need to build imx-ssi driver in. However, it will not work any more if we have a imx based machine driver going into the menuconfig while working with fsl_ssi driver (sound/soc/fsl/fsl_ssi.c) rather than imx-ssi one.
The patch adds an explicit Kconfig option SND_SOC_IMX_SSI for imx-ssi driver, so that it can be selected independently from the menuconfig option SND_IMX_SOC.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/imx/Kconfig | 7 +++++++ sound/soc/imx/Makefile | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 2566032..810acaa 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -8,6 +8,9 @@ menuconfig SND_IMX_SOC
if SND_IMX_SOC
+config SND_SOC_IMX_SSI + tristate + config SND_SOC_IMX_PCM tristate
@@ -30,6 +33,7 @@ config SND_MXC_SOC_WM1133_EV1 select SND_SOC_WM8350 select SND_MXC_SOC_FIQ select SND_SOC_IMX_AUDMUX + select SND_SOC_IMX_SSI help Enable support for audio on the i.MX31ADS with the WM1133-EV1 PMIC board with WM8835x fitted. @@ -40,6 +44,7 @@ config SND_SOC_MX27VIS_AIC32X4 select SND_SOC_TLV320AIC32X4 select SND_MXC_SOC_MX2 select SND_SOC_IMX_AUDMUX + select SND_SOC_IMX_SSI help Say Y if you want to add support for SoC audio on Visstrim SM10 board with TLV320AIC32X4 codec. @@ -51,6 +56,7 @@ config SND_SOC_PHYCORE_AC97 select SND_SOC_WM9712 select SND_MXC_SOC_FIQ select SND_SOC_IMX_AUDMUX + select SND_SOC_IMX_SSI help Say Y if you want to add support for SoC audio on Phytec phyCORE and phyCARD boards in AC97 mode @@ -65,6 +71,7 @@ config SND_SOC_EUKREA_TLV320 select SND_SOC_TLV320AIC23 select SND_MXC_SOC_FIQ select SND_SOC_IMX_AUDMUX + select SND_SOC_IMX_SSI help Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index e9ed362..f5db3e9 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile @@ -1,8 +1,8 @@ # i.MX Platform Support -snd-soc-imx-objs := imx-ssi.o +snd-soc-imx-ssi-objs := imx-ssi.o snd-soc-imx-audmux-objs := imx-audmux.o
-obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o +obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
The fsl_ssi driver will possibly be shared between Freescale PowerPC and ARM/IMX families, so give it a separate Kconfig option. Then fsl_ssi driver can possibly be selected independently from selecting PowerPC DMA based PCM driver.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/fsl/Kconfig | 15 +++++++++------ sound/soc/fsl/Makefile | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index d754d34..ca693b2 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,10 +1,11 @@ config SND_MPC52xx_DMA tristate
-# ASoC platform support for the Freescale PowerPC SOCs that have an SSI and -# an Elo DMA controller, such as the MPC8610 and P1022. You will still need to -# select a platform driver and a codec driver. -config SND_SOC_POWERPC_SSI +config SND_SOC_FSL_SSI + tristate + depends on FSL_SOC + +config SND_SOC_POWERPC_DMA tristate depends on FSL_SOC
@@ -12,7 +13,8 @@ config SND_SOC_MPC8610_HPCD tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" # I2C is necessary for the CS4270 driver depends on MPC8610_HPCD && I2C - select SND_SOC_POWERPC_SSI + select SND_SOC_FSL_SSI + select SND_SOC_POWERPC_DMA select SND_SOC_CS4270 select SND_SOC_CS4270_VD33_ERRATA default y if MPC8610_HPCD @@ -23,7 +25,8 @@ config SND_SOC_P1022_DS tristate "ALSA SoC support for the Freescale P1022 DS board" # I2C is necessary for the WM8776 driver depends on P1022_DS && I2C - select SND_SOC_POWERPC_SSI + select SND_SOC_FSL_SSI + select SND_SOC_POWERPC_DMA select SND_SOC_WM8776 default y if P1022_DS help diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index b4a38c0..95d483f 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -9,7 +9,8 @@ obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o # Freescale PowerPC SSI/DMA Platform Support snd-soc-fsl-ssi-objs := fsl_ssi.o snd-soc-fsl-dma-objs := fsl_dma.o -obj-$(CONFIG_SND_SOC_POWERPC_SSI) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o +obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o +obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
# MPC5200 Platform Support obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
Freescale PowerPC and ARM/IMX families share the same SSI IP block. The patch merges sound/soc/imx into sound/soc/fsl, so that the possible code sharing and consolidation can happen.
This is a plain merge, except that menuconfig SND_POWERPC_SOC is added in Kconfig for PowerPC platform as a correspondence to SND_IMX_SOC for IMX platform.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/Kconfig | 1 - sound/soc/Makefile | 1 - sound/soc/fsl/Kconfig | 92 ++++++++++++++++++++++++++++++ sound/soc/fsl/Makefile | 22 +++++++ sound/soc/{imx => fsl}/eukrea-tlv320.c | 2 +- sound/soc/{imx => fsl}/imx-audmux.c | 0 sound/soc/{imx => fsl}/imx-audmux.h | 0 sound/soc/{imx => fsl}/imx-pcm-dma-mx2.c | 0 sound/soc/{imx => fsl}/imx-pcm-fiq.c | 0 sound/soc/{imx => fsl}/imx-pcm.c | 0 sound/soc/{imx => fsl}/imx-pcm.h | 0 sound/soc/{imx => fsl}/imx-ssi.c | 2 +- sound/soc/{imx => fsl}/imx-ssi.h | 0 sound/soc/{imx => fsl}/mx27vis-aic32x4.c | 0 sound/soc/{imx => fsl}/phycore-ac97.c | 0 sound/soc/{imx => fsl}/wm1133-ev1.c | 0 sound/soc/imx/Kconfig | 79 ------------------------- sound/soc/imx/Makefile | 22 ------- 18 files changed, 116 insertions(+), 105 deletions(-) rename sound/soc/{imx => fsl}/eukrea-tlv320.c (99%) rename sound/soc/{imx => fsl}/imx-audmux.c (100%) rename sound/soc/{imx => fsl}/imx-audmux.h (100%) rename sound/soc/{imx => fsl}/imx-pcm-dma-mx2.c (100%) rename sound/soc/{imx => fsl}/imx-pcm-fiq.c (100%) rename sound/soc/{imx => fsl}/imx-pcm.c (100%) rename sound/soc/{imx => fsl}/imx-pcm.h (100%) rename sound/soc/{imx => fsl}/imx-ssi.c (99%) rename sound/soc/{imx => fsl}/imx-ssi.h (100%) rename sound/soc/{imx => fsl}/mx27vis-aic32x4.c (100%) rename sound/soc/{imx => fsl}/phycore-ac97.c (100%) rename sound/soc/{imx => fsl}/wm1133-ev1.c (100%) delete mode 100644 sound/soc/imx/Kconfig delete mode 100644 sound/soc/imx/Makefile
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 91c9855..0f85f6d 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -35,7 +35,6 @@ source "sound/soc/blackfin/Kconfig" source "sound/soc/davinci/Kconfig" source "sound/soc/ep93xx/Kconfig" source "sound/soc/fsl/Kconfig" -source "sound/soc/imx/Kconfig" source "sound/soc/jz4740/Kconfig" source "sound/soc/nuc900/Kconfig" source "sound/soc/omap/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 2feaf37..363dfd6 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_SND_SOC) += blackfin/ obj-$(CONFIG_SND_SOC) += davinci/ obj-$(CONFIG_SND_SOC) += ep93xx/ obj-$(CONFIG_SND_SOC) += fsl/ -obj-$(CONFIG_SND_SOC) += imx/ obj-$(CONFIG_SND_SOC) += jz4740/ obj-$(CONFIG_SND_SOC) += mid-x86/ obj-$(CONFIG_SND_SOC) += mxs/ diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index ca693b2..19856a0 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,3 +1,15 @@ +config SND_SOC_FSL_SSI + tristate + +menuconfig SND_POWERPC_SOC + tristate "SoC Audio for Freescale PowerPC CPUs" + depends on FSL_SOC + help + Say Y or M if you want to add support for codecs attached to + the PowerPC CPUs. + +if SND_POWERPC_SOC + config SND_MPC52xx_DMA tristate
@@ -68,3 +80,83 @@ config SND_MPC52xx_SOC_EFIKA help Say Y if you want to add support for sound on the Efika.
+endif # SND_POWERPC_SOC + +menuconfig SND_IMX_SOC + tristate "SoC Audio for Freescale i.MX CPUs" + depends on ARCH_MXC + help + Say Y or M if you want to add support for codecs attached to + the i.MX CPUs. + +if SND_IMX_SOC + +config SND_SOC_IMX_SSI + tristate + +config SND_SOC_IMX_PCM + tristate + +config SND_MXC_SOC_FIQ + tristate + select FIQ + select SND_SOC_IMX_PCM + +config SND_MXC_SOC_MX2 + tristate + select SND_SOC_DMAENGINE_PCM + select SND_SOC_IMX_PCM + +config SND_SOC_IMX_AUDMUX + tristate + +config SND_MXC_SOC_WM1133_EV1 + tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" + depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL + select SND_SOC_WM8350 + select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX + select SND_SOC_IMX_SSI + help + Enable support for audio on the i.MX31ADS with the WM1133-EV1 + PMIC board with WM8835x fitted. + +config SND_SOC_MX27VIS_AIC32X4 + tristate "SoC audio support for Visstrim M10 boards" + depends on MACH_IMX27_VISSTRIM_M10 && I2C + select SND_SOC_TLV320AIC32X4 + select SND_MXC_SOC_MX2 + select SND_SOC_IMX_AUDMUX + select SND_SOC_IMX_SSI + help + Say Y if you want to add support for SoC audio on Visstrim SM10 + board with TLV320AIC32X4 codec. + +config SND_SOC_PHYCORE_AC97 + tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" + depends on MACH_PCM043 || MACH_PCA100 + select SND_SOC_AC97_BUS + select SND_SOC_WM9712 + select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX + select SND_SOC_IMX_SSI + help + Say Y if you want to add support for SoC audio on Phytec phyCORE + and phyCARD boards in AC97 mode + +config SND_SOC_EUKREA_TLV320 + tristate "Eukrea TLV320" + depends on MACH_EUKREA_MBIMX27_BASEBOARD \ + || MACH_EUKREA_MBIMXSD25_BASEBOARD \ + || MACH_EUKREA_MBIMXSD35_BASEBOARD \ + || MACH_EUKREA_MBIMXSD51_BASEBOARD + depends on I2C + select SND_SOC_TLV320AIC23 + select SND_MXC_SOC_FIQ + select SND_SOC_IMX_AUDMUX + select SND_SOC_IMX_SSI + help + Enable I2S based access to the TLV320AIC23B codec attached + to the SSI interface + +endif # SND_IMX_SOC diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 95d483f..36c257f 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -21,3 +21,25 @@ obj-$(CONFIG_SND_SOC_MPC5200_AC97) += mpc5200_psc_ac97.o obj-$(CONFIG_SND_MPC52xx_SOC_PCM030) += pcm030-audio-fabric.o obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o
+# i.MX Platform Support +snd-soc-imx-ssi-objs := imx-ssi.o +snd-soc-imx-audmux-objs := imx-audmux.o + +obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o +obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o + +obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o +snd-soc-imx-pcm-y := imx-pcm.o +snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o +snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o + +# i.MX Machine Support +snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o +snd-soc-phycore-ac97-objs := phycore-ac97.o +snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o +snd-soc-wm1133-ev1-objs := wm1133-ev1.o + +obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o +obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o +obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o +obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c similarity index 99% rename from sound/soc/imx/eukrea-tlv320.c rename to sound/soc/fsl/eukrea-tlv320.c index 7d4475c..efb9ede 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -7,7 +7,7 @@ * which is Copyright 2009 Simtec Electronics * and on sound/soc/imx/phycore-ac97.c which is * Copyright 2009 Sascha Hauer, Pengutronix s.hauer@pengutronix.de - * + * * 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 diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/fsl/imx-audmux.c similarity index 100% rename from sound/soc/imx/imx-audmux.c rename to sound/soc/fsl/imx-audmux.c diff --git a/sound/soc/imx/imx-audmux.h b/sound/soc/fsl/imx-audmux.h similarity index 100% rename from sound/soc/imx/imx-audmux.h rename to sound/soc/fsl/imx-audmux.h diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/fsl/imx-pcm-dma-mx2.c similarity index 100% rename from sound/soc/imx/imx-pcm-dma-mx2.c rename to sound/soc/fsl/imx-pcm-dma-mx2.c diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c similarity index 100% rename from sound/soc/imx/imx-pcm-fiq.c rename to sound/soc/fsl/imx-pcm-fiq.c diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/fsl/imx-pcm.c similarity index 100% rename from sound/soc/imx/imx-pcm.c rename to sound/soc/fsl/imx-pcm.c diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/fsl/imx-pcm.h similarity index 100% rename from sound/soc/imx/imx-pcm.h rename to sound/soc/fsl/imx-pcm.h diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/fsl/imx-ssi.c similarity index 99% rename from sound/soc/imx/imx-ssi.c rename to sound/soc/fsl/imx-ssi.c index 4f81ed4..cf3ed03 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -28,7 +28,7 @@ * value. When we read the same register two times (and the register still * contains the same value) these status bits are not set. We work * around this by not polling these bits but only wait a fixed delay. - * + * */
#include <linux/clk.h> diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/fsl/imx-ssi.h similarity index 100% rename from sound/soc/imx/imx-ssi.h rename to sound/soc/fsl/imx-ssi.h diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c similarity index 100% rename from sound/soc/imx/mx27vis-aic32x4.c rename to sound/soc/fsl/mx27vis-aic32x4.c diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/fsl/phycore-ac97.c similarity index 100% rename from sound/soc/imx/phycore-ac97.c rename to sound/soc/fsl/phycore-ac97.c diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c similarity index 100% rename from sound/soc/imx/wm1133-ev1.c rename to sound/soc/fsl/wm1133-ev1.c diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig deleted file mode 100644 index 810acaa..0000000 --- a/sound/soc/imx/Kconfig +++ /dev/null @@ -1,79 +0,0 @@ -menuconfig SND_IMX_SOC - tristate "SoC Audio for Freescale i.MX CPUs" - depends on ARCH_MXC - help - Say Y or M if you want to add support for codecs attached to - the i.MX SSI interface. - - -if SND_IMX_SOC - -config SND_SOC_IMX_SSI - tristate - -config SND_SOC_IMX_PCM - tristate - -config SND_MXC_SOC_FIQ - tristate - select FIQ - select SND_SOC_IMX_PCM - -config SND_MXC_SOC_MX2 - select SND_SOC_DMAENGINE_PCM - tristate - select SND_SOC_IMX_PCM - -config SND_SOC_IMX_AUDMUX - tristate - -config SND_MXC_SOC_WM1133_EV1 - tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" - depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL - select SND_SOC_WM8350 - select SND_MXC_SOC_FIQ - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Enable support for audio on the i.MX31ADS with the WM1133-EV1 - PMIC board with WM8835x fitted. - -config SND_SOC_MX27VIS_AIC32X4 - tristate "SoC audio support for Visstrim M10 boards" - depends on MACH_IMX27_VISSTRIM_M10 && I2C - select SND_SOC_TLV320AIC32X4 - select SND_MXC_SOC_MX2 - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Say Y if you want to add support for SoC audio on Visstrim SM10 - board with TLV320AIC32X4 codec. - -config SND_SOC_PHYCORE_AC97 - tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" - depends on MACH_PCM043 || MACH_PCA100 - select SND_SOC_AC97_BUS - select SND_SOC_WM9712 - select SND_MXC_SOC_FIQ - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Say Y if you want to add support for SoC audio on Phytec phyCORE - and phyCARD boards in AC97 mode - -config SND_SOC_EUKREA_TLV320 - tristate "Eukrea TLV320" - depends on MACH_EUKREA_MBIMX27_BASEBOARD \ - || MACH_EUKREA_MBIMXSD25_BASEBOARD \ - || MACH_EUKREA_MBIMXSD35_BASEBOARD \ - || MACH_EUKREA_MBIMXSD51_BASEBOARD - depends on I2C - select SND_SOC_TLV320AIC23 - select SND_MXC_SOC_FIQ - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Enable I2S based access to the TLV320AIC23B codec attached - to the SSI interface - -endif # SND_IMX_SOC diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile deleted file mode 100644 index f5db3e9..0000000 --- a/sound/soc/imx/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# i.MX Platform Support -snd-soc-imx-ssi-objs := imx-ssi.o -snd-soc-imx-audmux-objs := imx-audmux.o - -obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o -obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o - -obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o -snd-soc-imx-pcm-y := imx-pcm.o -snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o -snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o - -# i.MX Machine Support -snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o -snd-soc-phycore-ac97-objs := phycore-ac97.o -snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o -snd-soc-wm1133-ev1-objs := wm1133-ev1.o - -obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o -obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o -obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o -obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
There is some amount of code duplication between mpc8610_hpcd and p1022_ds machine drivers, and the same code will be duplicated again when another new machine driver is added. The patch creates fsl_utils to accommodate the common functions to stop the code duplication.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/fsl/Kconfig | 5 ++ sound/soc/fsl/Makefile | 2 + sound/soc/fsl/fsl_utils.c | 135 ++++++++++++++++++++++++++++++++++++ sound/soc/fsl/fsl_utils.h | 27 +++++++ sound/soc/fsl/mpc8610_hpcd.c | 157 +++--------------------------------------- sound/soc/fsl/p1022_ds.c | 149 +++------------------------------------- 6 files changed, 189 insertions(+), 286 deletions(-) create mode 100644 sound/soc/fsl/fsl_utils.c create mode 100644 sound/soc/fsl/fsl_utils.h
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 19856a0..e579671 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,6 +1,9 @@ config SND_SOC_FSL_SSI tristate
+config SND_SOC_FSL_UTILS + tristate + menuconfig SND_POWERPC_SOC tristate "SoC Audio for Freescale PowerPC CPUs" depends on FSL_SOC @@ -26,6 +29,7 @@ config SND_SOC_MPC8610_HPCD # I2C is necessary for the CS4270 driver depends on MPC8610_HPCD && I2C select SND_SOC_FSL_SSI + select SND_SOC_FSL_UTILS select SND_SOC_POWERPC_DMA select SND_SOC_CS4270 select SND_SOC_CS4270_VD33_ERRATA @@ -38,6 +42,7 @@ config SND_SOC_P1022_DS # I2C is necessary for the WM8776 driver depends on P1022_DS && I2C select SND_SOC_FSL_SSI + select SND_SOC_FSL_UTILS select SND_SOC_POWERPC_DMA select SND_SOC_WM8776 default y if P1022_DS diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 36c257f..02b3e53 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -8,8 +8,10 @@ obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
# Freescale PowerPC SSI/DMA Platform Support snd-soc-fsl-ssi-objs := fsl_ssi.o +snd-soc-fsl-utils-objs := fsl_utils.o snd-soc-fsl-dma-objs := fsl_dma.o obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o +obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
# MPC5200 Platform Support diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c new file mode 100644 index 0000000..4370c28 --- /dev/null +++ b/sound/soc/fsl/fsl_utils.c @@ -0,0 +1,135 @@ +/** + * Freescale ALSA SoC Machine driver utility + * + * Author: Timur Tabi timur@freescale.com + * + * Copyright 2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_i2c.h> +#include <sound/soc.h> + +#include "fsl_utils.h" + +/** + * fsl_asoc_get_codec_dev_name - determine the dev_name for a codec node + * + * @np: pointer to the I2C device tree node + * @buf: buffer to be filled with the dev_name of the I2C device + * @len: the length of the buffer + * + * This function determines the dev_name for an I2C node. This is the name + * that would be returned by dev_name() if this device_node were part of a + * 'struct device' It's ugly and hackish, but it works. + * + * The dev_name for such devices include the bus number and I2C address. For + * example, "cs4270.0-004f". + */ +int fsl_asoc_get_codec_dev_name(struct device_node *np, char *buf, size_t len) +{ + const u32 *iprop; + u32 addr; + char temp[DAI_NAME_SIZE]; + struct i2c_client *i2c; + + of_modalias_node(np, temp, DAI_NAME_SIZE); + + iprop = of_get_property(np, "reg", NULL); + if (!iprop) + return -EINVAL; + + addr = be32_to_cpup(iprop); + + /* We need the adapter number */ + i2c = of_find_i2c_device_by_node(np); + if (!i2c) { + put_device(&i2c->dev); + return -ENODEV; + } + + snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr); + put_device(&i2c->dev); + + return 0; +} +EXPORT_SYMBOL(fsl_asoc_get_codec_dev_name); + +/** + * fsl_asoc_get_dma_channel - determine the dma channel for a SSI node + * + * @ssi_np: pointer to the SSI device tree node + * @name: name of the phandle pointing to the dma channel + * @dai: ASoC DAI link pointer to be filled with platform_name + * @dma_channel_id: dma channel id to be returned + * @dma_id: dma id to be returned + * + * This function determines the dma and channel id for given SSI node. It + * also discovers the platform_name for the ASoC DAI link. + */ +int fsl_asoc_get_dma_channel(struct device_node *ssi_np, + const char *name, + struct snd_soc_dai_link *dai, + unsigned int *dma_channel_id, + unsigned int *dma_id) +{ + struct resource res; + struct device_node *dma_channel_np, *dma_np; + const u32 *iprop; + int ret; + + dma_channel_np = of_parse_phandle(ssi_np, name, 0); + if (!dma_channel_np) + return -EINVAL; + + if (!of_device_is_compatible(dma_channel_np, "fsl,ssi-dma-channel")) { + of_node_put(dma_channel_np); + return -EINVAL; + } + + /* Determine the dev_name for the device_node. This code mimics the + * behavior of of_device_make_bus_id(). We need this because ASoC uses + * the dev_name() of the device to match the platform (DMA) device with + * the CPU (SSI) device. It's all ugly and hackish, but it works (for + * now). + * + * dai->platform name should already point to an allocated buffer. + */ + ret = of_address_to_resource(dma_channel_np, 0, &res); + if (ret) { + of_node_put(dma_channel_np); + return ret; + } + snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", + (unsigned long long) res.start, dma_channel_np->name); + + iprop = of_get_property(dma_channel_np, "cell-index", NULL); + if (!iprop) { + of_node_put(dma_channel_np); + return -EINVAL; + } + *dma_channel_id = be32_to_cpup(iprop); + + dma_np = of_get_parent(dma_channel_np); + iprop = of_get_property(dma_np, "cell-index", NULL); + if (!iprop) { + of_node_put(dma_np); + return -EINVAL; + } + *dma_id = be32_to_cpup(iprop); + + of_node_put(dma_np); + of_node_put(dma_channel_np); + + return 0; +} +EXPORT_SYMBOL(fsl_asoc_get_dma_channel); + +MODULE_AUTHOR("Timur Tabi timur@freescale.com"); +MODULE_DESCRIPTION("Freescale ASoC utility code"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_utils.h b/sound/soc/fsl/fsl_utils.h new file mode 100644 index 0000000..44d1436 --- /dev/null +++ b/sound/soc/fsl/fsl_utils.h @@ -0,0 +1,27 @@ +/** + * Freescale ALSA SoC Machine driver utility + * + * Author: Timur Tabi timur@freescale.com + * + * Copyright 2010 Freescale Semiconductor, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef _FSL_UTILS_H +#define _FSL_UTILS_H + +#define DAI_NAME_SIZE 32 + +struct snd_soc_dai_link; +struct device_node; + +int fsl_asoc_get_codec_dev_name(struct device_node *np, char *buf, size_t len); +int fsl_asoc_get_dma_channel(struct device_node *ssi_np, const char *name, + struct snd_soc_dai_link *dai, + unsigned int *dma_channel_id, + unsigned int *dma_id); + +#endif /* _FSL_UTILS_H */ diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index fcf9302..7ead1e5 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -14,18 +14,16 @@ #include <linux/interrupt.h> #include <linux/of_device.h> #include <linux/slab.h> -#include <linux/of_i2c.h> #include <sound/soc.h> #include <asm/fsl_guts.h>
#include "fsl_dma.h" #include "fsl_ssi.h" +#include "fsl_utils.h"
/* There's only one global utilities register */ static phys_addr_t guts_phys;
-#define DAI_NAME_SIZE 32 - /** * mpc8610_hpcd_data: machine-specific ASoC device data * @@ -181,141 +179,6 @@ static struct snd_soc_ops mpc8610_hpcd_ops = { };
/** - * get_node_by_phandle_name - get a node by its phandle name - * - * This function takes a node, the name of a property in that node, and a - * compatible string. Assuming the property is a phandle to another node, - * it returns that node, (optionally) if that node is compatible. - * - * If the property is not a phandle, or the node it points to is not compatible - * with the specific string, then NULL is returned. - */ -static struct device_node *get_node_by_phandle_name(struct device_node *np, - const char *name, - const char *compatible) -{ - const phandle *ph; - int len; - - ph = of_get_property(np, name, &len); - if (!ph || (len != sizeof(phandle))) - return NULL; - - np = of_find_node_by_phandle(*ph); - if (!np) - return NULL; - - if (compatible && !of_device_is_compatible(np, compatible)) { - of_node_put(np); - return NULL; - } - - return np; -} - -/** - * get_parent_cell_index -- return the cell-index of the parent of a node - * - * Return the value of the cell-index property of the parent of the given - * node. This is used for DMA channel nodes that need to know the DMA ID - * of the controller they are on. - */ -static int get_parent_cell_index(struct device_node *np) -{ - struct device_node *parent = of_get_parent(np); - const u32 *iprop; - - if (!parent) - return -1; - - iprop = of_get_property(parent, "cell-index", NULL); - of_node_put(parent); - - if (!iprop) - return -1; - - return be32_to_cpup(iprop); -} - -/** - * codec_node_dev_name - determine the dev_name for a codec node - * - * This function determines the dev_name for an I2C node. This is the name - * that would be returned by dev_name() if this device_node were part of a - * 'struct device' It's ugly and hackish, but it works. - * - * The dev_name for such devices include the bus number and I2C address. For - * example, "cs4270.0-004f". - */ -static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) -{ - const u32 *iprop; - int addr; - char temp[DAI_NAME_SIZE]; - struct i2c_client *i2c; - - of_modalias_node(np, temp, DAI_NAME_SIZE); - - iprop = of_get_property(np, "reg", NULL); - if (!iprop) - return -EINVAL; - - addr = be32_to_cpup(iprop); - - /* We need the adapter number */ - i2c = of_find_i2c_device_by_node(np); - if (!i2c) - return -ENODEV; - - snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr); - - return 0; -} - -static int get_dma_channel(struct device_node *ssi_np, - const char *name, - struct snd_soc_dai_link *dai, - unsigned int *dma_channel_id, - unsigned int *dma_id) -{ - struct resource res; - struct device_node *dma_channel_np; - const u32 *iprop; - int ret; - - dma_channel_np = get_node_by_phandle_name(ssi_np, name, - "fsl,ssi-dma-channel"); - if (!dma_channel_np) - return -EINVAL; - - /* Determine the dev_name for the device_node. This code mimics the - * behavior of of_device_make_bus_id(). We need this because ASoC uses - * the dev_name() of the device to match the platform (DMA) device with - * the CPU (SSI) device. It's all ugly and hackish, but it works (for - * now). - * - * dai->platform name should already point to an allocated buffer. - */ - ret = of_address_to_resource(dma_channel_np, 0, &res); - if (ret) - return ret; - snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", - (unsigned long long) res.start, dma_channel_np->name); - - iprop = of_get_property(dma_channel_np, "cell-index", NULL); - if (!iprop) { - of_node_put(dma_channel_np); - return -EINVAL; - } - - *dma_channel_id = be32_to_cpup(iprop); - *dma_id = get_parent_cell_index(dma_channel_np); - of_node_put(dma_channel_np); - - return 0; -} - -/** * mpc8610_hpcd_probe: platform probe function for the machine driver * * Although this is a machine driver, the SSI node is the "master" node with @@ -353,8 +216,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) machine_data->dai[0].ops = &mpc8610_hpcd_ops;
/* Determine the codec name, it will be used as the codec DAI name */ - ret = codec_node_dev_name(codec_np, machine_data->codec_name, - DAI_NAME_SIZE); + ret = fsl_asoc_get_codec_dev_name(codec_np, machine_data->codec_name, + DAI_NAME_SIZE); if (ret) { dev_err(&pdev->dev, "invalid codec node %s\n", codec_np->full_name); @@ -458,9 +321,10 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
/* Find the playback DMA channel to use. */ machine_data->dai[0].platform_name = machine_data->platform_name[0]; - ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0], - &machine_data->dma_channel_id[0], - &machine_data->dma_id[0]); + ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", + &machine_data->dai[0], + &machine_data->dma_channel_id[0], + &machine_data->dma_id[0]); if (ret) { dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n"); goto error; @@ -468,9 +332,10 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
/* Find the capture DMA channel to use. */ machine_data->dai[1].platform_name = machine_data->platform_name[1]; - ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1], - &machine_data->dma_channel_id[1], - &machine_data->dma_id[1]); + ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", + &machine_data->dai[1], + &machine_data->dma_channel_id[1], + &machine_data->dma_id[1]); if (ret) { dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n"); goto error; diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index d32ec46..60f7bb8 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -14,12 +14,12 @@ #include <linux/interrupt.h> #include <linux/of_device.h> #include <linux/slab.h> -#include <linux/of_i2c.h> #include <sound/soc.h> #include <asm/fsl_guts.h>
#include "fsl_dma.h" #include "fsl_ssi.h" +#include "fsl_utils.h"
/* P1022-specific PMUXCR and DMUXCR bit definitions */
@@ -57,8 +57,6 @@ static inline void guts_set_dmuxcr(struct ccsr_guts_85xx __iomem *guts, /* There's only one global utilities register */ static phys_addr_t guts_phys;
-#define DAI_NAME_SIZE 32 - /** * machine_data: machine-specific ASoC device data * @@ -191,136 +189,6 @@ static struct snd_soc_ops p1022_ds_ops = { };
/** - * get_node_by_phandle_name - get a node by its phandle name - * - * This function takes a node, the name of a property in that node, and a - * compatible string. Assuming the property is a phandle to another node, - * it returns that node, (optionally) if that node is compatible. - * - * If the property is not a phandle, or the node it points to is not compatible - * with the specific string, then NULL is returned. - */ -static struct device_node *get_node_by_phandle_name(struct device_node *np, - const char *name, const char *compatible) -{ - np = of_parse_phandle(np, name, 0); - if (!np) - return NULL; - - if (!of_device_is_compatible(np, compatible)) { - of_node_put(np); - return NULL; - } - - return np; -} - -/** - * get_parent_cell_index -- return the cell-index of the parent of a node - * - * Return the value of the cell-index property of the parent of the given - * node. This is used for DMA channel nodes that need to know the DMA ID - * of the controller they are on. - */ -static int get_parent_cell_index(struct device_node *np) -{ - struct device_node *parent = of_get_parent(np); - const u32 *iprop; - int ret = -1; - - if (!parent) - return -1; - - iprop = of_get_property(parent, "cell-index", NULL); - if (iprop) - ret = be32_to_cpup(iprop); - - of_node_put(parent); - - return ret; -} - -/** - * codec_node_dev_name - determine the dev_name for a codec node - * - * This function determines the dev_name for an I2C node. This is the name - * that would be returned by dev_name() if this device_node were part of a - * 'struct device' It's ugly and hackish, but it works. - * - * The dev_name for such devices include the bus number and I2C address. For - * example, "cs4270-codec.0-004f". - */ -static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) -{ - const u32 *iprop; - int addr; - char temp[DAI_NAME_SIZE]; - struct i2c_client *i2c; - - of_modalias_node(np, temp, DAI_NAME_SIZE); - - iprop = of_get_property(np, "reg", NULL); - if (!iprop) - return -EINVAL; - - addr = be32_to_cpup(iprop); - - /* We need the adapter number */ - i2c = of_find_i2c_device_by_node(np); - if (!i2c) - return -ENODEV; - - snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr); - - return 0; -} - -static int get_dma_channel(struct device_node *ssi_np, - const char *name, - struct snd_soc_dai_link *dai, - unsigned int *dma_channel_id, - unsigned int *dma_id) -{ - struct resource res; - struct device_node *dma_channel_np; - const u32 *iprop; - int ret; - - dma_channel_np = get_node_by_phandle_name(ssi_np, name, - "fsl,ssi-dma-channel"); - if (!dma_channel_np) - return -EINVAL; - - /* Determine the dev_name for the device_node. This code mimics the - * behavior of of_device_make_bus_id(). We need this because ASoC uses - * the dev_name() of the device to match the platform (DMA) device with - * the CPU (SSI) device. It's all ugly and hackish, but it works (for - * now). - * - * dai->platform name should already point to an allocated buffer. - */ - ret = of_address_to_resource(dma_channel_np, 0, &res); - if (ret) { - of_node_put(dma_channel_np); - return ret; - } - snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", - (unsigned long long) res.start, dma_channel_np->name); - - iprop = of_get_property(dma_channel_np, "cell-index", NULL); - if (!iprop) { - of_node_put(dma_channel_np); - return -EINVAL; - } - - *dma_channel_id = be32_to_cpup(iprop); - *dma_id = get_parent_cell_index(dma_channel_np); - of_node_put(dma_channel_np); - - return 0; -} - -/** * p1022_ds_probe: platform probe function for the machine driver * * Although this is a machine driver, the SSI node is the "master" node with @@ -358,7 +226,8 @@ static int p1022_ds_probe(struct platform_device *pdev) mdata->dai[0].ops = &p1022_ds_ops;
/* Determine the codec name, it will be used as the codec DAI name */ - ret = codec_node_dev_name(codec_np, mdata->codec_name, DAI_NAME_SIZE); + ret = fsl_asoc_get_codec_dev_name(codec_np, mdata->codec_name, + DAI_NAME_SIZE); if (ret) { dev_err(&pdev->dev, "invalid codec node %s\n", codec_np->full_name); @@ -454,9 +323,9 @@ static int p1022_ds_probe(struct platform_device *pdev)
/* Find the playback DMA channel to use. */ mdata->dai[0].platform_name = mdata->platform_name[0]; - ret = get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], - &mdata->dma_channel_id[0], - &mdata->dma_id[0]); + ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], + &mdata->dma_channel_id[0], + &mdata->dma_id[0]); if (ret) { dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n"); goto error; @@ -464,9 +333,9 @@ static int p1022_ds_probe(struct platform_device *pdev)
/* Find the capture DMA channel to use. */ mdata->dai[1].platform_name = mdata->platform_name[1]; - ret = get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1], - &mdata->dma_channel_id[1], - &mdata->dma_id[1]); + ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1], + &mdata->dma_channel_id[1], + &mdata->dma_id[1]); if (ret) { dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n"); goto error;
Check /compatible rather than /model to determine the machine name. The p1022ds older device trees get a different /model from the new ones, while /compatible is consistent there, so checking /compatible will save the bother of detecting older p1022ds device trees.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/fsl/fsl_ssi.c | 6 +++--- sound/soc/fsl/mpc8610_hpcd.c | 2 +- sound/soc/fsl/p1022_ds.c | 32 +++++--------------------------- 3 files changed, 9 insertions(+), 31 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 3e06696..2eb407f 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -716,12 +716,12 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) }
/* Trigger the machine driver's probe function. The platform driver - * name of the machine driver is taken from the /model property of the + * name of the machine driver is taken from /compatible property of the * device tree. We also pass the address of the CPU DAI driver * structure. */ - sprop = of_get_property(of_find_node_by_path("/"), "model", NULL); - /* Sometimes the model name has a "fsl," prefix, so we strip that. */ + sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL); + /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */ p = strrchr(sprop, ','); if (p) sprop = p + 1; diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 7ead1e5..4195182 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -411,7 +411,7 @@ static struct platform_driver mpc8610_hpcd_driver = { .probe = mpc8610_hpcd_probe, .remove = __devexit_p(mpc8610_hpcd_remove), .driver = { - /* The name must match the 'model' property in the device tree, + /* The name must match 'compatible' property in the device tree, * in lowercase letters. */ .name = "snd-soc-mpc8610hpcd", diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 60f7bb8..e3680ce 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -412,6 +412,11 @@ static struct platform_driver p1022_ds_driver = { .probe = p1022_ds_probe, .remove = __devexit_p(p1022_ds_remove), .driver = { + /* + * The name must match 'compatible' property in the device tree, + * in lowercase letters. + */ + .name = "snd-soc-p1022ds", .owner = THIS_MODULE, }, }; @@ -425,33 +430,6 @@ static int __init p1022_ds_init(void) { struct device_node *guts_np; struct resource res; - const char *sprop; - - /* - * Check if we're actually running on a P1022DS. Older device trees - * have a model of "fsl,P1022" and newer ones use "fsl,P1022DS", so we - * need to support both. The SSI driver uses that property to link to - * the machine driver, so have to match it. - */ - sprop = of_get_property(of_find_node_by_path("/"), "model", NULL); - if (!sprop) { - pr_err("snd-soc-p1022ds: missing /model node"); - return -ENODEV; - } - - pr_debug("snd-soc-p1022ds: board model name is %s\n", sprop); - - /* - * The name of this board, taken from the device tree. Normally, this is a* - * fixed string, but some P1022DS device trees have a /model property of - * "fsl,P1022", and others have "fsl,P1022DS". - */ - if (strcasecmp(sprop, "fsl,p1022ds") == 0) - p1022_ds_driver.driver.name = "snd-soc-p1022ds"; - else if (strcasecmp(sprop, "fsl,p1022") == 0) - p1022_ds_driver.driver.name = "snd-soc-p1022"; - else - return -ENODEV;
/* Get the physical address of the global utilities registers */ guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
Provide different pair of accessors for accessing SSI registers on PowerPC and ARM/IMX, so that fsl_ssi driver can be built on both architectures.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/fsl/fsl_ssi.c | 83 ++++++++++++++++++++++++++++++---------------- 1 files changed, 54 insertions(+), 29 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 2eb407f..0b53682 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -11,11 +11,14 @@ */
#include <linux/init.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/device.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/of_platform.h>
#include <sound/core.h> @@ -26,6 +29,14 @@
#include "fsl_ssi.h"
+#ifdef PPC +#define read_ssi(addr) in_be32(addr) +#define write_ssi(val, addr) out_be32(addr, val) +#elif defined ARM +#define read_ssi(addr) readl(addr) +#define write_ssi(val, addr) writel(val, addr) +#endif + /** * FSLSSI_I2S_RATES: sample rates supported by the I2S * @@ -145,7 +156,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) were interrupted for. We mask it with the Interrupt Enable register so that we only check for events that we're interested in. */ - sisr = in_be32(&ssi->sisr) & SIER_FLAGS; + sisr = read_ssi(&ssi->sisr) & SIER_FLAGS;
if (sisr & CCSR_SSI_SISR_RFRC) { ssi_private->stats.rfrc++; @@ -260,7 +271,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
/* Clear the bits that we set */ if (sisr2) - out_be32(&ssi->sisr, sisr2); + write_ssi(sisr2, &ssi->sisr);
return ret; } @@ -280,6 +291,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; + u32 val;
/* * If this is the first stream opened, then request the IRQ @@ -295,7 +307,9 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, * SSI needs to be disabled before updating the registers we set * here. */ - clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); + val = read_ssi(&ssi->scr); + val &= ~CCSR_SSI_SCR_SSIEN; + write_ssi(val, &ssi->scr);
/* * Program the SSI into I2S Slave Non-Network Synchronous mode. @@ -303,20 +317,19 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, * * FIXME: Little-endian samples require a different shift dir */ - clrsetbits_be32(&ssi->scr, - CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, - CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE - | (synchronous ? CCSR_SSI_SCR_SYN : 0)); + val = read_ssi(&ssi->scr); + val &= ~(CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN); + val |= CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | + (synchronous ? CCSR_SSI_SCR_SYN : 0); + write_ssi(val, &ssi->scr);
- out_be32(&ssi->stcr, - CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | + write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | - CCSR_SSI_STCR_TSCKP); + CCSR_SSI_STCR_TSCKP, &ssi->stcr);
- out_be32(&ssi->srcr, - CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | + write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | - CCSR_SSI_SRCR_RSCKP); + CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
/* * The DC and PM bits are only used if the SSI is the clock @@ -324,7 +337,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, */
/* Enable the interrupts and DMA requests */ - out_be32(&ssi->sier, SIER_FLAGS); + write_ssi(SIER_FLAGS, &ssi->sier);
/* * Set the watermark for transmit FIFI 0 and receive FIFO 0. We @@ -339,9 +352,9 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, * make this value larger (and maybe we should), but this way * data will be written to memory as soon as it's available. */ - out_be32(&ssi->sfcsr, - CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | - CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2)); + write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | + CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2), + &ssi->sfcsr);
/* * We keep the SSI disabled because if we enable it, then the @@ -417,7 +430,8 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, unsigned int sample_size = snd_pcm_format_width(params_format(hw_params)); u32 wl = CCSR_SSI_SxCCR_WL(sample_size); - int enabled = in_be32(&ssi->scr) & CCSR_SSI_SCR_SSIEN; + int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN; + u32 val;
/* * If we're in synchronous mode, and the SSI is already enabled, @@ -438,10 +452,17 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
/* In synchronous mode, the SSI uses STCCR for capture */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || - ssi_private->cpu_dai_drv.symmetric_rates) - clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); - else - clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); + ssi_private->cpu_dai_drv.symmetric_rates) { + val = read_ssi(&ssi->stccr); + val &= CCSR_SSI_SxCCR_WL_MASK; + val |= wl; + write_ssi(val, &ssi->stccr); + } else { + val = read_ssi(&ssi->srccr); + val &= CCSR_SSI_SxCCR_WL_MASK; + val |= wl; + write_ssi(val, &ssi->srccr); + }
return 0; } @@ -461,29 +482,30 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); struct ccsr_ssi __iomem *ssi = ssi_private->ssi; + u32 val;
+ val = read_ssi(&ssi->scr); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - setbits32(&ssi->scr, - CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); + val |= CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE; else - setbits32(&ssi->scr, - CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); + val |= CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); + val &= ~CCSR_SSI_SCR_TE; else - clrbits32(&ssi->scr, CCSR_SSI_SCR_RE); + val &= ~CCSR_SSI_SCR_RE; break;
default: return -EINVAL; } + write_ssi(val, &ssi->scr);
return 0; } @@ -498,6 +520,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); + u32 val;
if (ssi_private->first_stream == substream) ssi_private->first_stream = ssi_private->second_stream; @@ -510,7 +533,9 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, if (!ssi_private->first_stream) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
- clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); + val = read_ssi(&ssi->scr); + val &= ~CCSR_SSI_SCR_SSIEN; + write_ssi(val, &ssi->scr); } }
Shawn Guo wrote:
+#ifdef PPC +#define read_ssi(addr) in_be32(addr) +#define write_ssi(val, addr) out_be32(addr, val) +#elif defined ARM +#define read_ssi(addr) readl(addr) +#define write_ssi(val, addr) writel(val, addr) +#endif
Can you also add an ARM version of clrsetbits_be32()? Something like this:
#ifdef PPC #define read_ssi(addr) in_be32(addr) #define write_ssi(val, addr) out_be32(addr, val) #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) #elif defined ARM #define read_ssi(addr) readl(addr) #define write_ssi(val, addr) writel(val, addr) #define write_ssi_mask(addr, clear, set) \ { u32 __val; \ val = readl(&ssi->scr); \ val = (val & ~(clear) | (set); \ writel(val, addr) #endif
On Sun, Mar 04, 2012 at 11:13:09PM +0000, Tabi Timur-B04825 wrote:
Shawn Guo wrote:
+#ifdef PPC +#define read_ssi(addr) in_be32(addr) +#define write_ssi(val, addr) out_be32(addr, val) +#elif defined ARM +#define read_ssi(addr) readl(addr) +#define write_ssi(val, addr) writel(val, addr) +#endif
Can you also add an ARM version of clrsetbits_be32()? Something like this:
#ifdef PPC #define read_ssi(addr) in_be32(addr) #define write_ssi(val, addr) out_be32(addr, val) #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) #elif defined ARM #define read_ssi(addr) readl(addr) #define write_ssi(val, addr) writel(val, addr) #define write_ssi_mask(addr, clear, set) \ { u32 __val; \ val = readl(&ssi->scr); \ val = (val & ~(clear) | (set); \ writel(val, addr) #endif
Is the SCR shared between capture and playback? In that case, what makes this read-modify-write thread safe?
Russell King - ARM Linux wrote:
Is the SCR shared between capture and playback? In that case, what makes this read-modify-write thread safe?
What's "SCR"?
It's not thread-safe on PPC, but then neither is the entire function. You can't have two threads attempt to initialize the hardware at the same time. The macro does not attempt to be atomic, just convenient.
On Sun, Mar 04, 2012 at 11:32:50PM +0000, Tabi Timur-B04825 wrote:
Russell King - ARM Linux wrote:
Is the SCR shared between capture and playback? In that case, what makes this read-modify-write thread safe?
What's "SCR"?
I assumed you knew the code you were commenting on.
clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
The register these functions seem to be used on appears to be called 'SCR'.
It's not thread-safe on PPC, but then neither is the entire function. You can't have two threads attempt to initialize the hardware at the same time.
Why do you say "can't" - what prevents it? If nothing, then this stuff is buggy when preempt is enabled, or you're running on SMP.
Russell King - ARM Linux wrote:
On Sun, Mar 04, 2012 at 11:32:50PM +0000, Tabi Timur-B04825 wrote:
Russell King - ARM Linux wrote:
Is the SCR shared between capture and playback? In that case, what makes this read-modify-write thread safe?
What's "SCR"?
I assumed you knew the code you were commenting on.
clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
The register these functions seem to be used on appears to be called 'SCR'.
Oh, I didn't know you were referencing a specific register on the part. There are multiple uses of clrsetbits_be32 (and its variants) in the function.
To answer your question: I was lead to believe that the individual ALSA callback functions are atomic. So one thread should not be trying to start playback while another thread is simultaneously trying to stop it.
Why do you say "can't" - what prevents it? If nothing, then this stuff is buggy when preempt is enabled, or you're running on SMP.
Sorry, let me rephrase the sentence to be more clear.
"You can't have two threads attempt to initialize the hardware at the same time, and expect it to work."
Since I expect ALSA callback functions to be atomic, I'm not concerned about one two threads trying to use SCR at the same time.
On Mon, Mar 05, 2012 at 12:13:52AM +0000, Tabi Timur-B04825 wrote:
To answer your question: I was lead to believe that the individual ALSA callback functions are atomic. So one thread should not be trying to start playback while another thread is simultaneously trying to stop it.
That's correct, there's ALSA level locking.
On Mon, Mar 05, 2012 at 12:26:36AM +0000, Mark Brown wrote:
On Mon, Mar 05, 2012 at 12:13:52AM +0000, Tabi Timur-B04825 wrote:
To answer your question: I was lead to believe that the individual ALSA callback functions are atomic. So one thread should not be trying to start playback while another thread is simultaneously trying to stop it.
That's correct, there's ALSA level locking.
Please explain which lock prevents the capture substream trigger callback occuring simultaneously with a playback substream trigger callback on a SMP system.
Thanks.
On Tue, Mar 06, 2012 at 10:40:15AM +0000, Russell King - ARM Linux wrote:
On Mon, Mar 05, 2012 at 12:26:36AM +0000, Mark Brown wrote:
On Mon, Mar 05, 2012 at 12:13:52AM +0000, Tabi Timur-B04825 wrote:
To answer your question: I was lead to believe that the individual ALSA callback functions are atomic. So one thread should not be trying to start playback while another thread is simultaneously trying to stop it.
That's correct, there's ALSA level locking.
Please explain which lock prevents the capture substream trigger callback occuring simultaneously with a playback substream trigger callback on a SMP system.
Oh, bother - that one is per substream not per stream. Which isn't terribly helpful.
On Tue, Mar 06, 2012 at 12:06:47PM +0000, Mark Brown wrote:
On Tue, Mar 06, 2012 at 10:40:15AM +0000, Russell King - ARM Linux wrote:
On Mon, Mar 05, 2012 at 12:26:36AM +0000, Mark Brown wrote:
On Mon, Mar 05, 2012 at 12:13:52AM +0000, Tabi Timur-B04825 wrote:
To answer your question: I was lead to believe that the individual ALSA callback functions are atomic. So one thread should not be trying to start playback while another thread is simultaneously trying to stop it.
That's correct, there's ALSA level locking.
Please explain which lock prevents the capture substream trigger callback occuring simultaneously with a playback substream trigger callback on a SMP system.
Oh, bother - that one is per substream not per stream. Which isn't terribly helpful.
It's actually entirely right that the core shouldn't take care of this: it's entirely possible that drivers do not have any dependencies between the two substreams and so they should not be exposed to enforced exclusivity between the actions of two substreams in multiprocessor systems.
Please also note that in ALSA documentation, an 'atomic' callback means little with respect to race conditions. All it means is that the callback is called from a context where sleeping in the callback is not permitted. The documentation does not say what is protected by the ALSA spinlocks and mutexes, so without reviewing the ALSA code, driver writters have little idea whether they need their own locks or not.
On Tue, Mar 06, 2012 at 12:25:16PM +0000, Russell King - ARM Linux wrote:
Please also note that in ALSA documentation, an 'atomic' callback means little with respect to race conditions. All it means is that the callback is called from a context where sleeping in the callback is not permitted. The documentation does not say what is protected by the ALSA spinlocks and mutexes, so without reviewing the ALSA code, driver writters have little idea whether they need their own locks or not.
Well, who reads the documentation to get this stuff anyway? As you observe it's far from complete about what's what locked when and how so you need to go to the code to see what's actually going on, especially whenever you need to call back into the ALSA APIs. Though of course I'm pretty sure there's a bunch of uniprocessor assumptions through the body of driver code anyway...
Mark Brown wrote:
Well, who reads the documentation to get this stuff anyway? As you observe it's far from complete about what's what locked when and how so you need to go to the code to see what's actually going on, especially whenever you need to call back into the ALSA APIs. Though of course I'm pretty sure there's a bunch of uniprocessor assumptions through the body of driver code anyway...
So are you saying that it's possible for one CPU to call my trigger callback to start playback on one substream, while another CPU calls it to start capture on another substream?
If so, then I need to add locking in my trigger function.
On Tue, Mar 06, 2012 at 01:02:35PM +0000, Tabi Timur-B04825 wrote:
So are you saying that it's possible for one CPU to call my trigger callback to start playback on one substream, while another CPU calls it to start capture on another substream?
Yes, Russell is right here.
If so, then I need to add locking in my trigger function.
Yes.
At Tue, 6 Mar 2012 12:33:22 +0000, Mark Brown wrote:
On Tue, Mar 06, 2012 at 12:25:16PM +0000, Russell King - ARM Linux wrote:
Please also note that in ALSA documentation, an 'atomic' callback means little with respect to race conditions. All it means is that the callback is called from a context where sleeping in the callback is not permitted. The documentation does not say what is protected by the ALSA spinlocks and mutexes, so without reviewing the ALSA code, driver writters have little idea whether they need their own locks or not.
Well, who reads the documentation to get this stuff anyway?
At least Russell has read it ;)
Indeed, the word "atomic" in that context may be misleading. Meanwhile, it's actually protected by spinlock against the race to change the PCM state. But, since the PCM state is assigned to each substream, the protection is also only for a substream.
There are other some protections, e.g. in reset and prepare callbacks, but these are against linked streams via rw-semaphore, so that the linked list won't be corrupted. So, each substream instance isn't entirely protected in these cases.
As you observe it's far from complete about what's what locked when and how so you need to go to the code to see what's actually going on, especially whenever you need to call back into the ALSA APIs. Though of course I'm pretty sure there's a bunch of uniprocessor assumptions through the body of driver code anyway...
Not that much actually. On the contrary, because of the current design allowing concurrent accesses, many codes have been written rather in too complex and messy ways. It could have been much simplified if we didn't consider the concurrent accesses to each substream.
In summary, it's the lowlevel driver's responsibility to protect the concurrent hardware access. The ALSA core protects (in some level) the change of the PCM internal state of each substream. But it doesn't restrict the concurrent accesses over multiple substreams at all.
Takashi
On Tue, Mar 06, 2012 at 02:26:28PM +0100, Takashi Iwai wrote:
Mark Brown wrote:
On Tue, Mar 06, 2012 at 12:25:16PM +0000, Russell King - ARM Linux wrote:
whenever you need to call back into the ALSA APIs. Though of course I'm pretty sure there's a bunch of uniprocessor assumptions through the body of driver code anyway...
Not that much actually. On the contrary, because of the current design allowing concurrent accesses, many codes have been written rather in too complex and messy ways. It could have been much simplified if we didn't consider the concurrent accesses to each substream.
Right, but I'm fairly sure that at least some of the driver code is relying on uniprocessor assumptions for what it's doing - there's a bunch of things that can't happen on unipocessor that can happen on SMP (or preempting) systems.
At Tue, 6 Mar 2012 13:38:18 +0000, Mark Brown wrote:
On Tue, Mar 06, 2012 at 02:26:28PM +0100, Takashi Iwai wrote:
Mark Brown wrote:
On Tue, Mar 06, 2012 at 12:25:16PM +0000, Russell King - ARM Linux wrote:
whenever you need to call back into the ALSA APIs. Though of course I'm pretty sure there's a bunch of uniprocessor assumptions through the body of driver code anyway...
Not that much actually. On the contrary, because of the current design allowing concurrent accesses, many codes have been written rather in too complex and messy ways. It could have been much simplified if we didn't consider the concurrent accesses to each substream.
Right, but I'm fairly sure that at least some of the driver code is relying on uniprocessor assumptions for what it's doing - there's a bunch of things that can't happen on unipocessor that can happen on SMP (or preempting) systems.
Yeah, the driver codes. There must be handful such ones...
Takashi
On Tue, Mar 06, 2012 at 01:38:18PM +0000, Mark Brown wrote:
On Tue, Mar 06, 2012 at 02:26:28PM +0100, Takashi Iwai wrote:
Mark Brown wrote:
On Tue, Mar 06, 2012 at 12:25:16PM +0000, Russell King - ARM Linux wrote:
whenever you need to call back into the ALSA APIs. Though of course I'm pretty sure there's a bunch of uniprocessor assumptions through the body of driver code anyway...
Not that much actually. On the contrary, because of the current design allowing concurrent accesses, many codes have been written rather in too complex and messy ways. It could have been much simplified if we didn't consider the concurrent accesses to each substream.
Right, but I'm fairly sure that at least some of the driver code is relying on uniprocessor assumptions for what it's doing
Mark,
Stop using the term "uniprocessor assmptions".
Thinking that something is safe because you're running on a uniprocessor system is total bollocks at every level.
You can get other threads scheduled on a uniprocessor system because you happen to have called a function which has slept beneath you. As you later mention in your reply, preempt. Preempt will effectively turn a UP system into an effective SMP system as far as proper locking goes.
So, to talk about "uniprocessor assumptions" is at best misleading, but is totally and utterly wrong. Please stop mudding the issue with your system programming misunderstandings.
What you mean is "single threaded assumptions". Please use this term instead - it's what you actually mean.
On Tue, Mar 06, 2012 at 01:52:59PM +0000, Russell King - ARM Linux wrote:
Stop using the term "uniprocessor assmptions".
Thinking that something is safe because you're running on a uniprocessor system is total bollocks at every level.
Feh, it's hardly a new term - it dates back to when those crazy x86 kids first got their hands on this fancy new SMP stuff and started running into issues. It's coming from the fact that that was the first case to change the assumptions that had previously existed so things broke on SMP systems.
What you mean is "single threaded assumptions". Please use this term instead - it's what you actually mean.
If we're concerned about the name I'd not mention threads as that's often confusing for people in these contexts as it's not always obvious to everyone if or how interrupts count. "Single execution context" or even "old school Linux" are probably less ambiguous.
On Tue, Mar 06, 2012 at 12:33:22PM +0000, Mark Brown wrote:
On Tue, Mar 06, 2012 at 12:25:16PM +0000, Russell King - ARM Linux wrote:
Please also note that in ALSA documentation, an 'atomic' callback means little with respect to race conditions. All it means is that the callback is called from a context where sleeping in the callback is not permitted. The documentation does not say what is protected by the ALSA spinlocks and mutexes, so without reviewing the ALSA code, driver writters have little idea whether they need their own locks or not.
Well, who reads the documentation to get this stuff anyway?
Strangely, I do, and I'd bet most people writing an ALSA driver read the "Writing an ALSA Driver" document, even though it's seven years old. I also tend to read the code as well, though not everyone does.
As you observe it's far from complete about what's what locked when and how so you need to go to the code to see what's actually going on, especially whenever you need to call back into the ALSA APIs.
The point is, during this thread I've had this 'atomic' business quoted at me as the reason why read-modify-write of registers is safe. That's also proof that people other than me read that document - but not only that, they then go on to misunderstand it and don't bother to read the code.
On Mon, Mar 05, 2012 at 12:13:52AM +0000, Tabi Timur-B04825 wrote:
Russell King - ARM Linux wrote:
On Sun, Mar 04, 2012 at 11:32:50PM +0000, Tabi Timur-B04825 wrote:
Russell King - ARM Linux wrote:
Is the SCR shared between capture and playback? In that case, what makes this read-modify-write thread safe?
What's "SCR"?
I assumed you knew the code you were commenting on.
clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
The register these functions seem to be used on appears to be called 'SCR'.
Oh, I didn't know you were referencing a specific register on the part. There are multiple uses of clrsetbits_be32 (and its variants) in the function.
To answer your question: I was lead to believe that the individual ALSA callback functions are atomic. So one thread should not be trying to start playback while another thread is simultaneously trying to stop it.
Atomic with respect to what though? The substream? The PCM? All PCMs? Reading through the code, it turns out that the answer is the PCM, so calls into the low level driver are serialized by a per-PCM mutex.
However, this is not true of the trigger callback - the trigger callback does not take this mutex, but instead takes a spinlock (or two.) Whether this is enough to stop the capture and playback substream triggers being called simultaneously seems to depend on whether the substreams are part of the same group (which they probably aren't.)
So, in theory you could have the trigger method being called for the capture device while the playback device is in the middle of being opened. Luckily, for this case, the startup method only touches the hardware if its the first substream being opened, and shutdown only touches the hardware if its the last substream being closed.
However, I'm left wondering whether two trigger callbacks, one for the playback substream and one for the capture substream could be called simultaneously on two different CPUs. I see nothing which prevents this happening.
On Sun, Mar 04, 2012 at 11:13:09PM +0000, Tabi Timur-B04825 wrote:
Shawn Guo wrote:
+#ifdef PPC +#define read_ssi(addr) in_be32(addr) +#define write_ssi(val, addr) out_be32(addr, val) +#elif defined ARM +#define read_ssi(addr) readl(addr) +#define write_ssi(val, addr) writel(val, addr) +#endif
Can you also add an ARM version of clrsetbits_be32()? Something like this:
#ifdef PPC #define read_ssi(addr) in_be32(addr) #define write_ssi(val, addr) out_be32(addr, val) #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) #elif defined ARM #define read_ssi(addr) readl(addr) #define write_ssi(val, addr) writel(val, addr) #define write_ssi_mask(addr, clear, set) \ { u32 __val; \ val = readl(&ssi->scr); \ val = (val & ~(clear) | (set); \ writel(val, addr) #endif
Yeah, it makes the diff neat. However I would make it an inline function which is easier to play.
#ifdef PPC #define read_ssi(addr) in_be32(addr) #define write_ssi(val, addr) out_be32(addr, val) #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) #elif defined ARM #define read_ssi(addr) readl(addr) #define write_ssi(val, addr) writel(val, addr) static inline void write_ssi_mask(void __iomem *addr, u32 clear, u32 set) { u32 val = readl(addr); val = (val & ~clear) | set; writel(val, addr); } #endif
Shawn Guo wrote:
Yeah, it makes the diff neat. However I would make it an inline function which is easier to play.
However you want to do it is fine with me, although I would use "u32 __iomem *addr" instead of "void __iomem *addr".
On Mon, Mar 05, 2012 at 12:28:52PM +0000, Tabi Timur-B04825 wrote:
Shawn Guo wrote:
Yeah, it makes the diff neat. However I would make it an inline function which is easier to play.
However you want to do it is fine with me, although I would use "u32 __iomem *addr" instead of "void __iomem *addr".
Right, will make the change.
As Documentation/devicetree/bindings/powerpc/fsl/ssi.txt documented, codec-handle is an optional property, so missing it should not be a fatal error.
More importantly, the imx machine drivers to be added working with fsl_ssi will not have this property, as they use new ASoC machine driver binding mechanism.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/fsl/fsl_ssi.c | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 0b53682..9846091 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -647,12 +647,6 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) if (!of_device_is_available(np)) return -ENODEV;
- /* Check for a codec-handle property. */ - if (!of_get_property(np, "codec-handle", NULL)) { - dev_err(&pdev->dev, "missing codec-handle property\n"); - return -ENODEV; - } - /* We only support the SSI in "I2S Slave" mode */ sprop = of_get_property(np, "fsl,mode", NULL); if (!sprop || strcmp(sprop, "i2s-slave")) {
Makes necessary changes on fsl_ssi to let it work with imx pcm and machine drivers.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- sound/soc/fsl/fsl_ssi.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 9846091..270fc81 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -28,6 +28,7 @@ #include <sound/soc.h>
#include "fsl_ssi.h" +#include "imx-pcm.h"
#ifdef PPC #define read_ssi(addr) in_be32(addr) @@ -105,6 +106,10 @@ struct fsl_ssi_private { struct device_attribute dev_attr; struct platform_device *pdev;
+ int ssi_on_imx; + struct imx_pcm_dma_params dma_params_tx; + struct imx_pcm_dma_params dma_params_rx; + struct { unsigned int rfrc; unsigned int tfrc; @@ -406,6 +411,12 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, ssi_private->second_stream = substream; }
+ if (ssi_private->ssi_on_imx) + snd_soc_dai_set_dma_data(dai, substream, + (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + &ssi_private->dma_params_tx : + &ssi_private->dma_params_rx); + return 0; }
@@ -711,6 +722,38 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) /* Older 8610 DTs didn't have the fifo-depth property */ ssi_private->fifo_depth = 8;
+ if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx1-ssi")) { + u32 dma_events[2]; + ssi_private->ssi_on_imx = 1; + /* + * FIXME: The dma burst size must equal to ssi watermark + * setting on imx. We have burstsize be "fifo_depth - 2" + * here because "fifo_depth - 2" rather than fifo_depth is + * being written into watermark register in fsl_ssi_startup(). + * Is this something needs to be fixed for PowerPC? + */ + ssi_private->dma_params_tx.burstsize = + ssi_private->fifo_depth - 2; + ssi_private->dma_params_rx.burstsize = + ssi_private->fifo_depth - 2; + ssi_private->dma_params_tx.dma_addr = + ssi_private->ssi_phys + offsetof(struct ccsr_ssi, stx0); + ssi_private->dma_params_rx.dma_addr = + ssi_private->ssi_phys + offsetof(struct ccsr_ssi, srx0); + /* + * TODO: This is a temporary solution and should be changed + * to use generic DMA binding later when the helplers get in. + */ + ret = of_property_read_u32_array(pdev->dev.of_node, + "fsl,ssi-dma-events", dma_events, 2); + if (ret) { + dev_err(&pdev->dev, "could not get dma events\n"); + goto error_irq; + } + ssi_private->dma_params_tx.dma = dma_events[0]; + ssi_private->dma_params_rx.dma = dma_events[1]; + } + /* Initialize the the device_attribute structure */ dev_attr = &ssi_private->dev_attr; sysfs_attr_init(&dev_attr->attr); @@ -734,6 +777,13 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) goto error_dev; }
+ /* + * All imx machine drivers use new binding which does not require + * SSI driver to trigger machine driver's probe. + */ + if (ssi_private->ssi_on_imx) + return 0; + /* Trigger the machine driver's probe function. The platform driver * name of the machine driver is taken from /compatible property of the * device tree. We also pass the address of the CPU DAI driver @@ -798,6 +848,7 @@ static int fsl_ssi_remove(struct platform_device *pdev)
static const struct of_device_id fsl_ssi_ids[] = { { .compatible = "fsl,mpc8610-ssi", }, + { .compatible = "fsl,imx1-ssi", }, {} }; MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
From: Richard Zhao richard.zhao@linaro.org
It adds device tree probe support for imx-audmux driver.
Signed-off-by: Richard Zhao richard.zhao@linaro.org Signed-off-by: Shawn Guo shawn.guo@linaro.org --- .../devicetree/bindings/sound/imx-audmux.txt | 13 +++++++++++++ sound/soc/fsl/imx-audmux.c | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/imx-audmux.txt
diff --git a/Documentation/devicetree/bindings/sound/imx-audmux.txt b/Documentation/devicetree/bindings/sound/imx-audmux.txt new file mode 100644 index 0000000..215aa98 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/imx-audmux.txt @@ -0,0 +1,13 @@ +Freescale Digital Audio Mux (AUDMUX) device + +Required properties: +- compatible : "fsl,imx21-audmux" for AUDMUX version firstly used on i.MX21, + or "fsl,imx31-audmux" for the version firstly used on i.MX31. +- reg : Should contain AUDMUX registers location and length + +Example: + +audmux@021d8000 { + compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux"; + reg = <0x021d8000 0x4000>; +}; diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index d7bf154..bcaa7ee 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -22,6 +22,8 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h>
@@ -197,6 +199,13 @@ static struct platform_device_id imx_audmux_ids[] = { }; MODULE_DEVICE_TABLE(platform, imx_audmux_ids);
+static const struct of_device_id imx_audmux_dt_ids[] = { + { .compatible = "fsl,imx21-audmux", .data = &imx_audmux_ids[0], }, + { .compatible = "fsl,imx31-audmux", .data = &imx_audmux_ids[1], }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_audmux_dt_ids); + static unsigned char port_mapping[] = { 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, }; @@ -243,6 +252,8 @@ EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); static int __init imx_audmux_probe(struct platform_device *pdev) { struct resource *res; + const struct of_device_id *of_id = + of_match_device(imx_audmux_dt_ids, &pdev->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); audmux_base = devm_request_and_ioremap(&pdev->dev, res); @@ -256,6 +267,8 @@ static int __init imx_audmux_probe(struct platform_device *pdev) audmux_clk = NULL; }
+ if (of_id) + pdev->id_entry = of_id->data; audmux_type = pdev->id_entry->driver_data; if (audmux_type == IMX31_AUDMUX) audmux_debugfs_init(); @@ -279,6 +292,7 @@ static struct platform_driver imx_audmux_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .of_match_table = imx_audmux_dt_ids, } };
It moves and renames sgtl5000 device tree binding document to make it aligned with other codecs.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- .../{soc/codecs/fsl-sgtl5000.txt => sgtl5000.txt} | 0 1 files changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/sound/{soc/codecs/fsl-sgtl5000.txt => sgtl5000.txt} (100%)
diff --git a/Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/sgtl5000.txt similarity index 100% rename from Documentation/devicetree/bindings/sound/soc/codecs/fsl-sgtl5000.txt rename to Documentation/devicetree/bindings/sound/sgtl5000.txt
This is the initial imx-sgtl5000 machine driver support with only playback dai link implemented. More features can be added on top of it later.
It's a device tree only machine driver working with fsl_ssi driver.
Signed-off-by: Shawn Guo shawn.guo@linaro.org --- .../bindings/sound/imx-audio-sgtl5000.txt | 24 +++ sound/soc/fsl/Kconfig | 12 ++ sound/soc/fsl/Makefile | 2 + sound/soc/fsl/imx-sgtl5000.c | 210 ++++++++++++++++++++ 4 files changed, 248 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt create mode 100644 sound/soc/fsl/imx-sgtl5000.c
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt b/Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt new file mode 100644 index 0000000..22b3f03 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt @@ -0,0 +1,24 @@ +Freescale i.MX audio complex with SGTL5000 codec + +Required properties: +- compatible : "fsl,imx-audio-sgtl5000" +- fsl,model : The user-visible name of this sound complex +- fsl,ssi-controller : The phandle of the i.MX SSI controller +- fsl,audio-codec : The phandle of the SGTL5000 audio codec +- fsl,mux-int-port : The internal port of the i.MX audio muxer (AUDMUX) +- fsl,mux-ext-port : The external port of the i.MX audio muxer + +Note: The AUDMUX port numbering should start at 1, which is consistent with +hardware manual. + +Example: + +sound { + compatible = "fsl,imx51-babbage-sgtl5000", + "fsl,imx-audio-sgtl5000"; + fsl,model = "imx51-babbage-sgtl5000"; + fsl,ssi-controller = <&ssi1>; + fsl,audio-codec = <&sgtl5000>; + fsl,mux-int-port = <1>; + fsl,mux-ext-port = <3>; +}; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index e579671..42a3842 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -164,4 +164,16 @@ config SND_SOC_EUKREA_TLV320 Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface
+config SND_SOC_IMX_SGTL5000 + tristate "SoC Audio support for i.MX boards with sgtl5000" + depends on OF && I2C + select SND_SOC_SGTL5000 + select SND_MXC_SOC_MX2 + select SND_SOC_IMX_AUDMUX + select SND_SOC_FSL_SSI + select SND_SOC_FSL_UTILS + help + Say Y if you want to add support for SoC audio on an i.MX board with + a sgtl5000 codec. + endif # SND_IMX_SOC diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 02b3e53..5ae854b 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -40,8 +40,10 @@ snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o snd-soc-phycore-ac97-objs := phycore-ac97.o snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o snd-soc-wm1133-ev1-objs := wm1133-ev1.o +snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o +obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c new file mode 100644 index 0000000..483733f --- /dev/null +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -0,0 +1,210 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2012 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <sound/soc.h> + +#include "../codecs/sgtl5000.h" +#include "fsl_utils.h" +#include "imx-audmux.h" + +struct imx_sgtl5000_data { + struct snd_soc_dai_link dai[2]; + struct snd_soc_card card; + struct platform_device *pcm_audio_pdev; + struct platform_device *soc_audio_pdev; + char codec_name[DAI_NAME_SIZE]; + char codec_dai_name[DAI_NAME_SIZE]; + char platform_name[DAI_NAME_SIZE]; + unsigned int clk_frequency; +}; + +static int imx_sgtl5000_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct imx_sgtl5000_data *data = container_of(rtd->card, + struct imx_sgtl5000_data, card); + struct device *dev = rtd->card->dev; + int ret; + + ret = snd_soc_dai_set_fmt(rtd->codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM); + if (ret) { + dev_err(dev, "could not set codec driver audio format\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(rtd->codec_dai, SGTL5000_SYSCLK, + data->clk_frequency, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(dev, "could not set codec driver clock params\n"); + return ret; + } + + return 0; +} + +static struct snd_soc_ops imx_sgtl5000_ops = { + .startup = imx_sgtl5000_startup, +}; + +static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *ssi_np, *codec_np; + struct platform_device *ssi_pdev; + struct imx_sgtl5000_data *data; + int int_port, ext_port; + int ret; + + ret = of_property_read_u32(np, "fsl,mux-int-port", &int_port); + if (ret) { + dev_err(&pdev->dev, "mux-int-port missing or invalid\n"); + return -EINVAL; + } + ret = of_property_read_u32(np, "fsl,mux-ext-port", &ext_port); + if (ret) { + dev_err(&pdev->dev, "mux-ext-port missing or invalid\n"); + return -EINVAL; + } + + /* + * The port numbering in the hardware manual starts at 1, while + * the audmux API expects it starts at 0. + */ + int_port--; + ext_port--; + imx_audmux_v2_configure_port(int_port, + IMX_AUDMUX_V2_PTCR_SYN | + IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) | + IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) | + IMX_AUDMUX_V2_PTCR_TFSDIR | + IMX_AUDMUX_V2_PTCR_TCLKDIR, + IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)); + imx_audmux_v2_configure_port(ext_port, + IMX_AUDMUX_V2_PTCR_SYN | + IMX_AUDMUX_V2_PTCR_TCSEL(int_port), + IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); + + ssi_np = of_parse_phandle(pdev->dev.of_node, "fsl,ssi-controller", 0); + codec_np = of_parse_phandle(pdev->dev.of_node, "fsl,audio-codec", 0); + if (!ssi_np || !codec_np) { + dev_err(&pdev->dev, "phandle missing or invalid\n"); + return -EINVAL; + } + + ssi_pdev = of_find_device_by_node(ssi_np); + if (!ssi_pdev) { + dev_err(&pdev->dev, "failed to find SSI platform device\n"); + return -EINVAL; + } + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = of_property_read_u32(codec_np, "clock-frequency", + &data->clk_frequency); + if (ret) { + dev_err(&pdev->dev, "clock-frequency missing or invalid\n"); + return -EINVAL; + } + + ret = fsl_asoc_get_codec_dev_name(codec_np, data->codec_name, + DAI_NAME_SIZE); + if (ret) { + dev_err(&pdev->dev, "failed to get codec name\n"); + return -EINVAL; + } + + data->dai[0].name = "HiFi Tx"; + data->dai[0].stream_name = "HiFi Playback"; + data->dai[0].codec_dai_name = "sgtl5000"; + data->dai[0].codec_name = data->codec_name; + data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); + data->dai[0].platform_name = "imx-pcm-audio"; + data->dai[0].ops = &imx_sgtl5000_ops; + + ret = of_property_read_string(np, "fsl,model", &data->card.name); + if (ret) { + dev_err(&pdev->dev, "failed to get audio card name\n"); + return -EINVAL; + } + data->card.num_links = 1; + data->card.dai_link = data->dai; + + /* Add imx-pcm-audio device */ + data->pcm_audio_pdev = platform_device_alloc("imx-pcm-audio", -1); + if (!data->pcm_audio_pdev) + return -ENOMEM; + ret = platform_device_add(data->pcm_audio_pdev); + if (ret) { + platform_device_put(data->pcm_audio_pdev); + return ret; + } + + /* Add soc-audio device */ + data->soc_audio_pdev = platform_device_alloc("soc-audio", -1); + if (!data->soc_audio_pdev) { + ret = -ENOMEM; + goto err; + } + platform_set_drvdata(data->soc_audio_pdev, &data->card); + ret = platform_device_add(data->soc_audio_pdev); + if (ret) { + platform_device_put(data->soc_audio_pdev); + goto err; + } + + dev_set_drvdata(&pdev->dev, data); + of_node_put(codec_np); + + return 0; +err: + platform_device_unregister(data->pcm_audio_pdev); + return ret; +} + +static int __devexit imx_sgtl5000_remove(struct platform_device *pdev) +{ + struct imx_sgtl5000_data *data = dev_get_drvdata(&pdev->dev); + + platform_device_unregister(data->pcm_audio_pdev); + platform_device_unregister(data->soc_audio_pdev); + + return 0; +} + +static const struct of_device_id imx_sgtl5000_dt_ids[] = { + { .compatible = "fsl,imx-audio-sgtl5000", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_sgtl5000_dt_ids); + +static struct platform_driver imx_sgtl5000_driver = { + .driver = { + .name = "imx-sgtl5000", + .owner = THIS_MODULE, + .of_match_table = imx_sgtl5000_dt_ids, + }, + .probe = imx_sgtl5000_probe, + .remove = __devexit_p(imx_sgtl5000_remove), +}; +module_platform_driver(imx_sgtl5000_driver); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("Freescale i.MX SGTL5000 ASoC machine driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:imx-sgtl5000");
On Sat, Mar 03, 2012 at 11:20:01PM +0800, Shawn Guo wrote:
- ret = snd_soc_dai_set_fmt(rtd->codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM);
Initialise this from the card.
Since none of the startup is dynamic it should all be done on DAI init rather than rerun each time audio is started.
- /* Add soc-audio device */
- data->soc_audio_pdev = platform_device_alloc("soc-audio", -1);
- if (!data->soc_audio_pdev) {
ret = -ENOMEM;
goto err;
- }
No, use snd_soc_register_card(). soc-audio has been deprecated since 2.6.38.
+static int __devexit imx_sgtl5000_remove(struct platform_device *pdev) +{
- struct imx_sgtl5000_data *data = dev_get_drvdata(&pdev->dev);
- platform_device_unregister(data->pcm_audio_pdev);
This looks like there's a problem with the bindings, why are you registering the DMA device from the card?
On Sun, Mar 04, 2012 at 01:38:18PM +0000, Mark Brown wrote:
On Sat, Mar 03, 2012 at 11:20:01PM +0800, Shawn Guo wrote:
- ret = snd_soc_dai_set_fmt(rtd->codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM);
Initialise this from the card.
Since none of the startup is dynamic it should all be done on DAI init rather than rerun each time audio is started.
Ok, will move imx_sgtl5000_startup over to snd_soc_dai_link init hook. Please let me know if this is not what you are asking for.
- /* Add soc-audio device */
- data->soc_audio_pdev = platform_device_alloc("soc-audio", -1);
- if (!data->soc_audio_pdev) {
ret = -ENOMEM;
goto err;
- }
No, use snd_soc_register_card(). soc-audio has been deprecated since 2.6.38.
I copied it from mpc8610_hpcd driver. Will change.
+static int __devexit imx_sgtl5000_remove(struct platform_device *pdev) +{
- struct imx_sgtl5000_data *data = dev_get_drvdata(&pdev->dev);
- platform_device_unregister(data->pcm_audio_pdev);
This looks like there's a problem with the bindings, why are you registering the DMA device from the card?
There is a dma node in the device tree to instantiate the dma device backed by a dmaengine driver. As a client peripheral of that dmaengine device, the SSI owns just a dma request/event number. With the number encoded in SSI node, there is no hardware resource to be claimed by that pcm-device, so we do not have it in device tree. Then we have to register this device in either fsl_ssi driver or machine driver. I chose to do something that tegra is doing, registering the pcm device in machine driver, to keep fsl_ssi away from imx specific bits as much as possible.
On Mon, Mar 05, 2012 at 04:06:25PM +0800, Shawn Guo wrote:
On Sun, Mar 04, 2012 at 01:38:18PM +0000, Mark Brown wrote:
This looks like there's a problem with the bindings, why are you registering the DMA device from the card?
There is a dma node in the device tree to instantiate the dma device backed by a dmaengine driver. As a client peripheral of that dmaengine device, the SSI owns just a dma request/event number. With the number encoded in SSI node, there is no hardware resource to be claimed by that pcm-device, so we do not have it in device tree. Then we have to register this device in either fsl_ssi driver or machine driver. I chose to do something that tegra is doing, registering the pcm device in machine driver, to keep fsl_ssi away from imx specific bits as much as possible.
The above sounds like you have a unified DAI and PCM driver. In that case they should either both be using the same device or should have some sort of parent/child/sibling relationship. Either way the machine driver really shouldn't be involved in instantiating things, perhaps arch/arm but not the audio machine driver.
On Mon, Mar 05, 2012 at 11:56:12AM +0000, Mark Brown wrote:
On Mon, Mar 05, 2012 at 04:06:25PM +0800, Shawn Guo wrote:
On Sun, Mar 04, 2012 at 01:38:18PM +0000, Mark Brown wrote:
This looks like there's a problem with the bindings, why are you registering the DMA device from the card?
There is a dma node in the device tree to instantiate the dma device backed by a dmaengine driver. As a client peripheral of that dmaengine device, the SSI owns just a dma request/event number. With the number encoded in SSI node, there is no hardware resource to be claimed by that pcm-device, so we do not have it in device tree. Then we have to register this device in either fsl_ssi driver or machine driver. I chose to do something that tegra is doing, registering the pcm device in machine driver, to keep fsl_ssi away from imx specific bits as much as possible.
The above sounds like you have a unified DAI and PCM driver.
The pcm-dma driver is being shared across several i.MX SoCs, and we are trying to reuse fsl_ssi driver between PowerPC and IMX.
In that case they should either both be using the same device or should have some sort of parent/child/sibling relationship.
Sorry, I do not understand it. Can you elaborate it a little bit?
Either way the machine driver really shouldn't be involved in instantiating things, perhaps arch/arm but not the audio machine driver.
So you are saying neither what tegra_wm8903 and tegra_alc5632 are doing (registering pcm device in machine driver) nor what imx-ssi is doing (registering pcm device in DAI driver) is correct? Can you please make it clear what's the right thing to do?
On Mon, Mar 05, 2012 at 09:07:09PM +0800, Shawn Guo wrote:
On Mon, Mar 05, 2012 at 11:56:12AM +0000, Mark Brown wrote:
In that case they should either both be using the same device or should have some sort of parent/child/sibling relationship.
Sorry, I do not understand it. Can you elaborate it a little bit?
The DMA and SSI drivers should have some relationship with each other if they're the same piece of hardware. The machine driver certainly shouldn't be creating either of them.
Either way the machine driver really shouldn't be involved in instantiating things, perhaps arch/arm but not the audio machine driver.
So you are saying neither what tegra_wm8903 and tegra_alc5632 are doing (registering pcm device in machine driver) nor what imx-ssi is doing (registering pcm device in DAI driver) is correct? Can you please make it clear what's the right thing to do?
The above.
Mark Brown wrote at Monday, March 05, 2012 6:14 AM:
On Mon, Mar 05, 2012 at 09:07:09PM +0800, Shawn Guo wrote:
On Mon, Mar 05, 2012 at 11:56:12AM +0000, Mark Brown wrote:
In that case they should either both be using the same device or should have some sort of parent/child/sibling relationship.
Sorry, I do not understand it. Can you elaborate it a little bit?
The DMA and SSI drivers should have some relationship with each other if they're the same piece of hardware. The machine driver certainly shouldn't be creating either of them.
Note that in Tegra's case, the DMA HW and the DAI (I2S/SPDIF) HW are entirely separate HW blocks and have entirely separate drivers. The DMA engine is generic and not audio specific, so has a node that instantiates just a standalone DMA device which has its own API. This doesn't instantiate any kind of ALSA PCM driver. It doesn't make sense to have a DT node to instantiate the ALSA PCM driver since the PCM driver is more of an API bridge to the real DMA HW, and certainly not an actual HW module. It doesn't make sense to have either the I2S or SPDIF DAI drivers instantiate the PCM driver, since they both share the same one. Hence, the machine driver instantiates the PCM driver.
Perhaps our regular DMA module driver should expose both its custom interface for other clients, and register an ASoC PCM driver? That way we could remove the PCM device registration from the ASoC machine drivers.
Either way the machine driver really shouldn't be involved in instantiating things, perhaps arch/arm but not the audio machine driver.
So you are saying neither what tegra_wm8903 and tegra_alc5632 are doing (registering pcm device in machine driver) nor what imx-ssi is doing (registering pcm device in DAI driver) is correct? Can you please make it clear what's the right thing to do?
The above.
On Mon, Mar 05, 2012 at 08:55:22AM -0800, Stephen Warren wrote:
Mark Brown wrote at Monday, March 05, 2012 6:14 AM:
The DMA and SSI drivers should have some relationship with each other if they're the same piece of hardware. The machine driver certainly shouldn't be creating either of them.
Note that in Tegra's case, the DMA HW and the DAI (I2S/SPDIF) HW are entirely separate HW blocks and have entirely separate drivers. The DMA engine is generic and not audio specific, so has a node that instantiates just a standalone DMA device which has its own API. This doesn't instantiate any kind of ALSA PCM driver. It doesn't make sense to have a
In this case (and probably in the i.MX case, at a guess the structure is the same) I'd just have the DAI drivers kick off registration of the ASoC DMA stuff, it's all part of the ASoC driver for the hardware really.
DT node to instantiate the ALSA PCM driver since the PCM driver is more of an API bridge to the real DMA HW, and certainly not an actual HW
Yes, and a Linux driver model device is questionable too.
Perhaps our regular DMA module driver should expose both its custom interface for other clients, and register an ASoC PCM driver? That way we could remove the PCM device registration from the ASoC machine drivers.
That's another option, do it from the DMA driver instead of the DAI driver. My main concern here is that it shouldn't be the machine driver as it's all internal to the CPU and not machine specific.
On 03/05/2012 10:03 AM, Mark Brown wrote:
- PGP Signed by an unknown key
On Mon, Mar 05, 2012 at 08:55:22AM -0800, Stephen Warren wrote:
Mark Brown wrote at Monday, March 05, 2012 6:14 AM:
The DMA and SSI drivers should have some relationship with each other if they're the same piece of hardware. The machine driver certainly shouldn't be creating either of them.
Note that in Tegra's case, the DMA HW and the DAI (I2S/SPDIF) HW are entirely separate HW blocks and have entirely separate drivers. The DMA engine is generic and not audio specific, so has a node that instantiates just a standalone DMA device which has its own API. This doesn't instantiate any kind of ALSA PCM driver. It doesn't make sense to have a
In this case (and probably in the i.MX case, at a guess the structure is the same) I'd just have the DAI drivers kick off registration of the ASoC DMA stuff, it's all part of the ASoC driver for the hardware really.
How would that work when there are multiple DAIs, e.g. on a system with 2 I2S and 1 SPDIF DAI and they all want to register the PCM driver? I guess I could just add some utility function in the PCM driver file to ensure that the platform device only gets created once, and probably would also need to refcount it for when the DAIs get unloaded etc.
DT node to instantiate the ALSA PCM driver since the PCM driver is more of an API bridge to the real DMA HW, and certainly not an actual HW
Yes, and a Linux driver model device is questionable too.
Perhaps our regular DMA module driver should expose both its custom interface for other clients, and register an ASoC PCM driver? That way we could remove the PCM device registration from the ASoC machine drivers.
That's another option, do it from the DMA driver instead of the DAI driver. My main concern here is that it shouldn't be the machine driver as it's all internal to the CPU and not machine specific.
OK, not sure which way I prefer yet.
I'll file a bug internally for this so I don't forget about it...
On Tue, Mar 06, 2012 at 11:19:20AM -0700, Stephen Warren wrote:
In this case (and probably in the i.MX case, at a guess the structure is the same) I'd just have the DAI drivers kick off registration of the ASoC DMA stuff, it's all part of the ASoC driver for the hardware really.
How would that work when there are multiple DAIs, e.g. on a system with 2 I2S and 1 SPDIF DAI and they all want to register the PCM driver? I guess I could just add some utility function in the PCM driver file to ensure that the platform device only gets created once, and probably would also need to refcount it for when the DAIs get unloaded etc.
You could just create a DMA device per DAI since it's just a wrapper, you shouldn't even need to allocate a new struct device but just use the DAI device when registering the ASoC DMA driver.
Mark Brown wrote:
The DMA and SSI drivers should have some relationship with each other if they're the same piece of hardware.
The DMA and SSI are completely separate blocks in the SOC. On PowerPC, the P1022 SOC has an SSI and the standard FSL PPC DMA controller (we call it the Elo controller). On i.MX, there is a completely different DMA controller (I'm not familiar with it), but the same exact SSI.
On Mon, Mar 05, 2012 at 10:58:54AM -0600, Timur Tabi wrote:
Mark Brown wrote:
The DMA and SSI drivers should have some relationship with each other if they're the same piece of hardware.
The DMA and SSI are completely separate blocks in the SOC. On PowerPC, the P1022 SOC has an SSI and the standard FSL PPC DMA controller (we call it the Elo controller). On i.MX, there is a completely different DMA controller (I'm not familiar with it), but the same exact SSI.
Right, but in both cases we're talking about the adaption layer from ASoC to the support for the controller which is shared between everything on the SoC (though currently the PowerPC one just talks to the registers directly) so logically from a system perspective it's a part of the SSI driver.
Possibly the way to go here is to just call the DMA driver something generic (though you don't really need a separate Linux level device from a subsystem point of view) or have a library function which is implemented differently on each platform then have the SSI driver either create the device or do the call.
Either way it's something the SoC code ought to be handling, individual machine drivers shouldn't have to worry themselves about it.
On Sun, Mar 04, 2012 at 11:34:31PM +0000, Tabi Timur-B04825 wrote:
Shawn Guo wrote:
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
I encourage developers to put their own name in the MODULE_AUTHOR macro.
Seems you get a strong opinion on this. Okay, will put my name there.
On Sat, Mar 03, 2012 at 11:19:41PM +0800, Shawn Guo wrote:
It's the full series adding imx-sgtl5000 machine driver which works with fsl_ssi driver on DT based imx platforms.
- Patches 1 ~ 5: Convert audmux driver to a platform driver and move it into ASoC folder.
- Patches 6 ~ 12: Merge ASoC imx and fsl folders.
This also contains a bunch of random cleanups and refactorings which *really* should have been at the start of the series so they could be applied without dependencies on the other stuff...
participants (9)
-
Mark Brown
-
Russell King - ARM Linux
-
Sascha Hauer
-
Shawn Guo
-
Stephen Warren
-
Stephen Warren
-
Tabi Timur-B04825
-
Takashi Iwai
-
Timur Tabi