summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Waters <justin.waters@timesys.com>2013-03-29 13:08:55 -0400
committerJustin Waters <justin.waters@timesys.com>2013-03-29 13:08:55 -0400
commit21ceb093d796e94500502eee94a8cd5fcc76f619 (patch)
tree8f3255c05b10b382a361e1eca47794b3485c2572
parentf962cbcefdfad22ffff41e19ad4c5ff58815c05c (diff)
parentfcbe1245c34fa407ff20d6afd2f975e8f961a17b (diff)
Merge branch '3.0-pcm052' of ssh://github.com/tsfs/Vybrid-Linux into 3.0-pcm0523.0-pcm052-ts2.1
-rw-r--r--.gitignore1
-rw-r--r--arch/arm/configs/pcm052_defconfig10
-rw-r--r--arch/arm/mach-mvf/Makefile2
-rw-r--r--arch/arm/mach-mvf/board-pcm052.c32
-rw-r--r--arch/arm/mach-mvf/clock.c34
-rw-r--r--arch/arm/mach-mvf/crm_regs.h16
-rw-r--r--arch/arm/mach-mvf/mvf_sema4.c234
-rwxr-xr-xarch/arm/plat-mxc/Makefile4
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mvf.h6
-rw-r--r--arch/arm/plat-mxc/include/mach/mvf.h1
-rw-r--r--arch/arm/plat-mxc/pit.c6
-rw-r--r--drivers/i2c/busses/i2c-imx.c34
-rw-r--r--include/linux/mvf_sema4.h15
-rw-r--r--sound/soc/codecs/sgtl5000.h2
-rw-r--r--sound/soc/mvf/Kconfig12
-rw-r--r--sound/soc/mvf/Makefile2
-rw-r--r--sound/soc/mvf/mvf-sai.h4
-rw-r--r--sound/soc/mvf/pcm052-sgtl5000.c320
18 files changed, 693 insertions, 42 deletions
diff --git a/.gitignore b/.gitignore
index 9dacde0a4b2d..13f15ddf6dbf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
# Normal rules
#
.*
+!.config
*.o
*.o.*
*.a
diff --git a/arch/arm/configs/pcm052_defconfig b/arch/arm/configs/pcm052_defconfig
index bd13e16e0cea..dfe3c7ceac20 100644
--- a/arch/arm/configs/pcm052_defconfig
+++ b/arch/arm/configs/pcm052_defconfig
@@ -249,7 +249,9 @@ CONFIG_IMX_HAVE_PLATFORM_FLEXCAN=y
CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC=y
CONFIG_IMX_HAVE_PLATFORM_GPMI_NFC=y
CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT=y
+CONFIG_IMX_HAVE_PLATFORM_MVF_ADC=y
CONFIG_IMX_HAVE_PLATFORM_IMX_SNVS_RTC=y
+CONFIG_IMX_HAVE_PLATFORM_MVF_CAAM=y
CONFIG_IMX_HAVE_PLATFORM_IMX_I2C=y
CONFIG_IMX_HAVE_PLATFORM_IMX_SSI=y
CONFIG_IMX_HAVE_PLATFORM_IMX_UART=y
@@ -676,6 +678,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_DS1682 is not set
# CONFIG_TI_DAC7512 is not set
# CONFIG_BMP085 is not set
+# CONFIG_MVF_ADC is not set
# CONFIG_C2PORT is not set
#
@@ -1219,7 +1222,6 @@ CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_LOGO_TS_CLUT224=y
CONFIG_SOUND=y
CONFIG_SOUND_OSS_CORE=y
# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set
@@ -1261,7 +1263,8 @@ CONFIG_SND_SOC=y
# CONFIG_SND_IMX_SOC is not set
CONFIG_SND_MVF_SOC=y
CONFIG_SND_MVF_SOC_TWR=y
-CONFIG_SND_SOC_MVF_SGTL5000=y
+# CONFIG_SND_SOC_MVF_SGTL5000 is not set
+CONFIG_SND_SOC_PCM052_SGTL5000=y
CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
CONFIG_SND_SOC_SGTL5000=y
@@ -1591,6 +1594,7 @@ CONFIG_CLKSRC_MMIO=y
#
# MXC Asynchronous Sample Rate Converter support
#
+# CONFIG_MXC_ASRC is not set
#
# MXC Bluetooth support
@@ -1966,6 +1970,8 @@ CONFIG_CRYPTO_LZO=y
# CONFIG_CRYPTO_USER_API_HASH is not set
# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_FSL_CAAM is not set
+# CONFIG_CRYPTO_DEV_FSL_CAAM_SM is not set
CONFIG_BINARY_PRINTF=y
#
diff --git a/arch/arm/mach-mvf/Makefile b/arch/arm/mach-mvf/Makefile
index fad70a4a9dc7..3128d4288c3d 100644
--- a/arch/arm/mach-mvf/Makefile
+++ b/arch/arm/mach-mvf/Makefile
@@ -3,7 +3,7 @@
#
# Object file lists.
-obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o mvf_fec.o usb_dr.o usb_dr2.o pm.o
+obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o mvf_fec.o usb_dr.o usb_dr2.o pm.o mvf_sema4.o
obj-y += l2switch.o
obj-$(CONFIG_ARCH_MVFA5) += clock.o mvf_suspend.o
diff --git a/arch/arm/mach-mvf/board-pcm052.c b/arch/arm/mach-mvf/board-pcm052.c
index 84bd65623ebb..8048349afae7 100644
--- a/arch/arm/mach-mvf/board-pcm052.c
+++ b/arch/arm/mach-mvf/board-pcm052.c
@@ -147,14 +147,14 @@ static iomux_v3_cfg_t pcm052_pads[] = {
#endif
/*SAI2*/
-// MVF600_PAD6_PTA16_SAI2_TX_BCLK,
+ MVF600_PAD6_PTA16_SAI2_TX_BCLK,
MVF600_PAD8_PTA18_SAI2_TX_DATA,
-// MVF600_PAD3_PTA10_SAI2_TX_SYNC, // originally PAD9_PTA19
- MVF600_PAD11_PTA21_SAI2_RX_BCLK,
-// MVF600_PAD23_PTB1_SAI2_RX_DATA, // originally PAD12_PTA22
-// MVF600_PAD13_PTA23_SAI2_RX_SYNC, // UNUSED
+ MVF600_PAD9_PTA19_SAI2_TX_SYNC,
+// MVF600_PAD11_PTA21_SAI2_RX_BCLK,
+ MVF600_PAD23_PTB1_SAI2_RX_DATA, // originally PAD12_PTA22
+// MVF600_PAD24_PTB2_SAI2_RX_SYNC, // originally PAD13_PTA23
// MVF600_PAD40_PTB18_EXT_AUDIO_MCLK, // UNUSED
-// MVF600_PAD33_PTB11__CKO2, // phyCORE MCLK
+ MVF600_PAD33_PTB11__CKO2, // phyCORE MCLK
/*DCU0*/
MVF600_PAD25_PTB3_LCD_ENABLE,
@@ -204,15 +204,15 @@ static iomux_v3_cfg_t pcm052_pads[] = {
* FTM0 CH0~3 are connected to demo LED0~3
* PAD30 mux with LCD enable signal
*/
- MVF600_PAD22_PTB0_FTM0CH0,
- MVF600_PAD23_PTB1_FTM0CH1,
- MVF600_PAD24_PTB2_FTM0CH2,
+// MVF600_PAD22_PTB0_FTM0CH0,
+// MVF600_PAD23_PTB1_FTM0CH1,
+// MVF600_PAD24_PTB2_FTM0CH2,
// MVF600_PAD25_PTB3_FTM0CH3,
- MVF600_PAD28_PTB6_FTM0CH6,
- MVF600_PAD29_PTB7_FTM0CH7,
+// MVF600_PAD28_PTB6_FTM0CH6,
+// MVF600_PAD29_PTB7_FTM0CH7,
/*MVF600_PAD30_PTB8_FTM1CH0,*/
- MVF600_PAD31_PTB9_FTM1CH1,
+// MVF600_PAD31_PTB9_FTM1CH1,
/* Touch Screen */
MVF600_PAD32_PTB10_TS_IRQ,
@@ -236,7 +236,7 @@ static struct mxc_audio_platform_data pcm052_audio_data;
static int pcm052_sgtl5000_init(void)
{
- pcm052_audio_data.sysclk = 24576000;
+ pcm052_audio_data.sysclk = 12288000;
return 0;
}
@@ -252,7 +252,7 @@ static struct mxc_audio_platform_data pcm052_audio_data = {
};
static struct platform_device pcm052_audio_device = {
- .name = "mvf-sgtl5000",
+ .name = "pcm052-sgtl5000",
};
static struct imxuart_platform_data mvf_uart1_pdata = {
@@ -523,8 +523,8 @@ static void __init pcm052_board_init(void)
mvfa5_add_dcu(0, &mvf_dcu_pdata);
-// mxc_register_device(&pcm052_audio_device, &pcm052_audio_data);
-// mvfa5_add_sai(2, &mvf_sai_pdata);
+ mxc_register_device(&pcm052_audio_device, &pcm052_audio_data);
+ mvfa5_add_sai(2, &mvf_sai_pdata);
// mvf_add_wdt(0);
diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c
index 74ce8a9f290e..199483ccb32a 100644
--- a/arch/arm/mach-mvf/clock.c
+++ b/arch/arm/mach-mvf/clock.c
@@ -1389,7 +1389,7 @@ static struct clk dcu0_clk = {
static unsigned long get_audio_external_clock_rate(struct clk *clk)
{
- return 24576000;
+ return 24567000;
}
static struct clk audio_external_clk = {
@@ -1405,11 +1405,10 @@ static int _clk_sai2_set_parent(struct clk *clk, struct clk *parent)
mux = _get_mux6(parent, &audio_external_clk, NULL,
NULL, &pll4_audio_main_clk, NULL, NULL);
-
+
reg |= (mux << MXC_CCM_CSCMR1_SAI2_CLK_SEL_OFFSET);
-
__raw_writel(reg, MXC_CCM_CSCMR1);
-
+
return 0;
}
@@ -1448,10 +1447,18 @@ static int _clk_sai2_enable(struct clk *clk)
{
u32 reg;
+ /* enable SAI2 clock */
reg = __raw_readl(MXC_CCM_CSCDR1);
- reg |= MXC_CCM_CSCDR1_SAI2_EN;
+ reg |= MXC_CCM_CSCDR1_SAI2_EN | (0xF << MXC_CCM_CSCDR1_SAI2_DIV_OFFSET);
__raw_writel(reg, MXC_CCM_CSCDR1);
+ /* enable CKO2 observation of SAI2 */
+ reg = __raw_readl(MXC_CCM_CCOSR)
+ & ~MXC_CCM_CCOSR_CKO2_SEL_MASK;
+ reg |= MXC_CCM_CCOSR_CKO2_EN | MXC_CCM_CCOSR_CKO2_SEL_SAI2 |
+ (2 << MXC_CCM_CCOSR_CKO2_DIV_OFFSET);
+ __raw_writel(reg, MXC_CCM_CCOSR);
+
return 0;
}
@@ -1459,10 +1466,16 @@ static void _clk_sai2_disable(struct clk *clk)
{
u32 reg;
+ /* disable SAI2 clock */
reg = __raw_readl(MXC_CCM_CSCDR1);
reg &= ~MXC_CCM_CSCDR1_SAI2_EN;
__raw_writel(reg, MXC_CCM_CSCDR1);
+ /* disable CKO2 observation of SAI2 */
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKO2_EN;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+
return 0;
}
@@ -1488,7 +1501,7 @@ static unsigned long _clk_sai_round_rate(struct clk *clk,
static struct clk sai2_clk = {
__INIT_CLK_DEBUG(sai2_clk)
- .parent = &audio_external_clk,
+ .parent = &pll4_audio_main_clk,
.enable_reg = MXC_CCM_CCGR1,
.enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
.enable = _clk_sai2_enable,
@@ -1926,7 +1939,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk), /* arm core clk */
_REGISTER_CLOCK(NULL, "periph_clk", periph_clk), /* platform bus clk */
_REGISTER_CLOCK(NULL, "ipg_clk", ipg_clk),
-// _REGISTER_CLOCK(NULL, "audio ext clk", audio_external_clk),
+ _REGISTER_CLOCK(NULL, "audio ext clk", audio_external_clk),
_REGISTER_CLOCK(NULL, "mvf-uart.0", uart_clk[0]),
_REGISTER_CLOCK(NULL, "mvf-uart.1", uart_clk[0]),
_REGISTER_CLOCK(NULL, "mvf-uart.2", uart_clk[0]),
@@ -1940,8 +1953,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk),
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc1_clk),
_REGISTER_CLOCK("mvf-dcu.0", NULL, dcu0_clk),
-// _REGISTER_CLOCK("mvf-sai.0", NULL, sai2_clk),
-// _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[2]),
+ _REGISTER_CLOCK("mvf-sai.0", NULL, sai2_clk),
_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2]),
_REGISTER_CLOCK(NULL, "usb-clk", usb_clk),
_REGISTER_CLOCK(NULL, "mvf-usb.0", usb_phy0_clk),
@@ -2018,8 +2030,8 @@ int __init mvf_clocks_init(unsigned long ckil, unsigned long osc,
clk_set_parent(&dcu0_clk, &pll1_pfd2_452M);
clk_set_rate(&dcu0_clk, 113000000);
- clk_set_parent(&sai2_clk, &audio_external_clk);
- clk_set_rate(&sai2_clk, 24576000);
+ clk_set_parent(&sai2_clk, &pll4_audio_main_clk);
+ clk_set_rate(&sai2_clk, 24567000);
clk_set_parent(&qspi0_clk, &pll1_pfd4_528M);
clk_set_rate(&qspi0_clk, 66000000);
diff --git a/arch/arm/mach-mvf/crm_regs.h b/arch/arm/mach-mvf/crm_regs.h
index 57fac5bbe973..4cfc7898aa87 100644
--- a/arch/arm/mach-mvf/crm_regs.h
+++ b/arch/arm/mach-mvf/crm_regs.h
@@ -185,6 +185,10 @@
#define MXC_CCM_BASE MVF_IO_ADDRESS(MVF_CCM_BASE_ADDR)
+#define MVF_I2S0_BASE MVF_IO_ADDRESS(MVF_I2S0_BASE_ADDR)
+#define MVF_I2S0_TCR2 (MVF_I2S0_BASE + 0xF008)
+#define MVF_I2S0_RCR2 (MVF_I2S0_BASE + 0xF088)
+
/* Register addresses of CCM*/
#define MXC_CCM_CCR (MXC_CCM_BASE + 0x00)
#define MXC_CCM_CSR (MXC_CCM_BASE + 0x04)
@@ -199,6 +203,7 @@
#define MXC_CCM_CLPCR (MXC_CCM_BASE + 0x2c)
#define MXC_CCM_CISR (MXC_CCM_BASE + 0x30)
#define MXC_CCM_CIMR (MXC_CCM_BASE + 0x34)
+#define MXC_CCM_CCOSR (MXC_CCM_BASE + 0x38)
#define MXC_CCM_CGPR (MXC_CCM_BASE + 0x3c)
#define MXC_CCM_CCGR0 (MXC_CCM_BASE + 0x40)
#define MXC_CCM_CCGR1 (MXC_CCM_BASE + 0x44)
@@ -435,6 +440,17 @@
#define MXC_CCM_CIMR_LRF_PLL2 (1 << 1)
#define MXC_CCM_CIMR_LRF_PLL1 (1)
+/* CCOSR */
+#define MXC_CCM_CCOSR_CKO2_EN (1 << 26)
+#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (22)
+
+#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x3F << 16)
+#define MXC_CCM_CCOSR_CKO2_SEL_SAI2 (0xD << 16)
+#define MXC_CCM_CCOSR_CKO2_SEL_PLL4_MAIN (0x1A << 16)
+
+#define MXC_CCM_CCOSR_CKO1_EN (1 << 10)
+#define MXC_CCM_CCOSR_CKO1_DIV_OFFSET (6)
+
/* Define the bits in registers CGPR */
#define MXC_CCM_CGPR_EFUSE_PROG (1 << 4)
#define MXC_CCM_CGPR_QSPI1_ACCZ (1 << 1)
diff --git a/arch/arm/mach-mvf/mvf_sema4.c b/arch/arm/mach-mvf/mvf_sema4.c
new file mode 100644
index 000000000000..311b56a69d73
--- /dev/null
+++ b/arch/arm/mach-mvf/mvf_sema4.c
@@ -0,0 +1,234 @@
+/*
+* header goes here
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+
+#include <mach/mvf.h>
+
+#define NUM_GATES 16
+#define MASK_FROM_GATE(gate_num) ((u32)(1 << (NUM_GATES*2 - 1 - idx[gate_num])))
+
+#define THIS_CORE (0)
+#define LOCK_VALUE (THIS_CORE + 1)
+
+#define SEMA4_CP0INE (MVF_SEMA4_BASE_ADDR + 0x40)
+#define SEMA4_CP0NTF (MVF_SEMA4_BASE_ADDR + 0x80)
+
+//#if 0
+#include <linux/mm.h>
+#include <linux/version.h>
+#include <linux/kdev_t.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <mach/hardware.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+//#endif
+
+#include <linux/mvf_sema4.h>
+
+// ************************************ Local Data *************************************************
+
+static MVF_SEMA4* gates[NUM_GATES];
+
+static bool initialized = false;
+
+// account for the way the bits are set / returned in CP0INE and CP0NTF
+static const int idx[16] = {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12};
+
+
+// ************************************ Interrupt handler *************************************************
+
+static irqreturn_t sema4_irq_handler(int irq, void *dev_id)
+{
+ int gate_num;
+
+ u32 cp0ntf = readl(MVF_IO_ADDRESS(SEMA4_CP0NTF));
+
+ for(gate_num=0; gate_num<NUM_GATES; gate_num++)
+ {
+ // interrupt from this gate?
+ if(cp0ntf & MASK_FROM_GATE(gate_num))
+ {
+ // grab the gate to stop the interrupts
+ writeb(LOCK_VALUE, MVF_IO_ADDRESS(MVF_SEMA4_BASE_ADDR) + gate_num);
+
+ // make sure there's a gate assigned
+ if(gates[gate_num])
+ {
+ if(gates[gate_num]->use_interrupts)
+ // wake up whoever was aiting
+ wake_up_interruptible(&(gates[gate_num]->wait_queue));
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+// ************************************ Utility functions *************************************************
+
+static int find_sema4(MVF_SEMA4 *sema4)
+{
+ int i;
+
+ for(i=0; i<NUM_GATES; i++)
+ {
+ if(gates[i] == sema4)
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static int initialize(void)
+{
+ int i;
+
+ // clear the gates table
+ for(i=0; i<NUM_GATES; i++)
+ gates[i] = NULL;
+
+ // clear out all notification requests
+ writel(0, MVF_IO_ADDRESS(SEMA4_CP0INE));
+
+ //Register the interrupt handler
+ if (request_irq(MVF_INT_SEMA4, sema4_irq_handler, 0, "mvf_sema4_handler", NULL) != 0)
+ {
+ printk(KERN_ERR "Failed to register MVF_INT_SEMA4 interrupt.\n");
+ return -EIO;
+ }
+
+ initialized = true;
+ return 0;
+}
+
+int mvf_sema4_assign(int gate_num, bool use_interrupts, MVF_SEMA4** sema4_p)
+{
+ int retval;
+ u32 cp0ine;
+ unsigned long irq_flags;
+
+ // take the opportunity to initialize the whole sub-system
+ if(!initialized)
+ {
+ retval = initialize();
+ if(retval)
+ return retval;
+ }
+
+ if((gate_num < 0) || (gate_num >= NUM_GATES))
+ return -EINVAL;
+
+ if(gates[gate_num])
+ return -EBUSY;
+
+ *sema4_p = (MVF_SEMA4 *)kmalloc(sizeof(MVF_SEMA4), GFP_KERNEL);
+ if(*sema4_p == NULL)
+ return -ENOMEM;
+
+ gates[gate_num] = *sema4_p;
+ (*sema4_p)->gate_num = gate_num;
+ (*sema4_p)->use_interrupts = use_interrupts;
+
+ if(use_interrupts)
+ {
+ init_waitqueue_head(&((*sema4_p)->wait_queue));
+ local_irq_save(irq_flags);
+ cp0ine = readl(MVF_IO_ADDRESS(SEMA4_CP0INE));
+ cp0ine |= MASK_FROM_GATE(gate_num);
+ writel(cp0ine, MVF_IO_ADDRESS(SEMA4_CP0INE));
+ local_irq_restore(irq_flags);
+ }
+
+ return 0;
+}
+
+int mvf_sema4_deassign(MVF_SEMA4 *sema4)
+{
+ u32 cp0ine;
+ unsigned long irq_flags;
+
+ int gate_num = find_sema4(sema4);
+ if(gate_num < 0)
+ return gate_num;
+
+ if(sema4->use_interrupts)
+ {
+ local_irq_save(irq_flags);
+ cp0ine = readl(MVF_IO_ADDRESS(SEMA4_CP0INE));
+ cp0ine &= ~MASK_FROM_GATE(gate_num);
+ writel(cp0ine, MVF_IO_ADDRESS(SEMA4_CP0INE));
+ local_irq_restore(irq_flags);
+ }
+
+ kfree(sema4);
+ gates[gate_num] = NULL;
+
+ return 0;
+}
+
+int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us)
+{
+ int retval;
+ int gate_num = find_sema4(sema4);
+ if(gate_num < 0)
+ return gate_num;
+
+ // cant use timeouts if not using interruppts
+ // TODO use spin lock if not using interrupts
+ if((!sema4->use_interrupts) && timeout_us)
+ return -EINVAL;
+
+ // try to grab it
+ writeb(LOCK_VALUE, MVF_IO_ADDRESS(MVF_SEMA4_BASE_ADDR) + gate_num);
+ if(readb(MVF_IO_ADDRESS(MVF_SEMA4_BASE_ADDR) + gate_num) == LOCK_VALUE)
+ return 0;
+
+ // no timeout, fail
+ if(!timeout_us)
+ return -EBUSY;
+
+ // wait forever?
+ if(timeout_us == 0xffffffff)
+ {
+ if(wait_event_interruptible(sema4->wait_queue, (readb(MVF_IO_ADDRESS(MVF_SEMA4_BASE_ADDR) + gate_num) == LOCK_VALUE)))
+ return -ERESTARTSYS;
+ }
+ else
+ {
+ // return: 0 = timeout, >0 = woke up with that many jiffies left, <0 = error
+ retval = wait_event_interruptible_timeout(sema4->wait_queue,
+ (readb(MVF_IO_ADDRESS(MVF_SEMA4_BASE_ADDR) + gate_num) == LOCK_VALUE),
+ usecs_to_jiffies(timeout_us));
+ if(retval == 0)
+ return -ETIME;
+ else if(retval < 0)
+ return retval;
+ }
+
+ return 0;
+}
+
+int mvf_sema4_unlock(MVF_SEMA4 *sema4)
+{
+ int gate_num = find_sema4(sema4);
+ if(gate_num < 0)
+ return gate_num;
+
+ // unlock it
+ writeb(0, MVF_IO_ADDRESS(MVF_SEMA4_BASE_ADDR) + gate_num);
+
+ return 0;
+}
+
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index e2abb624f9d1..238788df23da 100755
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,12 +3,14 @@
#
# Common support
-obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o usb_common.o usb_wakeup.o
+#obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o usb_common.o usb_wakeup.o
+obj-y := clock.o devices.o cpu.o system.o irq-common.o usb_common.o usb_wakeup.o
ifdef CONFIG_ARCH_MVF
obj-y += gpio-mvf.o
else
obj-y += gpio.o
+obj-y += time.o
endif
# MX51 uses the TZIC interrupt controller, older platforms use AVIC
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mvf.h b/arch/arm/plat-mxc/include/mach/iomux-mvf.h
index eb093e2c0f7f..bde7e316433a 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mvf.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mvf.h
@@ -258,9 +258,9 @@ typedef enum iomux_config {
#define MVF600_PAD40_PTB18_EXT_AUDIO_MCLK \
IOMUX_PAD(0x00A0, 0x00A0, 2, 0x02ec, 2, \
MVF600_SAI_PAD_CTRL | PAD_CTL_IBE_ENABLE)
-#define MVF600_PAD33_PTB11__CKO2 \
- IOMUX_PAD(0x0084, 0x0084, 6, 0x24038, 0x040D, \
- MVF600_SAI_PAD_CTRL | PAD_CTL_IBE_ENABLE)
+#define MVF600_PAD33_PTB11__CKO2 \
+ IOMUX_PAD(0x0084, 0x0084, 6, 0x0000, 0, \
+ MVF600_SAI_PAD_CTRL | PAD_CTL_OBE_ENABLE)
/*DCU0*/
#define MVF600_PAD25_PTB3_LCD_ENABLE \
diff --git a/arch/arm/plat-mxc/include/mach/mvf.h b/arch/arm/plat-mxc/include/mach/mvf.h
index 4a47636fa741..fb0e5eb69704 100644
--- a/arch/arm/plat-mxc/include/mach/mvf.h
+++ b/arch/arm/plat-mxc/include/mach/mvf.h
@@ -124,6 +124,7 @@
#define MVF_DMA0TCD_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00019000)
#define MVF_SEMA4_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0001D000)
#define MVF_FLEXBUS_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x0001E000)
+#define MVF_I2S0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00020000)
#define MVF_FLEXCAN0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00021000)
#define MVF_DMAMUX0_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00024000)
#define MVF_DMAMUX1_BASE_ADDR (MVF_AIPS0_BASE_ADDR + 0x00025000)
diff --git a/arch/arm/plat-mxc/pit.c b/arch/arm/plat-mxc/pit.c
index ba71bda51c06..e82cca9d06ea 100644
--- a/arch/arm/plat-mxc/pit.c
+++ b/arch/arm/plat-mxc/pit.c
@@ -90,6 +90,12 @@ static cycle_t pit_read_clk(struct clocksource *cs);
static DEFINE_CLOCK_DATA(cd);
static void __iomem *sched_clock_reg;
+unsigned long long notrace sched_clock(void)
+{
+ cycle_t cyc = sched_clock_reg ? ((u32)~0
+ - __raw_readl(sched_clock_reg)) : 0;
+ return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
static void notrace mvf_update_sched_clock(void)
{
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 71b8cd4f8a3e..853e0688998e 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -52,6 +52,7 @@
#include <mach/irqs.h>
#include <mach/hardware.h>
#include <mach/i2c.h>
+#include <linux/mvf_sema4.h>
/** Defines ********************************************************************
*******************************************************************************/
@@ -122,6 +123,8 @@ static u16 __initdata i2c_clk_div[60][2] = {
{ 2304, 0x3C }, { 2560, 0x3D }, { 3072, 0x3E }, { 3584, 0x7A },
{ 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E },
};
+
+static MVF_SEMA4* sema4 = NULL;
#else
static u16 __initdata i2c_clk_div[50][2] = {
{ 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 },
@@ -215,7 +218,7 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
- clk_enable(i2c_imx->clk);
+ //clk_enable(i2c_imx->clk);
writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR);
/* Enable I2C controller */
#ifdef CONFIG_ARCH_MVF
@@ -269,8 +272,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
}
/* Disable I2C controller */
- writeb(0, i2c_imx->base + IMX_I2C_I2CR);
- clk_disable(i2c_imx->clk);
+ writeb(0x80, i2c_imx->base + IMX_I2C_I2CR);
+ //clk_disable(i2c_imx->clk);
}
static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
@@ -434,6 +437,23 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+#ifdef CONFIG_ARCH_MVF
+ // since this can get called before probe, assign happens here
+ if(!sema4)
+ {
+ result = mvf_sema4_assign(3, true, &sema4);
+ if(result) {
+ printk(KERN_ERR "can't assign sema4 %s %s exiting.\n",__FILE__,__func__);
+ return result;
+ }
+ }
+
+ // lock out MQX
+ result = mvf_sema4_lock(sema4, 10000000); // 10 seconds
+ if(result)
+ return result;
+#endif
+
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx);
if (result)
@@ -482,6 +502,10 @@ fail0:
/* Stop I2C transfer */
i2c_imx_stop(i2c_imx);
+#ifdef CONFIG_ARCH_MVF
+ mvf_sema4_unlock(sema4);
+#endif
+
dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
(result < 0) ? "error" : "success msg",
(result < 0) ? result : num);
@@ -571,6 +595,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can't get I2C clock\n");
goto fail3;
}
+clk_enable(i2c_imx->clk);
/* Request IRQ */
ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx);
@@ -592,8 +617,9 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE);
/* Set up chip registers to defaults */
- writeb(0, i2c_imx->base + IMX_I2C_I2CR);
+ writeb(0x80, i2c_imx->base + IMX_I2C_I2CR);
writeb(0, i2c_imx->base + IMX_I2C_I2SR);
+//clk_disable(i2c_imx->clk);
/* Add I2C adapter */
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
diff --git a/include/linux/mvf_sema4.h b/include/linux/mvf_sema4.h
new file mode 100644
index 000000000000..898065afb23f
--- /dev/null
+++ b/include/linux/mvf_sema4.h
@@ -0,0 +1,15 @@
+#ifndef __MVF_SEMA4__
+#define __MVF_SEMA4__
+
+typedef struct mvf_sema4_handle_struct {
+ int gate_num;
+ int use_interrupts;
+ wait_queue_head_t wait_queue;
+} MVF_SEMA4;
+
+int mvf_sema4_assign(int gate_num, bool use_interrupts, MVF_SEMA4** sema4_p);
+int mvf_sema4_deassign(MVF_SEMA4 *sema4);
+int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us);
+int mvf_sema4_unlock(MVF_SEMA4 *sema4);
+
+#endif
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h
index 8a9f43534b79..291371c565cc 100644
--- a/sound/soc/codecs/sgtl5000.h
+++ b/sound/soc/codecs/sgtl5000.h
@@ -394,7 +394,7 @@
#define SGTL5000_DAP_MIX_EN 0x0010
#define SGTL5000_DAP_EN 0x0001
-#define SGTL5000_SYSCLK 0x00
+#define SGTL5000_SYSCLK 1
#define SGTL5000_LRCLK 0x01
#endif
diff --git a/sound/soc/mvf/Kconfig b/sound/soc/mvf/Kconfig
index 6577df843926..7b34f5cf1c73 100644
--- a/sound/soc/mvf/Kconfig
+++ b/sound/soc/mvf/Kconfig
@@ -18,9 +18,19 @@ config SND_SOC_MVF_SGTL5000
depends on I2C
select SND_SOC_SGTL5000
select SND_MVF_SOC_TWR
- default y
+ default n
help
Say Y if you want to add support for SoC audio on an Farday board with
a sgtl5000 codec.
+config SND_SOC_PCM052_SGTL5000
+ tristate "SoC Audio support for the phyCORE-Vybrid board with sgtl5000"
+ depends on I2C
+ select SND_SOC_SGTL5000
+ select SND_MVF_SOC_TWR
+ default y
+ help
+ Say Y if you want to add support for SoC audio on the phyCORE-Vybrid
+ board with a sgtl5000 codec.
+
endif
diff --git a/sound/soc/mvf/Makefile b/sound/soc/mvf/Makefile
index c9e179ad0a8e..7bcc0bf01d71 100644
--- a/sound/soc/mvf/Makefile
+++ b/sound/soc/mvf/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_MVF_SOC_TWR) += snd-soc-mvf-twr.o
# Faraday Machine Support
snd-soc-mvf-sgtl5000-objs := mvf-sgtl5000.o
+snd-soc-pcm052-sgtl5000-objs := pcm052-sgtl5000.o
obj-$(CONFIG_SND_SOC_MVF_SGTL5000) += snd-soc-mvf-sgtl5000.o
+obj-$(CONFIG_SND_SOC_PCM052_SGTL5000) += snd-soc-pcm052-sgtl5000.o
diff --git a/sound/soc/mvf/mvf-sai.h b/sound/soc/mvf/mvf-sai.h
index 1406e28883a0..fbc108186158 100644
--- a/sound/soc/mvf/mvf-sai.h
+++ b/sound/soc/mvf/mvf-sai.h
@@ -21,7 +21,7 @@
#define SAI_TCR2 0x08
#define SAI_TCR2_SYNC (1 << 30)
-#define SAI_TCR2_MSEL_MASK (0xff << 26)
+#define SAI_TCR2_MSEL_MASK (0x3 << 26)
#define SAI_TCR2_MSEL_BUS (0 << 26)
#define SAI_TCR2_MSEL_MCLK1 (1 << 26)
#define SAI_TCR2_MSEL_MCLK2 (2 << 26)
@@ -73,7 +73,7 @@
#define SAI_RCR1 0x84
#define SAI_RCR2 0x88
-#define SAI_RCR2_MSEL_MASK (0xff << 26)
+#define SAI_RCR2_MSEL_MASK (0x3 << 26)
#define SAI_RCR2_MSEL_BUS (0 << 26)
#define SAI_RCR2_MSEL_MCLK1 (1 << 26)
#define SAI_RCR2_MSEL_MCLK2 (2 << 26)
diff --git a/sound/soc/mvf/pcm052-sgtl5000.c b/sound/soc/mvf/pcm052-sgtl5000.c
new file mode 100644
index 000000000000..553751930a29
--- /dev/null
+++ b/sound/soc/mvf/pcm052-sgtl5000.c
@@ -0,0 +1,320 @@
+/*
+ * sound/soc/mvf-sgtl5000.c -- SoC audio for Faraday TWR-AUDIO-SGTL boards
+ * with sgtl5000 codec
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * 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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/fsl_devices.h>
+#include <linux/gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/mach-types.h>
+
+#include "../codecs/sgtl5000.h"
+#include "mvf-sai.h"
+
+
+static struct mvf_sgtl5000_priv {
+ int sysclk;
+ int hw;
+ struct platform_device *pdev;
+} card_priv;
+
+static struct snd_soc_card mvf_sgtl5000;
+
+static int sgtl5000_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ u32 dai_format;
+ int ret;
+ unsigned int channels = params_channels(params);
+
+ snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, card_priv.sysclk, 1);
+
+ dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
+ if (ret < 0)
+ return ret;
+
+ /* TODO: The SAI driver should figure this out for us */
+ switch (channels) {
+ case 2:
+ snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffc, 0xfffffffc, 2, 0);
+ break;
+ case 1:
+ snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffe, 0xfffffffe, 1, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* set cpu DAI configuration */
+ dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBM_CFM;
+ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops mvf_sgtl5000_hifi_ops = {
+ .hw_params = sgtl5000_params,
+};
+
+static int sgtl5000_jack_func;
+static int sgtl5000_spk_func;
+static int sgtl5000_line_in_func;
+
+static const char * const jack_function[] = { "off", "on"};
+
+static const char * const spk_function[] = { "off", "on" };
+
+static const char * const line_in_function[] = { "off", "on" };
+
+static const struct soc_enum sgtl5000_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, jack_function),
+ SOC_ENUM_SINGLE_EXT(2, spk_function),
+ SOC_ENUM_SINGLE_EXT(2, line_in_function),
+};
+
+static int sgtl5000_get_jack(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] = sgtl5000_jack_func;
+ return 0;
+}
+
+static int sgtl5000_set_jack(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (sgtl5000_jack_func == ucontrol->value.enumerated.item[0])
+ return 0;
+
+ sgtl5000_jack_func = ucontrol->value.enumerated.item[0];
+ if (sgtl5000_jack_func)
+ snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+ else
+ snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
+
+ snd_soc_dapm_sync(&codec->dapm);
+ return 1;
+}
+
+static int sgtl5000_get_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] = sgtl5000_spk_func;
+ return 0;
+}
+
+static int sgtl5000_set_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (sgtl5000_spk_func == ucontrol->value.enumerated.item[0])
+ return 0;
+
+ sgtl5000_spk_func = ucontrol->value.enumerated.item[0];
+ if (sgtl5000_spk_func)
+ snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
+ else
+ snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
+
+ snd_soc_dapm_sync(&codec->dapm);
+ return 1;
+}
+
+static int sgtl5000_get_line_in(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] = sgtl5000_line_in_func;
+ return 0;
+}
+
+static int sgtl5000_set_line_in(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (sgtl5000_line_in_func == ucontrol->value.enumerated.item[0])
+ return 0;
+
+ sgtl5000_line_in_func = ucontrol->value.enumerated.item[0];
+ if (sgtl5000_line_in_func)
+ snd_soc_dapm_enable_pin(&codec->dapm, "Line In Jack");
+ else
+ snd_soc_dapm_disable_pin(&codec->dapm, "Line In Jack");
+
+ snd_soc_dapm_sync(&codec->dapm);
+ return 1;
+}
+
+static const struct snd_soc_dapm_widget mvf_pcm052_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_LINE("Line In Jack", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+};
+
+static const struct snd_kcontrol_new sgtl5000_machine_controls[] = {
+ SOC_ENUM_EXT("Jack Function", sgtl5000_enum[0], sgtl5000_get_jack,
+ sgtl5000_set_jack),
+ SOC_ENUM_EXT("Speaker Function", sgtl5000_enum[1], sgtl5000_get_spk,
+ sgtl5000_set_spk),
+ SOC_ENUM_EXT("Line In Function", sgtl5000_enum[1], sgtl5000_get_line_in,
+ sgtl5000_set_line_in),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+
+ /* Mic Jack --> MIC_IN (with automatic bias) */
+ {"MIC_IN", NULL, "Mic Jack"},
+
+ /* Line in Jack --> LINE_IN */
+ {"LINE_IN", NULL, "Line In Jack"},
+
+ /* HP_OUT --> Headphone Jack */
+ {"Headphone Jack", NULL, "HP_OUT"},
+
+ /* LINE_OUT --> Ext Speaker */
+ {"Ext Spk", NULL, "LINE_OUT"},
+};
+
+static int mvf_pcm052_sgtl5000_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ int ret;
+
+ ret = snd_soc_add_controls(codec, sgtl5000_machine_controls,
+ ARRAY_SIZE(sgtl5000_machine_controls));
+ if (ret)
+ return ret;
+
+ /* Add mvf_pcm052 specific widgets */
+ snd_soc_dapm_new_controls(&codec->dapm, mvf_pcm052_dapm_widgets,
+ ARRAY_SIZE(mvf_pcm052_dapm_widgets));
+
+ /* Set up mvf_pcm052 specific audio path audio_map */
+ snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_disable_pin(&codec->dapm, "Line In Jack");
+ snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+ snd_soc_dapm_sync(&codec->dapm);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link mvf_sgtl5000_dai[] = {
+ {
+ .name = "HiFi",
+ .stream_name = "HiFi",
+ .codec_dai_name = "sgtl5000",
+ .codec_name = "sgtl5000.2-000a",
+ .cpu_dai_name = "mvf-sai.0",
+ .platform_name = "mvf-pcm-audio.0",
+ .init = mvf_pcm052_sgtl5000_init,
+ .ops = &mvf_sgtl5000_hifi_ops,
+ },
+};
+
+static struct snd_soc_card mvf_sgtl5000 = {
+ .name = "sgtl5000-sai",
+ .dai_link = mvf_sgtl5000_dai,
+ .num_links = ARRAY_SIZE(mvf_sgtl5000_dai),
+};
+
+static struct platform_device *mvf_sgtl5000_snd_device;
+
+static int __devinit mvf_sgtl5000_probe(struct platform_device *pdev)
+{
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+
+ card_priv.pdev = pdev;
+
+ if (plat->init && plat->init())
+ return -EINVAL;
+
+ card_priv.sysclk = 24576000;
+
+ return 0;
+}
+
+static int mvf_sgtl5000_remove(struct platform_device *pdev)
+{
+ struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
+
+ if (plat->finit)
+ plat->finit();
+
+ return 0;
+}
+
+static struct platform_driver mvf_sgtl5000_audio_driver = {
+ .probe = mvf_sgtl5000_probe,
+ .remove = mvf_sgtl5000_remove,
+ .driver = {
+ .name = "pcm052-sgtl5000",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mvf_sgtl5000_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&mvf_sgtl5000_audio_driver);
+ if (ret)
+ return -ENOMEM;
+
+ mvf_sgtl5000_dai[0].codec_name = "sgtl5000.2-000a";
+
+ mvf_sgtl5000_snd_device = platform_device_alloc("soc-audio", 1);
+ if (!mvf_sgtl5000_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(mvf_sgtl5000_snd_device, &mvf_sgtl5000);
+
+ ret = platform_device_add(mvf_sgtl5000_snd_device);
+
+ if (ret) {
+ printk(KERN_ERR "ASoC: Platform device allocation failed\n");
+ platform_device_put(mvf_sgtl5000_snd_device);
+ }
+
+ return ret;
+}
+
+static void __exit mvf_sgtl5000_exit(void)
+{
+ platform_driver_unregister(&mvf_sgtl5000_audio_driver);
+ platform_device_unregister(mvf_sgtl5000_snd_device);
+}
+
+module_init(mvf_sgtl5000_init);
+module_exit(mvf_sgtl5000_exit);
+
+MODULE_AUTHOR("Alison Wang, <b18965@freescale.com>");
+MODULE_DESCRIPTION("PhyCORE ALSA SoC driver");
+MODULE_LICENSE("GPL");