aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-davinci/board-dm365-evm.c4
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h6
-rw-r--r--arch/arm/plat-omap/mcbsp.c55
-rw-r--r--drivers/gpio/wm8994-gpio.c12
-rw-r--r--drivers/mfd/Kconfig8
-rw-r--r--drivers/mfd/Makefile3
-rw-r--r--drivers/mfd/davinci_voicecodec.c190
-rw-r--r--drivers/mfd/twl-core.c4
-rw-r--r--drivers/mfd/wm8994-core.c43
-rw-r--r--drivers/mfd/wm8994-irq.c310
-rw-r--r--include/linux/i2c/twl.h6
-rw-r--r--include/linux/mfd/davinci_voicecodec.h126
-rw-r--r--include/linux/mfd/wm8350/audio.h2
-rw-r--r--include/linux/mfd/wm8994/core.h53
-rw-r--r--include/linux/mfd/wm8994/pdata.h1
-rw-r--r--include/sound/jack.h8
-rw-r--r--include/sound/soc-dai.h7
-rw-r--r--include/sound/soc-dapm.h5
-rw-r--r--include/sound/soc.h20
-rw-r--r--include/sound/tlv320dac33-plat.h1
-rw-r--r--include/sound/wm8903.h249
-rw-r--r--include/sound/wm8904.h110
-rw-r--r--include/sound/wm8960.h24
-rw-r--r--sound/core/jack.c71
-rw-r--r--sound/soc/atmel/atmel-pcm.c14
-rw-r--r--sound/soc/blackfin/Kconfig9
-rw-r--r--sound/soc/blackfin/Makefile4
-rw-r--r--sound/soc/blackfin/bf5xx-ad193x.c (renamed from sound/soc/blackfin/bf5xx-ad1938.c)66
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h28
-rw-r--r--sound/soc/codecs/Kconfig12
-rw-r--r--sound/soc/codecs/Makefile8
-rw-r--r--sound/soc/codecs/ad1938.c521
-rw-r--r--sound/soc/codecs/ad1938.h100
-rw-r--r--sound/soc/codecs/ad193x.c545
-rw-r--r--sound/soc/codecs/ad193x.h81
-rw-r--r--sound/soc/codecs/ak4642.c175
-rw-r--r--sound/soc/codecs/cq93vc.c299
-rw-r--r--sound/soc/codecs/cq93vc.h29
-rw-r--r--sound/soc/codecs/da7210.c153
-rw-r--r--sound/soc/codecs/ssm2602.c4
-rw-r--r--sound/soc/codecs/tlv320dac33.c38
-rw-r--r--sound/soc/codecs/twl4030.c72
-rw-r--r--sound/soc/codecs/twl6040.c1228
-rw-r--r--sound/soc/codecs/twl6040.h141
-rw-r--r--sound/soc/codecs/wm8350.c74
-rw-r--r--sound/soc/codecs/wm8350.h3
-rw-r--r--sound/soc/codecs/wm8750.c53
-rw-r--r--sound/soc/codecs/wm8903.c202
-rw-r--r--sound/soc/codecs/wm8903.h221
-rw-r--r--sound/soc/codecs/wm8904.c17
-rw-r--r--sound/soc/codecs/wm8904.h97
-rw-r--r--sound/soc/codecs/wm8960.c209
-rw-r--r--sound/soc/codecs/wm8960.h10
-rw-r--r--sound/soc/codecs/wm8994.c175
-rw-r--r--sound/soc/codecs/wm8994.h3
-rw-r--r--sound/soc/davinci/Kconfig27
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-evm.c61
-rw-r--r--sound/soc/davinci/davinci-vcif.c274
-rw-r--r--sound/soc/davinci/davinci-vcif.h28
-rw-r--r--sound/soc/imx/Kconfig8
-rw-r--r--sound/soc/imx/Makefile3
-rw-r--r--sound/soc/imx/wm1133-ev1.c308
-rw-r--r--sound/soc/omap/mcpdm.c548
-rw-r--r--sound/soc/omap/omap-mcbsp.c38
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c120
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.h4
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c40
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.h4
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c12
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h15
-rw-r--r--sound/soc/sh/Kconfig3
-rw-r--r--sound/soc/sh/fsi-ak4642.c14
-rw-r--r--sound/soc/sh/fsi.c191
-rw-r--r--sound/soc/soc-cache.c122
-rw-r--r--sound/soc/soc-core.c115
-rw-r--r--sound/soc/soc-dapm.c135
-rw-r--r--sound/soc/soc-jack.c38
78 files changed, 6236 insertions, 1783 deletions
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index d15beceb632e..512174a874a1 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -604,7 +604,11 @@ static __init void dm365_evm_init(void)
604 /* maybe setup mmc1/etc ... _after_ mmc0 */ 604 /* maybe setup mmc1/etc ... _after_ mmc0 */
605 evm_init_cpld(); 605 evm_init_cpld();
606 606
607#ifdef CONFIG_SND_DM365_AIC3X_CODEC
607 dm365_init_asp(&dm365_evm_snd_data); 608 dm365_init_asp(&dm365_evm_snd_data);
609#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
610 dm365_init_vc(&dm365_evm_snd_data);
611#endif
608 dm365_init_rtc(); 612 dm365_init_rtc();
609 dm365_init_ks(&dm365evm_ks_data); 613 dm365_init_ks(&dm365evm_ks_data);
610 614
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 39748354ce45..1bd7021336c2 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -149,6 +149,8 @@
149#define OMAP_MCBSP_REG_WAKEUPEN 0xA8 149#define OMAP_MCBSP_REG_WAKEUPEN 0xA8
150#define OMAP_MCBSP_REG_XCCR 0xAC 150#define OMAP_MCBSP_REG_XCCR 0xAC
151#define OMAP_MCBSP_REG_RCCR 0xB0 151#define OMAP_MCBSP_REG_RCCR 0xB0
152#define OMAP_MCBSP_REG_XBUFFSTAT 0xB4
153#define OMAP_MCBSP_REG_RBUFFSTAT 0xB8
152#define OMAP_MCBSP_REG_SSELCR 0xBC 154#define OMAP_MCBSP_REG_SSELCR 0xBC
153 155
154#define OMAP_ST_REG_REV 0x00 156#define OMAP_ST_REG_REV 0x00
@@ -471,6 +473,8 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
471void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); 473void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
472u16 omap_mcbsp_get_max_tx_threshold(unsigned int id); 474u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
473u16 omap_mcbsp_get_max_rx_threshold(unsigned int id); 475u16 omap_mcbsp_get_max_rx_threshold(unsigned int id);
476u16 omap_mcbsp_get_tx_delay(unsigned int id);
477u16 omap_mcbsp_get_rx_delay(unsigned int id);
474int omap_mcbsp_get_dma_op_mode(unsigned int id); 478int omap_mcbsp_get_dma_op_mode(unsigned int id);
475#else 479#else
476static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) 480static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
@@ -479,6 +483,8 @@ static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
479{ } 483{ }
480static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; } 484static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
481static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; } 485static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
486static inline u16 omap_mcbsp_get_tx_delay(unsigned int id) { return 0; }
487static inline u16 omap_mcbsp_get_rx_delay(unsigned int id) { return 0; }
482static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; } 488static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }
483#endif 489#endif
484int omap_mcbsp_request(unsigned int id); 490int omap_mcbsp_request(unsigned int id);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 52dfcc81511e..4ff7a11b1838 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -559,6 +559,61 @@ u16 omap_mcbsp_get_max_rx_threshold(unsigned int id)
559} 559}
560EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold); 560EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold);
561 561
562#define MCBSP2_FIFO_SIZE 0x500 /* 1024 + 256 locations */
563#define MCBSP1345_FIFO_SIZE 0x80 /* 128 locations */
564/*
565 * omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
566 */
567u16 omap_mcbsp_get_tx_delay(unsigned int id)
568{
569 struct omap_mcbsp *mcbsp;
570 u16 buffstat;
571
572 if (!omap_mcbsp_check_valid_id(id)) {
573 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
574 return -ENODEV;
575 }
576 mcbsp = id_to_mcbsp_ptr(id);
577
578 /* Returns the number of free locations in the buffer */
579 buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
580
581 /* Number of slots are different in McBSP ports */
582 if (mcbsp->id == 2)
583 return MCBSP2_FIFO_SIZE - buffstat;
584 else
585 return MCBSP1345_FIFO_SIZE - buffstat;
586}
587EXPORT_SYMBOL(omap_mcbsp_get_tx_delay);
588
589/*
590 * omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
591 * to reach the threshold value (when the DMA will be triggered to read it)
592 */
593u16 omap_mcbsp_get_rx_delay(unsigned int id)
594{
595 struct omap_mcbsp *mcbsp;
596 u16 buffstat, threshold;
597
598 if (!omap_mcbsp_check_valid_id(id)) {
599 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
600 return -ENODEV;
601 }
602 mcbsp = id_to_mcbsp_ptr(id);
603
604 /* Returns the number of used locations in the buffer */
605 buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
606 /* RX threshold */
607 threshold = MCBSP_READ(mcbsp, THRSH1);
608
609 /* Return the number of location till we reach the threshold limit */
610 if (threshold <= buffstat)
611 return 0;
612 else
613 return threshold - buffstat;
614}
615EXPORT_SYMBOL(omap_mcbsp_get_rx_delay);
616
562/* 617/*
563 * omap_mcbsp_get_dma_op_mode just return the current configured 618 * omap_mcbsp_get_dma_op_mode just return the current configured
564 * operating mode for the mcbsp channel 619 * operating mode for the mcbsp channel
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/wm8994-gpio.c
index de28b4a470ea..3ee35badcf1d 100644
--- a/drivers/gpio/wm8994-gpio.c
+++ b/drivers/gpio/wm8994-gpio.c
@@ -80,6 +80,18 @@ static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
80 wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value); 80 wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
81} 81}
82 82
83static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
84{
85 struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
86 struct wm8994 *wm8994 = wm8994_gpio->wm8994;
87
88 if (!wm8994->irq_base)
89 return -EINVAL;
90
91 return wm8994->irq_base + offset;
92}
93
94
83#ifdef CONFIG_DEBUG_FS 95#ifdef CONFIG_DEBUG_FS
84static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 96static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
85{ 97{
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2a5a0b78f84e..de3e74cde51c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -53,6 +53,10 @@ config MFD_SH_MOBILE_SDHI
53 This driver supports the SDHI hardware block found in many 53 This driver supports the SDHI hardware block found in many
54 SuperH Mobile SoCs. 54 SuperH Mobile SoCs.
55 55
56config MFD_DAVINCI_VOICECODEC
57 tristate
58 select MFD_CORE
59
56config MFD_DM355EVM_MSP 60config MFD_DM355EVM_MSP
57 bool "DaVinci DM355 EVM microcontroller" 61 bool "DaVinci DM355 EVM microcontroller"
58 depends on I2C && MACH_DAVINCI_DM355_EVM 62 depends on I2C && MACH_DAVINCI_DM355_EVM
@@ -297,9 +301,9 @@ config MFD_WM8350_I2C
297 selected to enable support for the functionality of the chip. 301 selected to enable support for the functionality of the chip.
298 302
299config MFD_WM8994 303config MFD_WM8994
300 tristate "Support Wolfson Microelectronics WM8994" 304 bool "Support Wolfson Microelectronics WM8994"
301 select MFD_CORE 305 select MFD_CORE
302 depends on I2C 306 depends on I2C=y && GENERIC_HARDIRQS
303 help 307 help
304 The WM8994 is a highly integrated hi-fi CODEC designed for 308 The WM8994 is a highly integrated hi-fi CODEC designed for
305 smartphone applicatiosn. As well as audio functionality it 309 smartphone applicatiosn. As well as audio functionality it
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 22715add99a7..87935f967aa0 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
12obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o 12obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
13obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o 13obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
14 14
15obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
15obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o 16obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
16 17
17obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o 18obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
@@ -25,7 +26,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
25wm8350-objs += wm8350-irq.o 26wm8350-objs += wm8350-irq.o
26obj-$(CONFIG_MFD_WM8350) += wm8350.o 27obj-$(CONFIG_MFD_WM8350) += wm8350.o
27obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o 28obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
28obj-$(CONFIG_MFD_WM8994) += wm8994-core.o 29obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o
29 30
30obj-$(CONFIG_TPS65010) += tps65010.o 31obj-$(CONFIG_TPS65010) += tps65010.o
31obj-$(CONFIG_MENELAUS) += menelaus.o 32obj-$(CONFIG_MENELAUS) += menelaus.o
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c
new file mode 100644
index 000000000000..3e75f02e4778
--- /dev/null
+++ b/drivers/mfd/davinci_voicecodec.c
@@ -0,0 +1,190 @@
1/*
2 * DaVinci Voice Codec Core Interface for TI platforms
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/device.h>
26#include <linux/slab.h>
27#include <linux/delay.h>
28#include <linux/io.h>
29#include <linux/clk.h>
30
31#include <sound/pcm.h>
32
33#include <linux/mfd/davinci_voicecodec.h>
34
35u32 davinci_vc_read(struct davinci_vc *davinci_vc, int reg)
36{
37 return __raw_readl(davinci_vc->base + reg);
38}
39
40void davinci_vc_write(struct davinci_vc *davinci_vc,
41 int reg, u32 val)
42{
43 __raw_writel(val, davinci_vc->base + reg);
44}
45
46static int __init davinci_vc_probe(struct platform_device *pdev)
47{
48 struct davinci_vc *davinci_vc;
49 struct resource *res, *mem;
50 struct mfd_cell *cell = NULL;
51 int ret;
52
53 davinci_vc = kzalloc(sizeof(struct davinci_vc), GFP_KERNEL);
54 if (!davinci_vc) {
55 dev_dbg(&pdev->dev,
56 "could not allocate memory for private data\n");
57 return -ENOMEM;
58 }
59
60 davinci_vc->clk = clk_get(&pdev->dev, NULL);
61 if (IS_ERR(davinci_vc->clk)) {
62 dev_dbg(&pdev->dev,
63 "could not get the clock for voice codec\n");
64 ret = -ENODEV;
65 goto fail1;
66 }
67 clk_enable(davinci_vc->clk);
68
69 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
70 if (!res) {
71 dev_err(&pdev->dev, "no mem resource\n");
72 ret = -ENODEV;
73 goto fail2;
74 }
75
76 davinci_vc->pbase = res->start;
77 davinci_vc->base_size = resource_size(res);
78
79 mem = request_mem_region(davinci_vc->pbase, davinci_vc->base_size,
80 pdev->name);
81 if (!mem) {
82 dev_err(&pdev->dev, "VCIF region already claimed\n");
83 ret = -EBUSY;
84 goto fail2;
85 }
86
87 davinci_vc->base = ioremap(davinci_vc->pbase, davinci_vc->base_size);
88 if (!davinci_vc->base) {
89 dev_err(&pdev->dev, "can't ioremap mem resource.\n");
90 ret = -ENOMEM;
91 goto fail3;
92 }
93
94 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
95 if (!res) {
96 dev_err(&pdev->dev, "no DMA resource\n");
97 return -ENXIO;
98 }
99
100 davinci_vc->davinci_vcif.dma_tx_channel = res->start;
101 davinci_vc->davinci_vcif.dma_tx_addr =
102 (dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_WFIFO);
103
104 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
105 if (!res) {
106 dev_err(&pdev->dev, "no DMA resource\n");
107 return -ENXIO;
108 }
109
110 davinci_vc->davinci_vcif.dma_rx_channel = res->start;
111 davinci_vc->davinci_vcif.dma_rx_addr =
112 (dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_RFIFO);
113
114 davinci_vc->dev = &pdev->dev;
115 davinci_vc->pdev = pdev;
116
117 /* Voice codec interface client */
118 cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
119 cell->name = "davinci_vcif";
120 cell->driver_data = davinci_vc;
121
122 /* Voice codec CQ93VC client */
123 cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
124 cell->name = "cq93vc";
125 cell->driver_data = davinci_vc;
126
127 ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
128 DAVINCI_VC_CELLS, NULL, 0);
129 if (ret != 0) {
130 dev_err(&pdev->dev, "fail to register client devices\n");
131 goto fail4;
132 }
133
134 return 0;
135
136fail4:
137 iounmap(davinci_vc->base);
138fail3:
139 release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
140fail2:
141 clk_disable(davinci_vc->clk);
142 clk_put(davinci_vc->clk);
143 davinci_vc->clk = NULL;
144fail1:
145 kfree(davinci_vc);
146
147 return ret;
148}
149
150static int __devexit davinci_vc_remove(struct platform_device *pdev)
151{
152 struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
153
154 mfd_remove_devices(&pdev->dev);
155
156 iounmap(davinci_vc->base);
157 release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
158
159 clk_disable(davinci_vc->clk);
160 clk_put(davinci_vc->clk);
161 davinci_vc->clk = NULL;
162
163 kfree(davinci_vc);
164
165 return 0;
166}
167
168static struct platform_driver davinci_vc_driver = {
169 .driver = {
170 .name = "davinci_voicecodec",
171 .owner = THIS_MODULE,
172 },
173 .remove = __devexit_p(davinci_vc_remove),
174};
175
176static int __init davinci_vc_init(void)
177{
178 return platform_driver_probe(&davinci_vc_driver, davinci_vc_probe);
179}
180module_init(davinci_vc_init);
181
182static void __exit davinci_vc_exit(void)
183{
184 platform_driver_unregister(&davinci_vc_driver);
185}
186module_exit(davinci_vc_exit);
187
188MODULE_AUTHOR("Miguel Aguilar");
189MODULE_DESCRIPTION("Texas Instruments DaVinci Voice Codec Core Interface");
190MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 562cd4935e17..720e099e506d 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -109,7 +109,7 @@
109#endif 109#endif
110 110
111#if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\ 111#if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\
112 defined(CONFIG_SND_SOC_TWL6030) || defined(CONFIG_SND_SOC_TWL6030_MODULE) 112 defined(CONFIG_SND_SOC_TWL6040) || defined(CONFIG_SND_SOC_TWL6040_MODULE)
113#define twl_has_codec() true 113#define twl_has_codec() true
114#else 114#else
115#define twl_has_codec() false 115#define twl_has_codec() false
@@ -708,7 +708,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
708 /* Phoenix*/ 708 /* Phoenix*/
709 if (twl_has_codec() && pdata->codec && twl_class_is_6030()) { 709 if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
710 sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; 710 sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
711 child = add_child(sub_chip_id, "twl6030_codec", 711 child = add_child(sub_chip_id, "twl6040_codec",
712 pdata->codec, sizeof(*pdata->codec), 712 pdata->codec, sizeof(*pdata->codec),
713 false, 0, 0); 713 false, 0, 0);
714 if (IS_ERR(child)) 714 if (IS_ERR(child))
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 844e1c1b7d90..39cde82afb48 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -172,9 +172,34 @@ static struct mfd_cell wm8994_regulator_devs[] = {
172 { .name = "wm8994-ldo", .id = 2 }, 172 { .name = "wm8994-ldo", .id = 2 },
173}; 173};
174 174
175static struct resource wm8994_codec_resources[] = {
176 {
177 .start = WM8994_IRQ_TEMP_SHUT,
178 .end = WM8994_IRQ_TEMP_WARN,
179 .flags = IORESOURCE_IRQ,
180 },
181};
182
183static struct resource wm8994_gpio_resources[] = {
184 {
185 .start = WM8994_IRQ_GPIO(1),
186 .end = WM8994_IRQ_GPIO(11),
187 .flags = IORESOURCE_IRQ,
188 },
189};
190
175static struct mfd_cell wm8994_devs[] = { 191static struct mfd_cell wm8994_devs[] = {
176 { .name = "wm8994-codec" }, 192 {
177 { .name = "wm8994-gpio" }, 193 .name = "wm8994-codec",
194 .num_resources = ARRAY_SIZE(wm8994_codec_resources),
195 .resources = wm8994_codec_resources,
196 },
197
198 {
199 .name = "wm8994-gpio",
200 .num_resources = ARRAY_SIZE(wm8994_gpio_resources),
201 .resources = wm8994_gpio_resources,
202 },
178}; 203};
179 204
180/* 205/*
@@ -235,6 +260,11 @@ static int wm8994_device_resume(struct device *dev)
235 return ret; 260 return ret;
236 } 261 }
237 262
263 ret = wm8994_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK,
264 WM8994_NUM_IRQ_REGS * 2, &wm8994->irq_masks_cur);
265 if (ret < 0)
266 dev_err(dev, "Failed to restore interrupt masks: %d\n", ret);
267
238 ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2, 268 ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
239 &wm8994->ldo_regs); 269 &wm8994->ldo_regs);
240 if (ret < 0) 270 if (ret < 0)
@@ -347,6 +377,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
347 377
348 378
349 if (pdata) { 379 if (pdata) {
380 wm8994->irq_base = pdata->irq_base;
350 wm8994->gpio_base = pdata->gpio_base; 381 wm8994->gpio_base = pdata->gpio_base;
351 382
352 /* GPIO configuration is only applied if it's non-zero */ 383 /* GPIO configuration is only applied if it's non-zero */
@@ -374,16 +405,20 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
374 WM8994_LDO1_DISCH, 0); 405 WM8994_LDO1_DISCH, 0);
375 } 406 }
376 407
408 wm8994_irq_init(wm8994);
409
377 ret = mfd_add_devices(wm8994->dev, -1, 410 ret = mfd_add_devices(wm8994->dev, -1,
378 wm8994_devs, ARRAY_SIZE(wm8994_devs), 411 wm8994_devs, ARRAY_SIZE(wm8994_devs),
379 NULL, 0); 412 NULL, 0);
380 if (ret != 0) { 413 if (ret != 0) {
381 dev_err(wm8994->dev, "Failed to add children: %d\n", ret); 414 dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
382 goto err_enable; 415 goto err_irq;
383 } 416 }
384 417
385 return 0; 418 return 0;
386 419
420err_irq:
421 wm8994_irq_exit(wm8994);
387err_enable: 422err_enable:
388 regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), 423 regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
389 wm8994->supplies); 424 wm8994->supplies);
@@ -400,6 +435,7 @@ err:
400static void wm8994_device_exit(struct wm8994 *wm8994) 435static void wm8994_device_exit(struct wm8994 *wm8994)
401{ 436{
402 mfd_remove_devices(wm8994->dev); 437 mfd_remove_devices(wm8994->dev);
438 wm8994_irq_exit(wm8994);
403 regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), 439 regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
404 wm8994->supplies); 440 wm8994->supplies);
405 regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies); 441 regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
@@ -468,6 +504,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
468 wm8994->control_data = i2c; 504 wm8994->control_data = i2c;
469 wm8994->read_dev = wm8994_i2c_read_device; 505 wm8994->read_dev = wm8994_i2c_read_device;
470 wm8994->write_dev = wm8994_i2c_write_device; 506 wm8994->write_dev = wm8994_i2c_write_device;
507 wm8994->irq = i2c->irq;
471 508
472 return wm8994_device_init(wm8994, id->driver_data, i2c->irq); 509 return wm8994_device_init(wm8994, id->driver_data, i2c->irq);
473} 510}
diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c
new file mode 100644
index 000000000000..8400eb1ee5db
--- /dev/null
+++ b/drivers/mfd/wm8994-irq.c
@@ -0,0 +1,310 @@
1/*
2 * wm8994-irq.c -- Interrupt controller support for Wolfson WM8994
3 *
4 * Copyright 2010 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/i2c.h>
18#include <linux/irq.h>
19#include <linux/mfd/core.h>
20#include <linux/interrupt.h>
21
22#include <linux/mfd/wm8994/core.h>
23#include <linux/mfd/wm8994/registers.h>
24
25#include <linux/delay.h>
26
27struct wm8994_irq_data {
28 int reg;
29 int mask;
30};
31
32static struct wm8994_irq_data wm8994_irqs[] = {
33 [WM8994_IRQ_TEMP_SHUT] = {
34 .reg = 2,
35 .mask = WM8994_TEMP_SHUT_EINT,
36 },
37 [WM8994_IRQ_MIC1_DET] = {
38 .reg = 2,
39 .mask = WM8994_MIC1_DET_EINT,
40 },
41 [WM8994_IRQ_MIC1_SHRT] = {
42 .reg = 2,
43 .mask = WM8994_MIC1_SHRT_EINT,
44 },
45 [WM8994_IRQ_MIC2_DET] = {
46 .reg = 2,
47 .mask = WM8994_MIC2_DET_EINT,
48 },
49 [WM8994_IRQ_MIC2_SHRT] = {
50 .reg = 2,
51 .mask = WM8994_MIC2_SHRT_EINT,
52 },
53 [WM8994_IRQ_FLL1_LOCK] = {
54 .reg = 2,
55 .mask = WM8994_FLL1_LOCK_EINT,
56 },
57 [WM8994_IRQ_FLL2_LOCK] = {
58 .reg = 2,
59 .mask = WM8994_FLL2_LOCK_EINT,
60 },
61 [WM8994_IRQ_SRC1_LOCK] = {
62 .reg = 2,
63 .mask = WM8994_SRC1_LOCK_EINT,
64 },
65 [WM8994_IRQ_SRC2_LOCK] = {
66 .reg = 2,
67 .mask = WM8994_SRC2_LOCK_EINT,
68 },
69 [WM8994_IRQ_AIF1DRC1_SIG_DET] = {
70 .reg = 2,
71 .mask = WM8994_AIF1DRC1_SIG_DET,
72 },
73 [WM8994_IRQ_AIF1DRC2_SIG_DET] = {
74 .reg = 2,
75 .mask = WM8994_AIF1DRC2_SIG_DET_EINT,
76 },
77 [WM8994_IRQ_AIF2DRC_SIG_DET] = {
78 .reg = 2,
79 .mask = WM8994_AIF2DRC_SIG_DET_EINT,
80 },
81 [WM8994_IRQ_FIFOS_ERR] = {
82 .reg = 2,
83 .mask = WM8994_FIFOS_ERR_EINT,
84 },
85 [WM8994_IRQ_WSEQ_DONE] = {
86 .reg = 2,
87 .mask = WM8994_WSEQ_DONE_EINT,
88 },
89 [WM8994_IRQ_DCS_DONE] = {
90 .reg = 2,
91 .mask = WM8994_DCS_DONE_EINT,
92 },
93 [WM8994_IRQ_TEMP_WARN] = {
94 .reg = 2,
95 .mask = WM8994_TEMP_WARN_EINT,
96 },
97 [WM8994_IRQ_GPIO(1)] = {
98 .reg = 1,
99 .mask = WM8994_GP1_EINT,
100 },
101 [WM8994_IRQ_GPIO(2)] = {
102 .reg = 1,
103 .mask = WM8994_GP2_EINT,
104 },
105 [WM8994_IRQ_GPIO(3)] = {
106 .reg = 1,
107 .mask = WM8994_GP3_EINT,
108 },
109 [WM8994_IRQ_GPIO(4)] = {
110 .reg = 1,
111 .mask = WM8994_GP4_EINT,
112 },
113 [WM8994_IRQ_GPIO(5)] = {
114 .reg = 1,
115 .mask = WM8994_GP5_EINT,
116 },
117 [WM8994_IRQ_GPIO(6)] = {
118 .reg = 1,
119 .mask = WM8994_GP6_EINT,
120 },
121 [WM8994_IRQ_GPIO(7)] = {
122 .reg = 1,
123 .mask = WM8994_GP7_EINT,
124 },
125 [WM8994_IRQ_GPIO(8)] = {
126 .reg = 1,
127 .mask = WM8994_GP8_EINT,
128 },
129 [WM8994_IRQ_GPIO(9)] = {
130 .reg = 1,
131 .mask = WM8994_GP8_EINT,
132 },
133 [WM8994_IRQ_GPIO(10)] = {
134 .reg = 1,
135 .mask = WM8994_GP10_EINT,
136 },
137 [WM8994_IRQ_GPIO(11)] = {
138 .reg = 1,
139 .mask = WM8994_GP11_EINT,
140 },
141};
142
143static inline int irq_data_to_status_reg(struct wm8994_irq_data *irq_data)
144{
145 return WM8994_INTERRUPT_STATUS_1 - 1 + irq_data->reg;
146}
147
148static inline int irq_data_to_mask_reg(struct wm8994_irq_data *irq_data)
149{
150 return WM8994_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
151}
152
153static inline struct wm8994_irq_data *irq_to_wm8994_irq(struct wm8994 *wm8994,
154 int irq)
155{
156 return &wm8994_irqs[irq - wm8994->irq_base];
157}
158
159static void wm8994_irq_lock(unsigned int irq)
160{
161 struct wm8994 *wm8994 = get_irq_chip_data(irq);
162
163 mutex_lock(&wm8994->irq_lock);
164}
165
166static void wm8994_irq_sync_unlock(unsigned int irq)
167{
168 struct wm8994 *wm8994 = get_irq_chip_data(irq);
169 int i;
170
171 for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
172 /* If there's been a change in the mask write it back
173 * to the hardware. */
174 if (wm8994->irq_masks_cur[i] != wm8994->irq_masks_cache[i]) {
175 wm8994->irq_masks_cache[i] = wm8994->irq_masks_cur[i];
176 wm8994_reg_write(wm8994,
177 WM8994_INTERRUPT_STATUS_1_MASK + i,
178 wm8994->irq_masks_cur[i]);
179 }
180 }
181
182 mutex_unlock(&wm8994->irq_lock);
183}
184
185static void wm8994_irq_unmask(unsigned int irq)
186{
187 struct wm8994 *wm8994 = get_irq_chip_data(irq);
188 struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, irq);
189
190 wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
191}
192
193static void wm8994_irq_mask(unsigned int irq)
194{
195 struct wm8994 *wm8994 = get_irq_chip_data(irq);
196 struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994, irq);
197
198 wm8994->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
199}
200
201static struct irq_chip wm8994_irq_chip = {
202 .name = "wm8994",
203 .bus_lock = wm8994_irq_lock,
204 .bus_sync_unlock = wm8994_irq_sync_unlock,
205 .mask = wm8994_irq_mask,
206 .unmask = wm8994_irq_unmask,
207};
208
209/* The processing of the primary interrupt occurs in a thread so that
210 * we can interact with the device over I2C or SPI. */
211static irqreturn_t wm8994_irq_thread(int irq, void *data)
212{
213 struct wm8994 *wm8994 = data;
214 unsigned int i;
215 u16 status[WM8994_NUM_IRQ_REGS];
216 int ret;
217
218 ret = wm8994_bulk_read(wm8994, WM8994_INTERRUPT_STATUS_1,
219 WM8994_NUM_IRQ_REGS, status);
220 if (ret < 0) {
221 dev_err(wm8994->dev, "Failed to read interrupt status: %d\n",
222 ret);
223 return IRQ_NONE;
224 }
225
226 /* Apply masking */
227 for (i = 0; i < WM8994_NUM_IRQ_REGS; i++)
228 status[i] &= ~wm8994->irq_masks_cur[i];
229
230 /* Report */
231 for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
232 if (status[wm8994_irqs[i].reg - 1] & wm8994_irqs[i].mask)
233 handle_nested_irq(wm8994->irq_base + i);
234 }
235
236 /* Ack any unmasked IRQs */
237 for (i = 0; i < ARRAY_SIZE(status); i++) {
238 if (status[i])
239 wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1 + i,
240 status[i]);
241 }
242
243 return IRQ_HANDLED;
244}
245
246int wm8994_irq_init(struct wm8994 *wm8994)
247{
248 int i, cur_irq, ret;
249
250 mutex_init(&wm8994->irq_lock);
251
252 /* Mask the individual interrupt sources */
253 for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
254 wm8994->irq_masks_cur[i] = 0xffff;
255 wm8994->irq_masks_cache[i] = 0xffff;
256 wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK + i,
257 0xffff);
258 }
259
260 if (!wm8994->irq) {
261 dev_warn(wm8994->dev,
262 "No interrupt specified, no interrupts\n");
263 wm8994->irq_base = 0;
264 return 0;
265 }
266
267 if (!wm8994->irq_base) {
268 dev_err(wm8994->dev,
269 "No interrupt base specified, no interrupts\n");
270 return 0;
271 }
272
273 /* Register them with genirq */
274 for (cur_irq = wm8994->irq_base;
275 cur_irq < ARRAY_SIZE(wm8994_irqs) + wm8994->irq_base;
276 cur_irq++) {
277 set_irq_chip_data(cur_irq, wm8994);
278 set_irq_chip_and_handler(cur_irq, &wm8994_irq_chip,
279 handle_edge_irq);
280 set_irq_nested_thread(cur_irq, 1);
281
282 /* ARM needs us to explicitly flag the IRQ as valid
283 * and will set them noprobe when we do so. */
284#ifdef CONFIG_ARM
285 set_irq_flags(cur_irq, IRQF_VALID);
286#else
287 set_irq_noprobe(cur_irq);
288#endif
289 }
290
291 ret = request_threaded_irq(wm8994->irq, NULL, wm8994_irq_thread,
292 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
293 "wm8994", wm8994);
294 if (ret != 0) {
295 dev_err(wm8994->dev, "Failed to request IRQ %d: %d\n",
296 wm8994->irq, ret);
297 return ret;
298 }
299
300 /* Enable top level interrupt if it was masked */
301 wm8994_reg_write(wm8994, WM8994_INTERRUPT_CONTROL, 0);
302
303 return 0;
304}
305
306void wm8994_irq_exit(struct wm8994 *wm8994)
307{
308 if (wm8994->irq)
309 free_irq(wm8994->irq, wm8994);
310}
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index fb6784e86d5f..ebd90ce58ca2 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -569,9 +569,9 @@ struct twl4030_codec_data {
569 struct twl4030_codec_audio_data *audio; 569 struct twl4030_codec_audio_data *audio;
570 struct twl4030_codec_vibra_data *vibra; 570 struct twl4030_codec_vibra_data *vibra;
571 571
572 /* twl6030 */ 572 /* twl6040 */
573 int audpwron_gpio; /* audio power-on gpio */ 573 int audpwron_gpio; /* audio power-on gpio */
574 int naudint_irq; /* audio interrupt */ 574 int naudint_irq; /* audio interrupt */
575}; 575};
576 576
577struct twl4030_platform_data { 577struct twl4030_platform_data {
diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h
new file mode 100644
index 000000000000..0ab61320ffa8
--- /dev/null
+++ b/include/linux/mfd/davinci_voicecodec.h
@@ -0,0 +1,126 @@
1/*
2 * DaVinci Voice Codec Core Interface for TI platforms
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifndef __LINUX_MFD_DAVINCI_VOICECODEC_H_
24#define __LINUX_MFD_DAVINIC_VOICECODEC_H_
25
26#include <linux/kernel.h>
27#include <linux/platform_device.h>
28#include <linux/mfd/core.h>
29
30#include <mach/edma.h>
31
32/*
33 * Register values.
34 */
35#define DAVINCI_VC_PID 0x00
36#define DAVINCI_VC_CTRL 0x04
37#define DAVINCI_VC_INTEN 0x08
38#define DAVINCI_VC_INTSTATUS 0x0c
39#define DAVINCI_VC_INTCLR 0x10
40#define DAVINCI_VC_EMUL_CTRL 0x14
41#define DAVINCI_VC_RFIFO 0x20
42#define DAVINCI_VC_WFIFO 0x24
43#define DAVINCI_VC_FIFOSTAT 0x28
44#define DAVINCI_VC_TST_CTRL 0x2C
45#define DAVINCI_VC_REG05 0x94
46#define DAVINCI_VC_REG09 0xA4
47#define DAVINCI_VC_REG12 0xB0
48
49/* DAVINCI_VC_CTRL bit fields */
50#define DAVINCI_VC_CTRL_MASK 0x5500
51#define DAVINCI_VC_CTRL_RSTADC BIT(0)
52#define DAVINCI_VC_CTRL_RSTDAC BIT(1)
53#define DAVINCI_VC_CTRL_RD_BITS_8 BIT(4)
54#define DAVINCI_VC_CTRL_RD_UNSIGNED BIT(5)
55#define DAVINCI_VC_CTRL_WD_BITS_8 BIT(6)
56#define DAVINCI_VC_CTRL_WD_UNSIGNED BIT(7)
57#define DAVINCI_VC_CTRL_RFIFOEN BIT(8)
58#define DAVINCI_VC_CTRL_RFIFOCL BIT(9)
59#define DAVINCI_VC_CTRL_RFIFOMD_WORD_1 BIT(10)
60#define DAVINCI_VC_CTRL_WFIFOEN BIT(12)
61#define DAVINCI_VC_CTRL_WFIFOCL BIT(13)
62#define DAVINCI_VC_CTRL_WFIFOMD_WORD_1 BIT(14)
63
64/* DAVINCI_VC_INT bit fields */
65#define DAVINCI_VC_INT_MASK 0x3F
66#define DAVINCI_VC_INT_RDRDY_MASK BIT(0)
67#define DAVINCI_VC_INT_RERROVF_MASK BIT(1)
68#define DAVINCI_VC_INT_RERRUDR_MASK BIT(2)
69#define DAVINCI_VC_INT_WDREQ_MASK BIT(3)
70#define DAVINCI_VC_INT_WERROVF_MASKBIT BIT(4)
71#define DAVINCI_VC_INT_WERRUDR_MASK BIT(5)
72
73/* DAVINCI_VC_REG05 bit fields */
74#define DAVINCI_VC_REG05_PGA_GAIN 0x07
75
76/* DAVINCI_VC_REG09 bit fields */
77#define DAVINCI_VC_REG09_MUTE 0x40
78#define DAVINCI_VC_REG09_DIG_ATTEN 0x3F
79
80/* DAVINCI_VC_REG12 bit fields */
81#define DAVINCI_VC_REG12_POWER_ALL_ON 0xFD
82#define DAVINCI_VC_REG12_POWER_ALL_OFF 0x00
83
84#define DAVINCI_VC_CELLS 2
85
86enum davinci_vc_cells {
87 DAVINCI_VC_VCIF_CELL,
88 DAVINCI_VC_CQ93VC_CELL,
89};
90
91struct davinci_vcif {
92 struct platform_device *pdev;
93 u32 dma_tx_channel;
94 u32 dma_rx_channel;
95 dma_addr_t dma_tx_addr;
96 dma_addr_t dma_rx_addr;
97};
98
99struct cq93vc {
100 struct platform_device *pdev;
101 struct snd_soc_codec *codec;
102 u32 sysclk;
103};
104
105struct davinci_vc;
106
107struct davinci_vc {
108 /* Device data */
109 struct device *dev;
110 struct platform_device *pdev;
111 struct clk *clk;
112
113 /* Memory resources */
114 void __iomem *base;
115 resource_size_t pbase;
116 size_t base_size;
117
118 /* MFD cells */
119 struct mfd_cell cells[DAVINCI_VC_CELLS];
120
121 /* Client devices */
122 struct davinci_vcif davinci_vcif;
123 struct cq93vc cq93vc;
124};
125
126#endif
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h
index d899dc0223ba..a95141eafce3 100644
--- a/include/linux/mfd/wm8350/audio.h
+++ b/include/linux/mfd/wm8350/audio.h
@@ -492,6 +492,8 @@
492 */ 492 */
493#define WM8350_JACK_L_LVL 0x0800 493#define WM8350_JACK_L_LVL 0x0800
494#define WM8350_JACK_R_LVL 0x0400 494#define WM8350_JACK_R_LVL 0x0400
495#define WM8350_JACK_MICSCD_LVL 0x0200
496#define WM8350_JACK_MICSD_LVL 0x0100
495 497
496/* 498/*
497 * WM8350 Platform setup 499 * WM8350 Platform setup
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h
index b06ff2846748..de79baee4925 100644
--- a/include/linux/mfd/wm8994/core.h
+++ b/include/linux/mfd/wm8994/core.h
@@ -15,14 +15,38 @@
15#ifndef __MFD_WM8994_CORE_H__ 15#ifndef __MFD_WM8994_CORE_H__
16#define __MFD_WM8994_CORE_H__ 16#define __MFD_WM8994_CORE_H__
17 17
18#include <linux/interrupt.h>
19
18struct regulator_dev; 20struct regulator_dev;
19struct regulator_bulk_data; 21struct regulator_bulk_data;
20 22
21#define WM8994_NUM_GPIO_REGS 11 23#define WM8994_NUM_GPIO_REGS 11
22#define WM8994_NUM_LDO_REGS 2 24#define WM8994_NUM_LDO_REGS 2
25#define WM8994_NUM_IRQ_REGS 2
26
27#define WM8994_IRQ_TEMP_SHUT 0
28#define WM8994_IRQ_MIC1_DET 1
29#define WM8994_IRQ_MIC1_SHRT 2
30#define WM8994_IRQ_MIC2_DET 3
31#define WM8994_IRQ_MIC2_SHRT 4
32#define WM8994_IRQ_FLL1_LOCK 5
33#define WM8994_IRQ_FLL2_LOCK 6
34#define WM8994_IRQ_SRC1_LOCK 7
35#define WM8994_IRQ_SRC2_LOCK 8
36#define WM8994_IRQ_AIF1DRC1_SIG_DET 9
37#define WM8994_IRQ_AIF1DRC2_SIG_DET 10
38#define WM8994_IRQ_AIF2DRC_SIG_DET 11
39#define WM8994_IRQ_FIFOS_ERR 12
40#define WM8994_IRQ_WSEQ_DONE 13
41#define WM8994_IRQ_DCS_DONE 14
42#define WM8994_IRQ_TEMP_WARN 15
43
44/* GPIOs in the chip are numbered from 1-11 */
45#define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN)
23 46
24struct wm8994 { 47struct wm8994 {
25 struct mutex io_lock; 48 struct mutex io_lock;
49 struct mutex irq_lock;
26 50
27 struct device *dev; 51 struct device *dev;
28 int (*read_dev)(struct wm8994 *wm8994, unsigned short reg, 52 int (*read_dev)(struct wm8994 *wm8994, unsigned short reg,
@@ -33,6 +57,11 @@ struct wm8994 {
33 void *control_data; 57 void *control_data;
34 58
35 int gpio_base; 59 int gpio_base;
60 int irq_base;
61
62 int irq;
63 u16 irq_masks_cur[WM8994_NUM_IRQ_REGS];
64 u16 irq_masks_cache[WM8994_NUM_IRQ_REGS];
36 65
37 /* Used over suspend/resume */ 66 /* Used over suspend/resume */
38 u16 ldo_regs[WM8994_NUM_LDO_REGS]; 67 u16 ldo_regs[WM8994_NUM_LDO_REGS];
@@ -51,4 +80,26 @@ int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
51int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg, 80int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
52 int count, u16 *buf); 81 int count, u16 *buf);
53 82
83
84/* Helper to save on boilerplate */
85static inline int wm8994_request_irq(struct wm8994 *wm8994, int irq,
86 irq_handler_t handler, const char *name,
87 void *data)
88{
89 if (!wm8994->irq_base)
90 return -EINVAL;
91 return request_threaded_irq(wm8994->irq_base + irq, NULL, handler,
92 IRQF_TRIGGER_RISING, name,
93 data);
94}
95static inline void wm8994_free_irq(struct wm8994 *wm8994, int irq, void *data)
96{
97 if (!wm8994->irq_base)
98 return;
99 free_irq(wm8994->irq_base + irq, data);
100}
101
102int wm8994_irq_init(struct wm8994 *wm8994);
103void wm8994_irq_exit(struct wm8994 *wm8994);
104
54#endif 105#endif
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 70d6a8687dc5..5c51f367c061 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -70,6 +70,7 @@ struct wm8994_pdata {
70 70
71 struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO]; 71 struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO];
72 72
73 int irq_base; /** Base IRQ number for WM8994, required for IRQs */
73 74
74 int num_drc_cfgs; 75 int num_drc_cfgs;
75 struct wm8994_drc_cfg *drc_cfgs; 76 struct wm8994_drc_cfg *drc_cfgs;
diff --git a/include/sound/jack.h b/include/sound/jack.h
index f236e426a706..d90b9fa32707 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -42,6 +42,11 @@ enum snd_jack_types {
42 SND_JACK_MECHANICAL = 0x0008, /* If detected separately */ 42 SND_JACK_MECHANICAL = 0x0008, /* If detected separately */
43 SND_JACK_VIDEOOUT = 0x0010, 43 SND_JACK_VIDEOOUT = 0x0010,
44 SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT, 44 SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
45
46 /* Kept separate from switches to facilitate implementation */
47 SND_JACK_BTN_0 = 0x4000,
48 SND_JACK_BTN_1 = 0x2000,
49 SND_JACK_BTN_2 = 0x1000,
45}; 50};
46 51
47struct snd_jack { 52struct snd_jack {
@@ -50,6 +55,7 @@ struct snd_jack {
50 int type; 55 int type;
51 const char *id; 56 const char *id;
52 char name[100]; 57 char name[100];
58 unsigned int key[3]; /* Keep in sync with definitions above */
53 void *private_data; 59 void *private_data;
54 void (*private_free)(struct snd_jack *); 60 void (*private_free)(struct snd_jack *);
55}; 61};
@@ -59,6 +65,8 @@ struct snd_jack {
59int snd_jack_new(struct snd_card *card, const char *id, int type, 65int snd_jack_new(struct snd_card *card, const char *id, int type,
60 struct snd_jack **jack); 66 struct snd_jack **jack);
61void snd_jack_set_parent(struct snd_jack *jack, struct device *parent); 67void snd_jack_set_parent(struct snd_jack *jack, struct device *parent);
68int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
69 int keytype);
62 70
63void snd_jack_report(struct snd_jack *jack, int status); 71void snd_jack_report(struct snd_jack *jack, int status);
64 72
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 0a0b019d41ad..377693a14385 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -182,6 +182,12 @@ struct snd_soc_dai_ops {
182 struct snd_soc_dai *); 182 struct snd_soc_dai *);
183 int (*trigger)(struct snd_pcm_substream *, int, 183 int (*trigger)(struct snd_pcm_substream *, int,
184 struct snd_soc_dai *); 184 struct snd_soc_dai *);
185 /*
186 * For hardware based FIFO caused delay reporting.
187 * Optional.
188 */
189 snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
190 struct snd_soc_dai *);
185}; 191};
186 192
187/* 193/*
@@ -215,7 +221,6 @@ struct snd_soc_dai {
215 unsigned int symmetric_rates:1; 221 unsigned int symmetric_rates:1;
216 222
217 /* DAI runtime info */ 223 /* DAI runtime info */
218 struct snd_pcm_runtime *runtime;
219 struct snd_soc_codec *codec; 224 struct snd_soc_codec *codec;
220 unsigned int active; 225 unsigned int active;
221 unsigned char pop_wait:1; 226 unsigned char pop_wait:1;
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index c0922a034223..d5d6ba862dfe 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -339,6 +339,8 @@ int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin);
339int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin); 339int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin);
340int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin); 340int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin);
341int snd_soc_dapm_sync(struct snd_soc_codec *codec); 341int snd_soc_dapm_sync(struct snd_soc_codec *codec);
342int snd_soc_dapm_force_enable_pin(struct snd_soc_codec *codec,
343 const char *pin);
342 344
343/* dapm widget types */ 345/* dapm widget types */
344enum snd_soc_dapm_type { 346enum snd_soc_dapm_type {
@@ -425,9 +427,8 @@ struct snd_soc_dapm_widget {
425 unsigned char connected:1; /* connected codec pin */ 427 unsigned char connected:1; /* connected codec pin */
426 unsigned char new:1; /* cnew complete */ 428 unsigned char new:1; /* cnew complete */
427 unsigned char ext:1; /* has external widgets */ 429 unsigned char ext:1; /* has external widgets */
428 unsigned char muted:1; /* muted for pop reduction */
429 unsigned char suspend:1; /* was active before suspend */ 430 unsigned char suspend:1; /* was active before suspend */
430 unsigned char pmdown:1; /* waiting for timeout */ 431 unsigned char force:1; /* force state */
431 432
432 int (*power_check)(struct snd_soc_dapm_widget *w); 433 int (*power_check)(struct snd_soc_dapm_widget *w);
433 434
diff --git a/include/sound/soc.h b/include/sound/soc.h
index a57fbfcd4c8f..4ab3dad4a9c9 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -15,6 +15,7 @@
15 15
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/types.h> 17#include <linux/types.h>
18#include <linux/notifier.h>
18#include <linux/workqueue.h> 19#include <linux/workqueue.h>
19#include <linux/interrupt.h> 20#include <linux/interrupt.h>
20#include <linux/kernel.h> 21#include <linux/kernel.h>
@@ -212,6 +213,7 @@ struct snd_soc_dai_mode;
212struct snd_soc_pcm_runtime; 213struct snd_soc_pcm_runtime;
213struct snd_soc_dai; 214struct snd_soc_dai;
214struct snd_soc_platform; 215struct snd_soc_platform;
216struct snd_soc_dai_link;
215struct snd_soc_codec; 217struct snd_soc_codec;
216struct soc_enum; 218struct soc_enum;
217struct snd_soc_ac97_ops; 219struct snd_soc_ac97_ops;
@@ -260,6 +262,10 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
260void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); 262void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
261int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, 263int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
262 struct snd_soc_jack_pin *pins); 264 struct snd_soc_jack_pin *pins);
265void snd_soc_jack_notifier_register(struct snd_soc_jack *jack,
266 struct notifier_block *nb);
267void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack,
268 struct notifier_block *nb);
263#ifdef CONFIG_GPIOLIB 269#ifdef CONFIG_GPIOLIB
264int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, 270int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
265 struct snd_soc_jack_gpio *gpios); 271 struct snd_soc_jack_gpio *gpios);
@@ -363,6 +369,7 @@ struct snd_soc_jack {
363 struct snd_soc_card *card; 369 struct snd_soc_card *card;
364 struct list_head pins; 370 struct list_head pins;
365 int status; 371 int status;
372 struct blocking_notifier_head notifier;
366}; 373};
367 374
368/* SoC PCM stream information */ 375/* SoC PCM stream information */
@@ -374,7 +381,7 @@ struct snd_soc_pcm_stream {
374 unsigned int rate_max; /* max rate */ 381 unsigned int rate_max; /* max rate */
375 unsigned int channels_min; /* min channels */ 382 unsigned int channels_min; /* min channels */
376 unsigned int channels_max; /* max channels */ 383 unsigned int channels_max; /* max channels */
377 unsigned int active:1; /* stream is in use */ 384 unsigned int active; /* stream is in use */
378 void *dma_data; /* used by platform code */ 385 void *dma_data; /* used by platform code */
379}; 386};
380 387
@@ -462,14 +469,21 @@ struct snd_soc_platform {
462 469
463 int (*probe)(struct platform_device *pdev); 470 int (*probe)(struct platform_device *pdev);
464 int (*remove)(struct platform_device *pdev); 471 int (*remove)(struct platform_device *pdev);
465 int (*suspend)(struct snd_soc_dai *dai); 472 int (*suspend)(struct snd_soc_dai_link *dai_link);
466 int (*resume)(struct snd_soc_dai *dai); 473 int (*resume)(struct snd_soc_dai_link *dai_link);
467 474
468 /* pcm creation and destruction */ 475 /* pcm creation and destruction */
469 int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, 476 int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
470 struct snd_pcm *); 477 struct snd_pcm *);
471 void (*pcm_free)(struct snd_pcm *); 478 void (*pcm_free)(struct snd_pcm *);
472 479
480 /*
481 * For platform caused delay reporting.
482 * Optional.
483 */
484 snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
485 struct snd_soc_dai *);
486
473 /* platform stream ops */ 487 /* platform stream ops */
474 struct snd_pcm_ops *pcm_ops; 488 struct snd_pcm_ops *pcm_ops;
475}; 489};
diff --git a/include/sound/tlv320dac33-plat.h b/include/sound/tlv320dac33-plat.h
index ac0665264bdf..3f428d53195b 100644
--- a/include/sound/tlv320dac33-plat.h
+++ b/include/sound/tlv320dac33-plat.h
@@ -15,6 +15,7 @@
15 15
16struct tlv320dac33_platform_data { 16struct tlv320dac33_platform_data {
17 int power_gpio; 17 int power_gpio;
18 int keep_bclk; /* Keep the BCLK running in FIFO modes */
18 u8 burst_bclkdiv; 19 u8 burst_bclkdiv;
19}; 20};
20 21
diff --git a/include/sound/wm8903.h b/include/sound/wm8903.h
new file mode 100644
index 000000000000..b4a0db2307ef
--- /dev/null
+++ b/include/sound/wm8903.h
@@ -0,0 +1,249 @@
1/*
2 * linux/sound/wm8903.h -- Platform data for WM8903
3 *
4 * Copyright 2010 Wolfson Microelectronics. PLC.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef __LINUX_SND_WM8903_H
12#define __LINUX_SND_WM8903_H
13
14/* Used to enable configuration of a GPIO to all zeros */
15#define WM8903_GPIO_NO_CONFIG 0x8000
16
17/*
18 * R6 (0x06) - Mic Bias Control 0
19 */
20#define WM8903_MICDET_HYST_ENA 0x0080 /* MICDET_HYST_ENA */
21#define WM8903_MICDET_HYST_ENA_MASK 0x0080 /* MICDET_HYST_ENA */
22#define WM8903_MICDET_HYST_ENA_SHIFT 7 /* MICDET_HYST_ENA */
23#define WM8903_MICDET_HYST_ENA_WIDTH 1 /* MICDET_HYST_ENA */
24#define WM8903_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */
25#define WM8903_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */
26#define WM8903_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */
27#define WM8903_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */
28#define WM8903_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */
29#define WM8903_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */
30#define WM8903_MICDET_ENA 0x0002 /* MICDET_ENA */
31#define WM8903_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */
32#define WM8903_MICDET_ENA_SHIFT 1 /* MICDET_ENA */
33#define WM8903_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
34#define WM8903_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */
35#define WM8903_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */
36#define WM8903_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
37#define WM8903_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
38
39/*
40 * R116 (0x74) - GPIO Control 1
41 */
42#define WM8903_GP1_FN_MASK 0x1F00 /* GP1_FN - [12:8] */
43#define WM8903_GP1_FN_SHIFT 8 /* GP1_FN - [12:8] */
44#define WM8903_GP1_FN_WIDTH 5 /* GP1_FN - [12:8] */
45#define WM8903_GP1_DIR 0x0080 /* GP1_DIR */
46#define WM8903_GP1_DIR_MASK 0x0080 /* GP1_DIR */
47#define WM8903_GP1_DIR_SHIFT 7 /* GP1_DIR */
48#define WM8903_GP1_DIR_WIDTH 1 /* GP1_DIR */
49#define WM8903_GP1_OP_CFG 0x0040 /* GP1_OP_CFG */
50#define WM8903_GP1_OP_CFG_MASK 0x0040 /* GP1_OP_CFG */
51#define WM8903_GP1_OP_CFG_SHIFT 6 /* GP1_OP_CFG */
52#define WM8903_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
53#define WM8903_GP1_IP_CFG 0x0020 /* GP1_IP_CFG */
54#define WM8903_GP1_IP_CFG_MASK 0x0020 /* GP1_IP_CFG */
55#define WM8903_GP1_IP_CFG_SHIFT 5 /* GP1_IP_CFG */
56#define WM8903_GP1_IP_CFG_WIDTH 1 /* GP1_IP_CFG */
57#define WM8903_GP1_LVL 0x0010 /* GP1_LVL */
58#define WM8903_GP1_LVL_MASK 0x0010 /* GP1_LVL */
59#define WM8903_GP1_LVL_SHIFT 4 /* GP1_LVL */
60#define WM8903_GP1_LVL_WIDTH 1 /* GP1_LVL */
61#define WM8903_GP1_PD 0x0008 /* GP1_PD */
62#define WM8903_GP1_PD_MASK 0x0008 /* GP1_PD */
63#define WM8903_GP1_PD_SHIFT 3 /* GP1_PD */
64#define WM8903_GP1_PD_WIDTH 1 /* GP1_PD */
65#define WM8903_GP1_PU 0x0004 /* GP1_PU */
66#define WM8903_GP1_PU_MASK 0x0004 /* GP1_PU */
67#define WM8903_GP1_PU_SHIFT 2 /* GP1_PU */
68#define WM8903_GP1_PU_WIDTH 1 /* GP1_PU */
69#define WM8903_GP1_INTMODE 0x0002 /* GP1_INTMODE */
70#define WM8903_GP1_INTMODE_MASK 0x0002 /* GP1_INTMODE */
71#define WM8903_GP1_INTMODE_SHIFT 1 /* GP1_INTMODE */
72#define WM8903_GP1_INTMODE_WIDTH 1 /* GP1_INTMODE */
73#define WM8903_GP1_DB 0x0001 /* GP1_DB */
74#define WM8903_GP1_DB_MASK 0x0001 /* GP1_DB */
75#define WM8903_GP1_DB_SHIFT 0 /* GP1_DB */
76#define WM8903_GP1_DB_WIDTH 1 /* GP1_DB */
77
78/*
79 * R117 (0x75) - GPIO Control 2
80 */
81#define WM8903_GP2_FN_MASK 0x1F00 /* GP2_FN - [12:8] */
82#define WM8903_GP2_FN_SHIFT 8 /* GP2_FN - [12:8] */
83#define WM8903_GP2_FN_WIDTH 5 /* GP2_FN - [12:8] */
84#define WM8903_GP2_DIR 0x0080 /* GP2_DIR */
85#define WM8903_GP2_DIR_MASK 0x0080 /* GP2_DIR */
86#define WM8903_GP2_DIR_SHIFT 7 /* GP2_DIR */
87#define WM8903_GP2_DIR_WIDTH 1 /* GP2_DIR */
88#define WM8903_GP2_OP_CFG 0x0040 /* GP2_OP_CFG */
89#define WM8903_GP2_OP_CFG_MASK 0x0040 /* GP2_OP_CFG */
90#define WM8903_GP2_OP_CFG_SHIFT 6 /* GP2_OP_CFG */
91#define WM8903_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
92#define WM8903_GP2_IP_CFG 0x0020 /* GP2_IP_CFG */
93#define WM8903_GP2_IP_CFG_MASK 0x0020 /* GP2_IP_CFG */
94#define WM8903_GP2_IP_CFG_SHIFT 5 /* GP2_IP_CFG */
95#define WM8903_GP2_IP_CFG_WIDTH 1 /* GP2_IP_CFG */
96#define WM8903_GP2_LVL 0x0010 /* GP2_LVL */
97#define WM8903_GP2_LVL_MASK 0x0010 /* GP2_LVL */
98#define WM8903_GP2_LVL_SHIFT 4 /* GP2_LVL */
99#define WM8903_GP2_LVL_WIDTH 1 /* GP2_LVL */
100#define WM8903_GP2_PD 0x0008 /* GP2_PD */
101#define WM8903_GP2_PD_MASK 0x0008 /* GP2_PD */
102#define WM8903_GP2_PD_SHIFT 3 /* GP2_PD */
103#define WM8903_GP2_PD_WIDTH 1 /* GP2_PD */
104#define WM8903_GP2_PU 0x0004 /* GP2_PU */
105#define WM8903_GP2_PU_MASK 0x0004 /* GP2_PU */
106#define WM8903_GP2_PU_SHIFT 2 /* GP2_PU */
107#define WM8903_GP2_PU_WIDTH 1 /* GP2_PU */
108#define WM8903_GP2_INTMODE 0x0002 /* GP2_INTMODE */
109#define WM8903_GP2_INTMODE_MASK 0x0002 /* GP2_INTMODE */
110#define WM8903_GP2_INTMODE_SHIFT 1 /* GP2_INTMODE */
111#define WM8903_GP2_INTMODE_WIDTH 1 /* GP2_INTMODE */
112#define WM8903_GP2_DB 0x0001 /* GP2_DB */
113#define WM8903_GP2_DB_MASK 0x0001 /* GP2_DB */
114#define WM8903_GP2_DB_SHIFT 0 /* GP2_DB */
115#define WM8903_GP2_DB_WIDTH 1 /* GP2_DB */
116
117/*
118 * R118 (0x76) - GPIO Control 3
119 */
120#define WM8903_GP3_FN_MASK 0x1F00 /* GP3_FN - [12:8] */
121#define WM8903_GP3_FN_SHIFT 8 /* GP3_FN - [12:8] */
122#define WM8903_GP3_FN_WIDTH 5 /* GP3_FN - [12:8] */
123#define WM8903_GP3_DIR 0x0080 /* GP3_DIR */
124#define WM8903_GP3_DIR_MASK 0x0080 /* GP3_DIR */
125#define WM8903_GP3_DIR_SHIFT 7 /* GP3_DIR */
126#define WM8903_GP3_DIR_WIDTH 1 /* GP3_DIR */
127#define WM8903_GP3_OP_CFG 0x0040 /* GP3_OP_CFG */
128#define WM8903_GP3_OP_CFG_MASK 0x0040 /* GP3_OP_CFG */
129#define WM8903_GP3_OP_CFG_SHIFT 6 /* GP3_OP_CFG */
130#define WM8903_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
131#define WM8903_GP3_IP_CFG 0x0020 /* GP3_IP_CFG */
132#define WM8903_GP3_IP_CFG_MASK 0x0020 /* GP3_IP_CFG */
133#define WM8903_GP3_IP_CFG_SHIFT 5 /* GP3_IP_CFG */
134#define WM8903_GP3_IP_CFG_WIDTH 1 /* GP3_IP_CFG */
135#define WM8903_GP3_LVL 0x0010 /* GP3_LVL */
136#define WM8903_GP3_LVL_MASK 0x0010 /* GP3_LVL */
137#define WM8903_GP3_LVL_SHIFT 4 /* GP3_LVL */
138#define WM8903_GP3_LVL_WIDTH 1 /* GP3_LVL */
139#define WM8903_GP3_PD 0x0008 /* GP3_PD */
140#define WM8903_GP3_PD_MASK 0x0008 /* GP3_PD */
141#define WM8903_GP3_PD_SHIFT 3 /* GP3_PD */
142#define WM8903_GP3_PD_WIDTH 1 /* GP3_PD */
143#define WM8903_GP3_PU 0x0004 /* GP3_PU */
144#define WM8903_GP3_PU_MASK 0x0004 /* GP3_PU */
145#define WM8903_GP3_PU_SHIFT 2 /* GP3_PU */
146#define WM8903_GP3_PU_WIDTH 1 /* GP3_PU */
147#define WM8903_GP3_INTMODE 0x0002 /* GP3_INTMODE */
148#define WM8903_GP3_INTMODE_MASK 0x0002 /* GP3_INTMODE */
149#define WM8903_GP3_INTMODE_SHIFT 1 /* GP3_INTMODE */
150#define WM8903_GP3_INTMODE_WIDTH 1 /* GP3_INTMODE */
151#define WM8903_GP3_DB 0x0001 /* GP3_DB */
152#define WM8903_GP3_DB_MASK 0x0001 /* GP3_DB */
153#define WM8903_GP3_DB_SHIFT 0 /* GP3_DB */
154#define WM8903_GP3_DB_WIDTH 1 /* GP3_DB */
155
156/*
157 * R119 (0x77) - GPIO Control 4
158 */
159#define WM8903_GP4_FN_MASK 0x1F00 /* GP4_FN - [12:8] */
160#define WM8903_GP4_FN_SHIFT 8 /* GP4_FN - [12:8] */
161#define WM8903_GP4_FN_WIDTH 5 /* GP4_FN - [12:8] */
162#define WM8903_GP4_DIR 0x0080 /* GP4_DIR */
163#define WM8903_GP4_DIR_MASK 0x0080 /* GP4_DIR */
164#define WM8903_GP4_DIR_SHIFT 7 /* GP4_DIR */
165#define WM8903_GP4_DIR_WIDTH 1 /* GP4_DIR */
166#define WM8903_GP4_OP_CFG 0x0040 /* GP4_OP_CFG */
167#define WM8903_GP4_OP_CFG_MASK 0x0040 /* GP4_OP_CFG */
168#define WM8903_GP4_OP_CFG_SHIFT 6 /* GP4_OP_CFG */
169#define WM8903_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
170#define WM8903_GP4_IP_CFG 0x0020 /* GP4_IP_CFG */
171#define WM8903_GP4_IP_CFG_MASK 0x0020 /* GP4_IP_CFG */
172#define WM8903_GP4_IP_CFG_SHIFT 5 /* GP4_IP_CFG */
173#define WM8903_GP4_IP_CFG_WIDTH 1 /* GP4_IP_CFG */
174#define WM8903_GP4_LVL 0x0010 /* GP4_LVL */
175#define WM8903_GP4_LVL_MASK 0x0010 /* GP4_LVL */
176#define WM8903_GP4_LVL_SHIFT 4 /* GP4_LVL */
177#define WM8903_GP4_LVL_WIDTH 1 /* GP4_LVL */
178#define WM8903_GP4_PD 0x0008 /* GP4_PD */
179#define WM8903_GP4_PD_MASK 0x0008 /* GP4_PD */
180#define WM8903_GP4_PD_SHIFT 3 /* GP4_PD */
181#define WM8903_GP4_PD_WIDTH 1 /* GP4_PD */
182#define WM8903_GP4_PU 0x0004 /* GP4_PU */
183#define WM8903_GP4_PU_MASK 0x0004 /* GP4_PU */
184#define WM8903_GP4_PU_SHIFT 2 /* GP4_PU */
185#define WM8903_GP4_PU_WIDTH 1 /* GP4_PU */
186#define WM8903_GP4_INTMODE 0x0002 /* GP4_INTMODE */
187#define WM8903_GP4_INTMODE_MASK 0x0002 /* GP4_INTMODE */
188#define WM8903_GP4_INTMODE_SHIFT 1 /* GP4_INTMODE */
189#define WM8903_GP4_INTMODE_WIDTH 1 /* GP4_INTMODE */
190#define WM8903_GP4_DB 0x0001 /* GP4_DB */
191#define WM8903_GP4_DB_MASK 0x0001 /* GP4_DB */
192#define WM8903_GP4_DB_SHIFT 0 /* GP4_DB */
193#define WM8903_GP4_DB_WIDTH 1 /* GP4_DB */
194
195/*
196 * R120 (0x78) - GPIO Control 5
197 */
198#define WM8903_GP5_FN_MASK 0x1F00 /* GP5_FN - [12:8] */
199#define WM8903_GP5_FN_SHIFT 8 /* GP5_FN - [12:8] */
200#define WM8903_GP5_FN_WIDTH 5 /* GP5_FN - [12:8] */
201#define WM8903_GP5_DIR 0x0080 /* GP5_DIR */
202#define WM8903_GP5_DIR_MASK 0x0080 /* GP5_DIR */
203#define WM8903_GP5_DIR_SHIFT 7 /* GP5_DIR */
204#define WM8903_GP5_DIR_WIDTH 1 /* GP5_DIR */
205#define WM8903_GP5_OP_CFG 0x0040 /* GP5_OP_CFG */
206#define WM8903_GP5_OP_CFG_MASK 0x0040 /* GP5_OP_CFG */
207#define WM8903_GP5_OP_CFG_SHIFT 6 /* GP5_OP_CFG */
208#define WM8903_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */
209#define WM8903_GP5_IP_CFG 0x0020 /* GP5_IP_CFG */
210#define WM8903_GP5_IP_CFG_MASK 0x0020 /* GP5_IP_CFG */
211#define WM8903_GP5_IP_CFG_SHIFT 5 /* GP5_IP_CFG */
212#define WM8903_GP5_IP_CFG_WIDTH 1 /* GP5_IP_CFG */
213#define WM8903_GP5_LVL 0x0010 /* GP5_LVL */
214#define WM8903_GP5_LVL_MASK 0x0010 /* GP5_LVL */
215#define WM8903_GP5_LVL_SHIFT 4 /* GP5_LVL */
216#define WM8903_GP5_LVL_WIDTH 1 /* GP5_LVL */
217#define WM8903_GP5_PD 0x0008 /* GP5_PD */
218#define WM8903_GP5_PD_MASK 0x0008 /* GP5_PD */
219#define WM8903_GP5_PD_SHIFT 3 /* GP5_PD */
220#define WM8903_GP5_PD_WIDTH 1 /* GP5_PD */
221#define WM8903_GP5_PU 0x0004 /* GP5_PU */
222#define WM8903_GP5_PU_MASK 0x0004 /* GP5_PU */
223#define WM8903_GP5_PU_SHIFT 2 /* GP5_PU */
224#define WM8903_GP5_PU_WIDTH 1 /* GP5_PU */
225#define WM8903_GP5_INTMODE 0x0002 /* GP5_INTMODE */
226#define WM8903_GP5_INTMODE_MASK 0x0002 /* GP5_INTMODE */
227#define WM8903_GP5_INTMODE_SHIFT 1 /* GP5_INTMODE */
228#define WM8903_GP5_INTMODE_WIDTH 1 /* GP5_INTMODE */
229#define WM8903_GP5_DB 0x0001 /* GP5_DB */
230#define WM8903_GP5_DB_MASK 0x0001 /* GP5_DB */
231#define WM8903_GP5_DB_SHIFT 0 /* GP5_DB */
232#define WM8903_GP5_DB_WIDTH 1 /* GP5_DB */
233
234struct wm8903_platform_data {
235 bool irq_active_low; /* Set if IRQ active low, default high */
236
237 /* Default register value for R6 (Mic bias), used to configure
238 * microphone detection. In conjunction with gpio_cfg this
239 * can be used to route the microphone status signals out onto
240 * the GPIOs for use with snd_soc_jack_add_gpios().
241 */
242 u16 micdet_cfg;
243
244 int micdet_delay; /* Delay after microphone detection (ms) */
245
246 u32 gpio_cfg[5]; /* Default register values for GPIO pin mux */
247};
248
249#endif
diff --git a/include/sound/wm8904.h b/include/sound/wm8904.h
index d66575a601be..898be3a8db9a 100644
--- a/include/sound/wm8904.h
+++ b/include/sound/wm8904.h
@@ -15,8 +15,111 @@
15#ifndef __MFD_WM8994_PDATA_H__ 15#ifndef __MFD_WM8994_PDATA_H__
16#define __MFD_WM8994_PDATA_H__ 16#define __MFD_WM8994_PDATA_H__
17 17
18#define WM8904_DRC_REGS 4 18/* Used to enable configuration of a GPIO to all zeros */
19#define WM8904_EQ_REGS 25 19#define WM8904_GPIO_NO_CONFIG 0x8000
20
21/*
22 * R6 (0x06) - Mic Bias Control 0
23 */
24#define WM8904_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */
25#define WM8904_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */
26#define WM8904_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */
27#define WM8904_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */
28#define WM8904_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */
29#define WM8904_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */
30#define WM8904_MICDET_ENA 0x0002 /* MICDET_ENA */
31#define WM8904_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */
32#define WM8904_MICDET_ENA_SHIFT 1 /* MICDET_ENA */
33#define WM8904_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
34#define WM8904_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */
35#define WM8904_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */
36#define WM8904_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
37#define WM8904_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
38
39/*
40 * R7 (0x07) - Mic Bias Control 1
41 */
42#define WM8904_MIC_DET_FILTER_ENA 0x8000 /* MIC_DET_FILTER_ENA */
43#define WM8904_MIC_DET_FILTER_ENA_MASK 0x8000 /* MIC_DET_FILTER_ENA */
44#define WM8904_MIC_DET_FILTER_ENA_SHIFT 15 /* MIC_DET_FILTER_ENA */
45#define WM8904_MIC_DET_FILTER_ENA_WIDTH 1 /* MIC_DET_FILTER_ENA */
46#define WM8904_MIC_SHORT_FILTER_ENA 0x4000 /* MIC_SHORT_FILTER_ENA */
47#define WM8904_MIC_SHORT_FILTER_ENA_MASK 0x4000 /* MIC_SHORT_FILTER_ENA */
48#define WM8904_MIC_SHORT_FILTER_ENA_SHIFT 14 /* MIC_SHORT_FILTER_ENA */
49#define WM8904_MIC_SHORT_FILTER_ENA_WIDTH 1 /* MIC_SHORT_FILTER_ENA */
50#define WM8904_MICBIAS_SEL_MASK 0x0007 /* MICBIAS_SEL - [2:0] */
51#define WM8904_MICBIAS_SEL_SHIFT 0 /* MICBIAS_SEL - [2:0] */
52#define WM8904_MICBIAS_SEL_WIDTH 3 /* MICBIAS_SEL - [2:0] */
53
54
55/*
56 * R121 (0x79) - GPIO Control 1
57 */
58#define WM8904_GPIO1_PU 0x0020 /* GPIO1_PU */
59#define WM8904_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */
60#define WM8904_GPIO1_PU_SHIFT 5 /* GPIO1_PU */
61#define WM8904_GPIO1_PU_WIDTH 1 /* GPIO1_PU */
62#define WM8904_GPIO1_PD 0x0010 /* GPIO1_PD */
63#define WM8904_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */
64#define WM8904_GPIO1_PD_SHIFT 4 /* GPIO1_PD */
65#define WM8904_GPIO1_PD_WIDTH 1 /* GPIO1_PD */
66#define WM8904_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
67#define WM8904_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */
68#define WM8904_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */
69
70/*
71 * R122 (0x7A) - GPIO Control 2
72 */
73#define WM8904_GPIO2_PU 0x0020 /* GPIO2_PU */
74#define WM8904_GPIO2_PU_MASK 0x0020 /* GPIO2_PU */
75#define WM8904_GPIO2_PU_SHIFT 5 /* GPIO2_PU */
76#define WM8904_GPIO2_PU_WIDTH 1 /* GPIO2_PU */
77#define WM8904_GPIO2_PD 0x0010 /* GPIO2_PD */
78#define WM8904_GPIO2_PD_MASK 0x0010 /* GPIO2_PD */
79#define WM8904_GPIO2_PD_SHIFT 4 /* GPIO2_PD */
80#define WM8904_GPIO2_PD_WIDTH 1 /* GPIO2_PD */
81#define WM8904_GPIO2_SEL_MASK 0x000F /* GPIO2_SEL - [3:0] */
82#define WM8904_GPIO2_SEL_SHIFT 0 /* GPIO2_SEL - [3:0] */
83#define WM8904_GPIO2_SEL_WIDTH 4 /* GPIO2_SEL - [3:0] */
84
85/*
86 * R123 (0x7B) - GPIO Control 3
87 */
88#define WM8904_GPIO3_PU 0x0020 /* GPIO3_PU */
89#define WM8904_GPIO3_PU_MASK 0x0020 /* GPIO3_PU */
90#define WM8904_GPIO3_PU_SHIFT 5 /* GPIO3_PU */
91#define WM8904_GPIO3_PU_WIDTH 1 /* GPIO3_PU */
92#define WM8904_GPIO3_PD 0x0010 /* GPIO3_PD */
93#define WM8904_GPIO3_PD_MASK 0x0010 /* GPIO3_PD */
94#define WM8904_GPIO3_PD_SHIFT 4 /* GPIO3_PD */
95#define WM8904_GPIO3_PD_WIDTH 1 /* GPIO3_PD */
96#define WM8904_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */
97#define WM8904_GPIO3_SEL_SHIFT 0 /* GPIO3_SEL - [3:0] */
98#define WM8904_GPIO3_SEL_WIDTH 4 /* GPIO3_SEL - [3:0] */
99
100/*
101 * R124 (0x7C) - GPIO Control 4
102 */
103#define WM8904_GPI7_ENA 0x0200 /* GPI7_ENA */
104#define WM8904_GPI7_ENA_MASK 0x0200 /* GPI7_ENA */
105#define WM8904_GPI7_ENA_SHIFT 9 /* GPI7_ENA */
106#define WM8904_GPI7_ENA_WIDTH 1 /* GPI7_ENA */
107#define WM8904_GPI8_ENA 0x0100 /* GPI8_ENA */
108#define WM8904_GPI8_ENA_MASK 0x0100 /* GPI8_ENA */
109#define WM8904_GPI8_ENA_SHIFT 8 /* GPI8_ENA */
110#define WM8904_GPI8_ENA_WIDTH 1 /* GPI8_ENA */
111#define WM8904_GPIO_BCLK_MODE_ENA 0x0080 /* GPIO_BCLK_MODE_ENA */
112#define WM8904_GPIO_BCLK_MODE_ENA_MASK 0x0080 /* GPIO_BCLK_MODE_ENA */
113#define WM8904_GPIO_BCLK_MODE_ENA_SHIFT 7 /* GPIO_BCLK_MODE_ENA */
114#define WM8904_GPIO_BCLK_MODE_ENA_WIDTH 1 /* GPIO_BCLK_MODE_ENA */
115#define WM8904_GPIO_BCLK_SEL_MASK 0x000F /* GPIO_BCLK_SEL - [3:0] */
116#define WM8904_GPIO_BCLK_SEL_SHIFT 0 /* GPIO_BCLK_SEL - [3:0] */
117#define WM8904_GPIO_BCLK_SEL_WIDTH 4 /* GPIO_BCLK_SEL - [3:0] */
118
119#define WM8904_MIC_REGS 2
120#define WM8904_GPIO_REGS 4
121#define WM8904_DRC_REGS 4
122#define WM8904_EQ_REGS 25
20 123
21/** 124/**
22 * DRC configurations are specified with a label and a set of register 125 * DRC configurations are specified with a label and a set of register
@@ -52,6 +155,9 @@ struct wm8904_pdata {
52 155
53 int num_retune_mobile_cfgs; 156 int num_retune_mobile_cfgs;
54 struct wm8904_retune_mobile_cfg *retune_mobile_cfgs; 157 struct wm8904_retune_mobile_cfg *retune_mobile_cfgs;
158
159 u32 gpio_cfg[WM8904_GPIO_REGS];
160 u32 mic_cfg[WM8904_MIC_REGS];
55}; 161};
56 162
57#endif 163#endif
diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h
new file mode 100644
index 000000000000..74e9a95529c5
--- /dev/null
+++ b/include/sound/wm8960.h
@@ -0,0 +1,24 @@
1/*
2 * wm8960.h -- WM8960 Soc Audio driver platform data
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _WM8960_PDATA_H
10#define _WM8960_PDATA_H
11
12#define WM8960_DRES_400R 0
13#define WM8960_DRES_200R 1
14#define WM8960_DRES_600R 2
15#define WM8960_DRES_150R 3
16#define WM8960_DRES_MAX 3
17
18struct wm8960_data {
19 bool capless; /* Headphone outputs configured in capless mode */
20
21 int dres; /* Discharge resistance for headphone outputs */
22};
23
24#endif
diff --git a/sound/core/jack.c b/sound/core/jack.c
index f705eec7372a..3813e7b04d05 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -23,7 +23,7 @@
23#include <sound/jack.h> 23#include <sound/jack.h>
24#include <sound/core.h> 24#include <sound/core.h>
25 25
26static int jack_types[] = { 26static int jack_switch_types[] = {
27 SW_HEADPHONE_INSERT, 27 SW_HEADPHONE_INSERT,
28 SW_MICROPHONE_INSERT, 28 SW_MICROPHONE_INSERT,
29 SW_LINEOUT_INSERT, 29 SW_LINEOUT_INSERT,
@@ -55,7 +55,7 @@ static int snd_jack_dev_register(struct snd_device *device)
55{ 55{
56 struct snd_jack *jack = device->device_data; 56 struct snd_jack *jack = device->device_data;
57 struct snd_card *card = device->card; 57 struct snd_card *card = device->card;
58 int err; 58 int err, i;
59 59
60 snprintf(jack->name, sizeof(jack->name), "%s %s", 60 snprintf(jack->name, sizeof(jack->name), "%s %s",
61 card->shortname, jack->id); 61 card->shortname, jack->id);
@@ -65,6 +65,19 @@ static int snd_jack_dev_register(struct snd_device *device)
65 if (!jack->input_dev->dev.parent) 65 if (!jack->input_dev->dev.parent)
66 jack->input_dev->dev.parent = snd_card_get_device_link(card); 66 jack->input_dev->dev.parent = snd_card_get_device_link(card);
67 67
68 /* Add capabilities for any keys that are enabled */
69 for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
70 int testbit = SND_JACK_BTN_0 >> i;
71
72 if (!(jack->type & testbit))
73 continue;
74
75 if (!jack->key[i])
76 jack->key[i] = BTN_0 + i;
77
78 input_set_capability(jack->input_dev, EV_KEY, jack->key[i]);
79 }
80
68 err = input_register_device(jack->input_dev); 81 err = input_register_device(jack->input_dev);
69 if (err == 0) 82 if (err == 0)
70 jack->registered = 1; 83 jack->registered = 1;
@@ -112,10 +125,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
112 125
113 jack->type = type; 126 jack->type = type;
114 127
115 for (i = 0; i < ARRAY_SIZE(jack_types); i++) 128 for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++)
116 if (type & (1 << i)) 129 if (type & (1 << i))
117 input_set_capability(jack->input_dev, EV_SW, 130 input_set_capability(jack->input_dev, EV_SW,
118 jack_types[i]); 131 jack_switch_types[i]);
119 132
120 err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); 133 err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
121 if (err < 0) 134 if (err < 0)
@@ -151,6 +164,43 @@ void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
151EXPORT_SYMBOL(snd_jack_set_parent); 164EXPORT_SYMBOL(snd_jack_set_parent);
152 165
153/** 166/**
167 * snd_jack_set_key - Set a key mapping on a jack
168 *
169 * @jack: The jack to configure
170 * @type: Jack report type for this key
171 * @keytype: Input layer key type to be reported
172 *
173 * Map a SND_JACK_BTN_ button type to an input layer key, allowing
174 * reporting of keys on accessories via the jack abstraction. If no
175 * mapping is provided but keys are enabled in the jack type then
176 * BTN_n numeric buttons will be reported.
177 *
178 * Note that this is intended to be use by simple devices with small
179 * numbers of keys that can be reported. It is also possible to
180 * access the input device directly - devices with complex input
181 * capabilities on accessories should consider doing this rather than
182 * using this abstraction.
183 *
184 * This function may only be called prior to registration of the jack.
185 */
186int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
187 int keytype)
188{
189 int key = fls(SND_JACK_BTN_0) - fls(type);
190
191 WARN_ON(jack->registered);
192
193 if (!keytype || key >= ARRAY_SIZE(jack->key))
194 return -EINVAL;
195
196 jack->type |= type;
197 jack->key[key] = keytype;
198
199 return 0;
200}
201EXPORT_SYMBOL(snd_jack_set_key);
202
203/**
154 * snd_jack_report - Report the current status of a jack 204 * snd_jack_report - Report the current status of a jack
155 * 205 *
156 * @jack: The jack to report status for 206 * @jack: The jack to report status for
@@ -163,10 +213,19 @@ void snd_jack_report(struct snd_jack *jack, int status)
163 if (!jack) 213 if (!jack)
164 return; 214 return;
165 215
166 for (i = 0; i < ARRAY_SIZE(jack_types); i++) { 216 for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
217 int testbit = SND_JACK_BTN_0 >> i;
218
219 if (jack->type & testbit)
220 input_report_key(jack->input_dev, jack->key[i],
221 status & testbit);
222 }
223
224 for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
167 int testbit = 1 << i; 225 int testbit = 1 << i;
168 if (jack->type & testbit) 226 if (jack->type & testbit)
169 input_report_switch(jack->input_dev, jack_types[i], 227 input_report_switch(jack->input_dev,
228 jack_switch_types[i],
170 status & testbit); 229 status & testbit);
171 } 230 }
172 231
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index 3e6628c8e665..f6b3cc04b34b 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -415,9 +415,12 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
415} 415}
416 416
417#ifdef CONFIG_PM 417#ifdef CONFIG_PM
418static int atmel_pcm_suspend(struct snd_soc_dai *dai) 418static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
419{ 419{
420 struct snd_pcm_runtime *runtime = dai->runtime; 420 struct snd_pcm *pcm = dai_link->pcm;
421 struct snd_pcm_str *stream = &pcm->streams[0];
422 struct snd_pcm_substream *substream = stream->substream;
423 struct snd_pcm_runtime *runtime = substream->runtime;
421 struct atmel_runtime_data *prtd; 424 struct atmel_runtime_data *prtd;
422 struct atmel_pcm_dma_params *params; 425 struct atmel_pcm_dma_params *params;
423 426
@@ -439,9 +442,12 @@ static int atmel_pcm_suspend(struct snd_soc_dai *dai)
439 return 0; 442 return 0;
440} 443}
441 444
442static int atmel_pcm_resume(struct snd_soc_dai *dai) 445static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)
443{ 446{
444 struct snd_pcm_runtime *runtime = dai->runtime; 447 struct snd_pcm *pcm = dai_link->pcm;
448 struct snd_pcm_str *stream = &pcm->streams[0];
449 struct snd_pcm_substream *substream = stream->substream;
450 struct snd_pcm_runtime *runtime = substream->runtime;
445 struct atmel_runtime_data *prtd; 451 struct atmel_runtime_data *prtd;
446 struct atmel_pcm_dma_params *params; 452 struct atmel_pcm_dma_params *params;
447 453
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 97f1a251e446..8ef25025f3dc 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -49,13 +49,14 @@ config SND_BF5XX_SOC_AD1836
49 help 49 help
50 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. 50 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
51 51
52config SND_BF5XX_SOC_AD1938 52config SND_BF5XX_SOC_AD193X
53 tristate "SoC AD1938 Audio support for Blackfin" 53 tristate "SoC AD193X Audio support for Blackfin"
54 depends on SND_BF5XX_TDM 54 depends on SND_BF5XX_TDM
55 select SND_BF5XX_SOC_TDM 55 select SND_BF5XX_SOC_TDM
56 select SND_SOC_AD1938 56 select SND_SOC_AD193X
57 help 57 help
58 Say Y if you want to add support for AD1938 codec on Blackfin. 58 Say Y if you want to add support for AD193X codec on Blackfin.
59 This driver supports AD1936, AD1937, AD1938 and AD1939.
59 60
60config SND_BF5XX_AC97 61config SND_BF5XX_AC97
61 tristate "SoC AC97 Audio for the ADI BF5xx chip" 62 tristate "SoC AC97 Audio for the ADI BF5xx chip"
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 87e30423912f..49af3f32aec8 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -20,10 +20,10 @@ snd-ad1836-objs := bf5xx-ad1836.o
20snd-ad1980-objs := bf5xx-ad1980.o 20snd-ad1980-objs := bf5xx-ad1980.o
21snd-ssm2602-objs := bf5xx-ssm2602.o 21snd-ssm2602-objs := bf5xx-ssm2602.o
22snd-ad73311-objs := bf5xx-ad73311.o 22snd-ad73311-objs := bf5xx-ad73311.o
23snd-ad1938-objs := bf5xx-ad1938.o 23snd-ad193x-objs := bf5xx-ad193x.o
24 24
25obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o 25obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o
26obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o 26obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
27obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o 27obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
28obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o 28obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
29obj-$(CONFIG_SND_BF5XX_SOC_AD1938) += snd-ad1938.o 29obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o
diff --git a/sound/soc/blackfin/bf5xx-ad1938.c b/sound/soc/blackfin/bf5xx-ad193x.c
index 2ef1e5013b8c..b8c9060cfd8e 100644
--- a/sound/soc/blackfin/bf5xx-ad1938.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -1,9 +1,9 @@
1/* 1/*
2 * File: sound/soc/blackfin/bf5xx-ad1938.c 2 * File: sound/soc/blackfin/bf5xx-ad193x.c
3 * Author: Barry Song <Barry.Song@analog.com> 3 * Author: Barry Song <Barry.Song@analog.com>
4 * 4 *
5 * Created: Thur June 4 2009 5 * Created: Thur June 4 2009
6 * Description: Board driver for ad1938 sound chip 6 * Description: Board driver for ad193x sound chip
7 * 7 *
8 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 8 * Bugs: Enter bugs at http://blackfin.uclinux.org/
9 * 9 *
@@ -38,15 +38,15 @@
38#include <asm/dma.h> 38#include <asm/dma.h>
39#include <asm/portmux.h> 39#include <asm/portmux.h>
40 40
41#include "../codecs/ad1938.h" 41#include "../codecs/ad193x.h"
42#include "bf5xx-sport.h" 42#include "bf5xx-sport.h"
43 43
44#include "bf5xx-tdm-pcm.h" 44#include "bf5xx-tdm-pcm.h"
45#include "bf5xx-tdm.h" 45#include "bf5xx-tdm.h"
46 46
47static struct snd_soc_card bf5xx_ad1938; 47static struct snd_soc_card bf5xx_ad193x;
48 48
49static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream) 49static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream)
50{ 50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data; 51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -55,7 +55,7 @@ static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream)
55 return 0; 55 return 0;
56} 56}
57 57
58static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream, 58static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
59 struct snd_pcm_hw_params *params) 59 struct snd_pcm_hw_params *params)
60{ 60{
61 struct snd_soc_pcm_runtime *rtd = substream->private_data; 61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -89,61 +89,61 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
89 return 0; 89 return 0;
90} 90}
91 91
92static struct snd_soc_ops bf5xx_ad1938_ops = { 92static struct snd_soc_ops bf5xx_ad193x_ops = {
93 .startup = bf5xx_ad1938_startup, 93 .startup = bf5xx_ad193x_startup,
94 .hw_params = bf5xx_ad1938_hw_params, 94 .hw_params = bf5xx_ad193x_hw_params,
95}; 95};
96 96
97static struct snd_soc_dai_link bf5xx_ad1938_dai = { 97static struct snd_soc_dai_link bf5xx_ad193x_dai = {
98 .name = "ad1938", 98 .name = "ad193x",
99 .stream_name = "AD1938", 99 .stream_name = "AD193X",
100 .cpu_dai = &bf5xx_tdm_dai, 100 .cpu_dai = &bf5xx_tdm_dai,
101 .codec_dai = &ad1938_dai, 101 .codec_dai = &ad193x_dai,
102 .ops = &bf5xx_ad1938_ops, 102 .ops = &bf5xx_ad193x_ops,
103}; 103};
104 104
105static struct snd_soc_card bf5xx_ad1938 = { 105static struct snd_soc_card bf5xx_ad193x = {
106 .name = "bf5xx_ad1938", 106 .name = "bf5xx_ad193x",
107 .platform = &bf5xx_tdm_soc_platform, 107 .platform = &bf5xx_tdm_soc_platform,
108 .dai_link = &bf5xx_ad1938_dai, 108 .dai_link = &bf5xx_ad193x_dai,
109 .num_links = 1, 109 .num_links = 1,
110}; 110};
111 111
112static struct snd_soc_device bf5xx_ad1938_snd_devdata = { 112static struct snd_soc_device bf5xx_ad193x_snd_devdata = {
113 .card = &bf5xx_ad1938, 113 .card = &bf5xx_ad193x,
114 .codec_dev = &soc_codec_dev_ad1938, 114 .codec_dev = &soc_codec_dev_ad193x,
115}; 115};
116 116
117static struct platform_device *bfxx_ad1938_snd_device; 117static struct platform_device *bfxx_ad193x_snd_device;
118 118
119static int __init bf5xx_ad1938_init(void) 119static int __init bf5xx_ad193x_init(void)
120{ 120{
121 int ret; 121 int ret;
122 122
123 bfxx_ad1938_snd_device = platform_device_alloc("soc-audio", -1); 123 bfxx_ad193x_snd_device = platform_device_alloc("soc-audio", -1);
124 if (!bfxx_ad1938_snd_device) 124 if (!bfxx_ad193x_snd_device)
125 return -ENOMEM; 125 return -ENOMEM;
126 126
127 platform_set_drvdata(bfxx_ad1938_snd_device, &bf5xx_ad1938_snd_devdata); 127 platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata);
128 bf5xx_ad1938_snd_devdata.dev = &bfxx_ad1938_snd_device->dev; 128 bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev;
129 ret = platform_device_add(bfxx_ad1938_snd_device); 129 ret = platform_device_add(bfxx_ad193x_snd_device);
130 130
131 if (ret) 131 if (ret)
132 platform_device_put(bfxx_ad1938_snd_device); 132 platform_device_put(bfxx_ad193x_snd_device);
133 133
134 return ret; 134 return ret;
135} 135}
136 136
137static void __exit bf5xx_ad1938_exit(void) 137static void __exit bf5xx_ad193x_exit(void)
138{ 138{
139 platform_device_unregister(bfxx_ad1938_snd_device); 139 platform_device_unregister(bfxx_ad193x_snd_device);
140} 140}
141 141
142module_init(bf5xx_ad1938_init); 142module_init(bf5xx_ad193x_init);
143module_exit(bf5xx_ad1938_exit); 143module_exit(bf5xx_ad193x_exit);
144 144
145/* Module information */ 145/* Module information */
146MODULE_AUTHOR("Barry Song"); 146MODULE_AUTHOR("Barry Song");
147MODULE_DESCRIPTION("ALSA SoC AD1938 board driver"); 147MODULE_DESCRIPTION("ALSA SoC AD193X board driver");
148MODULE_LICENSE("GPL"); 148MODULE_LICENSE("GPL");
149 149
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index 2e63dea73e9c..a86e8cc0b2d3 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -34,33 +34,7 @@
34#include <linux/wait.h> 34#include <linux/wait.h>
35#include <linux/workqueue.h> 35#include <linux/workqueue.h>
36#include <asm/dma.h> 36#include <asm/dma.h>
37 37#include <asm/bfin_sport.h>
38struct sport_register {
39 u16 tcr1; u16 reserved0;
40 u16 tcr2; u16 reserved1;
41 u16 tclkdiv; u16 reserved2;
42 u16 tfsdiv; u16 reserved3;
43 u32 tx;
44 u32 reserved_l0;
45 u32 rx;
46 u32 reserved_l1;
47 u16 rcr1; u16 reserved4;
48 u16 rcr2; u16 reserved5;
49 u16 rclkdiv; u16 reserved6;
50 u16 rfsdiv; u16 reserved7;
51 u16 stat; u16 reserved8;
52 u16 chnl; u16 reserved9;
53 u16 mcmc1; u16 reserved10;
54 u16 mcmc2; u16 reserved11;
55 u32 mtcs0;
56 u32 mtcs1;
57 u32 mtcs2;
58 u32 mtcs3;
59 u32 mrcs0;
60 u32 mrcs1;
61 u32 mrcs2;
62 u32 mrcs3;
63};
64 38
65#define DESC_ELEMENT_COUNT 9 39#define DESC_ELEMENT_COUNT 9
66 40
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 1743d565e996..bc0ab47e156b 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -13,7 +13,7 @@ config SND_SOC_ALL_CODECS
13 select SND_SOC_L3 13 select SND_SOC_L3
14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS 14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
15 select SND_SOC_AD1836 if SPI_MASTER 15 select SND_SOC_AD1836 if SPI_MASTER
16 select SND_SOC_AD1938 if SPI_MASTER 16 select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS 17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
18 select SND_SOC_ADS117X 18 select SND_SOC_ADS117X
19 select SND_SOC_AD73311 if I2C 19 select SND_SOC_AD73311 if I2C
@@ -21,6 +21,7 @@ config SND_SOC_ALL_CODECS
21 select SND_SOC_AK4535 if I2C 21 select SND_SOC_AK4535 if I2C
22 select SND_SOC_AK4642 if I2C 22 select SND_SOC_AK4642 if I2C
23 select SND_SOC_AK4671 if I2C 23 select SND_SOC_AK4671 if I2C
24 select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
24 select SND_SOC_CS4270 if I2C 25 select SND_SOC_CS4270 if I2C
25 select SND_SOC_MAX9877 if I2C 26 select SND_SOC_MAX9877 if I2C
26 select SND_SOC_DA7210 if I2C 27 select SND_SOC_DA7210 if I2C
@@ -34,6 +35,7 @@ config SND_SOC_ALL_CODECS
34 select SND_SOC_TPA6130A2 if I2C 35 select SND_SOC_TPA6130A2 if I2C
35 select SND_SOC_TLV320DAC33 if I2C 36 select SND_SOC_TLV320DAC33 if I2C
36 select SND_SOC_TWL4030 if TWL4030_CORE 37 select SND_SOC_TWL4030 if TWL4030_CORE
38 select SND_SOC_TWL6040 if TWL4030_CORE
37 select SND_SOC_UDA134X 39 select SND_SOC_UDA134X
38 select SND_SOC_UDA1380 if I2C 40 select SND_SOC_UDA1380 if I2C
39 select SND_SOC_WM2000 if I2C 41 select SND_SOC_WM2000 if I2C
@@ -90,7 +92,7 @@ config SND_SOC_AC97_CODEC
90config SND_SOC_AD1836 92config SND_SOC_AD1836
91 tristate 93 tristate
92 94
93config SND_SOC_AD1938 95config SND_SOC_AD193X
94 tristate 96 tristate
95 97
96config SND_SOC_AD1980 98config SND_SOC_AD1980
@@ -114,6 +116,9 @@ config SND_SOC_AK4642
114config SND_SOC_AK4671 116config SND_SOC_AK4671
115 tristate 117 tristate
116 118
119config SND_SOC_CQ0093VC
120 tristate
121
117# Cirrus Logic CS4270 Codec 122# Cirrus Logic CS4270 Codec
118config SND_SOC_CS4270 123config SND_SOC_CS4270
119 tristate 124 tristate
@@ -164,6 +169,9 @@ config SND_SOC_TWL4030
164 select TWL4030_CODEC 169 select TWL4030_CODEC
165 tristate 170 tristate
166 171
172config SND_SOC_TWL6040
173 tristate
174
167config SND_SOC_UDA134X 175config SND_SOC_UDA134X
168 tristate 176 tristate
169 177
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index dd5ce6df6292..337904167358 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,6 +1,6 @@
1snd-soc-ac97-objs := ac97.o 1snd-soc-ac97-objs := ac97.o
2snd-soc-ad1836-objs := ad1836.o 2snd-soc-ad1836-objs := ad1836.o
3snd-soc-ad1938-objs := ad1938.o 3snd-soc-ad193x-objs := ad193x.o
4snd-soc-ad1980-objs := ad1980.o 4snd-soc-ad1980-objs := ad1980.o
5snd-soc-ad73311-objs := ad73311.o 5snd-soc-ad73311-objs := ad73311.o
6snd-soc-ads117x-objs := ads117x.o 6snd-soc-ads117x-objs := ads117x.o
@@ -8,6 +8,7 @@ snd-soc-ak4104-objs := ak4104.o
8snd-soc-ak4535-objs := ak4535.o 8snd-soc-ak4535-objs := ak4535.o
9snd-soc-ak4642-objs := ak4642.o 9snd-soc-ak4642-objs := ak4642.o
10snd-soc-ak4671-objs := ak4671.o 10snd-soc-ak4671-objs := ak4671.o
11snd-soc-cq93vc-objs := cq93vc.o
11snd-soc-cs4270-objs := cs4270.o 12snd-soc-cs4270-objs := cs4270.o
12snd-soc-cx20442-objs := cx20442.o 13snd-soc-cx20442-objs := cx20442.o
13snd-soc-da7210-objs := da7210.o 14snd-soc-da7210-objs := da7210.o
@@ -21,6 +22,7 @@ snd-soc-tlv320aic26-objs := tlv320aic26.o
21snd-soc-tlv320aic3x-objs := tlv320aic3x.o 22snd-soc-tlv320aic3x-objs := tlv320aic3x.o
22snd-soc-tlv320dac33-objs := tlv320dac33.o 23snd-soc-tlv320dac33-objs := tlv320dac33.o
23snd-soc-twl4030-objs := twl4030.o 24snd-soc-twl4030-objs := twl4030.o
25snd-soc-twl6040-objs := twl6040.o
24snd-soc-uda134x-objs := uda134x.o 26snd-soc-uda134x-objs := uda134x.o
25snd-soc-uda1380-objs := uda1380.o 27snd-soc-uda1380-objs := uda1380.o
26snd-soc-wm8350-objs := wm8350.o 28snd-soc-wm8350-objs := wm8350.o
@@ -62,7 +64,7 @@ snd-soc-wm2000-objs := wm2000.o
62 64
63obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 65obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
64obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o 66obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
65obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o 67obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
66obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 68obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
67obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 69obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
68obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o 70obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
@@ -70,6 +72,7 @@ obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
70obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 72obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
71obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 73obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
72obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o 74obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
75obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
73obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 76obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
74obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 77obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
75obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o 78obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
@@ -83,6 +86,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
83obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 86obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
84obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o 87obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
85obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o 88obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
89obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
86obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o 90obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
87obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 91obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
88obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o 92obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
deleted file mode 100644
index c233810d463d..000000000000
--- a/sound/soc/codecs/ad1938.c
+++ /dev/null
@@ -1,521 +0,0 @@
1/*
2 * File: sound/soc/codecs/ad1938.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: June 04 2009
6 * Description: Driver for AD1938 sound chip
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/init.h>
30#include <linux/module.h>
31#include <linux/kernel.h>
32#include <linux/device.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/initval.h>
37#include <sound/soc.h>
38#include <sound/tlv.h>
39#include <sound/soc-dapm.h>
40#include <linux/spi/spi.h>
41#include "ad1938.h"
42
43/* codec private data */
44struct ad1938_priv {
45 struct snd_soc_codec codec;
46 u8 reg_cache[AD1938_NUM_REGS];
47};
48
49/* ad1938 register cache & default register settings */
50static const u8 ad1938_reg[AD1938_NUM_REGS] = {
51 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
52};
53
54static struct snd_soc_codec *ad1938_codec;
55struct snd_soc_codec_device soc_codec_dev_ad1938;
56static int ad1938_register(struct ad1938_priv *ad1938);
57static void ad1938_unregister(struct ad1938_priv *ad1938);
58
59/*
60 * AD1938 volume/mute/de-emphasis etc. controls
61 */
62static const char *ad1938_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
63
64static const struct soc_enum ad1938_deemp_enum =
65 SOC_ENUM_SINGLE(AD1938_DAC_CTRL2, 1, 4, ad1938_deemp);
66
67static const struct snd_kcontrol_new ad1938_snd_controls[] = {
68 /* DAC volume control */
69 SOC_DOUBLE_R("DAC1 Volume", AD1938_DAC_L1_VOL,
70 AD1938_DAC_R1_VOL, 0, 0xFF, 1),
71 SOC_DOUBLE_R("DAC2 Volume", AD1938_DAC_L2_VOL,
72 AD1938_DAC_R2_VOL, 0, 0xFF, 1),
73 SOC_DOUBLE_R("DAC3 Volume", AD1938_DAC_L3_VOL,
74 AD1938_DAC_R3_VOL, 0, 0xFF, 1),
75 SOC_DOUBLE_R("DAC4 Volume", AD1938_DAC_L4_VOL,
76 AD1938_DAC_R4_VOL, 0, 0xFF, 1),
77
78 /* ADC switch control */
79 SOC_DOUBLE("ADC1 Switch", AD1938_ADC_CTRL0, AD1938_ADCL1_MUTE,
80 AD1938_ADCR1_MUTE, 1, 1),
81 SOC_DOUBLE("ADC2 Switch", AD1938_ADC_CTRL0, AD1938_ADCL2_MUTE,
82 AD1938_ADCR2_MUTE, 1, 1),
83
84 /* DAC switch control */
85 SOC_DOUBLE("DAC1 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL1_MUTE,
86 AD1938_DACR1_MUTE, 1, 1),
87 SOC_DOUBLE("DAC2 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL2_MUTE,
88 AD1938_DACR2_MUTE, 1, 1),
89 SOC_DOUBLE("DAC3 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL3_MUTE,
90 AD1938_DACR3_MUTE, 1, 1),
91 SOC_DOUBLE("DAC4 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL4_MUTE,
92 AD1938_DACR4_MUTE, 1, 1),
93
94 /* ADC high-pass filter */
95 SOC_SINGLE("ADC High Pass Filter Switch", AD1938_ADC_CTRL0,
96 AD1938_ADC_HIGHPASS_FILTER, 1, 0),
97
98 /* DAC de-emphasis */
99 SOC_ENUM("Playback Deemphasis", ad1938_deemp_enum),
100};
101
102static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = {
103 SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1),
104 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
105 SND_SOC_DAPM_SUPPLY("PLL_PWR", AD1938_PLL_CLK_CTRL0, 0, 1, NULL, 0),
106 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0),
107 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
108 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
109 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
110 SND_SOC_DAPM_OUTPUT("DAC4OUT"),
111 SND_SOC_DAPM_INPUT("ADC1IN"),
112 SND_SOC_DAPM_INPUT("ADC2IN"),
113};
114
115static const struct snd_soc_dapm_route audio_paths[] = {
116 { "DAC", NULL, "PLL_PWR" },
117 { "ADC", NULL, "PLL_PWR" },
118 { "DAC", NULL, "ADC_PWR" },
119 { "ADC", NULL, "ADC_PWR" },
120 { "DAC1OUT", "DAC1 Switch", "DAC" },
121 { "DAC2OUT", "DAC2 Switch", "DAC" },
122 { "DAC3OUT", "DAC3 Switch", "DAC" },
123 { "DAC4OUT", "DAC4 Switch", "DAC" },
124 { "ADC", "ADC1 Switch", "ADC1IN" },
125 { "ADC", "ADC2 Switch", "ADC2IN" },
126};
127
128/*
129 * DAI ops entries
130 */
131
132static int ad1938_mute(struct snd_soc_dai *dai, int mute)
133{
134 struct snd_soc_codec *codec = dai->codec;
135 int reg;
136
137 reg = snd_soc_read(codec, AD1938_DAC_CTRL2);
138 reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg &
139 (~AD1938_DAC_MASTER_MUTE);
140 snd_soc_write(codec, AD1938_DAC_CTRL2, reg);
141
142 return 0;
143}
144
145static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
146 unsigned int rx_mask, int slots, int width)
147{
148 struct snd_soc_codec *codec = dai->codec;
149 int dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1);
150 int adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2);
151
152 dac_reg &= ~AD1938_DAC_CHAN_MASK;
153 adc_reg &= ~AD1938_ADC_CHAN_MASK;
154
155 switch (slots) {
156 case 2:
157 dac_reg |= AD1938_DAC_2_CHANNELS << AD1938_DAC_CHAN_SHFT;
158 adc_reg |= AD1938_ADC_2_CHANNELS << AD1938_ADC_CHAN_SHFT;
159 break;
160 case 4:
161 dac_reg |= AD1938_DAC_4_CHANNELS << AD1938_DAC_CHAN_SHFT;
162 adc_reg |= AD1938_ADC_4_CHANNELS << AD1938_ADC_CHAN_SHFT;
163 break;
164 case 8:
165 dac_reg |= AD1938_DAC_8_CHANNELS << AD1938_DAC_CHAN_SHFT;
166 adc_reg |= AD1938_ADC_8_CHANNELS << AD1938_ADC_CHAN_SHFT;
167 break;
168 case 16:
169 dac_reg |= AD1938_DAC_16_CHANNELS << AD1938_DAC_CHAN_SHFT;
170 adc_reg |= AD1938_ADC_16_CHANNELS << AD1938_ADC_CHAN_SHFT;
171 break;
172 default:
173 return -EINVAL;
174 }
175
176 snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg);
177 snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg);
178
179 return 0;
180}
181
182static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
183 unsigned int fmt)
184{
185 struct snd_soc_codec *codec = codec_dai->codec;
186 int adc_reg, dac_reg;
187
188 adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2);
189 dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1);
190
191 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
192 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
193 */
194 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
195 case SND_SOC_DAIFMT_I2S:
196 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
197 adc_reg |= AD1938_ADC_SERFMT_TDM;
198 break;
199 case SND_SOC_DAIFMT_DSP_A:
200 adc_reg &= ~AD1938_ADC_SERFMT_MASK;
201 adc_reg |= AD1938_ADC_SERFMT_AUX;
202 break;
203 default:
204 return -EINVAL;
205 }
206
207 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
208 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
209 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
210 adc_reg &= ~AD1938_ADC_BCLK_INV;
211 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
212 dac_reg &= ~AD1938_DAC_BCLK_INV;
213 break;
214 case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
215 adc_reg |= AD1938_ADC_LEFT_HIGH;
216 adc_reg &= ~AD1938_ADC_BCLK_INV;
217 dac_reg |= AD1938_DAC_LEFT_HIGH;
218 dac_reg &= ~AD1938_DAC_BCLK_INV;
219 break;
220 case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
221 adc_reg &= ~AD1938_ADC_LEFT_HIGH;
222 adc_reg |= AD1938_ADC_BCLK_INV;
223 dac_reg &= ~AD1938_DAC_LEFT_HIGH;
224 dac_reg |= AD1938_DAC_BCLK_INV;
225 break;
226
227 case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
228 adc_reg |= AD1938_ADC_LEFT_HIGH;
229 adc_reg |= AD1938_ADC_BCLK_INV;
230 dac_reg |= AD1938_DAC_LEFT_HIGH;
231 dac_reg |= AD1938_DAC_BCLK_INV;
232 break;
233 default:
234 return -EINVAL;
235 }
236
237 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
238 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
239 adc_reg |= AD1938_ADC_LCR_MASTER;
240 adc_reg |= AD1938_ADC_BCLK_MASTER;
241 dac_reg |= AD1938_DAC_LCR_MASTER;
242 dac_reg |= AD1938_DAC_BCLK_MASTER;
243 break;
244 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
245 adc_reg |= AD1938_ADC_LCR_MASTER;
246 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
247 dac_reg |= AD1938_DAC_LCR_MASTER;
248 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
249 break;
250 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
251 adc_reg &= ~AD1938_ADC_LCR_MASTER;
252 adc_reg |= AD1938_ADC_BCLK_MASTER;
253 dac_reg &= ~AD1938_DAC_LCR_MASTER;
254 dac_reg |= AD1938_DAC_BCLK_MASTER;
255 break;
256 case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
257 adc_reg &= ~AD1938_ADC_LCR_MASTER;
258 adc_reg &= ~AD1938_ADC_BCLK_MASTER;
259 dac_reg &= ~AD1938_DAC_LCR_MASTER;
260 dac_reg &= ~AD1938_DAC_BCLK_MASTER;
261 break;
262 default:
263 return -EINVAL;
264 }
265
266 snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg);
267 snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg);
268
269 return 0;
270}
271
272static int ad1938_hw_params(struct snd_pcm_substream *substream,
273 struct snd_pcm_hw_params *params,
274 struct snd_soc_dai *dai)
275{
276 int word_len = 0, reg = 0;
277
278 struct snd_soc_pcm_runtime *rtd = substream->private_data;
279 struct snd_soc_device *socdev = rtd->socdev;
280 struct snd_soc_codec *codec = socdev->card->codec;
281
282 /* bit size */
283 switch (params_format(params)) {
284 case SNDRV_PCM_FORMAT_S16_LE:
285 word_len = 3;
286 break;
287 case SNDRV_PCM_FORMAT_S20_3LE:
288 word_len = 1;
289 break;
290 case SNDRV_PCM_FORMAT_S24_LE:
291 case SNDRV_PCM_FORMAT_S32_LE:
292 word_len = 0;
293 break;
294 }
295
296 reg = snd_soc_read(codec, AD1938_DAC_CTRL2);
297 reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len;
298 snd_soc_write(codec, AD1938_DAC_CTRL2, reg);
299
300 reg = snd_soc_read(codec, AD1938_ADC_CTRL1);
301 reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len;
302 snd_soc_write(codec, AD1938_ADC_CTRL1, reg);
303
304 return 0;
305}
306
307static int __devinit ad1938_spi_probe(struct spi_device *spi)
308{
309 struct snd_soc_codec *codec;
310 struct ad1938_priv *ad1938;
311
312 ad1938 = kzalloc(sizeof(struct ad1938_priv), GFP_KERNEL);
313 if (ad1938 == NULL)
314 return -ENOMEM;
315
316 codec = &ad1938->codec;
317 codec->control_data = spi;
318 codec->dev = &spi->dev;
319
320 dev_set_drvdata(&spi->dev, ad1938);
321
322 return ad1938_register(ad1938);
323}
324
325static int __devexit ad1938_spi_remove(struct spi_device *spi)
326{
327 struct ad1938_priv *ad1938 = dev_get_drvdata(&spi->dev);
328
329 ad1938_unregister(ad1938);
330 return 0;
331}
332
333static struct spi_driver ad1938_spi_driver = {
334 .driver = {
335 .name = "ad1938",
336 .owner = THIS_MODULE,
337 },
338 .probe = ad1938_spi_probe,
339 .remove = __devexit_p(ad1938_spi_remove),
340};
341
342static struct snd_soc_dai_ops ad1938_dai_ops = {
343 .hw_params = ad1938_hw_params,
344 .digital_mute = ad1938_mute,
345 .set_tdm_slot = ad1938_set_tdm_slot,
346 .set_fmt = ad1938_set_dai_fmt,
347};
348
349/* codec DAI instance */
350struct snd_soc_dai ad1938_dai = {
351 .name = "AD1938",
352 .playback = {
353 .stream_name = "Playback",
354 .channels_min = 2,
355 .channels_max = 8,
356 .rates = SNDRV_PCM_RATE_48000,
357 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
358 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
359 },
360 .capture = {
361 .stream_name = "Capture",
362 .channels_min = 2,
363 .channels_max = 4,
364 .rates = SNDRV_PCM_RATE_48000,
365 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
366 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
367 },
368 .ops = &ad1938_dai_ops,
369};
370EXPORT_SYMBOL_GPL(ad1938_dai);
371
372static int ad1938_register(struct ad1938_priv *ad1938)
373{
374 int ret;
375 struct snd_soc_codec *codec = &ad1938->codec;
376
377 if (ad1938_codec) {
378 dev_err(codec->dev, "Another ad1938 is registered\n");
379 return -EINVAL;
380 }
381
382 mutex_init(&codec->mutex);
383 INIT_LIST_HEAD(&codec->dapm_widgets);
384 INIT_LIST_HEAD(&codec->dapm_paths);
385 codec->private_data = ad1938;
386 codec->reg_cache = ad1938->reg_cache;
387 codec->reg_cache_size = AD1938_NUM_REGS;
388 codec->name = "AD1938";
389 codec->owner = THIS_MODULE;
390 codec->dai = &ad1938_dai;
391 codec->num_dai = 1;
392 INIT_LIST_HEAD(&codec->dapm_widgets);
393 INIT_LIST_HEAD(&codec->dapm_paths);
394
395 ad1938_dai.dev = codec->dev;
396 ad1938_codec = codec;
397
398 memcpy(codec->reg_cache, ad1938_reg, AD1938_NUM_REGS);
399
400 ret = snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_SPI);
401 if (ret < 0) {
402 dev_err(codec->dev, "failed to set cache I/O: %d\n",
403 ret);
404 kfree(ad1938);
405 return ret;
406 }
407
408 /* default setting for ad1938 */
409
410 /* unmute dac channels */
411 snd_soc_write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
412 /* de-emphasis: 48kHz, powedown dac */
413 snd_soc_write(codec, AD1938_DAC_CTRL2, 0x1A);
414 /* powerdown dac, dac in tdm mode */
415 snd_soc_write(codec, AD1938_DAC_CTRL0, 0x41);
416 /* high-pass filter enable */
417 snd_soc_write(codec, AD1938_ADC_CTRL0, 0x3);
418 /* sata delay=1, adc aux mode */
419 snd_soc_write(codec, AD1938_ADC_CTRL1, 0x43);
420 /* pll input: mclki/xi */
421 snd_soc_write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
422 snd_soc_write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
423
424 ret = snd_soc_register_codec(codec);
425 if (ret != 0) {
426 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
427 kfree(ad1938);
428 return ret;
429 }
430
431 ret = snd_soc_register_dai(&ad1938_dai);
432 if (ret != 0) {
433 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
434 snd_soc_unregister_codec(codec);
435 kfree(ad1938);
436 return ret;
437 }
438
439 return 0;
440}
441
442static void ad1938_unregister(struct ad1938_priv *ad1938)
443{
444 snd_soc_unregister_dai(&ad1938_dai);
445 snd_soc_unregister_codec(&ad1938->codec);
446 kfree(ad1938);
447 ad1938_codec = NULL;
448}
449
450static int ad1938_probe(struct platform_device *pdev)
451{
452 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
453 struct snd_soc_codec *codec;
454 int ret = 0;
455
456 if (ad1938_codec == NULL) {
457 dev_err(&pdev->dev, "Codec device not registered\n");
458 return -ENODEV;
459 }
460
461 socdev->card->codec = ad1938_codec;
462 codec = ad1938_codec;
463
464 /* register pcms */
465 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
466 if (ret < 0) {
467 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
468 goto pcm_err;
469 }
470
471 snd_soc_add_controls(codec, ad1938_snd_controls,
472 ARRAY_SIZE(ad1938_snd_controls));
473 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets,
474 ARRAY_SIZE(ad1938_dapm_widgets));
475 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
476
477
478pcm_err:
479 return ret;
480}
481
482/* power down chip */
483static int ad1938_remove(struct platform_device *pdev)
484{
485 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
486
487 snd_soc_free_pcms(socdev);
488 snd_soc_dapm_free(socdev);
489
490 return 0;
491}
492
493struct snd_soc_codec_device soc_codec_dev_ad1938 = {
494 .probe = ad1938_probe,
495 .remove = ad1938_remove,
496};
497EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938);
498
499static int __init ad1938_init(void)
500{
501 int ret;
502
503 ret = spi_register_driver(&ad1938_spi_driver);
504 if (ret != 0) {
505 printk(KERN_ERR "Failed to register ad1938 SPI driver: %d\n",
506 ret);
507 }
508
509 return ret;
510}
511module_init(ad1938_init);
512
513static void __exit ad1938_exit(void)
514{
515 spi_unregister_driver(&ad1938_spi_driver);
516}
517module_exit(ad1938_exit);
518
519MODULE_DESCRIPTION("ASoC ad1938 driver");
520MODULE_AUTHOR("Barry Song ");
521MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1938.h b/sound/soc/codecs/ad1938.h
deleted file mode 100644
index fe3c48cd2d5b..000000000000
--- a/sound/soc/codecs/ad1938.h
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 * File: sound/soc/codecs/ad1836.h
3 * Based on:
4 * Author: Barry Song <Barry.Song@analog.com>
5 *
6 * Created: May 25, 2009
7 * Description: definitions for AD1938 registers
8 *
9 * Modified:
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#ifndef __AD1938_H__
30#define __AD1938_H__
31
32#define AD1938_PLL_CLK_CTRL0 0
33#define AD1938_PLL_POWERDOWN 0x01
34#define AD1938_PLL_CLK_CTRL1 1
35#define AD1938_DAC_CTRL0 2
36#define AD1938_DAC_POWERDOWN 0x01
37#define AD1938_DAC_SERFMT_MASK 0xC0
38#define AD1938_DAC_SERFMT_STEREO (0 << 6)
39#define AD1938_DAC_SERFMT_TDM (1 << 6)
40#define AD1938_DAC_CTRL1 3
41#define AD1938_DAC_2_CHANNELS 0
42#define AD1938_DAC_4_CHANNELS 1
43#define AD1938_DAC_8_CHANNELS 2
44#define AD1938_DAC_16_CHANNELS 3
45#define AD1938_DAC_CHAN_SHFT 1
46#define AD1938_DAC_CHAN_MASK (3 << AD1938_DAC_CHAN_SHFT)
47#define AD1938_DAC_LCR_MASTER (1 << 4)
48#define AD1938_DAC_BCLK_MASTER (1 << 5)
49#define AD1938_DAC_LEFT_HIGH (1 << 3)
50#define AD1938_DAC_BCLK_INV (1 << 7)
51#define AD1938_DAC_CTRL2 4
52#define AD1938_DAC_WORD_LEN_MASK 0xC
53#define AD1938_DAC_MASTER_MUTE 1
54#define AD1938_DAC_CHNL_MUTE 5
55#define AD1938_DACL1_MUTE 0
56#define AD1938_DACR1_MUTE 1
57#define AD1938_DACL2_MUTE 2
58#define AD1938_DACR2_MUTE 3
59#define AD1938_DACL3_MUTE 4
60#define AD1938_DACR3_MUTE 5
61#define AD1938_DACL4_MUTE 6
62#define AD1938_DACR4_MUTE 7
63#define AD1938_DAC_L1_VOL 6
64#define AD1938_DAC_R1_VOL 7
65#define AD1938_DAC_L2_VOL 8
66#define AD1938_DAC_R2_VOL 9
67#define AD1938_DAC_L3_VOL 10
68#define AD1938_DAC_R3_VOL 11
69#define AD1938_DAC_L4_VOL 12
70#define AD1938_DAC_R4_VOL 13
71#define AD1938_ADC_CTRL0 14
72#define AD1938_ADC_POWERDOWN 0x01
73#define AD1938_ADC_HIGHPASS_FILTER 1
74#define AD1938_ADCL1_MUTE 2
75#define AD1938_ADCR1_MUTE 3
76#define AD1938_ADCL2_MUTE 4
77#define AD1938_ADCR2_MUTE 5
78#define AD1938_ADC_CTRL1 15
79#define AD1938_ADC_SERFMT_MASK 0x60
80#define AD1938_ADC_SERFMT_STEREO (0 << 5)
81#define AD1938_ADC_SERFMT_TDM (1 << 2)
82#define AD1938_ADC_SERFMT_AUX (2 << 5)
83#define AD1938_ADC_WORD_LEN_MASK 0x3
84#define AD1938_ADC_CTRL2 16
85#define AD1938_ADC_2_CHANNELS 0
86#define AD1938_ADC_4_CHANNELS 1
87#define AD1938_ADC_8_CHANNELS 2
88#define AD1938_ADC_16_CHANNELS 3
89#define AD1938_ADC_CHAN_SHFT 4
90#define AD1938_ADC_CHAN_MASK (3 << AD1938_ADC_CHAN_SHFT)
91#define AD1938_ADC_LCR_MASTER (1 << 3)
92#define AD1938_ADC_BCLK_MASTER (1 << 6)
93#define AD1938_ADC_LEFT_HIGH (1 << 2)
94#define AD1938_ADC_BCLK_INV (1 << 1)
95
96#define AD1938_NUM_REGS 17
97
98extern struct snd_soc_dai ad1938_dai;
99extern struct snd_soc_codec_device soc_codec_dev_ad1938;
100#endif
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
new file mode 100644
index 000000000000..4bfd66bc2624
--- /dev/null
+++ b/sound/soc/codecs/ad193x.c
@@ -0,0 +1,545 @@
1/*
2 * AD193X Audio Codec driver supporting AD1936/7/8/9
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/kernel.h>
12#include <linux/device.h>
13#include <linux/i2c.h>
14#include <linux/spi/spi.h>
15#include <linux/slab.h>
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/initval.h>
20#include <sound/soc.h>
21#include <sound/tlv.h>
22#include <sound/soc-dapm.h>
23#include "ad193x.h"
24
25/* codec private data */
26struct ad193x_priv {
27 struct snd_soc_codec codec;
28 u8 reg_cache[AD193X_NUM_REGS];
29};
30
31/* ad193x register cache & default register settings */
32static const u8 ad193x_reg[AD193X_NUM_REGS] = {
33 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
34};
35
36static struct snd_soc_codec *ad193x_codec;
37struct snd_soc_codec_device soc_codec_dev_ad193x;
38
39/*
40 * AD193X volume/mute/de-emphasis etc. controls
41 */
42static const char *ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
43
44static const struct soc_enum ad193x_deemp_enum =
45 SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp);
46
47static const struct snd_kcontrol_new ad193x_snd_controls[] = {
48 /* DAC volume control */
49 SOC_DOUBLE_R("DAC1 Volume", AD193X_DAC_L1_VOL,
50 AD193X_DAC_R1_VOL, 0, 0xFF, 1),
51 SOC_DOUBLE_R("DAC2 Volume", AD193X_DAC_L2_VOL,
52 AD193X_DAC_R2_VOL, 0, 0xFF, 1),
53 SOC_DOUBLE_R("DAC3 Volume", AD193X_DAC_L3_VOL,
54 AD193X_DAC_R3_VOL, 0, 0xFF, 1),
55 SOC_DOUBLE_R("DAC4 Volume", AD193X_DAC_L4_VOL,
56 AD193X_DAC_R4_VOL, 0, 0xFF, 1),
57
58 /* ADC switch control */
59 SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE,
60 AD193X_ADCR1_MUTE, 1, 1),
61 SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE,
62 AD193X_ADCR2_MUTE, 1, 1),
63
64 /* DAC switch control */
65 SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE,
66 AD193X_DACR1_MUTE, 1, 1),
67 SOC_DOUBLE("DAC2 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL2_MUTE,
68 AD193X_DACR2_MUTE, 1, 1),
69 SOC_DOUBLE("DAC3 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL3_MUTE,
70 AD193X_DACR3_MUTE, 1, 1),
71 SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE,
72 AD193X_DACR4_MUTE, 1, 1),
73
74 /* ADC high-pass filter */
75 SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0,
76 AD193X_ADC_HIGHPASS_FILTER, 1, 0),
77
78 /* DAC de-emphasis */
79 SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum),
80};
81
82static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = {
83 SND_SOC_DAPM_DAC("DAC", "Playback", AD193X_DAC_CTRL0, 0, 1),
84 SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
85 SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0),
86 SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0),
87 SND_SOC_DAPM_OUTPUT("DAC1OUT"),
88 SND_SOC_DAPM_OUTPUT("DAC2OUT"),
89 SND_SOC_DAPM_OUTPUT("DAC3OUT"),
90 SND_SOC_DAPM_OUTPUT("DAC4OUT"),
91 SND_SOC_DAPM_INPUT("ADC1IN"),
92 SND_SOC_DAPM_INPUT("ADC2IN"),
93};
94
95static const struct snd_soc_dapm_route audio_paths[] = {
96 { "DAC", NULL, "PLL_PWR" },
97 { "ADC", NULL, "PLL_PWR" },
98 { "DAC", NULL, "ADC_PWR" },
99 { "ADC", NULL, "ADC_PWR" },
100 { "DAC1OUT", "DAC1 Switch", "DAC" },
101 { "DAC2OUT", "DAC2 Switch", "DAC" },
102 { "DAC3OUT", "DAC3 Switch", "DAC" },
103 { "DAC4OUT", "DAC4 Switch", "DAC" },
104 { "ADC", "ADC1 Switch", "ADC1IN" },
105 { "ADC", "ADC2 Switch", "ADC2IN" },
106};
107
108/*
109 * DAI ops entries
110 */
111
112static int ad193x_mute(struct snd_soc_dai *dai, int mute)
113{
114 struct snd_soc_codec *codec = dai->codec;
115 int reg;
116
117 reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
118 reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg &
119 (~AD193X_DAC_MASTER_MUTE);
120 snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
121
122 return 0;
123}
124
125static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
126 unsigned int rx_mask, int slots, int width)
127{
128 struct snd_soc_codec *codec = dai->codec;
129 int dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
130 int adc_reg = snd_soc_read(codec, AD193X_ADC_CTRL2);
131
132 dac_reg &= ~AD193X_DAC_CHAN_MASK;
133 adc_reg &= ~AD193X_ADC_CHAN_MASK;
134
135 switch (slots) {
136 case 2:
137 dac_reg |= AD193X_DAC_2_CHANNELS << AD193X_DAC_CHAN_SHFT;
138 adc_reg |= AD193X_ADC_2_CHANNELS << AD193X_ADC_CHAN_SHFT;
139 break;
140 case 4:
141 dac_reg |= AD193X_DAC_4_CHANNELS << AD193X_DAC_CHAN_SHFT;
142 adc_reg |= AD193X_ADC_4_CHANNELS << AD193X_ADC_CHAN_SHFT;
143 break;
144 case 8:
145 dac_reg |= AD193X_DAC_8_CHANNELS << AD193X_DAC_CHAN_SHFT;
146 adc_reg |= AD193X_ADC_8_CHANNELS << AD193X_ADC_CHAN_SHFT;
147 break;
148 case 16:
149 dac_reg |= AD193X_DAC_16_CHANNELS << AD193X_DAC_CHAN_SHFT;
150 adc_reg |= AD193X_ADC_16_CHANNELS << AD193X_ADC_CHAN_SHFT;
151 break;
152 default:
153 return -EINVAL;
154 }
155
156 snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
157 snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg);
158
159 return 0;
160}
161
162static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
163 unsigned int fmt)
164{
165 struct snd_soc_codec *codec = codec_dai->codec;
166 int adc_reg, dac_reg;
167
168 adc_reg = snd_soc_read(codec, AD193X_ADC_CTRL2);
169 dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
170
171 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
172 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
173 */
174 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
175 case SND_SOC_DAIFMT_I2S:
176 adc_reg &= ~AD193X_ADC_SERFMT_MASK;
177 adc_reg |= AD193X_ADC_SERFMT_TDM;
178 break;
179 case SND_SOC_DAIFMT_DSP_A:
180 adc_reg &= ~AD193X_ADC_SERFMT_MASK;
181 adc_reg |= AD193X_ADC_SERFMT_AUX;
182 break;
183 default:
184 return -EINVAL;
185 }
186
187 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
188 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
189 adc_reg &= ~AD193X_ADC_LEFT_HIGH;
190 adc_reg &= ~AD193X_ADC_BCLK_INV;
191 dac_reg &= ~AD193X_DAC_LEFT_HIGH;
192 dac_reg &= ~AD193X_DAC_BCLK_INV;
193 break;
194 case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
195 adc_reg |= AD193X_ADC_LEFT_HIGH;
196 adc_reg &= ~AD193X_ADC_BCLK_INV;
197 dac_reg |= AD193X_DAC_LEFT_HIGH;
198 dac_reg &= ~AD193X_DAC_BCLK_INV;
199 break;
200 case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
201 adc_reg &= ~AD193X_ADC_LEFT_HIGH;
202 adc_reg |= AD193X_ADC_BCLK_INV;
203 dac_reg &= ~AD193X_DAC_LEFT_HIGH;
204 dac_reg |= AD193X_DAC_BCLK_INV;
205 break;
206
207 case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
208 adc_reg |= AD193X_ADC_LEFT_HIGH;
209 adc_reg |= AD193X_ADC_BCLK_INV;
210 dac_reg |= AD193X_DAC_LEFT_HIGH;
211 dac_reg |= AD193X_DAC_BCLK_INV;
212 break;
213 default:
214 return -EINVAL;
215 }
216
217 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
218 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
219 adc_reg |= AD193X_ADC_LCR_MASTER;
220 adc_reg |= AD193X_ADC_BCLK_MASTER;
221 dac_reg |= AD193X_DAC_LCR_MASTER;
222 dac_reg |= AD193X_DAC_BCLK_MASTER;
223 break;
224 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
225 adc_reg |= AD193X_ADC_LCR_MASTER;
226 adc_reg &= ~AD193X_ADC_BCLK_MASTER;
227 dac_reg |= AD193X_DAC_LCR_MASTER;
228 dac_reg &= ~AD193X_DAC_BCLK_MASTER;
229 break;
230 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
231 adc_reg &= ~AD193X_ADC_LCR_MASTER;
232 adc_reg |= AD193X_ADC_BCLK_MASTER;
233 dac_reg &= ~AD193X_DAC_LCR_MASTER;
234 dac_reg |= AD193X_DAC_BCLK_MASTER;
235 break;
236 case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
237 adc_reg &= ~AD193X_ADC_LCR_MASTER;
238 adc_reg &= ~AD193X_ADC_BCLK_MASTER;
239 dac_reg &= ~AD193X_DAC_LCR_MASTER;
240 dac_reg &= ~AD193X_DAC_BCLK_MASTER;
241 break;
242 default:
243 return -EINVAL;
244 }
245
246 snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg);
247 snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
248
249 return 0;
250}
251
252static int ad193x_hw_params(struct snd_pcm_substream *substream,
253 struct snd_pcm_hw_params *params,
254 struct snd_soc_dai *dai)
255{
256 int word_len = 0, reg = 0;
257
258 struct snd_soc_pcm_runtime *rtd = substream->private_data;
259 struct snd_soc_device *socdev = rtd->socdev;
260 struct snd_soc_codec *codec = socdev->card->codec;
261
262 /* bit size */
263 switch (params_format(params)) {
264 case SNDRV_PCM_FORMAT_S16_LE:
265 word_len = 3;
266 break;
267 case SNDRV_PCM_FORMAT_S20_3LE:
268 word_len = 1;
269 break;
270 case SNDRV_PCM_FORMAT_S24_LE:
271 case SNDRV_PCM_FORMAT_S32_LE:
272 word_len = 0;
273 break;
274 }
275
276 reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
277 reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len;
278 snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
279
280 reg = snd_soc_read(codec, AD193X_ADC_CTRL1);
281 reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len;
282 snd_soc_write(codec, AD193X_ADC_CTRL1, reg);
283
284 return 0;
285}
286
287static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
288{
289 struct snd_soc_codec *codec;
290 struct ad193x_priv *ad193x;
291 int ret;
292
293 if (ad193x_codec) {
294 dev_err(dev, "Another ad193x is registered\n");
295 return -EINVAL;
296 }
297
298 ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
299 if (ad193x == NULL)
300 return -ENOMEM;
301
302 dev_set_drvdata(dev, ad193x);
303
304 codec = &ad193x->codec;
305 mutex_init(&codec->mutex);
306 codec->control_data = ctrl_data;
307 codec->dev = dev;
308 codec->private_data = ad193x;
309 codec->reg_cache = ad193x->reg_cache;
310 codec->reg_cache_size = AD193X_NUM_REGS;
311 codec->name = "AD193X";
312 codec->owner = THIS_MODULE;
313 codec->dai = &ad193x_dai;
314 codec->num_dai = 1;
315 INIT_LIST_HEAD(&codec->dapm_widgets);
316 INIT_LIST_HEAD(&codec->dapm_paths);
317
318 ad193x_dai.dev = codec->dev;
319 ad193x_codec = codec;
320
321 memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS);
322
323 if (bus_type == SND_SOC_I2C)
324 ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type);
325 else
326 ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type);
327 if (ret < 0) {
328 dev_err(codec->dev, "failed to set cache I/O: %d\n",
329 ret);
330 kfree(ad193x);
331 return ret;
332 }
333
334 /* default setting for ad193x */
335
336 /* unmute dac channels */
337 snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
338 /* de-emphasis: 48kHz, powedown dac */
339 snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
340 /* powerdown dac, dac in tdm mode */
341 snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
342 /* high-pass filter enable */
343 snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
344 /* sata delay=1, adc aux mode */
345 snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
346 /* pll input: mclki/xi */
347 snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
348 snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
349
350 ret = snd_soc_register_codec(codec);
351 if (ret != 0) {
352 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
353 kfree(ad193x);
354 return ret;
355 }
356
357 ret = snd_soc_register_dai(&ad193x_dai);
358 if (ret != 0) {
359 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
360 snd_soc_unregister_codec(codec);
361 kfree(ad193x);
362 return ret;
363 }
364
365 return 0;
366}
367
368static int ad193x_bus_remove(struct device *dev)
369{
370 struct ad193x_priv *ad193x = dev_get_drvdata(dev);
371
372 snd_soc_unregister_dai(&ad193x_dai);
373 snd_soc_unregister_codec(&ad193x->codec);
374 kfree(ad193x);
375 ad193x_codec = NULL;
376
377 return 0;
378}
379
380static struct snd_soc_dai_ops ad193x_dai_ops = {
381 .hw_params = ad193x_hw_params,
382 .digital_mute = ad193x_mute,
383 .set_tdm_slot = ad193x_set_tdm_slot,
384 .set_fmt = ad193x_set_dai_fmt,
385};
386
387/* codec DAI instance */
388struct snd_soc_dai ad193x_dai = {
389 .name = "AD193X",
390 .playback = {
391 .stream_name = "Playback",
392 .channels_min = 2,
393 .channels_max = 8,
394 .rates = SNDRV_PCM_RATE_48000,
395 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
396 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
397 },
398 .capture = {
399 .stream_name = "Capture",
400 .channels_min = 2,
401 .channels_max = 4,
402 .rates = SNDRV_PCM_RATE_48000,
403 .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
404 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
405 },
406 .ops = &ad193x_dai_ops,
407};
408EXPORT_SYMBOL_GPL(ad193x_dai);
409
410static int ad193x_probe(struct platform_device *pdev)
411{
412 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
413 struct snd_soc_codec *codec;
414 int ret = 0;
415
416 if (ad193x_codec == NULL) {
417 dev_err(&pdev->dev, "Codec device not registered\n");
418 return -ENODEV;
419 }
420
421 socdev->card->codec = ad193x_codec;
422 codec = ad193x_codec;
423
424 /* register pcms */
425 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
426 if (ret < 0) {
427 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
428 goto pcm_err;
429 }
430
431 snd_soc_add_controls(codec, ad193x_snd_controls,
432 ARRAY_SIZE(ad193x_snd_controls));
433 snd_soc_dapm_new_controls(codec, ad193x_dapm_widgets,
434 ARRAY_SIZE(ad193x_dapm_widgets));
435 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
436
437pcm_err:
438 return ret;
439}
440
441/* power down chip */
442static int ad193x_remove(struct platform_device *pdev)
443{
444 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
445
446 snd_soc_free_pcms(socdev);
447 snd_soc_dapm_free(socdev);
448
449 return 0;
450}
451
452struct snd_soc_codec_device soc_codec_dev_ad193x = {
453 .probe = ad193x_probe,
454 .remove = ad193x_remove,
455};
456EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x);
457
458#if defined(CONFIG_SPI_MASTER)
459static int __devinit ad193x_spi_probe(struct spi_device *spi)
460{
461 return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI);
462}
463
464static int __devexit ad193x_spi_remove(struct spi_device *spi)
465{
466 return ad193x_bus_remove(&spi->dev);
467}
468
469static struct spi_driver ad193x_spi_driver = {
470 .driver = {
471 .name = "ad193x",
472 .owner = THIS_MODULE,
473 },
474 .probe = ad193x_spi_probe,
475 .remove = __devexit_p(ad193x_spi_remove),
476};
477#endif
478
479#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
480static const struct i2c_device_id ad193x_id[] = {
481 { "ad1936", 0 },
482 { "ad1937", 0 },
483 { }
484};
485MODULE_DEVICE_TABLE(i2c, ad193x_id);
486
487static int __devinit ad193x_i2c_probe(struct i2c_client *client,
488 const struct i2c_device_id *id)
489{
490 return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C);
491}
492
493static int __devexit ad193x_i2c_remove(struct i2c_client *client)
494{
495 return ad193x_bus_remove(&client->dev);
496}
497
498static struct i2c_driver ad193x_i2c_driver = {
499 .driver = {
500 .name = "ad193x",
501 },
502 .probe = ad193x_i2c_probe,
503 .remove = __devexit_p(ad193x_i2c_remove),
504 .id_table = ad193x_id,
505};
506#endif
507
508static int __init ad193x_modinit(void)
509{
510 int ret;
511
512#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
513 ret = i2c_add_driver(&ad193x_i2c_driver);
514 if (ret != 0) {
515 printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n",
516 ret);
517 }
518#endif
519
520#if defined(CONFIG_SPI_MASTER)
521 ret = spi_register_driver(&ad193x_spi_driver);
522 if (ret != 0) {
523 printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n",
524 ret);
525 }
526#endif
527 return ret;
528}
529module_init(ad193x_modinit);
530
531static void __exit ad193x_modexit(void)
532{
533#if defined(CONFIG_SPI_MASTER)
534 spi_unregister_driver(&ad193x_spi_driver);
535#endif
536
537#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
538 i2c_del_driver(&ad193x_i2c_driver);
539#endif
540}
541module_exit(ad193x_modexit);
542
543MODULE_DESCRIPTION("ASoC ad193x driver");
544MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
545MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
new file mode 100644
index 000000000000..a03c880d52f9
--- /dev/null
+++ b/sound/soc/codecs/ad193x.h
@@ -0,0 +1,81 @@
1/*
2 * AD193X Audio Codec driver
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#ifndef __AD193X_H__
10#define __AD193X_H__
11
12#define AD193X_PLL_CLK_CTRL0 0x800
13#define AD193X_PLL_POWERDOWN 0x01
14#define AD193X_PLL_CLK_CTRL1 0x801
15#define AD193X_DAC_CTRL0 0x802
16#define AD193X_DAC_POWERDOWN 0x01
17#define AD193X_DAC_SERFMT_MASK 0xC0
18#define AD193X_DAC_SERFMT_STEREO (0 << 6)
19#define AD193X_DAC_SERFMT_TDM (1 << 6)
20#define AD193X_DAC_CTRL1 0x803
21#define AD193X_DAC_2_CHANNELS 0
22#define AD193X_DAC_4_CHANNELS 1
23#define AD193X_DAC_8_CHANNELS 2
24#define AD193X_DAC_16_CHANNELS 3
25#define AD193X_DAC_CHAN_SHFT 1
26#define AD193X_DAC_CHAN_MASK (3 << AD193X_DAC_CHAN_SHFT)
27#define AD193X_DAC_LCR_MASTER (1 << 4)
28#define AD193X_DAC_BCLK_MASTER (1 << 5)
29#define AD193X_DAC_LEFT_HIGH (1 << 3)
30#define AD193X_DAC_BCLK_INV (1 << 7)
31#define AD193X_DAC_CTRL2 0x804
32#define AD193X_DAC_WORD_LEN_MASK 0xC
33#define AD193X_DAC_MASTER_MUTE 1
34#define AD193X_DAC_CHNL_MUTE 0x805
35#define AD193X_DACL1_MUTE 0
36#define AD193X_DACR1_MUTE 1
37#define AD193X_DACL2_MUTE 2
38#define AD193X_DACR2_MUTE 3
39#define AD193X_DACL3_MUTE 4
40#define AD193X_DACR3_MUTE 5
41#define AD193X_DACL4_MUTE 6
42#define AD193X_DACR4_MUTE 7
43#define AD193X_DAC_L1_VOL 0x806
44#define AD193X_DAC_R1_VOL 0x807
45#define AD193X_DAC_L2_VOL 0x808
46#define AD193X_DAC_R2_VOL 0x809
47#define AD193X_DAC_L3_VOL 0x80a
48#define AD193X_DAC_R3_VOL 0x80b
49#define AD193X_DAC_L4_VOL 0x80c
50#define AD193X_DAC_R4_VOL 0x80d
51#define AD193X_ADC_CTRL0 0x80e
52#define AD193X_ADC_POWERDOWN 0x01
53#define AD193X_ADC_HIGHPASS_FILTER 1
54#define AD193X_ADCL1_MUTE 2
55#define AD193X_ADCR1_MUTE 3
56#define AD193X_ADCL2_MUTE 4
57#define AD193X_ADCR2_MUTE 5
58#define AD193X_ADC_CTRL1 0x80f
59#define AD193X_ADC_SERFMT_MASK 0x60
60#define AD193X_ADC_SERFMT_STEREO (0 << 5)
61#define AD193X_ADC_SERFMT_TDM (1 << 2)
62#define AD193X_ADC_SERFMT_AUX (2 << 5)
63#define AD193X_ADC_WORD_LEN_MASK 0x3
64#define AD193X_ADC_CTRL2 0x810
65#define AD193X_ADC_2_CHANNELS 0
66#define AD193X_ADC_4_CHANNELS 1
67#define AD193X_ADC_8_CHANNELS 2
68#define AD193X_ADC_16_CHANNELS 3
69#define AD193X_ADC_CHAN_SHFT 4
70#define AD193X_ADC_CHAN_MASK (3 << AD193X_ADC_CHAN_SHFT)
71#define AD193X_ADC_LCR_MASTER (1 << 3)
72#define AD193X_ADC_BCLK_MASTER (1 << 6)
73#define AD193X_ADC_LEFT_HIGH (1 << 2)
74#define AD193X_ADC_BCLK_INV (1 << 1)
75
76#define AD193X_NUM_REGS 17
77
78extern struct snd_soc_dai ad193x_dai;
79extern struct snd_soc_codec_device soc_codec_dev_ad193x;
80
81#endif
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 3ef16bbc8c83..de1809dc8d91 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -80,12 +80,39 @@
80 80
81#define AK4642_CACHEREGNUM 0x25 81#define AK4642_CACHEREGNUM 0x25
82 82
83/* PW_MGMT2 */
84#define HPMTN (1 << 6)
85#define PMHPL (1 << 5)
86#define PMHPR (1 << 4)
87#define MS (1 << 3) /* master/slave select */
88#define MCKO (1 << 1)
89#define PMPLL (1 << 0)
90
91#define PMHP_MASK (PMHPL | PMHPR)
92#define PMHP PMHP_MASK
93
94/* MD_CTL1 */
95#define PLL3 (1 << 7)
96#define PLL2 (1 << 6)
97#define PLL1 (1 << 5)
98#define PLL0 (1 << 4)
99#define PLL_MASK (PLL3 | PLL2 | PLL1 | PLL0)
100
101#define BCKO_MASK (1 << 3)
102#define BCKO_64 BCKO_MASK
103
104/* MD_CTL2 */
105#define FS0 (1 << 0)
106#define FS1 (1 << 1)
107#define FS2 (1 << 2)
108#define FS3 (1 << 5)
109#define FS_MASK (FS0 | FS1 | FS2 | FS3)
110
83struct snd_soc_codec_device soc_codec_dev_ak4642; 111struct snd_soc_codec_device soc_codec_dev_ak4642;
84 112
85/* codec private data */ 113/* codec private data */
86struct ak4642_priv { 114struct ak4642_priv {
87 struct snd_soc_codec codec; 115 struct snd_soc_codec codec;
88 unsigned int sysclk;
89}; 116};
90 117
91static struct snd_soc_codec *ak4642_codec; 118static struct snd_soc_codec *ak4642_codec;
@@ -176,17 +203,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
176 * 203 *
177 * PLL, Master Mode 204 * PLL, Master Mode
178 * Audio I/F Format :MSB justified (ADC & DAC) 205 * Audio I/F Format :MSB justified (ADC & DAC)
179 * Sampling Frequency: 44.1kHz 206 * Digital Volume: -8dB
180 * Digital Volume: −8dB
181 * Bass Boost Level : Middle 207 * Bass Boost Level : Middle
182 * 208 *
183 * This operation came from example code of 209 * This operation came from example code of
184 * "ASAHI KASEI AK4642" (japanese) manual p97. 210 * "ASAHI KASEI AK4642" (japanese) manual p97.
185 *
186 * Example code use 0x39, 0x79 value for 0x01 address,
187 * But we need MCKO (0x02) bit now
188 */ 211 */
189 ak4642_write(codec, 0x05, 0x27);
190 ak4642_write(codec, 0x0f, 0x09); 212 ak4642_write(codec, 0x0f, 0x09);
191 ak4642_write(codec, 0x0e, 0x19); 213 ak4642_write(codec, 0x0e, 0x19);
192 ak4642_write(codec, 0x09, 0x91); 214 ak4642_write(codec, 0x09, 0x91);
@@ -194,15 +216,14 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
194 ak4642_write(codec, 0x0a, 0x28); 216 ak4642_write(codec, 0x0a, 0x28);
195 ak4642_write(codec, 0x0d, 0x28); 217 ak4642_write(codec, 0x0d, 0x28);
196 ak4642_write(codec, 0x00, 0x64); 218 ak4642_write(codec, 0x00, 0x64);
197 ak4642_write(codec, 0x01, 0x3b); /* + MCKO bit */ 219 snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
198 ak4642_write(codec, 0x01, 0x7b); /* + MCKO bit */ 220 snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN);
199 } else { 221 } else {
200 /* 222 /*
201 * start stereo input 223 * start stereo input
202 * 224 *
203 * PLL Master Mode 225 * PLL Master Mode
204 * Audio I/F Format:MSB justified (ADC & DAC) 226 * Audio I/F Format:MSB justified (ADC & DAC)
205 * Sampling Frequency:44.1kHz
206 * Pre MIC AMP:+20dB 227 * Pre MIC AMP:+20dB
207 * MIC Power On 228 * MIC Power On
208 * ALC setting:Refer to Table 35 229 * ALC setting:Refer to Table 35
@@ -211,7 +232,6 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
211 * This operation came from example code of 232 * This operation came from example code of
212 * "ASAHI KASEI AK4642" (japanese) manual p94. 233 * "ASAHI KASEI AK4642" (japanese) manual p94.
213 */ 234 */
214 ak4642_write(codec, 0x05, 0x27);
215 ak4642_write(codec, 0x02, 0x05); 235 ak4642_write(codec, 0x02, 0x05);
216 ak4642_write(codec, 0x06, 0x3c); 236 ak4642_write(codec, 0x06, 0x3c);
217 ak4642_write(codec, 0x08, 0xe1); 237 ak4642_write(codec, 0x08, 0xe1);
@@ -232,8 +252,8 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
232 252
233 if (is_play) { 253 if (is_play) {
234 /* stop headphone output */ 254 /* stop headphone output */
235 ak4642_write(codec, 0x01, 0x3b); 255 snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0);
236 ak4642_write(codec, 0x01, 0x0b); 256 snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0);
237 ak4642_write(codec, 0x00, 0x40); 257 ak4642_write(codec, 0x00, 0x40);
238 ak4642_write(codec, 0x0e, 0x11); 258 ak4642_write(codec, 0x0e, 0x11);
239 ak4642_write(codec, 0x0f, 0x08); 259 ak4642_write(codec, 0x0f, 0x08);
@@ -249,9 +269,111 @@ static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai,
249 int clk_id, unsigned int freq, int dir) 269 int clk_id, unsigned int freq, int dir)
250{ 270{
251 struct snd_soc_codec *codec = codec_dai->codec; 271 struct snd_soc_codec *codec = codec_dai->codec;
252 struct ak4642_priv *ak4642 = codec->private_data; 272 u8 pll;
273
274 switch (freq) {
275 case 11289600:
276 pll = PLL2;
277 break;
278 case 12288000:
279 pll = PLL2 | PLL0;
280 break;
281 case 12000000:
282 pll = PLL2 | PLL1;
283 break;
284 case 24000000:
285 pll = PLL2 | PLL1 | PLL0;
286 break;
287 case 13500000:
288 pll = PLL3 | PLL2;
289 break;
290 case 27000000:
291 pll = PLL3 | PLL2 | PLL0;
292 break;
293 default:
294 return -EINVAL;
295 }
296 snd_soc_update_bits(codec, MD_CTL1, PLL_MASK, pll);
297
298 return 0;
299}
300
301static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
302{
303 struct snd_soc_codec *codec = dai->codec;
304 u8 data;
305 u8 bcko;
306
307 data = MCKO | PMPLL; /* use MCKO */
308 bcko = 0;
309
310 /* set master/slave audio interface */
311 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
312 case SND_SOC_DAIFMT_CBM_CFM:
313 data |= MS;
314 bcko = BCKO_64;
315 break;
316 case SND_SOC_DAIFMT_CBS_CFS:
317 break;
318 default:
319 return -EINVAL;
320 }
321 snd_soc_update_bits(codec, PW_MGMT2, MS, data);
322 snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko);
323
324 return 0;
325}
326
327static int ak4642_dai_hw_params(struct snd_pcm_substream *substream,
328 struct snd_pcm_hw_params *params,
329 struct snd_soc_dai *dai)
330{
331 struct snd_soc_codec *codec = dai->codec;
332 u8 rate;
333
334 switch (params_rate(params)) {
335 case 7350:
336 rate = FS2;
337 break;
338 case 8000:
339 rate = 0;
340 break;
341 case 11025:
342 rate = FS2 | FS0;
343 break;
344 case 12000:
345 rate = FS0;
346 break;
347 case 14700:
348 rate = FS2 | FS1;
349 break;
350 case 16000:
351 rate = FS1;
352 break;
353 case 22050:
354 rate = FS2 | FS1 | FS0;
355 break;
356 case 24000:
357 rate = FS1 | FS0;
358 break;
359 case 29400:
360 rate = FS3 | FS2 | FS1;
361 break;
362 case 32000:
363 rate = FS3 | FS1;
364 break;
365 case 44100:
366 rate = FS3 | FS2 | FS1 | FS0;
367 break;
368 case 48000:
369 rate = FS3 | FS1 | FS0;
370 break;
371 default:
372 return -EINVAL;
373 break;
374 }
375 snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate);
253 376
254 ak4642->sysclk = freq;
255 return 0; 377 return 0;
256} 378}
257 379
@@ -259,6 +381,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = {
259 .startup = ak4642_dai_startup, 381 .startup = ak4642_dai_startup,
260 .shutdown = ak4642_dai_shutdown, 382 .shutdown = ak4642_dai_shutdown,
261 .set_sysclk = ak4642_dai_set_sysclk, 383 .set_sysclk = ak4642_dai_set_sysclk,
384 .set_fmt = ak4642_dai_set_fmt,
385 .hw_params = ak4642_dai_hw_params,
262}; 386};
263 387
264struct snd_soc_dai ak4642_dai = { 388struct snd_soc_dai ak4642_dai = {
@@ -276,6 +400,7 @@ struct snd_soc_dai ak4642_dai = {
276 .rates = SNDRV_PCM_RATE_8000_48000, 400 .rates = SNDRV_PCM_RATE_8000_48000,
277 .formats = SNDRV_PCM_FMTBIT_S16_LE }, 401 .formats = SNDRV_PCM_FMTBIT_S16_LE },
278 .ops = &ak4642_dai_ops, 402 .ops = &ak4642_dai_ops,
403 .symmetric_rates = 1,
279}; 404};
280EXPORT_SYMBOL_GPL(ak4642_dai); 405EXPORT_SYMBOL_GPL(ak4642_dai);
281 406
@@ -337,26 +462,6 @@ static int ak4642_init(struct ak4642_priv *ak4642)
337 goto reg_cache_err; 462 goto reg_cache_err;
338 } 463 }
339 464
340 /*
341 * clock setting
342 *
343 * Audio I/F Format: MSB justified (ADC & DAC)
344 * BICK frequency at Master Mode: 64fs
345 * Input Master Clock Select at PLL Mode: 11.2896MHz
346 * MCKO: Enable
347 * Sampling Frequency: 44.1kHz
348 *
349 * This operation came from example code of
350 * "ASAHI KASEI AK4642" (japanese) manual p89.
351 *
352 * please fix-me
353 */
354 ak4642_write(codec, 0x01, 0x08);
355 ak4642_write(codec, 0x04, 0x4a);
356 ak4642_write(codec, 0x05, 0x27);
357 ak4642_write(codec, 0x00, 0x40);
358 ak4642_write(codec, 0x01, 0x0b);
359
360 return ret; 465 return ret;
361 466
362reg_cache_err: 467reg_cache_err:
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
new file mode 100644
index 000000000000..8f19b9310645
--- /dev/null
+++ b/sound/soc/codecs/cq93vc.c
@@ -0,0 +1,299 @@
1/*
2 * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/init.h>
25#include <linux/io.h>
26#include <linux/delay.h>
27#include <linux/pm.h>
28#include <linux/platform_device.h>
29#include <linux/device.h>
30#include <linux/slab.h>
31#include <linux/clk.h>
32#include <linux/mfd/davinci_voicecodec.h>
33
34#include <sound/core.h>
35#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37#include <sound/soc.h>
38#include <sound/soc-dai.h>
39#include <sound/soc-dapm.h>
40#include <sound/initval.h>
41
42#include <mach/dm365.h>
43
44#include "cq93vc.h"
45
46static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
47 unsigned int reg)
48{
49 struct davinci_vc *davinci_vc = codec->control_data;
50
51 return readl(davinci_vc->base + reg);
52}
53
54static inline int cq93vc_write(struct snd_soc_codec *codec, unsigned int reg,
55 unsigned int value)
56{
57 struct davinci_vc *davinci_vc = codec->control_data;
58
59 writel(value, davinci_vc->base + reg);
60
61 return 0;
62}
63
64static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
65 SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0),
66 SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0),
67};
68
69static int cq93vc_mute(struct snd_soc_dai *dai, int mute)
70{
71 struct snd_soc_codec *codec = dai->codec;
72 u8 reg = cq93vc_read(codec, DAVINCI_VC_REG09) & ~DAVINCI_VC_REG09_MUTE;
73
74 if (mute)
75 cq93vc_write(codec, DAVINCI_VC_REG09,
76 reg | DAVINCI_VC_REG09_MUTE);
77 else
78 cq93vc_write(codec, DAVINCI_VC_REG09, reg);
79
80 return 0;
81}
82
83static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai,
84 int clk_id, unsigned int freq, int dir)
85{
86 struct snd_soc_codec *codec = codec_dai->codec;
87 struct davinci_vc *davinci_vc = codec->control_data;
88
89 switch (freq) {
90 case 22579200:
91 case 27000000:
92 case 33868800:
93 davinci_vc->cq93vc.sysclk = freq;
94 return 0;
95 }
96
97 return -EINVAL;
98}
99
100static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
101 enum snd_soc_bias_level level)
102{
103 switch (level) {
104 case SND_SOC_BIAS_ON:
105 cq93vc_write(codec, DAVINCI_VC_REG12,
106 DAVINCI_VC_REG12_POWER_ALL_ON);
107 break;
108 case SND_SOC_BIAS_PREPARE:
109 break;
110 case SND_SOC_BIAS_STANDBY:
111 cq93vc_write(codec, DAVINCI_VC_REG12,
112 DAVINCI_VC_REG12_POWER_ALL_OFF);
113 break;
114 case SND_SOC_BIAS_OFF:
115 /* force all power off */
116 cq93vc_write(codec, DAVINCI_VC_REG12,
117 DAVINCI_VC_REG12_POWER_ALL_OFF);
118 break;
119 }
120 codec->bias_level = level;
121
122 return 0;
123}
124
125#define CQ93VC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
126#define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
127
128static struct snd_soc_dai_ops cq93vc_dai_ops = {
129 .digital_mute = cq93vc_mute,
130 .set_sysclk = cq93vc_set_dai_sysclk,
131};
132
133struct snd_soc_dai cq93vc_dai = {
134 .name = "CQ93VC",
135 .playback = {
136 .stream_name = "Playback",
137 .channels_min = 1,
138 .channels_max = 2,
139 .rates = CQ93VC_RATES,
140 .formats = CQ93VC_FORMATS,},
141 .capture = {
142 .stream_name = "Capture",
143 .channels_min = 1,
144 .channels_max = 2,
145 .rates = CQ93VC_RATES,
146 .formats = CQ93VC_FORMATS,},
147 .ops = &cq93vc_dai_ops,
148};
149EXPORT_SYMBOL_GPL(cq93vc_dai);
150
151static int cq93vc_resume(struct platform_device *pdev)
152{
153 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
154 struct snd_soc_codec *codec = socdev->card->codec;
155
156 cq93vc_set_bias_level(codec, codec->suspend_bias_level);
157
158 return 0;
159}
160
161static struct snd_soc_codec *cq93vc_codec;
162
163static int cq93vc_probe(struct platform_device *pdev)
164{
165 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
166 struct device *dev = &pdev->dev;
167 struct snd_soc_codec *codec;
168 int ret;
169
170 socdev->card->codec = cq93vc_codec;
171 codec = socdev->card->codec;
172
173 /* Register pcms */
174 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
175 if (ret < 0) {
176 dev_err(dev, "%s: failed to create pcms\n", pdev->name);
177 return ret;
178 }
179
180 /* Set controls */
181 snd_soc_add_controls(codec, cq93vc_snd_controls,
182 ARRAY_SIZE(cq93vc_snd_controls));
183
184 /* Off, with power on */
185 cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
186
187 return 0;
188}
189
190static int cq93vc_remove(struct platform_device *pdev)
191{
192 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
193
194 snd_soc_free_pcms(socdev);
195 snd_soc_dapm_free(socdev);
196
197 return 0;
198}
199
200struct snd_soc_codec_device soc_codec_dev_cq93vc = {
201 .probe = cq93vc_probe,
202 .remove = cq93vc_remove,
203 .resume = cq93vc_resume,
204};
205EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc);
206
207static __init int cq93vc_codec_probe(struct platform_device *pdev)
208{
209 struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
210 struct snd_soc_codec *codec;
211 int ret;
212
213 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
214 if (codec == NULL) {
215 dev_dbg(davinci_vc->dev,
216 "could not allocate memory for codec data\n");
217 return -ENOMEM;
218 }
219
220 davinci_vc->cq93vc.codec = codec;
221
222 cq93vc_dai.dev = &pdev->dev;
223
224 mutex_init(&codec->mutex);
225 INIT_LIST_HEAD(&codec->dapm_widgets);
226 INIT_LIST_HEAD(&codec->dapm_paths);
227 codec->dev = &pdev->dev;
228 codec->name = "CQ93VC";
229 codec->owner = THIS_MODULE;
230 codec->read = cq93vc_read;
231 codec->write = cq93vc_write;
232 codec->set_bias_level = cq93vc_set_bias_level;
233 codec->dai = &cq93vc_dai;
234 codec->num_dai = 1;
235 codec->control_data = davinci_vc;
236
237 cq93vc_codec = codec;
238
239 ret = snd_soc_register_codec(codec);
240 if (ret) {
241 dev_err(davinci_vc->dev, "failed to register codec\n");
242 goto fail1;
243 }
244
245 ret = snd_soc_register_dai(&cq93vc_dai);
246 if (ret) {
247 dev_err(davinci_vc->dev, "could register dai\n");
248 goto fail2;
249 }
250 return 0;
251
252fail2:
253 snd_soc_unregister_codec(codec);
254
255fail1:
256 kfree(codec);
257 cq93vc_codec = NULL;
258
259 return ret;
260}
261
262static int __devexit cq93vc_codec_remove(struct platform_device *pdev)
263{
264 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
265 struct snd_soc_codec *codec = socdev->card->codec;
266
267 snd_soc_unregister_dai(&cq93vc_dai);
268 snd_soc_unregister_codec(&codec);
269
270 kfree(codec);
271 cq93vc_codec = NULL;
272
273 return 0;
274}
275
276static struct platform_driver cq93vc_codec_driver = {
277 .driver = {
278 .name = "cq93vc",
279 .owner = THIS_MODULE,
280 },
281 .probe = cq93vc_codec_probe,
282 .remove = __devexit_p(cq93vc_codec_remove),
283};
284
285static __init int cq93vc_init(void)
286{
287 return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe);
288}
289module_init(cq93vc_init);
290
291static __exit void cq93vc_exit(void)
292{
293 platform_driver_unregister(&cq93vc_codec_driver);
294}
295module_exit(cq93vc_exit);
296
297MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver");
298MODULE_AUTHOR("Miguel Aguilar");
299MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h
new file mode 100644
index 000000000000..845b1968ef9c
--- /dev/null
+++ b/sound/soc/codecs/cq93vc.h
@@ -0,0 +1,29 @@
1/*
2 * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifndef _CQ93VC_H
24#define _CQ93VC_H
25
26extern struct snd_soc_dai cq93vc_dai;
27extern struct snd_soc_codec_device soc_codec_dev_cq93vc;
28
29#endif
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index cf2975a7294a..35b881638658 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -55,8 +55,14 @@
55#define DA7210_DAI_SRC_SEL 0x25 55#define DA7210_DAI_SRC_SEL 0x25
56#define DA7210_DAI_CFG1 0x26 56#define DA7210_DAI_CFG1 0x26
57#define DA7210_DAI_CFG3 0x28 57#define DA7210_DAI_CFG3 0x28
58#define DA7210_PLL_DIV1 0x29
59#define DA7210_PLL_DIV2 0x2A
58#define DA7210_PLL_DIV3 0x2B 60#define DA7210_PLL_DIV3 0x2B
59#define DA7210_PLL 0x2C 61#define DA7210_PLL 0x2C
62#define DA7210_A_HID_UNLOCK 0x8A
63#define DA7210_A_TEST_UNLOCK 0x8B
64#define DA7210_A_PLL1 0x90
65#define DA7210_A_CP_MODE 0xA7
60 66
61/* STARTUP1 bit fields */ 67/* STARTUP1 bit fields */
62#define DA7210_SC_MST_EN (1 << 0) 68#define DA7210_SC_MST_EN (1 << 0)
@@ -74,15 +80,14 @@
74/* INMIX_R bit fields */ 80/* INMIX_R bit fields */
75#define DA7210_IN_R_EN (1 << 7) 81#define DA7210_IN_R_EN (1 << 7)
76 82
77/* ADC_HPF bit fields */
78#define DA7210_ADC_VOICE_EN (1 << 7)
79
80/* ADC bit fields */ 83/* ADC bit fields */
81#define DA7210_ADC_L_EN (1 << 3) 84#define DA7210_ADC_L_EN (1 << 3)
82#define DA7210_ADC_R_EN (1 << 7) 85#define DA7210_ADC_R_EN (1 << 7)
83 86
84/* DAC_HPF fields */ 87/* DAC/ADC HPF fields */
85#define DA7210_DAC_VOICE_EN (1 << 7) 88#define DA7210_VOICE_F0_MASK (0x7 << 4)
89#define DA7210_VOICE_F0_25 (1 << 4)
90#define DA7210_VOICE_EN (1 << 7)
86 91
87/* DAC_SEL bit fields */ 92/* DAC_SEL bit fields */
88#define DA7210_DAC_L_SRC_DAI_L (4 << 0) 93#define DA7210_DAC_L_SRC_DAI_L (4 << 0)
@@ -123,7 +128,19 @@
123#define DA7210_PLL_BYP (1 << 6) 128#define DA7210_PLL_BYP (1 << 6)
124 129
125/* PLL bit fields */ 130/* PLL bit fields */
126#define DA7210_PLL_FS_48000 (11 << 0) 131#define DA7210_PLL_FS_MASK (0xF << 0)
132#define DA7210_PLL_FS_8000 (0x1 << 0)
133#define DA7210_PLL_FS_11025 (0x2 << 0)
134#define DA7210_PLL_FS_12000 (0x3 << 0)
135#define DA7210_PLL_FS_16000 (0x5 << 0)
136#define DA7210_PLL_FS_22050 (0x6 << 0)
137#define DA7210_PLL_FS_24000 (0x7 << 0)
138#define DA7210_PLL_FS_32000 (0x9 << 0)
139#define DA7210_PLL_FS_44100 (0xA << 0)
140#define DA7210_PLL_FS_48000 (0xB << 0)
141#define DA7210_PLL_FS_88200 (0xE << 0)
142#define DA7210_PLL_FS_96000 (0xF << 0)
143#define DA7210_PLL_EN (0x1 << 7)
127 144
128#define DA7210_VERSION "0.0.1" 145#define DA7210_VERSION "0.0.1"
129 146
@@ -241,7 +258,8 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
241 struct snd_soc_device *socdev = rtd->socdev; 258 struct snd_soc_device *socdev = rtd->socdev;
242 struct snd_soc_codec *codec = socdev->card->codec; 259 struct snd_soc_codec *codec = socdev->card->codec;
243 u32 dai_cfg1; 260 u32 dai_cfg1;
244 u32 reg, mask; 261 u32 hpf_reg, hpf_mask, hpf_value;
262 u32 fs, bypass;
245 263
246 /* set DAI source to Left and Right ADC */ 264 /* set DAI source to Left and Right ADC */
247 da7210_write(codec, DA7210_DAI_SRC_SEL, 265 da7210_write(codec, DA7210_DAI_SRC_SEL,
@@ -265,25 +283,84 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
265 283
266 da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1); 284 da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
267 285
268 /* FIXME 286 hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ?
269 * 287 DA7210_DAC_HPF : DA7210_ADC_HPF;
270 * It support 48K only now 288
271 */
272 switch (params_rate(params)) { 289 switch (params_rate(params)) {
290 case 8000:
291 fs = DA7210_PLL_FS_8000;
292 hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
293 hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
294 bypass = DA7210_PLL_BYP;
295 break;
296 case 11025:
297 fs = DA7210_PLL_FS_11025;
298 hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
299 hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
300 bypass = 0;
301 break;
302 case 12000:
303 fs = DA7210_PLL_FS_12000;
304 hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
305 hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
306 bypass = DA7210_PLL_BYP;
307 break;
308 case 16000:
309 fs = DA7210_PLL_FS_16000;
310 hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
311 hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
312 bypass = DA7210_PLL_BYP;
313 break;
314 case 22050:
315 fs = DA7210_PLL_FS_22050;
316 hpf_mask = DA7210_VOICE_EN;
317 hpf_value = 0;
318 bypass = 0;
319 break;
320 case 32000:
321 fs = DA7210_PLL_FS_32000;
322 hpf_mask = DA7210_VOICE_EN;
323 hpf_value = 0;
324 bypass = DA7210_PLL_BYP;
325 break;
326 case 44100:
327 fs = DA7210_PLL_FS_44100;
328 hpf_mask = DA7210_VOICE_EN;
329 hpf_value = 0;
330 bypass = 0;
331 break;
273 case 48000: 332 case 48000:
274 if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { 333 fs = DA7210_PLL_FS_48000;
275 reg = DA7210_DAC_HPF; 334 hpf_mask = DA7210_VOICE_EN;
276 mask = DA7210_DAC_VOICE_EN; 335 hpf_value = 0;
277 } else { 336 bypass = DA7210_PLL_BYP;
278 reg = DA7210_ADC_HPF; 337 break;
279 mask = DA7210_ADC_VOICE_EN; 338 case 88200:
280 } 339 fs = DA7210_PLL_FS_88200;
340 hpf_mask = DA7210_VOICE_EN;
341 hpf_value = 0;
342 bypass = 0;
343 break;
344 case 96000:
345 fs = DA7210_PLL_FS_96000;
346 hpf_mask = DA7210_VOICE_EN;
347 hpf_value = 0;
348 bypass = DA7210_PLL_BYP;
281 break; 349 break;
282 default: 350 default:
283 return -EINVAL; 351 return -EINVAL;
284 } 352 }
285 353
286 snd_soc_update_bits(codec, reg, mask, 0); 354 /* Disable active mode */
355 snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0);
356
357 snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value);
358 snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs);
359 snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass);
360
361 /* Enable active mode */
362 snd_soc_update_bits(codec, DA7210_STARTUP1,
363 DA7210_SC_MST_EN, DA7210_SC_MST_EN);
287 364
288 return 0; 365 return 0;
289} 366}
@@ -361,6 +438,7 @@ struct snd_soc_dai da7210_dai = {
361 .formats = DA7210_FORMATS, 438 .formats = DA7210_FORMATS,
362 }, 439 },
363 .ops = &da7210_dai_ops, 440 .ops = &da7210_dai_ops,
441 .symmetric_rates = 1,
364}; 442};
365EXPORT_SYMBOL_GPL(da7210_dai); 443EXPORT_SYMBOL_GPL(da7210_dai);
366 444
@@ -415,9 +493,23 @@ static int da7210_init(struct da7210_priv *da7210)
415 /* FIXME 493 /* FIXME
416 * 494 *
417 * This driver use fixed value here 495 * This driver use fixed value here
496 * And below settings expects MCLK = 12.288MHz
497 *
498 * When you select different MCLK, please check...
499 * DA7210_PLL_DIV1 val
500 * DA7210_PLL_DIV2 val
501 * DA7210_PLL_DIV3 val
502 * DA7210_PLL_DIV3 :: DA7210_MCLK_RANGExxx
418 */ 503 */
419 504
420 /* 505 /*
506 * make sure that DA7210 use bypass mode before start up
507 */
508 da7210_write(codec, DA7210_STARTUP1, 0);
509 da7210_write(codec, DA7210_PLL_DIV3,
510 DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
511
512 /*
421 * ADC settings 513 * ADC settings
422 */ 514 */
423 515
@@ -453,9 +545,28 @@ static int da7210_init(struct da7210_priv *da7210)
453 /* Diable PLL and bypass it */ 545 /* Diable PLL and bypass it */
454 da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000); 546 da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
455 547
456 /* Bypass PLL and set MCLK freq rang to 10-20MHz */ 548 /*
457 da7210_write(codec, DA7210_PLL_DIV3, 549 * If 48kHz sound came, it use bypass mode,
550 * and when it is 44.1kHz, it use PLL.
551 *
552 * This time, this driver sets PLL always ON
553 * and controls bypass/PLL mode by switching
554 * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit.
555 * see da7210_hw_params
556 */
557 da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
558 da7210_write(codec, DA7210_PLL_DIV2, 0x99);
559 da7210_write(codec, DA7210_PLL_DIV3, 0x0A |
458 DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); 560 DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
561 snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
562
563 /* As suggested by Dialog */
564 da7210_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */
565 da7210_write(codec, DA7210_A_TEST_UNLOCK, 0xB4);
566 da7210_write(codec, DA7210_A_PLL1, 0x01);
567 da7210_write(codec, DA7210_A_CP_MODE, 0x7C);
568 da7210_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */
569 da7210_write(codec, DA7210_A_TEST_UNLOCK, 0x00);
459 570
460 /* Activate all enabled subsystem */ 571 /* Activate all enabled subsystem */
461 da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); 572 da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index d2ff1cde6883..942f5dc30801 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -139,6 +139,7 @@ SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0),
139SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), 139SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1),
140 140
141SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), 141SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
142SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 7, 1, 0),
142SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), 143SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
143 144
144SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1), 145SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1),
@@ -604,8 +605,7 @@ static int ssm2602_init(struct snd_soc_device *socdev)
604 reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); 605 reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V);
605 ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); 606 ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
606 /*select Line in as default input*/ 607 /*select Line in as default input*/
607 ssm2602_write(codec, SSM2602_APANA, 608 ssm2602_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
608 APANA_ENABLE_MIC_BOOST2 | APANA_SELECT_DAC |
609 APANA_ENABLE_MIC_BOOST); 609 APANA_ENABLE_MIC_BOOST);
610 ssm2602_write(codec, SSM2602_PWR, 0); 610 ssm2602_write(codec, SSM2602_PWR, 0);
611 611
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index d50f1699ccb2..ee2e1e36d995 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -93,6 +93,8 @@ struct tlv320dac33_priv {
93 unsigned int nsample; /* burst read amount from host */ 93 unsigned int nsample; /* burst read amount from host */
94 u8 burst_bclkdiv; /* BCLK divider value in burst mode */ 94 u8 burst_bclkdiv; /* BCLK divider value in burst mode */
95 95
96 int keep_bclk; /* Keep the BCLK continuously running
97 * in FIFO modes */
96 enum dac33_state state; 98 enum dac33_state state;
97}; 99};
98 100
@@ -310,7 +312,8 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
310 if (power) 312 if (power)
311 reg |= DAC33_PDNALLB; 313 reg |= DAC33_PDNALLB;
312 else 314 else
313 reg &= ~DAC33_PDNALLB; 315 reg &= ~(DAC33_PDNALLB | DAC33_OSCPDNB |
316 DAC33_DACRPDNB | DAC33_DACLPDNB);
314 dac33_write(codec, DAC33_PWR_CTRL, reg); 317 dac33_write(codec, DAC33_PWR_CTRL, reg);
315} 318}
316 319
@@ -634,26 +637,6 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev)
634 return IRQ_HANDLED; 637 return IRQ_HANDLED;
635} 638}
636 639
637static void dac33_shutdown(struct snd_pcm_substream *substream,
638 struct snd_soc_dai *dai)
639{
640 struct snd_soc_pcm_runtime *rtd = substream->private_data;
641 struct snd_soc_device *socdev = rtd->socdev;
642 struct snd_soc_codec *codec = socdev->card->codec;
643 struct tlv320dac33_priv *dac33 = codec->private_data;
644 unsigned int pwr_ctrl;
645
646 /* Stop pending workqueue */
647 if (dac33->fifo_mode)
648 cancel_work_sync(&dac33->work);
649
650 mutex_lock(&dac33->mutex);
651 pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
652 pwr_ctrl &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB);
653 dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl);
654 mutex_unlock(&dac33->mutex);
655}
656
657static void dac33_oscwait(struct snd_soc_codec *codec) 640static void dac33_oscwait(struct snd_soc_codec *codec)
658{ 641{
659 int timeout = 20; 642 int timeout = 20;
@@ -751,6 +734,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
751 } 734 }
752 735
753 mutex_lock(&dac33->mutex); 736 mutex_lock(&dac33->mutex);
737 dac33_soft_power(codec, 0);
754 dac33_soft_power(codec, 1); 738 dac33_soft_power(codec, 1);
755 739
756 reg_tmp = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL); 740 reg_tmp = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL);
@@ -821,7 +805,10 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
821 */ 805 */
822 fifoctrl_a &= ~DAC33_FBYPAS; 806 fifoctrl_a &= ~DAC33_FBYPAS;
823 fifoctrl_a &= ~DAC33_FAUTO; 807 fifoctrl_a &= ~DAC33_FAUTO;
824 aictrl_b &= ~DAC33_BCLKON; 808 if (dac33->keep_bclk)
809 aictrl_b |= DAC33_BCLKON;
810 else
811 aictrl_b &= ~DAC33_BCLKON;
825 break; 812 break;
826 case DAC33_FIFO_MODE7: 813 case DAC33_FIFO_MODE7:
827 /* 814 /*
@@ -832,7 +819,10 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
832 */ 819 */
833 fifoctrl_a &= ~DAC33_FBYPAS; 820 fifoctrl_a &= ~DAC33_FBYPAS;
834 fifoctrl_a |= DAC33_FAUTO; 821 fifoctrl_a |= DAC33_FAUTO;
835 aictrl_b &= ~DAC33_BCLKON; 822 if (dac33->keep_bclk)
823 aictrl_b |= DAC33_BCLKON;
824 else
825 aictrl_b &= ~DAC33_BCLKON;
836 break; 826 break;
837 default: 827 default:
838 /* 828 /*
@@ -1181,7 +1171,6 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
1181#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE 1171#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE
1182 1172
1183static struct snd_soc_dai_ops dac33_dai_ops = { 1173static struct snd_soc_dai_ops dac33_dai_ops = {
1184 .shutdown = dac33_shutdown,
1185 .hw_params = dac33_hw_params, 1174 .hw_params = dac33_hw_params,
1186 .prepare = dac33_pcm_prepare, 1175 .prepare = dac33_pcm_prepare,
1187 .trigger = dac33_pcm_trigger, 1176 .trigger = dac33_pcm_trigger,
@@ -1249,6 +1238,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
1249 1238
1250 dac33->power_gpio = pdata->power_gpio; 1239 dac33->power_gpio = pdata->power_gpio;
1251 dac33->burst_bclkdiv = pdata->burst_bclkdiv; 1240 dac33->burst_bclkdiv = pdata->burst_bclkdiv;
1241 dac33->keep_bclk = pdata->keep_bclk;
1252 dac33->irq = client->irq; 1242 dac33->irq = client->irq;
1253 dac33->nsample = NSAMPLE_MAX; 1243 dac33->nsample = NSAMPLE_MAX;
1254 /* Disable FIFO use by default */ 1244 /* Disable FIFO use by default */
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 6f5d4af20052..bf59b8a4d1d7 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -135,9 +135,11 @@ struct twl4030_priv {
135 135
136 unsigned int sysclk; 136 unsigned int sysclk;
137 137
138 /* Headset output state handling */ 138 /* Output (with associated amp) states */
139 unsigned int hsl_enabled; 139 u8 hsl_enabled, hsr_enabled;
140 unsigned int hsr_enabled; 140 u8 earpiece_enabled;
141 u8 predrivel_enabled, predriver_enabled;
142 u8 carkitl_enabled, carkitr_enabled;
141}; 143};
142 144
143/* 145/*
@@ -173,12 +175,47 @@ static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
173static int twl4030_write(struct snd_soc_codec *codec, 175static int twl4030_write(struct snd_soc_codec *codec,
174 unsigned int reg, unsigned int value) 176 unsigned int reg, unsigned int value)
175{ 177{
178 struct twl4030_priv *twl4030 = codec->private_data;
179 int write_to_reg = 0;
180
176 twl4030_write_reg_cache(codec, reg, value); 181 twl4030_write_reg_cache(codec, reg, value);
177 if (likely(reg < TWL4030_REG_SW_SHADOW)) 182 if (likely(reg < TWL4030_REG_SW_SHADOW)) {
178 return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, 183 /* Decide if the given register can be written */
179 reg); 184 switch (reg) {
180 else 185 case TWL4030_REG_EAR_CTL:
181 return 0; 186 if (twl4030->earpiece_enabled)
187 write_to_reg = 1;
188 break;
189 case TWL4030_REG_PREDL_CTL:
190 if (twl4030->predrivel_enabled)
191 write_to_reg = 1;
192 break;
193 case TWL4030_REG_PREDR_CTL:
194 if (twl4030->predriver_enabled)
195 write_to_reg = 1;
196 break;
197 case TWL4030_REG_PRECKL_CTL:
198 if (twl4030->carkitl_enabled)
199 write_to_reg = 1;
200 break;
201 case TWL4030_REG_PRECKR_CTL:
202 if (twl4030->carkitr_enabled)
203 write_to_reg = 1;
204 break;
205 case TWL4030_REG_HS_GAIN_SET:
206 if (twl4030->hsl_enabled || twl4030->hsr_enabled)
207 write_to_reg = 1;
208 break;
209 default:
210 /* All other register can be written */
211 write_to_reg = 1;
212 break;
213 }
214 if (write_to_reg)
215 return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
216 value, reg);
217 }
218 return 0;
182} 219}
183 220
184static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 221static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
@@ -525,26 +562,26 @@ static int micpath_event(struct snd_soc_dapm_widget *w,
525 * Output PGA builder: 562 * Output PGA builder:
526 * Handle the muting and unmuting of the given output (turning off the 563 * Handle the muting and unmuting of the given output (turning off the
527 * amplifier associated with the output pin) 564 * amplifier associated with the output pin)
528 * On mute bypass the reg_cache and mute the volume 565 * On mute bypass the reg_cache and write 0 to the register
529 * On unmute: restore the register content 566 * On unmute: restore the register content from the reg_cache
530 * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R 567 * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R
531 */ 568 */
532#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \ 569#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \
533static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ 570static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \
534 struct snd_kcontrol *kcontrol, int event) \ 571 struct snd_kcontrol *kcontrol, int event) \
535{ \ 572{ \
536 u8 reg_val; \ 573 struct twl4030_priv *twl4030 = w->codec->private_data; \
537 \ 574 \
538 switch (event) { \ 575 switch (event) { \
539 case SND_SOC_DAPM_POST_PMU: \ 576 case SND_SOC_DAPM_POST_PMU: \
577 twl4030->pin_name##_enabled = 1; \
540 twl4030_write(w->codec, reg, \ 578 twl4030_write(w->codec, reg, \
541 twl4030_read_reg_cache(w->codec, reg)); \ 579 twl4030_read_reg_cache(w->codec, reg)); \
542 break; \ 580 break; \
543 case SND_SOC_DAPM_POST_PMD: \ 581 case SND_SOC_DAPM_POST_PMD: \
544 reg_val = twl4030_read_reg_cache(w->codec, reg); \ 582 twl4030->pin_name##_enabled = 0; \
545 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ 583 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \
546 reg_val & (~mask), \ 584 0, reg); \
547 reg); \
548 break; \ 585 break; \
549 } \ 586 } \
550 return 0; \ 587 return 0; \
@@ -664,7 +701,10 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
664 /* Headset ramp-up according to the TRM */ 701 /* Headset ramp-up according to the TRM */
665 hs_pop |= TWL4030_VMID_EN; 702 hs_pop |= TWL4030_VMID_EN;
666 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 703 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
667 twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain); 704 /* Actually write to the register */
705 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
706 hs_gain,
707 TWL4030_REG_HS_GAIN_SET);
668 hs_pop |= TWL4030_RAMP_EN; 708 hs_pop |= TWL4030_RAMP_EN;
669 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 709 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
670 /* Wait ramp delay time + 1, so the VMID can settle */ 710 /* Wait ramp delay time + 1, so the VMID can settle */
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
new file mode 100644
index 000000000000..108c51a513c8
--- /dev/null
+++ b/sound/soc/codecs/twl6040.c
@@ -0,0 +1,1228 @@
1/*
2 * ALSA SoC TWL6040 codec driver
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/pm.h>
27#include <linux/i2c.h>
28#include <linux/gpio.h>
29#include <linux/platform_device.h>
30#include <linux/slab.h>
31#include <linux/i2c/twl.h>
32
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37#include <sound/soc-dapm.h>
38#include <sound/initval.h>
39#include <sound/tlv.h>
40
41#include "twl6040.h"
42
43#define TWL6040_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
44#define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
45
46/* codec private data */
47struct twl6040_data {
48 struct snd_soc_codec codec;
49 int audpwron;
50 int naudint;
51 int codec_powered;
52 int pll;
53 int non_lp;
54 unsigned int sysclk;
55 struct snd_pcm_hw_constraint_list *sysclk_constraints;
56 struct completion ready;
57};
58
59/*
60 * twl6040 register cache & default register settings
61 */
62static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
63 0x00, /* not used 0x00 */
64 0x4B, /* TWL6040_ASICID (ro) 0x01 */
65 0x00, /* TWL6040_ASICREV (ro) 0x02 */
66 0x00, /* TWL6040_INTID 0x03 */
67 0x00, /* TWL6040_INTMR 0x04 */
68 0x00, /* TWL6040_NCPCTRL 0x05 */
69 0x00, /* TWL6040_LDOCTL 0x06 */
70 0x60, /* TWL6040_HPPLLCTL 0x07 */
71 0x00, /* TWL6040_LPPLLCTL 0x08 */
72 0x4A, /* TWL6040_LPPLLDIV 0x09 */
73 0x00, /* TWL6040_AMICBCTL 0x0A */
74 0x00, /* TWL6040_DMICBCTL 0x0B */
75 0x18, /* TWL6040_MICLCTL 0x0C - No input selected on Left Mic */
76 0x18, /* TWL6040_MICRCTL 0x0D - No input selected on Right Mic */
77 0x00, /* TWL6040_MICGAIN 0x0E */
78 0x1B, /* TWL6040_LINEGAIN 0x0F */
79 0x00, /* TWL6040_HSLCTL 0x10 */
80 0x00, /* TWL6040_HSRCTL 0x11 */
81 0x00, /* TWL6040_HSGAIN 0x12 */
82 0x00, /* TWL6040_EARCTL 0x13 */
83 0x00, /* TWL6040_HFLCTL 0x14 */
84 0x00, /* TWL6040_HFLGAIN 0x15 */
85 0x00, /* TWL6040_HFRCTL 0x16 */
86 0x00, /* TWL6040_HFRGAIN 0x17 */
87 0x00, /* TWL6040_VIBCTLL 0x18 */
88 0x00, /* TWL6040_VIBDATL 0x19 */
89 0x00, /* TWL6040_VIBCTLR 0x1A */
90 0x00, /* TWL6040_VIBDATR 0x1B */
91 0x00, /* TWL6040_HKCTL1 0x1C */
92 0x00, /* TWL6040_HKCTL2 0x1D */
93 0x00, /* TWL6040_GPOCTL 0x1E */
94 0x00, /* TWL6040_ALB 0x1F */
95 0x00, /* TWL6040_DLB 0x20 */
96 0x00, /* not used 0x21 */
97 0x00, /* not used 0x22 */
98 0x00, /* not used 0x23 */
99 0x00, /* not used 0x24 */
100 0x00, /* not used 0x25 */
101 0x00, /* not used 0x26 */
102 0x00, /* not used 0x27 */
103 0x00, /* TWL6040_TRIM1 0x28 */
104 0x00, /* TWL6040_TRIM2 0x29 */
105 0x00, /* TWL6040_TRIM3 0x2A */
106 0x00, /* TWL6040_HSOTRIM 0x2B */
107 0x00, /* TWL6040_HFOTRIM 0x2C */
108 0x09, /* TWL6040_ACCCTL 0x2D */
109 0x00, /* TWL6040_STATUS (ro) 0x2E */
110};
111
112/*
113 * twl6040 vio/gnd registers:
114 * registers under vio/gnd supply can be accessed
115 * before the power-up sequence, after NRESPWRON goes high
116 */
117static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = {
118 TWL6040_REG_ASICID,
119 TWL6040_REG_ASICREV,
120 TWL6040_REG_INTID,
121 TWL6040_REG_INTMR,
122 TWL6040_REG_NCPCTL,
123 TWL6040_REG_LDOCTL,
124 TWL6040_REG_AMICBCTL,
125 TWL6040_REG_DMICBCTL,
126 TWL6040_REG_HKCTL1,
127 TWL6040_REG_HKCTL2,
128 TWL6040_REG_GPOCTL,
129 TWL6040_REG_TRIM1,
130 TWL6040_REG_TRIM2,
131 TWL6040_REG_TRIM3,
132 TWL6040_REG_HSOTRIM,
133 TWL6040_REG_HFOTRIM,
134 TWL6040_REG_ACCCTL,
135 TWL6040_REG_STATUS,
136};
137
138/*
139 * twl6040 vdd/vss registers:
140 * registers under vdd/vss supplies can only be accessed
141 * after the power-up sequence
142 */
143static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
144 TWL6040_REG_HPPLLCTL,
145 TWL6040_REG_LPPLLCTL,
146 TWL6040_REG_LPPLLDIV,
147 TWL6040_REG_MICLCTL,
148 TWL6040_REG_MICRCTL,
149 TWL6040_REG_MICGAIN,
150 TWL6040_REG_LINEGAIN,
151 TWL6040_REG_HSLCTL,
152 TWL6040_REG_HSRCTL,
153 TWL6040_REG_HSGAIN,
154 TWL6040_REG_EARCTL,
155 TWL6040_REG_HFLCTL,
156 TWL6040_REG_HFLGAIN,
157 TWL6040_REG_HFRCTL,
158 TWL6040_REG_HFRGAIN,
159 TWL6040_REG_VIBCTLL,
160 TWL6040_REG_VIBDATL,
161 TWL6040_REG_VIBCTLR,
162 TWL6040_REG_VIBDATR,
163 TWL6040_REG_ALB,
164 TWL6040_REG_DLB,
165};
166
167/*
168 * read twl6040 register cache
169 */
170static inline unsigned int twl6040_read_reg_cache(struct snd_soc_codec *codec,
171 unsigned int reg)
172{
173 u8 *cache = codec->reg_cache;
174
175 if (reg >= TWL6040_CACHEREGNUM)
176 return -EIO;
177
178 return cache[reg];
179}
180
181/*
182 * write twl6040 register cache
183 */
184static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
185 u8 reg, u8 value)
186{
187 u8 *cache = codec->reg_cache;
188
189 if (reg >= TWL6040_CACHEREGNUM)
190 return;
191 cache[reg] = value;
192}
193
194/*
195 * read from twl6040 hardware register
196 */
197static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
198 unsigned int reg)
199{
200 u8 value;
201
202 if (reg >= TWL6040_CACHEREGNUM)
203 return -EIO;
204
205 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &value, reg);
206 twl6040_write_reg_cache(codec, reg, value);
207
208 return value;
209}
210
211/*
212 * write to the twl6040 register space
213 */
214static int twl6040_write(struct snd_soc_codec *codec,
215 unsigned int reg, unsigned int value)
216{
217 if (reg >= TWL6040_CACHEREGNUM)
218 return -EIO;
219
220 twl6040_write_reg_cache(codec, reg, value);
221 return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
222}
223
224static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
225{
226 u8 *cache = codec->reg_cache;
227 int reg, i;
228
229 /* allow registers to be accessed by i2c */
230 twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]);
231
232 for (i = 0; i < TWL6040_VIOREGNUM; i++) {
233 reg = twl6040_vio_reg[i];
234 /* skip read-only registers (ASICID, ASICREV, STATUS) */
235 switch (reg) {
236 case TWL6040_REG_ASICID:
237 case TWL6040_REG_ASICREV:
238 case TWL6040_REG_STATUS:
239 continue;
240 default:
241 break;
242 }
243 twl6040_write(codec, reg, cache[reg]);
244 }
245}
246
247static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
248{
249 u8 *cache = codec->reg_cache;
250 int reg, i;
251
252 for (i = 0; i < TWL6040_VDDREGNUM; i++) {
253 reg = twl6040_vdd_reg[i];
254 twl6040_write(codec, reg, cache[reg]);
255 }
256}
257
258/* twl6040 codec manual power-up sequence */
259static void twl6040_power_up(struct snd_soc_codec *codec)
260{
261 u8 ncpctl, ldoctl, lppllctl, accctl;
262
263 ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
264 ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
265 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
266 accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
267
268 /* enable reference system */
269 ldoctl |= TWL6040_REFENA;
270 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
271 msleep(10);
272 /* enable internal oscillator */
273 ldoctl |= TWL6040_OSCENA;
274 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
275 udelay(10);
276 /* enable high-side ldo */
277 ldoctl |= TWL6040_HSLDOENA;
278 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
279 udelay(244);
280 /* enable negative charge pump */
281 ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
282 twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
283 udelay(488);
284 /* enable low-side ldo */
285 ldoctl |= TWL6040_LSLDOENA;
286 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
287 udelay(244);
288 /* enable low-power pll */
289 lppllctl |= TWL6040_LPLLENA;
290 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
291 /* reset state machine */
292 accctl |= TWL6040_RESETSPLIT;
293 twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
294 mdelay(5);
295 accctl &= ~TWL6040_RESETSPLIT;
296 twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
297 /* disable internal oscillator */
298 ldoctl &= ~TWL6040_OSCENA;
299 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
300}
301
302/* twl6040 codec manual power-down sequence */
303static void twl6040_power_down(struct snd_soc_codec *codec)
304{
305 u8 ncpctl, ldoctl, lppllctl, accctl;
306
307 ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
308 ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
309 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
310 accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);
311
312 /* enable internal oscillator */
313 ldoctl |= TWL6040_OSCENA;
314 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
315 udelay(10);
316 /* disable low-power pll */
317 lppllctl &= ~TWL6040_LPLLENA;
318 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
319 /* disable low-side ldo */
320 ldoctl &= ~TWL6040_LSLDOENA;
321 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
322 udelay(244);
323 /* disable negative charge pump */
324 ncpctl &= ~(TWL6040_NCPENA | TWL6040_NCPOPEN);
325 twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
326 udelay(488);
327 /* disable high-side ldo */
328 ldoctl &= ~TWL6040_HSLDOENA;
329 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
330 udelay(244);
331 /* disable internal oscillator */
332 ldoctl &= ~TWL6040_OSCENA;
333 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
334 /* disable reference system */
335 ldoctl &= ~TWL6040_REFENA;
336 twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
337 msleep(10);
338}
339
340/* set headset dac and driver power mode */
341static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
342{
343 int hslctl, hsrctl;
344 int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;
345
346 hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
347 hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
348
349 if (high_perf) {
350 hslctl &= ~mask;
351 hsrctl &= ~mask;
352 } else {
353 hslctl |= mask;
354 hsrctl |= mask;
355 }
356
357 twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
358 twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
359
360 return 0;
361}
362
363static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
364 struct snd_kcontrol *kcontrol, int event)
365{
366 struct snd_soc_codec *codec = w->codec;
367 struct twl6040_data *priv = codec->private_data;
368
369 if (SND_SOC_DAPM_EVENT_ON(event))
370 priv->non_lp++;
371 else
372 priv->non_lp--;
373
374 return 0;
375}
376
377/* audio interrupt handler */
378static irqreturn_t twl6040_naudint_handler(int irq, void *data)
379{
380 struct snd_soc_codec *codec = data;
381 struct twl6040_data *priv = codec->private_data;
382 u8 intid;
383
384 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid, TWL6040_REG_INTID);
385
386 switch (intid) {
387 case TWL6040_THINT:
388 dev_alert(codec->dev, "die temp over-limit detection\n");
389 break;
390 case TWL6040_PLUGINT:
391 case TWL6040_UNPLUGINT:
392 case TWL6040_HOOKINT:
393 break;
394 case TWL6040_HFINT:
395 dev_alert(codec->dev, "hf drivers over current detection\n");
396 break;
397 case TWL6040_VIBINT:
398 dev_alert(codec->dev, "vib drivers over current detection\n");
399 break;
400 case TWL6040_READYINT:
401 complete(&priv->ready);
402 break;
403 default:
404 dev_err(codec->dev, "unknown audio interrupt %d\n", intid);
405 break;
406 }
407
408 return IRQ_HANDLED;
409}
410
411/*
412 * MICATT volume control:
413 * from -6 to 0 dB in 6 dB steps
414 */
415static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
416
417/*
418 * MICGAIN volume control:
419 * from 6 to 30 dB in 6 dB steps
420 */
421static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0);
422
423/*
424 * HSGAIN volume control:
425 * from -30 to 0 dB in 2 dB steps
426 */
427static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0);
428
429/*
430 * HFGAIN volume control:
431 * from -52 to 6 dB in 2 dB steps
432 */
433static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0);
434
435/* Left analog microphone selection */
436static const char *twl6040_amicl_texts[] =
437 {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
438
439/* Right analog microphone selection */
440static const char *twl6040_amicr_texts[] =
441 {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
442
443static const struct soc_enum twl6040_enum[] = {
444 SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 3, twl6040_amicl_texts),
445 SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 3, twl6040_amicr_texts),
446};
447
448static const struct snd_kcontrol_new amicl_control =
449 SOC_DAPM_ENUM("Route", twl6040_enum[0]);
450
451static const struct snd_kcontrol_new amicr_control =
452 SOC_DAPM_ENUM("Route", twl6040_enum[1]);
453
454/* Headset DAC playback switches */
455static const struct snd_kcontrol_new hsdacl_switch_controls =
456 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 5, 1, 0);
457
458static const struct snd_kcontrol_new hsdacr_switch_controls =
459 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 5, 1, 0);
460
461/* Handsfree DAC playback switches */
462static const struct snd_kcontrol_new hfdacl_switch_controls =
463 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 2, 1, 0);
464
465static const struct snd_kcontrol_new hfdacr_switch_controls =
466 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 2, 1, 0);
467
468/* Headset driver switches */
469static const struct snd_kcontrol_new hsl_driver_switch_controls =
470 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 2, 1, 0);
471
472static const struct snd_kcontrol_new hsr_driver_switch_controls =
473 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 2, 1, 0);
474
475/* Handsfree driver switches */
476static const struct snd_kcontrol_new hfl_driver_switch_controls =
477 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 4, 1, 0);
478
479static const struct snd_kcontrol_new hfr_driver_switch_controls =
480 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 4, 1, 0);
481
482static const struct snd_kcontrol_new twl6040_snd_controls[] = {
483 /* Capture gains */
484 SOC_DOUBLE_TLV("Capture Preamplifier Volume",
485 TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv),
486 SOC_DOUBLE_TLV("Capture Volume",
487 TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv),
488
489 /* Playback gains */
490 SOC_DOUBLE_TLV("Headset Playback Volume",
491 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
492 SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
493 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
494
495};
496
497static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
498 /* Inputs */
499 SND_SOC_DAPM_INPUT("MAINMIC"),
500 SND_SOC_DAPM_INPUT("HSMIC"),
501 SND_SOC_DAPM_INPUT("SUBMIC"),
502 SND_SOC_DAPM_INPUT("AFML"),
503 SND_SOC_DAPM_INPUT("AFMR"),
504
505 /* Outputs */
506 SND_SOC_DAPM_OUTPUT("HSOL"),
507 SND_SOC_DAPM_OUTPUT("HSOR"),
508 SND_SOC_DAPM_OUTPUT("HFL"),
509 SND_SOC_DAPM_OUTPUT("HFR"),
510
511 /* Analog input muxes for the capture amplifiers */
512 SND_SOC_DAPM_MUX("Analog Left Capture Route",
513 SND_SOC_NOPM, 0, 0, &amicl_control),
514 SND_SOC_DAPM_MUX("Analog Right Capture Route",
515 SND_SOC_NOPM, 0, 0, &amicr_control),
516
517 /* Analog capture PGAs */
518 SND_SOC_DAPM_PGA("MicAmpL",
519 TWL6040_REG_MICLCTL, 0, 0, NULL, 0),
520 SND_SOC_DAPM_PGA("MicAmpR",
521 TWL6040_REG_MICRCTL, 0, 0, NULL, 0),
522
523 /* ADCs */
524 SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture",
525 TWL6040_REG_MICLCTL, 2, 0),
526 SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture",
527 TWL6040_REG_MICRCTL, 2, 0),
528
529 /* Microphone bias */
530 SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
531 TWL6040_REG_AMICBCTL, 0, 0),
532 SND_SOC_DAPM_MICBIAS("Main Mic Bias",
533 TWL6040_REG_AMICBCTL, 4, 0),
534 SND_SOC_DAPM_MICBIAS("Digital Mic1 Bias",
535 TWL6040_REG_DMICBCTL, 0, 0),
536 SND_SOC_DAPM_MICBIAS("Digital Mic2 Bias",
537 TWL6040_REG_DMICBCTL, 4, 0),
538
539 /* DACs */
540 SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback",
541 TWL6040_REG_HSLCTL, 0, 0),
542 SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback",
543 TWL6040_REG_HSRCTL, 0, 0),
544 SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
545 TWL6040_REG_HFLCTL, 0, 0,
546 twl6040_power_mode_event,
547 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
548 SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
549 TWL6040_REG_HFRCTL, 0, 0,
550 twl6040_power_mode_event,
551 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
552
553 /* Analog playback switches */
554 SND_SOC_DAPM_SWITCH("HSDAC Left Playback",
555 SND_SOC_NOPM, 0, 0, &hsdacl_switch_controls),
556 SND_SOC_DAPM_SWITCH("HSDAC Right Playback",
557 SND_SOC_NOPM, 0, 0, &hsdacr_switch_controls),
558 SND_SOC_DAPM_SWITCH("HFDAC Left Playback",
559 SND_SOC_NOPM, 0, 0, &hfdacl_switch_controls),
560 SND_SOC_DAPM_SWITCH("HFDAC Right Playback",
561 SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls),
562
563 SND_SOC_DAPM_SWITCH("Headset Left Driver",
564 SND_SOC_NOPM, 0, 0, &hsl_driver_switch_controls),
565 SND_SOC_DAPM_SWITCH("Headset Right Driver",
566 SND_SOC_NOPM, 0, 0, &hsr_driver_switch_controls),
567 SND_SOC_DAPM_SWITCH_E("Handsfree Left Driver",
568 SND_SOC_NOPM, 0, 0, &hfl_driver_switch_controls,
569 twl6040_power_mode_event,
570 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
571 SND_SOC_DAPM_SWITCH_E("Handsfree Right Driver",
572 SND_SOC_NOPM, 0, 0, &hfr_driver_switch_controls,
573 twl6040_power_mode_event,
574 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
575
576 /* Analog playback PGAs */
577 SND_SOC_DAPM_PGA("HFDAC Left PGA",
578 TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
579 SND_SOC_DAPM_PGA("HFDAC Right PGA",
580 TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
581
582};
583
584static const struct snd_soc_dapm_route intercon[] = {
585 /* Capture path */
586 {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
587 {"Analog Left Capture Route", "Main Mic", "MAINMIC"},
588 {"Analog Left Capture Route", "Aux/FM Left", "AFML"},
589
590 {"Analog Right Capture Route", "Headset Mic", "HSMIC"},
591 {"Analog Right Capture Route", "Sub Mic", "SUBMIC"},
592 {"Analog Right Capture Route", "Aux/FM Right", "AFMR"},
593
594 {"MicAmpL", NULL, "Analog Left Capture Route"},
595 {"MicAmpR", NULL, "Analog Right Capture Route"},
596
597 {"ADC Left", NULL, "MicAmpL"},
598 {"ADC Right", NULL, "MicAmpR"},
599
600 /* Headset playback path */
601 {"HSDAC Left Playback", "Switch", "HSDAC Left"},
602 {"HSDAC Right Playback", "Switch", "HSDAC Right"},
603
604 {"Headset Left Driver", "Switch", "HSDAC Left Playback"},
605 {"Headset Right Driver", "Switch", "HSDAC Right Playback"},
606
607 {"HSOL", NULL, "Headset Left Driver"},
608 {"HSOR", NULL, "Headset Right Driver"},
609
610 /* Handsfree playback path */
611 {"HFDAC Left Playback", "Switch", "HFDAC Left"},
612 {"HFDAC Right Playback", "Switch", "HFDAC Right"},
613
614 {"HFDAC Left PGA", NULL, "HFDAC Left Playback"},
615 {"HFDAC Right PGA", NULL, "HFDAC Right Playback"},
616
617 {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
618 {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
619
620 {"HFL", NULL, "Handsfree Left Driver"},
621 {"HFR", NULL, "Handsfree Right Driver"},
622};
623
624static int twl6040_add_widgets(struct snd_soc_codec *codec)
625{
626 snd_soc_dapm_new_controls(codec, twl6040_dapm_widgets,
627 ARRAY_SIZE(twl6040_dapm_widgets));
628
629 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
630
631 snd_soc_dapm_new_widgets(codec);
632
633 return 0;
634}
635
636static int twl6040_power_up_completion(struct snd_soc_codec *codec,
637 int naudint)
638{
639 struct twl6040_data *priv = codec->private_data;
640 int time_left;
641 u8 intid;
642
643 time_left = wait_for_completion_timeout(&priv->ready,
644 msecs_to_jiffies(48));
645
646 if (!time_left) {
647 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &intid,
648 TWL6040_REG_INTID);
649 if (!(intid & TWL6040_READYINT)) {
650 dev_err(codec->dev, "timeout waiting for READYINT\n");
651 return -ETIMEDOUT;
652 }
653 }
654
655 priv->codec_powered = 1;
656
657 return 0;
658}
659
660static int twl6040_set_bias_level(struct snd_soc_codec *codec,
661 enum snd_soc_bias_level level)
662{
663 struct twl6040_data *priv = codec->private_data;
664 int audpwron = priv->audpwron;
665 int naudint = priv->naudint;
666 int ret;
667
668 switch (level) {
669 case SND_SOC_BIAS_ON:
670 break;
671 case SND_SOC_BIAS_PREPARE:
672 break;
673 case SND_SOC_BIAS_STANDBY:
674 if (priv->codec_powered)
675 break;
676
677 if (gpio_is_valid(audpwron)) {
678 /* use AUDPWRON line */
679 gpio_set_value(audpwron, 1);
680
681 /* wait for power-up completion */
682 ret = twl6040_power_up_completion(codec, naudint);
683 if (ret)
684 return ret;
685
686 /* sync registers updated during power-up sequence */
687 twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
688 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
689 twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
690 } else {
691 /* use manual power-up sequence */
692 twl6040_power_up(codec);
693 priv->codec_powered = 1;
694 }
695
696 /* initialize vdd/vss registers with reg_cache */
697 twl6040_init_vdd_regs(codec);
698 break;
699 case SND_SOC_BIAS_OFF:
700 if (!priv->codec_powered)
701 break;
702
703 if (gpio_is_valid(audpwron)) {
704 /* use AUDPWRON line */
705 gpio_set_value(audpwron, 0);
706
707 /* power-down sequence latency */
708 udelay(500);
709
710 /* sync registers updated during power-down sequence */
711 twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
712 twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
713 twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
714 0x00);
715 } else {
716 /* use manual power-down sequence */
717 twl6040_power_down(codec);
718 }
719
720 priv->codec_powered = 0;
721 break;
722 }
723
724 codec->bias_level = level;
725
726 return 0;
727}
728
729/* set of rates for each pll: low-power and high-performance */
730
731static unsigned int lp_rates[] = {
732 88200,
733 96000,
734};
735
736static struct snd_pcm_hw_constraint_list lp_constraints = {
737 .count = ARRAY_SIZE(lp_rates),
738 .list = lp_rates,
739};
740
741static unsigned int hp_rates[] = {
742 96000,
743};
744
745static struct snd_pcm_hw_constraint_list hp_constraints = {
746 .count = ARRAY_SIZE(hp_rates),
747 .list = hp_rates,
748};
749
750static int twl6040_startup(struct snd_pcm_substream *substream,
751 struct snd_soc_dai *dai)
752{
753 struct snd_soc_pcm_runtime *rtd = substream->private_data;
754 struct snd_soc_device *socdev = rtd->socdev;
755 struct snd_soc_codec *codec = socdev->card->codec;
756 struct twl6040_data *priv = codec->private_data;
757
758 if (!priv->sysclk) {
759 dev_err(codec->dev,
760 "no mclk configured, call set_sysclk() on init\n");
761 return -EINVAL;
762 }
763
764 /*
765 * capture is not supported at 17.64 MHz,
766 * it's reserved for headset low-power playback scenario
767 */
768 if ((priv->sysclk == 17640000) && substream->stream) {
769 dev_err(codec->dev,
770 "capture mode is not supported at %dHz\n",
771 priv->sysclk);
772 return -EINVAL;
773 }
774
775 snd_pcm_hw_constraint_list(substream->runtime, 0,
776 SNDRV_PCM_HW_PARAM_RATE,
777 priv->sysclk_constraints);
778
779 return 0;
780}
781
782static int twl6040_hw_params(struct snd_pcm_substream *substream,
783 struct snd_pcm_hw_params *params,
784 struct snd_soc_dai *dai)
785{
786 struct snd_soc_pcm_runtime *rtd = substream->private_data;
787 struct snd_soc_device *socdev = rtd->socdev;
788 struct snd_soc_codec *codec = socdev->card->codec;
789 struct twl6040_data *priv = codec->private_data;
790 u8 lppllctl;
791 int rate;
792
793 /* nothing to do for high-perf pll, it supports only 48 kHz */
794 if (priv->pll == TWL6040_HPPLL_ID)
795 return 0;
796
797 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
798
799 rate = params_rate(params);
800 switch (rate) {
801 case 88200:
802 lppllctl |= TWL6040_LPLLFIN;
803 priv->sysclk = 17640000;
804 break;
805 case 96000:
806 lppllctl &= ~TWL6040_LPLLFIN;
807 priv->sysclk = 19200000;
808 break;
809 default:
810 dev_err(codec->dev, "unsupported rate %d\n", rate);
811 return -EINVAL;
812 }
813
814 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
815
816 return 0;
817}
818
819static int twl6040_trigger(struct snd_pcm_substream *substream,
820 int cmd, struct snd_soc_dai *dai)
821{
822 struct snd_soc_pcm_runtime *rtd = substream->private_data;
823 struct snd_soc_device *socdev = rtd->socdev;
824 struct snd_soc_codec *codec = socdev->card->codec;
825 struct twl6040_data *priv = codec->private_data;
826
827 switch (cmd) {
828 case SNDRV_PCM_TRIGGER_START:
829 case SNDRV_PCM_TRIGGER_RESUME:
830 /*
831 * low-power playback mode is restricted
832 * for headset path only
833 */
834 if ((priv->sysclk == 17640000) && priv->non_lp) {
835 dev_err(codec->dev,
836 "some enabled paths aren't supported at %dHz\n",
837 priv->sysclk);
838 return -EPERM;
839 }
840 break;
841 default:
842 break;
843 }
844
845 return 0;
846}
847
848static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
849 int clk_id, unsigned int freq, int dir)
850{
851 struct snd_soc_codec *codec = codec_dai->codec;
852 struct twl6040_data *priv = codec->private_data;
853 u8 hppllctl, lppllctl;
854
855 hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL);
856 lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
857
858 switch (clk_id) {
859 case TWL6040_SYSCLK_SEL_LPPLL:
860 switch (freq) {
861 case 32768:
862 /* headset dac and driver must be in low-power mode */
863 headset_power_mode(codec, 0);
864
865 /* clk32k input requires low-power pll */
866 lppllctl |= TWL6040_LPLLENA;
867 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
868 mdelay(5);
869 lppllctl &= ~TWL6040_HPLLSEL;
870 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
871 hppllctl &= ~TWL6040_HPLLENA;
872 twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
873 break;
874 default:
875 dev_err(codec->dev, "unknown mclk freq %d\n", freq);
876 return -EINVAL;
877 }
878
879 /* lppll divider */
880 switch (priv->sysclk) {
881 case 17640000:
882 lppllctl |= TWL6040_LPLLFIN;
883 break;
884 case 19200000:
885 lppllctl &= ~TWL6040_LPLLFIN;
886 break;
887 default:
888 /* sysclk not yet configured */
889 lppllctl &= ~TWL6040_LPLLFIN;
890 priv->sysclk = 19200000;
891 break;
892 }
893
894 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
895
896 priv->pll = TWL6040_LPPLL_ID;
897 priv->sysclk_constraints = &lp_constraints;
898 break;
899 case TWL6040_SYSCLK_SEL_HPPLL:
900 hppllctl &= ~TWL6040_MCLK_MSK;
901
902 switch (freq) {
903 case 12000000:
904 /* mclk input, pll enabled */
905 hppllctl |= TWL6040_MCLK_12000KHZ |
906 TWL6040_HPLLSQRBP |
907 TWL6040_HPLLENA;
908 break;
909 case 19200000:
910 /* mclk input, pll disabled */
911 hppllctl |= TWL6040_MCLK_19200KHZ |
912 TWL6040_HPLLSQRBP |
913 TWL6040_HPLLBP;
914 break;
915 case 26000000:
916 /* mclk input, pll enabled */
917 hppllctl |= TWL6040_MCLK_26000KHZ |
918 TWL6040_HPLLSQRBP |
919 TWL6040_HPLLENA;
920 break;
921 case 38400000:
922 /* clk slicer, pll disabled */
923 hppllctl |= TWL6040_MCLK_38400KHZ |
924 TWL6040_HPLLSQRENA |
925 TWL6040_HPLLBP;
926 break;
927 default:
928 dev_err(codec->dev, "unknown mclk freq %d\n", freq);
929 return -EINVAL;
930 }
931
932 /* headset dac and driver must be in high-performance mode */
933 headset_power_mode(codec, 1);
934
935 twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
936 udelay(500);
937 lppllctl |= TWL6040_HPLLSEL;
938 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
939 lppllctl &= ~TWL6040_LPLLENA;
940 twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
941
942 /* high-performance pll can provide only 19.2 MHz */
943 priv->pll = TWL6040_HPPLL_ID;
944 priv->sysclk = 19200000;
945 priv->sysclk_constraints = &hp_constraints;
946 break;
947 default:
948 dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
949 return -EINVAL;
950 }
951
952 return 0;
953}
954
955static struct snd_soc_dai_ops twl6040_dai_ops = {
956 .startup = twl6040_startup,
957 .hw_params = twl6040_hw_params,
958 .trigger = twl6040_trigger,
959 .set_sysclk = twl6040_set_dai_sysclk,
960};
961
962struct snd_soc_dai twl6040_dai = {
963 .name = "twl6040",
964 .playback = {
965 .stream_name = "Playback",
966 .channels_min = 1,
967 .channels_max = 4,
968 .rates = TWL6040_RATES,
969 .formats = TWL6040_FORMATS,
970 },
971 .capture = {
972 .stream_name = "Capture",
973 .channels_min = 1,
974 .channels_max = 2,
975 .rates = TWL6040_RATES,
976 .formats = TWL6040_FORMATS,
977 },
978 .ops = &twl6040_dai_ops,
979};
980EXPORT_SYMBOL_GPL(twl6040_dai);
981
982#ifdef CONFIG_PM
983static int twl6040_suspend(struct platform_device *pdev, pm_message_t state)
984{
985 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
986 struct snd_soc_codec *codec = socdev->card->codec;
987
988 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
989
990 return 0;
991}
992
993static int twl6040_resume(struct platform_device *pdev)
994{
995 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
996 struct snd_soc_codec *codec = socdev->card->codec;
997
998 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
999 twl6040_set_bias_level(codec, codec->suspend_bias_level);
1000
1001 return 0;
1002}
1003#else
1004#define twl6040_suspend NULL
1005#define twl6040_resume NULL
1006#endif
1007
1008static struct snd_soc_codec *twl6040_codec;
1009
1010static int twl6040_probe(struct platform_device *pdev)
1011{
1012 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1013 struct snd_soc_codec *codec;
1014 int ret = 0;
1015
1016 BUG_ON(!twl6040_codec);
1017
1018 codec = twl6040_codec;
1019 socdev->card->codec = codec;
1020
1021 /* register pcms */
1022 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1023 if (ret < 0) {
1024 dev_err(&pdev->dev, "failed to create pcms\n");
1025 return ret;
1026 }
1027
1028 snd_soc_add_controls(codec, twl6040_snd_controls,
1029 ARRAY_SIZE(twl6040_snd_controls));
1030 twl6040_add_widgets(codec);
1031
1032 if (ret < 0) {
1033 dev_err(&pdev->dev, "failed to register card\n");
1034 goto card_err;
1035 }
1036
1037 return ret;
1038
1039card_err:
1040 snd_soc_free_pcms(socdev);
1041 snd_soc_dapm_free(socdev);
1042 return ret;
1043}
1044
1045static int twl6040_remove(struct platform_device *pdev)
1046{
1047 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1048 struct snd_soc_codec *codec = socdev->card->codec;
1049
1050 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1051 snd_soc_free_pcms(socdev);
1052 snd_soc_dapm_free(socdev);
1053 kfree(codec);
1054
1055 return 0;
1056}
1057
1058struct snd_soc_codec_device soc_codec_dev_twl6040 = {
1059 .probe = twl6040_probe,
1060 .remove = twl6040_remove,
1061 .suspend = twl6040_suspend,
1062 .resume = twl6040_resume,
1063};
1064EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040);
1065
1066static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1067{
1068 struct twl4030_codec_data *twl_codec = pdev->dev.platform_data;
1069 struct snd_soc_codec *codec;
1070 struct twl6040_data *priv;
1071 int audpwron, naudint;
1072 int ret = 0;
1073
1074 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
1075 if (priv == NULL)
1076 return -ENOMEM;
1077
1078 if (twl_codec) {
1079 audpwron = twl_codec->audpwron_gpio;
1080 naudint = twl_codec->naudint_irq;
1081 } else {
1082 audpwron = -EINVAL;
1083 naudint = 0;
1084 }
1085
1086 priv->audpwron = audpwron;
1087 priv->naudint = naudint;
1088
1089 codec = &priv->codec;
1090 codec->dev = &pdev->dev;
1091 twl6040_dai.dev = &pdev->dev;
1092
1093 codec->name = "twl6040";
1094 codec->owner = THIS_MODULE;
1095 codec->read = twl6040_read_reg_cache;
1096 codec->write = twl6040_write;
1097 codec->set_bias_level = twl6040_set_bias_level;
1098 codec->private_data = priv;
1099 codec->dai = &twl6040_dai;
1100 codec->num_dai = 1;
1101 codec->reg_cache_size = ARRAY_SIZE(twl6040_reg);
1102 codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg),
1103 GFP_KERNEL);
1104 if (codec->reg_cache == NULL) {
1105 ret = -ENOMEM;
1106 goto cache_err;
1107 }
1108
1109 mutex_init(&codec->mutex);
1110 INIT_LIST_HEAD(&codec->dapm_widgets);
1111 INIT_LIST_HEAD(&codec->dapm_paths);
1112 init_completion(&priv->ready);
1113
1114 if (gpio_is_valid(audpwron)) {
1115 ret = gpio_request(audpwron, "audpwron");
1116 if (ret)
1117 goto gpio1_err;
1118
1119 ret = gpio_direction_output(audpwron, 0);
1120 if (ret)
1121 goto gpio2_err;
1122
1123 priv->codec_powered = 0;
1124 }
1125
1126 if (naudint) {
1127 /* audio interrupt */
1128 ret = request_threaded_irq(naudint, NULL,
1129 twl6040_naudint_handler,
1130 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
1131 "twl6040_codec", codec);
1132 if (ret)
1133 goto gpio2_err;
1134 } else {
1135 if (gpio_is_valid(audpwron)) {
1136 /* enable only codec ready interrupt */
1137 twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1138 ~TWL6040_READYMSK & TWL6040_ALLINT_MSK);
1139 } else {
1140 /* no interrupts at all */
1141 twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
1142 TWL6040_ALLINT_MSK);
1143 }
1144 }
1145
1146 /* init vio registers */
1147 twl6040_init_vio_regs(codec);
1148
1149 /* power on device */
1150 ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1151 if (ret)
1152 goto irq_err;
1153
1154 ret = snd_soc_register_codec(codec);
1155 if (ret)
1156 goto reg_err;
1157
1158 twl6040_codec = codec;
1159
1160 ret = snd_soc_register_dai(&twl6040_dai);
1161 if (ret)
1162 goto dai_err;
1163
1164 return 0;
1165
1166dai_err:
1167 snd_soc_unregister_codec(codec);
1168 twl6040_codec = NULL;
1169reg_err:
1170 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1171irq_err:
1172 if (naudint)
1173 free_irq(naudint, codec);
1174gpio2_err:
1175 if (gpio_is_valid(audpwron))
1176 gpio_free(audpwron);
1177gpio1_err:
1178 kfree(codec->reg_cache);
1179cache_err:
1180 kfree(priv);
1181 return ret;
1182}
1183
1184static int __devexit twl6040_codec_remove(struct platform_device *pdev)
1185{
1186 struct twl6040_data *priv = twl6040_codec->private_data;
1187 int audpwron = priv->audpwron;
1188 int naudint = priv->naudint;
1189
1190 if (gpio_is_valid(audpwron))
1191 gpio_free(audpwron);
1192
1193 if (naudint)
1194 free_irq(naudint, twl6040_codec);
1195
1196 snd_soc_unregister_dai(&twl6040_dai);
1197 snd_soc_unregister_codec(twl6040_codec);
1198
1199 kfree(twl6040_codec);
1200 twl6040_codec = NULL;
1201
1202 return 0;
1203}
1204
1205static struct platform_driver twl6040_codec_driver = {
1206 .driver = {
1207 .name = "twl6040_codec",
1208 .owner = THIS_MODULE,
1209 },
1210 .probe = twl6040_codec_probe,
1211 .remove = __devexit_p(twl6040_codec_remove),
1212};
1213
1214static int __init twl6040_codec_init(void)
1215{
1216 return platform_driver_register(&twl6040_codec_driver);
1217}
1218module_init(twl6040_codec_init);
1219
1220static void __exit twl6040_codec_exit(void)
1221{
1222 platform_driver_unregister(&twl6040_codec_driver);
1223}
1224module_exit(twl6040_codec_exit);
1225
1226MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
1227MODULE_AUTHOR("Misael Lopez Cruz");
1228MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
new file mode 100644
index 000000000000..c472070a1da2
--- /dev/null
+++ b/sound/soc/codecs/twl6040.h
@@ -0,0 +1,141 @@
1/*
2 * ALSA SoC TWL6040 codec driver
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#ifndef __TWL6040_H__
23#define __TWL6040_H__
24
25#define TWL6040_REG_ASICID 0x01
26#define TWL6040_REG_ASICREV 0x02
27#define TWL6040_REG_INTID 0x03
28#define TWL6040_REG_INTMR 0x04
29#define TWL6040_REG_NCPCTL 0x05
30#define TWL6040_REG_LDOCTL 0x06
31#define TWL6040_REG_HPPLLCTL 0x07
32#define TWL6040_REG_LPPLLCTL 0x08
33#define TWL6040_REG_LPPLLDIV 0x09
34#define TWL6040_REG_AMICBCTL 0x0A
35#define TWL6040_REG_DMICBCTL 0x0B
36#define TWL6040_REG_MICLCTL 0x0C
37#define TWL6040_REG_MICRCTL 0x0D
38#define TWL6040_REG_MICGAIN 0x0E
39#define TWL6040_REG_LINEGAIN 0x0F
40#define TWL6040_REG_HSLCTL 0x10
41#define TWL6040_REG_HSRCTL 0x11
42#define TWL6040_REG_HSGAIN 0x12
43#define TWL6040_REG_EARCTL 0x13
44#define TWL6040_REG_HFLCTL 0x14
45#define TWL6040_REG_HFLGAIN 0x15
46#define TWL6040_REG_HFRCTL 0x16
47#define TWL6040_REG_HFRGAIN 0x17
48#define TWL6040_REG_VIBCTLL 0x18
49#define TWL6040_REG_VIBDATL 0x19
50#define TWL6040_REG_VIBCTLR 0x1A
51#define TWL6040_REG_VIBDATR 0x1B
52#define TWL6040_REG_HKCTL1 0x1C
53#define TWL6040_REG_HKCTL2 0x1D
54#define TWL6040_REG_GPOCTL 0x1E
55#define TWL6040_REG_ALB 0x1F
56#define TWL6040_REG_DLB 0x20
57#define TWL6040_REG_TRIM1 0x28
58#define TWL6040_REG_TRIM2 0x29
59#define TWL6040_REG_TRIM3 0x2A
60#define TWL6040_REG_HSOTRIM 0x2B
61#define TWL6040_REG_HFOTRIM 0x2C
62#define TWL6040_REG_ACCCTL 0x2D
63#define TWL6040_REG_STATUS 0x2E
64
65#define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1)
66
67#define TWL6040_VIOREGNUM 18
68#define TWL6040_VDDREGNUM 21
69
70/* INTID (0x03) fields */
71
72#define TWL6040_THINT 0x01
73#define TWL6040_PLUGINT 0x02
74#define TWL6040_UNPLUGINT 0x04
75#define TWL6040_HOOKINT 0x08
76#define TWL6040_HFINT 0x10
77#define TWL6040_VIBINT 0x20
78#define TWL6040_READYINT 0x40
79
80/* INTMR (0x04) fields */
81
82#define TWL6040_READYMSK 0x40
83#define TWL6040_ALLINT_MSK 0x7B
84
85/* NCPCTL (0x05) fields */
86
87#define TWL6040_NCPENA 0x01
88#define TWL6040_NCPOPEN 0x40
89
90/* LDOCTL (0x06) fields */
91
92#define TWL6040_LSLDOENA 0x01
93#define TWL6040_HSLDOENA 0x04
94#define TWL6040_REFENA 0x40
95#define TWL6040_OSCENA 0x80
96
97/* HPPLLCTL (0x07) fields */
98
99#define TWL6040_HPLLENA 0x01
100#define TWL6040_HPLLRST 0x02
101#define TWL6040_HPLLBP 0x04
102#define TWL6040_HPLLSQRENA 0x08
103#define TWL6040_HPLLSQRBP 0x10
104#define TWL6040_MCLK_12000KHZ (0 << 5)
105#define TWL6040_MCLK_19200KHZ (1 << 5)
106#define TWL6040_MCLK_26000KHZ (2 << 5)
107#define TWL6040_MCLK_38400KHZ (3 << 5)
108#define TWL6040_MCLK_MSK 0x60
109
110/* LPPLLCTL (0x08) fields */
111
112#define TWL6040_LPLLENA 0x01
113#define TWL6040_LPLLRST 0x02
114#define TWL6040_LPLLSEL 0x04
115#define TWL6040_LPLLFIN 0x08
116#define TWL6040_HPLLSEL 0x10
117
118/* HSLCTL (0x10) fields */
119
120#define TWL6040_HSDACMODEL 0x02
121#define TWL6040_HSDRVMODEL 0x08
122
123/* HSRCTL (0x11) fields */
124
125#define TWL6040_HSDACMODER 0x02
126#define TWL6040_HSDRVMODER 0x08
127
128/* ACCCTL (0x2D) fields */
129
130#define TWL6040_RESETSPLIT 0x04
131
132#define TWL6040_SYSCLK_SEL_LPPLL 1
133#define TWL6040_SYSCLK_SEL_HPPLL 2
134
135#define TWL6040_HPPLL_ID 1
136#define TWL6040_LPPLL_ID 2
137
138extern struct snd_soc_dai twl6040_dai;
139extern struct snd_soc_codec_device soc_codec_dev_twl6040;
140
141#endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index df2c6d9617fb..8ac92f5e4f91 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -54,6 +54,7 @@ struct wm8350_output {
54struct wm8350_jack_data { 54struct wm8350_jack_data {
55 struct snd_soc_jack *jack; 55 struct snd_soc_jack *jack;
56 int report; 56 int report;
57 int short_report;
57}; 58};
58 59
59struct wm8350_data { 60struct wm8350_data {
@@ -62,6 +63,7 @@ struct wm8350_data {
62 struct wm8350_output out2; 63 struct wm8350_output out2;
63 struct wm8350_jack_data hpl; 64 struct wm8350_jack_data hpl;
64 struct wm8350_jack_data hpr; 65 struct wm8350_jack_data hpr;
66 struct wm8350_jack_data mic;
65 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 67 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
66 int fll_freq_out; 68 int fll_freq_out;
67 int fll_freq_in; 69 int fll_freq_in;
@@ -1391,7 +1393,8 @@ static irqreturn_t wm8350_hp_jack_handler(int irq, void *data)
1391 * @jack: jack to report detection events on 1393 * @jack: jack to report detection events on
1392 * @report: value to report 1394 * @report: value to report
1393 * 1395 *
1394 * Enables the headphone jack detection of the WM8350. 1396 * Enables the headphone jack detection of the WM8350. If no report
1397 * is specified then detection is disabled.
1395 */ 1398 */
1396int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, 1399int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
1397 struct snd_soc_jack *jack, int report) 1400 struct snd_soc_jack *jack, int report)
@@ -1420,8 +1423,12 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
1420 return -EINVAL; 1423 return -EINVAL;
1421 } 1424 }
1422 1425
1423 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); 1426 if (report) {
1424 wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); 1427 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1428 wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);
1429 } else {
1430 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, ena);
1431 }
1425 1432
1426 /* Sync status */ 1433 /* Sync status */
1427 wm8350_hp_jack_handler(irq + wm8350->irq_base, priv); 1434 wm8350_hp_jack_handler(irq + wm8350->irq_base, priv);
@@ -1430,6 +1437,60 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
1430} 1437}
1431EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); 1438EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect);
1432 1439
1440static irqreturn_t wm8350_mic_handler(int irq, void *data)
1441{
1442 struct wm8350_data *priv = data;
1443 struct wm8350 *wm8350 = priv->codec.control_data;
1444 u16 reg;
1445 int report = 0;
1446
1447 reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS);
1448 if (reg & WM8350_JACK_MICSCD_LVL)
1449 report |= priv->mic.short_report;
1450 if (reg & WM8350_JACK_MICSD_LVL)
1451 report |= priv->mic.report;
1452
1453 snd_soc_jack_report(priv->mic.jack, report,
1454 priv->mic.report | priv->mic.short_report);
1455
1456 return IRQ_HANDLED;
1457}
1458
1459/**
1460 * wm8350_mic_jack_detect - Enable microphone jack detection.
1461 *
1462 * @codec: WM8350 codec
1463 * @jack: jack to report detection events on
1464 * @detect_report: value to report when presence detected
1465 * @short_report: value to report when microphone short detected
1466 *
1467 * Enables the microphone jack detection of the WM8350. If both reports
1468 * are specified as zero then detection is disabled.
1469 */
1470int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
1471 struct snd_soc_jack *jack,
1472 int detect_report, int short_report)
1473{
1474 struct wm8350_data *priv = codec->private_data;
1475 struct wm8350 *wm8350 = codec->control_data;
1476
1477 priv->mic.jack = jack;
1478 priv->mic.report = detect_report;
1479 priv->mic.short_report = short_report;
1480
1481 if (detect_report || short_report) {
1482 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1483 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_1,
1484 WM8350_MIC_DET_ENA);
1485 } else {
1486 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_1,
1487 WM8350_MIC_DET_ENA);
1488 }
1489
1490 return 0;
1491}
1492EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect);
1493
1433static struct snd_soc_codec *wm8350_codec; 1494static struct snd_soc_codec *wm8350_codec;
1434 1495
1435static int wm8350_probe(struct platform_device *pdev) 1496static int wm8350_probe(struct platform_device *pdev)
@@ -1493,6 +1554,10 @@ static int wm8350_probe(struct platform_device *pdev)
1493 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, 1554 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
1494 wm8350_hp_jack_handler, 0, "Right jack detect", 1555 wm8350_hp_jack_handler, 0, "Right jack detect",
1495 priv); 1556 priv);
1557 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD,
1558 wm8350_mic_handler, 0, "Microphone short", priv);
1559 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
1560 wm8350_mic_handler, 0, "Microphone detect", priv);
1496 1561
1497 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 1562 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1498 if (ret < 0) { 1563 if (ret < 0) {
@@ -1521,11 +1586,14 @@ static int wm8350_remove(struct platform_device *pdev)
1521 WM8350_JDL_ENA | WM8350_JDR_ENA); 1586 WM8350_JDL_ENA | WM8350_JDR_ENA);
1522 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); 1587 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1523 1588
1589 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICD, priv);
1590 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, priv);
1524 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv); 1591 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv);
1525 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv); 1592 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv);
1526 1593
1527 priv->hpl.jack = NULL; 1594 priv->hpl.jack = NULL;
1528 priv->hpr.jack = NULL; 1595 priv->hpr.jack = NULL;
1596 priv->mic.jack = NULL;
1529 1597
1530 /* cancel any work waiting to be queued. */ 1598 /* cancel any work waiting to be queued. */
1531 ret = cancel_delayed_work(&codec->delayed_work); 1599 ret = cancel_delayed_work(&codec->delayed_work);
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index d088eb4b88bb..9ed0467c71db 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -25,5 +25,8 @@ enum wm8350_jack {
25 25
26int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, 26int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
27 struct snd_soc_jack *jack, int report); 27 struct snd_soc_jack *jack, int report);
28int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
29 struct snd_soc_jack *jack,
30 int detect_report, int short_report);
28 31
29#endif 32#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 475c67ac7818..ee084083a49d 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -29,8 +29,6 @@
29 29
30#include "wm8750.h" 30#include "wm8750.h"
31 31
32#define WM8750_VERSION "0.12"
33
34/* codec private data */ 32/* codec private data */
35struct wm8750_priv { 33struct wm8750_priv {
36 unsigned int sysclk; 34 unsigned int sysclk;
@@ -613,10 +611,16 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
613 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); 611 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
614 break; 612 break;
615 case SND_SOC_BIAS_PREPARE: 613 case SND_SOC_BIAS_PREPARE:
616 /* set vmid to 5k for quick power up */
617 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
618 break; 614 break;
619 case SND_SOC_BIAS_STANDBY: 615 case SND_SOC_BIAS_STANDBY:
616 if (codec->bias_level == SND_SOC_BIAS_OFF) {
617 /* Set VMID to 5k */
618 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
619
620 /* ...and ramp */
621 msleep(1000);
622 }
623
620 /* mute dac and set vmid to 500k, enable VREF */ 624 /* mute dac and set vmid to 500k, enable VREF */
621 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141); 625 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
622 break; 626 break;
@@ -660,13 +664,6 @@ struct snd_soc_dai wm8750_dai = {
660}; 664};
661EXPORT_SYMBOL_GPL(wm8750_dai); 665EXPORT_SYMBOL_GPL(wm8750_dai);
662 666
663static void wm8750_work(struct work_struct *work)
664{
665 struct snd_soc_codec *codec =
666 container_of(work, struct snd_soc_codec, delayed_work.work);
667 wm8750_set_bias_level(codec, codec->bias_level);
668}
669
670static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) 667static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
671{ 668{
672 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 669 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -695,14 +692,6 @@ static int wm8750_resume(struct platform_device *pdev)
695 692
696 wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 693 wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
697 694
698 /* charge wm8750 caps */
699 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
700 wm8750_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
701 codec->bias_level = SND_SOC_BIAS_ON;
702 schedule_delayed_work(&codec->delayed_work,
703 msecs_to_jiffies(1000));
704 }
705
706 return 0; 695 return 0;
707} 696}
708 697
@@ -746,9 +735,7 @@ static int wm8750_init(struct snd_soc_device *socdev,
746 } 735 }
747 736
748 /* charge output caps */ 737 /* charge output caps */
749 wm8750_set_bias_level(codec, SND_SOC_BIAS_PREPARE); 738 wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
750 codec->bias_level = SND_SOC_BIAS_STANDBY;
751 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
752 739
753 /* set the update bits */ 740 /* set the update bits */
754 reg = snd_soc_read(codec, WM8750_LDAC); 741 reg = snd_soc_read(codec, WM8750_LDAC);
@@ -912,7 +899,6 @@ static int wm8750_probe(struct platform_device *pdev)
912 struct wm8750_priv *wm8750; 899 struct wm8750_priv *wm8750;
913 int ret; 900 int ret;
914 901
915 pr_info("WM8750 Audio Codec %s", WM8750_VERSION);
916 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 902 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
917 if (codec == NULL) 903 if (codec == NULL)
918 return -ENOMEM; 904 return -ENOMEM;
@@ -929,7 +915,6 @@ static int wm8750_probe(struct platform_device *pdev)
929 INIT_LIST_HEAD(&codec->dapm_widgets); 915 INIT_LIST_HEAD(&codec->dapm_widgets);
930 INIT_LIST_HEAD(&codec->dapm_paths); 916 INIT_LIST_HEAD(&codec->dapm_paths);
931 wm8750_socdev = socdev; 917 wm8750_socdev = socdev;
932 INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
933 918
934 ret = -ENODEV; 919 ret = -ENODEV;
935 920
@@ -953,25 +938,6 @@ static int wm8750_probe(struct platform_device *pdev)
953 return ret; 938 return ret;
954} 939}
955 940
956/*
957 * This function forces any delayed work to be queued and run.
958 */
959static int run_delayed_work(struct delayed_work *dwork)
960{
961 int ret;
962
963 /* cancel any work waiting to be queued. */
964 ret = cancel_delayed_work(dwork);
965
966 /* if there was any work waiting then we run it now and
967 * wait for it's completion */
968 if (ret) {
969 schedule_delayed_work(dwork, 0);
970 flush_scheduled_work();
971 }
972 return ret;
973}
974
975/* power down chip */ 941/* power down chip */
976static int wm8750_remove(struct platform_device *pdev) 942static int wm8750_remove(struct platform_device *pdev)
977{ 943{
@@ -980,7 +946,6 @@ static int wm8750_remove(struct platform_device *pdev)
980 946
981 if (codec->control_data) 947 if (codec->control_data)
982 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); 948 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
983 run_delayed_work(&codec->delayed_work);
984 snd_soc_free_pcms(socdev); 949 snd_soc_free_pcms(socdev);
985 snd_soc_dapm_free(socdev); 950 snd_soc_dapm_free(socdev);
986#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 951#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 3595bd57c4eb..134b17532f23 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -11,25 +11,26 @@
11 * 11 *
12 * TODO: 12 * TODO:
13 * - TDM mode configuration. 13 * - TDM mode configuration.
14 * - Mic detect.
15 * - Digital microphone support. 14 * - Digital microphone support.
16 * - Interrupt support (mic detect and sequencer).
17 */ 15 */
18 16
19#include <linux/module.h> 17#include <linux/module.h>
20#include <linux/moduleparam.h> 18#include <linux/moduleparam.h>
21#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/completion.h>
22#include <linux/delay.h> 21#include <linux/delay.h>
23#include <linux/pm.h> 22#include <linux/pm.h>
24#include <linux/i2c.h> 23#include <linux/i2c.h>
25#include <linux/platform_device.h> 24#include <linux/platform_device.h>
26#include <sound/core.h> 25#include <sound/core.h>
26#include <sound/jack.h>
27#include <sound/pcm.h> 27#include <sound/pcm.h>
28#include <sound/pcm_params.h> 28#include <sound/pcm_params.h>
29#include <sound/tlv.h> 29#include <sound/tlv.h>
30#include <sound/soc.h> 30#include <sound/soc.h>
31#include <sound/soc-dapm.h> 31#include <sound/soc-dapm.h>
32#include <sound/initval.h> 32#include <sound/initval.h>
33#include <sound/wm8903.h>
33 34
34#include "wm8903.h" 35#include "wm8903.h"
35 36
@@ -221,6 +222,14 @@ struct wm8903_priv {
221 int playback_active; 222 int playback_active;
222 int capture_active; 223 int capture_active;
223 224
225 struct completion wseq;
226
227 struct snd_soc_jack *mic_jack;
228 int mic_det;
229 int mic_short;
230 int mic_last_report;
231 int mic_delay;
232
224 struct snd_pcm_substream *master_substream; 233 struct snd_pcm_substream *master_substream;
225 struct snd_pcm_substream *slave_substream; 234 struct snd_pcm_substream *slave_substream;
226}; 235};
@@ -243,13 +252,14 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
243{ 252{
244 u16 reg[5]; 253 u16 reg[5];
245 struct i2c_client *i2c = codec->control_data; 254 struct i2c_client *i2c = codec->control_data;
255 struct wm8903_priv *wm8903 = codec->private_data;
246 256
247 BUG_ON(start > 48); 257 BUG_ON(start > 48);
248 258
249 /* Enable the sequencer */ 259 /* Enable the sequencer if it's not already on */
250 reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0); 260 reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0);
251 reg[0] |= WM8903_WSEQ_ENA; 261 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
252 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); 262 reg[0] | WM8903_WSEQ_ENA);
253 263
254 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); 264 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
255 265
@@ -257,20 +267,19 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
257 start | WM8903_WSEQ_START); 267 start | WM8903_WSEQ_START);
258 268
259 /* Wait for it to complete. If we have the interrupt wired up then 269 /* Wait for it to complete. If we have the interrupt wired up then
260 * we could block waiting for an interrupt, though polling may still 270 * that will break us out of the poll early.
261 * be desirable for diagnostic purposes.
262 */ 271 */
263 do { 272 do {
264 msleep(10); 273 wait_for_completion_timeout(&wm8903->wseq,
274 msecs_to_jiffies(10));
265 275
266 reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); 276 reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
267 } while (reg[4] & WM8903_WSEQ_BUSY); 277 } while (reg[4] & WM8903_WSEQ_BUSY);
268 278
269 dev_dbg(&i2c->dev, "Sequence complete\n"); 279 dev_dbg(&i2c->dev, "Sequence complete\n");
270 280
271 /* Disable the sequencer again */ 281 /* Disable the sequencer again if we enabled it */
272 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 282 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
273 reg[0] & ~WM8903_WSEQ_ENA);
274 283
275 return 0; 284 return 0;
276} 285}
@@ -1435,6 +1444,116 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1435 return 0; 1444 return 0;
1436} 1445}
1437 1446
1447/**
1448 * wm8903_mic_detect - Enable microphone detection via the WM8903 IRQ
1449 *
1450 * @codec: WM8903 codec
1451 * @jack: jack to report detection events on
1452 * @det: value to report for presence detection
1453 * @shrt: value to report for short detection
1454 *
1455 * Enable microphone detection via IRQ on the WM8903. If GPIOs are
1456 * being used to bring out signals to the processor then only platform
1457 * data configuration is needed for WM8903 and processor GPIOs should
1458 * be configured using snd_soc_jack_add_gpios() instead.
1459 *
1460 * The current threasholds for detection should be configured using
1461 * micdet_cfg in the platform data. Using this function will force on
1462 * the microphone bias for the device.
1463 */
1464int wm8903_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
1465 int det, int shrt)
1466{
1467 struct wm8903_priv *wm8903 = codec->private_data;
1468 int irq_mask = WM8903_MICDET_EINT | WM8903_MICSHRT_EINT;
1469
1470 dev_dbg(codec->dev, "Enabling microphone detection: %x %x\n",
1471 det, shrt);
1472
1473 /* Store the configuration */
1474 wm8903->mic_jack = jack;
1475 wm8903->mic_det = det;
1476 wm8903->mic_short = shrt;
1477
1478 /* Enable interrupts we've got a report configured for */
1479 if (det)
1480 irq_mask &= ~WM8903_MICDET_EINT;
1481 if (shrt)
1482 irq_mask &= ~WM8903_MICSHRT_EINT;
1483
1484 snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK,
1485 WM8903_MICDET_EINT | WM8903_MICSHRT_EINT,
1486 irq_mask);
1487
1488 if (det && shrt) {
1489 /* Enable mic detection, this may not have been set through
1490 * platform data (eg, if the defaults are OK). */
1491 snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
1492 WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
1493 snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0,
1494 WM8903_MICDET_ENA, WM8903_MICDET_ENA);
1495 } else {
1496 snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0,
1497 WM8903_MICDET_ENA, 0);
1498 }
1499
1500 return 0;
1501}
1502EXPORT_SYMBOL_GPL(wm8903_mic_detect);
1503
1504static irqreturn_t wm8903_irq(int irq, void *data)
1505{
1506 struct wm8903_priv *wm8903 = data;
1507 struct snd_soc_codec *codec = &wm8903->codec;
1508 int mic_report;
1509 int int_pol;
1510 int int_val = 0;
1511 int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK);
1512
1513 int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask;
1514
1515 if (int_val & WM8903_WSEQ_BUSY_EINT) {
1516 dev_dbg(codec->dev, "Write sequencer done\n");
1517 complete(&wm8903->wseq);
1518 }
1519
1520 /*
1521 * The rest is microphone jack detection. We need to manually
1522 * invert the polarity of the interrupt after each event - to
1523 * simplify the code keep track of the last state we reported
1524 * and just invert the relevant bits in both the report and
1525 * the polarity register.
1526 */
1527 mic_report = wm8903->mic_last_report;
1528 int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1);
1529
1530 if (int_val & WM8903_MICSHRT_EINT) {
1531 dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol);
1532
1533 mic_report ^= wm8903->mic_short;
1534 int_pol ^= WM8903_MICSHRT_INV;
1535 }
1536
1537 if (int_val & WM8903_MICDET_EINT) {
1538 dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol);
1539
1540 mic_report ^= wm8903->mic_det;
1541 int_pol ^= WM8903_MICDET_INV;
1542
1543 msleep(wm8903->mic_delay);
1544 }
1545
1546 snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1,
1547 WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol);
1548
1549 snd_soc_jack_report(wm8903->mic_jack, mic_report,
1550 wm8903->mic_short | wm8903->mic_det);
1551
1552 wm8903->mic_last_report = mic_report;
1553
1554 return IRQ_HANDLED;
1555}
1556
1438#define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ 1557#define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\
1439 SNDRV_PCM_RATE_11025 | \ 1558 SNDRV_PCM_RATE_11025 | \
1440 SNDRV_PCM_RATE_16000 | \ 1559 SNDRV_PCM_RATE_16000 | \
@@ -1529,9 +1648,11 @@ static struct snd_soc_codec *wm8903_codec;
1529static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, 1648static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1530 const struct i2c_device_id *id) 1649 const struct i2c_device_id *id)
1531{ 1650{
1651 struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
1532 struct wm8903_priv *wm8903; 1652 struct wm8903_priv *wm8903;
1533 struct snd_soc_codec *codec; 1653 struct snd_soc_codec *codec;
1534 int ret; 1654 int ret, i;
1655 int trigger, irq_pol;
1535 u16 val; 1656 u16 val;
1536 1657
1537 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); 1658 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
@@ -1555,6 +1676,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1555 codec->reg_cache = &wm8903->reg_cache[0]; 1676 codec->reg_cache = &wm8903->reg_cache[0];
1556 codec->private_data = wm8903; 1677 codec->private_data = wm8903;
1557 codec->volatile_register = wm8903_volatile_register; 1678 codec->volatile_register = wm8903_volatile_register;
1679 init_completion(&wm8903->wseq);
1558 1680
1559 i2c_set_clientdata(i2c, codec); 1681 i2c_set_clientdata(i2c, codec);
1560 codec->control_data = i2c; 1682 codec->control_data = i2c;
@@ -1578,6 +1700,53 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1578 1700
1579 wm8903_reset(codec); 1701 wm8903_reset(codec);
1580 1702
1703 /* Set up GPIOs and microphone detection */
1704 if (pdata) {
1705 for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
1706 if (!pdata->gpio_cfg[i])
1707 continue;
1708
1709 snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
1710 pdata->gpio_cfg[i] & 0xffff);
1711 }
1712
1713 snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
1714 pdata->micdet_cfg);
1715
1716 /* Microphone detection needs the WSEQ clock */
1717 if (pdata->micdet_cfg)
1718 snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
1719 WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
1720
1721 wm8903->mic_delay = pdata->micdet_delay;
1722 }
1723
1724 if (i2c->irq) {
1725 if (pdata && pdata->irq_active_low) {
1726 trigger = IRQF_TRIGGER_LOW;
1727 irq_pol = WM8903_IRQ_POL;
1728 } else {
1729 trigger = IRQF_TRIGGER_HIGH;
1730 irq_pol = 0;
1731 }
1732
1733 snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL,
1734 WM8903_IRQ_POL, irq_pol);
1735
1736 ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq,
1737 trigger | IRQF_ONESHOT,
1738 "wm8903", wm8903);
1739 if (ret != 0) {
1740 dev_err(&i2c->dev, "Failed to request IRQ: %d\n",
1741 ret);
1742 goto err;
1743 }
1744
1745 /* Enable write sequencer interrupts */
1746 snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK,
1747 WM8903_IM_WSEQ_BUSY_EINT, 0);
1748 }
1749
1581 /* power on device */ 1750 /* power on device */
1582 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1751 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1583 1752
@@ -1618,7 +1787,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1618 ret = snd_soc_register_codec(codec); 1787 ret = snd_soc_register_codec(codec);
1619 if (ret != 0) { 1788 if (ret != 0) {
1620 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); 1789 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1621 goto err; 1790 goto err_irq;
1622 } 1791 }
1623 1792
1624 ret = snd_soc_register_dai(&wm8903_dai); 1793 ret = snd_soc_register_dai(&wm8903_dai);
@@ -1631,6 +1800,9 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1631 1800
1632err_codec: 1801err_codec:
1633 snd_soc_unregister_codec(codec); 1802 snd_soc_unregister_codec(codec);
1803err_irq:
1804 if (i2c->irq)
1805 free_irq(i2c->irq, wm8903);
1634err: 1806err:
1635 wm8903_codec = NULL; 1807 wm8903_codec = NULL;
1636 kfree(wm8903); 1808 kfree(wm8903);
@@ -1640,12 +1812,16 @@ err:
1640static __devexit int wm8903_i2c_remove(struct i2c_client *client) 1812static __devexit int wm8903_i2c_remove(struct i2c_client *client)
1641{ 1813{
1642 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1814 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1815 struct wm8903_priv *priv = codec->private_data;
1643 1816
1644 snd_soc_unregister_dai(&wm8903_dai); 1817 snd_soc_unregister_dai(&wm8903_dai);
1645 snd_soc_unregister_codec(codec); 1818 snd_soc_unregister_codec(codec);
1646 1819
1647 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); 1820 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1648 1821
1822 if (client->irq)
1823 free_irq(client->irq, priv);
1824
1649 kfree(codec->private_data); 1825 kfree(codec->private_data);
1650 1826
1651 wm8903_codec = NULL; 1827 wm8903_codec = NULL;
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
index 0ea27e2b9963..ce384a2ad820 100644
--- a/sound/soc/codecs/wm8903.h
+++ b/sound/soc/codecs/wm8903.h
@@ -18,6 +18,10 @@
18extern struct snd_soc_dai wm8903_dai; 18extern struct snd_soc_dai wm8903_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8903; 19extern struct snd_soc_codec_device soc_codec_dev_wm8903;
20 20
21extern int wm8903_mic_detect(struct snd_soc_codec *codec,
22 struct snd_soc_jack *jack,
23 int det, int shrt);
24
21#define WM8903_MCLK_DIV_2 1 25#define WM8903_MCLK_DIV_2 1
22#define WM8903_CLK_SYS 2 26#define WM8903_CLK_SYS 2
23#define WM8903_BCLK 3 27#define WM8903_BCLK 3
@@ -173,28 +177,6 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8903;
173#define WM8903_VMID_RES_5K 4 177#define WM8903_VMID_RES_5K 4
174 178
175/* 179/*
176 * R6 (0x06) - Mic Bias Control 0
177 */
178#define WM8903_MICDET_HYST_ENA 0x0080 /* MICDET_HYST_ENA */
179#define WM8903_MICDET_HYST_ENA_MASK 0x0080 /* MICDET_HYST_ENA */
180#define WM8903_MICDET_HYST_ENA_SHIFT 7 /* MICDET_HYST_ENA */
181#define WM8903_MICDET_HYST_ENA_WIDTH 1 /* MICDET_HYST_ENA */
182#define WM8903_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */
183#define WM8903_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */
184#define WM8903_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */
185#define WM8903_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */
186#define WM8903_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */
187#define WM8903_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */
188#define WM8903_MICDET_ENA 0x0002 /* MICDET_ENA */
189#define WM8903_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */
190#define WM8903_MICDET_ENA_SHIFT 1 /* MICDET_ENA */
191#define WM8903_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
192#define WM8903_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */
193#define WM8903_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */
194#define WM8903_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
195#define WM8903_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
196
197/*
198 * R8 (0x08) - Analogue DAC 0 180 * R8 (0x08) - Analogue DAC 0
199 */ 181 */
200#define WM8903_DACBIAS_SEL_MASK 0x0018 /* DACBIAS_SEL - [4:3] */ 182#define WM8903_DACBIAS_SEL_MASK 0x0018 /* DACBIAS_SEL - [4:3] */
@@ -1135,201 +1117,6 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8903;
1135#define WM8903_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */ 1117#define WM8903_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */
1136 1118
1137/* 1119/*
1138 * R116 (0x74) - GPIO Control 1
1139 */
1140#define WM8903_GP1_FN_MASK 0x1F00 /* GP1_FN - [12:8] */
1141#define WM8903_GP1_FN_SHIFT 8 /* GP1_FN - [12:8] */
1142#define WM8903_GP1_FN_WIDTH 5 /* GP1_FN - [12:8] */
1143#define WM8903_GP1_DIR 0x0080 /* GP1_DIR */
1144#define WM8903_GP1_DIR_MASK 0x0080 /* GP1_DIR */
1145#define WM8903_GP1_DIR_SHIFT 7 /* GP1_DIR */
1146#define WM8903_GP1_DIR_WIDTH 1 /* GP1_DIR */
1147#define WM8903_GP1_OP_CFG 0x0040 /* GP1_OP_CFG */
1148#define WM8903_GP1_OP_CFG_MASK 0x0040 /* GP1_OP_CFG */
1149#define WM8903_GP1_OP_CFG_SHIFT 6 /* GP1_OP_CFG */
1150#define WM8903_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
1151#define WM8903_GP1_IP_CFG 0x0020 /* GP1_IP_CFG */
1152#define WM8903_GP1_IP_CFG_MASK 0x0020 /* GP1_IP_CFG */
1153#define WM8903_GP1_IP_CFG_SHIFT 5 /* GP1_IP_CFG */
1154#define WM8903_GP1_IP_CFG_WIDTH 1 /* GP1_IP_CFG */
1155#define WM8903_GP1_LVL 0x0010 /* GP1_LVL */
1156#define WM8903_GP1_LVL_MASK 0x0010 /* GP1_LVL */
1157#define WM8903_GP1_LVL_SHIFT 4 /* GP1_LVL */
1158#define WM8903_GP1_LVL_WIDTH 1 /* GP1_LVL */
1159#define WM8903_GP1_PD 0x0008 /* GP1_PD */
1160#define WM8903_GP1_PD_MASK 0x0008 /* GP1_PD */
1161#define WM8903_GP1_PD_SHIFT 3 /* GP1_PD */
1162#define WM8903_GP1_PD_WIDTH 1 /* GP1_PD */
1163#define WM8903_GP1_PU 0x0004 /* GP1_PU */
1164#define WM8903_GP1_PU_MASK 0x0004 /* GP1_PU */
1165#define WM8903_GP1_PU_SHIFT 2 /* GP1_PU */
1166#define WM8903_GP1_PU_WIDTH 1 /* GP1_PU */
1167#define WM8903_GP1_INTMODE 0x0002 /* GP1_INTMODE */
1168#define WM8903_GP1_INTMODE_MASK 0x0002 /* GP1_INTMODE */
1169#define WM8903_GP1_INTMODE_SHIFT 1 /* GP1_INTMODE */
1170#define WM8903_GP1_INTMODE_WIDTH 1 /* GP1_INTMODE */
1171#define WM8903_GP1_DB 0x0001 /* GP1_DB */
1172#define WM8903_GP1_DB_MASK 0x0001 /* GP1_DB */
1173#define WM8903_GP1_DB_SHIFT 0 /* GP1_DB */
1174#define WM8903_GP1_DB_WIDTH 1 /* GP1_DB */
1175
1176/*
1177 * R117 (0x75) - GPIO Control 2
1178 */
1179#define WM8903_GP2_FN_MASK 0x1F00 /* GP2_FN - [12:8] */
1180#define WM8903_GP2_FN_SHIFT 8 /* GP2_FN - [12:8] */
1181#define WM8903_GP2_FN_WIDTH 5 /* GP2_FN - [12:8] */
1182#define WM8903_GP2_DIR 0x0080 /* GP2_DIR */
1183#define WM8903_GP2_DIR_MASK 0x0080 /* GP2_DIR */
1184#define WM8903_GP2_DIR_SHIFT 7 /* GP2_DIR */
1185#define WM8903_GP2_DIR_WIDTH 1 /* GP2_DIR */
1186#define WM8903_GP2_OP_CFG 0x0040 /* GP2_OP_CFG */
1187#define WM8903_GP2_OP_CFG_MASK 0x0040 /* GP2_OP_CFG */
1188#define WM8903_GP2_OP_CFG_SHIFT 6 /* GP2_OP_CFG */
1189#define WM8903_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
1190#define WM8903_GP2_IP_CFG 0x0020 /* GP2_IP_CFG */
1191#define WM8903_GP2_IP_CFG_MASK 0x0020 /* GP2_IP_CFG */
1192#define WM8903_GP2_IP_CFG_SHIFT 5 /* GP2_IP_CFG */
1193#define WM8903_GP2_IP_CFG_WIDTH 1 /* GP2_IP_CFG */
1194#define WM8903_GP2_LVL 0x0010 /* GP2_LVL */
1195#define WM8903_GP2_LVL_MASK 0x0010 /* GP2_LVL */
1196#define WM8903_GP2_LVL_SHIFT 4 /* GP2_LVL */
1197#define WM8903_GP2_LVL_WIDTH 1 /* GP2_LVL */
1198#define WM8903_GP2_PD 0x0008 /* GP2_PD */
1199#define WM8903_GP2_PD_MASK 0x0008 /* GP2_PD */
1200#define WM8903_GP2_PD_SHIFT 3 /* GP2_PD */
1201#define WM8903_GP2_PD_WIDTH 1 /* GP2_PD */
1202#define WM8903_GP2_PU 0x0004 /* GP2_PU */
1203#define WM8903_GP2_PU_MASK 0x0004 /* GP2_PU */
1204#define WM8903_GP2_PU_SHIFT 2 /* GP2_PU */
1205#define WM8903_GP2_PU_WIDTH 1 /* GP2_PU */
1206#define WM8903_GP2_INTMODE 0x0002 /* GP2_INTMODE */
1207#define WM8903_GP2_INTMODE_MASK 0x0002 /* GP2_INTMODE */
1208#define WM8903_GP2_INTMODE_SHIFT 1 /* GP2_INTMODE */
1209#define WM8903_GP2_INTMODE_WIDTH 1 /* GP2_INTMODE */
1210#define WM8903_GP2_DB 0x0001 /* GP2_DB */
1211#define WM8903_GP2_DB_MASK 0x0001 /* GP2_DB */
1212#define WM8903_GP2_DB_SHIFT 0 /* GP2_DB */
1213#define WM8903_GP2_DB_WIDTH 1 /* GP2_DB */
1214
1215/*
1216 * R118 (0x76) - GPIO Control 3
1217 */
1218#define WM8903_GP3_FN_MASK 0x1F00 /* GP3_FN - [12:8] */
1219#define WM8903_GP3_FN_SHIFT 8 /* GP3_FN - [12:8] */
1220#define WM8903_GP3_FN_WIDTH 5 /* GP3_FN - [12:8] */
1221#define WM8903_GP3_DIR 0x0080 /* GP3_DIR */
1222#define WM8903_GP3_DIR_MASK 0x0080 /* GP3_DIR */
1223#define WM8903_GP3_DIR_SHIFT 7 /* GP3_DIR */
1224#define WM8903_GP3_DIR_WIDTH 1 /* GP3_DIR */
1225#define WM8903_GP3_OP_CFG 0x0040 /* GP3_OP_CFG */
1226#define WM8903_GP3_OP_CFG_MASK 0x0040 /* GP3_OP_CFG */
1227#define WM8903_GP3_OP_CFG_SHIFT 6 /* GP3_OP_CFG */
1228#define WM8903_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
1229#define WM8903_GP3_IP_CFG 0x0020 /* GP3_IP_CFG */
1230#define WM8903_GP3_IP_CFG_MASK 0x0020 /* GP3_IP_CFG */
1231#define WM8903_GP3_IP_CFG_SHIFT 5 /* GP3_IP_CFG */
1232#define WM8903_GP3_IP_CFG_WIDTH 1 /* GP3_IP_CFG */
1233#define WM8903_GP3_LVL 0x0010 /* GP3_LVL */
1234#define WM8903_GP3_LVL_MASK 0x0010 /* GP3_LVL */
1235#define WM8903_GP3_LVL_SHIFT 4 /* GP3_LVL */
1236#define WM8903_GP3_LVL_WIDTH 1 /* GP3_LVL */
1237#define WM8903_GP3_PD 0x0008 /* GP3_PD */
1238#define WM8903_GP3_PD_MASK 0x0008 /* GP3_PD */
1239#define WM8903_GP3_PD_SHIFT 3 /* GP3_PD */
1240#define WM8903_GP3_PD_WIDTH 1 /* GP3_PD */
1241#define WM8903_GP3_PU 0x0004 /* GP3_PU */
1242#define WM8903_GP3_PU_MASK 0x0004 /* GP3_PU */
1243#define WM8903_GP3_PU_SHIFT 2 /* GP3_PU */
1244#define WM8903_GP3_PU_WIDTH 1 /* GP3_PU */
1245#define WM8903_GP3_INTMODE 0x0002 /* GP3_INTMODE */
1246#define WM8903_GP3_INTMODE_MASK 0x0002 /* GP3_INTMODE */
1247#define WM8903_GP3_INTMODE_SHIFT 1 /* GP3_INTMODE */
1248#define WM8903_GP3_INTMODE_WIDTH 1 /* GP3_INTMODE */
1249#define WM8903_GP3_DB 0x0001 /* GP3_DB */
1250#define WM8903_GP3_DB_MASK 0x0001 /* GP3_DB */
1251#define WM8903_GP3_DB_SHIFT 0 /* GP3_DB */
1252#define WM8903_GP3_DB_WIDTH 1 /* GP3_DB */
1253
1254/*
1255 * R119 (0x77) - GPIO Control 4
1256 */
1257#define WM8903_GP4_FN_MASK 0x1F00 /* GP4_FN - [12:8] */
1258#define WM8903_GP4_FN_SHIFT 8 /* GP4_FN - [12:8] */
1259#define WM8903_GP4_FN_WIDTH 5 /* GP4_FN - [12:8] */
1260#define WM8903_GP4_DIR 0x0080 /* GP4_DIR */
1261#define WM8903_GP4_DIR_MASK 0x0080 /* GP4_DIR */
1262#define WM8903_GP4_DIR_SHIFT 7 /* GP4_DIR */
1263#define WM8903_GP4_DIR_WIDTH 1 /* GP4_DIR */
1264#define WM8903_GP4_OP_CFG 0x0040 /* GP4_OP_CFG */
1265#define WM8903_GP4_OP_CFG_MASK 0x0040 /* GP4_OP_CFG */
1266#define WM8903_GP4_OP_CFG_SHIFT 6 /* GP4_OP_CFG */
1267#define WM8903_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
1268#define WM8903_GP4_IP_CFG 0x0020 /* GP4_IP_CFG */
1269#define WM8903_GP4_IP_CFG_MASK 0x0020 /* GP4_IP_CFG */
1270#define WM8903_GP4_IP_CFG_SHIFT 5 /* GP4_IP_CFG */
1271#define WM8903_GP4_IP_CFG_WIDTH 1 /* GP4_IP_CFG */
1272#define WM8903_GP4_LVL 0x0010 /* GP4_LVL */
1273#define WM8903_GP4_LVL_MASK 0x0010 /* GP4_LVL */
1274#define WM8903_GP4_LVL_SHIFT 4 /* GP4_LVL */
1275#define WM8903_GP4_LVL_WIDTH 1 /* GP4_LVL */
1276#define WM8903_GP4_PD 0x0008 /* GP4_PD */
1277#define WM8903_GP4_PD_MASK 0x0008 /* GP4_PD */
1278#define WM8903_GP4_PD_SHIFT 3 /* GP4_PD */
1279#define WM8903_GP4_PD_WIDTH 1 /* GP4_PD */
1280#define WM8903_GP4_PU 0x0004 /* GP4_PU */
1281#define WM8903_GP4_PU_MASK 0x0004 /* GP4_PU */
1282#define WM8903_GP4_PU_SHIFT 2 /* GP4_PU */
1283#define WM8903_GP4_PU_WIDTH 1 /* GP4_PU */
1284#define WM8903_GP4_INTMODE 0x0002 /* GP4_INTMODE */
1285#define WM8903_GP4_INTMODE_MASK 0x0002 /* GP4_INTMODE */
1286#define WM8903_GP4_INTMODE_SHIFT 1 /* GP4_INTMODE */
1287#define WM8903_GP4_INTMODE_WIDTH 1 /* GP4_INTMODE */
1288#define WM8903_GP4_DB 0x0001 /* GP4_DB */
1289#define WM8903_GP4_DB_MASK 0x0001 /* GP4_DB */
1290#define WM8903_GP4_DB_SHIFT 0 /* GP4_DB */
1291#define WM8903_GP4_DB_WIDTH 1 /* GP4_DB */
1292
1293/*
1294 * R120 (0x78) - GPIO Control 5
1295 */
1296#define WM8903_GP5_FN_MASK 0x1F00 /* GP5_FN - [12:8] */
1297#define WM8903_GP5_FN_SHIFT 8 /* GP5_FN - [12:8] */
1298#define WM8903_GP5_FN_WIDTH 5 /* GP5_FN - [12:8] */
1299#define WM8903_GP5_DIR 0x0080 /* GP5_DIR */
1300#define WM8903_GP5_DIR_MASK 0x0080 /* GP5_DIR */
1301#define WM8903_GP5_DIR_SHIFT 7 /* GP5_DIR */
1302#define WM8903_GP5_DIR_WIDTH 1 /* GP5_DIR */
1303#define WM8903_GP5_OP_CFG 0x0040 /* GP5_OP_CFG */
1304#define WM8903_GP5_OP_CFG_MASK 0x0040 /* GP5_OP_CFG */
1305#define WM8903_GP5_OP_CFG_SHIFT 6 /* GP5_OP_CFG */
1306#define WM8903_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */
1307#define WM8903_GP5_IP_CFG 0x0020 /* GP5_IP_CFG */
1308#define WM8903_GP5_IP_CFG_MASK 0x0020 /* GP5_IP_CFG */
1309#define WM8903_GP5_IP_CFG_SHIFT 5 /* GP5_IP_CFG */
1310#define WM8903_GP5_IP_CFG_WIDTH 1 /* GP5_IP_CFG */
1311#define WM8903_GP5_LVL 0x0010 /* GP5_LVL */
1312#define WM8903_GP5_LVL_MASK 0x0010 /* GP5_LVL */
1313#define WM8903_GP5_LVL_SHIFT 4 /* GP5_LVL */
1314#define WM8903_GP5_LVL_WIDTH 1 /* GP5_LVL */
1315#define WM8903_GP5_PD 0x0008 /* GP5_PD */
1316#define WM8903_GP5_PD_MASK 0x0008 /* GP5_PD */
1317#define WM8903_GP5_PD_SHIFT 3 /* GP5_PD */
1318#define WM8903_GP5_PD_WIDTH 1 /* GP5_PD */
1319#define WM8903_GP5_PU 0x0004 /* GP5_PU */
1320#define WM8903_GP5_PU_MASK 0x0004 /* GP5_PU */
1321#define WM8903_GP5_PU_SHIFT 2 /* GP5_PU */
1322#define WM8903_GP5_PU_WIDTH 1 /* GP5_PU */
1323#define WM8903_GP5_INTMODE 0x0002 /* GP5_INTMODE */
1324#define WM8903_GP5_INTMODE_MASK 0x0002 /* GP5_INTMODE */
1325#define WM8903_GP5_INTMODE_SHIFT 1 /* GP5_INTMODE */
1326#define WM8903_GP5_INTMODE_WIDTH 1 /* GP5_INTMODE */
1327#define WM8903_GP5_DB 0x0001 /* GP5_DB */
1328#define WM8903_GP5_DB_MASK 0x0001 /* GP5_DB */
1329#define WM8903_GP5_DB_SHIFT 0 /* GP5_DB */
1330#define WM8903_GP5_DB_WIDTH 1 /* GP5_DB */
1331
1332/*
1333 * R121 (0x79) - Interrupt Status 1 1120 * R121 (0x79) - Interrupt Status 1
1334 */ 1121 */
1335#define WM8903_MICSHRT_EINT 0x8000 /* MICSHRT_EINT */ 1122#define WM8903_MICSHRT_EINT 0x8000 /* MICSHRT_EINT */
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 593e47d0e0eb..c5b50d73f2d5 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2425,6 +2425,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904);
2425static int wm8904_register(struct wm8904_priv *wm8904, 2425static int wm8904_register(struct wm8904_priv *wm8904,
2426 enum snd_soc_control_type control) 2426 enum snd_soc_control_type control)
2427{ 2427{
2428 struct wm8904_pdata *pdata = wm8904->pdata;
2428 int ret; 2429 int ret;
2429 struct snd_soc_codec *codec = &wm8904->codec; 2430 struct snd_soc_codec *codec = &wm8904->codec;
2430 int i; 2431 int i;
@@ -2530,6 +2531,22 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2530 WM8904_LINEOUTRZC; 2531 WM8904_LINEOUTRZC;
2531 wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; 2532 wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
2532 2533
2534 /* Apply configuration from the platform data. */
2535 if (wm8904->pdata) {
2536 for (i = 0; i < WM8904_GPIO_REGS; i++) {
2537 if (!pdata->gpio_cfg[i])
2538 continue;
2539
2540 wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i]
2541 = pdata->gpio_cfg[i] & 0xffff;
2542 }
2543
2544 /* Zero is the default value for these anyway */
2545 for (i = 0; i < WM8904_MIC_REGS; i++)
2546 wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
2547 = pdata->mic_cfg[i];
2548 }
2549
2533 /* Set Class W by default - this will be managed by the Class 2550 /* Set Class W by default - this will be managed by the Class
2534 * G widget at runtime where bypass paths are available. 2551 * G widget at runtime where bypass paths are available.
2535 */ 2552 */
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h
index b68886df34e4..abe5059b3004 100644
--- a/sound/soc/codecs/wm8904.h
+++ b/sound/soc/codecs/wm8904.h
@@ -186,39 +186,6 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8904;
186#define WM8904_VMID_ENA_WIDTH 1 /* VMID_ENA */ 186#define WM8904_VMID_ENA_WIDTH 1 /* VMID_ENA */
187 187
188/* 188/*
189 * R6 (0x06) - Mic Bias Control 0
190 */
191#define WM8904_MICDET_THR_MASK 0x0070 /* MICDET_THR - [6:4] */
192#define WM8904_MICDET_THR_SHIFT 4 /* MICDET_THR - [6:4] */
193#define WM8904_MICDET_THR_WIDTH 3 /* MICDET_THR - [6:4] */
194#define WM8904_MICSHORT_THR_MASK 0x000C /* MICSHORT_THR - [3:2] */
195#define WM8904_MICSHORT_THR_SHIFT 2 /* MICSHORT_THR - [3:2] */
196#define WM8904_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [3:2] */
197#define WM8904_MICDET_ENA 0x0002 /* MICDET_ENA */
198#define WM8904_MICDET_ENA_MASK 0x0002 /* MICDET_ENA */
199#define WM8904_MICDET_ENA_SHIFT 1 /* MICDET_ENA */
200#define WM8904_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
201#define WM8904_MICBIAS_ENA 0x0001 /* MICBIAS_ENA */
202#define WM8904_MICBIAS_ENA_MASK 0x0001 /* MICBIAS_ENA */
203#define WM8904_MICBIAS_ENA_SHIFT 0 /* MICBIAS_ENA */
204#define WM8904_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
205
206/*
207 * R7 (0x07) - Mic Bias Control 1
208 */
209#define WM8904_MIC_DET_FILTER_ENA 0x8000 /* MIC_DET_FILTER_ENA */
210#define WM8904_MIC_DET_FILTER_ENA_MASK 0x8000 /* MIC_DET_FILTER_ENA */
211#define WM8904_MIC_DET_FILTER_ENA_SHIFT 15 /* MIC_DET_FILTER_ENA */
212#define WM8904_MIC_DET_FILTER_ENA_WIDTH 1 /* MIC_DET_FILTER_ENA */
213#define WM8904_MIC_SHORT_FILTER_ENA 0x4000 /* MIC_SHORT_FILTER_ENA */
214#define WM8904_MIC_SHORT_FILTER_ENA_MASK 0x4000 /* MIC_SHORT_FILTER_ENA */
215#define WM8904_MIC_SHORT_FILTER_ENA_SHIFT 14 /* MIC_SHORT_FILTER_ENA */
216#define WM8904_MIC_SHORT_FILTER_ENA_WIDTH 1 /* MIC_SHORT_FILTER_ENA */
217#define WM8904_MICBIAS_SEL_MASK 0x0007 /* MICBIAS_SEL - [2:0] */
218#define WM8904_MICBIAS_SEL_SHIFT 0 /* MICBIAS_SEL - [2:0] */
219#define WM8904_MICBIAS_SEL_WIDTH 3 /* MICBIAS_SEL - [2:0] */
220
221/*
222 * R8 (0x08) - Analogue DAC 0 189 * R8 (0x08) - Analogue DAC 0
223 */ 190 */
224#define WM8904_DAC_BIAS_SEL_MASK 0x0018 /* DAC_BIAS_SEL - [4:3] */ 191#define WM8904_DAC_BIAS_SEL_MASK 0x0018 /* DAC_BIAS_SEL - [4:3] */
@@ -1200,70 +1167,6 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8904;
1200#define WM8904_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */ 1167#define WM8904_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */
1201 1168
1202/* 1169/*
1203 * R121 (0x79) - GPIO Control 1
1204 */
1205#define WM8904_GPIO1_PU 0x0020 /* GPIO1_PU */
1206#define WM8904_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */
1207#define WM8904_GPIO1_PU_SHIFT 5 /* GPIO1_PU */
1208#define WM8904_GPIO1_PU_WIDTH 1 /* GPIO1_PU */
1209#define WM8904_GPIO1_PD 0x0010 /* GPIO1_PD */
1210#define WM8904_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */
1211#define WM8904_GPIO1_PD_SHIFT 4 /* GPIO1_PD */
1212#define WM8904_GPIO1_PD_WIDTH 1 /* GPIO1_PD */
1213#define WM8904_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */
1214#define WM8904_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */
1215#define WM8904_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */
1216
1217/*
1218 * R122 (0x7A) - GPIO Control 2
1219 */
1220#define WM8904_GPIO2_PU 0x0020 /* GPIO2_PU */
1221#define WM8904_GPIO2_PU_MASK 0x0020 /* GPIO2_PU */
1222#define WM8904_GPIO2_PU_SHIFT 5 /* GPIO2_PU */
1223#define WM8904_GPIO2_PU_WIDTH 1 /* GPIO2_PU */
1224#define WM8904_GPIO2_PD 0x0010 /* GPIO2_PD */
1225#define WM8904_GPIO2_PD_MASK 0x0010 /* GPIO2_PD */
1226#define WM8904_GPIO2_PD_SHIFT 4 /* GPIO2_PD */
1227#define WM8904_GPIO2_PD_WIDTH 1 /* GPIO2_PD */
1228#define WM8904_GPIO2_SEL_MASK 0x000F /* GPIO2_SEL - [3:0] */
1229#define WM8904_GPIO2_SEL_SHIFT 0 /* GPIO2_SEL - [3:0] */
1230#define WM8904_GPIO2_SEL_WIDTH 4 /* GPIO2_SEL - [3:0] */
1231
1232/*
1233 * R123 (0x7B) - GPIO Control 3
1234 */
1235#define WM8904_GPIO3_PU 0x0020 /* GPIO3_PU */
1236#define WM8904_GPIO3_PU_MASK 0x0020 /* GPIO3_PU */
1237#define WM8904_GPIO3_PU_SHIFT 5 /* GPIO3_PU */
1238#define WM8904_GPIO3_PU_WIDTH 1 /* GPIO3_PU */
1239#define WM8904_GPIO3_PD 0x0010 /* GPIO3_PD */
1240#define WM8904_GPIO3_PD_MASK 0x0010 /* GPIO3_PD */
1241#define WM8904_GPIO3_PD_SHIFT 4 /* GPIO3_PD */
1242#define WM8904_GPIO3_PD_WIDTH 1 /* GPIO3_PD */
1243#define WM8904_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */
1244#define WM8904_GPIO3_SEL_SHIFT 0 /* GPIO3_SEL - [3:0] */
1245#define WM8904_GPIO3_SEL_WIDTH 4 /* GPIO3_SEL - [3:0] */
1246
1247/*
1248 * R124 (0x7C) - GPIO Control 4
1249 */
1250#define WM8904_GPI7_ENA 0x0200 /* GPI7_ENA */
1251#define WM8904_GPI7_ENA_MASK 0x0200 /* GPI7_ENA */
1252#define WM8904_GPI7_ENA_SHIFT 9 /* GPI7_ENA */
1253#define WM8904_GPI7_ENA_WIDTH 1 /* GPI7_ENA */
1254#define WM8904_GPI8_ENA 0x0100 /* GPI8_ENA */
1255#define WM8904_GPI8_ENA_MASK 0x0100 /* GPI8_ENA */
1256#define WM8904_GPI8_ENA_SHIFT 8 /* GPI8_ENA */
1257#define WM8904_GPI8_ENA_WIDTH 1 /* GPI8_ENA */
1258#define WM8904_GPIO_BCLK_MODE_ENA 0x0080 /* GPIO_BCLK_MODE_ENA */
1259#define WM8904_GPIO_BCLK_MODE_ENA_MASK 0x0080 /* GPIO_BCLK_MODE_ENA */
1260#define WM8904_GPIO_BCLK_MODE_ENA_SHIFT 7 /* GPIO_BCLK_MODE_ENA */
1261#define WM8904_GPIO_BCLK_MODE_ENA_WIDTH 1 /* GPIO_BCLK_MODE_ENA */
1262#define WM8904_GPIO_BCLK_SEL_MASK 0x000F /* GPIO_BCLK_SEL - [3:0] */
1263#define WM8904_GPIO_BCLK_SEL_SHIFT 0 /* GPIO_BCLK_SEL - [3:0] */
1264#define WM8904_GPIO_BCLK_SEL_WIDTH 4 /* GPIO_BCLK_SEL - [3:0] */
1265
1266/*
1267 * R126 (0x7E) - Digital Pulls 1170 * R126 (0x7E) - Digital Pulls
1268 */ 1171 */
1269#define WM8904_MCLK_PU 0x0080 /* MCLK_PU */ 1172#define WM8904_MCLK_PU 0x0080 /* MCLK_PU */
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index d07bcc1e1c60..c2960d3ec6df 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -22,6 +22,7 @@
22#include <sound/soc-dapm.h> 22#include <sound/soc-dapm.h>
23#include <sound/initval.h> 23#include <sound/initval.h>
24#include <sound/tlv.h> 24#include <sound/tlv.h>
25#include <sound/wm8960.h>
25 26
26#include "wm8960.h" 27#include "wm8960.h"
27 28
@@ -30,8 +31,14 @@
30struct snd_soc_codec_device soc_codec_dev_wm8960; 31struct snd_soc_codec_device soc_codec_dev_wm8960;
31 32
32/* R25 - Power 1 */ 33/* R25 - Power 1 */
34#define WM8960_VMID_MASK 0x180
33#define WM8960_VREF 0x40 35#define WM8960_VREF 0x40
34 36
37/* R26 - Power 2 */
38#define WM8960_PWR2_LOUT1 0x40
39#define WM8960_PWR2_ROUT1 0x20
40#define WM8960_PWR2_OUT3 0x02
41
35/* R28 - Anti-pop 1 */ 42/* R28 - Anti-pop 1 */
36#define WM8960_POBCTRL 0x80 43#define WM8960_POBCTRL 0x80
37#define WM8960_BUFDCOPEN 0x10 44#define WM8960_BUFDCOPEN 0x10
@@ -41,6 +48,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8960;
41 48
42/* R29 - Anti-pop 2 */ 49/* R29 - Anti-pop 2 */
43#define WM8960_DISOP 0x40 50#define WM8960_DISOP 0x40
51#define WM8960_DRES_MASK 0x30
44 52
45/* 53/*
46 * wm8960 register cache 54 * wm8960 register cache
@@ -67,6 +75,9 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
67struct wm8960_priv { 75struct wm8960_priv {
68 u16 reg_cache[WM8960_CACHEREGNUM]; 76 u16 reg_cache[WM8960_CACHEREGNUM];
69 struct snd_soc_codec codec; 77 struct snd_soc_codec codec;
78 struct snd_soc_dapm_widget *lout1;
79 struct snd_soc_dapm_widget *rout1;
80 struct snd_soc_dapm_widget *out3;
70}; 81};
71 82
72#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) 83#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
@@ -225,10 +236,6 @@ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0,
225 &wm8960_routput_mixer[0], 236 &wm8960_routput_mixer[0],
226 ARRAY_SIZE(wm8960_routput_mixer)), 237 ARRAY_SIZE(wm8960_routput_mixer)),
227 238
228SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
229 &wm8960_mono_out[0],
230 ARRAY_SIZE(wm8960_mono_out)),
231
232SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), 239SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0),
233SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), 240SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0),
234 241
@@ -247,6 +254,17 @@ SND_SOC_DAPM_OUTPUT("SPK_RN"),
247SND_SOC_DAPM_OUTPUT("OUT3"), 254SND_SOC_DAPM_OUTPUT("OUT3"),
248}; 255};
249 256
257static const struct snd_soc_dapm_widget wm8960_dapm_widgets_out3[] = {
258SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,
259 &wm8960_mono_out[0],
260 ARRAY_SIZE(wm8960_mono_out)),
261};
262
263/* Represent OUT3 as a PGA so that it gets turned on with LOUT1/ROUT1 */
264static const struct snd_soc_dapm_widget wm8960_dapm_widgets_capless[] = {
265SND_SOC_DAPM_PGA("OUT3 VMID", WM8960_POWER2, 1, 0, NULL, 0),
266};
267
250static const struct snd_soc_dapm_route audio_paths[] = { 268static const struct snd_soc_dapm_route audio_paths[] = {
251 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" }, 269 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },
252 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" }, 270 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
@@ -277,9 +295,6 @@ static const struct snd_soc_dapm_route audio_paths[] = {
277 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } , 295 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } ,
278 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" }, 296 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },
279 297
280 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
281 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
282
283 { "LOUT1 PGA", NULL, "Left Output Mixer" }, 298 { "LOUT1 PGA", NULL, "Left Output Mixer" },
284 { "ROUT1 PGA", NULL, "Right Output Mixer" }, 299 { "ROUT1 PGA", NULL, "Right Output Mixer" },
285 300
@@ -296,17 +311,65 @@ static const struct snd_soc_dapm_route audio_paths[] = {
296 { "SPK_LP", NULL, "Left Speaker Output" }, 311 { "SPK_LP", NULL, "Left Speaker Output" },
297 { "SPK_RN", NULL, "Right Speaker Output" }, 312 { "SPK_RN", NULL, "Right Speaker Output" },
298 { "SPK_RP", NULL, "Right Speaker Output" }, 313 { "SPK_RP", NULL, "Right Speaker Output" },
314};
315
316static const struct snd_soc_dapm_route audio_paths_out3[] = {
317 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },
318 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },
299 319
300 { "OUT3", NULL, "Mono Output Mixer", } 320 { "OUT3", NULL, "Mono Output Mixer", }
301}; 321};
302 322
323static const struct snd_soc_dapm_route audio_paths_capless[] = {
324 { "HP_L", NULL, "OUT3 VMID" },
325 { "HP_R", NULL, "OUT3 VMID" },
326
327 { "OUT3 VMID", NULL, "Left Output Mixer" },
328 { "OUT3 VMID", NULL, "Right Output Mixer" },
329};
330
303static int wm8960_add_widgets(struct snd_soc_codec *codec) 331static int wm8960_add_widgets(struct snd_soc_codec *codec)
304{ 332{
333 struct wm8960_data *pdata = codec->dev->platform_data;
334 struct wm8960_priv *wm8960 = codec->private_data;
335 struct snd_soc_dapm_widget *w;
336
305 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets, 337 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets,
306 ARRAY_SIZE(wm8960_dapm_widgets)); 338 ARRAY_SIZE(wm8960_dapm_widgets));
307 339
308 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 340 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
309 341
342 /* In capless mode OUT3 is used to provide VMID for the
343 * headphone outputs, otherwise it is used as a mono mixer.
344 */
345 if (pdata && pdata->capless) {
346 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets_capless,
347 ARRAY_SIZE(wm8960_dapm_widgets_capless));
348
349 snd_soc_dapm_add_routes(codec, audio_paths_capless,
350 ARRAY_SIZE(audio_paths_capless));
351 } else {
352 snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets_out3,
353 ARRAY_SIZE(wm8960_dapm_widgets_out3));
354
355 snd_soc_dapm_add_routes(codec, audio_paths_out3,
356 ARRAY_SIZE(audio_paths_out3));
357 }
358
359 /* We need to power up the headphone output stage out of
360 * sequence for capless mode. To save scanning the widget
361 * list each time to find the desired power state do so now
362 * and save the result.
363 */
364 list_for_each_entry(w, &codec->dapm_widgets, list) {
365 if (strcmp(w->name, "LOUT1 PGA") == 0)
366 wm8960->lout1 = w;
367 if (strcmp(w->name, "ROUT1 PGA") == 0)
368 wm8960->rout1 = w;
369 if (strcmp(w->name, "OUT3 VMID") == 0)
370 wm8960->out3 = w;
371 }
372
310 return 0; 373 return 0;
311} 374}
312 375
@@ -407,10 +470,9 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute)
407 return 0; 470 return 0;
408} 471}
409 472
410static int wm8960_set_bias_level(struct snd_soc_codec *codec, 473static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
411 enum snd_soc_bias_level level) 474 enum snd_soc_bias_level level)
412{ 475{
413 struct wm8960_data *pdata = codec->dev->platform_data;
414 u16 reg; 476 u16 reg;
415 477
416 switch (level) { 478 switch (level) {
@@ -429,18 +491,8 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
429 if (codec->bias_level == SND_SOC_BIAS_OFF) { 491 if (codec->bias_level == SND_SOC_BIAS_OFF) {
430 /* Enable anti-pop features */ 492 /* Enable anti-pop features */
431 snd_soc_write(codec, WM8960_APOP1, 493 snd_soc_write(codec, WM8960_APOP1,
432 WM8960_POBCTRL | WM8960_SOFT_ST | 494 WM8960_POBCTRL | WM8960_SOFT_ST |
433 WM8960_BUFDCOPEN | WM8960_BUFIOEN); 495 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
434
435 /* Discharge HP output */
436 reg = WM8960_DISOP;
437 if (pdata)
438 reg |= pdata->dres << 4;
439 snd_soc_write(codec, WM8960_APOP2, reg);
440
441 msleep(400);
442
443 snd_soc_write(codec, WM8960_APOP2, 0);
444 496
445 /* Enable & ramp VMID at 2x50k */ 497 /* Enable & ramp VMID at 2x50k */
446 reg = snd_soc_read(codec, WM8960_POWER1); 498 reg = snd_soc_read(codec, WM8960_POWER1);
@@ -471,8 +523,101 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
471 /* Disable VMID and VREF, let them discharge */ 523 /* Disable VMID and VREF, let them discharge */
472 snd_soc_write(codec, WM8960_POWER1, 0); 524 snd_soc_write(codec, WM8960_POWER1, 0);
473 msleep(600); 525 msleep(600);
526 break;
527 }
528
529 codec->bias_level = level;
530
531 return 0;
532}
533
534static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
535 enum snd_soc_bias_level level)
536{
537 struct wm8960_priv *wm8960 = codec->private_data;
538 int reg;
539
540 switch (level) {
541 case SND_SOC_BIAS_ON:
542 break;
543
544 case SND_SOC_BIAS_PREPARE:
545 switch (codec->bias_level) {
546 case SND_SOC_BIAS_STANDBY:
547 /* Enable anti pop mode */
548 snd_soc_update_bits(codec, WM8960_APOP1,
549 WM8960_POBCTRL | WM8960_SOFT_ST |
550 WM8960_BUFDCOPEN,
551 WM8960_POBCTRL | WM8960_SOFT_ST |
552 WM8960_BUFDCOPEN);
553
554 /* Enable LOUT1, ROUT1 and OUT3 if they're enabled */
555 reg = 0;
556 if (wm8960->lout1 && wm8960->lout1->power)
557 reg |= WM8960_PWR2_LOUT1;
558 if (wm8960->rout1 && wm8960->rout1->power)
559 reg |= WM8960_PWR2_ROUT1;
560 if (wm8960->out3 && wm8960->out3->power)
561 reg |= WM8960_PWR2_OUT3;
562 snd_soc_update_bits(codec, WM8960_POWER2,
563 WM8960_PWR2_LOUT1 |
564 WM8960_PWR2_ROUT1 |
565 WM8960_PWR2_OUT3, reg);
566
567 /* Enable VMID at 2*50k */
568 snd_soc_update_bits(codec, WM8960_POWER1,
569 WM8960_VMID_MASK, 0x80);
570
571 /* Ramp */
572 msleep(100);
573
574 /* Enable VREF */
575 snd_soc_update_bits(codec, WM8960_POWER1,
576 WM8960_VREF, WM8960_VREF);
577
578 msleep(100);
579 break;
580
581 case SND_SOC_BIAS_ON:
582 /* Enable anti-pop mode */
583 snd_soc_update_bits(codec, WM8960_APOP1,
584 WM8960_POBCTRL | WM8960_SOFT_ST |
585 WM8960_BUFDCOPEN,
586 WM8960_POBCTRL | WM8960_SOFT_ST |
587 WM8960_BUFDCOPEN);
588
589 /* Disable VMID and VREF */
590 snd_soc_update_bits(codec, WM8960_POWER1,
591 WM8960_VREF | WM8960_VMID_MASK, 0);
592 break;
593
594 default:
595 break;
596 }
597 break;
598
599 case SND_SOC_BIAS_STANDBY:
600 switch (codec->bias_level) {
601 case SND_SOC_BIAS_PREPARE:
602 /* Disable HP discharge */
603 snd_soc_update_bits(codec, WM8960_APOP2,
604 WM8960_DISOP | WM8960_DRES_MASK,
605 0);
606
607 /* Disable anti-pop features */
608 snd_soc_update_bits(codec, WM8960_APOP1,
609 WM8960_POBCTRL | WM8960_SOFT_ST |
610 WM8960_BUFDCOPEN,
611 WM8960_POBCTRL | WM8960_SOFT_ST |
612 WM8960_BUFDCOPEN);
613 break;
614
615 default:
616 break;
617 }
618 break;
474 619
475 snd_soc_write(codec, WM8960_APOP1, 0); 620 case SND_SOC_BIAS_OFF:
476 break; 621 break;
477 } 622 }
478 623
@@ -662,7 +807,7 @@ static int wm8960_suspend(struct platform_device *pdev, pm_message_t state)
662 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 807 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
663 struct snd_soc_codec *codec = socdev->card->codec; 808 struct snd_soc_codec *codec = socdev->card->codec;
664 809
665 wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF); 810 codec->set_bias_level(codec, SND_SOC_BIAS_OFF);
666 return 0; 811 return 0;
667} 812}
668 813
@@ -681,8 +826,8 @@ static int wm8960_resume(struct platform_device *pdev)
681 codec->hw_write(codec->control_data, data, 2); 826 codec->hw_write(codec->control_data, data, 2);
682 } 827 }
683 828
684 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 829 codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
685 wm8960_set_bias_level(codec, codec->suspend_bias_level); 830 codec->set_bias_level(codec, codec->suspend_bias_level);
686 return 0; 831 return 0;
687} 832}
688 833
@@ -752,6 +897,8 @@ static int wm8960_register(struct wm8960_priv *wm8960,
752 goto err; 897 goto err;
753 } 898 }
754 899
900 codec->set_bias_level = wm8960_set_bias_level_out3;
901
755 if (!pdata) { 902 if (!pdata) {
756 dev_warn(codec->dev, "No platform data supplied\n"); 903 dev_warn(codec->dev, "No platform data supplied\n");
757 } else { 904 } else {
@@ -759,6 +906,9 @@ static int wm8960_register(struct wm8960_priv *wm8960,
759 dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); 906 dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres);
760 pdata->dres = 0; 907 pdata->dres = 0;
761 } 908 }
909
910 if (pdata->capless)
911 codec->set_bias_level = wm8960_set_bias_level_capless;
762 } 912 }
763 913
764 mutex_init(&codec->mutex); 914 mutex_init(&codec->mutex);
@@ -769,7 +919,6 @@ static int wm8960_register(struct wm8960_priv *wm8960,
769 codec->name = "WM8960"; 919 codec->name = "WM8960";
770 codec->owner = THIS_MODULE; 920 codec->owner = THIS_MODULE;
771 codec->bias_level = SND_SOC_BIAS_OFF; 921 codec->bias_level = SND_SOC_BIAS_OFF;
772 codec->set_bias_level = wm8960_set_bias_level;
773 codec->dai = &wm8960_dai; 922 codec->dai = &wm8960_dai;
774 codec->num_dai = 1; 923 codec->num_dai = 1;
775 codec->reg_cache_size = WM8960_CACHEREGNUM; 924 codec->reg_cache_size = WM8960_CACHEREGNUM;
@@ -791,7 +940,7 @@ static int wm8960_register(struct wm8960_priv *wm8960,
791 940
792 wm8960_dai.dev = codec->dev; 941 wm8960_dai.dev = codec->dev;
793 942
794 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 943 codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
795 944
796 /* Latch the update bits */ 945 /* Latch the update bits */
797 reg = snd_soc_read(codec, WM8960_LINVOL); 946 reg = snd_soc_read(codec, WM8960_LINVOL);
@@ -840,7 +989,7 @@ err:
840 989
841static void wm8960_unregister(struct wm8960_priv *wm8960) 990static void wm8960_unregister(struct wm8960_priv *wm8960)
842{ 991{
843 wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); 992 wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF);
844 snd_soc_unregister_dai(&wm8960_dai); 993 snd_soc_unregister_dai(&wm8960_dai);
845 snd_soc_unregister_codec(&wm8960->codec); 994 snd_soc_unregister_codec(&wm8960->codec);
846 kfree(wm8960); 995 kfree(wm8960);
@@ -882,7 +1031,7 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
882 1031
883static struct i2c_driver wm8960_i2c_driver = { 1032static struct i2c_driver wm8960_i2c_driver = {
884 .driver = { 1033 .driver = {
885 .name = "WM8960 I2C Codec", 1034 .name = "wm8960",
886 .owner = THIS_MODULE, 1035 .owner = THIS_MODULE,
887 }, 1036 },
888 .probe = wm8960_i2c_probe, 1037 .probe = wm8960_i2c_probe,
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h
index c9af56c9d9d4..d67bfe1300da 100644
--- a/sound/soc/codecs/wm8960.h
+++ b/sound/soc/codecs/wm8960.h
@@ -114,14 +114,4 @@
114extern struct snd_soc_dai wm8960_dai; 114extern struct snd_soc_dai wm8960_dai;
115extern struct snd_soc_codec_device soc_codec_dev_wm8960; 115extern struct snd_soc_codec_device soc_codec_dev_wm8960;
116 116
117#define WM8960_DRES_400R 0
118#define WM8960_DRES_200R 1
119#define WM8960_DRES_600R 2
120#define WM8960_DRES_150R 3
121#define WM8960_DRES_MAX 3
122
123struct wm8960_data {
124 int dres;
125};
126
127#endif 117#endif
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index f8355ac76a42..e00201e0820e 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -61,6 +61,12 @@ static int wm8994_retune_mobile_base[] = {
61 61
62#define WM8994_REG_CACHE_SIZE 0x621 62#define WM8994_REG_CACHE_SIZE 0x621
63 63
64struct wm8994_micdet {
65 struct snd_soc_jack *jack;
66 int det;
67 int shrt;
68};
69
64/* codec private data */ 70/* codec private data */
65struct wm8994_priv { 71struct wm8994_priv {
66 struct wm_hubs_data hubs; 72 struct wm_hubs_data hubs;
@@ -86,6 +92,8 @@ struct wm8994_priv {
86 int retune_mobile_cfg[WM8994_NUM_EQ]; 92 int retune_mobile_cfg[WM8994_NUM_EQ];
87 struct soc_enum retune_mobile_enum; 93 struct soc_enum retune_mobile_enum;
88 94
95 struct wm8994_micdet micdet[2];
96
89 struct wm8994_pdata *pdata; 97 struct wm8994_pdata *pdata;
90}; 98};
91 99
@@ -3337,6 +3345,36 @@ static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute)
3337 return 0; 3345 return 0;
3338} 3346}
3339 3347
3348static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate)
3349{
3350 struct snd_soc_codec *codec = codec_dai->codec;
3351 int reg, val, mask;
3352
3353 switch (codec_dai->id) {
3354 case 1:
3355 reg = WM8994_AIF1_MASTER_SLAVE;
3356 mask = WM8994_AIF1_TRI;
3357 break;
3358 case 2:
3359 reg = WM8994_AIF2_MASTER_SLAVE;
3360 mask = WM8994_AIF2_TRI;
3361 break;
3362 case 3:
3363 reg = WM8994_POWER_MANAGEMENT_6;
3364 mask = WM8994_AIF3_TRI;
3365 break;
3366 default:
3367 return -EINVAL;
3368 }
3369
3370 if (tristate)
3371 val = mask;
3372 else
3373 val = 0;
3374
3375 return snd_soc_update_bits(codec, reg, mask, reg);
3376}
3377
3340#define WM8994_RATES SNDRV_PCM_RATE_8000_96000 3378#define WM8994_RATES SNDRV_PCM_RATE_8000_96000
3341 3379
3342#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 3380#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
@@ -3348,6 +3386,7 @@ static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
3348 .hw_params = wm8994_hw_params, 3386 .hw_params = wm8994_hw_params,
3349 .digital_mute = wm8994_aif_mute, 3387 .digital_mute = wm8994_aif_mute,
3350 .set_pll = wm8994_set_fll, 3388 .set_pll = wm8994_set_fll,
3389 .set_tristate = wm8994_set_tristate,
3351}; 3390};
3352 3391
3353static struct snd_soc_dai_ops wm8994_aif2_dai_ops = { 3392static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
@@ -3356,6 +3395,11 @@ static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
3356 .hw_params = wm8994_hw_params, 3395 .hw_params = wm8994_hw_params,
3357 .digital_mute = wm8994_aif_mute, 3396 .digital_mute = wm8994_aif_mute,
3358 .set_pll = wm8994_set_fll, 3397 .set_pll = wm8994_set_fll,
3398 .set_tristate = wm8994_set_tristate,
3399};
3400
3401static struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
3402 .set_tristate = wm8994_set_tristate,
3359}; 3403};
3360 3404
3361struct snd_soc_dai wm8994_dai[] = { 3405struct snd_soc_dai wm8994_dai[] = {
@@ -3399,6 +3443,7 @@ struct snd_soc_dai wm8994_dai[] = {
3399 }, 3443 },
3400 { 3444 {
3401 .name = "WM8994 AIF3", 3445 .name = "WM8994 AIF3",
3446 .id = 3,
3402 .playback = { 3447 .playback = {
3403 .stream_name = "AIF3 Playback", 3448 .stream_name = "AIF3 Playback",
3404 .channels_min = 2, 3449 .channels_min = 2,
@@ -3413,6 +3458,7 @@ struct snd_soc_dai wm8994_dai[] = {
3413 .rates = WM8994_RATES, 3458 .rates = WM8994_RATES,
3414 .formats = WM8994_FORMATS, 3459 .formats = WM8994_FORMATS,
3415 }, 3460 },
3461 .ops = &wm8994_aif3_dai_ops,
3416 } 3462 }
3417}; 3463};
3418EXPORT_SYMBOL_GPL(wm8994_dai); 3464EXPORT_SYMBOL_GPL(wm8994_dai);
@@ -3669,6 +3715,96 @@ struct snd_soc_codec_device soc_codec_dev_wm8994 = {
3669}; 3715};
3670EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); 3716EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
3671 3717
3718/**
3719 * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ
3720 *
3721 * @codec: WM8994 codec
3722 * @jack: jack to report detection events on
3723 * @micbias: microphone bias to detect on
3724 * @det: value to report for presence detection
3725 * @shrt: value to report for short detection
3726 *
3727 * Enable microphone detection via IRQ on the WM8994. If GPIOs are
3728 * being used to bring out signals to the processor then only platform
3729 * data configuration is needed for WM8903 and processor GPIOs should
3730 * be configured using snd_soc_jack_add_gpios() instead.
3731 *
3732 * Configuration of detection levels is available via the micbias1_lvl
3733 * and micbias2_lvl platform data members.
3734 */
3735int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
3736 int micbias, int det, int shrt)
3737{
3738 struct wm8994_priv *wm8994 = codec->private_data;
3739 struct wm8994_micdet *micdet;
3740 int reg;
3741
3742 switch (micbias) {
3743 case 1:
3744 micdet = &wm8994->micdet[0];
3745 break;
3746 case 2:
3747 micdet = &wm8994->micdet[1];
3748 break;
3749 default:
3750 return -EINVAL;
3751 }
3752
3753 dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
3754 micbias, det, shrt);
3755
3756 /* Store the configuration */
3757 micdet->jack = jack;
3758 micdet->det = det;
3759 micdet->shrt = shrt;
3760
3761 /* If either of the jacks is set up then enable detection */
3762 if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
3763 reg = WM8994_MICD_ENA;
3764 else
3765 reg = 0;
3766
3767 snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
3768
3769 return 0;
3770}
3771EXPORT_SYMBOL_GPL(wm8994_mic_detect);
3772
3773static irqreturn_t wm8994_mic_irq(int irq, void *data)
3774{
3775 struct wm8994_priv *priv = data;
3776 struct snd_soc_codec *codec = &priv->codec;
3777 int reg;
3778 int report;
3779
3780 reg = snd_soc_read(codec, WM8994_INTERRUPT_RAW_STATUS_2);
3781 if (reg < 0) {
3782 dev_err(codec->dev, "Failed to read microphone status: %d\n",
3783 reg);
3784 return IRQ_HANDLED;
3785 }
3786
3787 dev_dbg(codec->dev, "Microphone status: %x\n", reg);
3788
3789 report = 0;
3790 if (reg & WM8994_MIC1_DET_STS)
3791 report |= priv->micdet[0].det;
3792 if (reg & WM8994_MIC1_SHRT_STS)
3793 report |= priv->micdet[0].shrt;
3794 snd_soc_jack_report(priv->micdet[0].jack, report,
3795 priv->micdet[0].det | priv->micdet[0].shrt);
3796
3797 report = 0;
3798 if (reg & WM8994_MIC2_DET_STS)
3799 report |= priv->micdet[1].det;
3800 if (reg & WM8994_MIC2_SHRT_STS)
3801 report |= priv->micdet[1].shrt;
3802 snd_soc_jack_report(priv->micdet[1].jack, report,
3803 priv->micdet[1].det | priv->micdet[1].shrt);
3804
3805 return IRQ_HANDLED;
3806}
3807
3672static int wm8994_codec_probe(struct platform_device *pdev) 3808static int wm8994_codec_probe(struct platform_device *pdev)
3673{ 3809{
3674 int ret; 3810 int ret;
@@ -3742,6 +3878,30 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3742 break; 3878 break;
3743 } 3879 }
3744 3880
3881 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
3882 wm8994_mic_irq, "Mic 1 detect", wm8994);
3883 if (ret != 0)
3884 dev_warn(&pdev->dev,
3885 "Failed to request Mic1 detect IRQ: %d\n", ret);
3886
3887 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
3888 wm8994_mic_irq, "Mic 1 short", wm8994);
3889 if (ret != 0)
3890 dev_warn(&pdev->dev,
3891 "Failed to request Mic1 short IRQ: %d\n", ret);
3892
3893 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
3894 wm8994_mic_irq, "Mic 2 detect", wm8994);
3895 if (ret != 0)
3896 dev_warn(&pdev->dev,
3897 "Failed to request Mic2 detect IRQ: %d\n", ret);
3898
3899 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,
3900 wm8994_mic_irq, "Mic 2 short", wm8994);
3901 if (ret != 0)
3902 dev_warn(&pdev->dev,
3903 "Failed to request Mic2 short IRQ: %d\n", ret);
3904
3745 /* Remember if AIFnLRCLK is configured as a GPIO. This should be 3905 /* Remember if AIFnLRCLK is configured as a GPIO. This should be
3746 * configured on init - if a system wants to do this dynamically 3906 * configured on init - if a system wants to do this dynamically
3747 * at runtime we can deal with that then. 3907 * at runtime we can deal with that then.
@@ -3749,7 +3909,7 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3749 ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_1); 3909 ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_1);
3750 if (ret < 0) { 3910 if (ret < 0) {
3751 dev_err(codec->dev, "Failed to read GPIO1 state: %d\n", ret); 3911 dev_err(codec->dev, "Failed to read GPIO1 state: %d\n", ret);
3752 goto err; 3912 goto err_irq;
3753 } 3913 }
3754 if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { 3914 if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
3755 wm8994->lrclk_shared[0] = 1; 3915 wm8994->lrclk_shared[0] = 1;
@@ -3761,7 +3921,7 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3761 ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_6); 3921 ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_6);
3762 if (ret < 0) { 3922 if (ret < 0) {
3763 dev_err(codec->dev, "Failed to read GPIO6 state: %d\n", ret); 3923 dev_err(codec->dev, "Failed to read GPIO6 state: %d\n", ret);
3764 goto err; 3924 goto err_irq;
3765 } 3925 }
3766 if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { 3926 if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
3767 wm8994->lrclk_shared[1] = 1; 3927 wm8994->lrclk_shared[1] = 1;
@@ -3811,7 +3971,7 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3811 ret = snd_soc_register_codec(codec); 3971 ret = snd_soc_register_codec(codec);
3812 if (ret != 0) { 3972 if (ret != 0) {
3813 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 3973 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
3814 goto err; 3974 goto err_irq;
3815 } 3975 }
3816 3976
3817 ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); 3977 ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
@@ -3826,6 +3986,11 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3826 3986
3827err_codec: 3987err_codec:
3828 snd_soc_unregister_codec(codec); 3988 snd_soc_unregister_codec(codec);
3989err_irq:
3990 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
3991 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
3992 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
3993 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
3829err: 3994err:
3830 kfree(wm8994); 3995 kfree(wm8994);
3831 return ret; 3996 return ret;
@@ -3839,6 +4004,10 @@ static int __devexit wm8994_codec_remove(struct platform_device *pdev)
3839 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); 4004 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
3840 snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); 4005 snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
3841 snd_soc_unregister_codec(&wm8994->codec); 4006 snd_soc_unregister_codec(&wm8994->codec);
4007 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
4008 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
4009 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
4010 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
3842 kfree(wm8994); 4011 kfree(wm8994);
3843 wm8994_codec = NULL; 4012 wm8994_codec = NULL;
3844 4013
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 0a5e1424dea0..79d5915ae4b3 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -23,4 +23,7 @@ extern struct snd_soc_dai wm8994_dai[];
23#define WM8994_FLL1 1 23#define WM8994_FLL1 1
24#define WM8994_FLL2 2 24#define WM8994_FLL2 2
25 25
26int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
27 int micbias, int det, int shrt);
28
26#endif 29#endif
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 047ee39418c0..6bbf001f6591 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -12,15 +12,38 @@ config SND_DAVINCI_SOC_I2S
12config SND_DAVINCI_SOC_MCASP 12config SND_DAVINCI_SOC_MCASP
13 tristate 13 tristate
14 14
15config SND_DAVINCI_SOC_VCIF
16 tristate
17
15config SND_DAVINCI_SOC_EVM 18config SND_DAVINCI_SOC_EVM
16 tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" 19 tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
17 depends on SND_DAVINCI_SOC 20 depends on SND_DAVINCI_SOC
18 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM 21 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
19 select SND_DAVINCI_SOC_I2S 22 select SND_DAVINCI_SOC_I2S
20 select SND_SOC_TLV320AIC3X 23 select SND_SOC_TLV320AIC3X
21 help 24 help
22 Say Y if you want to add support for SoC audio on TI 25 Say Y if you want to add support for SoC audio on TI
23 DaVinci DM6446 or DM355 EVM platforms. 26 DaVinci DM6446, DM355 or DM365 EVM platforms.
27
28choice
29 prompt "DM365 codec select"
30 depends on SND_DAVINCI_SOC_EVM
31 depends on MACH_DAVINCI_DM365_EVM
32 default SND_DM365_EXTERNAL_CODEC
33
34config SND_DM365_AIC3X_CODEC
35 bool "Audio Codec - AIC3101"
36 help
37 Say Y if you want to add support for AIC3101 audio codec
38
39config SND_DM365_VOICE_CODEC
40 bool "Voice Codec - CQ93VC"
41 select MFD_DAVINCI_VOICECODEC
42 select SND_DAVINCI_SOC_VCIF
43 select SND_SOC_CQ0093VC
44 help
45 Say Y if you want to add support for SoC On-chip voice codec
46endchoice
24 47
25config SND_DM6467_SOC_EVM 48config SND_DM6467_SOC_EVM
26 tristate "SoC Audio support for DaVinci DM6467 EVM" 49 tristate "SoC Audio support for DaVinci DM6467 EVM"
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index a6939d71b988..a93679d618cd 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -2,10 +2,12 @@
2snd-soc-davinci-objs := davinci-pcm.o 2snd-soc-davinci-objs := davinci-pcm.o
3snd-soc-davinci-i2s-objs := davinci-i2s.o 3snd-soc-davinci-i2s-objs := davinci-i2s.o
4snd-soc-davinci-mcasp-objs:= davinci-mcasp.o 4snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
5snd-soc-davinci-vcif-objs:= davinci-vcif.o
5 6
6obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o 7obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
7obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o 8obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
8obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o 9obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
10obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
9 11
10# DAVINCI Machine Support 12# DAVINCI Machine Support
11snd-soc-evm-objs := davinci-evm.o 13snd-soc-evm-objs := davinci-evm.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 7ccbe6684fc2..97f74d6a33e6 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -28,10 +28,12 @@
28#include <mach/mux.h> 28#include <mach/mux.h>
29 29
30#include "../codecs/tlv320aic3x.h" 30#include "../codecs/tlv320aic3x.h"
31#include "../codecs/cq93vc.h"
31#include "../codecs/spdif_transciever.h" 32#include "../codecs/spdif_transciever.h"
32#include "davinci-pcm.h" 33#include "davinci-pcm.h"
33#include "davinci-i2s.h" 34#include "davinci-i2s.h"
34#include "davinci-mcasp.h" 35#include "davinci-mcasp.h"
36#include "davinci-vcif.h"
35 37
36#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ 38#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
37 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) 39 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -81,10 +83,24 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
81 return 0; 83 return 0;
82} 84}
83 85
86static int evm_spdif_hw_params(struct snd_pcm_substream *substream,
87 struct snd_pcm_hw_params *params)
88{
89 struct snd_soc_pcm_runtime *rtd = substream->private_data;
90 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
91
92 /* set cpu DAI configuration */
93 return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
94}
95
84static struct snd_soc_ops evm_ops = { 96static struct snd_soc_ops evm_ops = {
85 .hw_params = evm_hw_params, 97 .hw_params = evm_hw_params,
86}; 98};
87 99
100static struct snd_soc_ops evm_spdif_ops = {
101 .hw_params = evm_spdif_hw_params,
102};
103
88/* davinci-evm machine dapm widgets */ 104/* davinci-evm machine dapm widgets */
89static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { 105static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
90 SND_SOC_DAPM_HP("Headphone Jack", NULL), 106 SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -151,6 +167,22 @@ static struct snd_soc_dai_link evm_dai = {
151 .ops = &evm_ops, 167 .ops = &evm_ops,
152}; 168};
153 169
170static struct snd_soc_dai_link dm365_evm_dai = {
171#ifdef CONFIG_SND_DM365_AIC3X_CODEC
172 .name = "TLV320AIC3X",
173 .stream_name = "AIC3X",
174 .cpu_dai = &davinci_i2s_dai,
175 .codec_dai = &aic3x_dai,
176 .init = evm_aic3x_init,
177 .ops = &evm_ops,
178#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
179 .name = "Voice Codec - CQ93VC",
180 .stream_name = "CQ93",
181 .cpu_dai = &davinci_vcif_dai,
182 .codec_dai = &cq93vc_dai,
183#endif
184};
185
154static struct snd_soc_dai_link dm6467_evm_dai[] = { 186static struct snd_soc_dai_link dm6467_evm_dai[] = {
155 { 187 {
156 .name = "TLV320AIC3X", 188 .name = "TLV320AIC3X",
@@ -165,7 +197,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = {
165 .stream_name = "spdif", 197 .stream_name = "spdif",
166 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], 198 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI],
167 .codec_dai = &dit_stub_dai, 199 .codec_dai = &dit_stub_dai,
168 .ops = &evm_ops, 200 .ops = &evm_spdif_ops,
169 }, 201 },
170}; 202};
171static struct snd_soc_dai_link da8xx_evm_dai = { 203static struct snd_soc_dai_link da8xx_evm_dai = {
@@ -177,7 +209,7 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
177 .ops = &evm_ops, 209 .ops = &evm_ops,
178}; 210};
179 211
180/* davinci dm6446, dm355 or dm365 evm audio machine driver */ 212/* davinci dm6446, dm355 evm audio machine driver */
181static struct snd_soc_card snd_soc_card_evm = { 213static struct snd_soc_card snd_soc_card_evm = {
182 .name = "DaVinci EVM", 214 .name = "DaVinci EVM",
183 .platform = &davinci_soc_platform, 215 .platform = &davinci_soc_platform,
@@ -185,6 +217,15 @@ static struct snd_soc_card snd_soc_card_evm = {
185 .num_links = 1, 217 .num_links = 1,
186}; 218};
187 219
220/* davinci dm365 evm audio machine driver */
221static struct snd_soc_card dm365_snd_soc_card_evm = {
222 .name = "DaVinci DM365 EVM",
223 .platform = &davinci_soc_platform,
224 .dai_link = &dm365_evm_dai,
225 .num_links = 1,
226};
227
228
188/* davinci dm6467 evm audio machine driver */ 229/* davinci dm6467 evm audio machine driver */
189static struct snd_soc_card dm6467_snd_soc_card_evm = { 230static struct snd_soc_card dm6467_snd_soc_card_evm = {
190 .name = "DaVinci DM6467 EVM", 231 .name = "DaVinci DM6467 EVM",
@@ -217,6 +258,17 @@ static struct snd_soc_device evm_snd_devdata = {
217}; 258};
218 259
219/* evm audio subsystem */ 260/* evm audio subsystem */
261static struct snd_soc_device dm365_evm_snd_devdata = {
262 .card = &dm365_snd_soc_card_evm,
263#ifdef CONFIG_SND_DM365_AIC3X_CODEC
264 .codec_dev = &soc_codec_dev_aic3x,
265 .codec_data = &aic3x_setup,
266#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
267 .codec_dev = &soc_codec_dev_cq93vc,
268#endif
269};
270
271/* evm audio subsystem */
220static struct snd_soc_device dm6467_evm_snd_devdata = { 272static struct snd_soc_device dm6467_evm_snd_devdata = {
221 .card = &dm6467_snd_soc_card_evm, 273 .card = &dm6467_snd_soc_card_evm,
222 .codec_dev = &soc_codec_dev_aic3x, 274 .codec_dev = &soc_codec_dev_aic3x,
@@ -244,12 +296,15 @@ static int __init evm_init(void)
244 int index; 296 int index;
245 int ret; 297 int ret;
246 298
247 if (machine_is_davinci_evm() || machine_is_davinci_dm365_evm()) { 299 if (machine_is_davinci_evm()) {
248 evm_snd_dev_data = &evm_snd_devdata; 300 evm_snd_dev_data = &evm_snd_devdata;
249 index = 0; 301 index = 0;
250 } else if (machine_is_davinci_dm355_evm()) { 302 } else if (machine_is_davinci_dm355_evm()) {
251 evm_snd_dev_data = &evm_snd_devdata; 303 evm_snd_dev_data = &evm_snd_devdata;
252 index = 1; 304 index = 1;
305 } else if (machine_is_davinci_dm365_evm()) {
306 evm_snd_dev_data = &dm365_evm_snd_devdata;
307 index = 0;
253 } else if (machine_is_davinci_dm6467_evm()) { 308 } else if (machine_is_davinci_dm6467_evm()) {
254 evm_snd_dev_data = &dm6467_evm_snd_devdata; 309 evm_snd_dev_data = &dm6467_evm_snd_devdata;
255 index = 0; 310 index = 0;
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
new file mode 100644
index 000000000000..9aa980d38231
--- /dev/null
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -0,0 +1,274 @@
1/*
2 * ALSA SoC Voice Codec Interface for TI DAVINCI processor
3 *
4 * Copyright (C) 2010 Texas Instruments.
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/device.h>
26#include <linux/delay.h>
27#include <linux/slab.h>
28#include <linux/io.h>
29#include <linux/mfd/davinci_voicecodec.h>
30
31#include <sound/core.h>
32#include <sound/pcm.h>
33#include <sound/pcm_params.h>
34#include <sound/initval.h>
35#include <sound/soc.h>
36
37#include "davinci-pcm.h"
38#include "davinci-i2s.h"
39#include "davinci-vcif.h"
40
41#define MOD_REG_BIT(val, mask, set) do { \
42 if (set) { \
43 val |= mask; \
44 } else { \
45 val &= ~mask; \
46 } \
47} while (0)
48
49struct davinci_vcif_dev {
50 struct davinci_vc *davinci_vc;
51 struct davinci_pcm_dma_params dma_params[2];
52};
53
54static void davinci_vcif_start(struct snd_pcm_substream *substream)
55{
56 struct snd_soc_pcm_runtime *rtd = substream->private_data;
57 struct davinci_vcif_dev *davinci_vcif_dev =
58 rtd->dai->cpu_dai->private_data;
59 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
60 u32 w;
61
62 /* Start the sample generator and enable transmitter/receiver */
63 w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
64
65 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
66 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1);
67 else
68 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1);
69
70 writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
71}
72
73static void davinci_vcif_stop(struct snd_pcm_substream *substream)
74{
75 struct snd_soc_pcm_runtime *rtd = substream->private_data;
76 struct davinci_vcif_dev *davinci_vcif_dev =
77 rtd->dai->cpu_dai->private_data;
78 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
79 u32 w;
80
81 /* Reset transmitter/receiver and sample rate/frame sync generators */
82 w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
83 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
84 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0);
85 else
86 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0);
87
88 writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
89}
90
91static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
92 struct snd_pcm_hw_params *params,
93 struct snd_soc_dai *dai)
94{
95 struct davinci_vcif_dev *davinci_vcif_dev = dai->private_data;
96 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
97 struct davinci_pcm_dma_params *dma_params =
98 &davinci_vcif_dev->dma_params[substream->stream];
99 u32 w;
100
101 /* Restart the codec before setup */
102 davinci_vcif_stop(substream);
103 davinci_vcif_start(substream);
104
105 /* General line settings */
106 writel(DAVINCI_VC_CTRL_MASK, davinci_vc->base + DAVINCI_VC_CTRL);
107
108 writel(DAVINCI_VC_INT_MASK, davinci_vc->base + DAVINCI_VC_INTCLR);
109
110 writel(DAVINCI_VC_INT_MASK, davinci_vc->base + DAVINCI_VC_INTEN);
111
112 w = readl(davinci_vc->base + DAVINCI_VC_CTRL);
113
114 /* Determine xfer data type */
115 switch (params_format(params)) {
116 case SNDRV_PCM_FORMAT_U8:
117 dma_params->data_type = 0;
118
119 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
120 DAVINCI_VC_CTRL_RD_UNSIGNED |
121 DAVINCI_VC_CTRL_WD_BITS_8 |
122 DAVINCI_VC_CTRL_WD_UNSIGNED, 1);
123 break;
124 case SNDRV_PCM_FORMAT_S8:
125 dma_params->data_type = 1;
126
127 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
128 DAVINCI_VC_CTRL_WD_BITS_8, 1);
129
130 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_UNSIGNED |
131 DAVINCI_VC_CTRL_WD_UNSIGNED, 0);
132 break;
133 case SNDRV_PCM_FORMAT_S16_LE:
134 dma_params->data_type = 2;
135
136 MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 |
137 DAVINCI_VC_CTRL_RD_UNSIGNED |
138 DAVINCI_VC_CTRL_WD_BITS_8 |
139 DAVINCI_VC_CTRL_WD_UNSIGNED, 0);
140 break;
141 default:
142 printk(KERN_WARNING "davinci-vcif: unsupported PCM format");
143 return -EINVAL;
144 }
145
146 dma_params->acnt = dma_params->data_type;
147
148 writel(w, davinci_vc->base + DAVINCI_VC_CTRL);
149
150 return 0;
151}
152
153static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd,
154 struct snd_soc_dai *dai)
155{
156 int ret = 0;
157
158 switch (cmd) {
159 case SNDRV_PCM_TRIGGER_START:
160 case SNDRV_PCM_TRIGGER_RESUME:
161 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
162 davinci_vcif_start(substream);
163 case SNDRV_PCM_TRIGGER_STOP:
164 case SNDRV_PCM_TRIGGER_SUSPEND:
165 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
166 davinci_vcif_stop(substream);
167 break;
168 default:
169 ret = -EINVAL;
170 }
171
172 return ret;
173}
174
175#define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000
176
177static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
178 .trigger = davinci_vcif_trigger,
179 .hw_params = davinci_vcif_hw_params,
180};
181
182struct snd_soc_dai davinci_vcif_dai = {
183 .name = "davinci-vcif",
184 .playback = {
185 .channels_min = 1,
186 .channels_max = 2,
187 .rates = DAVINCI_VCIF_RATES,
188 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
189 .capture = {
190 .channels_min = 1,
191 .channels_max = 2,
192 .rates = DAVINCI_VCIF_RATES,
193 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
194 .ops = &davinci_vcif_dai_ops,
195
196};
197EXPORT_SYMBOL_GPL(davinci_vcif_dai);
198
199static int davinci_vcif_probe(struct platform_device *pdev)
200{
201 struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
202 struct davinci_vcif_dev *davinci_vcif_dev;
203 int ret;
204
205 davinci_vcif_dev = kzalloc(sizeof(struct davinci_vcif_dev), GFP_KERNEL);
206 if (!davinci_vc) {
207 dev_dbg(&pdev->dev,
208 "could not allocate memory for private data\n");
209 return -ENOMEM;
210 }
211
212 /* DMA tx params */
213 davinci_vcif_dev->davinci_vc = davinci_vc;
214 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel =
215 davinci_vc->davinci_vcif.dma_tx_channel;
216 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr =
217 davinci_vc->davinci_vcif.dma_tx_addr;
218
219 /* DMA rx params */
220 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel =
221 davinci_vc->davinci_vcif.dma_rx_channel;
222 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
223 davinci_vc->davinci_vcif.dma_rx_addr;
224
225 davinci_vcif_dai.dev = &pdev->dev;
226 davinci_vcif_dai.capture.dma_data = davinci_vcif_dev->dma_params;
227 davinci_vcif_dai.playback.dma_data = davinci_vcif_dev->dma_params;
228 davinci_vcif_dai.private_data = davinci_vcif_dev;
229
230 ret = snd_soc_register_dai(&davinci_vcif_dai);
231 if (ret != 0) {
232 dev_err(&pdev->dev, "could not register dai\n");
233 goto fail;
234 }
235
236 return 0;
237
238fail:
239 kfree(davinci_vcif_dev);
240
241 return ret;
242}
243
244static int davinci_vcif_remove(struct platform_device *pdev)
245{
246 snd_soc_unregister_dai(&davinci_vcif_dai);
247
248 return 0;
249}
250
251static struct platform_driver davinci_vcif_driver = {
252 .probe = davinci_vcif_probe,
253 .remove = davinci_vcif_remove,
254 .driver = {
255 .name = "davinci_vcif",
256 .owner = THIS_MODULE,
257 },
258};
259
260static int __init davinci_vcif_init(void)
261{
262 return platform_driver_probe(&davinci_vcif_driver, davinci_vcif_probe);
263}
264module_init(davinci_vcif_init);
265
266static void __exit davinci_vcif_exit(void)
267{
268 platform_driver_unregister(&davinci_vcif_driver);
269}
270module_exit(davinci_vcif_exit);
271
272MODULE_AUTHOR("Miguel Aguilar");
273MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC Voice Codec Interface");
274MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-vcif.h b/sound/soc/davinci/davinci-vcif.h
new file mode 100644
index 000000000000..571c9948724f
--- /dev/null
+++ b/sound/soc/davinci/davinci-vcif.h
@@ -0,0 +1,28 @@
1/*
2 * ALSA SoC Voice Codec Interface for TI DAVINCI processor
3 *
4 * Copyright (C) 2010 Texas Instruments.
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifndef _DAVINCI_VCIF_H
24#define _DAVINCI_VCIF_H
25
26extern struct snd_soc_dai davinci_vcif_dai;
27
28#endif
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index 7174b4c710de..eba9b9d257a1 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -11,3 +11,11 @@ config SND_IMX_SOC
11config SND_MXC_SOC_SSI 11config SND_MXC_SOC_SSI
12 tristate 12 tristate
13 13
14config SND_MXC_SOC_WM1133_EV1
15 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
16 depends on SND_IMX_SOC && EXPERIMENTAL
17 select SND_SOC_WM8350
18 select SND_MXC_SOC_SSI
19 help
20 Enable support for audio on the i.MX31ADS with the WM1133-EV1
21 PMIC board with WM8835x fitted.
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index 9f8bb92ddfcc..2d203635ac11 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -9,4 +9,7 @@ obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
9 9
10# i.MX Machine Support 10# i.MX Machine Support
11snd-soc-phycore-ac97-objs := phycore-ac97.o 11snd-soc-phycore-ac97-objs := phycore-ac97.o
12snd-soc-wm1133-ev1-objs := wm1133-ev1.o
13
12obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o 14obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
15obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c
new file mode 100644
index 000000000000..a6e7d9497639
--- /dev/null
+++ b/sound/soc/imx/wm1133-ev1.c
@@ -0,0 +1,308 @@
1/*
2 * wm1133-ev1.c - Audio for WM1133-EV1 on i.MX31ADS
3 *
4 * Copyright (c) 2010 Wolfson Microelectronics plc
5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
6 *
7 * Based on an earlier driver for the same hardware by Liam Girdwood.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#include <linux/platform_device.h>
16#include <linux/clk.h>
17#include <sound/core.h>
18#include <sound/jack.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23
24#include <mach/audmux.h>
25
26#include "imx-ssi.h"
27#include "../codecs/wm8350.h"
28
29/* There is a silicon mic on the board optionally connected via a solder pad
30 * SP1. Define this to enable it.
31 */
32#undef USE_SIMIC
33
34struct _wm8350_audio {
35 unsigned int channels;
36 snd_pcm_format_t format;
37 unsigned int rate;
38 unsigned int sysclk;
39 unsigned int bclkdiv;
40 unsigned int clkdiv;
41 unsigned int lr_rate;
42};
43
44/* in order of power consumption per rate (lowest first) */
45static const struct _wm8350_audio wm8350_audio[] = {
46 /* 16bit mono modes */
47 {1, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000 >> 1,
48 WM8350_BCLK_DIV_48, WM8350_DACDIV_3, 16,},
49
50 /* 16 bit stereo modes */
51 {2, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000,
52 WM8350_BCLK_DIV_48, WM8350_DACDIV_6, 32,},
53 {2, SNDRV_PCM_FORMAT_S16_LE, 16000, 12288000,
54 WM8350_BCLK_DIV_24, WM8350_DACDIV_3, 32,},
55 {2, SNDRV_PCM_FORMAT_S16_LE, 32000, 12288000,
56 WM8350_BCLK_DIV_12, WM8350_DACDIV_1_5, 32,},
57 {2, SNDRV_PCM_FORMAT_S16_LE, 48000, 12288000,
58 WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,},
59 {2, SNDRV_PCM_FORMAT_S16_LE, 96000, 24576000,
60 WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,},
61 {2, SNDRV_PCM_FORMAT_S16_LE, 11025, 11289600,
62 WM8350_BCLK_DIV_32, WM8350_DACDIV_4, 32,},
63 {2, SNDRV_PCM_FORMAT_S16_LE, 22050, 11289600,
64 WM8350_BCLK_DIV_16, WM8350_DACDIV_2, 32,},
65 {2, SNDRV_PCM_FORMAT_S16_LE, 44100, 11289600,
66 WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,},
67 {2, SNDRV_PCM_FORMAT_S16_LE, 88200, 22579200,
68 WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,},
69
70 /* 24bit stereo modes */
71 {2, SNDRV_PCM_FORMAT_S24_LE, 48000, 12288000,
72 WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,},
73 {2, SNDRV_PCM_FORMAT_S24_LE, 96000, 24576000,
74 WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,},
75 {2, SNDRV_PCM_FORMAT_S24_LE, 44100, 11289600,
76 WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,},
77 {2, SNDRV_PCM_FORMAT_S24_LE, 88200, 22579200,
78 WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,},
79};
80
81static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream,
82 struct snd_pcm_hw_params *params)
83{
84 struct snd_soc_pcm_runtime *rtd = substream->private_data;
85 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
86 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
87 int i, found = 0;
88 snd_pcm_format_t format = params_format(params);
89 unsigned int rate = params_rate(params);
90 unsigned int channels = params_channels(params);
91 u32 dai_format;
92
93 /* find the correct audio parameters */
94 for (i = 0; i < ARRAY_SIZE(wm8350_audio); i++) {
95 if (rate == wm8350_audio[i].rate &&
96 format == wm8350_audio[i].format &&
97 channels == wm8350_audio[i].channels) {
98 found = 1;
99 break;
100 }
101 }
102 if (!found)
103 return -EINVAL;
104
105 /* codec FLL input is 14.75 MHz from MCLK */
106 snd_soc_dai_set_pll(codec_dai, 0, 0, 14750000, wm8350_audio[i].sysclk);
107
108 dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
109 SND_SOC_DAIFMT_CBM_CFM;
110
111 /* set codec DAI configuration */
112 snd_soc_dai_set_fmt(codec_dai, dai_format);
113
114 /* set cpu DAI configuration */
115 snd_soc_dai_set_fmt(cpu_dai, dai_format);
116
117 /* TODO: The SSI driver should figure this out for us */
118 switch (channels) {
119 case 2:
120 snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0);
121 break;
122 case 1:
123 snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffe, 0xffffffe, 1, 0);
124 break;
125 default:
126 return -EINVAL;
127 }
128
129 /* set MCLK as the codec system clock for DAC and ADC */
130 snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_MCLK,
131 wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN);
132
133 /* set codec BCLK division for sample rate */
134 snd_soc_dai_set_clkdiv(codec_dai, WM8350_BCLK_CLKDIV,
135 wm8350_audio[i].bclkdiv);
136
137 /* DAI is synchronous and clocked with DAC LRCLK & ADC LRC */
138 snd_soc_dai_set_clkdiv(codec_dai,
139 WM8350_DACLR_CLKDIV, wm8350_audio[i].lr_rate);
140 snd_soc_dai_set_clkdiv(codec_dai,
141 WM8350_ADCLR_CLKDIV, wm8350_audio[i].lr_rate);
142
143 /* now configure DAC and ADC clocks */
144 snd_soc_dai_set_clkdiv(codec_dai,
145 WM8350_DAC_CLKDIV, wm8350_audio[i].clkdiv);
146
147 snd_soc_dai_set_clkdiv(codec_dai,
148 WM8350_ADC_CLKDIV, wm8350_audio[i].clkdiv);
149
150 return 0;
151}
152
153static struct snd_soc_ops wm1133_ev1_ops = {
154 .hw_params = wm1133_ev1_hw_params,
155};
156
157static const struct snd_soc_dapm_widget wm1133_ev1_widgets[] = {
158#ifdef USE_SIMIC
159 SND_SOC_DAPM_MIC("SiMIC", NULL),
160#endif
161 SND_SOC_DAPM_MIC("Mic1 Jack", NULL),
162 SND_SOC_DAPM_MIC("Mic2 Jack", NULL),
163 SND_SOC_DAPM_LINE("Line In Jack", NULL),
164 SND_SOC_DAPM_LINE("Line Out Jack", NULL),
165 SND_SOC_DAPM_HP("Headphone Jack", NULL),
166};
167
168/* imx32ads soc_card audio map */
169static const struct snd_soc_dapm_route wm1133_ev1_map[] = {
170
171#ifdef USE_SIMIC
172 /* SiMIC --> IN1LN (with automatic bias) via SP1 */
173 { "IN1LN", NULL, "Mic Bias" },
174 { "Mic Bias", NULL, "SiMIC" },
175#endif
176
177 /* Mic 1 Jack --> IN1LN and IN1LP (with automatic bias) */
178 { "IN1LN", NULL, "Mic Bias" },
179 { "IN1LP", NULL, "Mic1 Jack" },
180 { "Mic Bias", NULL, "Mic1 Jack" },
181
182 /* Mic 2 Jack --> IN1RN and IN1RP (with automatic bias) */
183 { "IN1RN", NULL, "Mic Bias" },
184 { "IN1RP", NULL, "Mic2 Jack" },
185 { "Mic Bias", NULL, "Mic2 Jack" },
186
187 /* Line in Jack --> AUX (L+R) */
188 { "IN3R", NULL, "Line In Jack" },
189 { "IN3L", NULL, "Line In Jack" },
190
191 /* Out1 --> Headphone Jack */
192 { "Headphone Jack", NULL, "OUT1R" },
193 { "Headphone Jack", NULL, "OUT1L" },
194
195 /* Out1 --> Line Out Jack */
196 { "Line Out Jack", NULL, "OUT2R" },
197 { "Line Out Jack", NULL, "OUT2L" },
198};
199
200static struct snd_soc_jack hp_jack;
201
202static struct snd_soc_jack_pin hp_jack_pins[] = {
203 { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE },
204};
205
206static struct snd_soc_jack mic_jack;
207
208static struct snd_soc_jack_pin mic_jack_pins[] = {
209 { .pin = "Mic1 Jack", .mask = SND_JACK_MICROPHONE },
210 { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE },
211};
212
213static int wm1133_ev1_init(struct snd_soc_codec *codec)
214{
215 struct snd_soc_card *card = codec->socdev->card;
216
217 snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets,
218 ARRAY_SIZE(wm1133_ev1_widgets));
219
220 snd_soc_dapm_add_routes(codec, wm1133_ev1_map,
221 ARRAY_SIZE(wm1133_ev1_map));
222
223 /* Headphone jack detection */
224 snd_soc_jack_new(card, "Headphone", SND_JACK_HEADPHONE, &hp_jack);
225 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
226 hp_jack_pins);
227 wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE);
228
229 /* Microphone jack detection */
230 snd_soc_jack_new(card, "Microphone",
231 SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack);
232 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
233 mic_jack_pins);
234 wm8350_mic_jack_detect(codec, &mic_jack, SND_JACK_MICROPHONE,
235 SND_JACK_BTN_0);
236
237 snd_soc_dapm_force_enable_pin(codec, "Mic Bias");
238
239 return 0;
240}
241
242
243static struct snd_soc_dai_link wm1133_ev1_dai = {
244 .name = "WM1133-EV1",
245 .stream_name = "Audio",
246 .cpu_dai = &imx_ssi_pcm_dai[0],
247 .codec_dai = &wm8350_dai,
248 .init = wm1133_ev1_init,
249 .ops = &wm1133_ev1_ops,
250 .symmetric_rates = 1,
251};
252
253static struct snd_soc_card wm1133_ev1 = {
254 .name = "WM1133-EV1",
255 .platform = &imx_soc_platform,
256 .dai_link = &wm1133_ev1_dai,
257 .num_links = 1,
258};
259
260static struct snd_soc_device wm1133_ev1_snd_devdata = {
261 .card = &wm1133_ev1,
262 .codec_dev = &soc_codec_dev_wm8350,
263};
264
265static struct platform_device *wm1133_ev1_snd_device;
266
267static int __init wm1133_ev1_audio_init(void)
268{
269 int ret;
270 unsigned int ptcr, pdcr;
271
272 /* SSI0 mastered by port 5 */
273 ptcr = MXC_AUDMUX_V2_PTCR_SYN |
274 MXC_AUDMUX_V2_PTCR_TFSDIR |
275 MXC_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
276 MXC_AUDMUX_V2_PTCR_TCLKDIR |
277 MXC_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
278 pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
279 mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
280
281 ptcr = MXC_AUDMUX_V2_PTCR_SYN;
282 pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
283 mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
284
285 wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1);
286 if (!wm1133_ev1_snd_device)
287 return -ENOMEM;
288
289 platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1_snd_devdata);
290 wm1133_ev1_snd_devdata.dev = &wm1133_ev1_snd_device->dev;
291 ret = platform_device_add(wm1133_ev1_snd_device);
292
293 if (ret)
294 platform_device_put(wm1133_ev1_snd_device);
295
296 return ret;
297}
298module_init(wm1133_ev1_audio_init);
299
300static void __exit wm1133_ev1_audio_exit(void)
301{
302 platform_device_unregister(wm1133_ev1_snd_device);
303}
304module_exit(wm1133_ev1_audio_exit);
305
306MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
307MODULE_DESCRIPTION("Audio for WM1133-EV1 on i.MX31ADS");
308MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
index ad8df6cfae88..479d3b6306d7 100644
--- a/sound/soc/omap/mcpdm.c
+++ b/sound/soc/omap/mcpdm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * mcpdm.c -- McPDM interface driver 2 * mcpdm.c -- McPDM interface driver
3 * 3 *
4 * Author: Jorge Eduardo Candelaria <x0107209@ti.com> 4 * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
5 * Copyright (C) 2009 - Texas Instruments, Inc. 5 * Copyright (C) 2009 - Texas Instruments, Inc.
@@ -38,46 +38,46 @@ static struct omap_mcpdm *mcpdm;
38 38
39static inline void omap_mcpdm_write(u16 reg, u32 val) 39static inline void omap_mcpdm_write(u16 reg, u32 val)
40{ 40{
41 __raw_writel(val, mcpdm->io_base + reg); 41 __raw_writel(val, mcpdm->io_base + reg);
42} 42}
43 43
44static inline int omap_mcpdm_read(u16 reg) 44static inline int omap_mcpdm_read(u16 reg)
45{ 45{
46 return __raw_readl(mcpdm->io_base + reg); 46 return __raw_readl(mcpdm->io_base + reg);
47} 47}
48 48
49static void omap_mcpdm_reg_dump(void) 49static void omap_mcpdm_reg_dump(void)
50{ 50{
51 dev_dbg(mcpdm->dev, "***********************\n"); 51 dev_dbg(mcpdm->dev, "***********************\n");
52 dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n", 52 dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n",
53 omap_mcpdm_read(MCPDM_IRQSTATUS_RAW)); 53 omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
54 dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n", 54 dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
55 omap_mcpdm_read(MCPDM_IRQSTATUS)); 55 omap_mcpdm_read(MCPDM_IRQSTATUS));
56 dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n", 56 dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n",
57 omap_mcpdm_read(MCPDM_IRQENABLE_SET)); 57 omap_mcpdm_read(MCPDM_IRQENABLE_SET));
58 dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n", 58 dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n",
59 omap_mcpdm_read(MCPDM_IRQENABLE_CLR)); 59 omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
60 dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n", 60 dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
61 omap_mcpdm_read(MCPDM_IRQWAKE_EN)); 61 omap_mcpdm_read(MCPDM_IRQWAKE_EN));
62 dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n", 62 dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
63 omap_mcpdm_read(MCPDM_DMAENABLE_SET)); 63 omap_mcpdm_read(MCPDM_DMAENABLE_SET));
64 dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n", 64 dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n",
65 omap_mcpdm_read(MCPDM_DMAENABLE_CLR)); 65 omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
66 dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n", 66 dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
67 omap_mcpdm_read(MCPDM_DMAWAKEEN)); 67 omap_mcpdm_read(MCPDM_DMAWAKEEN));
68 dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n", 68 dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n",
69 omap_mcpdm_read(MCPDM_CTRL)); 69 omap_mcpdm_read(MCPDM_CTRL));
70 dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n", 70 dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n",
71 omap_mcpdm_read(MCPDM_DN_DATA)); 71 omap_mcpdm_read(MCPDM_DN_DATA));
72 dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n", 72 dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
73 omap_mcpdm_read(MCPDM_UP_DATA)); 73 omap_mcpdm_read(MCPDM_UP_DATA));
74 dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n", 74 dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
75 omap_mcpdm_read(MCPDM_FIFO_CTRL_DN)); 75 omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
76 dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n", 76 dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n",
77 omap_mcpdm_read(MCPDM_FIFO_CTRL_UP)); 77 omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
78 dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n", 78 dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
79 omap_mcpdm_read(MCPDM_DN_OFFSET)); 79 omap_mcpdm_read(MCPDM_DN_OFFSET));
80 dev_dbg(mcpdm->dev, "***********************\n"); 80 dev_dbg(mcpdm->dev, "***********************\n");
81} 81}
82 82
83/* 83/*
@@ -86,26 +86,26 @@ static void omap_mcpdm_reg_dump(void)
86 */ 86 */
87static void omap_mcpdm_reset_capture(int reset) 87static void omap_mcpdm_reset_capture(int reset)
88{ 88{
89 int ctrl = omap_mcpdm_read(MCPDM_CTRL); 89 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
90 90
91 if (reset) 91 if (reset)
92 ctrl |= SW_UP_RST; 92 ctrl |= SW_UP_RST;
93 else 93 else
94 ctrl &= ~SW_UP_RST; 94 ctrl &= ~SW_UP_RST;
95 95
96 omap_mcpdm_write(MCPDM_CTRL, ctrl); 96 omap_mcpdm_write(MCPDM_CTRL, ctrl);
97} 97}
98 98
99static void omap_mcpdm_reset_playback(int reset) 99static void omap_mcpdm_reset_playback(int reset)
100{ 100{
101 int ctrl = omap_mcpdm_read(MCPDM_CTRL); 101 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
102 102
103 if (reset) 103 if (reset)
104 ctrl |= SW_DN_RST; 104 ctrl |= SW_DN_RST;
105 else 105 else
106 ctrl &= ~SW_DN_RST; 106 ctrl &= ~SW_DN_RST;
107 107
108 omap_mcpdm_write(MCPDM_CTRL, ctrl); 108 omap_mcpdm_write(MCPDM_CTRL, ctrl);
109} 109}
110 110
111/* 111/*
@@ -114,14 +114,14 @@ static void omap_mcpdm_reset_playback(int reset)
114 */ 114 */
115void omap_mcpdm_start(int stream) 115void omap_mcpdm_start(int stream)
116{ 116{
117 int ctrl = omap_mcpdm_read(MCPDM_CTRL); 117 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
118 118
119 if (stream) 119 if (stream)
120 ctrl |= mcpdm->up_channels; 120 ctrl |= mcpdm->up_channels;
121 else 121 else
122 ctrl |= mcpdm->dn_channels; 122 ctrl |= mcpdm->dn_channels;
123 123
124 omap_mcpdm_write(MCPDM_CTRL, ctrl); 124 omap_mcpdm_write(MCPDM_CTRL, ctrl);
125} 125}
126 126
127/* 127/*
@@ -130,14 +130,14 @@ void omap_mcpdm_start(int stream)
130 */ 130 */
131void omap_mcpdm_stop(int stream) 131void omap_mcpdm_stop(int stream)
132{ 132{
133 int ctrl = omap_mcpdm_read(MCPDM_CTRL); 133 int ctrl = omap_mcpdm_read(MCPDM_CTRL);
134 134
135 if (stream) 135 if (stream)
136 ctrl &= ~mcpdm->up_channels; 136 ctrl &= ~mcpdm->up_channels;
137 else 137 else
138 ctrl &= ~mcpdm->dn_channels; 138 ctrl &= ~mcpdm->dn_channels;
139 139
140 omap_mcpdm_write(MCPDM_CTRL, ctrl); 140 omap_mcpdm_write(MCPDM_CTRL, ctrl);
141} 141}
142 142
143/* 143/*
@@ -146,38 +146,38 @@ void omap_mcpdm_stop(int stream)
146 */ 146 */
147int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink) 147int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
148{ 148{
149 int irq_mask = 0; 149 int irq_mask = 0;
150 int ctrl; 150 int ctrl;
151 151
152 if (!uplink) 152 if (!uplink)
153 return -EINVAL; 153 return -EINVAL;
154 154
155 mcpdm->uplink = uplink; 155 mcpdm->uplink = uplink;
156 156
157 /* Enable irq request generation */ 157 /* Enable irq request generation */
158 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK; 158 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
159 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask); 159 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
160 160
161 /* Configure uplink threshold */ 161 /* Configure uplink threshold */
162 if (uplink->threshold > UP_THRES_MAX) 162 if (uplink->threshold > UP_THRES_MAX)
163 uplink->threshold = UP_THRES_MAX; 163 uplink->threshold = UP_THRES_MAX;
164 164
165 omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold); 165 omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
166 166
167 /* Configure DMA controller */ 167 /* Configure DMA controller */
168 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE); 168 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
169 169
170 /* Set pdm out format */ 170 /* Set pdm out format */
171 ctrl = omap_mcpdm_read(MCPDM_CTRL); 171 ctrl = omap_mcpdm_read(MCPDM_CTRL);
172 ctrl &= ~PDMOUTFORMAT; 172 ctrl &= ~PDMOUTFORMAT;
173 ctrl |= uplink->format & PDMOUTFORMAT; 173 ctrl |= uplink->format & PDMOUTFORMAT;
174 174
175 /* Uplink channels */ 175 /* Uplink channels */
176 mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK); 176 mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
177 177
178 omap_mcpdm_write(MCPDM_CTRL, ctrl); 178 omap_mcpdm_write(MCPDM_CTRL, ctrl);
179 179
180 return 0; 180 return 0;
181} 181}
182 182
183/* 183/*
@@ -186,38 +186,38 @@ int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
186 */ 186 */
187int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink) 187int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
188{ 188{
189 int irq_mask = 0; 189 int irq_mask = 0;
190 int ctrl; 190 int ctrl;
191 191
192 if (!downlink) 192 if (!downlink)
193 return -EINVAL; 193 return -EINVAL;
194 194
195 mcpdm->downlink = downlink; 195 mcpdm->downlink = downlink;
196 196
197 /* Enable irq request generation */ 197 /* Enable irq request generation */
198 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK; 198 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
199 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask); 199 omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
200 200
201 /* Configure uplink threshold */ 201 /* Configure uplink threshold */
202 if (downlink->threshold > DN_THRES_MAX) 202 if (downlink->threshold > DN_THRES_MAX)
203 downlink->threshold = DN_THRES_MAX; 203 downlink->threshold = DN_THRES_MAX;
204 204
205 omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold); 205 omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
206 206
207 /* Enable DMA request generation */ 207 /* Enable DMA request generation */
208 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE); 208 omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
209 209
210 /* Set pdm out format */ 210 /* Set pdm out format */
211 ctrl = omap_mcpdm_read(MCPDM_CTRL); 211 ctrl = omap_mcpdm_read(MCPDM_CTRL);
212 ctrl &= ~PDMOUTFORMAT; 212 ctrl &= ~PDMOUTFORMAT;
213 ctrl |= downlink->format & PDMOUTFORMAT; 213 ctrl |= downlink->format & PDMOUTFORMAT;
214 214
215 /* Downlink channels */ 215 /* Downlink channels */
216 mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK); 216 mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
217 217
218 omap_mcpdm_write(MCPDM_CTRL, ctrl); 218 omap_mcpdm_write(MCPDM_CTRL, ctrl);
219 219
220 return 0; 220 return 0;
221} 221}
222 222
223/* 223/*
@@ -226,24 +226,24 @@ int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
226 */ 226 */
227int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink) 227int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
228{ 228{
229 int irq_mask = 0; 229 int irq_mask = 0;
230 230
231 if (!uplink) 231 if (!uplink)
232 return -EINVAL; 232 return -EINVAL;
233 233
234 /* Disable irq request generation */ 234 /* Disable irq request generation */
235 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK; 235 irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
236 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask); 236 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
237 237
238 /* Disable DMA request generation */ 238 /* Disable DMA request generation */
239 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE); 239 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
240 240
241 /* Clear Downlink channels */ 241 /* Clear Downlink channels */
242 mcpdm->up_channels = 0; 242 mcpdm->up_channels = 0;
243 243
244 mcpdm->uplink = NULL; 244 mcpdm->uplink = NULL;
245 245
246 return 0; 246 return 0;
247} 247}
248 248
249/* 249/*
@@ -252,124 +252,124 @@ int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
252 */ 252 */
253int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink) 253int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink)
254{ 254{
255 int irq_mask = 0; 255 int irq_mask = 0;
256 256
257 if (!downlink) 257 if (!downlink)
258 return -EINVAL; 258 return -EINVAL;
259 259
260 /* Disable irq request generation */ 260 /* Disable irq request generation */
261 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK; 261 irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
262 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask); 262 omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
263 263
264 /* Disable DMA request generation */ 264 /* Disable DMA request generation */
265 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE); 265 omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
266 266
267 /* clear Downlink channels */ 267 /* clear Downlink channels */
268 mcpdm->dn_channels = 0; 268 mcpdm->dn_channels = 0;
269 269
270 mcpdm->downlink = NULL; 270 mcpdm->downlink = NULL;
271 271
272 return 0; 272 return 0;
273} 273}
274 274
275static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id) 275static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
276{ 276{
277 struct omap_mcpdm *mcpdm_irq = dev_id; 277 struct omap_mcpdm *mcpdm_irq = dev_id;
278 int irq_status; 278 int irq_status;
279 279
280 irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS); 280 irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
281 281
282 /* Acknowledge irq event */ 282 /* Acknowledge irq event */
283 omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status); 283 omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
284 284
285 if (irq & MCPDM_DN_IRQ_FULL) { 285 if (irq & MCPDM_DN_IRQ_FULL) {
286 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status); 286 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
287 omap_mcpdm_reset_playback(1); 287 omap_mcpdm_reset_playback(1);
288 omap_mcpdm_playback_open(mcpdm_irq->downlink); 288 omap_mcpdm_playback_open(mcpdm_irq->downlink);
289 omap_mcpdm_reset_playback(0); 289 omap_mcpdm_reset_playback(0);
290 } 290 }
291 291
292 if (irq & MCPDM_DN_IRQ_EMPTY) { 292 if (irq & MCPDM_DN_IRQ_EMPTY) {
293 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status); 293 dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
294 omap_mcpdm_reset_playback(1); 294 omap_mcpdm_reset_playback(1);
295 omap_mcpdm_playback_open(mcpdm_irq->downlink); 295 omap_mcpdm_playback_open(mcpdm_irq->downlink);
296 omap_mcpdm_reset_playback(0); 296 omap_mcpdm_reset_playback(0);
297 } 297 }
298 298
299 if (irq & MCPDM_DN_IRQ) { 299 if (irq & MCPDM_DN_IRQ) {
300 dev_dbg(mcpdm_irq->dev, "DN write request\n"); 300 dev_dbg(mcpdm_irq->dev, "DN write request\n");
301 } 301 }
302 302
303 if (irq & MCPDM_UP_IRQ_FULL) { 303 if (irq & MCPDM_UP_IRQ_FULL) {
304 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status); 304 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
305 omap_mcpdm_reset_capture(1); 305 omap_mcpdm_reset_capture(1);
306 omap_mcpdm_capture_open(mcpdm_irq->uplink); 306 omap_mcpdm_capture_open(mcpdm_irq->uplink);
307 omap_mcpdm_reset_capture(0); 307 omap_mcpdm_reset_capture(0);
308 } 308 }
309 309
310 if (irq & MCPDM_UP_IRQ_EMPTY) { 310 if (irq & MCPDM_UP_IRQ_EMPTY) {
311 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status); 311 dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
312 omap_mcpdm_reset_capture(1); 312 omap_mcpdm_reset_capture(1);
313 omap_mcpdm_capture_open(mcpdm_irq->uplink); 313 omap_mcpdm_capture_open(mcpdm_irq->uplink);
314 omap_mcpdm_reset_capture(0); 314 omap_mcpdm_reset_capture(0);
315 } 315 }
316 316
317 if (irq & MCPDM_UP_IRQ) { 317 if (irq & MCPDM_UP_IRQ) {
318 dev_dbg(mcpdm_irq->dev, "UP write request\n"); 318 dev_dbg(mcpdm_irq->dev, "UP write request\n");
319 } 319 }
320 320
321 return IRQ_HANDLED; 321 return IRQ_HANDLED;
322} 322}
323 323
324int omap_mcpdm_request(void) 324int omap_mcpdm_request(void)
325{ 325{
326 int ret; 326 int ret;
327 327
328 clk_enable(mcpdm->clk); 328 clk_enable(mcpdm->clk);
329 329
330 spin_lock(&mcpdm->lock); 330 spin_lock(&mcpdm->lock);
331 331
332 if (!mcpdm->free) { 332 if (!mcpdm->free) {
333 dev_err(mcpdm->dev, "McPDM interface is in use\n"); 333 dev_err(mcpdm->dev, "McPDM interface is in use\n");
334 spin_unlock(&mcpdm->lock); 334 spin_unlock(&mcpdm->lock);
335 ret = -EBUSY; 335 ret = -EBUSY;
336 goto err; 336 goto err;
337 } 337 }
338 mcpdm->free = 0; 338 mcpdm->free = 0;
339 339
340 spin_unlock(&mcpdm->lock); 340 spin_unlock(&mcpdm->lock);
341 341
342 /* Disable lines while request is ongoing */ 342 /* Disable lines while request is ongoing */
343 omap_mcpdm_write(MCPDM_CTRL, 0x00); 343 omap_mcpdm_write(MCPDM_CTRL, 0x00);
344 344
345 ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, 345 ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
346 0, "McPDM", (void *)mcpdm); 346 0, "McPDM", (void *)mcpdm);
347 if (ret) { 347 if (ret) {
348 dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n"); 348 dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
349 goto err; 349 goto err;
350 } 350 }
351 351
352 return 0; 352 return 0;
353 353
354err: 354err:
355 clk_disable(mcpdm->clk); 355 clk_disable(mcpdm->clk);
356 return ret; 356 return ret;
357} 357}
358 358
359void omap_mcpdm_free(void) 359void omap_mcpdm_free(void)
360{ 360{
361 spin_lock(&mcpdm->lock); 361 spin_lock(&mcpdm->lock);
362 if (mcpdm->free) { 362 if (mcpdm->free) {
363 dev_err(mcpdm->dev, "McPDM interface is already free\n"); 363 dev_err(mcpdm->dev, "McPDM interface is already free\n");
364 spin_unlock(&mcpdm->lock); 364 spin_unlock(&mcpdm->lock);
365 return; 365 return;
366 } 366 }
367 mcpdm->free = 1; 367 mcpdm->free = 1;
368 spin_unlock(&mcpdm->lock); 368 spin_unlock(&mcpdm->lock);
369 369
370 clk_disable(mcpdm->clk); 370 clk_disable(mcpdm->clk);
371 371
372 free_irq(mcpdm->irq, (void *)mcpdm); 372 free_irq(mcpdm->irq, (void *)mcpdm);
373} 373}
374 374
375/* Enable/disable DC offset cancelation for the analog 375/* Enable/disable DC offset cancelation for the analog
@@ -377,108 +377,108 @@ void omap_mcpdm_free(void)
377 */ 377 */
378int omap_mcpdm_set_offset(int offset1, int offset2) 378int omap_mcpdm_set_offset(int offset1, int offset2)
379{ 379{
380 int offset; 380 int offset;
381 381
382 if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX)) 382 if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
383 return -EINVAL; 383 return -EINVAL;
384 384
385 offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2); 385 offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
386 386
387 /* offset cancellation for channel 1 */ 387 /* offset cancellation for channel 1 */
388 if (offset1) 388 if (offset1)
389 offset |= DN_OFST_RX1_EN; 389 offset |= DN_OFST_RX1_EN;
390 else 390 else
391 offset &= ~DN_OFST_RX1_EN; 391 offset &= ~DN_OFST_RX1_EN;
392 392
393 /* offset cancellation for channel 2 */ 393 /* offset cancellation for channel 2 */
394 if (offset2) 394 if (offset2)
395 offset |= DN_OFST_RX2_EN; 395 offset |= DN_OFST_RX2_EN;
396 else 396 else
397 offset &= ~DN_OFST_RX2_EN; 397 offset &= ~DN_OFST_RX2_EN;
398 398
399 omap_mcpdm_write(MCPDM_DN_OFFSET, offset); 399 omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
400 400
401 return 0; 401 return 0;
402} 402}
403 403
404static int __devinit omap_mcpdm_probe(struct platform_device *pdev) 404static int __devinit omap_mcpdm_probe(struct platform_device *pdev)
405{ 405{
406 struct resource *res; 406 struct resource *res;
407 int ret = 0; 407 int ret = 0;
408 408
409 mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); 409 mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
410 if (!mcpdm) { 410 if (!mcpdm) {
411 ret = -ENOMEM; 411 ret = -ENOMEM;
412 goto exit; 412 goto exit;
413 } 413 }
414 414
415 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 415 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
416 if (res == NULL) { 416 if (res == NULL) {
417 dev_err(&pdev->dev, "no resource\n"); 417 dev_err(&pdev->dev, "no resource\n");
418 goto err_resource; 418 goto err_resource;
419 } 419 }
420 420
421 spin_lock_init(&mcpdm->lock); 421 spin_lock_init(&mcpdm->lock);
422 mcpdm->free = 1; 422 mcpdm->free = 1;
423 mcpdm->io_base = ioremap(res->start, resource_size(res)); 423 mcpdm->io_base = ioremap(res->start, resource_size(res));
424 if (!mcpdm->io_base) { 424 if (!mcpdm->io_base) {
425 ret = -ENOMEM; 425 ret = -ENOMEM;
426 goto err_resource; 426 goto err_resource;
427 } 427 }
428 428
429 mcpdm->irq = platform_get_irq(pdev, 0); 429 mcpdm->irq = platform_get_irq(pdev, 0);
430 430
431 mcpdm->clk = clk_get(&pdev->dev, "pdm_ck"); 431 mcpdm->clk = clk_get(&pdev->dev, "pdm_ck");
432 if (IS_ERR(mcpdm->clk)) { 432 if (IS_ERR(mcpdm->clk)) {
433 ret = PTR_ERR(mcpdm->clk); 433 ret = PTR_ERR(mcpdm->clk);
434 dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret); 434 dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret);
435 goto err_clk; 435 goto err_clk;
436 } 436 }
437 437
438 mcpdm->dev = &pdev->dev; 438 mcpdm->dev = &pdev->dev;
439 platform_set_drvdata(pdev, mcpdm); 439 platform_set_drvdata(pdev, mcpdm);
440 440
441 return 0; 441 return 0;
442 442
443err_clk: 443err_clk:
444 iounmap(mcpdm->io_base); 444 iounmap(mcpdm->io_base);
445err_resource: 445err_resource:
446 kfree(mcpdm); 446 kfree(mcpdm);
447exit: 447exit:
448 return ret; 448 return ret;
449} 449}
450 450
451static int __devexit omap_mcpdm_remove(struct platform_device *pdev) 451static int __devexit omap_mcpdm_remove(struct platform_device *pdev)
452{ 452{
453 struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev); 453 struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
454 454
455 platform_set_drvdata(pdev, NULL); 455 platform_set_drvdata(pdev, NULL);
456 456
457 clk_put(mcpdm_ptr->clk); 457 clk_put(mcpdm_ptr->clk);
458 458
459 iounmap(mcpdm_ptr->io_base); 459 iounmap(mcpdm_ptr->io_base);
460 460
461 mcpdm_ptr->clk = NULL; 461 mcpdm_ptr->clk = NULL;
462 mcpdm_ptr->free = 0; 462 mcpdm_ptr->free = 0;
463 mcpdm_ptr->dev = NULL; 463 mcpdm_ptr->dev = NULL;
464 464
465 kfree(mcpdm_ptr); 465 kfree(mcpdm_ptr);
466 466
467 return 0; 467 return 0;
468} 468}
469 469
470static struct platform_driver omap_mcpdm_driver = { 470static struct platform_driver omap_mcpdm_driver = {
471 .probe = omap_mcpdm_probe, 471 .probe = omap_mcpdm_probe,
472 .remove = __devexit_p(omap_mcpdm_remove), 472 .remove = __devexit_p(omap_mcpdm_remove),
473 .driver = { 473 .driver = {
474 .name = "omap-mcpdm", 474 .name = "omap-mcpdm",
475 }, 475 },
476}; 476};
477 477
478static struct platform_device *omap_mcpdm_device; 478static struct platform_device *omap_mcpdm_device;
479 479
480static int __init omap_mcpdm_init(void) 480static int __init omap_mcpdm_init(void)
481{ 481{
482 return platform_driver_register(&omap_mcpdm_driver); 482 return platform_driver_register(&omap_mcpdm_driver);
483} 483}
484arch_initcall(omap_mcpdm_init); 484arch_initcall(omap_mcpdm_init);
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 8ad9dc901007..2d33a89f147a 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -256,6 +256,31 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
256 return err; 256 return err;
257} 257}
258 258
259static snd_pcm_sframes_t omap_mcbsp_dai_delay(
260 struct snd_pcm_substream *substream,
261 struct snd_soc_dai *dai)
262{
263 struct snd_soc_pcm_runtime *rtd = substream->private_data;
264 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
265 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
266 u16 fifo_use;
267 snd_pcm_sframes_t delay;
268
269 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
270 fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
271 else
272 fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
273
274 /*
275 * Divide the used locations with the channel count to get the
276 * FIFO usage in samples (don't care about partial samples in the
277 * buffer).
278 */
279 delay = fifo_use / substream->runtime->channels;
280
281 return delay;
282}
283
259static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, 284static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
260 struct snd_pcm_hw_params *params, 285 struct snd_pcm_hw_params *params,
261 struct snd_soc_dai *dai) 286 struct snd_soc_dai *dai)
@@ -308,7 +333,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
308 333
309 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; 334 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
310 wpf = channels = params_channels(params); 335 wpf = channels = params_channels(params);
311 if (channels == 2 && format == SND_SOC_DAIFMT_I2S) { 336 if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
337 format == SND_SOC_DAIFMT_LEFT_J)) {
312 /* Use dual-phase frames */ 338 /* Use dual-phase frames */
313 regs->rcr2 |= RPHASE; 339 regs->rcr2 |= RPHASE;
314 regs->xcr2 |= XPHASE; 340 regs->xcr2 |= XPHASE;
@@ -353,6 +379,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
353 /* Set FS period and length in terms of bit clock periods */ 379 /* Set FS period and length in terms of bit clock periods */
354 switch (format) { 380 switch (format) {
355 case SND_SOC_DAIFMT_I2S: 381 case SND_SOC_DAIFMT_I2S:
382 case SND_SOC_DAIFMT_LEFT_J:
356 regs->srgr2 |= FPER(framesize - 1); 383 regs->srgr2 |= FPER(framesize - 1);
357 regs->srgr1 |= FWID((framesize >> 1) - 1); 384 regs->srgr1 |= FWID((framesize >> 1) - 1);
358 break; 385 break;
@@ -404,6 +431,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
404 regs->rcr2 |= RDATDLY(1); 431 regs->rcr2 |= RDATDLY(1);
405 regs->xcr2 |= XDATDLY(1); 432 regs->xcr2 |= XDATDLY(1);
406 break; 433 break;
434 case SND_SOC_DAIFMT_LEFT_J:
435 /* 0-bit data delay */
436 regs->rcr2 |= RDATDLY(0);
437 regs->xcr2 |= XDATDLY(0);
438 regs->spcr1 |= RJUST(2);
439 /* Invert FS polarity configuration */
440 temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
441 break;
407 case SND_SOC_DAIFMT_DSP_A: 442 case SND_SOC_DAIFMT_DSP_A:
408 /* 1-bit data delay */ 443 /* 1-bit data delay */
409 regs->rcr2 |= RDATDLY(1); 444 regs->rcr2 |= RDATDLY(1);
@@ -609,6 +644,7 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
609 .startup = omap_mcbsp_dai_startup, 644 .startup = omap_mcbsp_dai_startup,
610 .shutdown = omap_mcbsp_dai_shutdown, 645 .shutdown = omap_mcbsp_dai_shutdown,
611 .trigger = omap_mcbsp_dai_trigger, 646 .trigger = omap_mcbsp_dai_trigger,
647 .delay = omap_mcbsp_dai_delay,
612 .hw_params = omap_mcbsp_dai_hw_params, 648 .hw_params = omap_mcbsp_dai_hw_params,
613 .set_fmt = omap_mcbsp_dai_set_dai_fmt, 649 .set_fmt = omap_mcbsp_dai_set_dai_fmt,
614 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, 650 .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index 88515946b6c0..865f93143bf1 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -16,18 +16,12 @@
16 * option) any later version. 16 * option) any later version.
17 */ 17 */
18 18
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/device.h>
22#include <linux/delay.h> 19#include <linux/delay.h>
23#include <linux/clk.h> 20#include <linux/clk.h>
24#include <linux/kernel.h>
25#include <linux/io.h> 21#include <linux/io.h>
26 22
27#include <sound/core.h>
28#include <sound/pcm.h> 23#include <sound/pcm.h>
29#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
30#include <sound/initval.h>
31#include <sound/soc.h> 25#include <sound/soc.h>
32 26
33#include <plat/regs-s3c2412-iis.h> 27#include <plat/regs-s3c2412-iis.h>
@@ -332,7 +326,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
332 return 0; 326 return 0;
333} 327}
334 328
335static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, 329static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
336 struct snd_pcm_hw_params *params, 330 struct snd_pcm_hw_params *params,
337 struct snd_soc_dai *socdai) 331 struct snd_soc_dai *socdai)
338{ 332{
@@ -355,34 +349,18 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
355 iismod = readl(i2s->regs + S3C2412_IISMOD); 349 iismod = readl(i2s->regs + S3C2412_IISMOD);
356 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); 350 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
357 351
358#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) 352 iismod &= ~S3C64XX_IISMOD_BLC_MASK;
359 switch (params_format(params)) {
360 case SNDRV_PCM_FORMAT_S8:
361 iismod |= S3C2412_IISMOD_8BIT;
362 break;
363 case SNDRV_PCM_FORMAT_S16_LE:
364 iismod &= ~S3C2412_IISMOD_8BIT;
365 break;
366 }
367#endif
368
369#ifdef CONFIG_PLAT_S3C64XX
370 iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK);
371 /* Sample size */ 353 /* Sample size */
372 switch (params_format(params)) { 354 switch (params_format(params)) {
373 case SNDRV_PCM_FORMAT_S8: 355 case SNDRV_PCM_FORMAT_S8:
374 /* 8 bit sample, 16fs BCLK */ 356 iismod |= S3C64XX_IISMOD_BLC_8BIT;
375 iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS);
376 break; 357 break;
377 case SNDRV_PCM_FORMAT_S16_LE: 358 case SNDRV_PCM_FORMAT_S16_LE:
378 /* 16 bit sample, 32fs BCLK */
379 break; 359 break;
380 case SNDRV_PCM_FORMAT_S24_LE: 360 case SNDRV_PCM_FORMAT_S24_LE:
381 /* 24 bit sample, 48fs BCLK */ 361 iismod |= S3C64XX_IISMOD_BLC_24BIT;
382 iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS);
383 break; 362 break;
384 } 363 }
385#endif
386 364
387 writel(iismod, i2s->regs + S3C2412_IISMOD); 365 writel(iismod, i2s->regs + S3C2412_IISMOD);
388 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod); 366 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
@@ -472,29 +450,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
472 450
473 switch (div_id) { 451 switch (div_id) {
474 case S3C_I2SV2_DIV_BCLK: 452 case S3C_I2SV2_DIV_BCLK:
475 if (div > 3) { 453 switch (div) {
476 /* convert value to bit field */ 454 case 16:
477 455 div = S3C2412_IISMOD_BCLK_16FS;
478 switch (div) { 456 break;
479 case 16:
480 div = S3C2412_IISMOD_BCLK_16FS;
481 break;
482 457
483 case 32: 458 case 32:
484 div = S3C2412_IISMOD_BCLK_32FS; 459 div = S3C2412_IISMOD_BCLK_32FS;
485 break; 460 break;
486 461
487 case 24: 462 case 24:
488 div = S3C2412_IISMOD_BCLK_24FS; 463 div = S3C2412_IISMOD_BCLK_24FS;
489 break; 464 break;
490 465
491 case 48: 466 case 48:
492 div = S3C2412_IISMOD_BCLK_48FS; 467 div = S3C2412_IISMOD_BCLK_48FS;
493 break; 468 break;
494 469
495 default: 470 default:
496 return -EINVAL; 471 return -EINVAL;
497 }
498 } 472 }
499 473
500 reg = readl(i2s->regs + S3C2412_IISMOD); 474 reg = readl(i2s->regs + S3C2412_IISMOD);
@@ -505,29 +479,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
505 break; 479 break;
506 480
507 case S3C_I2SV2_DIV_RCLK: 481 case S3C_I2SV2_DIV_RCLK:
508 if (div > 3) { 482 switch (div) {
509 /* convert value to bit field */ 483 case 256:
510 484 div = S3C2412_IISMOD_RCLK_256FS;
511 switch (div) { 485 break;
512 case 256:
513 div = S3C2412_IISMOD_RCLK_256FS;
514 break;
515 486
516 case 384: 487 case 384:
517 div = S3C2412_IISMOD_RCLK_384FS; 488 div = S3C2412_IISMOD_RCLK_384FS;
518 break; 489 break;
519 490
520 case 512: 491 case 512:
521 div = S3C2412_IISMOD_RCLK_512FS; 492 div = S3C2412_IISMOD_RCLK_512FS;
522 break; 493 break;
523 494
524 case 768: 495 case 768:
525 div = S3C2412_IISMOD_RCLK_768FS; 496 div = S3C2412_IISMOD_RCLK_768FS;
526 break; 497 break;
527 498
528 default: 499 default:
529 return -EINVAL; 500 return -EINVAL;
530 }
531 } 501 }
532 502
533 reg = readl(i2s->regs + S3C2412_IISMOD); 503 reg = readl(i2s->regs + S3C2412_IISMOD);
@@ -553,6 +523,21 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
553 return 0; 523 return 0;
554} 524}
555 525
526static snd_pcm_sframes_t s3c2412_i2s_delay(struct snd_pcm_substream *substream,
527 struct snd_soc_dai *dai)
528{
529 struct s3c_i2sv2_info *i2s = to_info(dai);
530 u32 reg = readl(i2s->regs + S3C2412_IISFIC);
531 snd_pcm_sframes_t delay;
532
533 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
534 delay = S3C2412_IISFIC_TXCOUNT(reg);
535 else
536 delay = S3C2412_IISFIC_RXCOUNT(reg);
537
538 return delay;
539}
540
556/* default table of all avaialable root fs divisors */ 541/* default table of all avaialable root fs divisors */
557static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; 542static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 };
558 543
@@ -735,10 +720,15 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
735 struct snd_soc_dai_ops *ops = dai->ops; 720 struct snd_soc_dai_ops *ops = dai->ops;
736 721
737 ops->trigger = s3c2412_i2s_trigger; 722 ops->trigger = s3c2412_i2s_trigger;
738 ops->hw_params = s3c2412_i2s_hw_params; 723 if (!ops->hw_params)
724 ops->hw_params = s3c_i2sv2_hw_params;
739 ops->set_fmt = s3c2412_i2s_set_fmt; 725 ops->set_fmt = s3c2412_i2s_set_fmt;
740 ops->set_clkdiv = s3c2412_i2s_set_clkdiv; 726 ops->set_clkdiv = s3c2412_i2s_set_clkdiv;
741 727
728 /* Allow overriding by (for example) IISv4 */
729 if (!ops->delay)
730 ops->delay = s3c2412_i2s_delay;
731
742 dai->suspend = s3c2412_i2s_suspend; 732 dai->suspend = s3c2412_i2s_suspend;
743 dai->resume = s3c2412_i2s_resume; 733 dai->resume = s3c2412_i2s_resume;
744 734
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h
index ecf8eaaed1db..b094d3c23cbe 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.h
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.h
@@ -25,6 +25,10 @@
25#define S3C_I2SV2_DIV_RCLK (2) 25#define S3C_I2SV2_DIV_RCLK (2)
26#define S3C_I2SV2_DIV_PRESCALER (3) 26#define S3C_I2SV2_DIV_PRESCALER (3)
27 27
28#define S3C_I2SV2_CLKSRC_PCLK 0
29#define S3C_I2SV2_CLKSRC_AUDIOBUS 1
30#define S3C_I2SV2_CLKSRC_CDCLK 2
31
28/** 32/**
29 * struct s3c_i2sv2_info - S3C I2S-V2 information 33 * struct s3c_i2sv2_info - S3C I2S-V2 information
30 * @dev: The parent device passed to use from the probe. 34 * @dev: The parent device passed to use from the probe.
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index 359e59346ba2..f3148f98b419 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -103,6 +103,10 @@ struct clk *s3c2412_get_iisclk(void)
103} 103}
104EXPORT_SYMBOL_GPL(s3c2412_get_iisclk); 104EXPORT_SYMBOL_GPL(s3c2412_get_iisclk);
105 105
106static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
107{
108 return cpu_dai->private_data;
109}
106 110
107static int s3c2412_i2s_probe(struct platform_device *pdev, 111static int s3c2412_i2s_probe(struct platform_device *pdev,
108 struct snd_soc_dai *dai) 112 struct snd_soc_dai *dai)
@@ -142,6 +146,41 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
142 return 0; 146 return 0;
143} 147}
144 148
149static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
150 struct snd_pcm_hw_params *params,
151 struct snd_soc_dai *cpu_dai)
152{
153 struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
154 struct s3c_dma_params *dma_data;
155 u32 iismod;
156
157 pr_debug("Entered %s\n", __func__);
158
159 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
160 dma_data = i2s->dma_playback;
161 else
162 dma_data = i2s->dma_capture;
163
164 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
165
166 iismod = readl(i2s->regs + S3C2412_IISMOD);
167 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
168
169 switch (params_format(params)) {
170 case SNDRV_PCM_FORMAT_S8:
171 iismod |= S3C2412_IISMOD_8BIT;
172 break;
173 case SNDRV_PCM_FORMAT_S16_LE:
174 iismod &= ~S3C2412_IISMOD_8BIT;
175 break;
176 }
177
178 writel(iismod, i2s->regs + S3C2412_IISMOD);
179 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
180
181 return 0;
182}
183
145#define S3C2412_I2S_RATES \ 184#define S3C2412_I2S_RATES \
146 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ 185 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
147 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 186 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
@@ -149,6 +188,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
149 188
150static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { 189static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
151 .set_sysclk = s3c2412_i2s_set_sysclk, 190 .set_sysclk = s3c2412_i2s_set_sysclk,
191 .hw_params = s3c2412_i2s_hw_params,
152}; 192};
153 193
154struct snd_soc_dai s3c2412_i2s_dai = { 194struct snd_soc_dai s3c2412_i2s_dai = {
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h
index 92848e54be16..60cac002a830 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.h
+++ b/sound/soc/s3c24xx/s3c2412-i2s.h
@@ -21,8 +21,8 @@
21#define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK 21#define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK
22#define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER 22#define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
23 23
24#define S3C2412_CLKSRC_PCLK (0) 24#define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK
25#define S3C2412_CLKSRC_I2SCLK (1) 25#define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS
26 26
27extern struct clk *s3c2412_get_iisclk(void); 27extern struct clk *s3c2412_get_iisclk(void);
28 28
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index a72c251401ac..ab1fa159d3ae 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -12,9 +12,6 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/device.h>
18#include <linux/clk.h> 15#include <linux/clk.h>
19#include <linux/gpio.h> 16#include <linux/gpio.h>
20#include <linux/io.h> 17#include <linux/io.h>
@@ -130,15 +127,6 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev,
130} 127}
131 128
132 129
133#define S3C64XX_I2S_RATES \
134 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
135 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
136 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
137
138#define S3C64XX_I2S_FMTS \
139 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
140 SNDRV_PCM_FMTBIT_S24_LE)
141
142static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { 130static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = {
143 .set_sysclk = s3c64xx_i2s_set_sysclk, 131 .set_sysclk = s3c64xx_i2s_set_sysclk,
144}; 132};
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
index abe7253b55fc..53d2a0a0df36 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -23,9 +23,18 @@ struct clk;
23#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK 23#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK
24#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER 24#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
25 25
26#define S3C64XX_CLKSRC_PCLK (0) 26#define S3C64XX_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK
27#define S3C64XX_CLKSRC_MUX (1) 27#define S3C64XX_CLKSRC_MUX S3C_I2SV2_CLKSRC_AUDIOBUS
28#define S3C64XX_CLKSRC_CDCLK (2) 28#define S3C64XX_CLKSRC_CDCLK S3C_I2SV2_CLKSRC_CDCLK
29
30#define S3C64XX_I2S_RATES \
31 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
32 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
33 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
34
35#define S3C64XX_I2S_FMTS \
36 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
37 SNDRV_PCM_FMTBIT_S24_LE)
29 38
30extern struct snd_soc_dai s3c64xx_i2s_dai[]; 39extern struct snd_soc_dai s3c64xx_i2s_dai[];
31 40
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index f07f6d8b93e1..a1d14bc3c76f 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -1,5 +1,5 @@
1menu "SoC Audio support for SuperH" 1menu "SoC Audio support for SuperH"
2 depends on SUPERH 2 depends on SUPERH || ARCH_SHMOBILE
3 3
4config SND_SOC_PCM_SH7760 4config SND_SOC_PCM_SH7760
5 tristate "SoC Audio support for Renesas SH7760" 5 tristate "SoC Audio support for Renesas SH7760"
@@ -22,7 +22,6 @@ config SND_SOC_SH4_SSI
22 22
23config SND_SOC_SH4_FSI 23config SND_SOC_SH4_FSI
24 tristate "SH4 FSI support" 24 tristate "SH4 FSI support"
25 depends on CPU_SUBTYPE_SH7724
26 help 25 help
27 This option enables FSI sound support 26 This option enables FSI sound support
28 27
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index 5263ab18f827..be018542314e 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -22,11 +22,25 @@
22#include <sound/sh_fsi.h> 22#include <sound/sh_fsi.h>
23#include <../sound/soc/codecs/ak4642.h> 23#include <../sound/soc/codecs/ak4642.h>
24 24
25static int fsi_ak4642_dai_init(struct snd_soc_codec *codec)
26{
27 int ret;
28
29 ret = snd_soc_dai_set_fmt(&ak4642_dai, SND_SOC_DAIFMT_CBM_CFM);
30 if (ret < 0)
31 return ret;
32
33 ret = snd_soc_dai_set_sysclk(&ak4642_dai, 0, 11289600, 0);
34
35 return ret;
36}
37
25static struct snd_soc_dai_link fsi_dai_link = { 38static struct snd_soc_dai_link fsi_dai_link = {
26 .name = "AK4642", 39 .name = "AK4642",
27 .stream_name = "AK4642", 40 .stream_name = "AK4642",
28 .cpu_dai = &fsi_soc_dai[0], /* fsi */ 41 .cpu_dai = &fsi_soc_dai[0], /* fsi */
29 .codec_dai = &ak4642_dai, 42 .codec_dai = &ak4642_dai,
43 .init = fsi_ak4642_dai_init,
30 .ops = NULL, 44 .ops = NULL,
31}; 45};
32 46
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 993abb730dfa..f14bbb0410c1 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -40,14 +40,19 @@
40#define MUTE_ST 0x0028 40#define MUTE_ST 0x0028
41#define REG_END MUTE_ST 41#define REG_END MUTE_ST
42 42
43
44#define CPU_INT_ST 0x01F4
45#define CPU_IEMSK 0x01F8
46#define CPU_IMSK 0x01FC
43#define INT_ST 0x0200 47#define INT_ST 0x0200
44#define IEMSK 0x0204 48#define IEMSK 0x0204
45#define IMSK 0x0208 49#define IMSK 0x0208
46#define MUTE 0x020C 50#define MUTE 0x020C
47#define CLK_RST 0x0210 51#define CLK_RST 0x0210
48#define SOFT_RST 0x0214 52#define SOFT_RST 0x0214
49#define MREG_START INT_ST 53#define FIFO_SZ 0x0218
50#define MREG_END SOFT_RST 54#define MREG_START CPU_INT_ST
55#define MREG_END FIFO_SZ
51 56
52/* DO_FMT */ 57/* DO_FMT */
53/* DI_FMT */ 58/* DI_FMT */
@@ -79,6 +84,17 @@
79#define INT_A_IN (1 << 4) 84#define INT_A_IN (1 << 4)
80#define INT_A_OUT (1 << 0) 85#define INT_A_OUT (1 << 0)
81 86
87/* SOFT_RST */
88#define PBSR (1 << 12) /* Port B Software Reset */
89#define PASR (1 << 8) /* Port A Software Reset */
90#define IR (1 << 4) /* Interrupt Reset */
91#define FSISR (1 << 0) /* Software Reset */
92
93/* FIFO_SZ */
94#define OUT_SZ_MASK 0x7
95#define BO_SZ_SHIFT 8
96#define AO_SZ_SHIFT 0
97
82#define FSI_RATES SNDRV_PCM_RATE_8000_96000 98#define FSI_RATES SNDRV_PCM_RATE_8000_96000
83 99
84#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) 100#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
@@ -104,11 +120,18 @@ struct fsi_priv {
104 int periods; 120 int periods;
105}; 121};
106 122
123struct fsi_regs {
124 u32 int_st;
125 u32 iemsk;
126 u32 imsk;
127};
128
107struct fsi_master { 129struct fsi_master {
108 void __iomem *base; 130 void __iomem *base;
109 int irq; 131 int irq;
110 struct fsi_priv fsia; 132 struct fsi_priv fsia;
111 struct fsi_priv fsib; 133 struct fsi_priv fsib;
134 struct fsi_regs *regs;
112 struct sh_fsi_platform_info *info; 135 struct sh_fsi_platform_info *info;
113 spinlock_t lock; 136 spinlock_t lock;
114}; 137};
@@ -316,7 +339,7 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
316/************************************************************************ 339/************************************************************************
317 340
318 341
319 ctrl function 342 irq function
320 343
321 344
322************************************************************************/ 345************************************************************************/
@@ -325,8 +348,8 @@ static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
325 u32 data = fsi_port_ab_io_bit(fsi, is_play); 348 u32 data = fsi_port_ab_io_bit(fsi, is_play);
326 struct fsi_master *master = fsi_get_master(fsi); 349 struct fsi_master *master = fsi_get_master(fsi);
327 350
328 fsi_master_mask_set(master, IMSK, data, data); 351 fsi_master_mask_set(master, master->regs->imsk, data, data);
329 fsi_master_mask_set(master, IEMSK, data, data); 352 fsi_master_mask_set(master, master->regs->iemsk, data, data);
330} 353}
331 354
332static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) 355static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
@@ -334,10 +357,39 @@ static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
334 u32 data = fsi_port_ab_io_bit(fsi, is_play); 357 u32 data = fsi_port_ab_io_bit(fsi, is_play);
335 struct fsi_master *master = fsi_get_master(fsi); 358 struct fsi_master *master = fsi_get_master(fsi);
336 359
337 fsi_master_mask_set(master, IMSK, data, 0); 360 fsi_master_mask_set(master, master->regs->imsk, data, 0);
338 fsi_master_mask_set(master, IEMSK, data, 0); 361 fsi_master_mask_set(master, master->regs->iemsk, data, 0);
362}
363
364static u32 fsi_irq_get_status(struct fsi_master *master)
365{
366 return fsi_master_read(master, master->regs->int_st);
367}
368
369static void fsi_irq_clear_all_status(struct fsi_master *master)
370{
371 fsi_master_write(master, master->regs->int_st, 0x0000000);
339} 372}
340 373
374static void fsi_irq_clear_status(struct fsi_priv *fsi)
375{
376 u32 data = 0;
377 struct fsi_master *master = fsi_get_master(fsi);
378
379 data |= fsi_port_ab_io_bit(fsi, 0);
380 data |= fsi_port_ab_io_bit(fsi, 1);
381
382 /* clear interrupt factor */
383 fsi_master_mask_set(master, master->regs->int_st, data, 0);
384}
385
386/************************************************************************
387
388
389 ctrl function
390
391
392************************************************************************/
341static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) 393static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
342{ 394{
343 u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); 395 u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4);
@@ -349,41 +401,61 @@ static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
349 fsi_master_mask_set(master, CLK_RST, val, 0); 401 fsi_master_mask_set(master, CLK_RST, val, 0);
350} 402}
351 403
352static void fsi_irq_init(struct fsi_priv *fsi, int is_play) 404static void fsi_fifo_init(struct fsi_priv *fsi,
405 int is_play,
406 struct snd_soc_dai *dai)
353{ 407{
354 u32 data; 408 struct fsi_master *master = fsi_get_master(fsi);
355 u32 ctrl; 409 u32 ctrl, shift, i;
356 410
357 data = fsi_port_ab_io_bit(fsi, is_play); 411 /* get on-chip RAM capacity */
358 ctrl = is_play ? DOFF_CTL : DIFF_CTL; 412 shift = fsi_master_read(master, FIFO_SZ);
413 shift >>= fsi_is_port_a(fsi) ? AO_SZ_SHIFT : BO_SZ_SHIFT;
414 shift &= OUT_SZ_MASK;
415 fsi->fifo_max = 256 << shift;
416 dev_dbg(dai->dev, "fifo = %d words\n", fsi->fifo_max);
359 417
360 /* set IMSK */ 418 /*
361 fsi_irq_disable(fsi, is_play); 419 * The maximum number of sample data varies depending
420 * on the number of channels selected for the format.
421 *
422 * FIFOs are used in 4-channel units in 3-channel mode
423 * and in 8-channel units in 5- to 7-channel mode
424 * meaning that more FIFOs than the required size of DPRAM
425 * are used.
426 *
427 * ex) if 256 words of DP-RAM is connected
428 * 1 channel: 256 (256 x 1 = 256)
429 * 2 channels: 128 (128 x 2 = 256)
430 * 3 channels: 64 ( 64 x 3 = 192)
431 * 4 channels: 64 ( 64 x 4 = 256)
432 * 5 channels: 32 ( 32 x 5 = 160)
433 * 6 channels: 32 ( 32 x 6 = 192)
434 * 7 channels: 32 ( 32 x 7 = 224)
435 * 8 channels: 32 ( 32 x 8 = 256)
436 */
437 for (i = 1; i < fsi->chan; i <<= 1)
438 fsi->fifo_max >>= 1;
439 dev_dbg(dai->dev, "%d channel %d store\n", fsi->chan, fsi->fifo_max);
440
441 ctrl = is_play ? DOFF_CTL : DIFF_CTL;
362 442
363 /* set interrupt generation factor */ 443 /* set interrupt generation factor */
364 fsi_reg_write(fsi, ctrl, IRQ_HALF); 444 fsi_reg_write(fsi, ctrl, IRQ_HALF);
365 445
366 /* clear FIFO */ 446 /* clear FIFO */
367 fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR); 447 fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR);
368
369 /* clear interrupt factor */
370 fsi_master_mask_set(fsi_get_master(fsi), INT_ST, data, 0);
371} 448}
372 449
373static void fsi_soft_all_reset(struct fsi_master *master) 450static void fsi_soft_all_reset(struct fsi_master *master)
374{ 451{
375 u32 status = fsi_master_read(master, SOFT_RST);
376
377 /* port AB reset */ 452 /* port AB reset */
378 status &= 0x000000ff; 453 fsi_master_mask_set(master, SOFT_RST, PASR | PBSR, 0);
379 fsi_master_write(master, SOFT_RST, status);
380 mdelay(10); 454 mdelay(10);
381 455
382 /* soft reset */ 456 /* soft reset */
383 status &= 0x000000f0; 457 fsi_master_mask_set(master, SOFT_RST, FSISR, 0);
384 fsi_master_write(master, SOFT_RST, status); 458 fsi_master_mask_set(master, SOFT_RST, FSISR, FSISR);
385 status |= 0x00000001;
386 fsi_master_write(master, SOFT_RST, status);
387 mdelay(10); 459 mdelay(10);
388} 460}
389 461
@@ -558,12 +630,11 @@ static int fsi_data_pop(struct fsi_priv *fsi, int startup)
558static irqreturn_t fsi_interrupt(int irq, void *data) 630static irqreturn_t fsi_interrupt(int irq, void *data)
559{ 631{
560 struct fsi_master *master = data; 632 struct fsi_master *master = data;
561 u32 status = fsi_master_read(master, SOFT_RST) & ~0x00000010; 633 u32 int_st = fsi_irq_get_status(master);
562 u32 int_st = fsi_master_read(master, INT_ST);
563 634
564 /* clear irq status */ 635 /* clear irq status */
565 fsi_master_write(master, SOFT_RST, status); 636 fsi_master_mask_set(master, SOFT_RST, IR, 0);
566 fsi_master_write(master, SOFT_RST, status | 0x00000010); 637 fsi_master_mask_set(master, SOFT_RST, IR, IR);
567 638
568 if (int_st & INT_A_OUT) 639 if (int_st & INT_A_OUT)
569 fsi_data_push(&master->fsia, 0); 640 fsi_data_push(&master->fsia, 0);
@@ -574,7 +645,7 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
574 if (int_st & INT_B_IN) 645 if (int_st & INT_B_IN)
575 fsi_data_pop(&master->fsib, 0); 646 fsi_data_pop(&master->fsib, 0);
576 647
577 fsi_master_write(master, INT_ST, 0x0000000); 648 fsi_irq_clear_all_status(master);
578 649
579 return IRQ_HANDLED; 650 return IRQ_HANDLED;
580} 651}
@@ -668,29 +739,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
668 dev_err(dai->dev, "unknown format.\n"); 739 dev_err(dai->dev, "unknown format.\n");
669 return -EINVAL; 740 return -EINVAL;
670 } 741 }
671
672 switch (fsi->chan) {
673 case 1:
674 fsi->fifo_max = 256;
675 break;
676 case 2:
677 fsi->fifo_max = 128;
678 break;
679 case 3:
680 case 4:
681 fsi->fifo_max = 64;
682 break;
683 case 5:
684 case 6:
685 case 7:
686 case 8:
687 fsi->fifo_max = 32;
688 break;
689 default:
690 dev_err(dai->dev, "channel size error.\n");
691 return -EINVAL;
692 }
693
694 fsi_reg_write(fsi, reg, data); 742 fsi_reg_write(fsi, reg, data);
695 743
696 /* 744 /*
@@ -699,8 +747,12 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
699 if (is_master) 747 if (is_master)
700 fsi_clk_ctrl(fsi, 1); 748 fsi_clk_ctrl(fsi, 1);
701 749
702 /* irq setting */ 750 /* irq clear */
703 fsi_irq_init(fsi, is_play); 751 fsi_irq_disable(fsi, is_play);
752 fsi_irq_clear_status(fsi);
753
754 /* fifo init */
755 fsi_fifo_init(fsi, is_play, dai);
704 756
705 return ret; 757 return ret;
706} 758}
@@ -912,6 +964,7 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform);
912static int fsi_probe(struct platform_device *pdev) 964static int fsi_probe(struct platform_device *pdev)
913{ 965{
914 struct fsi_master *master; 966 struct fsi_master *master;
967 const struct platform_device_id *id_entry;
915 struct resource *res; 968 struct resource *res;
916 unsigned int irq; 969 unsigned int irq;
917 int ret; 970 int ret;
@@ -921,6 +974,12 @@ static int fsi_probe(struct platform_device *pdev)
921 return -ENODEV; 974 return -ENODEV;
922 } 975 }
923 976
977 id_entry = pdev->id_entry;
978 if (!id_entry) {
979 dev_err(&pdev->dev, "unknown fsi device\n");
980 return -ENODEV;
981 }
982
924 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 983 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
925 irq = platform_get_irq(pdev, 0); 984 irq = platform_get_irq(pdev, 0);
926 if (!res || (int)irq <= 0) { 985 if (!res || (int)irq <= 0) {
@@ -949,6 +1008,7 @@ static int fsi_probe(struct platform_device *pdev)
949 master->fsia.master = master; 1008 master->fsia.master = master;
950 master->fsib.base = master->base + 0x40; 1009 master->fsib.base = master->base + 0x40;
951 master->fsib.master = master; 1010 master->fsib.master = master;
1011 master->regs = (struct fsi_regs *)id_entry->driver_data;
952 spin_lock_init(&master->lock); 1012 spin_lock_init(&master->lock);
953 1013
954 pm_runtime_enable(&pdev->dev); 1014 pm_runtime_enable(&pdev->dev);
@@ -961,7 +1021,8 @@ static int fsi_probe(struct platform_device *pdev)
961 1021
962 fsi_soft_all_reset(master); 1022 fsi_soft_all_reset(master);
963 1023
964 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); 1024 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED,
1025 id_entry->name, master);
965 if (ret) { 1026 if (ret) {
966 dev_err(&pdev->dev, "irq request err\n"); 1027 dev_err(&pdev->dev, "irq request err\n");
967 goto exit_iounmap; 1028 goto exit_iounmap;
@@ -1028,6 +1089,23 @@ static struct dev_pm_ops fsi_pm_ops = {
1028 .runtime_resume = fsi_runtime_nop, 1089 .runtime_resume = fsi_runtime_nop,
1029}; 1090};
1030 1091
1092static struct fsi_regs fsi_regs = {
1093 .int_st = INT_ST,
1094 .iemsk = IEMSK,
1095 .imsk = IMSK,
1096};
1097
1098static struct fsi_regs fsi2_regs = {
1099 .int_st = CPU_INT_ST,
1100 .iemsk = CPU_IEMSK,
1101 .imsk = CPU_IMSK,
1102};
1103
1104static struct platform_device_id fsi_id_table[] = {
1105 { "sh_fsi", (kernel_ulong_t)&fsi_regs },
1106 { "sh_fsi2", (kernel_ulong_t)&fsi2_regs },
1107};
1108
1031static struct platform_driver fsi_driver = { 1109static struct platform_driver fsi_driver = {
1032 .driver = { 1110 .driver = {
1033 .name = "sh_fsi", 1111 .name = "sh_fsi",
@@ -1035,6 +1113,7 @@ static struct platform_driver fsi_driver = {
1035 }, 1113 },
1036 .probe = fsi_probe, 1114 .probe = fsi_probe,
1037 .remove = fsi_remove, 1115 .remove = fsi_remove,
1116 .id_table = fsi_id_table,
1038}; 1117};
1039 1118
1040static int __init fsi_mobile_init(void) 1119static int __init fsi_mobile_init(void)
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 5869dc3be781..9dfe9a58a314 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -159,7 +159,8 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
159 159
160 BUG_ON(codec->volatile_register); 160 BUG_ON(codec->volatile_register);
161 161
162 data[0] = reg & 0xff; 162 reg &= 0xff;
163 data[0] = reg;
163 data[1] = value & 0xff; 164 data[1] = value & 0xff;
164 165
165 if (reg < codec->reg_cache_size) 166 if (reg < codec->reg_cache_size)
@@ -180,6 +181,7 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
180 unsigned int reg) 181 unsigned int reg)
181{ 182{
182 u8 *cache = codec->reg_cache; 183 u8 *cache = codec->reg_cache;
184 reg &= 0xff;
183 if (reg >= codec->reg_cache_size) 185 if (reg >= codec->reg_cache_size)
184 return -1; 186 return -1;
185 return cache[reg]; 187 return cache[reg];
@@ -226,6 +228,40 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
226} 228}
227 229
228#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) 230#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
231static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
232 unsigned int r)
233{
234 struct i2c_msg xfer[2];
235 u8 reg = r;
236 u8 data;
237 int ret;
238 struct i2c_client *client = codec->control_data;
239
240 /* Write register */
241 xfer[0].addr = client->addr;
242 xfer[0].flags = 0;
243 xfer[0].len = 1;
244 xfer[0].buf = &reg;
245
246 /* Read data */
247 xfer[1].addr = client->addr;
248 xfer[1].flags = I2C_M_RD;
249 xfer[1].len = 1;
250 xfer[1].buf = &data;
251
252 ret = i2c_transfer(client->adapter, xfer, 2);
253 if (ret != 2) {
254 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
255 return 0;
256 }
257
258 return data;
259}
260#else
261#define snd_soc_8_8_read_i2c NULL
262#endif
263
264#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
229static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, 265static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
230 unsigned int r) 266 unsigned int r)
231{ 267{
@@ -366,6 +402,84 @@ static int snd_soc_16_8_spi_write(void *control_data, const char *data,
366#define snd_soc_16_8_spi_write NULL 402#define snd_soc_16_8_spi_write NULL
367#endif 403#endif
368 404
405#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
406static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
407 unsigned int r)
408{
409 struct i2c_msg xfer[2];
410 u16 reg = cpu_to_be16(r);
411 u16 data;
412 int ret;
413 struct i2c_client *client = codec->control_data;
414
415 /* Write register */
416 xfer[0].addr = client->addr;
417 xfer[0].flags = 0;
418 xfer[0].len = 2;
419 xfer[0].buf = (u8 *)&reg;
420
421 /* Read data */
422 xfer[1].addr = client->addr;
423 xfer[1].flags = I2C_M_RD;
424 xfer[1].len = 2;
425 xfer[1].buf = (u8 *)&data;
426
427 ret = i2c_transfer(client->adapter, xfer, 2);
428 if (ret != 2) {
429 dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
430 return 0;
431 }
432
433 return be16_to_cpu(data);
434}
435#else
436#define snd_soc_16_16_read_i2c NULL
437#endif
438
439static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
440 unsigned int reg)
441{
442 u16 *cache = codec->reg_cache;
443
444 if (reg >= codec->reg_cache_size ||
445 snd_soc_codec_volatile_register(codec, reg)) {
446 if (codec->cache_only)
447 return -EINVAL;
448
449 return codec->hw_read(codec, reg);
450 }
451
452 return cache[reg];
453}
454
455static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
456 unsigned int value)
457{
458 u16 *cache = codec->reg_cache;
459 u8 data[4];
460 int ret;
461
462 data[0] = (reg >> 8) & 0xff;
463 data[1] = reg & 0xff;
464 data[2] = (value >> 8) & 0xff;
465 data[3] = value & 0xff;
466
467 if (reg < codec->reg_cache_size)
468 cache[reg] = value;
469
470 if (codec->cache_only) {
471 codec->cache_sync = 1;
472 return 0;
473 }
474
475 ret = codec->hw_write(codec->control_data, data, 4);
476 if (ret == 4)
477 return 0;
478 if (ret < 0)
479 return ret;
480 else
481 return -EIO;
482}
369 483
370static struct { 484static struct {
371 int addr_bits; 485 int addr_bits;
@@ -388,6 +502,7 @@ static struct {
388 { 502 {
389 .addr_bits = 8, .data_bits = 8, 503 .addr_bits = 8, .data_bits = 8,
390 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read, 504 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
505 .i2c_read = snd_soc_8_8_read_i2c,
391 }, 506 },
392 { 507 {
393 .addr_bits = 8, .data_bits = 16, 508 .addr_bits = 8, .data_bits = 16,
@@ -400,6 +515,11 @@ static struct {
400 .i2c_read = snd_soc_16_8_read_i2c, 515 .i2c_read = snd_soc_16_8_read_i2c,
401 .spi_write = snd_soc_16_8_spi_write, 516 .spi_write = snd_soc_16_8_spi_write,
402 }, 517 },
518 {
519 .addr_bits = 16, .data_bits = 16,
520 .write = snd_soc_16_16_write, .read = snd_soc_16_16_read,
521 .i2c_read = snd_soc_16_16_read_i2c,
522 },
403}; 523};
404 524
405/** 525/**
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index d0efd5eaaa0b..d59076e2ca84 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -315,7 +315,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
315 315
316 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || 316 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
317 machine->symmetric_rates) { 317 machine->symmetric_rates) {
318 dev_dbg(card->dev, "Symmetry forces %dHz rate\n", 318 dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
319 machine->rate); 319 machine->rate);
320 320
321 ret = snd_pcm_hw_constraint_minmax(substream->runtime, 321 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -404,6 +404,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
404 codec_dai->playback.formats & cpu_dai->playback.formats; 404 codec_dai->playback.formats & cpu_dai->playback.formats;
405 runtime->hw.rates = 405 runtime->hw.rates =
406 codec_dai->playback.rates & cpu_dai->playback.rates; 406 codec_dai->playback.rates & cpu_dai->playback.rates;
407 if (codec_dai->playback.rates
408 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
409 runtime->hw.rates |= cpu_dai->playback.rates;
410 if (cpu_dai->playback.rates
411 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
412 runtime->hw.rates |= codec_dai->playback.rates;
407 } else { 413 } else {
408 runtime->hw.rate_min = 414 runtime->hw.rate_min =
409 max(codec_dai->capture.rate_min, 415 max(codec_dai->capture.rate_min,
@@ -421,6 +427,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
421 codec_dai->capture.formats & cpu_dai->capture.formats; 427 codec_dai->capture.formats & cpu_dai->capture.formats;
422 runtime->hw.rates = 428 runtime->hw.rates =
423 codec_dai->capture.rates & cpu_dai->capture.rates; 429 codec_dai->capture.rates & cpu_dai->capture.rates;
430 if (codec_dai->capture.rates
431 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
432 runtime->hw.rates |= cpu_dai->capture.rates;
433 if (cpu_dai->capture.rates
434 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
435 runtime->hw.rates |= codec_dai->capture.rates;
424 } 436 }
425 437
426 snd_pcm_limit_hw_rates(runtime); 438 snd_pcm_limit_hw_rates(runtime);
@@ -454,12 +466,15 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
454 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, 466 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
455 runtime->hw.rate_max); 467 runtime->hw.rate_max);
456 468
457 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 469 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
458 cpu_dai->playback.active = codec_dai->playback.active = 1; 470 cpu_dai->playback.active++;
459 else 471 codec_dai->playback.active++;
460 cpu_dai->capture.active = codec_dai->capture.active = 1; 472 } else {
461 cpu_dai->active = codec_dai->active = 1; 473 cpu_dai->capture.active++;
462 cpu_dai->runtime = runtime; 474 codec_dai->capture.active++;
475 }
476 cpu_dai->active++;
477 codec_dai->active++;
463 card->codec->active++; 478 card->codec->active++;
464 mutex_unlock(&pcm_mutex); 479 mutex_unlock(&pcm_mutex);
465 return 0; 480 return 0;
@@ -535,15 +550,16 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
535 550
536 mutex_lock(&pcm_mutex); 551 mutex_lock(&pcm_mutex);
537 552
538 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 553 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
539 cpu_dai->playback.active = codec_dai->playback.active = 0; 554 cpu_dai->playback.active--;
540 else 555 codec_dai->playback.active--;
541 cpu_dai->capture.active = codec_dai->capture.active = 0; 556 } else {
542 557 cpu_dai->capture.active--;
543 if (codec_dai->playback.active == 0 && 558 codec_dai->capture.active--;
544 codec_dai->capture.active == 0) {
545 cpu_dai->active = codec_dai->active = 0;
546 } 559 }
560
561 cpu_dai->active--;
562 codec_dai->active--;
547 codec->active--; 563 codec->active--;
548 564
549 /* Muting the DAC suppresses artifacts caused during digital 565 /* Muting the DAC suppresses artifacts caused during digital
@@ -563,7 +579,6 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
563 579
564 if (platform->pcm_ops->close) 580 if (platform->pcm_ops->close)
565 platform->pcm_ops->close(substream); 581 platform->pcm_ops->close(substream);
566 cpu_dai->runtime = NULL;
567 582
568 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 583 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
569 /* start delayed pop wq here for playback streams */ 584 /* start delayed pop wq here for playback streams */
@@ -801,6 +816,41 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
801 return 0; 816 return 0;
802} 817}
803 818
819/*
820 * soc level wrapper for pointer callback
821 * If cpu_dai, codec_dai, platform driver has the delay callback, than
822 * the runtime->delay will be updated accordingly.
823 */
824static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
825{
826 struct snd_soc_pcm_runtime *rtd = substream->private_data;
827 struct snd_soc_device *socdev = rtd->socdev;
828 struct snd_soc_card *card = socdev->card;
829 struct snd_soc_platform *platform = card->platform;
830 struct snd_soc_dai_link *machine = rtd->dai;
831 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
832 struct snd_soc_dai *codec_dai = machine->codec_dai;
833 struct snd_pcm_runtime *runtime = substream->runtime;
834 snd_pcm_uframes_t offset = 0;
835 snd_pcm_sframes_t delay = 0;
836
837 if (platform->pcm_ops->pointer)
838 offset = platform->pcm_ops->pointer(substream);
839
840 if (cpu_dai->ops->delay)
841 delay += cpu_dai->ops->delay(substream, cpu_dai);
842
843 if (codec_dai->ops->delay)
844 delay += codec_dai->ops->delay(substream, codec_dai);
845
846 if (platform->delay)
847 delay += platform->delay(substream, codec_dai);
848
849 runtime->delay = delay;
850
851 return offset;
852}
853
804/* ASoC PCM operations */ 854/* ASoC PCM operations */
805static struct snd_pcm_ops soc_pcm_ops = { 855static struct snd_pcm_ops soc_pcm_ops = {
806 .open = soc_pcm_open, 856 .open = soc_pcm_open,
@@ -809,6 +859,7 @@ static struct snd_pcm_ops soc_pcm_ops = {
809 .hw_free = soc_pcm_hw_free, 859 .hw_free = soc_pcm_hw_free,
810 .prepare = soc_pcm_prepare, 860 .prepare = soc_pcm_prepare,
811 .trigger = soc_pcm_trigger, 861 .trigger = soc_pcm_trigger,
862 .pointer = soc_pcm_pointer,
812}; 863};
813 864
814#ifdef CONFIG_PM 865#ifdef CONFIG_PM
@@ -858,7 +909,7 @@ static int soc_suspend(struct device *dev)
858 if (cpu_dai->suspend && !cpu_dai->ac97_control) 909 if (cpu_dai->suspend && !cpu_dai->ac97_control)
859 cpu_dai->suspend(cpu_dai); 910 cpu_dai->suspend(cpu_dai);
860 if (platform->suspend) 911 if (platform->suspend)
861 platform->suspend(cpu_dai); 912 platform->suspend(&card->dai_link[i]);
862 } 913 }
863 914
864 /* close any waiting streams and save state */ 915 /* close any waiting streams and save state */
@@ -947,7 +998,7 @@ static void soc_resume_deferred(struct work_struct *work)
947 if (cpu_dai->resume && !cpu_dai->ac97_control) 998 if (cpu_dai->resume && !cpu_dai->ac97_control)
948 cpu_dai->resume(cpu_dai); 999 cpu_dai->resume(cpu_dai);
949 if (platform->resume) 1000 if (platform->resume)
950 platform->resume(cpu_dai); 1001 platform->resume(&card->dai_link[i]);
951 } 1002 }
952 1003
953 if (card->resume_post) 1004 if (card->resume_post)
@@ -1232,26 +1283,25 @@ static int soc_remove(struct platform_device *pdev)
1232 struct snd_soc_platform *platform = card->platform; 1283 struct snd_soc_platform *platform = card->platform;
1233 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 1284 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
1234 1285
1235 if (!card->instantiated) 1286 if (card->instantiated) {
1236 return 0; 1287 run_delayed_work(&card->delayed_work);
1237 1288
1238 run_delayed_work(&card->delayed_work); 1289 if (platform->remove)
1290 platform->remove(pdev);
1239 1291
1240 if (platform->remove) 1292 if (codec_dev->remove)
1241 platform->remove(pdev); 1293 codec_dev->remove(pdev);
1242 1294
1243 if (codec_dev->remove) 1295 for (i = 0; i < card->num_links; i++) {
1244 codec_dev->remove(pdev); 1296 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
1297 if (cpu_dai->remove)
1298 cpu_dai->remove(pdev, cpu_dai);
1299 }
1245 1300
1246 for (i = 0; i < card->num_links; i++) { 1301 if (card->remove)
1247 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1302 card->remove(pdev);
1248 if (cpu_dai->remove)
1249 cpu_dai->remove(pdev, cpu_dai);
1250 } 1303 }
1251 1304
1252 if (card->remove)
1253 card->remove(pdev);
1254
1255 snd_soc_unregister_card(card); 1305 snd_soc_unregister_card(card);
1256 1306
1257 return 0; 1307 return 0;
@@ -1335,7 +1385,6 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1335 dai_link->pcm = pcm; 1385 dai_link->pcm = pcm;
1336 pcm->private_data = rtd; 1386 pcm->private_data = rtd;
1337 soc_pcm_ops.mmap = platform->pcm_ops->mmap; 1387 soc_pcm_ops.mmap = platform->pcm_ops->mmap;
1338 soc_pcm_ops.pointer = platform->pcm_ops->pointer;
1339 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; 1388 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
1340 soc_pcm_ops.copy = platform->pcm_ops->copy; 1389 soc_pcm_ops.copy = platform->pcm_ops->copy;
1341 soc_pcm_ops.silence = platform->pcm_ops->silence; 1390 soc_pcm_ops.silence = platform->pcm_ops->silence;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 6c3351095786..476dbe6dabad 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -97,7 +97,6 @@ static void pop_dbg(u32 pop_time, const char *fmt, ...)
97 97
98 if (pop_time) { 98 if (pop_time) {
99 vprintk(fmt, args); 99 vprintk(fmt, args);
100 pop_wait(pop_time);
101 } 100 }
102 101
103 va_end(args); 102 va_end(args);
@@ -314,62 +313,14 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
314 pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", 313 pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n",
315 widget->name, widget->power ? "on" : "off", 314 widget->name, widget->power ? "on" : "off",
316 codec->pop_time); 315 codec->pop_time);
317 snd_soc_write(codec, widget->reg, new);
318 pop_wait(codec->pop_time); 316 pop_wait(codec->pop_time);
317 snd_soc_write(codec, widget->reg, new);
319 } 318 }
320 pr_debug("reg %x old %x new %x change %d\n", widget->reg, 319 pr_debug("reg %x old %x new %x change %d\n", widget->reg,
321 old, new, change); 320 old, new, change);
322 return change; 321 return change;
323} 322}
324 323
325/* ramps the volume up or down to minimise pops before or after a
326 * DAPM power event */
327static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
328{
329 const struct snd_kcontrol_new *k = widget->kcontrols;
330
331 if (widget->muted && !power)
332 return 0;
333 if (!widget->muted && power)
334 return 0;
335
336 if (widget->num_kcontrols && k) {
337 struct soc_mixer_control *mc =
338 (struct soc_mixer_control *)k->private_value;
339 unsigned int reg = mc->reg;
340 unsigned int shift = mc->shift;
341 int max = mc->max;
342 unsigned int mask = (1 << fls(max)) - 1;
343 unsigned int invert = mc->invert;
344
345 if (power) {
346 int i;
347 /* power up has happended, increase volume to last level */
348 if (invert) {
349 for (i = max; i > widget->saved_value; i--)
350 snd_soc_update_bits(widget->codec, reg, mask, i);
351 } else {
352 for (i = 0; i < widget->saved_value; i++)
353 snd_soc_update_bits(widget->codec, reg, mask, i);
354 }
355 widget->muted = 0;
356 } else {
357 /* power down is about to occur, decrease volume to mute */
358 int val = snd_soc_read(widget->codec, reg);
359 int i = widget->saved_value = (val >> shift) & mask;
360 if (invert) {
361 for (; i < mask; i++)
362 snd_soc_update_bits(widget->codec, reg, mask, i);
363 } else {
364 for (; i > 0; i--)
365 snd_soc_update_bits(widget->codec, reg, mask, i);
366 }
367 widget->muted = 1;
368 }
369 }
370 return 0;
371}
372
373/* create new dapm mixer control */ 324/* create new dapm mixer control */
374static int dapm_new_mixer(struct snd_soc_codec *codec, 325static int dapm_new_mixer(struct snd_soc_codec *codec,
375 struct snd_soc_dapm_widget *w) 326 struct snd_soc_dapm_widget *w)
@@ -464,20 +415,10 @@ err:
464static int dapm_new_pga(struct snd_soc_codec *codec, 415static int dapm_new_pga(struct snd_soc_codec *codec,
465 struct snd_soc_dapm_widget *w) 416 struct snd_soc_dapm_widget *w)
466{ 417{
467 struct snd_kcontrol *kcontrol; 418 if (w->num_kcontrols)
468 int ret = 0; 419 pr_err("asoc: PGA controls not supported: '%s'\n", w->name);
469
470 if (!w->num_kcontrols)
471 return -EINVAL;
472 420
473 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); 421 return 0;
474 ret = snd_ctl_add(codec->card, kcontrol);
475 if (ret < 0) {
476 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
477 return ret;
478 }
479
480 return ret;
481} 422}
482 423
483/* reset 'walked' bit for each dapm path */ 424/* reset 'walked' bit for each dapm path */
@@ -633,16 +574,8 @@ static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w)
633 return ret; 574 return ret;
634 } 575 }
635 576
636 /* Lower PGA volume to reduce pops */
637 if (w->id == snd_soc_dapm_pga && !w->power)
638 dapm_set_pga(w, w->power);
639
640 dapm_update_bits(w); 577 dapm_update_bits(w);
641 578
642 /* Raise PGA volume to reduce pops */
643 if (w->id == snd_soc_dapm_pga && w->power)
644 dapm_set_pga(w, w->power);
645
646 /* power up post event */ 579 /* power up post event */
647 if (w->power && w->event && 580 if (w->power && w->event &&
648 (w->event_flags & SND_SOC_DAPM_POST_PMU)) { 581 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
@@ -809,10 +742,6 @@ static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
809 pr_err("%s: pre event failed: %d\n", 742 pr_err("%s: pre event failed: %d\n",
810 w->name, ret); 743 w->name, ret);
811 } 744 }
812
813 /* Lower PGA volume to reduce pops */
814 if (w->id == snd_soc_dapm_pga && !w->power)
815 dapm_set_pga(w, w->power);
816 } 745 }
817 746
818 if (reg >= 0) { 747 if (reg >= 0) {
@@ -824,10 +753,6 @@ static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
824 } 753 }
825 754
826 list_for_each_entry(w, pending, power_list) { 755 list_for_each_entry(w, pending, power_list) {
827 /* Raise PGA volume to reduce pops */
828 if (w->id == snd_soc_dapm_pga && w->power)
829 dapm_set_pga(w, w->power);
830
831 /* power up post event */ 756 /* power up post event */
832 if (w->power && w->event && 757 if (w->power && w->event &&
833 (w->event_flags & SND_SOC_DAPM_POST_PMU)) { 758 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
@@ -980,7 +905,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
980 break; 905 break;
981 906
982 default: 907 default:
983 power = w->power_check(w); 908 if (!w->force)
909 power = w->power_check(w);
910 else
911 power = 1;
984 if (power) 912 if (power)
985 sys_power = 1; 913 sys_power = 1;
986 break; 914 break;
@@ -1075,6 +1003,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
1075 1003
1076 pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n", 1004 pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n",
1077 codec->pop_time); 1005 codec->pop_time);
1006 pop_wait(codec->pop_time);
1078 1007
1079 return 0; 1008 return 0;
1080} 1009}
@@ -1337,6 +1266,9 @@ static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
1337 if (!strcmp(w->name, pin)) { 1266 if (!strcmp(w->name, pin)) {
1338 pr_debug("dapm: %s: pin %s\n", codec->name, pin); 1267 pr_debug("dapm: %s: pin %s\n", codec->name, pin);
1339 w->connected = status; 1268 w->connected = status;
1269 /* Allow disabling of forced pins */
1270 if (status == 0)
1271 w->force = 0;
1340 return 0; 1272 return 0;
1341 } 1273 }
1342 } 1274 }
@@ -1593,12 +1525,6 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
1593 unsigned int invert = mc->invert; 1525 unsigned int invert = mc->invert;
1594 unsigned int mask = (1 << fls(max)) - 1; 1526 unsigned int mask = (1 << fls(max)) - 1;
1595 1527
1596 /* return the saved value if we are powered down */
1597 if (widget->id == snd_soc_dapm_pga && !widget->power) {
1598 ucontrol->value.integer.value[0] = widget->saved_value;
1599 return 0;
1600 }
1601
1602 ucontrol->value.integer.value[0] = 1528 ucontrol->value.integer.value[0] =
1603 (snd_soc_read(widget->codec, reg) >> shift) & mask; 1529 (snd_soc_read(widget->codec, reg) >> shift) & mask;
1604 if (shift != rshift) 1530 if (shift != rshift)
@@ -1658,13 +1584,6 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1658 mutex_lock(&widget->codec->mutex); 1584 mutex_lock(&widget->codec->mutex);
1659 widget->value = val; 1585 widget->value = val;
1660 1586
1661 /* save volume value if the widget is powered down */
1662 if (widget->id == snd_soc_dapm_pga && !widget->power) {
1663 widget->saved_value = val;
1664 mutex_unlock(&widget->codec->mutex);
1665 return 1;
1666 }
1667
1668 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { 1587 if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) {
1669 if (val) 1588 if (val)
1670 /* new connection */ 1589 /* new connection */
@@ -2134,6 +2053,36 @@ int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin)
2134EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); 2053EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
2135 2054
2136/** 2055/**
2056 * snd_soc_dapm_force_enable_pin - force a pin to be enabled
2057 * @codec: SoC codec
2058 * @pin: pin name
2059 *
2060 * Enables input/output pin regardless of any other state. This is
2061 * intended for use with microphone bias supplies used in microphone
2062 * jack detection.
2063 *
2064 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
2065 * do any widget power switching.
2066 */
2067int snd_soc_dapm_force_enable_pin(struct snd_soc_codec *codec, const char *pin)
2068{
2069 struct snd_soc_dapm_widget *w;
2070
2071 list_for_each_entry(w, &codec->dapm_widgets, list) {
2072 if (!strcmp(w->name, pin)) {
2073 pr_debug("dapm: %s: pin %s\n", codec->name, pin);
2074 w->connected = 1;
2075 w->force = 1;
2076 return 0;
2077 }
2078 }
2079
2080 pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin);
2081 return -EINVAL;
2082}
2083EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
2084
2085/**
2137 * snd_soc_dapm_disable_pin - disable pin. 2086 * snd_soc_dapm_disable_pin - disable pin.
2138 * @codec: SoC codec 2087 * @codec: SoC codec
2139 * @pin: pin name 2088 * @pin: pin name
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 3c07a94c2e30..f8fd22cc70bc 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -37,6 +37,7 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
37{ 37{
38 jack->card = card; 38 jack->card = card;
39 INIT_LIST_HEAD(&jack->pins); 39 INIT_LIST_HEAD(&jack->pins);
40 BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
40 41
41 return snd_jack_new(card->codec->card, id, type, &jack->jack); 42 return snd_jack_new(card->codec->card, id, type, &jack->jack);
42} 43}
@@ -93,6 +94,9 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
93 snd_soc_dapm_disable_pin(codec, pin->pin); 94 snd_soc_dapm_disable_pin(codec, pin->pin);
94 } 95 }
95 96
97 /* Report before the DAPM sync to help users updating micbias status */
98 blocking_notifier_call_chain(&jack->notifier, status, NULL);
99
96 snd_soc_dapm_sync(codec); 100 snd_soc_dapm_sync(codec);
97 101
98 snd_jack_report(jack->jack, status); 102 snd_jack_report(jack->jack, status);
@@ -143,6 +147,40 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
143} 147}
144EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); 148EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins);
145 149
150/**
151 * snd_soc_jack_notifier_register - Register a notifier for jack status
152 *
153 * @jack: ASoC jack
154 * @nb: Notifier block to register
155 *
156 * Register for notification of the current status of the jack. Note
157 * that it is not possible to report additional jack events in the
158 * callback from the notifier, this is intended to support
159 * applications such as enabling electrical detection only when a
160 * mechanical detection event has occurred.
161 */
162void snd_soc_jack_notifier_register(struct snd_soc_jack *jack,
163 struct notifier_block *nb)
164{
165 blocking_notifier_chain_register(&jack->notifier, nb);
166}
167EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_register);
168
169/**
170 * snd_soc_jack_notifier_unregister - Unregister a notifier for jack status
171 *
172 * @jack: ASoC jack
173 * @nb: Notifier block to unregister
174 *
175 * Stop notifying for status changes.
176 */
177void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack,
178 struct notifier_block *nb)
179{
180 blocking_notifier_chain_unregister(&jack->notifier, nb);
181}
182EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_unregister);
183
146#ifdef CONFIG_GPIOLIB 184#ifdef CONFIG_GPIOLIB
147/* gpio detect */ 185/* gpio detect */
148static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) 186static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)