aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-11-11 05:36:43 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-11-11 05:37:35 -0500
commit47a09af68ba50695c46511b8ed7f036d249bba48 (patch)
tree051c4b70501a9f360729ecc9a9493a2f8ba33b6f /sound
parenta23547374215422017239af32094e1aacc5d435e (diff)
parent206c5f60a3d902bc4b56dab2de3e88de5eb06108 (diff)
Merge tag 'v3.18-rc4' into patchwork
Needed due to some important regression fixes at RC core. * commit 'v3.18-rc4': (587 commits) Linux 3.18-rc4 ARM: dts: zynq: Enable PL clocks for Parallella tiny: rename ENABLE_DEV_COREDUMP to ALLOW_DEV_COREDUMP tiny: reverse logic for DISABLE_DEV_COREDUMP i2c: core: Dispose OF IRQ mapping at client removal time i2c: at91: don't account as iowait i2c: remove FSF address USB: Update default usb-storage delay_use value in kernel-parameters.txt sysfs: driver core: Fix glue dir race condition by gdp_mutex MIPS: Fix build with binutils 2.24.51+ xfs: track bulkstat progress by agino xfs: bulkstat error handling is broken xfs: bulkstat main loop logic is a mess xfs: bulkstat chunk-formatter has issues xfs: bulkstat chunk formatting cursor is broken xfs: bulkstat btree walk doesn't terminate mm: Fix comment before truncate_setsize() USB: cdc-acm: add quirk for control-line state requests tty: Fix pty master poll() after slave closes v2 MIPS: R3000: Fix debug output for Virtual page number ... Conflicts: drivers/media/rc/rc-main.c
Diffstat (limited to 'sound')
-rw-r--r--sound/core/pcm_compat.c2
-rw-r--r--sound/firewire/bebob/bebob_focusrite.c62
-rw-r--r--sound/firewire/bebob/bebob_stream.c18
-rw-r--r--sound/firewire/bebob/bebob_terratec.c7
-rw-r--r--sound/pci/ad1889.c8
-rw-r--r--sound/pci/hda/hda_intel.c4
-rw-r--r--sound/pci/hda/patch_realtek.c128
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/codecs/adau1761.c4
-rw-r--r--sound/soc/fsl/fsl_asrc.c2
-rw-r--r--sound/soc/fsl/fsl_esai.c2
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c4
-rw-r--r--sound/soc/s6000/Kconfig26
-rw-r--r--sound/soc/s6000/Makefile11
-rw-r--r--sound/soc/s6000/s6000-i2s.c617
-rw-r--r--sound/soc/s6000/s6000-i2s.h23
-rw-r--r--sound/soc/s6000/s6000-pcm.c521
-rw-r--r--sound/soc/s6000/s6000-pcm.h33
-rw-r--r--sound/soc/s6000/s6105-ipcam.c221
-rw-r--r--sound/usb/card.c9
21 files changed, 184 insertions, 1520 deletions
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 102e8fd1d450..2d957ba63557 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -210,6 +210,8 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
210 if (err < 0) 210 if (err < 0)
211 return err; 211 return err;
212 212
213 if (clear_user(src, sizeof(*src)))
214 return -EFAULT;
213 if (put_user(status.state, &src->state) || 215 if (put_user(status.state, &src->state) ||
214 compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || 216 compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
215 compat_put_timespec(&status.tstamp, &src->tstamp) || 217 compat_put_timespec(&status.tstamp, &src->tstamp) ||
diff --git a/sound/firewire/bebob/bebob_focusrite.c b/sound/firewire/bebob/bebob_focusrite.c
index 45a0eed6d5b1..3b052ed0fbf5 100644
--- a/sound/firewire/bebob/bebob_focusrite.c
+++ b/sound/firewire/bebob/bebob_focusrite.c
@@ -27,12 +27,14 @@
27#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0 27#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0
28#define SAFFIRE_CLOCK_SOURCE_SPDIF 1 28#define SAFFIRE_CLOCK_SOURCE_SPDIF 1
29 29
30/* '1' is absent, why... */ 30/* clock sources as returned from register of Saffire Pro 10 and 26 */
31#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0 31#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0
32#define SAFFIREPRO_CLOCK_SOURCE_SKIP 1 /* never used on hardware */
32#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2 33#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2
33#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 34#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 /* not used on s.pro. 10 */
34#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 35#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 /* not used on s.pro. 10 */
35#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5 36#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5
37#define SAFFIREPRO_CLOCK_SOURCE_COUNT 6
36 38
37/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */ 39/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
38#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4 40#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4
@@ -101,13 +103,34 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
101 &data, sizeof(__be32), 0); 103 &data, sizeof(__be32), 0);
102} 104}
103 105
106static char *const saffirepro_10_clk_src_labels[] = {
107 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
108};
104static char *const saffirepro_26_clk_src_labels[] = { 109static char *const saffirepro_26_clk_src_labels[] = {
105 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock" 110 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock"
106}; 111};
107 112/* Value maps between registers and labels for SaffirePro 10/26. */
108static char *const saffirepro_10_clk_src_labels[] = { 113static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = {
109 SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock" 114 /* SaffirePro 10 */
115 [0] = {
116 [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0,
117 [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */
118 [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1,
119 [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = -1, /* not supported */
120 [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = -1, /* not supported */
121 [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 2,
122 },
123 /* SaffirePro 26 */
124 [1] = {
125 [SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0,
126 [SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */
127 [SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1,
128 [SAFFIREPRO_CLOCK_SOURCE_ADAT1] = 2,
129 [SAFFIREPRO_CLOCK_SOURCE_ADAT2] = 3,
130 [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 4,
131 }
110}; 132};
133
111static int 134static int
112saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate) 135saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
113{ 136{
@@ -138,24 +161,35 @@ saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
138 161
139 return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id); 162 return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
140} 163}
164
165/*
166 * query hardware for current clock source, return our internally
167 * used clock index in *id, depending on hardware.
168 */
141static int 169static int
142saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id) 170saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
143{ 171{
144 int err; 172 int err;
145 u32 value; 173 u32 value; /* clock source read from hw register */
174 const signed char *map;
146 175
147 err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value); 176 err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
148 if (err < 0) 177 if (err < 0)
149 goto end; 178 goto end;
150 179
151 if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) { 180 /* depending on hardware, use a different mapping */
152 if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK) 181 if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels)
153 *id = 2; 182 map = saffirepro_clk_maps[0];
154 else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF) 183 else
155 *id = 1; 184 map = saffirepro_clk_maps[1];
156 } else if (value > 1) { 185
157 *id = value - 1; 186 /* In a case that this driver cannot handle the value of register. */
187 if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) {
188 err = -EIO;
189 goto end;
158 } 190 }
191
192 *id = (unsigned int)map[value];
159end: 193end:
160 return err; 194 return err;
161} 195}
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
index ef4d0c9f6578..1aab0a32870c 100644
--- a/sound/firewire/bebob/bebob_stream.c
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -129,12 +129,24 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal)
129 /* 1.The device has its own operation to switch source of clock */ 129 /* 1.The device has its own operation to switch source of clock */
130 if (clk_spec) { 130 if (clk_spec) {
131 err = clk_spec->get(bebob, &id); 131 err = clk_spec->get(bebob, &id);
132 if (err < 0) 132 if (err < 0) {
133 dev_err(&bebob->unit->device, 133 dev_err(&bebob->unit->device,
134 "fail to get clock source: %d\n", err); 134 "fail to get clock source: %d\n", err);
135 else if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, 135 goto end;
136 strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) 136 }
137
138 if (id >= clk_spec->num) {
139 dev_err(&bebob->unit->device,
140 "clock source %d out of range 0..%d\n",
141 id, clk_spec->num - 1);
142 err = -EIO;
143 goto end;
144 }
145
146 if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL,
147 strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0)
137 *internal = true; 148 *internal = true;
149
138 goto end; 150 goto end;
139 } 151 }
140 152
diff --git a/sound/firewire/bebob/bebob_terratec.c b/sound/firewire/bebob/bebob_terratec.c
index 0e4c0bfc463b..9940611f2e1b 100644
--- a/sound/firewire/bebob/bebob_terratec.c
+++ b/sound/firewire/bebob/bebob_terratec.c
@@ -24,7 +24,12 @@ phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
24 if (err < 0) 24 if (err < 0)
25 goto end; 25 goto end;
26 26
27 *id = (enable_ext & 0x01) | ((enable_word & 0x01) << 1); 27 if (enable_ext == 0)
28 *id = 0;
29 else if (enable_word == 0)
30 *id = 1;
31 else
32 *id = 2;
28end: 33end:
29 return err; 34 return err;
30} 35}
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 7bfdf9c51416..1610c38337af 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -681,7 +681,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
681 681
682 /* WARQ is at offset 12 */ 682 /* WARQ is at offset 12 */
683 tmp = (reg & AD_DS_WSMC_WARQ) ? 683 tmp = (reg & AD_DS_WSMC_WARQ) ?
684 (((reg & AD_DS_WSMC_WARQ >> 12) & 0x01) ? 12 : 18) : 4; 684 ((((reg & AD_DS_WSMC_WARQ) >> 12) & 0x01) ? 12 : 18) : 4;
685 tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1; 685 tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
686 686
687 snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp, 687 snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp,
@@ -693,7 +693,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
693 693
694 /* SYRQ is at offset 4 */ 694 /* SYRQ is at offset 4 */
695 tmp = (reg & AD_DS_WSMC_SYRQ) ? 695 tmp = (reg & AD_DS_WSMC_SYRQ) ?
696 (((reg & AD_DS_WSMC_SYRQ >> 4) & 0x01) ? 12 : 18) : 4; 696 ((((reg & AD_DS_WSMC_SYRQ) >> 4) & 0x01) ? 12 : 18) : 4;
697 tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1; 697 tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
698 698
699 snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp, 699 snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp,
@@ -709,7 +709,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
709 709
710 /* ACRQ is at offset 4 */ 710 /* ACRQ is at offset 4 */
711 tmp = (reg & AD_DS_RAMC_ACRQ) ? 711 tmp = (reg & AD_DS_RAMC_ACRQ) ?
712 (((reg & AD_DS_RAMC_ACRQ >> 4) & 0x01) ? 12 : 18) : 4; 712 ((((reg & AD_DS_RAMC_ACRQ) >> 4) & 0x01) ? 12 : 18) : 4;
713 tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1; 713 tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
714 714
715 snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp, 715 snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp,
@@ -720,7 +720,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
720 720
721 /* RERQ is at offset 12 */ 721 /* RERQ is at offset 12 */
722 tmp = (reg & AD_DS_RAMC_RERQ) ? 722 tmp = (reg & AD_DS_RAMC_RERQ) ?
723 (((reg & AD_DS_RAMC_RERQ >> 12) & 0x01) ? 12 : 18) : 4; 723 ((((reg & AD_DS_RAMC_RERQ) >> 12) & 0x01) ? 12 : 18) : 4;
724 tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1; 724 tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
725 725
726 snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp, 726 snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp,
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cfcca4c30d4d..9ab1e631cb32 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -374,6 +374,8 @@ static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool
374#ifdef CONFIG_SND_DMA_SGBUF 374#ifdef CONFIG_SND_DMA_SGBUF
375 if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) { 375 if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) {
376 struct snd_sg_buf *sgbuf = dmab->private_data; 376 struct snd_sg_buf *sgbuf = dmab->private_data;
377 if (chip->driver_type == AZX_DRIVER_CMEDIA)
378 return; /* deal with only CORB/RIRB buffers */
377 if (on) 379 if (on)
378 set_pages_array_wc(sgbuf->page_table, sgbuf->pages); 380 set_pages_array_wc(sgbuf->page_table, sgbuf->pages);
379 else 381 else
@@ -1769,7 +1771,7 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
1769#ifdef CONFIG_X86 1771#ifdef CONFIG_X86
1770 struct azx_pcm *apcm = snd_pcm_substream_chip(substream); 1772 struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
1771 struct azx *chip = apcm->chip; 1773 struct azx *chip = apcm->chip;
1772 if (!azx_snoop(chip)) 1774 if (!azx_snoop(chip) && chip->driver_type != AZX_DRIVER_CMEDIA)
1773 area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); 1775 area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
1774#endif 1776#endif
1775} 1777}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 34b7bdb510c7..da03693099eb 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -291,18 +291,14 @@ static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
291/* additional initialization for ALC888 variants */ 291/* additional initialization for ALC888 variants */
292static void alc888_coef_init(struct hda_codec *codec) 292static void alc888_coef_init(struct hda_codec *codec)
293{ 293{
294 if (alc_get_coef0(codec) == 0x20) 294 switch (alc_get_coef0(codec) & 0x00f0) {
295 /* alc888S-VC */ 295 /* alc888-VA */
296 alc_write_coef_idx(codec, 7, 0x830); 296 case 0x00:
297 else 297 /* alc888-VB */
298 /* alc888-VB */ 298 case 0x10:
299 alc_write_coef_idx(codec, 7, 0x3030); 299 alc_update_coef_idx(codec, 7, 0, 0x2030); /* Turn EAPD to High */
300} 300 break;
301 301 }
302/* additional initialization for ALC889 variants */
303static void alc889_coef_init(struct hda_codec *codec)
304{
305 alc_update_coef_idx(codec, 7, 0, 0x2010);
306} 302}
307 303
308/* turn on/off EAPD control (only if available) */ 304/* turn on/off EAPD control (only if available) */
@@ -359,25 +355,15 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
359 case 0x10ec0260: 355 case 0x10ec0260:
360 alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010); 356 alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010);
361 break; 357 break;
362 case 0x10ec0262:
363 case 0x10ec0880: 358 case 0x10ec0880:
364 case 0x10ec0882: 359 case 0x10ec0882:
365 case 0x10ec0883: 360 case 0x10ec0883:
366 case 0x10ec0885: 361 case 0x10ec0885:
367 case 0x10ec0887: 362 alc_update_coef_idx(codec, 7, 0, 0x2030);
368 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
369 case 0x10ec0900:
370 alc889_coef_init(codec);
371 break; 363 break;
372 case 0x10ec0888: 364 case 0x10ec0888:
373 alc888_coef_init(codec); 365 alc888_coef_init(codec);
374 break; 366 break;
375#if 0 /* XXX: This may cause the silent output on speaker on some machines */
376 case 0x10ec0267:
377 case 0x10ec0268:
378 alc_update_coef_idx(codec, 7, 0, 0x3000);
379 break;
380#endif /* XXX */
381 } 367 }
382 break; 368 break;
383 } 369 }
@@ -1710,7 +1696,7 @@ static void alc889_fixup_coef(struct hda_codec *codec,
1710{ 1696{
1711 if (action != HDA_FIXUP_ACT_INIT) 1697 if (action != HDA_FIXUP_ACT_INIT)
1712 return; 1698 return;
1713 alc889_coef_init(codec); 1699 alc_update_coef_idx(codec, 7, 0, 0x2030);
1714} 1700}
1715 1701
1716/* toggle speaker-output according to the hp-jack state */ 1702/* toggle speaker-output according to the hp-jack state */
@@ -2675,7 +2661,7 @@ static void alc269_shutup(struct hda_codec *codec)
2675 2661
2676static struct coef_fw alc282_coefs[] = { 2662static struct coef_fw alc282_coefs[] = {
2677 WRITE_COEF(0x03, 0x0002), /* Power Down Control */ 2663 WRITE_COEF(0x03, 0x0002), /* Power Down Control */
2678 WRITE_COEF(0x05, 0x0700), /* FIFO and filter clock */ 2664 UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
2679 WRITE_COEF(0x07, 0x0200), /* DMIC control */ 2665 WRITE_COEF(0x07, 0x0200), /* DMIC control */
2680 UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */ 2666 UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
2681 UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */ 2667 UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
@@ -2786,7 +2772,7 @@ static void alc282_shutup(struct hda_codec *codec)
2786 2772
2787static struct coef_fw alc283_coefs[] = { 2773static struct coef_fw alc283_coefs[] = {
2788 WRITE_COEF(0x03, 0x0002), /* Power Down Control */ 2774 WRITE_COEF(0x03, 0x0002), /* Power Down Control */
2789 WRITE_COEF(0x05, 0x0700), /* FIFO and filter clock */ 2775 UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
2790 WRITE_COEF(0x07, 0x0200), /* DMIC control */ 2776 WRITE_COEF(0x07, 0x0200), /* DMIC control */
2791 UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */ 2777 UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
2792 UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */ 2778 UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
@@ -2817,6 +2803,7 @@ static struct coef_fw alc283_coefs[] = {
2817 UPDATE_COEF(0x40, 0xf800, 0x9800), /* Class D DC enable */ 2803 UPDATE_COEF(0x40, 0xf800, 0x9800), /* Class D DC enable */
2818 UPDATE_COEF(0x42, 0xf000, 0x2000), /* DC offset */ 2804 UPDATE_COEF(0x42, 0xf000, 0x2000), /* DC offset */
2819 WRITE_COEF(0x37, 0xfc06), /* Class D amp control */ 2805 WRITE_COEF(0x37, 0xfc06), /* Class D amp control */
2806 UPDATE_COEF(0x1b, 0x8000, 0), /* HP JD control */
2820 {} 2807 {}
2821}; 2808};
2822 2809
@@ -3349,6 +3336,27 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
3349 } 3336 }
3350} 3337}
3351 3338
3339static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
3340 const struct hda_fixup *fix, int action)
3341{
3342 /* Like hp_gpio_mic1_led, but also needs GPIO4 low to enable headphone amp */
3343 struct alc_spec *spec = codec->spec;
3344 static const struct hda_verb gpio_init[] = {
3345 { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
3346 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
3347 {}
3348 };
3349
3350 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3351 spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
3352 spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
3353 spec->gpio_led = 0;
3354 spec->cap_mute_led_nid = 0x18;
3355 snd_hda_add_verbs(codec, gpio_init);
3356 codec->power_filter = led_power_filter;
3357 }
3358}
3359
3352static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, 3360static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
3353 const struct hda_fixup *fix, int action) 3361 const struct hda_fixup *fix, int action)
3354{ 3362{
@@ -4216,6 +4224,7 @@ enum {
4216 ALC283_FIXUP_BXBT2807_MIC, 4224 ALC283_FIXUP_BXBT2807_MIC,
4217 ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, 4225 ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
4218 ALC282_FIXUP_ASPIRE_V5_PINS, 4226 ALC282_FIXUP_ASPIRE_V5_PINS,
4227 ALC280_FIXUP_HP_GPIO4,
4219}; 4228};
4220 4229
4221static const struct hda_fixup alc269_fixups[] = { 4230static const struct hda_fixup alc269_fixups[] = {
@@ -4679,7 +4688,10 @@ static const struct hda_fixup alc269_fixups[] = {
4679 { }, 4688 { },
4680 }, 4689 },
4681 }, 4690 },
4682 4691 [ALC280_FIXUP_HP_GPIO4] = {
4692 .type = HDA_FIXUP_FUNC,
4693 .v.func = alc280_fixup_hp_gpio4,
4694 },
4683}; 4695};
4684 4696
4685static const struct snd_pci_quirk alc269_fixup_tbl[] = { 4697static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -4727,21 +4739,16 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
4727 SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), 4739 SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4728 SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4740 SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4729 SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4741 SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4730 SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4731 /* ALC290 */ 4742 /* ALC290 */
4732 SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4743 SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4733 SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4744 SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4734 SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4745 SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4735 SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4746 SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4736 SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4737 SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4738 SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4739 SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4747 SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4740 SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4748 SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4741 SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4749 SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4742 SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4750 SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4743 SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4751 SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4744 SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4745 SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4752 SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4746 SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4753 SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4747 SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), 4754 SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4750,7 +4757,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
4750 SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), 4757 SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4751 SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4758 SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4752 SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4759 SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4753 SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4754 SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), 4760 SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4755 SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), 4761 SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4756 SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), 4762 SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4803,7 +4809,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
4803 SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK), 4809 SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
4804 SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK), 4810 SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
4805 SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK), 4811 SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
4806 SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), 4812 SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
4807 SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), 4813 SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4808 SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), 4814 SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
4809 SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), 4815 SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -4983,6 +4989,19 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
4983 {0x17, 0x40000000}, 4989 {0x17, 0x40000000},
4984 {0x1d, 0x40700001}, 4990 {0x1d, 0x40700001},
4985 {0x21, 0x02211040}), 4991 {0x21, 0x02211040}),
4992 SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
4993 {0x12, 0x90a60130},
4994 {0x13, 0x40000000},
4995 {0x14, 0x90170110},
4996 {0x15, 0x0421101f},
4997 {0x16, 0x411111f0},
4998 {0x17, 0x411111f0},
4999 {0x18, 0x411111f0},
5000 {0x19, 0x411111f0},
5001 {0x1a, 0x04a11020},
5002 {0x1b, 0x411111f0},
5003 {0x1d, 0x40748605},
5004 {0x1e, 0x411111f0}),
4986 SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED, 5005 SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED,
4987 {0x12, 0x90a60140}, 5006 {0x12, 0x90a60140},
4988 {0x13, 0x40000000}, 5007 {0x13, 0x40000000},
@@ -5650,6 +5669,35 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec,
5650 } 5669 }
5651} 5670}
5652 5671
5672static struct coef_fw alc668_coefs[] = {
5673 WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0),
5674 WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80),
5675 WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b, 0x0),
5676 WRITE_COEF(0x0c, 0x7cf7), WRITE_COEF(0x0d, 0x1080), WRITE_COEF(0x0e, 0x7f7f),
5677 WRITE_COEF(0x0f, 0xcccc), WRITE_COEF(0x10, 0xddcc), WRITE_COEF(0x11, 0x0001),
5678 WRITE_COEF(0x13, 0x0), WRITE_COEF(0x14, 0x2aa0), WRITE_COEF(0x17, 0xa940),
5679 WRITE_COEF(0x19, 0x0), WRITE_COEF(0x1a, 0x0), WRITE_COEF(0x1b, 0x0),
5680 WRITE_COEF(0x1c, 0x0), WRITE_COEF(0x1d, 0x0), WRITE_COEF(0x1e, 0x7418),
5681 WRITE_COEF(0x1f, 0x0804), WRITE_COEF(0x20, 0x4200), WRITE_COEF(0x21, 0x0468),
5682 WRITE_COEF(0x22, 0x8ccc), WRITE_COEF(0x23, 0x0250), WRITE_COEF(0x24, 0x7418),
5683 WRITE_COEF(0x27, 0x0), WRITE_COEF(0x28, 0x8ccc), WRITE_COEF(0x2a, 0xff00),
5684 WRITE_COEF(0x2b, 0x8000), WRITE_COEF(0xa7, 0xff00), WRITE_COEF(0xa8, 0x8000),
5685 WRITE_COEF(0xaa, 0x2e17), WRITE_COEF(0xab, 0xa0c0), WRITE_COEF(0xac, 0x0),
5686 WRITE_COEF(0xad, 0x0), WRITE_COEF(0xae, 0x2ac6), WRITE_COEF(0xaf, 0xa480),
5687 WRITE_COEF(0xb0, 0x0), WRITE_COEF(0xb1, 0x0), WRITE_COEF(0xb2, 0x0),
5688 WRITE_COEF(0xb3, 0x0), WRITE_COEF(0xb4, 0x0), WRITE_COEF(0xb5, 0x1040),
5689 WRITE_COEF(0xb6, 0xd697), WRITE_COEF(0xb7, 0x902b), WRITE_COEF(0xb8, 0xd697),
5690 WRITE_COEF(0xb9, 0x902b), WRITE_COEF(0xba, 0xb8ba), WRITE_COEF(0xbb, 0xaaab),
5691 WRITE_COEF(0xbc, 0xaaaf), WRITE_COEF(0xbd, 0x6aaa), WRITE_COEF(0xbe, 0x1c02),
5692 WRITE_COEF(0xc0, 0x00ff), WRITE_COEF(0xc1, 0x0fa6),
5693 {}
5694};
5695
5696static void alc668_restore_default_value(struct hda_codec *codec)
5697{
5698 alc_process_coef_fw(codec, alc668_coefs);
5699}
5700
5653enum { 5701enum {
5654 ALC662_FIXUP_ASPIRE, 5702 ALC662_FIXUP_ASPIRE,
5655 ALC662_FIXUP_LED_GPIO1, 5703 ALC662_FIXUP_LED_GPIO1,
@@ -5922,6 +5970,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
5922 SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), 5970 SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
5923 SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), 5971 SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
5924 SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), 5972 SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
5973 SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
5925 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), 5974 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
5926 SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A), 5975 SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A),
5927 SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), 5976 SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
@@ -6116,8 +6165,15 @@ static int patch_alc662(struct hda_codec *codec)
6116 6165
6117 alc_fix_pll_init(codec, 0x20, 0x04, 15); 6166 alc_fix_pll_init(codec, 0x20, 0x04, 15);
6118 6167
6119 spec->init_hook = alc662_fill_coef; 6168 switch (codec->vendor_id) {
6120 alc662_fill_coef(codec); 6169 case 0x10ec0668:
6170 spec->init_hook = alc668_restore_default_value;
6171 break;
6172 default:
6173 spec->init_hook = alc662_fill_coef;
6174 alc662_fill_coef(codec);
6175 break;
6176 }
6121 6177
6122 snd_hda_pick_fixup(codec, alc662_fixup_models, 6178 snd_hda_pick_fixup(codec, alc662_fixup_models,
6123 alc662_fixup_tbl, alc662_fixups); 6179 alc662_fixup_tbl, alc662_fixups);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 0e9623368ab0..7d5d6444a837 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -49,7 +49,6 @@ source "sound/soc/mxs/Kconfig"
49source "sound/soc/pxa/Kconfig" 49source "sound/soc/pxa/Kconfig"
50source "sound/soc/rockchip/Kconfig" 50source "sound/soc/rockchip/Kconfig"
51source "sound/soc/samsung/Kconfig" 51source "sound/soc/samsung/Kconfig"
52source "sound/soc/s6000/Kconfig"
53source "sound/soc/sh/Kconfig" 52source "sound/soc/sh/Kconfig"
54source "sound/soc/sirf/Kconfig" 53source "sound/soc/sirf/Kconfig"
55source "sound/soc/spear/Kconfig" 54source "sound/soc/spear/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 534714a1ca44..d88edfced8c4 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -26,7 +26,6 @@ obj-$(CONFIG_SND_SOC) += kirkwood/
26obj-$(CONFIG_SND_SOC) += pxa/ 26obj-$(CONFIG_SND_SOC) += pxa/
27obj-$(CONFIG_SND_SOC) += rockchip/ 27obj-$(CONFIG_SND_SOC) += rockchip/
28obj-$(CONFIG_SND_SOC) += samsung/ 28obj-$(CONFIG_SND_SOC) += samsung/
29obj-$(CONFIG_SND_SOC) += s6000/
30obj-$(CONFIG_SND_SOC) += sh/ 29obj-$(CONFIG_SND_SOC) += sh/
31obj-$(CONFIG_SND_SOC) += sirf/ 30obj-$(CONFIG_SND_SOC) += sirf/
32obj-$(CONFIG_SND_SOC) += spear/ 31obj-$(CONFIG_SND_SOC) += spear/
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c
index 5518ebd6947c..91f60282fd2f 100644
--- a/sound/soc/codecs/adau1761.c
+++ b/sound/soc/codecs/adau1761.c
@@ -405,6 +405,7 @@ static const struct snd_soc_dapm_widget adau1761_dapm_widgets[] = {
405 2, 0, NULL, 0), 405 2, 0, NULL, 0),
406 406
407 SND_SOC_DAPM_SUPPLY("Slew Clock", ADAU1761_CLK_ENABLE0, 6, 0, NULL, 0), 407 SND_SOC_DAPM_SUPPLY("Slew Clock", ADAU1761_CLK_ENABLE0, 6, 0, NULL, 0),
408 SND_SOC_DAPM_SUPPLY("ALC Clock", ADAU1761_CLK_ENABLE0, 5, 0, NULL, 0),
408 409
409 SND_SOC_DAPM_SUPPLY_S("Digital Clock 0", 1, ADAU1761_CLK_ENABLE1, 410 SND_SOC_DAPM_SUPPLY_S("Digital Clock 0", 1, ADAU1761_CLK_ENABLE1,
410 0, 0, NULL, 0), 411 0, 0, NULL, 0),
@@ -436,6 +437,9 @@ static const struct snd_soc_dapm_route adau1761_dapm_routes[] = {
436 { "Right Playback Mixer", NULL, "Slew Clock" }, 437 { "Right Playback Mixer", NULL, "Slew Clock" },
437 { "Left Playback Mixer", NULL, "Slew Clock" }, 438 { "Left Playback Mixer", NULL, "Slew Clock" },
438 439
440 { "Left Input Mixer", NULL, "ALC Clock" },
441 { "Right Input Mixer", NULL, "ALC Clock" },
442
439 { "Digital Clock 0", NULL, "SYSCLK" }, 443 { "Digital Clock 0", NULL, "SYSCLK" },
440 { "Digital Clock 1", NULL, "SYSCLK" }, 444 { "Digital Clock 1", NULL, "SYSCLK" },
441}; 445};
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 3b145313f93e..ed866e9a2928 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -792,7 +792,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
792 return -ENOMEM; 792 return -ENOMEM;
793 793
794 asrc_priv->pdev = pdev; 794 asrc_priv->pdev = pdev;
795 strcpy(asrc_priv->name, np->name); 795 strncpy(asrc_priv->name, np->name, sizeof(asrc_priv->name) - 1);
796 796
797 /* Get the addresses and IRQ */ 797 /* Get the addresses and IRQ */
798 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 798 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 8bcdfda09d7a..a645e296199e 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -734,7 +734,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
734 return -ENOMEM; 734 return -ENOMEM;
735 735
736 esai_priv->pdev = pdev; 736 esai_priv->pdev = pdev;
737 strcpy(esai_priv->name, np->name); 737 strncpy(esai_priv->name, np->name, sizeof(esai_priv->name) - 1);
738 738
739 /* Get the addresses and IRQ */ 739 /* Get the addresses and IRQ */
740 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 740 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c
index 33fc5c3abf55..4df867cbb92a 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -691,9 +691,7 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
691} 691}
692 692
693#define HSW_FORMATS \ 693#define HSW_FORMATS \
694 (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ 694 (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
695 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\
696 SNDRV_PCM_FMTBIT_S8)
697 695
698static struct snd_soc_dai_driver hsw_dais[] = { 696static struct snd_soc_dai_driver hsw_dais[] = {
699 { 697 {
diff --git a/sound/soc/s6000/Kconfig b/sound/soc/s6000/Kconfig
deleted file mode 100644
index f244a2566f20..000000000000
--- a/sound/soc/s6000/Kconfig
+++ /dev/null
@@ -1,26 +0,0 @@
1config SND_S6000_SOC
2 tristate "SoC Audio for the Stretch s6000 family"
3 depends on XTENSA_VARIANT_S6000 || COMPILE_TEST
4 depends on HAS_IOMEM
5 select SND_S6000_SOC_PCM if XTENSA_VARIANT_S6000
6 help
7 Say Y or M if you want to add support for codecs attached to
8 s6000 family chips. You will also need to select the platform
9 to support below.
10
11config SND_S6000_SOC_PCM
12 tristate
13
14config SND_S6000_SOC_I2S
15 tristate
16
17config SND_S6000_SOC_S6IPCAM
18 bool "SoC Audio support for Stretch 6105 IP Camera"
19 depends on SND_S6000_SOC=y
20 depends on I2C=y
21 depends on XTENSA_PLATFORM_S6105 || COMPILE_TEST
22 select SND_S6000_SOC_I2S
23 select SND_SOC_TLV320AIC3X
24 help
25 Say Y if you want to add support for SoC audio on the
26 Stretch s6105 IP Camera Reference Design.
diff --git a/sound/soc/s6000/Makefile b/sound/soc/s6000/Makefile
deleted file mode 100644
index 0f0ae2a012aa..000000000000
--- a/sound/soc/s6000/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
1# s6000 Platform Support
2snd-soc-s6000-objs := s6000-pcm.o
3snd-soc-s6000-i2s-objs := s6000-i2s.o
4
5obj-$(CONFIG_SND_S6000_SOC_PCM) += snd-soc-s6000.o
6obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o
7
8# s6105 Machine Support
9snd-soc-s6ipcam-objs := s6105-ipcam.o
10
11obj-$(CONFIG_SND_S6000_SOC_S6IPCAM) += snd-soc-s6ipcam.o
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
deleted file mode 100644
index 1c8d01166e5b..000000000000
--- a/sound/soc/s6000/s6000-i2s.c
+++ /dev/null
@@ -1,617 +0,0 @@
1/*
2 * ALSA SoC I2S Audio Layer for the Stretch S6000 family
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/delay.h>
16#include <linux/clk.h>
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/slab.h>
20
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/initval.h>
25#include <sound/soc.h>
26
27#include "s6000-i2s.h"
28#include "s6000-pcm.h"
29
30struct s6000_i2s_dev {
31 dma_addr_t sifbase;
32 u8 __iomem *scbbase;
33 unsigned int wide;
34 unsigned int channel_in;
35 unsigned int channel_out;
36 unsigned int lines_in;
37 unsigned int lines_out;
38 struct s6000_pcm_dma_params dma_params;
39};
40
41#define S6_I2S_INTERRUPT_STATUS 0x00
42#define S6_I2S_INT_OVERRUN 1
43#define S6_I2S_INT_UNDERRUN 2
44#define S6_I2S_INT_ALIGNMENT 4
45#define S6_I2S_INTERRUPT_ENABLE 0x04
46#define S6_I2S_INTERRUPT_RAW 0x08
47#define S6_I2S_INTERRUPT_CLEAR 0x0C
48#define S6_I2S_INTERRUPT_SET 0x10
49#define S6_I2S_MODE 0x20
50#define S6_I2S_DUAL 0
51#define S6_I2S_WIDE 1
52#define S6_I2S_TX_DEFAULT 0x24
53#define S6_I2S_DATA_CFG(c) (0x40 + 0x10 * (c))
54#define S6_I2S_IN 0
55#define S6_I2S_OUT 1
56#define S6_I2S_UNUSED 2
57#define S6_I2S_INTERFACE_CFG(c) (0x44 + 0x10 * (c))
58#define S6_I2S_DIV_MASK 0x001fff
59#define S6_I2S_16BIT 0x000000
60#define S6_I2S_20BIT 0x002000
61#define S6_I2S_24BIT 0x004000
62#define S6_I2S_32BIT 0x006000
63#define S6_I2S_BITS_MASK 0x006000
64#define S6_I2S_MEM_16BIT 0x000000
65#define S6_I2S_MEM_32BIT 0x008000
66#define S6_I2S_MEM_MASK 0x008000
67#define S6_I2S_CHANNELS_SHIFT 16
68#define S6_I2S_CHANNELS_MASK 0x030000
69#define S6_I2S_SCK_IN 0x000000
70#define S6_I2S_SCK_OUT 0x040000
71#define S6_I2S_SCK_DIR 0x040000
72#define S6_I2S_WS_IN 0x000000
73#define S6_I2S_WS_OUT 0x080000
74#define S6_I2S_WS_DIR 0x080000
75#define S6_I2S_LEFT_FIRST 0x000000
76#define S6_I2S_RIGHT_FIRST 0x100000
77#define S6_I2S_FIRST 0x100000
78#define S6_I2S_CUR_SCK 0x200000
79#define S6_I2S_CUR_WS 0x400000
80#define S6_I2S_ENABLE(c) (0x48 + 0x10 * (c))
81#define S6_I2S_DISABLE_IF 0x02
82#define S6_I2S_ENABLE_IF 0x03
83#define S6_I2S_IS_BUSY 0x04
84#define S6_I2S_DMA_ACTIVE 0x08
85#define S6_I2S_IS_ENABLED 0x10
86
87#define S6_I2S_NUM_LINES 4
88
89#define S6_I2S_SIF_PORT0 0x0000000
90#define S6_I2S_SIF_PORT1 0x0000080 /* docs say 0x0000010 */
91
92static inline void s6_i2s_write_reg(struct s6000_i2s_dev *dev, int reg, u32 val)
93{
94 writel(val, dev->scbbase + reg);
95}
96
97static inline u32 s6_i2s_read_reg(struct s6000_i2s_dev *dev, int reg)
98{
99 return readl(dev->scbbase + reg);
100}
101
102static inline void s6_i2s_mod_reg(struct s6000_i2s_dev *dev, int reg,
103 u32 mask, u32 val)
104{
105 val ^= s6_i2s_read_reg(dev, reg) & ~mask;
106 s6_i2s_write_reg(dev, reg, val);
107}
108
109static void s6000_i2s_start_channel(struct s6000_i2s_dev *dev, int channel)
110{
111 int i, j, cur, prev;
112
113 /*
114 * Wait for WCLK to toggle 5 times before enabling the channel
115 * s6000 Family Datasheet 3.6.4:
116 * "At least two cycles of WS must occur between commands
117 * to disable or enable the interface"
118 */
119 j = 0;
120 prev = ~S6_I2S_CUR_WS;
121 for (i = 1000000; --i && j < 6; ) {
122 cur = s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(channel))
123 & S6_I2S_CUR_WS;
124 if (prev != cur) {
125 prev = cur;
126 j++;
127 }
128 }
129 if (j < 6)
130 printk(KERN_WARNING "s6000-i2s: timeout waiting for WCLK\n");
131
132 s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_ENABLE_IF);
133}
134
135static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel)
136{
137 s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_DISABLE_IF);
138}
139
140static void s6000_i2s_start(struct snd_pcm_substream *substream)
141{
142 struct snd_soc_pcm_runtime *rtd = substream->private_data;
143 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
144 int channel;
145
146 channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
147 dev->channel_out : dev->channel_in;
148
149 s6000_i2s_start_channel(dev, channel);
150}
151
152static void s6000_i2s_stop(struct snd_pcm_substream *substream)
153{
154 struct snd_soc_pcm_runtime *rtd = substream->private_data;
155 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
156 int channel;
157
158 channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
159 dev->channel_out : dev->channel_in;
160
161 s6000_i2s_stop_channel(dev, channel);
162}
163
164static int s6000_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
165 int after)
166{
167 switch (cmd) {
168 case SNDRV_PCM_TRIGGER_START:
169 case SNDRV_PCM_TRIGGER_RESUME:
170 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
171 if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ^ !after)
172 s6000_i2s_start(substream);
173 break;
174 case SNDRV_PCM_TRIGGER_STOP:
175 case SNDRV_PCM_TRIGGER_SUSPEND:
176 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
177 if (!after)
178 s6000_i2s_stop(substream);
179 }
180 return 0;
181}
182
183static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev)
184{
185 unsigned int pending;
186 pending = s6_i2s_read_reg(dev, S6_I2S_INTERRUPT_RAW);
187 pending &= S6_I2S_INT_ALIGNMENT |
188 S6_I2S_INT_UNDERRUN |
189 S6_I2S_INT_OVERRUN;
190 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR, pending);
191
192 return pending;
193}
194
195static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai)
196{
197 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
198 unsigned int errors;
199 unsigned int ret;
200
201 errors = s6000_i2s_int_sources(dev);
202 if (likely(!errors))
203 return 0;
204
205 ret = 0;
206 if (errors & S6_I2S_INT_ALIGNMENT)
207 printk(KERN_ERR "s6000-i2s: WCLK misaligned\n");
208 if (errors & S6_I2S_INT_UNDERRUN)
209 ret |= 1 << SNDRV_PCM_STREAM_PLAYBACK;
210 if (errors & S6_I2S_INT_OVERRUN)
211 ret |= 1 << SNDRV_PCM_STREAM_CAPTURE;
212 return ret;
213}
214
215static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev)
216{
217 int channel;
218 int n = 50;
219 for (channel = 0; channel < 2; channel++) {
220 while (--n >= 0) {
221 int v = s6_i2s_read_reg(dev, S6_I2S_ENABLE(channel));
222 if ((v & S6_I2S_IS_ENABLED)
223 || !(v & (S6_I2S_DMA_ACTIVE | S6_I2S_IS_BUSY)))
224 break;
225 udelay(20);
226 }
227 }
228 if (n < 0)
229 printk(KERN_WARNING "s6000-i2s: timeout disabling interfaces");
230}
231
232static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
233 unsigned int fmt)
234{
235 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
236 u32 w;
237
238 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
239 case SND_SOC_DAIFMT_CBM_CFM:
240 w = S6_I2S_SCK_IN | S6_I2S_WS_IN;
241 break;
242 case SND_SOC_DAIFMT_CBS_CFM:
243 w = S6_I2S_SCK_OUT | S6_I2S_WS_IN;
244 break;
245 case SND_SOC_DAIFMT_CBM_CFS:
246 w = S6_I2S_SCK_IN | S6_I2S_WS_OUT;
247 break;
248 case SND_SOC_DAIFMT_CBS_CFS:
249 w = S6_I2S_SCK_OUT | S6_I2S_WS_OUT;
250 break;
251 default:
252 return -EINVAL;
253 }
254
255 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
256 case SND_SOC_DAIFMT_NB_NF:
257 w |= S6_I2S_LEFT_FIRST;
258 break;
259 case SND_SOC_DAIFMT_NB_IF:
260 w |= S6_I2S_RIGHT_FIRST;
261 break;
262 default:
263 return -EINVAL;
264 }
265
266 s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(0),
267 S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w);
268 s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(1),
269 S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w);
270
271 return 0;
272}
273
274static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
275{
276 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
277
278 if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2)
279 return -EINVAL;
280
281 s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(div_id),
282 S6_I2S_DIV_MASK, div / 2 - 1);
283 return 0;
284}
285
286static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
287 struct snd_pcm_hw_params *params,
288 struct snd_soc_dai *dai)
289{
290 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
291 int interf;
292 u32 w = 0;
293
294 if (dev->wide)
295 interf = 0;
296 else {
297 w |= (((params_channels(params) - 2) / 2)
298 << S6_I2S_CHANNELS_SHIFT) & S6_I2S_CHANNELS_MASK;
299 interf = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
300 ? dev->channel_out : dev->channel_in;
301 }
302
303 switch (params_format(params)) {
304 case SNDRV_PCM_FORMAT_S16_LE:
305 w |= S6_I2S_16BIT | S6_I2S_MEM_16BIT;
306 break;
307 case SNDRV_PCM_FORMAT_S32_LE:
308 w |= S6_I2S_32BIT | S6_I2S_MEM_32BIT;
309 break;
310 default:
311 printk(KERN_WARNING "s6000-i2s: unsupported PCM format %x\n",
312 params_format(params));
313 return -EINVAL;
314 }
315
316 if (s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(interf))
317 & S6_I2S_IS_ENABLED) {
318 printk(KERN_ERR "s6000-i2s: interface already enabled\n");
319 return -EBUSY;
320 }
321
322 s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(interf),
323 S6_I2S_CHANNELS_MASK|S6_I2S_MEM_MASK|S6_I2S_BITS_MASK,
324 w);
325
326 return 0;
327}
328
329static int s6000_i2s_dai_probe(struct snd_soc_dai *dai)
330{
331 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
332 struct s6000_snd_platform_data *pdata = dai->dev->platform_data;
333
334 if (!pdata)
335 return -EINVAL;
336
337 dai->capture_dma_data = &dev->dma_params;
338 dai->playback_dma_data = &dev->dma_params;
339
340 dev->wide = pdata->wide;
341 dev->channel_in = pdata->channel_in;
342 dev->channel_out = pdata->channel_out;
343 dev->lines_in = pdata->lines_in;
344 dev->lines_out = pdata->lines_out;
345
346 s6_i2s_write_reg(dev, S6_I2S_MODE,
347 dev->wide ? S6_I2S_WIDE : S6_I2S_DUAL);
348
349 if (dev->wide) {
350 int i;
351
352 if (dev->lines_in + dev->lines_out > S6_I2S_NUM_LINES)
353 return -EINVAL;
354
355 dev->channel_in = 0;
356 dev->channel_out = 1;
357 dai->driver->capture.channels_min = 2 * dev->lines_in;
358 dai->driver->capture.channels_max = dai->driver->capture.channels_min;
359 dai->driver->playback.channels_min = 2 * dev->lines_out;
360 dai->driver->playback.channels_max = dai->driver->playback.channels_min;
361
362 for (i = 0; i < dev->lines_out; i++)
363 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT);
364
365 for (; i < S6_I2S_NUM_LINES - dev->lines_in; i++)
366 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i),
367 S6_I2S_UNUSED);
368
369 for (; i < S6_I2S_NUM_LINES; i++)
370 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_IN);
371 } else {
372 unsigned int cfg[2] = {S6_I2S_UNUSED, S6_I2S_UNUSED};
373
374 if (dev->lines_in > 1 || dev->lines_out > 1)
375 return -EINVAL;
376
377 dai->driver->capture.channels_min = 2 * dev->lines_in;
378 dai->driver->capture.channels_max = 8 * dev->lines_in;
379 dai->driver->playback.channels_min = 2 * dev->lines_out;
380 dai->driver->playback.channels_max = 8 * dev->lines_out;
381
382 if (dev->lines_in)
383 cfg[dev->channel_in] = S6_I2S_IN;
384 if (dev->lines_out)
385 cfg[dev->channel_out] = S6_I2S_OUT;
386
387 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(0), cfg[0]);
388 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(1), cfg[1]);
389 }
390
391 if (dev->lines_out) {
392 if (dev->lines_in) {
393 if (!dev->dma_params.dma_out)
394 return -ENODEV;
395 } else {
396 dev->dma_params.dma_out = dev->dma_params.dma_in;
397 dev->dma_params.dma_in = 0;
398 }
399 }
400 dev->dma_params.sif_in = dev->sifbase + (dev->channel_in ?
401 S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0);
402 dev->dma_params.sif_out = dev->sifbase + (dev->channel_out ?
403 S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0);
404 dev->dma_params.same_rate = pdata->same_rate | pdata->wide;
405 return 0;
406}
407
408#define S6000_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
409#define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
410
411static const struct snd_soc_dai_ops s6000_i2s_dai_ops = {
412 .set_fmt = s6000_i2s_set_dai_fmt,
413 .set_clkdiv = s6000_i2s_set_clkdiv,
414 .hw_params = s6000_i2s_hw_params,
415};
416
417static struct snd_soc_dai_driver s6000_i2s_dai = {
418 .probe = s6000_i2s_dai_probe,
419 .playback = {
420 .channels_min = 2,
421 .channels_max = 8,
422 .formats = S6000_I2S_FORMATS,
423 .rates = S6000_I2S_RATES,
424 .rate_min = 0,
425 .rate_max = 1562500,
426 },
427 .capture = {
428 .channels_min = 2,
429 .channels_max = 8,
430 .formats = S6000_I2S_FORMATS,
431 .rates = S6000_I2S_RATES,
432 .rate_min = 0,
433 .rate_max = 1562500,
434 },
435 .ops = &s6000_i2s_dai_ops,
436};
437
438static const struct snd_soc_component_driver s6000_i2s_component = {
439 .name = "s6000-i2s",
440};
441
442static int s6000_i2s_probe(struct platform_device *pdev)
443{
444 struct s6000_i2s_dev *dev;
445 struct resource *scbmem, *sifmem, *region, *dma1, *dma2;
446 u8 __iomem *mmio;
447 int ret;
448
449 scbmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
450 if (!scbmem) {
451 dev_err(&pdev->dev, "no mem resource?\n");
452 ret = -ENODEV;
453 goto err_release_none;
454 }
455
456 region = request_mem_region(scbmem->start, resource_size(scbmem),
457 pdev->name);
458 if (!region) {
459 dev_err(&pdev->dev, "I2S SCB region already claimed\n");
460 ret = -EBUSY;
461 goto err_release_none;
462 }
463
464 mmio = ioremap(scbmem->start, resource_size(scbmem));
465 if (!mmio) {
466 dev_err(&pdev->dev, "can't ioremap SCB region\n");
467 ret = -ENOMEM;
468 goto err_release_scb;
469 }
470
471 sifmem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
472 if (!sifmem) {
473 dev_err(&pdev->dev, "no second mem resource?\n");
474 ret = -ENODEV;
475 goto err_release_map;
476 }
477
478 region = request_mem_region(sifmem->start, resource_size(sifmem),
479 pdev->name);
480 if (!region) {
481 dev_err(&pdev->dev, "I2S SIF region already claimed\n");
482 ret = -EBUSY;
483 goto err_release_map;
484 }
485
486 dma1 = platform_get_resource(pdev, IORESOURCE_DMA, 0);
487 if (!dma1) {
488 dev_err(&pdev->dev, "no dma resource?\n");
489 ret = -ENODEV;
490 goto err_release_sif;
491 }
492
493 region = request_mem_region(dma1->start, resource_size(dma1),
494 pdev->name);
495 if (!region) {
496 dev_err(&pdev->dev, "I2S DMA region already claimed\n");
497 ret = -EBUSY;
498 goto err_release_sif;
499 }
500
501 dma2 = platform_get_resource(pdev, IORESOURCE_DMA, 1);
502 if (dma2) {
503 region = request_mem_region(dma2->start, resource_size(dma2),
504 pdev->name);
505 if (!region) {
506 dev_err(&pdev->dev,
507 "I2S DMA region already claimed\n");
508 ret = -EBUSY;
509 goto err_release_dma1;
510 }
511 }
512
513 dev = kzalloc(sizeof(struct s6000_i2s_dev), GFP_KERNEL);
514 if (!dev) {
515 ret = -ENOMEM;
516 goto err_release_dma2;
517 }
518 dev_set_drvdata(&pdev->dev, dev);
519
520 dev->sifbase = sifmem->start;
521 dev->scbbase = mmio;
522
523 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
524 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR,
525 S6_I2S_INT_ALIGNMENT |
526 S6_I2S_INT_UNDERRUN |
527 S6_I2S_INT_OVERRUN);
528
529 s6000_i2s_stop_channel(dev, 0);
530 s6000_i2s_stop_channel(dev, 1);
531 s6000_i2s_wait_disabled(dev);
532
533 dev->dma_params.check_xrun = s6000_i2s_check_xrun;
534 dev->dma_params.trigger = s6000_i2s_trigger;
535 dev->dma_params.dma_in = dma1->start;
536 dev->dma_params.dma_out = dma2 ? dma2->start : 0;
537 dev->dma_params.irq = platform_get_irq(pdev, 0);
538 if (dev->dma_params.irq < 0) {
539 dev_err(&pdev->dev, "no irq resource?\n");
540 ret = -ENODEV;
541 goto err_release_dev;
542 }
543
544 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE,
545 S6_I2S_INT_ALIGNMENT |
546 S6_I2S_INT_UNDERRUN |
547 S6_I2S_INT_OVERRUN);
548
549 ret = snd_soc_register_component(&pdev->dev, &s6000_i2s_component,
550 &s6000_i2s_dai, 1);
551 if (ret)
552 goto err_release_dev;
553
554 return 0;
555
556err_release_dev:
557 kfree(dev);
558err_release_dma2:
559 if (dma2)
560 release_mem_region(dma2->start, resource_size(dma2));
561err_release_dma1:
562 release_mem_region(dma1->start, resource_size(dma1));
563err_release_sif:
564 release_mem_region(sifmem->start, resource_size(sifmem));
565err_release_map:
566 iounmap(mmio);
567err_release_scb:
568 release_mem_region(scbmem->start, resource_size(scbmem));
569err_release_none:
570 return ret;
571}
572
573static int s6000_i2s_remove(struct platform_device *pdev)
574{
575 struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
576 struct resource *region;
577 void __iomem *mmio = dev->scbbase;
578
579 snd_soc_unregister_component(&pdev->dev);
580
581 s6000_i2s_stop_channel(dev, 0);
582 s6000_i2s_stop_channel(dev, 1);
583
584 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
585 kfree(dev);
586
587 region = platform_get_resource(pdev, IORESOURCE_DMA, 0);
588 release_mem_region(region->start, resource_size(region));
589
590 region = platform_get_resource(pdev, IORESOURCE_DMA, 1);
591 if (region)
592 release_mem_region(region->start, resource_size(region));
593
594 region = platform_get_resource(pdev, IORESOURCE_MEM, 0);
595 release_mem_region(region->start, resource_size(region));
596
597 iounmap(mmio);
598 region = platform_get_resource(pdev, IORESOURCE_IO, 0);
599 release_mem_region(region->start, resource_size(region));
600
601 return 0;
602}
603
604static struct platform_driver s6000_i2s_driver = {
605 .probe = s6000_i2s_probe,
606 .remove = s6000_i2s_remove,
607 .driver = {
608 .name = "s6000-i2s",
609 .owner = THIS_MODULE,
610 },
611};
612
613module_platform_driver(s6000_i2s_driver);
614
615MODULE_AUTHOR("Daniel Gloeckner");
616MODULE_DESCRIPTION("Stretch s6000 family I2S SoC Interface");
617MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h
deleted file mode 100644
index 86aa1921c89e..000000000000
--- a/sound/soc/s6000/s6000-i2s.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * ALSA SoC I2S Audio Layer for the Stretch s6000 family
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _S6000_I2S_H
13#define _S6000_I2S_H
14
15struct s6000_snd_platform_data {
16 int lines_in;
17 int lines_out;
18 int channel_in;
19 int channel_out;
20 int wide;
21 int same_rate;
22};
23#endif
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
deleted file mode 100644
index fb8461e1b1f6..000000000000
--- a/sound/soc/s6000/s6000-pcm.c
+++ /dev/null
@@ -1,521 +0,0 @@
1/*
2 * ALSA PCM interface for the Stetch s6000 family
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16#include <linux/dma-mapping.h>
17#include <linux/interrupt.h>
18
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/soc.h>
23
24#include <asm/dma.h>
25#include <variant/dmac.h>
26
27#include "s6000-pcm.h"
28
29#define S6_PCM_PREALLOCATE_SIZE (96 * 1024)
30#define S6_PCM_PREALLOCATE_MAX (2048 * 1024)
31
32static struct snd_pcm_hardware s6000_pcm_hardware = {
33 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
34 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
35 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX),
36 .buffer_bytes_max = 0x7ffffff0,
37 .period_bytes_min = 16,
38 .period_bytes_max = 0xfffff0,
39 .periods_min = 2,
40 .periods_max = 1024, /* no limit */
41 .fifo_size = 0,
42};
43
44struct s6000_runtime_data {
45 spinlock_t lock;
46 int period; /* current DMA period */
47};
48
49static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)
50{
51 struct snd_pcm_runtime *runtime = substream->runtime;
52 struct s6000_runtime_data *prtd = runtime->private_data;
53 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
54 struct s6000_pcm_dma_params *par;
55 int channel;
56 unsigned int period_size;
57 unsigned int dma_offset;
58 dma_addr_t dma_pos;
59 dma_addr_t src, dst;
60
61 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
62
63 period_size = snd_pcm_lib_period_bytes(substream);
64 dma_offset = prtd->period * period_size;
65 dma_pos = runtime->dma_addr + dma_offset;
66
67 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
68 src = dma_pos;
69 dst = par->sif_out;
70 channel = par->dma_out;
71 } else {
72 src = par->sif_in;
73 dst = dma_pos;
74 channel = par->dma_in;
75 }
76
77 if (!s6dmac_channel_enabled(DMA_MASK_DMAC(channel),
78 DMA_INDEX_CHNL(channel)))
79 return;
80
81 if (s6dmac_fifo_full(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel))) {
82 printk(KERN_ERR "s6000-pcm: fifo full\n");
83 return;
84 }
85
86 if (WARN_ON(period_size & 15))
87 return;
88 s6dmac_put_fifo(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel),
89 src, dst, period_size);
90
91 prtd->period++;
92 if (unlikely(prtd->period >= runtime->periods))
93 prtd->period = 0;
94}
95
96static irqreturn_t s6000_pcm_irq(int irq, void *data)
97{
98 struct snd_pcm *pcm = data;
99 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
100 struct s6000_runtime_data *prtd;
101 unsigned int has_xrun;
102 int i, ret = IRQ_NONE;
103
104 for (i = 0; i < 2; ++i) {
105 struct snd_pcm_substream *substream = pcm->streams[i].substream;
106 struct s6000_pcm_dma_params *params =
107 snd_soc_dai_get_dma_data(runtime->cpu_dai, substream);
108 u32 channel;
109 unsigned int pending;
110
111 if (substream == SNDRV_PCM_STREAM_PLAYBACK)
112 channel = params->dma_out;
113 else
114 channel = params->dma_in;
115
116 has_xrun = params->check_xrun(runtime->cpu_dai);
117
118 if (!channel)
119 continue;
120
121 if (unlikely(has_xrun & (1 << i)) &&
122 substream->runtime &&
123 snd_pcm_running(substream)) {
124 dev_dbg(pcm->dev, "xrun\n");
125 snd_pcm_stream_lock(substream);
126 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
127 snd_pcm_stream_unlock(substream);
128 ret = IRQ_HANDLED;
129 }
130
131 pending = s6dmac_int_sources(DMA_MASK_DMAC(channel),
132 DMA_INDEX_CHNL(channel));
133
134 if (pending & 1) {
135 ret = IRQ_HANDLED;
136 if (likely(substream->runtime &&
137 snd_pcm_running(substream))) {
138 snd_pcm_period_elapsed(substream);
139 dev_dbg(pcm->dev, "period elapsed %x %x\n",
140 s6dmac_cur_src(DMA_MASK_DMAC(channel),
141 DMA_INDEX_CHNL(channel)),
142 s6dmac_cur_dst(DMA_MASK_DMAC(channel),
143 DMA_INDEX_CHNL(channel)));
144 prtd = substream->runtime->private_data;
145 spin_lock(&prtd->lock);
146 s6000_pcm_enqueue_dma(substream);
147 spin_unlock(&prtd->lock);
148 }
149 }
150
151 if (unlikely(pending & ~7)) {
152 if (pending & (1 << 3))
153 printk(KERN_WARNING
154 "s6000-pcm: DMA %x Underflow\n",
155 channel);
156 if (pending & (1 << 4))
157 printk(KERN_WARNING
158 "s6000-pcm: DMA %x Overflow\n",
159 channel);
160 if (pending & 0x1e0)
161 printk(KERN_WARNING
162 "s6000-pcm: DMA %x Master Error "
163 "(mask %x)\n",
164 channel, pending >> 5);
165
166 }
167 }
168
169 return ret;
170}
171
172static int s6000_pcm_start(struct snd_pcm_substream *substream)
173{
174 struct s6000_runtime_data *prtd = substream->runtime->private_data;
175 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
176 struct s6000_pcm_dma_params *par;
177 unsigned long flags;
178 int srcinc;
179 u32 dma;
180
181 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
182
183 spin_lock_irqsave(&prtd->lock, flags);
184
185 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
186 srcinc = 1;
187 dma = par->dma_out;
188 } else {
189 srcinc = 0;
190 dma = par->dma_in;
191 }
192 s6dmac_enable_chan(DMA_MASK_DMAC(dma), DMA_INDEX_CHNL(dma),
193 1 /* priority 1 (0 is max) */,
194 0 /* peripheral requests w/o xfer length mode */,
195 srcinc /* source address increment */,
196 srcinc^1 /* destination address increment */,
197 0 /* chunksize 0 (skip impossible on this dma) */,
198 0 /* source skip after chunk (impossible) */,
199 0 /* destination skip after chunk (impossible) */,
200 4 /* 16 byte burst size */,
201 -1 /* don't conserve bandwidth */,
202 0 /* low watermark irq descriptor threshold */,
203 0 /* disable hardware timestamps */,
204 1 /* enable channel */);
205
206 s6000_pcm_enqueue_dma(substream);
207 s6000_pcm_enqueue_dma(substream);
208
209 spin_unlock_irqrestore(&prtd->lock, flags);
210
211 return 0;
212}
213
214static int s6000_pcm_stop(struct snd_pcm_substream *substream)
215{
216 struct s6000_runtime_data *prtd = substream->runtime->private_data;
217 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
218 struct s6000_pcm_dma_params *par;
219 unsigned long flags;
220 u32 channel;
221
222 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
223
224 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
225 channel = par->dma_out;
226 else
227 channel = par->dma_in;
228
229 s6dmac_set_terminal_count(DMA_MASK_DMAC(channel),
230 DMA_INDEX_CHNL(channel), 0);
231
232 spin_lock_irqsave(&prtd->lock, flags);
233
234 s6dmac_disable_chan(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel));
235
236 spin_unlock_irqrestore(&prtd->lock, flags);
237
238 return 0;
239}
240
241static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
242{
243 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
244 struct s6000_pcm_dma_params *par;
245 int ret;
246
247 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
248
249 ret = par->trigger(substream, cmd, 0);
250 if (ret < 0)
251 return ret;
252
253 switch (cmd) {
254 case SNDRV_PCM_TRIGGER_START:
255 case SNDRV_PCM_TRIGGER_RESUME:
256 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
257 ret = s6000_pcm_start(substream);
258 break;
259 case SNDRV_PCM_TRIGGER_STOP:
260 case SNDRV_PCM_TRIGGER_SUSPEND:
261 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
262 ret = s6000_pcm_stop(substream);
263 break;
264 default:
265 ret = -EINVAL;
266 }
267 if (ret < 0)
268 return ret;
269
270 return par->trigger(substream, cmd, 1);
271}
272
273static int s6000_pcm_prepare(struct snd_pcm_substream *substream)
274{
275 struct s6000_runtime_data *prtd = substream->runtime->private_data;
276
277 prtd->period = 0;
278
279 return 0;
280}
281
282static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
283{
284 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
285 struct s6000_pcm_dma_params *par;
286 struct snd_pcm_runtime *runtime = substream->runtime;
287 struct s6000_runtime_data *prtd = runtime->private_data;
288 unsigned long flags;
289 unsigned int offset;
290 dma_addr_t count;
291
292 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
293
294 spin_lock_irqsave(&prtd->lock, flags);
295
296 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
297 count = s6dmac_cur_src(DMA_MASK_DMAC(par->dma_out),
298 DMA_INDEX_CHNL(par->dma_out));
299 else
300 count = s6dmac_cur_dst(DMA_MASK_DMAC(par->dma_in),
301 DMA_INDEX_CHNL(par->dma_in));
302
303 count -= runtime->dma_addr;
304
305 spin_unlock_irqrestore(&prtd->lock, flags);
306
307 offset = bytes_to_frames(runtime, count);
308 if (unlikely(offset >= runtime->buffer_size))
309 offset = 0;
310
311 return offset;
312}
313
314static int s6000_pcm_open(struct snd_pcm_substream *substream)
315{
316 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
317 struct s6000_pcm_dma_params *par;
318 struct snd_pcm_runtime *runtime = substream->runtime;
319 struct s6000_runtime_data *prtd;
320 int ret;
321
322 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
323 snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);
324
325 ret = snd_pcm_hw_constraint_step(runtime, 0,
326 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16);
327 if (ret < 0)
328 return ret;
329 ret = snd_pcm_hw_constraint_step(runtime, 0,
330 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
331 if (ret < 0)
332 return ret;
333 ret = snd_pcm_hw_constraint_integer(runtime,
334 SNDRV_PCM_HW_PARAM_PERIODS);
335 if (ret < 0)
336 return ret;
337
338 if (par->same_rate) {
339 int rate;
340 spin_lock(&par->lock); /* needed? */
341 rate = par->rate;
342 spin_unlock(&par->lock);
343 if (rate != -1) {
344 ret = snd_pcm_hw_constraint_minmax(runtime,
345 SNDRV_PCM_HW_PARAM_RATE,
346 rate, rate);
347 if (ret < 0)
348 return ret;
349 }
350 }
351
352 prtd = kzalloc(sizeof(struct s6000_runtime_data), GFP_KERNEL);
353 if (prtd == NULL)
354 return -ENOMEM;
355
356 spin_lock_init(&prtd->lock);
357
358 runtime->private_data = prtd;
359
360 return 0;
361}
362
363static int s6000_pcm_close(struct snd_pcm_substream *substream)
364{
365 struct snd_pcm_runtime *runtime = substream->runtime;
366 struct s6000_runtime_data *prtd = runtime->private_data;
367
368 kfree(prtd);
369
370 return 0;
371}
372
373static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
374 struct snd_pcm_hw_params *hw_params)
375{
376 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
377 struct s6000_pcm_dma_params *par;
378 int ret;
379 ret = snd_pcm_lib_malloc_pages(substream,
380 params_buffer_bytes(hw_params));
381 if (ret < 0) {
382 printk(KERN_WARNING "s6000-pcm: allocation of memory failed\n");
383 return ret;
384 }
385
386 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
387
388 if (par->same_rate) {
389 spin_lock(&par->lock);
390 if (par->rate == -1 ||
391 !(par->in_use & ~(1 << substream->stream))) {
392 par->rate = params_rate(hw_params);
393 par->in_use |= 1 << substream->stream;
394 } else if (params_rate(hw_params) != par->rate) {
395 snd_pcm_lib_free_pages(substream);
396 par->in_use &= ~(1 << substream->stream);
397 ret = -EBUSY;
398 }
399 spin_unlock(&par->lock);
400 }
401 return ret;
402}
403
404static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)
405{
406 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
407 struct s6000_pcm_dma_params *par =
408 snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
409
410 spin_lock(&par->lock);
411 par->in_use &= ~(1 << substream->stream);
412 if (!par->in_use)
413 par->rate = -1;
414 spin_unlock(&par->lock);
415
416 return snd_pcm_lib_free_pages(substream);
417}
418
419static struct snd_pcm_ops s6000_pcm_ops = {
420 .open = s6000_pcm_open,
421 .close = s6000_pcm_close,
422 .ioctl = snd_pcm_lib_ioctl,
423 .hw_params = s6000_pcm_hw_params,
424 .hw_free = s6000_pcm_hw_free,
425 .trigger = s6000_pcm_trigger,
426 .prepare = s6000_pcm_prepare,
427 .pointer = s6000_pcm_pointer,
428};
429
430static void s6000_pcm_free(struct snd_pcm *pcm)
431{
432 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
433 struct s6000_pcm_dma_params *params =
434 snd_soc_dai_get_dma_data(runtime->cpu_dai,
435 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
436
437 free_irq(params->irq, pcm);
438 snd_pcm_lib_preallocate_free_for_all(pcm);
439}
440
441static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
442{
443 struct snd_card *card = runtime->card->snd_card;
444 struct snd_pcm *pcm = runtime->pcm;
445 struct s6000_pcm_dma_params *params;
446 int res;
447
448 params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
449 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
450
451 res = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
452 if (res)
453 return res;
454
455 if (params->dma_in) {
456 s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in),
457 DMA_INDEX_CHNL(params->dma_in));
458 s6dmac_int_sources(DMA_MASK_DMAC(params->dma_in),
459 DMA_INDEX_CHNL(params->dma_in));
460 }
461
462 if (params->dma_out) {
463 s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_out),
464 DMA_INDEX_CHNL(params->dma_out));
465 s6dmac_int_sources(DMA_MASK_DMAC(params->dma_out),
466 DMA_INDEX_CHNL(params->dma_out));
467 }
468
469 res = request_irq(params->irq, s6000_pcm_irq, IRQF_SHARED,
470 "s6000-audio", pcm);
471 if (res) {
472 printk(KERN_ERR "s6000-pcm couldn't get IRQ\n");
473 return res;
474 }
475
476 res = snd_pcm_lib_preallocate_pages_for_all(pcm,
477 SNDRV_DMA_TYPE_DEV,
478 card->dev,
479 S6_PCM_PREALLOCATE_SIZE,
480 S6_PCM_PREALLOCATE_MAX);
481 if (res)
482 printk(KERN_WARNING "s6000-pcm: preallocation failed\n");
483
484 spin_lock_init(&params->lock);
485 params->in_use = 0;
486 params->rate = -1;
487 return 0;
488}
489
490static struct snd_soc_platform_driver s6000_soc_platform = {
491 .ops = &s6000_pcm_ops,
492 .pcm_new = s6000_pcm_new,
493 .pcm_free = s6000_pcm_free,
494};
495
496static int s6000_soc_platform_probe(struct platform_device *pdev)
497{
498 return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform);
499}
500
501static int s6000_soc_platform_remove(struct platform_device *pdev)
502{
503 snd_soc_unregister_platform(&pdev->dev);
504 return 0;
505}
506
507static struct platform_driver s6000_pcm_driver = {
508 .driver = {
509 .name = "s6000-pcm-audio",
510 .owner = THIS_MODULE,
511 },
512
513 .probe = s6000_soc_platform_probe,
514 .remove = s6000_soc_platform_remove,
515};
516
517module_platform_driver(s6000_pcm_driver);
518
519MODULE_AUTHOR("Daniel Gloeckner");
520MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
521MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h
deleted file mode 100644
index 09d9b883e58b..000000000000
--- a/sound/soc/s6000/s6000-pcm.h
+++ /dev/null
@@ -1,33 +0,0 @@
1/*
2 * ALSA PCM interface for the Stretch s6000 family
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _S6000_PCM_H
13#define _S6000_PCM_H
14
15struct snd_soc_dai;
16struct snd_pcm_substream;
17
18struct s6000_pcm_dma_params {
19 unsigned int (*check_xrun)(struct snd_soc_dai *cpu_dai);
20 int (*trigger)(struct snd_pcm_substream *substream, int cmd, int after);
21 dma_addr_t sif_in;
22 dma_addr_t sif_out;
23 u32 dma_in;
24 u32 dma_out;
25 int irq;
26 int same_rate;
27
28 spinlock_t lock;
29 int in_use;
30 int rate;
31};
32
33#endif
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
deleted file mode 100644
index 3510c01f8a6a..000000000000
--- a/sound/soc/s6000/s6105-ipcam.c
+++ /dev/null
@@ -1,221 +0,0 @@
1/*
2 * ASoC driver for Stretch s6105 IP camera platform
3 *
4 * Author: Daniel Gloeckner, <dg@emlix.com>
5 * Copyright: (C) 2009 emlix GmbH <info@emlix.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/timer.h>
15#include <linux/interrupt.h>
16#include <linux/platform_device.h>
17#include <linux/i2c.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/soc.h>
21
22#include "s6000-pcm.h"
23#include "s6000-i2s.h"
24
25#define S6105_CAM_CODEC_CLOCK 12288000
26
27static int s6105_hw_params(struct snd_pcm_substream *substream,
28 struct snd_pcm_hw_params *params)
29{
30 struct snd_soc_pcm_runtime *rtd = substream->private_data;
31 struct snd_soc_dai *codec_dai = rtd->codec_dai;
32 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
33 int ret = 0;
34
35 /* set codec DAI configuration */
36 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
37 SND_SOC_DAIFMT_CBM_CFM);
38 if (ret < 0)
39 return ret;
40
41 /* set cpu DAI configuration */
42 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
43 SND_SOC_DAIFMT_NB_NF);
44 if (ret < 0)
45 return ret;
46
47 /* set the codec system clock */
48 ret = snd_soc_dai_set_sysclk(codec_dai, 0, S6105_CAM_CODEC_CLOCK,
49 SND_SOC_CLOCK_OUT);
50 if (ret < 0)
51 return ret;
52
53 return 0;
54}
55
56static struct snd_soc_ops s6105_ops = {
57 .hw_params = s6105_hw_params,
58};
59
60/* s6105 machine dapm widgets */
61static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
62 SND_SOC_DAPM_LINE("Audio Out Differential", NULL),
63 SND_SOC_DAPM_LINE("Audio Out Stereo", NULL),
64 SND_SOC_DAPM_LINE("Audio In", NULL),
65};
66
67/* s6105 machine audio_mapnections to the codec pins */
68static const struct snd_soc_dapm_route audio_map[] = {
69 /* Audio Out connected to HPLOUT, HPLCOM, HPROUT */
70 {"Audio Out Differential", NULL, "HPLOUT"},
71 {"Audio Out Differential", NULL, "HPLCOM"},
72 {"Audio Out Stereo", NULL, "HPLOUT"},
73 {"Audio Out Stereo", NULL, "HPROUT"},
74
75 /* Audio In connected to LINE1L, LINE1R */
76 {"LINE1L", NULL, "Audio In"},
77 {"LINE1R", NULL, "Audio In"},
78};
79
80static int output_type_info(struct snd_kcontrol *kcontrol,
81 struct snd_ctl_elem_info *uinfo)
82{
83 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
84 uinfo->count = 1;
85 uinfo->value.enumerated.items = 2;
86 if (uinfo->value.enumerated.item) {
87 uinfo->value.enumerated.item = 1;
88 strcpy(uinfo->value.enumerated.name, "HPLOUT/HPROUT");
89 } else {
90 strcpy(uinfo->value.enumerated.name, "HPLOUT/HPLCOM");
91 }
92 return 0;
93}
94
95static int output_type_get(struct snd_kcontrol *kcontrol,
96 struct snd_ctl_elem_value *ucontrol)
97{
98 ucontrol->value.enumerated.item[0] = kcontrol->private_value;
99 return 0;
100}
101
102static int output_type_put(struct snd_kcontrol *kcontrol,
103 struct snd_ctl_elem_value *ucontrol)
104{
105 struct snd_soc_card *card = kcontrol->private_data;
106 struct snd_soc_dapm_context *dapm = &card->dapm;
107 unsigned int val = (ucontrol->value.enumerated.item[0] != 0);
108 char *differential = "Audio Out Differential";
109 char *stereo = "Audio Out Stereo";
110
111 if (kcontrol->private_value == val)
112 return 0;
113 kcontrol->private_value = val;
114 snd_soc_dapm_disable_pin(dapm, val ? differential : stereo);
115 snd_soc_dapm_sync(dapm);
116 snd_soc_dapm_enable_pin(dapm, val ? stereo : differential);
117 snd_soc_dapm_sync(dapm);
118
119 return 1;
120}
121
122static const struct snd_kcontrol_new audio_out_mux = {
123 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
124 .name = "Master Output Mux",
125 .index = 0,
126 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
127 .info = output_type_info,
128 .get = output_type_get,
129 .put = output_type_put,
130 .private_value = 1 /* default to stereo */
131};
132
133/* Logic for a aic3x as connected on the s6105 ip camera ref design */
134static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd)
135{
136 struct snd_soc_card *card = rtd->card;
137
138 /* must correspond to audio_out_mux.private_value initializer */
139 snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential");
140
141 snd_ctl_add(card->snd_card, snd_ctl_new1(&audio_out_mux, card));
142
143 return 0;
144}
145
146/* s6105 digital audio interface glue - connects codec <--> CPU */
147static struct snd_soc_dai_link s6105_dai = {
148 .name = "TLV320AIC31",
149 .stream_name = "AIC31",
150 .cpu_dai_name = "s6000-i2s",
151 .codec_dai_name = "tlv320aic3x-hifi",
152 .platform_name = "s6000-pcm-audio",
153 .codec_name = "tlv320aic3x-codec.0-001a",
154 .init = s6105_aic3x_init,
155 .ops = &s6105_ops,
156};
157
158/* s6105 audio machine driver */
159static struct snd_soc_card snd_soc_card_s6105 = {
160 .name = "Stretch IP Camera",
161 .owner = THIS_MODULE,
162 .dai_link = &s6105_dai,
163 .num_links = 1,
164
165 .dapm_widgets = aic3x_dapm_widgets,
166 .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets),
167 .dapm_routes = audio_map,
168 .num_dapm_routes = ARRAY_SIZE(audio_map),
169 .fully_routed = true,
170};
171
172static struct s6000_snd_platform_data s6105_snd_data __initdata = {
173 .wide = 0,
174 .channel_in = 0,
175 .channel_out = 1,
176 .lines_in = 1,
177 .lines_out = 1,
178 .same_rate = 1,
179};
180
181static struct platform_device *s6105_snd_device;
182
183/* temporary i2c device creation until this can be moved into the machine
184 * support file.
185*/
186static struct i2c_board_info i2c_device[] = {
187 { I2C_BOARD_INFO("tlv320aic33", 0x18), }
188};
189
190static int __init s6105_init(void)
191{
192 int ret;
193
194 i2c_register_board_info(0, i2c_device, ARRAY_SIZE(i2c_device));
195
196 s6105_snd_device = platform_device_alloc("soc-audio", -1);
197 if (!s6105_snd_device)
198 return -ENOMEM;
199
200 platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105);
201 platform_device_add_data(s6105_snd_device, &s6105_snd_data,
202 sizeof(s6105_snd_data));
203
204 ret = platform_device_add(s6105_snd_device);
205 if (ret)
206 platform_device_put(s6105_snd_device);
207
208 return ret;
209}
210
211static void __exit s6105_exit(void)
212{
213 platform_device_unregister(s6105_snd_device);
214}
215
216module_init(s6105_init);
217module_exit(s6105_exit);
218
219MODULE_AUTHOR("Daniel Gloeckner");
220MODULE_DESCRIPTION("Stretch s6105 IP camera ASoC driver");
221MODULE_LICENSE("GPL");
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 7ecd0e8a5c51..f61ebb17cc64 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -591,18 +591,19 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
591{ 591{
592 struct snd_card *card; 592 struct snd_card *card;
593 struct list_head *p; 593 struct list_head *p;
594 bool was_shutdown;
594 595
595 if (chip == (void *)-1L) 596 if (chip == (void *)-1L)
596 return; 597 return;
597 598
598 card = chip->card; 599 card = chip->card;
599 down_write(&chip->shutdown_rwsem); 600 down_write(&chip->shutdown_rwsem);
601 was_shutdown = chip->shutdown;
600 chip->shutdown = 1; 602 chip->shutdown = 1;
601 up_write(&chip->shutdown_rwsem); 603 up_write(&chip->shutdown_rwsem);
602 604
603 mutex_lock(&register_mutex); 605 mutex_lock(&register_mutex);
604 chip->num_interfaces--; 606 if (!was_shutdown) {
605 if (chip->num_interfaces <= 0) {
606 struct snd_usb_endpoint *ep; 607 struct snd_usb_endpoint *ep;
607 608
608 snd_card_disconnect(card); 609 snd_card_disconnect(card);
@@ -622,6 +623,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
622 list_for_each(p, &chip->mixer_list) { 623 list_for_each(p, &chip->mixer_list) {
623 snd_usb_mixer_disconnect(p); 624 snd_usb_mixer_disconnect(p);
624 } 625 }
626 }
627
628 chip->num_interfaces--;
629 if (chip->num_interfaces <= 0) {
625 usb_chip[chip->index] = NULL; 630 usb_chip[chip->index] = NULL;
626 mutex_unlock(&register_mutex); 631 mutex_unlock(&register_mutex);
627 snd_card_free_when_closed(card); 632 snd_card_free_when_closed(card);