summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorWilliam Lai <b04597@freescale.com>2010-06-30 19:37:15 +0800
committerWilliam Lai <b04597@freescale.com>2010-07-08 16:23:24 +0800
commite01220ea65dadfbb7acac0cbd39dd4628cf853bb (patch)
treeac599b9bf0d8291ae6b57ef8f58958280cd953e0 /arch/arm
parent54cadaff22243f39f99e4be37726ef7ae267ead3 (diff)
ENGR00124740-3 MX53 : Multi-channel audio support
CS4288 is built in as default for MX53, but with a command parameter of apc in the commandline to enable. Signed-off-by: William Lai <b04597@freescale.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/configs/imx5_defconfig5
-rw-r--r--arch/arm/mach-mx5/clock.c103
-rw-r--r--arch/arm/mach-mx5/devices.c22
-rw-r--r--arch/arm/mach-mx5/devices.h1
-rw-r--r--arch/arm/mach-mx5/mx53_evk.c37
-rw-r--r--arch/arm/mach-mx5/mx53_evk_gpio.c118
6 files changed, 259 insertions, 27 deletions
diff --git a/arch/arm/configs/imx5_defconfig b/arch/arm/configs/imx5_defconfig
index da699bd1f04e..5b8f801cb189 100644
--- a/arch/arm/configs/imx5_defconfig
+++ b/arch/arm/configs/imx5_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.31
-# Sat Jun 26 00:18:13 2010
+# Wed Jun 30 16:57:27 2010
#
CONFIG_ARM=y
CONFIG_HAVE_PWM=y
@@ -1408,14 +1408,17 @@ CONFIG_SND_USB=y
CONFIG_SND_SOC=y
CONFIG_SND_MXC_SOC=y
CONFIG_SND_MXC_SOC_SSI=y
+CONFIG_SND_MXC_SOC_ESAI=y
CONFIG_SND_MXC_SOC_IRAM=y
CONFIG_SND_SOC_IMX_3STACK_SGTL5000=y
# CONFIG_SND_SOC_IMX_3STACK_AK4647 is not set
# CONFIG_SND_SOC_IMX_3STACK_WM8580 is not set
# CONFIG_SND_SOC_IMX_3STACK_AK5702 is not set
# CONFIG_SND_SOC_IMX_3STACK_BLUETOOTH is not set
+CONFIG_SND_SOC_IMX_3STACK_CS42888=y
CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_CS42888=y
CONFIG_SND_SOC_SGTL5000=y
# CONFIG_SOUND_PRIME is not set
CONFIG_HID_SUPPORT=y
diff --git a/arch/arm/mach-mx5/clock.c b/arch/arm/mach-mx5/clock.c
index c50151696706..04f120832cc1 100644
--- a/arch/arm/mach-mx5/clock.c
+++ b/arch/arm/mach-mx5/clock.c
@@ -2245,28 +2245,6 @@ static struct clk uart5_clk[] = {
},
};
-static struct clk esai_clk[] = {
- {
- .name = "esai_clk",
- .id = 2,
- .parent = &pll3_sw_clk,
- .secondary = &esai_clk[1],
- .enable_reg = MXC_CCM_CCGR6,
- .enable_shift = MXC_CCM_CCGR6_CG9_OFFSET,
- .enable = _clk_enable,
- .disable = _clk_disable,
- },
- {
- .name = "esai_ipg_clk",
- .id = 2,
- .parent = &pll3_sw_clk,
- .enable_reg = MXC_CCM_CCGR6,
- .enable_shift = MXC_CCM_CCGR6_CG8_OFFSET,
- .enable = _clk_enable,
- .disable = _clk_disable,
- },
-};
-
static struct clk gpt_clk[] = {
{
.name = "gpt_clk",
@@ -2789,6 +2767,83 @@ static struct clk ssi_ext2_clk = {
.disable = _clk_disable,
};
+static int _clk_esai_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ if (parent == &pll1_sw_clk || parent == &pll2_sw_clk ||
+ parent == &pll3_sw_clk) {
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ NULL);
+ reg &= ~MXC_CCM_CSCMR2_ESAI_PRE_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR2_ESAI_PRE_SEL_OFFSET;
+ reg &= ~MXC_CCM_CSCMR2_ESAI_POST_SEL_MASK;
+ reg |= 0 << MXC_CCM_CSCMR2_ESAI_POST_SEL_OFFSET;
+ /* divider setting */
+ } else {
+ mux = _get_mux(parent, &ssi1_clk[0], &ssi2_clk[0], &ckih_clk,
+ &ckih2_clk);
+ reg &= ~MXC_CCM_CSCMR2_ESAI_POST_SEL_MASK;
+ reg |= (mux + 1) << MXC_CCM_CSCMR2_ESAI_POST_SEL_OFFSET;
+ /* divider setting */
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ /* set podf = 0 */
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK;
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+static void _clk_esai_recalc(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ if (clk->parent == &pll1_sw_clk || clk->parent == &pll2_sw_clk ||
+ clk->parent == &pll3_sw_clk) {
+ pred = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+ clk->rate = clk->parent->rate / (pred * podf);
+ } else {
+ podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+ clk->rate = clk->parent->rate / podf;
+ }
+}
+
+static struct clk esai_clk[] = {
+ {
+ .name = "esai_clk",
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_esai_set_parent,
+ .recalc = _clk_esai_recalc,
+ .secondary = &esai_clk[1],
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGR6_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .name = "esai_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGR6_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
static struct clk iim_clk = {
.name = "iim_clk",
.parent = &ipg_clk,
@@ -4732,6 +4787,10 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
clk_register(&can2_clk[0]);
clk_register(&ldb_di_clk[0]);
clk_register(&ldb_di_clk[1]);
+ /* OSC of 22.5792M or 24.576M for ESAI */
+ clk_register(&esai_clk[0]);
+ clk_set_parent(&esai_clk[0], &ckih_clk);
+ clk_register(&esai_clk[1]);
ldb_di_clk[0].parent = ldb_di_clk[1].parent =
tve_clk.parent = &pll4_sw_clk;
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 4a77e0e245ac..6fceacc9f3a5 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -578,6 +578,26 @@ struct platform_device mxc_ssi2_device = {
.resource = ssi2_resources,
};
+static struct resource esai_resources[] = {
+ {
+ .start = ESAI_BASE_ADDR,
+ .end = ESAI_BASE_ADDR + 0x100,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_ESAI,
+ .end = MXC_INT_ESAI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_esai_device = {
+ .name = "mxc_esai",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(esai_resources),
+ .resource = esai_resources,
+};
+
static struct resource tve_resources[] = {
{
.start = TVE_BASE_ADDR,
@@ -1428,6 +1448,8 @@ int __init mxc_init_devices(void)
ssi1_resources[0].end -= MX53_OFFSET;
ssi2_resources[0].start -= MX53_OFFSET;
ssi2_resources[0].end -= MX53_OFFSET;
+ esai_resources[0].start -= MX53_OFFSET;
+ esai_resources[0].end -= MX53_OFFSET;
tve_resources[0].start -= MX53_OFFSET;
tve_resources[0].end -= MX53_OFFSET;
dvfs_core_resources[0].start -= MX53_OFFSET;
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
index 6272a42878cb..0b897f68328e 100644
--- a/arch/arm/mach-mx5/devices.h
+++ b/arch/arm/mach-mx5/devices.h
@@ -44,6 +44,7 @@ extern struct platform_device mxc_dvfs_core_device;
extern struct platform_device mxc_dvfs_per_device;
extern struct platform_device mxc_ssi1_device;
extern struct platform_device mxc_ssi2_device;
+extern struct platform_device mxc_esai_device;
extern struct platform_device mxc_alsa_spdif_device;
extern struct platform_device mx51_lpmode_device;
extern struct platform_device mx53_lpmode_device;
diff --git a/arch/arm/mach-mx5/mx53_evk.c b/arch/arm/mach-mx5/mx53_evk.c
index 2de3ad0b37e4..f13420926121 100644
--- a/arch/arm/mach-mx5/mx53_evk.c
+++ b/arch/arm/mach-mx5/mx53_evk.c
@@ -309,6 +309,10 @@ static struct ldb_platform_data ldb_data = {
.ext_ref = 1,
};
+static struct mxc_esai_platform_data esai_data = {
+ .activate_esai_ports = gpio_activate_esai_ports,
+};
+
static void adv7180_pwdn(int pwdn)
{
gpio_request(IOMUX_TO_GPIO(MX53_PIN_CSI0_D5), "gpio5_23");
@@ -410,6 +414,10 @@ static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
.addr = 0x21,
.platform_data = (void *)&adv7180_data,
},
+ {
+ .type = "cs42888",
+ .addr = 0x48,
+ },
};
/* TO DO add platform data */
@@ -810,6 +818,26 @@ static struct mxc_spdif_platform_data mxc_spdif_data = {
.spdif_clk = NULL, /* spdif bus clk */
};
+static struct mxc_audio_platform_data mxc_surround_audio_data = {
+ .ext_ram = 1,
+};
+
+
+static struct platform_device mxc_alsa_surround_device = {
+ .name = "imx-3stack-cs42888",
+};
+
+static int __initdata mxc_apc_on = { 0 }; /* OFF: 0 (default), ON: 1 */
+
+static int __init apc_setup(char *__unused)
+{
+ mxc_apc_on = 1;
+ printk(KERN_INFO "Automotive Port Card is Plugged on\n");
+ return 1;
+}
+__setup("apc", apc_setup);
+
+
/*!
* Board specific fixup function. It is called by \b setup_arch() in
* setup.c file very early on during kernel starts. It allows the user to
@@ -966,8 +994,8 @@ static void __init mxc_board_init(void)
mxc_register_device(&mxc_ssi2_device, NULL);
mxc_register_device(&ahci_fsl_device, &sata_data);
mxc_register_device(&mxc_alsa_spdif_device, &mxc_spdif_data);
-
- mxc_register_device(&mxc_fec_device, &fec_data);
+ if (!mxc_apc_on)
+ mxc_register_device(&mxc_fec_device, &fec_data);
spi_register_board_info(mxc_dataflash_device,
ARRAY_SIZE(mxc_dataflash_device));
i2c_register_board_info(0, mxc_i2c0_board_info,
@@ -984,6 +1012,11 @@ static void __init mxc_board_init(void)
mx5_usb_dr_init();
mx5_usbh1_init();
mxc_register_device(&mxc_nandv2_mtd_device, &mxc_nand_data);
+ if (mxc_apc_on) {
+ mxc_register_device(&mxc_esai_device, &esai_data);
+ mxc_register_device(&mxc_alsa_surround_device,
+ &mxc_surround_audio_data);
+ }
}
static void __init mx53_evk_timer_init(void)
diff --git a/arch/arm/mach-mx5/mx53_evk_gpio.c b/arch/arm/mach-mx5/mx53_evk_gpio.c
index 25120d926bd0..56e7d65924cb 100644
--- a/arch/arm/mach-mx5/mx53_evk_gpio.c
+++ b/arch/arm/mach-mx5/mx53_evk_gpio.c
@@ -272,8 +272,11 @@ static struct mxc_iomux_pin_cfg __initdata mxc_iomux_pins[] = {
{
MX53_PIN_GPIO_11, IOMUX_CONFIG_GPIO,
},
- {
- MX53_PIN_GPIO_12, IOMUX_CONFIG_GPIO,
+ { /* ESAI reset */
+ MX53_PIN_GPIO_12, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_HIGH | PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE |
+ PAD_CTL_PUE_PULL | PAD_CTL_100K_PU | PAD_CTL_ODE_OPENDRAIN_ENABLE |
+ PAD_CTL_SRE_FAST),
},
{
MX53_PIN_GPIO_13, IOMUX_CONFIG_GPIO,
@@ -905,6 +908,10 @@ void __init mx53_evk_io_init(void)
msleep(1);
gpio_set_value(IOMUX_TO_GPIO(MX53_PIN_ATA_DA_0), 1);
+ /* CS42888 reset GPIO */
+ gpio_direction_output(IOMUX_TO_GPIO(MX53_PIN_GPIO_12), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX53_PIN_GPIO_12), 0);
+
}
/* DVI Detect */
@@ -1115,3 +1122,110 @@ void gpio_lcd_active(void)
/* TO DO */
}
EXPORT_SYMBOL(gpio_lcd_active);
+
+void gpio_activate_esai_ports(void)
+{
+ unsigned int pad_val;
+
+ /* ESAI1-HCKR */
+ mxc_request_iomux(MX53_PIN_FEC_RX_ER, IOMUX_CONFIG_ALT2);
+ /* ESAI1-SCKR */
+ mxc_request_iomux(MX53_PIN_FEC_MDIO, IOMUX_CONFIG_ALT2);
+ /* ESAI1-FSR */
+ mxc_request_iomux(MX53_PIN_FEC_REF_CLK, IOMUX_CONFIG_ALT2);
+ /* ESAI1-HCKT */
+ mxc_request_iomux(MX53_PIN_FEC_RXD0, IOMUX_CONFIG_ALT2);
+ /* ESAI1-SCKT */
+ mxc_request_iomux(MX53_PIN_FEC_CRS_DV, IOMUX_CONFIG_ALT2);
+ /* ESAI1-FST */
+ mxc_request_iomux(MX53_PIN_FEC_RXD1, IOMUX_CONFIG_ALT2);
+ /* ESAI1-TX5-RX0 */
+ mxc_request_iomux(MX53_PIN_FEC_MDC, IOMUX_CONFIG_ALT2);
+ /* ESAI1-TX4-RX1 */
+ mxc_request_iomux(MX53_PIN_FEC_TXD0, IOMUX_CONFIG_ALT2);
+ /* ESAI1-TX3-RX2 */
+ mxc_request_iomux(MX53_PIN_FEC_TX_EN, IOMUX_CONFIG_ALT2);
+ /* ESAI1-TX2-RX3 */
+ mxc_request_iomux(MX53_PIN_FEC_TXD1, IOMUX_CONFIG_ALT2);
+ /* ESAI1-TX1 */
+ mxc_request_iomux(MX53_PIN_NANDF_CS3, IOMUX_CONFIG_ALT3);
+ /* ESAI1-TX0 */
+ mxc_request_iomux(MX53_PIN_NANDF_CS2, IOMUX_CONFIG_ALT3);
+
+ pad_val = PAD_CTL_DRV_HIGH | PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL |
+ PAD_CTL_100K_PU | PAD_CTL_ODE_OPENDRAIN_NONE;
+
+ /* ESAI1-HCKR */
+ mxc_iomux_set_pad(MX53_PIN_FEC_RX_ER, pad_val);
+ /* ESAI1-SCKR */
+ mxc_iomux_set_pad(MX53_PIN_FEC_MDIO, pad_val);
+ /* ESAI1-FSR */
+ mxc_iomux_set_pad(MX53_PIN_FEC_REF_CLK, pad_val);
+ /* ESAI1-HCKT */
+ mxc_iomux_set_pad(MX53_PIN_FEC_RXD0, pad_val);
+ /* ESAI1-SCKT */
+ mxc_iomux_set_pad(MX53_PIN_FEC_CRS_DV, pad_val);
+ /* ESAI1-FST */
+ mxc_iomux_set_pad(MX53_PIN_FEC_RXD1, pad_val);
+ /* ESAI1-TX5-RX0 */
+ mxc_iomux_set_pad(MX53_PIN_FEC_MDC, pad_val);
+ /* ESAI1-TX4-RX1 */
+ mxc_iomux_set_pad(MX53_PIN_FEC_TXD0, pad_val);
+ /* ESAI1-TX3-RX2 */
+ mxc_iomux_set_pad(MX53_PIN_FEC_TX_EN, pad_val);
+ /* ESAI1-TX2-RX3 */
+ mxc_iomux_set_pad(MX53_PIN_FEC_TXD1, pad_val);
+ /* ESAI1-TX1 */
+ mxc_iomux_set_pad(MX53_PIN_NANDF_CS3, pad_val);
+ /* ESAI1-TX0 */
+ mxc_iomux_set_pad(MX53_PIN_NANDF_CS2, pad_val);
+
+ /* ESAI1-HCKR */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_HCKR_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-SCKR */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_SCKR_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-FSR */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_FSR_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-HCKT */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_HCKT_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-SCKT */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_SCKT_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-FST */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_FST_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-TX5-RX0 */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_SDO5_SDI0_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-TX4-RX1 */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_SDO4_SDI1_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-TX3-RX2 */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_SDO3_SDI2_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-TX2-RX3 */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_SDO2_SDI3_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-TX1 */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_SDO1_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+ /* ESAI1-TX0 */
+ mxc_iomux_set_input(MUX_IN_ESAI1_IPP_IND_SDO0_SELECT_INPUT,
+ INPUT_CTL_PATH0);
+
+}
+EXPORT_SYMBOL(gpio_activate_esai_ports);
+
+void gpio_cs42888_pdwn(int pdwn)
+{
+ if (pdwn)
+ gpio_set_value(IOMUX_TO_GPIO(MX53_PIN_GPIO_12), 0);
+ else
+ gpio_set_value(IOMUX_TO_GPIO(MX53_PIN_GPIO_12), 1);
+}
+EXPORT_SYMBOL(gpio_cs42888_pdwn);