Commit 30307634 authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into topic/asoc

A few more ASoC updates, the main one is the move of the audmux driver
from arch/arm into sound/soc.  There's also some general driver specific
tweaks and fixes.
parents 650d6e25 9d5ef266
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>;
};
......@@ -46,7 +46,6 @@ config SOC_IMX21
bool
select MACH_MX21
select CPU_ARM926T
select ARCH_MXC_AUDMUX_V1
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_V2
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_V1
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_V2
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_V2
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_V2
select ARCH_HAS_CPUFREQ
select ARCH_MX5
bool
......
......@@ -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)
......
......@@ -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"
......
......@@ -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);
......
......@@ -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);
......
......@@ -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)
......
......@@ -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);
......
......@@ -75,6 +75,10 @@ void __init mx21_init_irq(void)
mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
}
static const struct resource imx21_audmux_res[] __initconst = {
DEFINE_RES_MEM(MX21_AUDMUX_BASE_ADDR, SZ_4K),
};
void __init imx21_soc_init(void)
{
mxc_register_gpio("imx21-gpio", 0, MX21_GPIO1_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
......@@ -85,4 +89,6 @@ void __init imx21_soc_init(void)
mxc_register_gpio("imx21-gpio", 5, MX21_GPIO6_BASE_ADDR, SZ_256, MX21_INT_GPIO, 0);
imx_add_imx_dma();
platform_device_register_simple("imx21-audmux", 0, imx21_audmux_res,
ARRAY_SIZE(imx21_audmux_res));
}
......@@ -83,6 +83,10 @@ static struct sdma_platform_data imx25_sdma_pdata __initdata = {
.script_addrs = &imx25_sdma_script,
};
static const struct resource imx25_audmux_res[] __initconst = {
DEFINE_RES_MEM(MX25_AUDMUX_BASE_ADDR, SZ_16K),
};
void __init imx25_soc_init(void)
{
/* i.mx25 has the i.mx31 type gpio */
......@@ -93,4 +97,7 @@ void __init imx25_soc_init(void)
/* i.mx25 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
/* i.mx25 has the i.mx31 type audmux */
platform_device_register_simple("imx31-audmux", 0, imx25_audmux_res,
ARRAY_SIZE(imx25_audmux_res));
}
......@@ -75,6 +75,10 @@ void __init mx27_init_irq(void)
mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
}
static const struct resource imx27_audmux_res[] __initconst = {
DEFINE_RES_MEM(MX27_AUDMUX_BASE_ADDR, SZ_4K),
};
void __init imx27_soc_init(void)
{
/* i.mx27 has the i.mx21 type gpio */
......@@ -86,4 +90,7 @@ void __init imx27_soc_init(void)
mxc_register_gpio("imx21-gpio", 5, MX27_GPIO6_BASE_ADDR, SZ_256, MX27_INT_GPIO, 0);
imx_add_imx_dma();
/* imx27 has the imx21 type audmux */
platform_device_register_simple("imx21-audmux", 0, imx27_audmux_res,
ARRAY_SIZE(imx27_audmux_res));
}
......@@ -158,6 +158,10 @@ static struct sdma_platform_data imx31_sdma_pdata __initdata = {
.script_addrs = &imx31_to2_sdma_script,
};
static const struct resource imx31_audmux_res[] __initconst = {
DEFINE_RES_MEM(MX31_AUDMUX_BASE_ADDR, SZ_16K),
};
void __init imx31_soc_init(void)
{
int to_version = mx31_revision() >> 4;
......@@ -175,6 +179,8 @@ void __init imx31_soc_init(void)
}
imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
platform_device_register_simple("imx31-audmux", 0, imx31_audmux_res,
ARRAY_SIZE(imx31_audmux_res));
}
#endif /* ifdef CONFIG_SOC_IMX31 */
......@@ -241,6 +247,10 @@ static struct sdma_platform_data imx35_sdma_pdata __initdata = {
.script_addrs = &imx35_to2_sdma_script,
};
static const struct resource imx35_audmux_res[] __initconst = {
DEFINE_RES_MEM(MX35_AUDMUX_BASE_ADDR, SZ_16K),
};
void __init imx35_soc_init(void)
{
int to_version = mx35_revision() >> 4;
......@@ -259,5 +269,8 @@ void __init imx35_soc_init(void)
}
imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
/* i.mx35 has the i.mx31 type audmux */
platform_device_register_simple("imx31-audmux", 0, imx35_audmux_res,
ARRAY_SIZE(imx35_audmux_res));
}
#endif /* ifdef CONFIG_SOC_IMX35 */
......@@ -170,6 +170,18 @@ static struct sdma_platform_data imx53_sdma_pdata __initdata = {
.script_addrs = &imx53_sdma_script,
};
static const struct resource imx50_audmux_res[] __initconst = {
DEFINE_RES_MEM(MX50_AUDMUX_BASE_ADDR, SZ_16K),
};
static const struct resource imx51_audmux_res[] __initconst = {
DEFINE_RES_MEM(MX51_AUDMUX_BASE_ADDR, SZ_16K),
};
static const struct resource imx53_audmux_res[] __initconst = {
DEFINE_RES_MEM(MX53_AUDMUX_BASE_ADDR, SZ_16K),
};
void __init imx50_soc_init(void)
{
/* i.mx50 has the i.mx31 type gpio */
......@@ -179,6 +191,10 @@ void __init imx50_soc_init(void)
mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
/* i.mx50 has the i.mx31 type audmux */
platform_device_register_simple("imx31-audmux", 0, imx50_audmux_res,
ARRAY_SIZE(imx50_audmux_res));
}
void __init imx51_soc_init(void)
......@@ -191,6 +207,9 @@ void __init imx51_soc_init(void)
/* i.mx51 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
/* i.mx51 has the i.mx31 type audmux */
platform_device_register_simple("imx31-audmux", 0, imx51_audmux_res,
ARRAY_SIZE(imx51_audmux_res));
}
void __init imx53_soc_init(void)
......@@ -206,4 +225,7 @@ void __init imx53_soc_init(void)
/* i.mx53 has the i.mx35 type sdma */
imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
/* i.mx53 has the i.mx31 type audmux */
platform_device_register_simple("imx31-audmux", 0, imx53_audmux_res,
ARRAY_SIZE(imx53_audmux_res));
}
......@@ -88,12 +88,6 @@ config IMX_HAVE_IOMUX_V1
config ARCH_MXC_IOMUX_V3
bool
config ARCH_MXC_AUDMUX_V1
bool
config ARCH_MXC_AUDMUX_V2
bool
config IRAM_ALLOC
bool
select GENERIC_ALLOCATOR
......
......@@ -14,8 +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_V1) += audmux-v1.o
obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o
ifdef CONFIG_SND_IMX_SOC
......
/*
* 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);
......@@ -755,6 +755,12 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
if (!wm8804)
return -ENOMEM;
wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config);
if (IS_ERR(wm8804->regmap)) {
ret = PTR_ERR(wm8804->regmap);
return ret;
}
i2c_set_clientdata(i2c, wm8804);
ret = snd_soc_register_codec(&i2c->dev,
......
......@@ -116,11 +116,11 @@ static struct reg_default wm8962_reg[] = {
{ 1, 0x049F }, /* R1 - Right Input volume */
{ 2, 0x0000 }, /* R2 - HPOUTL volume */
{ 3, 0x0000 }, /* R3 - HPOUTR volume */
{ 4, 0x0020 }, /* R4 - Clocking1 */
{ 5, 0x0018 }, /* R5 - ADC & DAC Control 1 */
{ 6, 0x2008 }, /* R6 - ADC & DAC Control 2 */
{ 7, 0x000A }, /* R7 - Audio Interface 0 */
{ 8, 0x01E4 }, /* R8 - Clocking2 */
{ 9, 0x0300 }, /* R9 - Audio Interface 1 */
{ 10, 0x00C0 }, /* R10 - Left DAC volume */
{ 11, 0x00C0 }, /* R11 - Right DAC volume */
......@@ -129,7 +129,7 @@ static struct reg_default wm8962_reg[] = {
{ 15, 0x6243 }, /* R15 - Software Reset */
{ 17, 0x007B }, /* R17 - ALC1 */
{ 18, 0x0000 }, /* R18 - ALC2 */
{ 19, 0x1C32 }, /* R19 - ALC3 */
{ 20, 0x3200 }, /* R20 - Noise Gate */
{ 21, 0x00C0 }, /* R21 - Left ADC volume */
......@@ -153,10 +153,6 @@ static struct reg_default wm8962_reg[] = {
{ 40, 0x0000 }, /* R40 - SPKOUTL volume */
{ 41, 0x0000 }, /* R41 - SPKOUTR volume */
{ 47, 0x0000 }, /* R47 - Thermal Shutdown Status */
{ 48, 0x8027 }, /* R48 - Additional Control (4) */
{ 49, 0x0010 }, /* R49 - Class D Control 1 */
{ 51, 0x0003 }, /* R51 - Class D Control 2 */
{ 56, 0x0506 }, /* R56 - Clocking 4 */
......@@ -168,8 +164,6 @@ static struct reg_default wm8962_reg[] = {
{ 64, 0x0810 }, /* R64 - DC Servo 4 */
{ 66, 0x0000 }, /* R66 - DC Servo 6 */
{ 68, 0x001B }, /* R68 - Analogue PGA Bias */
{ 69, 0x0000 }, /* R69 - Analogue HP 0 */
......@@ -302,9 +296,6 @@ static struct reg_default wm8962_reg[] = {
{ 516, 0x8100 }, /* R516 - GPIO 5 */
{ 517, 0x8100 }, /* R517 - GPIO 6 */
{ 560, 0x0000 }, /* R560 - Interrupt Status 1 */
{ 561, 0x0000 }, /* R561 - Interrupt Status 2 */
{ 568, 0x0030 }, /* R568 - Interrupt Status 1 Mask */
{ 569, 0xFFED }, /* R569 - Interrupt Status 2 Mask */
......@@ -316,8 +307,6 @@ static struct reg_default wm8962_reg[] = {
{ 768, 0x1C00 }, /* R768 - DSP2 Power Management */
{ 1037, 0x0000 }, /* R1037 - DSP2_ExecControl */
{ 8192, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */
{ 9216, 0x0030 }, /* R9216 - DSP2 Address RAM 2 */
......@@ -3673,7 +3662,6 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
ret);
}
pm_runtime_set_active(&i2c->dev);
pm_runtime_enable(&i2c->dev);
pm_request_idle(&i2c->dev);
......
......@@ -685,8 +685,6 @@ SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 old = snd_soc_read(codec, WM8994_ANTIPOP_2)
& WM1811_JACKDET_MODE_MASK;
if (!wm8994->jackdet || !wm8994->jack_cb)
return;
......@@ -694,28 +692,17 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
if (wm8994->active_refcount)
mode = WM1811_JACKDET_MODE_AUDIO;
if (mode == old)
if (mode == wm8994->jackdet_mode)
return;
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM1811_JACKDET_MODE_MASK, mode);
switch (mode) {
case WM1811_JACKDET_MODE_MIC:
case WM1811_JACKDET_MODE_AUDIO:
switch (old) {
case WM1811_JACKDET_MODE_MIC:
case WM1811_JACKDET_MODE_AUDIO:
break;
default:
msleep(2);
break;
}
wm8994->jackdet_mode = mode;
default:
break;
}
/* Always use audio mode to detect while the system is active */
if (mode != WM1811_JACKDET_MODE_NONE)
mode = WM1811_JACKDET_MODE_AUDIO;
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM1811_JACKDET_MODE_MASK, mode);
}
static void active_reference(struct snd_soc_codec *codec)
......@@ -2749,7 +2736,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
};
#ifdef CONFIG_PM
static int wm8994_suspend(struct snd_soc_codec *codec)
static int wm8994_codec_suspend(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
......@@ -2783,7 +2770,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec)
return 0;
}
static int wm8994_resume(struct snd_soc_codec *codec)
static int wm8994_codec_resume(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
......@@ -2842,8 +2829,8 @@ static int wm8994_resume(struct snd_soc_codec *codec)
return 0;
}
#else
#define wm8994_suspend NULL
#define wm8994_resume NULL
#define wm8994_codec_suspend NULL
#define wm8994_codec_resume NULL
#endif
static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
......@@ -3955,8 +3942,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.probe = wm8994_codec_probe,
.remove = wm8994_codec_remove,
.suspend = wm8994_suspend,
.resume = wm8994_resume,
.suspend = wm8994_codec_suspend,
.resume = wm8994_codec_resume,
.set_bias_level = wm8994_set_bias_level,
};
......@@ -3983,11 +3970,43 @@ static int __devexit wm8994_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int wm8994_suspend(struct device *dev)
{
struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
/* Drop down to power saving mode when system is suspended */
if (wm8994->jackdet && !wm8994->active_refcount)
regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
WM1811_JACKDET_MODE_MASK,
wm8994->jackdet_mode);
return 0;
}
static int wm8994_resume(struct device *dev)
{
struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
if (wm8994->jackdet && wm8994->jack_cb)
regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
WM1811_JACKDET_MODE_MASK,
WM1811_JACKDET_MODE_AUDIO);
return 0;
}
#endif
static const struct dev_pm_ops wm8994_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume)
};
static struct platform_driver wm8994_codec_driver = {
.driver = {
.name = "wm8994-codec",
.owner = THIS_MODULE,
},
.name = "wm8994-codec",
.owner = THIS_MODULE,
.pm = &wm8994_pm_ops,
},
.probe = wm8994_probe,
.remove = __devexit_p(wm8994_remove),
};
......
......@@ -122,6 +122,7 @@ struct wm8994_priv {
bool jack_mic;
int btn_mask;
bool jackdet;
int jackdet_mode;
wm8958_micdet_cb jack_cb;
void *jack_cb_data;
......
......@@ -8,19 +8,32 @@ menuconfig SND_IMX_SOC
if SND_IMX_SOC
config SND_SOC_IMX_SSI
tristate
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
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.
......@@ -30,6 +43,8 @@ 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
select SND_SOC_IMX_SSI
help
Say Y if you want to add support for SoC audio on Visstrim SM10
board with TLV320AIC32X4 codec.
......@@ -40,6 +55,8 @@ config SND_SOC_PHYCORE_AC97
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
......@@ -53,6 +70,8 @@ config SND_SOC_EUKREA_TLV320
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
......
# 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-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_MXC_SOC_FIQ) += snd-soc-imx-fiq.o
obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.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
......
......@@ -26,6 +26,7 @@
#include "../codecs/tlv320aic23.h"
#include "imx-ssi.h"
#include "imx-audmux.h"
#define CODEC_CLOCK 12000000
......@@ -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()) {
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)
);
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;
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)
);
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 */
return 0;
}
eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1);
if (!eukrea_tlv320_snd_device)
......
/*
* 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,20 +17,25 @@
* 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/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <mach/audmux.h>
#include <mach/hardware.h>
#include "imx-audmux.h"
#define DRIVER_NAME "imx-audmux"
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;
......@@ -75,8 +82,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);
......@@ -84,7 +91,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));
......@@ -92,7 +99,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));
......@@ -102,11 +109,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));
......@@ -114,7 +121,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));
......@@ -140,7 +147,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,61 +166,149 @@ 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
int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
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 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 const uint8_t port_mapping[] = {
0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
};
int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
{
if (audmux_type != IMX21_AUDMUX)
return -EINVAL;
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(imx_audmux_v1_configure_port);
int imx_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;
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 mxc_audmux_v2_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);
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);
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;
}
audmux_debugfs_init();
if (of_id)
pdev->id_entry = of_id->data;
audmux_type = pdev->id_entry->driver_data;
if (audmux_type == IMX31_AUDMUX)
audmux_debugfs_init();
return 0;
}
static int __exit imx_audmux_remove(struct platform_device *pdev)
{
if (audmux_type == IMX31_AUDMUX)
audmux_debugfs_remove();
clk_put(audmux_clk);
return 0;
}
postcore_initcall(mxc_audmux_v2_init);
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,
.of_match_table = imx_audmux_dt_ids,
}
};
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);
#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
......@@ -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 /* __MACH_AUDMUX_H */
#endif /* __IMX_AUDMUX_H */
......@@ -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)
{
......
/*
* 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);
/*
* 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 */
......@@ -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);
......
......@@ -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 */
......@@ -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
......@@ -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,
......
......@@ -19,6 +19,8 @@
#include <sound/soc.h>
#include <asm/mach-types.h>
#include "imx-audmux.h"
static struct snd_soc_card imx_phycore;
static struct snd_soc_ops imx_phycore_hifi_ops = {
......@@ -50,9 +52,32 @@ static int __init imx_phycore_init(void)
{
int ret;
if (!machine_is_pcm043() && !machine_is_pca100())
if (machine_is_pca100()) {
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()) {
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;
}
imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1);
if (!imx_phycore_snd_ac97_device)
......
......@@ -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.
......@@ -268,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)
......
......@@ -1569,8 +1569,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
out = is_connected_output_ep(w);
dapm_clear_walk(w->dapm);
ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d",
w->name, w->power ? "On" : "Off", in, out);
ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
w->name, w->power ? "On" : "Off",
w->force ? " (forced)" : "", in, out);
if (w->reg >= 0)
ret += snprintf(buf + ret, PAGE_SIZE - ret,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment