aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-07 20:07:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-07 20:07:31 -0400
commitfaa38b5e0e092914764cdba9f83d31a3f794d182 (patch)
treeb3e5921bdc36378033b4910eb4f29cb0dfc486e0 /sound
parent78417334b5cb6e1f915b8fdcc4fce3f1a1b4420c (diff)
parent74bf40f0793fed9e01eb6164c2ce63e8c27ca205 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (214 commits) ALSA: hda - Add pin-fix for HP dc5750 ALSA: als4000: Fix potentially invalid DMA mode setup ALSA: als4000: enable burst mode ALSA: hda - Fix initial capsrc selection in patch_alc269() ASoC: TWL4030: Capture route runtime DAPM ordering fix ALSA: hda - Add PC-beep whitelist for an Intel board ALSA: hda - More relax for pending period handling ALSA: hda - Define AC_FMT_* constants ALSA: hda - Fix beep frequency on IDT 92HD73xx and 92HD71Bxx codecs ALSA: hda - Add support for HDMI HBR passthrough ALSA: hda - Set Stream Type in Stream Format according to AES0 ALSA: hda - Fix Thinkpad X300 so SPDIF is not exposed ALSA: hda - FIX to not expose SPDIF on Thinkpad X301, since it does not have the ability to use SPDIF ASoC: wm9081: fix resource reclaim in wm9081_register error path ASoC: wm8978: fix a memory leak if a wm8978_register fail ASoC: wm8974: fix a memory leak if another WM8974 is registered ASoC: wm8961: fix resource reclaim in wm8961_register error path ASoC: wm8955: fix resource reclaim in wm8955_register error path ASoC: wm8940: fix a memory leak if wm8940_register return error ASoC: wm8904: fix resource reclaim in wm8904_register error path ...
Diffstat (limited to 'sound')
-rw-r--r--sound/core/pcm_lib.c25
-rw-r--r--sound/core/pcm_misc.c16
-rw-r--r--sound/drivers/Kconfig24
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c5
-rw-r--r--sound/isa/sb/emu8000_pcm.c9
-rw-r--r--sound/oss/au1550_ac97.c91
-rw-r--r--sound/oss/dmasound/dmasound_core.c63
-rw-r--r--sound/oss/midi_synth.c4
-rw-r--r--sound/oss/msnd_pinnacle.c35
-rw-r--r--sound/oss/sh_dac_audio.c27
-rw-r--r--sound/oss/soundcard.c20
-rw-r--r--sound/oss/swarm_cs4297a.c41
-rw-r--r--sound/oss/vidc.c3
-rw-r--r--sound/oss/vwsnd.c32
-rw-r--r--sound/oss/waveartist.c10
-rw-r--r--sound/pci/als4000.c4
-rw-r--r--sound/pci/asihpi/asihpi.c16
-rw-r--r--sound/pci/asihpi/hpi.h68
-rw-r--r--sound/pci/asihpi/hpi6000.c7
-rw-r--r--sound/pci/asihpi/hpi_internal.h40
-rw-r--r--sound/pci/asihpi/hpicmn.c10
-rw-r--r--sound/pci/asihpi/hpidebug.c2
-rw-r--r--sound/pci/asihpi/hpidebug.h4
-rw-r--r--sound/pci/asihpi/hpifunc.c327
-rw-r--r--sound/pci/asihpi/hpimsgx.c2
-rw-r--r--sound/pci/asihpi/hpioctl.c21
-rw-r--r--sound/pci/echoaudio/echoaudio.c2
-rw-r--r--sound/pci/hda/hda_codec.c97
-rw-r--r--sound/pci/hda/hda_codec.h32
-rw-r--r--sound/pci/hda/hda_hwdep.c4
-rw-r--r--sound/pci/hda/hda_intel.c5
-rw-r--r--sound/pci/hda/hda_proc.c7
-rw-r--r--sound/pci/hda/patch_analog.c7
-rw-r--r--sound/pci/hda/patch_conexant.c95
-rw-r--r--sound/pci/hda/patch_hdmi.c43
-rw-r--r--sound/pci/hda/patch_intelhdmi.c3
-rw-r--r--sound/pci/hda/patch_nvhdmi.c3
-rw-r--r--sound/pci/hda/patch_realtek.c720
-rw-r--r--sound/pci/hda/patch_sigmatel.c12
-rw-r--r--sound/pci/hda/patch_via.c32
-rw-r--r--sound/pci/riptide/riptide.c18
-rw-r--r--sound/pci/sis7019.c16
-rw-r--r--sound/pci/via82xx.c9
-rw-r--r--sound/soc/Kconfig4
-rw-r--r--sound/soc/Makefile4
-rw-r--r--sound/soc/atmel/atmel-pcm.c1
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c1
-rw-r--r--sound/soc/au1x/psc-ac97.c13
-rw-r--r--sound/soc/au1x/psc-i2s.c13
-rw-r--r--sound/soc/au1x/psc.h1
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c6
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c6
-rw-r--r--sound/soc/codecs/Kconfig20
-rw-r--r--sound/soc/codecs/Makefile6
-rw-r--r--sound/soc/codecs/ad1836.c1
-rw-r--r--sound/soc/codecs/ad193x.c41
-rw-r--r--sound/soc/codecs/ad193x.h5
-rw-r--r--sound/soc/codecs/ak4642.c36
-rw-r--r--sound/soc/codecs/cs42l51.c763
-rw-r--r--sound/soc/codecs/cs42l51.h163
-rw-r--r--sound/soc/codecs/da7210.c48
-rw-r--r--sound/soc/codecs/jz4740.c511
-rw-r--r--sound/soc/codecs/jz4740.h20
-rw-r--r--sound/soc/codecs/spdif_transciever.c94
-rw-r--r--sound/soc/codecs/spdif_transciever.h1
-rw-r--r--sound/soc/codecs/tlv320aic23.c7
-rw-r--r--sound/soc/codecs/tlv320dac33.c180
-rw-r--r--sound/soc/codecs/twl4030.c388
-rw-r--r--sound/soc/codecs/twl4030.h4
-rw-r--r--sound/soc/codecs/twl6040.c58
-rw-r--r--sound/soc/codecs/uda134x.c64
-rw-r--r--sound/soc/codecs/uda134x.h5
-rw-r--r--sound/soc/codecs/wm2000.c2
-rw-r--r--sound/soc/codecs/wm8523.c10
-rw-r--r--sound/soc/codecs/wm8711.c3
-rw-r--r--sound/soc/codecs/wm8741.c579
-rw-r--r--sound/soc/codecs/wm8741.h214
-rw-r--r--sound/soc/codecs/wm8750.c11
-rw-r--r--sound/soc/codecs/wm8904.c13
-rw-r--r--sound/soc/codecs/wm8940.c7
-rw-r--r--sound/soc/codecs/wm8955.c10
-rw-r--r--sound/soc/codecs/wm8960.c99
-rw-r--r--sound/soc/codecs/wm8961.c9
-rw-r--r--sound/soc/codecs/wm8974.c3
-rw-r--r--sound/soc/codecs/wm8978.c10
-rw-r--r--sound/soc/codecs/wm8990.c4
-rw-r--r--sound/soc/codecs/wm8994.c75
-rw-r--r--sound/soc/codecs/wm8994.h3
-rw-r--r--sound/soc/codecs/wm9081.c11
-rw-r--r--sound/soc/codecs/wm_hubs.c2
-rw-r--r--sound/soc/davinci/davinci-i2s.c163
-rw-r--r--sound/soc/davinci/davinci-i2s.h5
-rw-r--r--sound/soc/davinci/davinci-mcasp.c6
-rw-r--r--sound/soc/davinci/davinci-pcm.c7
-rw-r--r--sound/soc/davinci/davinci-pcm.h3
-rw-r--r--sound/soc/davinci/davinci-vcif.c2
-rw-r--r--sound/soc/ep93xx/Kconfig18
-rw-r--r--sound/soc/ep93xx/Makefile11
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c487
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.h18
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c319
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.h22
-rw-r--r--sound/soc/ep93xx/snappercl15.c150
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c1
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.h12
-rw-r--r--sound/soc/imx/Kconfig19
-rw-r--r--sound/soc/imx/Makefile2
-rw-r--r--sound/soc/imx/eukrea-tlv320.c137
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c6
-rw-r--r--sound/soc/imx/imx-pcm-fiq.c6
-rw-r--r--sound/soc/imx/imx-ssi.c11
-rw-r--r--sound/soc/jz4740/Kconfig23
-rw-r--r--sound/soc/jz4740/Makefile13
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c540
-rw-r--r--sound/soc/jz4740/jz4740-i2s.h18
-rw-r--r--sound/soc/jz4740/jz4740-pcm.c373
-rw-r--r--sound/soc/jz4740/jz4740-pcm.h22
-rw-r--r--sound/soc/jz4740/qi_lb60.c166
-rw-r--r--sound/soc/kirkwood/Kconfig20
-rw-r--r--sound/soc/kirkwood/Makefile9
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c383
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.h17
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c495
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.h17
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c126
-rw-r--r--sound/soc/kirkwood/kirkwood.h129
-rw-r--r--sound/soc/nuc900/Kconfig27
-rw-r--r--sound/soc/nuc900/Makefile11
-rw-r--r--sound/soc/nuc900/nuc900-ac97.c430
-rw-r--r--sound/soc/nuc900/nuc900-audio.c81
-rw-r--r--sound/soc/nuc900/nuc900-audio.h117
-rw-r--r--sound/soc/nuc900/nuc900-pcm.c354
-rw-r--r--sound/soc/omap/omap-mcbsp.c175
-rw-r--r--sound/soc/omap/omap3pandora.c36
-rw-r--r--sound/soc/omap/rx51.c73
-rw-r--r--sound/soc/s3c24xx/Kconfig10
-rw-r--r--sound/soc/s3c24xx/Makefile2
-rw-r--r--sound/soc/s3c24xx/s3c-ac97.c1
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c3
-rw-r--r--sound/soc/s3c24xx/smartq_wm8987.c295
-rw-r--r--sound/soc/s3c24xx/smdk_wm9713.c3
-rw-r--r--sound/soc/s6000/s6000-i2s.c38
-rw-r--r--sound/soc/sh/Kconfig4
-rw-r--r--sound/soc/sh/fsi-ak4642.c13
-rw-r--r--sound/soc/sh/fsi-da7210.c13
-rw-r--r--sound/soc/sh/fsi.c257
-rw-r--r--sound/soc/soc-core.c115
-rw-r--r--sound/sound_core.c9
-rw-r--r--sound/usb/card.c2
-rw-r--r--sound/usb/clock.c59
-rw-r--r--sound/usb/clock.h4
-rw-r--r--sound/usb/endpoint.c5
-rw-r--r--sound/usb/format.c9
-rw-r--r--sound/usb/midi.c14
-rw-r--r--sound/usb/mixer.c77
-rw-r--r--sound/usb/mixer.h1
-rw-r--r--sound/usb/pcm.h3
-rw-r--r--sound/usb/quirks-table.h30
-rw-r--r--sound/usb/quirks.c1
159 files changed, 10357 insertions, 1211 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index e9d98be190c5..e23e0e7ab26f 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -67,6 +67,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
67 } else { 67 } else {
68 if (new_hw_ptr == ULONG_MAX) { /* initialization */ 68 if (new_hw_ptr == ULONG_MAX) { /* initialization */
69 snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime); 69 snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime);
70 if (avail > runtime->buffer_size)
71 avail = runtime->buffer_size;
70 runtime->silence_filled = avail > 0 ? avail : 0; 72 runtime->silence_filled = avail > 0 ? avail : 0;
71 runtime->silence_start = (runtime->status->hw_ptr + 73 runtime->silence_start = (runtime->status->hw_ptr +
72 runtime->silence_filled) % 74 runtime->silence_filled) %
@@ -287,8 +289,11 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
287 return -EPIPE; 289 return -EPIPE;
288 } 290 }
289 } 291 }
290 if (avail >= runtime->control->avail_min) 292 if (runtime->twake) {
291 wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep); 293 if (avail >= runtime->twake)
294 wake_up(&runtime->tsleep);
295 } else if (avail >= runtime->control->avail_min)
296 wake_up(&runtime->sleep);
292 return 0; 297 return 0;
293} 298}
294 299
@@ -1707,7 +1712,7 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed);
1707 * The available space is stored on availp. When err = 0 and avail = 0 1712 * The available space is stored on availp. When err = 0 and avail = 0
1708 * on the capture stream, it indicates the stream is in DRAINING state. 1713 * on the capture stream, it indicates the stream is in DRAINING state.
1709 */ 1714 */
1710static int wait_for_avail_min(struct snd_pcm_substream *substream, 1715static int wait_for_avail(struct snd_pcm_substream *substream,
1711 snd_pcm_uframes_t *availp) 1716 snd_pcm_uframes_t *availp)
1712{ 1717{
1713 struct snd_pcm_runtime *runtime = substream->runtime; 1718 struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1757,7 +1762,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
1757 avail = snd_pcm_playback_avail(runtime); 1762 avail = snd_pcm_playback_avail(runtime);
1758 else 1763 else
1759 avail = snd_pcm_capture_avail(runtime); 1764 avail = snd_pcm_capture_avail(runtime);
1760 if (avail >= runtime->control->avail_min) 1765 if (avail >= runtime->twake)
1761 break; 1766 break;
1762 } 1767 }
1763 _endloop: 1768 _endloop:
@@ -1820,7 +1825,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
1820 goto _end_unlock; 1825 goto _end_unlock;
1821 } 1826 }
1822 1827
1823 runtime->twake = 1; 1828 runtime->twake = runtime->control->avail_min ? : 1;
1824 while (size > 0) { 1829 while (size > 0) {
1825 snd_pcm_uframes_t frames, appl_ptr, appl_ofs; 1830 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
1826 snd_pcm_uframes_t avail; 1831 snd_pcm_uframes_t avail;
@@ -1833,7 +1838,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
1833 err = -EAGAIN; 1838 err = -EAGAIN;
1834 goto _end_unlock; 1839 goto _end_unlock;
1835 } 1840 }
1836 err = wait_for_avail_min(substream, &avail); 1841 runtime->twake = min_t(snd_pcm_uframes_t, size,
1842 runtime->control->avail_min ? : 1);
1843 err = wait_for_avail(substream, &avail);
1837 if (err < 0) 1844 if (err < 0)
1838 goto _end_unlock; 1845 goto _end_unlock;
1839 } 1846 }
@@ -2042,7 +2049,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2042 goto _end_unlock; 2049 goto _end_unlock;
2043 } 2050 }
2044 2051
2045 runtime->twake = 1; 2052 runtime->twake = runtime->control->avail_min ? : 1;
2046 while (size > 0) { 2053 while (size > 0) {
2047 snd_pcm_uframes_t frames, appl_ptr, appl_ofs; 2054 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
2048 snd_pcm_uframes_t avail; 2055 snd_pcm_uframes_t avail;
@@ -2060,7 +2067,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2060 err = -EAGAIN; 2067 err = -EAGAIN;
2061 goto _end_unlock; 2068 goto _end_unlock;
2062 } 2069 }
2063 err = wait_for_avail_min(substream, &avail); 2070 runtime->twake = min_t(snd_pcm_uframes_t, size,
2071 runtime->control->avail_min ? : 1);
2072 err = wait_for_avail(substream, &avail);
2064 if (err < 0) 2073 if (err < 0)
2065 goto _end_unlock; 2074 goto _end_unlock;
2066 if (!avail) 2075 if (!avail)
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index ea2bf82c9373..434af3c56d52 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -128,6 +128,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
128 .width = 4, .phys = 4, .le = -1, .signd = -1, 128 .width = 4, .phys = 4, .le = -1, .signd = -1,
129 .silence = {}, 129 .silence = {},
130 }, 130 },
131 [SNDRV_PCM_FORMAT_G723_24] = {
132 .width = 3, .phys = 3, .le = -1, .signd = -1,
133 .silence = {},
134 },
135 [SNDRV_PCM_FORMAT_G723_40] = {
136 .width = 5, .phys = 5, .le = -1, .signd = -1,
137 .silence = {},
138 },
131 /* FIXME: the following three formats are not defined properly yet */ 139 /* FIXME: the following three formats are not defined properly yet */
132 [SNDRV_PCM_FORMAT_MPEG] = { 140 [SNDRV_PCM_FORMAT_MPEG] = {
133 .le = -1, .signd = -1, 141 .le = -1, .signd = -1,
@@ -186,6 +194,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
186 .width = 18, .phys = 24, .le = 0, .signd = 0, 194 .width = 18, .phys = 24, .le = 0, .signd = 0,
187 .silence = { 0x02, 0x00, 0x00 }, 195 .silence = { 0x02, 0x00, 0x00 },
188 }, 196 },
197 [SNDRV_PCM_FORMAT_G723_24_1B] = {
198 .width = 3, .phys = 8, .le = -1, .signd = -1,
199 .silence = {},
200 },
201 [SNDRV_PCM_FORMAT_G723_40_1B] = {
202 .width = 5, .phys = 8, .le = -1, .signd = -1,
203 .silence = {},
204 },
189}; 205};
190 206
191 207
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index c290cee4cee8..480c38623da8 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -170,9 +170,25 @@ config SND_AC97_POWER_SAVE
170 AC97 codecs. In this mode, the power-mode is dynamically 170 AC97 codecs. In this mode, the power-mode is dynamically
171 controlled at each open/close. 171 controlled at each open/close.
172 172
173 The mode is activated by passing power_save=1 option to 173 The mode is activated by passing 'power_save=X' to the
174 snd-ac97-codec driver. You can toggle it dynamically over 174 snd-ac97-codec driver module, where 'X' is the time-out
175 sysfs, too. 175 value, a nonnegative integer that specifies how many
176 seconds of idle time the driver must count before it may
177 put the AC97 into power-save mode; a value of 0 (zero)
178 disables the use of this power-save mode.
179
180 After the snd-ac97-codec driver module has been loaded,
181 the 'power_save' parameter can be set via sysfs as follows:
182
183 echo 10 > /sys/module/snd_ac97_codec/parameters/power_save
184
185 In this case, the time-out is set to 10 seconds; setting
186 the time-out to 1 second (the minimum activation value)
187 isn't recommended because many applications try to reopen
188 the device frequently. A value of 10 seconds would be a
189 good choice for normal operations.
190
191 See Documentation/sound/alsa/powersave.txt for more details.
176 192
177config SND_AC97_POWER_SAVE_DEFAULT 193config SND_AC97_POWER_SAVE_DEFAULT
178 int "Default time-out for AC97 power-save mode" 194 int "Default time-out for AC97 power-save mode"
@@ -182,4 +198,6 @@ config SND_AC97_POWER_SAVE_DEFAULT
182 The default time-out value in seconds for AC97 automatic 198 The default time-out value in seconds for AC97 automatic
183 power-save mode. 0 means to disable the power-save mode. 199 power-save mode. 0 means to disable the power-save mode.
184 200
201 See SND_AC97_POWER_SAVE for more details.
202
185endif # SND_DRIVERS 203endif # SND_DRIVERS
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 60b6abd71612..5f3e68401f90 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -549,7 +549,10 @@ static int __devinit snd_msnd_attach(struct snd_card *card)
549 printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); 549 printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
550 return err; 550 return err;
551 } 551 }
552 request_region(chip->io, DSP_NUMIO, card->shortname); 552 if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) {
553 free_irq(chip->irq, chip);
554 return -EBUSY;
555 }
553 556
554 if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) { 557 if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
555 printk(KERN_ERR LOGNAME 558 printk(KERN_ERR LOGNAME
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index ccedbfed061a..2f85c66f8e38 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -433,7 +433,8 @@ static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned sh
433 while (count > 0) { 433 while (count > 0) {
434 unsigned short sval; 434 unsigned short sval;
435 CHECK_SCHEDULER(); 435 CHECK_SCHEDULER();
436 get_user(sval, buf); 436 if (get_user(sval, buf))
437 return -EFAULT;
437 EMU8000_SMLD_WRITE(emu, sval); 438 EMU8000_SMLD_WRITE(emu, sval);
438 buf++; 439 buf++;
439 count--; 440 count--;
@@ -525,12 +526,14 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
525 while (count-- > 0) { 526 while (count-- > 0) {
526 unsigned short sval; 527 unsigned short sval;
527 CHECK_SCHEDULER(); 528 CHECK_SCHEDULER();
528 get_user(sval, buf); 529 if (get_user(sval, buf))
530 return -EFAULT;
529 EMU8000_SMLD_WRITE(emu, sval); 531 EMU8000_SMLD_WRITE(emu, sval);
530 buf++; 532 buf++;
531 if (rec->voices > 1) { 533 if (rec->voices > 1) {
532 CHECK_SCHEDULER(); 534 CHECK_SCHEDULER();
533 get_user(sval, buf); 535 if (get_user(sval, buf))
536 return -EFAULT;
534 EMU8000_SMRD_WRITE(emu, sval); 537 EMU8000_SMRD_WRITE(emu, sval);
535 buf++; 538 buf++;
536 } 539 }
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index c1070e33b32f..c4a4cdc07ab9 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -43,6 +43,7 @@
43#include <linux/sound.h> 43#include <linux/sound.h>
44#include <linux/slab.h> 44#include <linux/slab.h>
45#include <linux/soundcard.h> 45#include <linux/soundcard.h>
46#include <linux/smp_lock.h>
46#include <linux/init.h> 47#include <linux/init.h>
47#include <linux/interrupt.h> 48#include <linux/interrupt.h>
48#include <linux/kernel.h> 49#include <linux/kernel.h>
@@ -162,19 +163,10 @@ ld2(unsigned int x)
162static void 163static void
163au1550_delay(int msec) 164au1550_delay(int msec)
164{ 165{
165 unsigned long tmo;
166 signed long tmo2;
167
168 if (in_interrupt()) 166 if (in_interrupt())
169 return; 167 return;
170 168
171 tmo = jiffies + (msec * HZ) / 1000; 169 schedule_timeout_uninterruptible(msecs_to_jiffies(msec));
172 for (;;) {
173 tmo2 = tmo - jiffies;
174 if (tmo2 <= 0)
175 break;
176 schedule_timeout(tmo2);
177 }
178} 170}
179 171
180static u16 172static u16
@@ -807,7 +799,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin)
807static int 799static int
808au1550_open_mixdev(struct inode *inode, struct file *file) 800au1550_open_mixdev(struct inode *inode, struct file *file)
809{ 801{
802 lock_kernel();
810 file->private_data = &au1550_state; 803 file->private_data = &au1550_state;
804 unlock_kernel();
811 return 0; 805 return 0;
812} 806}
813 807
@@ -824,22 +818,26 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
824 return codec->mixer_ioctl(codec, cmd, arg); 818 return codec->mixer_ioctl(codec, cmd, arg);
825} 819}
826 820
827static int 821static long
828au1550_ioctl_mixdev(struct inode *inode, struct file *file, 822au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg)
829 unsigned int cmd, unsigned long arg)
830{ 823{
831 struct au1550_state *s = (struct au1550_state *)file->private_data; 824 struct au1550_state *s = (struct au1550_state *)file->private_data;
832 struct ac97_codec *codec = s->codec; 825 struct ac97_codec *codec = s->codec;
826 int ret;
833 827
834 return mixdev_ioctl(codec, cmd, arg); 828 lock_kernel();
829 ret = mixdev_ioctl(codec, cmd, arg);
830 unlock_kernel();
831
832 return ret;
835} 833}
836 834
837static /*const */ struct file_operations au1550_mixer_fops = { 835static /*const */ struct file_operations au1550_mixer_fops = {
838 owner:THIS_MODULE, 836 .owner = THIS_MODULE,
839 llseek:au1550_llseek, 837 .llseek = au1550_llseek,
840 ioctl:au1550_ioctl_mixdev, 838 .unlocked_ioctl = au1550_ioctl_mixdev,
841 open:au1550_open_mixdev, 839 .open = au1550_open_mixdev,
842 release:au1550_release_mixdev, 840 .release = au1550_release_mixdev,
843}; 841};
844 842
845static int 843static int
@@ -1343,8 +1341,7 @@ dma_count_done(struct dmabuf *db)
1343 1341
1344 1342
1345static int 1343static int
1346au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 1344au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1347 unsigned long arg)
1348{ 1345{
1349 struct au1550_state *s = (struct au1550_state *)file->private_data; 1346 struct au1550_state *s = (struct au1550_state *)file->private_data;
1350 unsigned long flags; 1347 unsigned long flags;
@@ -1780,6 +1777,17 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
1780 return mixdev_ioctl(s->codec, cmd, arg); 1777 return mixdev_ioctl(s->codec, cmd, arg);
1781} 1778}
1782 1779
1780static long
1781au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1782{
1783 int ret;
1784
1785 lock_kernel();
1786 ret = au1550_ioctl(file, cmd, arg);
1787 unlock_kernel();
1788
1789 return ret;
1790}
1783 1791
1784static int 1792static int
1785au1550_open(struct inode *inode, struct file *file) 1793au1550_open(struct inode *inode, struct file *file)
@@ -1797,21 +1805,22 @@ au1550_open(struct inode *inode, struct file *file)
1797#endif 1805#endif
1798 1806
1799 file->private_data = s; 1807 file->private_data = s;
1808 lock_kernel();
1800 /* wait for device to become free */ 1809 /* wait for device to become free */
1801 mutex_lock(&s->open_mutex); 1810 mutex_lock(&s->open_mutex);
1802 while (s->open_mode & file->f_mode) { 1811 while (s->open_mode & file->f_mode) {
1803 if (file->f_flags & O_NONBLOCK) { 1812 ret = -EBUSY;
1804 mutex_unlock(&s->open_mutex); 1813 if (file->f_flags & O_NONBLOCK)
1805 return -EBUSY; 1814 goto out;
1806 }
1807 add_wait_queue(&s->open_wait, &wait); 1815 add_wait_queue(&s->open_wait, &wait);
1808 __set_current_state(TASK_INTERRUPTIBLE); 1816 __set_current_state(TASK_INTERRUPTIBLE);
1809 mutex_unlock(&s->open_mutex); 1817 mutex_unlock(&s->open_mutex);
1810 schedule(); 1818 schedule();
1811 remove_wait_queue(&s->open_wait, &wait); 1819 remove_wait_queue(&s->open_wait, &wait);
1812 set_current_state(TASK_RUNNING); 1820 set_current_state(TASK_RUNNING);
1821 ret = -ERESTARTSYS;
1813 if (signal_pending(current)) 1822 if (signal_pending(current))
1814 return -ERESTARTSYS; 1823 goto out2;
1815 mutex_lock(&s->open_mutex); 1824 mutex_lock(&s->open_mutex);
1816 } 1825 }
1817 1826
@@ -1840,17 +1849,21 @@ au1550_open(struct inode *inode, struct file *file)
1840 1849
1841 if (file->f_mode & FMODE_READ) { 1850 if (file->f_mode & FMODE_READ) {
1842 if ((ret = prog_dmabuf_adc(s))) 1851 if ((ret = prog_dmabuf_adc(s)))
1843 return ret; 1852 goto out;
1844 } 1853 }
1845 if (file->f_mode & FMODE_WRITE) { 1854 if (file->f_mode & FMODE_WRITE) {
1846 if ((ret = prog_dmabuf_dac(s))) 1855 if ((ret = prog_dmabuf_dac(s)))
1847 return ret; 1856 goto out;
1848 } 1857 }
1849 1858
1850 s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); 1859 s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
1851 mutex_unlock(&s->open_mutex);
1852 mutex_init(&s->sem); 1860 mutex_init(&s->sem);
1853 return 0; 1861 ret = 0;
1862out:
1863 mutex_unlock(&s->open_mutex);
1864out2:
1865 unlock_kernel();
1866 return ret;
1854} 1867}
1855 1868
1856static int 1869static int
@@ -1885,15 +1898,15 @@ au1550_release(struct inode *inode, struct file *file)
1885} 1898}
1886 1899
1887static /*const */ struct file_operations au1550_audio_fops = { 1900static /*const */ struct file_operations au1550_audio_fops = {
1888 owner: THIS_MODULE, 1901 .owner = THIS_MODULE,
1889 llseek: au1550_llseek, 1902 .llseek = au1550_llseek,
1890 read: au1550_read, 1903 .read = au1550_read,
1891 write: au1550_write, 1904 .write = au1550_write,
1892 poll: au1550_poll, 1905 .poll = au1550_poll,
1893 ioctl: au1550_ioctl, 1906 .unlocked_ioctl = au1550_unlocked_ioctl,
1894 mmap: au1550_mmap, 1907 .mmap = au1550_mmap,
1895 open: au1550_open, 1908 .open = au1550_open,
1896 release: au1550_release, 1909 .release = au1550_release,
1897}; 1910};
1898 1911
1899MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com"); 1912MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index 3f3c3f71db4b..6ecd41abb066 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -323,9 +323,13 @@ static struct {
323 323
324static int mixer_open(struct inode *inode, struct file *file) 324static int mixer_open(struct inode *inode, struct file *file)
325{ 325{
326 if (!try_module_get(dmasound.mach.owner)) 326 lock_kernel();
327 if (!try_module_get(dmasound.mach.owner)) {
328 unlock_kernel();
327 return -ENODEV; 329 return -ENODEV;
330 }
328 mixer.busy = 1; 331 mixer.busy = 1;
332 unlock_kernel();
329 return 0; 333 return 0;
330} 334}
331 335
@@ -337,8 +341,8 @@ static int mixer_release(struct inode *inode, struct file *file)
337 unlock_kernel(); 341 unlock_kernel();
338 return 0; 342 return 0;
339} 343}
340static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, 344
341 u_long arg) 345static int mixer_ioctl(struct file *file, u_int cmd, u_long arg)
342{ 346{
343 if (_SIOC_DIR(cmd) & _SIOC_WRITE) 347 if (_SIOC_DIR(cmd) & _SIOC_WRITE)
344 mixer.modify_counter++; 348 mixer.modify_counter++;
@@ -362,11 +366,22 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
362 return -EINVAL; 366 return -EINVAL;
363} 367}
364 368
369static long mixer_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
370{
371 int ret;
372
373 lock_kernel();
374 ret = mixer_ioctl(file, cmd, arg);
375 unlock_kernel();
376
377 return ret;
378}
379
365static const struct file_operations mixer_fops = 380static const struct file_operations mixer_fops =
366{ 381{
367 .owner = THIS_MODULE, 382 .owner = THIS_MODULE,
368 .llseek = no_llseek, 383 .llseek = no_llseek,
369 .ioctl = mixer_ioctl, 384 .unlocked_ioctl = mixer_unlocked_ioctl,
370 .open = mixer_open, 385 .open = mixer_open,
371 .release = mixer_release, 386 .release = mixer_release,
372}; 387};
@@ -737,8 +752,11 @@ static int sq_open(struct inode *inode, struct file *file)
737{ 752{
738 int rc; 753 int rc;
739 754
740 if (!try_module_get(dmasound.mach.owner)) 755 lock_kernel();
756 if (!try_module_get(dmasound.mach.owner)) {
757 unlock_kernel();
741 return -ENODEV; 758 return -ENODEV;
759 }
742 760
743 rc = write_sq_open(file); /* checks the f_mode */ 761 rc = write_sq_open(file); /* checks the f_mode */
744 if (rc) 762 if (rc)
@@ -781,10 +799,11 @@ static int sq_open(struct inode *inode, struct file *file)
781 sound_set_format(AFMT_MU_LAW); 799 sound_set_format(AFMT_MU_LAW);
782 } 800 }
783#endif 801#endif
784 802 unlock_kernel();
785 return 0; 803 return 0;
786 out: 804 out:
787 module_put(dmasound.mach.owner); 805 module_put(dmasound.mach.owner);
806 unlock_kernel();
788 return rc; 807 return rc;
789} 808}
790 809
@@ -955,8 +974,7 @@ printk("dmasound_core: tried to set_queue_frags on a locked queue\n") ;
955 return 0 ; 974 return 0 ;
956} 975}
957 976
958static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, 977static int sq_ioctl(struct file *file, u_int cmd, u_long arg)
959 u_long arg)
960{ 978{
961 int val, result; 979 int val, result;
962 u_long fmt; 980 u_long fmt;
@@ -1114,18 +1132,29 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
1114 return IOCTL_OUT(arg,val); 1132 return IOCTL_OUT(arg,val);
1115 1133
1116 default: 1134 default:
1117 return mixer_ioctl(inode, file, cmd, arg); 1135 return mixer_ioctl(file, cmd, arg);
1118 } 1136 }
1119 return -EINVAL; 1137 return -EINVAL;
1120} 1138}
1121 1139
1140static long sq_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
1141{
1142 int ret;
1143
1144 lock_kernel();
1145 ret = sq_ioctl(file, cmd, arg);
1146 unlock_kernel();
1147
1148 return ret;
1149}
1150
1122static const struct file_operations sq_fops = 1151static const struct file_operations sq_fops =
1123{ 1152{
1124 .owner = THIS_MODULE, 1153 .owner = THIS_MODULE,
1125 .llseek = no_llseek, 1154 .llseek = no_llseek,
1126 .write = sq_write, 1155 .write = sq_write,
1127 .poll = sq_poll, 1156 .poll = sq_poll,
1128 .ioctl = sq_ioctl, 1157 .unlocked_ioctl = sq_unlocked_ioctl,
1129 .open = sq_open, 1158 .open = sq_open,
1130 .release = sq_release, 1159 .release = sq_release,
1131}; 1160};
@@ -1226,12 +1255,17 @@ static int state_open(struct inode *inode, struct file *file)
1226{ 1255{
1227 char *buffer = state.buf; 1256 char *buffer = state.buf;
1228 int len = 0; 1257 int len = 0;
1258 int ret;
1229 1259
1260 lock_kernel();
1261 ret = -EBUSY;
1230 if (state.busy) 1262 if (state.busy)
1231 return -EBUSY; 1263 goto out;
1232 1264
1265 ret = -ENODEV;
1233 if (!try_module_get(dmasound.mach.owner)) 1266 if (!try_module_get(dmasound.mach.owner))
1234 return -ENODEV; 1267 goto out;
1268
1235 state.ptr = 0; 1269 state.ptr = 0;
1236 state.busy = 1; 1270 state.busy = 1;
1237 1271
@@ -1293,7 +1327,10 @@ printk("dmasound: stat buffer used %d bytes\n", len) ;
1293 printk(KERN_ERR "dmasound_core: stat buffer overflowed!\n"); 1327 printk(KERN_ERR "dmasound_core: stat buffer overflowed!\n");
1294 1328
1295 state.len = len; 1329 state.len = len;
1296 return 0; 1330 ret = 0;
1331out:
1332 unlock_kernel();
1333 return ret;
1297} 1334}
1298 1335
1299static int state_release(struct inode *inode, struct file *file) 1336static int state_release(struct inode *inode, struct file *file)
diff --git a/sound/oss/midi_synth.c b/sound/oss/midi_synth.c
index 3bc7104c5379..3c09374ea5bf 100644
--- a/sound/oss/midi_synth.c
+++ b/sound/oss/midi_synth.c
@@ -523,7 +523,9 @@ midi_synth_load_patch(int dev, int format, const char __user *addr,
523 { 523 {
524 unsigned char data; 524 unsigned char data;
525 525
526 get_user(*(unsigned char *) &data, (unsigned char __user *) &((addr)[hdr_size + i])); 526 if (get_user(data,
527 (unsigned char __user *)(addr + hdr_size + i)))
528 return -EFAULT;
527 529
528 eox_seen = (i > 0 && data & 0x80); /* End of sysex */ 530 eox_seen = (i > 0 && data & 0x80); /* End of sysex */
529 531
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index a1e3f9671bea..2e48b17667d0 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -639,21 +639,26 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
639 return -EINVAL; 639 return -EINVAL;
640} 640}
641 641
642static int dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 642static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
643{ 643{
644 int minor = iminor(inode); 644 int minor = iminor(file->f_path.dentry->d_inode);
645 int ret;
645 646
646 if (cmd == OSS_GETVERSION) { 647 if (cmd == OSS_GETVERSION) {
647 int sound_version = SOUND_VERSION; 648 int sound_version = SOUND_VERSION;
648 return put_user(sound_version, (int __user *)arg); 649 return put_user(sound_version, (int __user *)arg);
649 } 650 }
650 651
652 ret = -EINVAL;
653
654 lock_kernel();
651 if (minor == dev.dsp_minor) 655 if (minor == dev.dsp_minor)
652 return dsp_ioctl(file, cmd, arg); 656 ret = dsp_ioctl(file, cmd, arg);
653 else if (minor == dev.mixer_minor) 657 else if (minor == dev.mixer_minor)
654 return mixer_ioctl(cmd, arg); 658 ret = mixer_ioctl(cmd, arg);
659 unlock_kernel();
655 660
656 return -EINVAL; 661 return ret;
657} 662}
658 663
659static void dsp_write_flush(void) 664static void dsp_write_flush(void)
@@ -756,12 +761,15 @@ static int dev_open(struct inode *inode, struct file *file)
756 int minor = iminor(inode); 761 int minor = iminor(inode);
757 int err = 0; 762 int err = 0;
758 763
764 lock_kernel();
759 if (minor == dev.dsp_minor) { 765 if (minor == dev.dsp_minor) {
760 if ((file->f_mode & FMODE_WRITE && 766 if ((file->f_mode & FMODE_WRITE &&
761 test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) || 767 test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) ||
762 (file->f_mode & FMODE_READ && 768 (file->f_mode & FMODE_READ &&
763 test_bit(F_AUDIO_READ_INUSE, &dev.flags))) 769 test_bit(F_AUDIO_READ_INUSE, &dev.flags))) {
764 return -EBUSY; 770 err = -EBUSY;
771 goto out;
772 }
765 773
766 if ((err = dsp_open(file)) >= 0) { 774 if ((err = dsp_open(file)) >= 0) {
767 dev.nresets = 0; 775 dev.nresets = 0;
@@ -782,7 +790,8 @@ static int dev_open(struct inode *inode, struct file *file)
782 /* nothing */ 790 /* nothing */
783 } else 791 } else
784 err = -EINVAL; 792 err = -EINVAL;
785 793out:
794 unlock_kernel();
786 return err; 795 return err;
787} 796}
788 797
@@ -1105,7 +1114,7 @@ static const struct file_operations dev_fileops = {
1105 .owner = THIS_MODULE, 1114 .owner = THIS_MODULE,
1106 .read = dev_read, 1115 .read = dev_read,
1107 .write = dev_write, 1116 .write = dev_write,
1108 .ioctl = dev_ioctl, 1117 .unlocked_ioctl = dev_ioctl,
1109 .open = dev_open, 1118 .open = dev_open,
1110 .release = dev_release, 1119 .release = dev_release,
1111}; 1120};
@@ -1391,9 +1400,13 @@ static int __init attach_multisound(void)
1391 printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq); 1400 printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq);
1392 return err; 1401 return err;
1393 } 1402 }
1394 request_region(dev.io, dev.numio, dev.name); 1403 if (request_region(dev.io, dev.numio, dev.name) == NULL) {
1404 free_irq(dev.irq, &dev);
1405 return -EBUSY;
1406 }
1395 1407
1396 if ((err = dsp_full_reset()) < 0) { 1408 err = dsp_full_reset();
1409 if (err < 0) {
1397 release_region(dev.io, dev.numio); 1410 release_region(dev.io, dev.numio);
1398 free_irq(dev.irq, &dev); 1411 free_irq(dev.irq, &dev);
1399 return err; 1412 return err;
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index 4153752507e3..fdb58eb83d4e 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -15,7 +15,9 @@
15#include <linux/linkage.h> 15#include <linux/linkage.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/smp_lock.h>
18#include <linux/sound.h> 19#include <linux/sound.h>
20#include <linux/smp_lock.h>
19#include <linux/soundcard.h> 21#include <linux/soundcard.h>
20#include <linux/interrupt.h> 22#include <linux/interrupt.h>
21#include <linux/hrtimer.h> 23#include <linux/hrtimer.h>
@@ -92,7 +94,7 @@ static void dac_audio_set_rate(void)
92 wakeups_per_second = ktime_set(0, 1000000000 / rate); 94 wakeups_per_second = ktime_set(0, 1000000000 / rate);
93} 95}
94 96
95static int dac_audio_ioctl(struct inode *inode, struct file *file, 97static int dac_audio_ioctl(struct file *file,
96 unsigned int cmd, unsigned long arg) 98 unsigned int cmd, unsigned long arg)
97{ 99{
98 int val; 100 int val;
@@ -158,6 +160,17 @@ static int dac_audio_ioctl(struct inode *inode, struct file *file,
158 return -EINVAL; 160 return -EINVAL;
159} 161}
160 162
163static long dac_audio_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
164{
165 int ret;
166
167 lock_kernel();
168 ret = dac_audio_ioctl(file, cmd, arg);
169 unlock_kernel();
170
171 return ret;
172}
173
161static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count, 174static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
162 loff_t * ppos) 175 loff_t * ppos)
163{ 176{
@@ -216,13 +229,17 @@ static int dac_audio_open(struct inode *inode, struct file *file)
216{ 229{
217 if (file->f_mode & FMODE_READ) 230 if (file->f_mode & FMODE_READ)
218 return -ENODEV; 231 return -ENODEV;
219 if (in_use) 232
233 lock_kernel();
234 if (in_use) {
235 unlock_kernel();
220 return -EBUSY; 236 return -EBUSY;
237 }
221 238
222 in_use = 1; 239 in_use = 1;
223 240
224 dac_audio_start(); 241 dac_audio_start();
225 242 unlock_kernel();
226 return 0; 243 return 0;
227} 244}
228 245
@@ -237,8 +254,8 @@ static int dac_audio_release(struct inode *inode, struct file *file)
237 254
238const struct file_operations dac_audio_fops = { 255const struct file_operations dac_audio_fops = {
239 .read = dac_audio_read, 256 .read = dac_audio_read,
240 .write = dac_audio_write, 257 .write = dac_audio_write,
241 .ioctl = dac_audio_ioctl, 258 .unlocked_ioctl = dac_audio_unlocked_ioctl,
242 .open = dac_audio_open, 259 .open = dac_audio_open,
243 .release = dac_audio_release, 260 .release = dac_audio_release,
244}; 261};
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 2d9c51312622..92aa762ffb7e 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -210,42 +210,44 @@ static int sound_open(struct inode *inode, struct file *file)
210 printk(KERN_ERR "Invalid minor device %d\n", dev); 210 printk(KERN_ERR "Invalid minor device %d\n", dev);
211 return -ENXIO; 211 return -ENXIO;
212 } 212 }
213 lock_kernel();
213 switch (dev & 0x0f) { 214 switch (dev & 0x0f) {
214 case SND_DEV_CTL: 215 case SND_DEV_CTL:
215 dev >>= 4; 216 dev >>= 4;
216 if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { 217 if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) {
217 request_module("mixer%d", dev); 218 request_module("mixer%d", dev);
218 } 219 }
220 retval = -ENXIO;
219 if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL)) 221 if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL))
220 return -ENXIO; 222 break;
221 223
222 if (!try_module_get(mixer_devs[dev]->owner)) 224 if (!try_module_get(mixer_devs[dev]->owner))
223 return -ENXIO; 225 break;
226
227 retval = 0;
224 break; 228 break;
225 229
226 case SND_DEV_SEQ: 230 case SND_DEV_SEQ:
227 case SND_DEV_SEQ2: 231 case SND_DEV_SEQ2:
228 if ((retval = sequencer_open(dev, file)) < 0) 232 retval = sequencer_open(dev, file);
229 return retval;
230 break; 233 break;
231 234
232 case SND_DEV_MIDIN: 235 case SND_DEV_MIDIN:
233 if ((retval = MIDIbuf_open(dev, file)) < 0) 236 retval = MIDIbuf_open(dev, file);
234 return retval;
235 break; 237 break;
236 238
237 case SND_DEV_DSP: 239 case SND_DEV_DSP:
238 case SND_DEV_DSP16: 240 case SND_DEV_DSP16:
239 case SND_DEV_AUDIO: 241 case SND_DEV_AUDIO:
240 if ((retval = audio_open(dev, file)) < 0) 242 retval = audio_open(dev, file);
241 return retval;
242 break; 243 break;
243 244
244 default: 245 default:
245 printk(KERN_ERR "Invalid minor device %d\n", dev); 246 printk(KERN_ERR "Invalid minor device %d\n", dev);
246 return -ENXIO; 247 retval = -ENXIO;
247 } 248 }
248 249
250 unlock_kernel();
249 return 0; 251 return 0;
250} 252}
251 253
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index 3136c88eacdf..b15840ad2527 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -68,6 +68,7 @@
68#include <linux/delay.h> 68#include <linux/delay.h>
69#include <linux/sound.h> 69#include <linux/sound.h>
70#include <linux/slab.h> 70#include <linux/slab.h>
71#include <linux/smp_lock.h>
71#include <linux/soundcard.h> 72#include <linux/soundcard.h>
72#include <linux/ac97_codec.h> 73#include <linux/ac97_codec.h>
73#include <linux/pci.h> 74#include <linux/pci.h>
@@ -1534,6 +1535,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
1534 CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, 1535 CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
1535 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n")); 1536 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n"));
1536 1537
1538 lock_kernel();
1537 list_for_each(entry, &cs4297a_devs) 1539 list_for_each(entry, &cs4297a_devs)
1538 { 1540 {
1539 s = list_entry(entry, struct cs4297a_state, list); 1541 s = list_entry(entry, struct cs4297a_state, list);
@@ -1544,6 +1546,8 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
1544 { 1546 {
1545 CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, 1547 CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
1546 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n")); 1548 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n"));
1549
1550 unlock_kernel();
1547 return -ENODEV; 1551 return -ENODEV;
1548 } 1552 }
1549 VALIDATE_STATE(s); 1553 VALIDATE_STATE(s);
@@ -1551,6 +1555,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
1551 1555
1552 CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, 1556 CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
1553 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n")); 1557 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n"));
1558 unlock_kernel();
1554 1559
1555 return nonseekable_open(inode, file); 1560 return nonseekable_open(inode, file);
1556} 1561}
@@ -1566,11 +1571,15 @@ static int cs4297a_release_mixdev(struct inode *inode, struct file *file)
1566} 1571}
1567 1572
1568 1573
1569static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file, 1574static int cs4297a_ioctl_mixdev(struct file *file,
1570 unsigned int cmd, unsigned long arg) 1575 unsigned int cmd, unsigned long arg)
1571{ 1576{
1572 return mixer_ioctl((struct cs4297a_state *) file->private_data, cmd, 1577 int ret;
1578 lock_kernel();
1579 ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd,
1573 arg); 1580 arg);
1581 unlock_kernel();
1582 return ret;
1574} 1583}
1575 1584
1576 1585
@@ -1580,7 +1589,7 @@ static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file,
1580static const struct file_operations cs4297a_mixer_fops = { 1589static const struct file_operations cs4297a_mixer_fops = {
1581 .owner = THIS_MODULE, 1590 .owner = THIS_MODULE,
1582 .llseek = no_llseek, 1591 .llseek = no_llseek,
1583 .ioctl = cs4297a_ioctl_mixdev, 1592 .unlocked_ioctl = cs4297a_ioctl_mixdev,
1584 .open = cs4297a_open_mixdev, 1593 .open = cs4297a_open_mixdev,
1585 .release = cs4297a_release_mixdev, 1594 .release = cs4297a_release_mixdev,
1586}; 1595};
@@ -1944,7 +1953,7 @@ static int cs4297a_mmap(struct file *file, struct vm_area_struct *vma)
1944} 1953}
1945 1954
1946 1955
1947static int cs4297a_ioctl(struct inode *inode, struct file *file, 1956static int cs4297a_ioctl(struct file *file,
1948 unsigned int cmd, unsigned long arg) 1957 unsigned int cmd, unsigned long arg)
1949{ 1958{
1950 struct cs4297a_state *s = 1959 struct cs4297a_state *s =
@@ -2337,6 +2346,16 @@ static int cs4297a_ioctl(struct inode *inode, struct file *file,
2337 return mixer_ioctl(s, cmd, arg); 2346 return mixer_ioctl(s, cmd, arg);
2338} 2347}
2339 2348
2349static long cs4297a_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
2350{
2351 int ret;
2352
2353 lock_kernel();
2354 ret = cs4297a_ioctl(file, cmd, arg);
2355 unlock_kernel();
2356
2357 return ret;
2358}
2340 2359
2341static int cs4297a_release(struct inode *inode, struct file *file) 2360static int cs4297a_release(struct inode *inode, struct file *file)
2342{ 2361{
@@ -2369,7 +2388,7 @@ static int cs4297a_release(struct inode *inode, struct file *file)
2369 return 0; 2388 return 0;
2370} 2389}
2371 2390
2372static int cs4297a_open(struct inode *inode, struct file *file) 2391static int cs4297a_locked_open(struct inode *inode, struct file *file)
2373{ 2392{
2374 int minor = iminor(inode); 2393 int minor = iminor(inode);
2375 struct cs4297a_state *s=NULL; 2394 struct cs4297a_state *s=NULL;
@@ -2486,6 +2505,16 @@ static int cs4297a_open(struct inode *inode, struct file *file)
2486 return nonseekable_open(inode, file); 2505 return nonseekable_open(inode, file);
2487} 2506}
2488 2507
2508static int cs4297a_open(struct inode *inode, struct file *file)
2509{
2510 int ret;
2511
2512 lock_kernel();
2513 ret = cs4297a_open(inode, file);
2514 unlock_kernel();
2515
2516 return ret;
2517}
2489 2518
2490// ****************************************************************************************** 2519// ******************************************************************************************
2491// Wave (audio) file operations struct. 2520// Wave (audio) file operations struct.
@@ -2496,7 +2525,7 @@ static const struct file_operations cs4297a_audio_fops = {
2496 .read = cs4297a_read, 2525 .read = cs4297a_read,
2497 .write = cs4297a_write, 2526 .write = cs4297a_write,
2498 .poll = cs4297a_poll, 2527 .poll = cs4297a_poll,
2499 .ioctl = cs4297a_ioctl, 2528 .unlocked_ioctl = cs4297a_unlocked_ioctl,
2500 .mmap = cs4297a_mmap, 2529 .mmap = cs4297a_mmap,
2501 .open = cs4297a_open, 2530 .open = cs4297a_open,
2502 .release = cs4297a_release, 2531 .release = cs4297a_release,
diff --git a/sound/oss/vidc.c b/sound/oss/vidc.c
index ac39a531df19..f0e0caa53200 100644
--- a/sound/oss/vidc.c
+++ b/sound/oss/vidc.c
@@ -491,9 +491,6 @@ static void __init attach_vidc(struct address_info *hw_config)
491 vidc_adev = adev; 491 vidc_adev = adev;
492 vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8)); 492 vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
493 493
494#if defined(CONFIG_SOUND_SOFTOSS) || defined(CONFIG_SOUND_SOFTOSS_MODULE)
495 softoss_dev = adev;
496#endif
497 return; 494 return;
498 495
499irq_failed: 496irq_failed:
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
index 20b3b325aa80..8cd73cdd88af 100644
--- a/sound/oss/vwsnd.c
+++ b/sound/oss/vwsnd.c
@@ -2429,8 +2429,7 @@ static unsigned int vwsnd_audio_poll(struct file *file,
2429 return mask; 2429 return mask;
2430} 2430}
2431 2431
2432static int vwsnd_audio_do_ioctl(struct inode *inode, 2432static int vwsnd_audio_do_ioctl(struct file *file,
2433 struct file *file,
2434 unsigned int cmd, 2433 unsigned int cmd,
2435 unsigned long arg) 2434 unsigned long arg)
2436{ 2435{
@@ -2446,8 +2445,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode,
2446 int ival; 2445 int ival;
2447 2446
2448 2447
2449 DBGEV("(inode=0x%p, file=0x%p, cmd=0x%x, arg=0x%lx)\n", 2448 DBGEV("(file=0x%p, cmd=0x%x, arg=0x%lx)\n",
2450 inode, file, cmd, arg); 2449 file, cmd, arg);
2451 switch (cmd) { 2450 switch (cmd) {
2452 case OSS_GETVERSION: /* _SIOR ('M', 118, int) */ 2451 case OSS_GETVERSION: /* _SIOR ('M', 118, int) */
2453 DBGX("OSS_GETVERSION\n"); 2452 DBGX("OSS_GETVERSION\n");
@@ -2885,17 +2884,19 @@ static int vwsnd_audio_do_ioctl(struct inode *inode,
2885 return -EINVAL; 2884 return -EINVAL;
2886} 2885}
2887 2886
2888static int vwsnd_audio_ioctl(struct inode *inode, 2887static long vwsnd_audio_ioctl(struct file *file,
2889 struct file *file,
2890 unsigned int cmd, 2888 unsigned int cmd,
2891 unsigned long arg) 2889 unsigned long arg)
2892{ 2890{
2893 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data; 2891 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
2894 int ret; 2892 int ret;
2895 2893
2894 lock_kernel();
2896 mutex_lock(&devc->io_mutex); 2895 mutex_lock(&devc->io_mutex);
2897 ret = vwsnd_audio_do_ioctl(inode, file, cmd, arg); 2896 ret = vwsnd_audio_do_ioctl(file, cmd, arg);
2898 mutex_unlock(&devc->io_mutex); 2897 mutex_unlock(&devc->io_mutex);
2898 unlock_kernel();
2899
2899 return ret; 2900 return ret;
2900} 2901}
2901 2902
@@ -2921,6 +2922,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
2921 2922
2922 DBGE("(inode=0x%p, file=0x%p)\n", inode, file); 2923 DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
2923 2924
2925 lock_kernel();
2924 INC_USE_COUNT; 2926 INC_USE_COUNT;
2925 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev) 2927 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
2926 if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F)) 2928 if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
@@ -2928,6 +2930,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
2928 2930
2929 if (devc == NULL) { 2931 if (devc == NULL) {
2930 DEC_USE_COUNT; 2932 DEC_USE_COUNT;
2933 unlock_kernel();
2931 return -ENODEV; 2934 return -ENODEV;
2932 } 2935 }
2933 2936
@@ -2936,11 +2939,13 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
2936 mutex_unlock(&devc->open_mutex); 2939 mutex_unlock(&devc->open_mutex);
2937 if (file->f_flags & O_NONBLOCK) { 2940 if (file->f_flags & O_NONBLOCK) {
2938 DEC_USE_COUNT; 2941 DEC_USE_COUNT;
2942 unlock_kernel();
2939 return -EBUSY; 2943 return -EBUSY;
2940 } 2944 }
2941 interruptible_sleep_on(&devc->open_wait); 2945 interruptible_sleep_on(&devc->open_wait);
2942 if (signal_pending(current)) { 2946 if (signal_pending(current)) {
2943 DEC_USE_COUNT; 2947 DEC_USE_COUNT;
2948 unlock_kernel();
2944 return -ERESTARTSYS; 2949 return -ERESTARTSYS;
2945 } 2950 }
2946 mutex_lock(&devc->open_mutex); 2951 mutex_lock(&devc->open_mutex);
@@ -2993,6 +2998,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
2993 2998
2994 file->private_data = devc; 2999 file->private_data = devc;
2995 DBGRV(); 3000 DBGRV();
3001 unlock_kernel();
2996 return 0; 3002 return 0;
2997} 3003}
2998 3004
@@ -3044,7 +3050,7 @@ static const struct file_operations vwsnd_audio_fops = {
3044 .read = vwsnd_audio_read, 3050 .read = vwsnd_audio_read,
3045 .write = vwsnd_audio_write, 3051 .write = vwsnd_audio_write,
3046 .poll = vwsnd_audio_poll, 3052 .poll = vwsnd_audio_poll,
3047 .ioctl = vwsnd_audio_ioctl, 3053 .unlocked_ioctl = vwsnd_audio_ioctl,
3048 .mmap = vwsnd_audio_mmap, 3054 .mmap = vwsnd_audio_mmap,
3049 .open = vwsnd_audio_open, 3055 .open = vwsnd_audio_open,
3050 .release = vwsnd_audio_release, 3056 .release = vwsnd_audio_release,
@@ -3062,15 +3068,18 @@ static int vwsnd_mixer_open(struct inode *inode, struct file *file)
3062 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file); 3068 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
3063 3069
3064 INC_USE_COUNT; 3070 INC_USE_COUNT;
3071 lock_kernel();
3065 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev) 3072 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
3066 if (devc->mixer_minor == iminor(inode)) 3073 if (devc->mixer_minor == iminor(inode))
3067 break; 3074 break;
3068 3075
3069 if (devc == NULL) { 3076 if (devc == NULL) {
3070 DEC_USE_COUNT; 3077 DEC_USE_COUNT;
3078 unlock_kernel();
3071 return -ENODEV; 3079 return -ENODEV;
3072 } 3080 }
3073 file->private_data = devc; 3081 file->private_data = devc;
3082 unlock_kernel();
3074 return 0; 3083 return 0;
3075} 3084}
3076 3085
@@ -3203,8 +3212,7 @@ static int mixer_write_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *ar
3203 3212
3204/* This is the ioctl entry to the mixer driver. */ 3213/* This is the ioctl entry to the mixer driver. */
3205 3214
3206static int vwsnd_mixer_ioctl(struct inode *ioctl, 3215static long vwsnd_mixer_ioctl(struct file *file,
3207 struct file *file,
3208 unsigned int cmd, 3216 unsigned int cmd,
3209 unsigned long arg) 3217 unsigned long arg)
3210{ 3218{
@@ -3215,6 +3223,7 @@ static int vwsnd_mixer_ioctl(struct inode *ioctl,
3215 3223
3216 DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg); 3224 DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
3217 3225
3226 lock_kernel();
3218 mutex_lock(&devc->mix_mutex); 3227 mutex_lock(&devc->mix_mutex);
3219 { 3228 {
3220 if ((cmd & ~nrmask) == MIXER_READ(0)) 3229 if ((cmd & ~nrmask) == MIXER_READ(0))
@@ -3225,13 +3234,14 @@ static int vwsnd_mixer_ioctl(struct inode *ioctl,
3225 retval = -EINVAL; 3234 retval = -EINVAL;
3226 } 3235 }
3227 mutex_unlock(&devc->mix_mutex); 3236 mutex_unlock(&devc->mix_mutex);
3237 unlock_kernel();
3228 return retval; 3238 return retval;
3229} 3239}
3230 3240
3231static const struct file_operations vwsnd_mixer_fops = { 3241static const struct file_operations vwsnd_mixer_fops = {
3232 .owner = THIS_MODULE, 3242 .owner = THIS_MODULE,
3233 .llseek = no_llseek, 3243 .llseek = no_llseek,
3234 .ioctl = vwsnd_mixer_ioctl, 3244 .unlocked_ioctl = vwsnd_mixer_ioctl,
3235 .open = vwsnd_mixer_open, 3245 .open = vwsnd_mixer_open,
3236 .release = vwsnd_mixer_release, 3246 .release = vwsnd_mixer_release,
3237}; 3247};
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
index e688dde6bbde..52468742d9f2 100644
--- a/sound/oss/waveartist.c
+++ b/sound/oss/waveartist.c
@@ -184,14 +184,8 @@ waveartist_iack(wavnc_info *devc)
184static inline int 184static inline int
185waveartist_sleep(int timeout_ms) 185waveartist_sleep(int timeout_ms)
186{ 186{
187 unsigned int timeout = timeout_ms * 10 * HZ / 100; 187 unsigned int timeout = msecs_to_jiffies(timeout_ms*100);
188 188 return schedule_timeout_interruptible(timeout);
189 do {
190 set_current_state(TASK_INTERRUPTIBLE);
191 timeout = schedule_timeout(timeout);
192 } while (timeout);
193
194 return 0;
195} 189}
196 190
197static int 191static int
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 6cf1de8042e8..0e247cb90ecc 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -763,9 +763,9 @@ static void snd_als4000_configure(struct snd_sb *chip)
763 /* SPECS_PAGE: 39 */ 763 /* SPECS_PAGE: 39 */
764 for (i = ALS4K_GCR91_DMA0_ADDR; i <= ALS4K_GCR96_DMA3_MODE_COUNT; ++i) 764 for (i = ALS4K_GCR91_DMA0_ADDR; i <= ALS4K_GCR96_DMA3_MODE_COUNT; ++i)
765 snd_als4k_gcr_write(chip, i, 0); 765 snd_als4k_gcr_write(chip, i, 0);
766 766 /* enable burst mode to prevent dropouts during high PCI bus usage */
767 snd_als4k_gcr_write(chip, ALS4K_GCR99_DMA_EMULATION_CTRL, 767 snd_als4k_gcr_write(chip, ALS4K_GCR99_DMA_EMULATION_CTRL,
768 snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL)); 768 (snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL) & ~0x07) | 0x04);
769 spin_unlock_irq(&chip->reg_lock); 769 spin_unlock_irq(&chip->reg_lock);
770} 770}
771 771
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index 1db586af4f9c..c80b0b863c54 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -460,6 +460,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
460 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 460 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
461 int err; 461 int err;
462 u16 format; 462 u16 format;
463 int width;
463 unsigned int bytes_per_sec; 464 unsigned int bytes_per_sec;
464 465
465 print_hwparams(params); 466 print_hwparams(params);
@@ -512,9 +513,10 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
512 dpcm->hpi_buffer_attached); 513 dpcm->hpi_buffer_attached);
513 } 514 }
514 bytes_per_sec = params_rate(params) * params_channels(params); 515 bytes_per_sec = params_rate(params) * params_channels(params);
515 bytes_per_sec *= snd_pcm_format_width(params_format(params)); 516 width = snd_pcm_format_width(params_format(params));
517 bytes_per_sec *= width;
516 bytes_per_sec /= 8; 518 bytes_per_sec /= 8;
517 if (bytes_per_sec <= 0) 519 if (width < 0 || bytes_per_sec == 0)
518 return -EINVAL; 520 return -EINVAL;
519 521
520 dpcm->bytes_per_sec = bytes_per_sec; 522 dpcm->bytes_per_sec = bytes_per_sec;
@@ -1383,7 +1385,7 @@ static char *asihpi_src_names[] =
1383 1385
1384compile_time_assert( 1386compile_time_assert(
1385 (ARRAY_SIZE(asihpi_src_names) == 1387 (ARRAY_SIZE(asihpi_src_names) ==
1386 (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_BASE+1)), 1388 (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)),
1387 assert_src_names_size); 1389 assert_src_names_size);
1388 1390
1389#if ASI_STYLE_NAMES 1391#if ASI_STYLE_NAMES
@@ -1414,7 +1416,7 @@ static char *asihpi_dst_names[] =
1414 1416
1415compile_time_assert( 1417compile_time_assert(
1416 (ARRAY_SIZE(asihpi_dst_names) == 1418 (ARRAY_SIZE(asihpi_dst_names) ==
1417 (HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_BASE+1)), 1419 (HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_NONE+1)),
1418 assert_dst_names_size); 1420 assert_dst_names_size);
1419 1421
1420static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl, 1422static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl,
@@ -2171,7 +2173,7 @@ static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol,
2171 &src_node_type, &src_node_index); 2173 &src_node_type, &src_node_index);
2172 2174
2173 sprintf(uinfo->value.enumerated.name, "%s %d", 2175 sprintf(uinfo->value.enumerated.name, "%s %d",
2174 asihpi_src_names[src_node_type - HPI_SOURCENODE_BASE], 2176 asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE],
2175 src_node_index); 2177 src_node_index);
2176 return 0; 2178 return 0;
2177} 2179}
@@ -2603,8 +2605,8 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
2603 2605
2604 } 2606 }
2605 2607
2606 hpi_ctl.src_node_type -= HPI_SOURCENODE_BASE; 2608 hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE;
2607 hpi_ctl.dst_node_type -= HPI_DESTNODE_BASE; 2609 hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE;
2608 2610
2609 /* ASI50xx in SSX mode has multiple meters on the same node. 2611 /* ASI50xx in SSX mode has multiple meters on the same node.
2610 Use subindex to create distinct ALSA controls 2612 Use subindex to create distinct ALSA controls
diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h
index 0173bbe62b67..23399d02f666 100644
--- a/sound/pci/asihpi/hpi.h
+++ b/sound/pci/asihpi/hpi.h
@@ -50,7 +50,8 @@ i.e 3.05.02 is a development version
50#define HPI_VER_RELEASE(v) ((int)(v & 0xFF)) 50#define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
51 51
52/* Use single digits for versions less that 10 to avoid octal. */ 52/* Use single digits for versions less that 10 to avoid octal. */
53#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 3, 25) 53#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 4, 1)
54#define HPI_VER_STRING "4.04.01"
54 55
55/* Library version as documented in hpi-api-versions.txt */ 56/* Library version as documented in hpi-api-versions.txt */
56#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0) 57#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0)
@@ -203,8 +204,6 @@ enum HPI_SOURCENODES {
203 exists on a destination node can be searched for using a source 204 exists on a destination node can be searched for using a source
204 node value of either 0, or HPI_SOURCENODE_NONE */ 205 node value of either 0, or HPI_SOURCENODE_NONE */
205 HPI_SOURCENODE_NONE = 100, 206 HPI_SOURCENODE_NONE = 100,
206 /** \deprecated Use HPI_SOURCENODE_NONE instead. */
207 HPI_SOURCENODE_BASE = 100,
208 /** Out Stream (Play) node. */ 207 /** Out Stream (Play) node. */
209 HPI_SOURCENODE_OSTREAM = 101, 208 HPI_SOURCENODE_OSTREAM = 101,
210 /** Line in node - could be analog, AES/EBU or network. */ 209 /** Line in node - could be analog, AES/EBU or network. */
@@ -235,8 +234,6 @@ enum HPI_DESTNODES {
235 exists on a source node can be searched for using a destination 234 exists on a source node can be searched for using a destination
236 node value of either 0, or HPI_DESTNODE_NONE */ 235 node value of either 0, or HPI_DESTNODE_NONE */
237 HPI_DESTNODE_NONE = 200, 236 HPI_DESTNODE_NONE = 200,
238 /** \deprecated Use HPI_DESTNODE_NONE instead. */
239 HPI_DESTNODE_BASE = 200,
240 /** In Stream (Record) node. */ 237 /** In Stream (Record) node. */
241 HPI_DESTNODE_ISTREAM = 201, 238 HPI_DESTNODE_ISTREAM = 201,
242 HPI_DESTNODE_LINEOUT = 202, /**< line out node. */ 239 HPI_DESTNODE_LINEOUT = 202, /**< line out node. */
@@ -432,7 +429,18 @@ Property 2 - adapter can do stream grouping (supports SSX2)
432Property 1 - adapter can do samplerate conversion (MRX) 429Property 1 - adapter can do samplerate conversion (MRX)
433Property 2 - adapter can do timestretch (TSX) 430Property 2 - adapter can do timestretch (TSX)
434*/ 431*/
435 HPI_ADAPTER_PROPERTY_CAPS2 = 269 432 HPI_ADAPTER_PROPERTY_CAPS2 = 269,
433
434/** Readonly adapter sync header connection count.
435*/
436 HPI_ADAPTER_PROPERTY_SYNC_HEADER_CONNECTIONS = 270,
437/** Readonly supports SSX2 property.
438Indicates the adapter supports SSX2 in some mode setting. The
439return value is true (1) or false (0). If the current adapter
440mode is MONO SSX2 is disabled, even though this property will
441return true.
442*/
443 HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271
436}; 444};
437 445
438/** Adapter mode commands 446/** Adapter mode commands
@@ -813,8 +821,6 @@ enum HPI_SAMPLECLOCK_SOURCES {
813/** The sampleclock output is derived from its local samplerate generator. 821/** The sampleclock output is derived from its local samplerate generator.
814 The local samplerate may be set using HPI_SampleClock_SetLocalRate(). */ 822 The local samplerate may be set using HPI_SampleClock_SetLocalRate(). */
815 HPI_SAMPLECLOCK_SOURCE_LOCAL = 1, 823 HPI_SAMPLECLOCK_SOURCE_LOCAL = 1,
816/** \deprecated Use HPI_SAMPLECLOCK_SOURCE_LOCAL instead */
817 HPI_SAMPLECLOCK_SOURCE_ADAPTER = 1,
818/** The adapter is clocked from a dedicated AES/EBU SampleClock input.*/ 824/** The adapter is clocked from a dedicated AES/EBU SampleClock input.*/
819 HPI_SAMPLECLOCK_SOURCE_AESEBU_SYNC = 2, 825 HPI_SAMPLECLOCK_SOURCE_AESEBU_SYNC = 2,
820/** From external wordclock connector */ 826/** From external wordclock connector */
@@ -825,10 +831,6 @@ enum HPI_SAMPLECLOCK_SOURCES {
825 HPI_SAMPLECLOCK_SOURCE_SMPTE = 5, 831 HPI_SAMPLECLOCK_SOURCE_SMPTE = 5,
826/** One of the aesebu inputs */ 832/** One of the aesebu inputs */
827 HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT = 6, 833 HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT = 6,
828/** \deprecated The first aesebu input with a valid signal
829Superseded by separate Auto enable flag
830*/
831 HPI_SAMPLECLOCK_SOURCE_AESEBU_AUTO = 7,
832/** From a network interface e.g. Cobranet or Livewire at either 48 or 96kHz */ 834/** From a network interface e.g. Cobranet or Livewire at either 48 or 96kHz */
833 HPI_SAMPLECLOCK_SOURCE_NETWORK = 8, 835 HPI_SAMPLECLOCK_SOURCE_NETWORK = 8,
834/** From previous adjacent module (ASI2416 only)*/ 836/** From previous adjacent module (ASI2416 only)*/
@@ -1015,8 +1017,6 @@ enum HPI_ERROR_CODES {
1015 HPI_ERROR_CONTROL_DISABLED = 404, 1017 HPI_ERROR_CONTROL_DISABLED = 404,
1016 /** I2C transaction failed due to a missing ACK. */ 1018 /** I2C transaction failed due to a missing ACK. */
1017 HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405, 1019 HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405,
1018 /** Control attribute is valid, but not supported by this hardware. */
1019 HPI_ERROR_UNSUPPORTED_CONTROL_ATTRIBUTE = 406,
1020 /** Control is busy, or coming out of 1020 /** Control is busy, or coming out of
1021 reset and cannot be accessed at this time. */ 1021 reset and cannot be accessed at this time. */
1022 HPI_ERROR_CONTROL_NOT_READY = 407, 1022 HPI_ERROR_CONTROL_NOT_READY = 407,
@@ -1827,13 +1827,41 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
1827 Compressor Expander control 1827 Compressor Expander control
1828*******************************/ 1828*******************************/
1829 1829
1830u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control, 1830u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys,
1831 u16 attack, u16 decay, short ratio100, short threshold0_01dB, 1831 u32 h_control, u32 on);
1832 short makeup_gain0_01dB); 1832
1833u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys,
1834 u32 h_control, u32 *pon);
1835
1836u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys,
1837 u32 h_control, short makeup_gain0_01dB);
1838
1839u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys,
1840 u32 h_control, short *pn_makeup_gain0_01dB);
1841
1842u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys
1843 *ph_subsys, u32 h_control, u32 index, u32 attack);
1844
1845u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys
1846 *ph_subsys, u32 h_control, u32 index, u32 *pw_attack);
1847
1848u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
1849 u32 h_control, u32 index, u32 decay);
1850
1851u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
1852 u32 h_control, u32 index, u32 *pw_decay);
1853
1854u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
1855 u32 h_control, u32 index, short threshold0_01dB);
1856
1857u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
1858 u32 h_control, u32 index, short *pn_threshold0_01dB);
1859
1860u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys,
1861 u32 h_control, u32 index, u32 ratio100);
1833 1862
1834u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control, 1863u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys,
1835 u16 *pw_attack, u16 *pw_decay, short *pw_ratio100, 1864 u32 h_control, u32 index, u32 *pw_ratio100);
1836 short *pn_threshold0_01dB, short *pn_makeup_gain0_01dB);
1837 1865
1838/******************************* 1866/*******************************
1839 Cobranet HMI control 1867 Cobranet HMI control
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
index 12dab5e4892c..f7e374ec4414 100644
--- a/sound/pci/asihpi/hpi6000.c
+++ b/sound/pci/asihpi/hpi6000.c
@@ -687,6 +687,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
687 switch (pao->pci.subsys_device_id) { 687 switch (pao->pci.subsys_device_id) {
688 case 0x5100: 688 case 0x5100:
689 case 0x5110: /* ASI5100 revB or higher with C6711D */ 689 case 0x5110: /* ASI5100 revB or higher with C6711D */
690 case 0x5200: /* ASI5200 PC_ie version of ASI5100 */
690 case 0x6100: 691 case 0x6100:
691 case 0x6200: 692 case 0x6200:
692 boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200); 693 boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
@@ -1133,6 +1134,12 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
1133 subsys_device_id) == 1134 subsys_device_id) ==
1134 HPI_ADAPTER_FAMILY_ASI(0x5100)) 1135 HPI_ADAPTER_FAMILY_ASI(0x5100))
1135 mask = 0x00000000L; 1136 mask = 0x00000000L;
1137 /* ASI5200 uses AX6 code, */
1138 /* but has no PLD r/w register to test */
1139 if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
1140 subsys_device_id) ==
1141 HPI_ADAPTER_FAMILY_ASI(0x5200))
1142 mask = 0x00000000L;
1136 break; 1143 break;
1137 case HPI_ADAPTER_FAMILY_ASI(0x8800): 1144 case HPI_ADAPTER_FAMILY_ASI(0x8800):
1138 /* ASI8800 has 16bit path to FPGA */ 1145 /* ASI8800 has 16bit path to FPGA */
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h
index fdd0ce02aa68..16f502d459de 100644
--- a/sound/pci/asihpi/hpi_internal.h
+++ b/sound/pci/asihpi/hpi_internal.h
@@ -104,9 +104,9 @@ typedef void hpi_handler_func(struct hpi_message *, struct hpi_response *);
104#define STR_ROLE_FIELD_MAX 255U 104#define STR_ROLE_FIELD_MAX 255U
105 105
106struct hpi_entity_str { 106struct hpi_entity_str {
107 uint16_t size; 107 u16 size;
108 uint8_t type; 108 u8 type;
109 uint8_t role; 109 u8 role;
110}; 110};
111 111
112#if defined(_MSC_VER) 112#if defined(_MSC_VER)
@@ -119,11 +119,11 @@ struct hpi_entity {
119#if ! defined(HPI_OS_DSP_C6000) || (defined(HPI_OS_DSP_C6000) && (__TI_COMPILER_VERSION__ > 6000008)) 119#if ! defined(HPI_OS_DSP_C6000) || (defined(HPI_OS_DSP_C6000) && (__TI_COMPILER_VERSION__ > 6000008))
120 /* DSP C6000 compiler v6.0.8 and lower 120 /* DSP C6000 compiler v6.0.8 and lower
121 do not support flexible array member */ 121 do not support flexible array member */
122 uint8_t value[]; 122 u8 value[];
123#else 123#else
124 /* NOTE! Using sizeof(struct hpi_entity) will give erroneous results */ 124 /* NOTE! Using sizeof(struct hpi_entity) will give erroneous results */
125#define HPI_INTERNAL_WARN_ABOUT_ENTITY_VALUE 125#define HPI_INTERNAL_WARN_ABOUT_ENTITY_VALUE
126 uint8_t value[1]; 126 u8 value[1];
127#endif 127#endif
128}; 128};
129 129
@@ -142,12 +142,15 @@ enum HPI_BUSES {
142/******************************************* CONTROL ATTRIBUTES ****/ 142/******************************************* CONTROL ATTRIBUTES ****/
143/* (in order of control type ID */ 143/* (in order of control type ID */
144 144
145 /* This allows for 255 control types, 256 unique attributes each */ 145/* This allows for 255 control types, 256 unique attributes each */
146#define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai) 146#define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai)
147 147
148/* Get the sub-index of the attribute for a control type */ 148/* Get the sub-index of the attribute for a control type */
149#define HPI_CTL_ATTR_INDEX(i) (i&0xff) 149#define HPI_CTL_ATTR_INDEX(i) (i&0xff)
150 150
151/* Extract the control from the control attribute */
152#define HPI_CTL_ATTR_CONTROL(i) (i>>8)
153
151/* Generic control attributes. */ 154/* Generic control attributes. */
152 155
153/** Enable a control. 156/** Enable a control.
@@ -311,8 +314,7 @@ Used for HPI_ChannelModeSet/Get()
311/* Microphone control attributes */ 314/* Microphone control attributes */
312#define HPI_MICROPHONE_PHANTOM_POWER HPI_CTL_ATTR(MICROPHONE, 1) 315#define HPI_MICROPHONE_PHANTOM_POWER HPI_CTL_ATTR(MICROPHONE, 1)
313 316
314/** Equalizer control attributes 317/** Equalizer control attributes */
315*/
316/** Used to get number of filters in an EQ. (Can't set) */ 318/** Used to get number of filters in an EQ. (Can't set) */
317#define HPI_EQUALIZER_NUM_FILTERS HPI_CTL_ATTR(EQUALIZER, 1) 319#define HPI_EQUALIZER_NUM_FILTERS HPI_CTL_ATTR(EQUALIZER, 1)
318/** Set/get the filter by type, freq, Q, gain */ 320/** Set/get the filter by type, freq, Q, gain */
@@ -320,13 +322,15 @@ Used for HPI_ChannelModeSet/Get()
320/** Get the biquad coefficients */ 322/** Get the biquad coefficients */
321#define HPI_EQUALIZER_COEFFICIENTS HPI_CTL_ATTR(EQUALIZER, 3) 323#define HPI_EQUALIZER_COEFFICIENTS HPI_CTL_ATTR(EQUALIZER, 3)
322 324
323#define HPI_COMPANDER_PARAMS HPI_CTL_ATTR(COMPANDER, 1) 325/* Note compander also uses HPI_GENERIC_ENABLE */
326#define HPI_COMPANDER_PARAMS HPI_CTL_ATTR(COMPANDER, 1)
327#define HPI_COMPANDER_MAKEUPGAIN HPI_CTL_ATTR(COMPANDER, 2)
328#define HPI_COMPANDER_THRESHOLD HPI_CTL_ATTR(COMPANDER, 3)
329#define HPI_COMPANDER_RATIO HPI_CTL_ATTR(COMPANDER, 4)
330#define HPI_COMPANDER_ATTACK HPI_CTL_ATTR(COMPANDER, 5)
331#define HPI_COMPANDER_DECAY HPI_CTL_ATTR(COMPANDER, 6)
324 332
325/* Cobranet control attributes. 333/* Cobranet control attributes. */
326 MUST be distinct from all other control attributes.
327 This is so that host side processing can easily identify a Cobranet control
328 and apply additional host side operations (like copying data) as required.
329*/
330#define HPI_COBRANET_SET HPI_CTL_ATTR(COBRANET, 1) 334#define HPI_COBRANET_SET HPI_CTL_ATTR(COBRANET, 1)
331#define HPI_COBRANET_GET HPI_CTL_ATTR(COBRANET, 2) 335#define HPI_COBRANET_GET HPI_CTL_ATTR(COBRANET, 2)
332#define HPI_COBRANET_SET_DATA HPI_CTL_ATTR(COBRANET, 3) 336#define HPI_COBRANET_SET_DATA HPI_CTL_ATTR(COBRANET, 3)
@@ -1512,11 +1516,11 @@ struct hpi_control_cache_single {
1512 struct hpi_control_cache_info i; 1516 struct hpi_control_cache_info i;
1513 union { 1517 union {
1514 struct { /* volume */ 1518 struct { /* volume */
1515 u16 an_log[2]; 1519 short an_log[2];
1516 } v; 1520 } v;
1517 struct { /* peak meter */ 1521 struct { /* peak meter */
1518 u16 an_log_peak[2]; 1522 short an_log_peak[2];
1519 u16 an_logRMS[2]; 1523 short an_logRMS[2];
1520 } p; 1524 } p;
1521 struct { /* channel mode */ 1525 struct { /* channel mode */
1522 u16 mode; 1526 u16 mode;
@@ -1526,7 +1530,7 @@ struct hpi_control_cache_single {
1526 u16 source_node_index; 1530 u16 source_node_index;
1527 } x; 1531 } x;
1528 struct { /* level/trim */ 1532 struct { /* level/trim */
1529 u16 an_log[2]; 1533 short an_log[2];
1530 } l; 1534 } l;
1531 struct { /* tuner - partial caching. 1535 struct { /* tuner - partial caching.
1532 some attributes go to the DSP. */ 1536 some attributes go to the DSP. */
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c
index fcd64539d9ef..dda4f1c6f658 100644
--- a/sound/pci/asihpi/hpicmn.c
+++ b/sound/pci/asihpi/hpicmn.c
@@ -353,7 +353,12 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
353 phr->u.c.param1 = pC->u.t.band; 353 phr->u.c.param1 = pC->u.t.band;
354 else if ((phm->u.c.attribute == HPI_TUNER_LEVEL) 354 else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
355 && (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE)) 355 && (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
356 phr->u.c.param1 = pC->u.t.level; 356 if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) {
357 phr->u.c.param1 = 0;
358 phr->error =
359 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
360 } else
361 phr->u.c.param1 = pC->u.t.level;
357 else 362 else
358 found = 0; 363 found = 0;
359 break; 364 break;
@@ -397,7 +402,8 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
397 if (pC->u.clk.source_index == 402 if (pC->u.clk.source_index ==
398 HPI_ERROR_ILLEGAL_CACHE_VALUE) { 403 HPI_ERROR_ILLEGAL_CACHE_VALUE) {
399 phr->u.c.param1 = 0; 404 phr->u.c.param1 = 0;
400 phr->error = HPI_ERROR_INVALID_OPERATION; 405 phr->error =
406 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
401 } else 407 } else
402 phr->u.c.param1 = pC->u.clk.source_index; 408 phr->u.c.param1 = pC->u.clk.source_index;
403 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE) 409 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
diff --git a/sound/pci/asihpi/hpidebug.c b/sound/pci/asihpi/hpidebug.c
index 4cd85a401b34..949836ec913a 100644
--- a/sound/pci/asihpi/hpidebug.c
+++ b/sound/pci/asihpi/hpidebug.c
@@ -111,7 +111,7 @@ make_treenode_from_array(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS)
111 &hpi_profile_strings,\ 111 &hpi_profile_strings,\
112 &hpi_control_strings, \ 112 &hpi_control_strings, \
113 &hpi_asyncevent_strings \ 113 &hpi_asyncevent_strings \
114}; 114}
115 make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS) 115 make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS)
116 116
117 compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match); 117 compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);
diff --git a/sound/pci/asihpi/hpidebug.h b/sound/pci/asihpi/hpidebug.h
index 44dccadcc25b..a2f0952a99f0 100644
--- a/sound/pci/asihpi/hpidebug.h
+++ b/sound/pci/asihpi/hpidebug.h
@@ -356,7 +356,7 @@ compile_time_assert((HPI_CONTROL_LAST_INDEX + 1 == 27),
356 "HPI_SOURCENODE_ADAPTER" \ 356 "HPI_SOURCENODE_ADAPTER" \
357} 357}
358 358
359compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_BASE + 1) == 359compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_NONE + 1) ==
360 (12), sourcenode_strings_match_defs); 360 (12), sourcenode_strings_match_defs);
361 361
362#define HPI_DESTNODE_STRINGS \ 362#define HPI_DESTNODE_STRINGS \
@@ -370,7 +370,7 @@ compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_BASE + 1) ==
370 "HPI_DESTNODE_COBRANET", \ 370 "HPI_DESTNODE_COBRANET", \
371 "HPI_DESTNODE_ANALOG" \ 371 "HPI_DESTNODE_ANALOG" \
372} 372}
373compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_BASE + 1) == (8), 373compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_NONE + 1) == (8),
374 destnode_strings_match_defs); 374 destnode_strings_match_defs);
375 375
376#define HPI_CONTROL_CHANNEL_MODE_STRINGS \ 376#define HPI_CONTROL_CHANNEL_MODE_STRINGS \
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c
index 298eef3e20e9..1e92eb6dd509 100644
--- a/sound/pci/asihpi/hpifunc.c
+++ b/sound/pci/asihpi/hpifunc.c
@@ -96,8 +96,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR)
96 96
97static struct hpi_hsubsys gh_subsys; 97static struct hpi_hsubsys gh_subsys;
98 98
99struct hpi_hsubsys *hpi_subsys_create(void 99struct hpi_hsubsys *hpi_subsys_create(void)
100 )
101{ 100{
102 struct hpi_message hm; 101 struct hpi_message hm;
103 struct hpi_response hr; 102 struct hpi_response hr;
@@ -302,6 +301,7 @@ u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
302{ 301{
303 struct hpi_message hm; 302 struct hpi_message hm;
304 struct hpi_response hr; 303 struct hpi_response hr;
304
305 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 305 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
306 HPI_ADAPTER_SET_MODE); 306 HPI_ADAPTER_SET_MODE);
307 hm.adapter_index = adapter_index; 307 hm.adapter_index = adapter_index;
@@ -510,7 +510,7 @@ u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys,
510 hm.adapter_index = adapter_index; 510 hm.adapter_index = adapter_index;
511 hm.u.ax.debug_read.dsp_address = dsp_address; 511 hm.u.ax.debug_read.dsp_address = dsp_address;
512 512
513 if (*count_bytes > sizeof(hr.u.bytes)) 513 if (*count_bytes > (int)sizeof(hr.u.bytes))
514 *count_bytes = sizeof(hr.u.bytes); 514 *count_bytes = sizeof(hr.u.bytes);
515 515
516 hm.u.ax.debug_read.count_bytes = *count_bytes; 516 hm.u.ax.debug_read.count_bytes = *count_bytes;
@@ -976,6 +976,7 @@ u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
976{ 976{
977 struct hpi_message hm; 977 struct hpi_message hm;
978 struct hpi_response hr; 978 struct hpi_response hr;
979
979 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, 980 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
980 HPI_OSTREAM_ANC_READ); 981 HPI_OSTREAM_ANC_READ);
981 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); 982 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
@@ -1581,6 +1582,7 @@ u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys,
1581{ 1582{
1582 struct hpi_message hm; 1583 struct hpi_message hm;
1583 struct hpi_response hr; 1584 struct hpi_response hr;
1585
1584 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 1586 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1585 HPI_CONTROL_SET_STATE); 1587 HPI_CONTROL_SET_STATE);
1586 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 1588 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1591,6 +1593,22 @@ u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys,
1591 return hr.error; 1593 return hr.error;
1592} 1594}
1593 1595
1596static u16 hpi_control_log_set2(u32 h_control, u16 attrib, short sv0,
1597 short sv1)
1598{
1599 struct hpi_message hm;
1600 struct hpi_response hr;
1601
1602 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1603 HPI_CONTROL_SET_STATE);
1604 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1605 hm.u.c.attribute = attrib;
1606 hm.u.c.an_log_value[0] = sv0;
1607 hm.u.c.an_log_value[1] = sv1;
1608 hpi_send_recv(&hm, &hr);
1609 return hr.error;
1610}
1611
1594static 1612static
1595u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys, 1613u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
1596 const u32 h_control, const u16 attrib, u32 param1, u32 param2, 1614 const u32 h_control, const u16 attrib, u32 param1, u32 param2,
@@ -1598,6 +1616,7 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
1598{ 1616{
1599 struct hpi_message hm; 1617 struct hpi_message hm;
1600 struct hpi_response hr; 1618 struct hpi_response hr;
1619
1601 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 1620 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1602 HPI_CONTROL_GET_STATE); 1621 HPI_CONTROL_GET_STATE);
1603 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 1622 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1605,8 +1624,8 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
1605 hm.u.c.param1 = param1; 1624 hm.u.c.param1 = param1;
1606 hm.u.c.param2 = param2; 1625 hm.u.c.param2 = param2;
1607 hpi_send_recv(&hm, &hr); 1626 hpi_send_recv(&hm, &hr);
1608 if (pparam1) 1627
1609 *pparam1 = hr.u.c.param1; 1628 *pparam1 = hr.u.c.param1;
1610 if (pparam2) 1629 if (pparam2)
1611 *pparam2 = hr.u.c.param2; 1630 *pparam2 = hr.u.c.param2;
1612 1631
@@ -1617,10 +1636,23 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
1617 hpi_control_param_get(s, h, a, 0, 0, p1, NULL) 1636 hpi_control_param_get(s, h, a, 0, 0, p1, NULL)
1618#define hpi_control_param2_get(s, h, a, p1, p2) \ 1637#define hpi_control_param2_get(s, h, a, p1, p2) \
1619 hpi_control_param_get(s, h, a, 0, 0, p1, p2) 1638 hpi_control_param_get(s, h, a, 0, 0, p1, p2)
1620#define hpi_control_ex_param1_get(s, h, a, p1) \ 1639
1621 hpi_control_ex_param_get(s, h, a, 0, 0, p1, NULL) 1640static u16 hpi_control_log_get2(const struct hpi_hsubsys *ph_subsys,
1622#define hpi_control_ex_param2_get(s, h, a, p1, p2) \ 1641 u32 h_control, u16 attrib, short *sv0, short *sv1)
1623 hpi_control_ex_param_get(s, h, a, 0, 0, p1, p2) 1642{
1643 struct hpi_message hm;
1644 struct hpi_response hr;
1645 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1646 HPI_CONTROL_GET_STATE);
1647 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1648 hm.u.c.attribute = attrib;
1649
1650 hpi_send_recv(&hm, &hr);
1651 *sv0 = hr.u.c.an_log_value[0];
1652 if (sv1)
1653 *sv1 = hr.u.c.an_log_value[1];
1654 return hr.error;
1655}
1624 1656
1625static 1657static
1626u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys, 1658u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
@@ -1629,6 +1661,7 @@ u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
1629{ 1661{
1630 struct hpi_message hm; 1662 struct hpi_message hm;
1631 struct hpi_response hr; 1663 struct hpi_response hr;
1664
1632 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 1665 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1633 HPI_CONTROL_GET_INFO); 1666 HPI_CONTROL_GET_INFO);
1634 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 1667 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1643,9 +1676,8 @@ u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
1643 return hr.error; 1676 return hr.error;
1644} 1677}
1645 1678
1646static u16 hpi_control_get_string(const struct hpi_hsubsys *ph_subsys, 1679static u16 hpi_control_get_string(const u32 h_control, const u16 attribute,
1647 const u32 h_control, const u16 attribute, char *psz_string, 1680 char *psz_string, const u32 string_length)
1648 const u32 string_length)
1649{ 1681{
1650 unsigned int sub_string_index = 0, j = 0; 1682 unsigned int sub_string_index = 0, j = 0;
1651 char c = 0; 1683 char c = 0;
@@ -1916,6 +1948,7 @@ u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1916{ 1948{
1917 struct hpi_message hm; 1949 struct hpi_message hm;
1918 struct hpi_response hr; 1950 struct hpi_response hr;
1951
1919 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, 1952 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
1920 HPI_CONTROL_SET_STATE); 1953 HPI_CONTROL_SET_STATE);
1921 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 1954 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1941,6 +1974,7 @@ u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1941{ 1974{
1942 struct hpi_message hm; 1975 struct hpi_message hm;
1943 struct hpi_response hr; 1976 struct hpi_response hr;
1977
1944 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, 1978 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
1945 HPI_CONTROL_GET_STATE); 1979 HPI_CONTROL_GET_STATE);
1946 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 1980 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1980,6 +2014,7 @@ u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
1980{ 2014{
1981 struct hpi_message hm; 2015 struct hpi_message hm;
1982 struct hpi_response hr; 2016 struct hpi_response hr;
2017
1983 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, 2018 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
1984 HPI_CONTROL_GET_STATE); 2019 HPI_CONTROL_GET_STATE);
1985 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2020 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2006,6 +2041,7 @@ u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys,
2006 u32 byte_count; 2041 u32 byte_count;
2007 u32 iP; 2042 u32 iP;
2008 u16 error; 2043 u16 error;
2044
2009 error = hpi_cobranet_hmi_read(ph_subsys, h_control, 2045 error = hpi_cobranet_hmi_read(ph_subsys, h_control,
2010 HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count, 2046 HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count,
2011 (u8 *)&iP); 2047 (u8 *)&iP);
@@ -2082,6 +2118,7 @@ u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
2082 u32 byte_count; 2118 u32 byte_count;
2083 u16 error; 2119 u16 error;
2084 u32 mAC; 2120 u32 mAC;
2121
2085 error = hpi_cobranet_hmi_read(ph_subsys, h_control, 2122 error = hpi_cobranet_hmi_read(ph_subsys, h_control,
2086 HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count, 2123 HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count,
2087 (u8 *)&mAC); 2124 (u8 *)&mAC);
@@ -2103,53 +2140,111 @@ u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
2103 return error; 2140 return error;
2104} 2141}
2105 2142
2106u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control, 2143u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys,
2107 u16 attack, u16 decay, short ratio100, short threshold0_01dB, 2144 u32 h_control, u32 enable)
2108 short makeup_gain0_01dB) 2145{
2146 return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE,
2147 enable, 0);
2148}
2149
2150u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys,
2151 u32 h_control, u32 *enable)
2152{
2153 return hpi_control_param1_get(ph_subsys, h_control,
2154 HPI_GENERIC_ENABLE, enable);
2155}
2156
2157u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys,
2158 u32 h_control, short makeup_gain0_01dB)
2159{
2160 return hpi_control_log_set2(h_control, HPI_COMPANDER_MAKEUPGAIN,
2161 makeup_gain0_01dB, 0);
2162}
2163
2164u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys,
2165 u32 h_control, short *makeup_gain0_01dB)
2166{
2167 return hpi_control_log_get2(ph_subsys, h_control,
2168 HPI_COMPANDER_MAKEUPGAIN, makeup_gain0_01dB, NULL);
2169}
2170
2171u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys
2172 *ph_subsys, u32 h_control, unsigned int index, u32 attack)
2173{
2174 return hpi_control_param_set(ph_subsys, h_control,
2175 HPI_COMPANDER_ATTACK, attack, index);
2176}
2177
2178u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys
2179 *ph_subsys, u32 h_control, unsigned int index, u32 *attack)
2180{
2181 return hpi_control_param_get(ph_subsys, h_control,
2182 HPI_COMPANDER_ATTACK, 0, index, attack, NULL);
2183}
2184
2185u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
2186 u32 h_control, unsigned int index, u32 decay)
2187{
2188 return hpi_control_param_set(ph_subsys, h_control,
2189 HPI_COMPANDER_DECAY, decay, index);
2190}
2191
2192u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
2193 u32 h_control, unsigned int index, u32 *decay)
2194{
2195 return hpi_control_param_get(ph_subsys, h_control,
2196 HPI_COMPANDER_DECAY, 0, index, decay, NULL);
2197
2198}
2199
2200u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
2201 u32 h_control, unsigned int index, short threshold0_01dB)
2109{ 2202{
2110 struct hpi_message hm; 2203 struct hpi_message hm;
2111 struct hpi_response hr; 2204 struct hpi_response hr;
2205
2112 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 2206 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2113 HPI_CONTROL_SET_STATE); 2207 HPI_CONTROL_SET_STATE);
2114 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2208 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2115 2209 hm.u.c.attribute = HPI_COMPANDER_THRESHOLD;
2116 hm.u.c.param1 = attack + ((u32)ratio100 << 16); 2210 hm.u.c.param2 = index;
2117 hm.u.c.param2 = (decay & 0xFFFFL);
2118 hm.u.c.an_log_value[0] = threshold0_01dB; 2211 hm.u.c.an_log_value[0] = threshold0_01dB;
2119 hm.u.c.an_log_value[1] = makeup_gain0_01dB;
2120 hm.u.c.attribute = HPI_COMPANDER_PARAMS;
2121 2212
2122 hpi_send_recv(&hm, &hr); 2213 hpi_send_recv(&hm, &hr);
2123 2214
2124 return hr.error; 2215 return hr.error;
2125} 2216}
2126 2217
2127u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control, 2218u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
2128 u16 *pw_attack, u16 *pw_decay, short *pw_ratio100, 2219 u32 h_control, unsigned int index, short *threshold0_01dB)
2129 short *pn_threshold0_01dB, short *pn_makeup_gain0_01dB)
2130{ 2220{
2131 struct hpi_message hm; 2221 struct hpi_message hm;
2132 struct hpi_response hr; 2222 struct hpi_response hr;
2223
2133 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 2224 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2134 HPI_CONTROL_GET_STATE); 2225 HPI_CONTROL_GET_STATE);
2135 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2226 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2136 hm.u.c.attribute = HPI_COMPANDER_PARAMS; 2227 hm.u.c.attribute = HPI_COMPANDER_THRESHOLD;
2228 hm.u.c.param2 = index;
2137 2229
2138 hpi_send_recv(&hm, &hr); 2230 hpi_send_recv(&hm, &hr);
2231 *threshold0_01dB = hr.u.c.an_log_value[0];
2139 2232
2140 if (pw_attack) 2233 return hr.error;
2141 *pw_attack = (short)(hr.u.c.param1 & 0xFFFF); 2234}
2142 if (pw_decay)
2143 *pw_decay = (short)(hr.u.c.param2 & 0xFFFF);
2144 if (pw_ratio100)
2145 *pw_ratio100 = (short)(hr.u.c.param1 >> 16);
2146 2235
2147 if (pn_threshold0_01dB) 2236u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys,
2148 *pn_threshold0_01dB = hr.u.c.an_log_value[0]; 2237 u32 h_control, u32 index, u32 ratio100)
2149 if (pn_makeup_gain0_01dB) 2238{
2150 *pn_makeup_gain0_01dB = hr.u.c.an_log_value[1]; 2239 return hpi_control_param_set(ph_subsys, h_control,
2240 HPI_COMPANDER_RATIO, ratio100, index);
2241}
2151 2242
2152 return hr.error; 2243u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys,
2244 u32 h_control, u32 index, u32 *ratio100)
2245{
2246 return hpi_control_param_get(ph_subsys, h_control,
2247 HPI_COMPANDER_RATIO, 0, index, ratio100, NULL);
2153} 2248}
2154 2249
2155u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, 2250u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
@@ -2157,6 +2252,7 @@ u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2157{ 2252{
2158 struct hpi_message hm; 2253 struct hpi_message hm;
2159 struct hpi_response hr; 2254 struct hpi_response hr;
2255
2160 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 2256 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2161 HPI_CONTROL_GET_STATE); 2257 HPI_CONTROL_GET_STATE);
2162 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2258 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2181,37 +2277,16 @@ u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2181 short an_gain0_01dB[HPI_MAX_CHANNELS] 2277 short an_gain0_01dB[HPI_MAX_CHANNELS]
2182 ) 2278 )
2183{ 2279{
2184 struct hpi_message hm; 2280 return hpi_control_log_set2(h_control, HPI_LEVEL_GAIN,
2185 struct hpi_response hr; 2281 an_gain0_01dB[0], an_gain0_01dB[1]);
2186
2187 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2188 HPI_CONTROL_SET_STATE);
2189 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2190 memcpy(hm.u.c.an_log_value, an_gain0_01dB,
2191 sizeof(short) * HPI_MAX_CHANNELS);
2192 hm.u.c.attribute = HPI_LEVEL_GAIN;
2193
2194 hpi_send_recv(&hm, &hr);
2195
2196 return hr.error;
2197} 2282}
2198 2283
2199u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, 2284u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2200 short an_gain0_01dB[HPI_MAX_CHANNELS] 2285 short an_gain0_01dB[HPI_MAX_CHANNELS]
2201 ) 2286 )
2202{ 2287{
2203 struct hpi_message hm; 2288 return hpi_control_log_get2(ph_subsys, h_control, HPI_LEVEL_GAIN,
2204 struct hpi_response hr; 2289 &an_gain0_01dB[0], &an_gain0_01dB[1]);
2205 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2206 HPI_CONTROL_GET_STATE);
2207 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2208 hm.u.c.attribute = HPI_LEVEL_GAIN;
2209
2210 hpi_send_recv(&hm, &hr);
2211
2212 memcpy(an_gain0_01dB, hr.u.c.an_log_value,
2213 sizeof(short) * HPI_MAX_CHANNELS);
2214 return hr.error;
2215} 2290}
2216 2291
2217u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys, 2292u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
@@ -2413,6 +2488,7 @@ u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
2413{ 2488{
2414 struct hpi_message hm; 2489 struct hpi_message hm;
2415 struct hpi_response hr; 2490 struct hpi_response hr;
2491
2416 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 2492 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2417 HPI_CONTROL_GET_STATE); 2493 HPI_CONTROL_GET_STATE);
2418 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2494 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2439,6 +2515,7 @@ u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
2439{ 2515{
2440 struct hpi_message hm; 2516 struct hpi_message hm;
2441 struct hpi_response hr; 2517 struct hpi_response hr;
2518
2442 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 2519 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2443 HPI_CONTROL_SET_STATE); 2520 HPI_CONTROL_SET_STATE);
2444 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2521 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2460,6 +2537,7 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
2460{ 2537{
2461 struct hpi_message hm; 2538 struct hpi_message hm;
2462 struct hpi_response hr; 2539 struct hpi_response hr;
2540
2463 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 2541 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2464 HPI_CONTROL_GET_STATE); 2542 HPI_CONTROL_GET_STATE);
2465 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2543 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2623,8 +2701,8 @@ u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys,
2623u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys, 2701u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys,
2624 u32 h_control, u32 *state) 2702 u32 h_control, u32 *state)
2625{ 2703{
2626 return hpi_control_param_get(ph_subsys, h_control, 2704 return hpi_control_param1_get(ph_subsys, h_control,
2627 HPI_TONEDETECTOR_STATE, 0, 0, (u32 *)state, NULL); 2705 HPI_TONEDETECTOR_STATE, state);
2628} 2706}
2629 2707
2630u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys, 2708u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
@@ -2637,8 +2715,8 @@ u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
2637u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys, 2715u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
2638 u32 h_control, u32 *enable) 2716 u32 h_control, u32 *enable)
2639{ 2717{
2640 return hpi_control_param_get(ph_subsys, h_control, HPI_GENERIC_ENABLE, 2718 return hpi_control_param1_get(ph_subsys, h_control,
2641 0, 0, (u32 *)enable, NULL); 2719 HPI_GENERIC_ENABLE, enable);
2642} 2720}
2643 2721
2644u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys, 2722u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
@@ -2651,8 +2729,8 @@ u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
2651u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys, 2729u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
2652 u32 h_control, u32 *event_enable) 2730 u32 h_control, u32 *event_enable)
2653{ 2731{
2654 return hpi_control_param_get(ph_subsys, h_control, 2732 return hpi_control_param1_get(ph_subsys, h_control,
2655 HPI_GENERIC_EVENT_ENABLE, 0, 0, (u32 *)event_enable, NULL); 2733 HPI_GENERIC_EVENT_ENABLE, event_enable);
2656} 2734}
2657 2735
2658u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys, 2736u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
@@ -2665,15 +2743,15 @@ u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
2665u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys, 2743u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
2666 u32 h_control, int *threshold) 2744 u32 h_control, int *threshold)
2667{ 2745{
2668 return hpi_control_param_get(ph_subsys, h_control, 2746 return hpi_control_param1_get(ph_subsys, h_control,
2669 HPI_TONEDETECTOR_THRESHOLD, 0, 0, (u32 *)threshold, NULL); 2747 HPI_TONEDETECTOR_THRESHOLD, (u32 *)threshold);
2670} 2748}
2671 2749
2672u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys, 2750u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
2673 u32 h_control, u32 *state) 2751 u32 h_control, u32 *state)
2674{ 2752{
2675 return hpi_control_param_get(ph_subsys, h_control, 2753 return hpi_control_param1_get(ph_subsys, h_control,
2676 HPI_SILENCEDETECTOR_STATE, 0, 0, (u32 *)state, NULL); 2754 HPI_SILENCEDETECTOR_STATE, state);
2677} 2755}
2678 2756
2679u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys, 2757u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
@@ -2686,50 +2764,50 @@ u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
2686u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys, 2764u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
2687 u32 h_control, u32 *enable) 2765 u32 h_control, u32 *enable)
2688{ 2766{
2689 return hpi_control_param_get(ph_subsys, h_control, HPI_GENERIC_ENABLE, 2767 return hpi_control_param1_get(ph_subsys, h_control,
2690 0, 0, (u32 *)enable, NULL); 2768 HPI_GENERIC_ENABLE, enable);
2691} 2769}
2692 2770
2693u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys, 2771u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
2694 u32 h_control, u32 event_enable) 2772 u32 h_control, u32 event_enable)
2695{ 2773{
2696 return hpi_control_param_set(ph_subsys, h_control, 2774 return hpi_control_param_set(ph_subsys, h_control,
2697 HPI_GENERIC_EVENT_ENABLE, (u32)event_enable, 0); 2775 HPI_GENERIC_EVENT_ENABLE, event_enable, 0);
2698} 2776}
2699 2777
2700u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys, 2778u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
2701 u32 h_control, u32 *event_enable) 2779 u32 h_control, u32 *event_enable)
2702{ 2780{
2703 return hpi_control_param_get(ph_subsys, h_control, 2781 return hpi_control_param1_get(ph_subsys, h_control,
2704 HPI_GENERIC_EVENT_ENABLE, 0, 0, (u32 *)event_enable, NULL); 2782 HPI_GENERIC_EVENT_ENABLE, event_enable);
2705} 2783}
2706 2784
2707u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys, 2785u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
2708 u32 h_control, u32 delay) 2786 u32 h_control, u32 delay)
2709{ 2787{
2710 return hpi_control_param_set(ph_subsys, h_control, 2788 return hpi_control_param_set(ph_subsys, h_control,
2711 HPI_SILENCEDETECTOR_DELAY, (u32)delay, 0); 2789 HPI_SILENCEDETECTOR_DELAY, delay, 0);
2712} 2790}
2713 2791
2714u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys, 2792u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
2715 u32 h_control, u32 *delay) 2793 u32 h_control, u32 *delay)
2716{ 2794{
2717 return hpi_control_param_get(ph_subsys, h_control, 2795 return hpi_control_param1_get(ph_subsys, h_control,
2718 HPI_SILENCEDETECTOR_DELAY, 0, 0, (u32 *)delay, NULL); 2796 HPI_SILENCEDETECTOR_DELAY, delay);
2719} 2797}
2720 2798
2721u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys, 2799u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
2722 u32 h_control, int threshold) 2800 u32 h_control, int threshold)
2723{ 2801{
2724 return hpi_control_param_set(ph_subsys, h_control, 2802 return hpi_control_param_set(ph_subsys, h_control,
2725 HPI_SILENCEDETECTOR_THRESHOLD, (u32)threshold, 0); 2803 HPI_SILENCEDETECTOR_THRESHOLD, threshold, 0);
2726} 2804}
2727 2805
2728u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys, 2806u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
2729 u32 h_control, int *threshold) 2807 u32 h_control, int *threshold)
2730{ 2808{
2731 return hpi_control_param_get(ph_subsys, h_control, 2809 return hpi_control_param1_get(ph_subsys, h_control,
2732 HPI_SILENCEDETECTOR_THRESHOLD, 0, 0, (u32 *)threshold, NULL); 2810 HPI_SILENCEDETECTOR_THRESHOLD, (u32 *)threshold);
2733} 2811}
2734 2812
2735u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys, 2813u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
@@ -2822,6 +2900,7 @@ u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2822{ 2900{
2823 struct hpi_message hm; 2901 struct hpi_message hm;
2824 struct hpi_response hr; 2902 struct hpi_response hr;
2903
2825 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 2904 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2826 HPI_CONTROL_GET_STATE); 2905 HPI_CONTROL_GET_STATE);
2827 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2906 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2838,6 +2917,7 @@ u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys,
2838{ 2917{
2839 struct hpi_message hm; 2918 struct hpi_message hm;
2840 struct hpi_response hr; 2919 struct hpi_response hr;
2920
2841 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 2921 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2842 HPI_CONTROL_GET_STATE); 2922 HPI_CONTROL_GET_STATE);
2843 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 2923 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2894,14 +2974,14 @@ u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2894u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys, 2974u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys,
2895 u32 h_control, char *psz_dsp_version, const u32 string_size) 2975 u32 h_control, char *psz_dsp_version, const u32 string_size)
2896{ 2976{
2897 return hpi_control_get_string(ph_subsys, h_control, 2977 return hpi_control_get_string(h_control,
2898 HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size); 2978 HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size);
2899} 2979}
2900 2980
2901u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys, 2981u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
2902 u32 h_control, char *psz_sdk_version, const u32 string_size) 2982 u32 h_control, char *psz_sdk_version, const u32 string_size)
2903{ 2983{
2904 return hpi_control_get_string(ph_subsys, h_control, 2984 return hpi_control_get_string(h_control,
2905 HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size); 2985 HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size);
2906} 2986}
2907 2987
@@ -2942,15 +3022,15 @@ u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2942u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys, 3022u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
2943 u32 h_control, u32 *pquality) 3023 u32 h_control, u32 *pquality)
2944{ 3024{
2945 return hpi_control_param_get(ph_subsys, h_control, 3025 return hpi_control_param1_get(ph_subsys, h_control,
2946 HPI_TUNER_HDRADIO_SIGNAL_QUALITY, 0, 0, pquality, NULL); 3026 HPI_TUNER_HDRADIO_SIGNAL_QUALITY, pquality);
2947} 3027}
2948 3028
2949u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys, 3029u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
2950 u32 h_control, u32 *pblend) 3030 u32 h_control, u32 *pblend)
2951{ 3031{
2952 return hpi_control_param_get(ph_subsys, h_control, 3032 return hpi_control_param1_get(ph_subsys, h_control,
2953 HPI_TUNER_HDRADIO_BLEND, 0, 0, pblend, NULL); 3033 HPI_TUNER_HDRADIO_BLEND, pblend);
2954} 3034}
2955 3035
2956u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys, 3036u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
@@ -2965,6 +3045,7 @@ u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2965{ 3045{
2966 struct hpi_message hm; 3046 struct hpi_message hm;
2967 struct hpi_response hr; 3047 struct hpi_response hr;
3048
2968 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 3049 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2969 HPI_CONTROL_GET_STATE); 3050 HPI_CONTROL_GET_STATE);
2970 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 3051 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2981,43 +3062,43 @@ u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2981u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys, 3062u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
2982 u32 h_control, char *psz_string, const u32 data_length) 3063 u32 h_control, char *psz_string, const u32 data_length)
2983{ 3064{
2984 return hpi_control_get_string(ph_subsys, h_control, 3065 return hpi_control_get_string(h_control, HPI_PAD_CHANNEL_NAME,
2985 HPI_PAD_CHANNEL_NAME, psz_string, data_length); 3066 psz_string, data_length);
2986} 3067}
2987 3068
2988u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control, 3069u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2989 char *psz_string, const u32 data_length) 3070 char *psz_string, const u32 data_length)
2990{ 3071{
2991 return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_ARTIST, 3072 return hpi_control_get_string(h_control, HPI_PAD_ARTIST, psz_string,
2992 psz_string, data_length); 3073 data_length);
2993} 3074}
2994 3075
2995u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control, 3076u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2996 char *psz_string, const u32 data_length) 3077 char *psz_string, const u32 data_length)
2997{ 3078{
2998 return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_TITLE, 3079 return hpi_control_get_string(h_control, HPI_PAD_TITLE, psz_string,
2999 psz_string, data_length); 3080 data_length);
3000} 3081}
3001 3082
3002u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control, 3083u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3003 char *psz_string, const u32 data_length) 3084 char *psz_string, const u32 data_length)
3004{ 3085{
3005 return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_COMMENT, 3086 return hpi_control_get_string(h_control, HPI_PAD_COMMENT, psz_string,
3006 psz_string, data_length); 3087 data_length);
3007} 3088}
3008 3089
3009u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys, 3090u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
3010 u32 h_control, u32 *ppTY) 3091 u32 h_control, u32 *ppTY)
3011{ 3092{
3012 return hpi_control_param_get(ph_subsys, h_control, 3093 return hpi_control_param1_get(ph_subsys, h_control,
3013 HPI_PAD_PROGRAM_TYPE, 0, 0, ppTY, NULL); 3094 HPI_PAD_PROGRAM_TYPE, ppTY);
3014} 3095}
3015 3096
3016u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control, 3097u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3017 u32 *ppI) 3098 u32 *ppI)
3018{ 3099{
3019 return hpi_control_param_get(ph_subsys, h_control, HPI_PAD_PROGRAM_ID, 3100 return hpi_control_param1_get(ph_subsys, h_control,
3020 0, 0, ppI, NULL); 3101 HPI_PAD_PROGRAM_ID, ppI);
3021} 3102}
3022 3103
3023u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys, 3104u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
@@ -3031,36 +3112,16 @@ u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3031 short an_log_gain[HPI_MAX_CHANNELS] 3112 short an_log_gain[HPI_MAX_CHANNELS]
3032 ) 3113 )
3033{ 3114{
3034 struct hpi_message hm; 3115 return hpi_control_log_set2(h_control, HPI_VOLUME_GAIN,
3035 struct hpi_response hr; 3116 an_log_gain[0], an_log_gain[1]);
3036 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3037 HPI_CONTROL_SET_STATE);
3038 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
3039 memcpy(hm.u.c.an_log_value, an_log_gain,
3040 sizeof(short) * HPI_MAX_CHANNELS);
3041 hm.u.c.attribute = HPI_VOLUME_GAIN;
3042
3043 hpi_send_recv(&hm, &hr);
3044
3045 return hr.error;
3046} 3117}
3047 3118
3048u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, 3119u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3049 short an_log_gain[HPI_MAX_CHANNELS] 3120 short an_log_gain[HPI_MAX_CHANNELS]
3050 ) 3121 )
3051{ 3122{
3052 struct hpi_message hm; 3123 return hpi_control_log_get2(ph_subsys, h_control, HPI_VOLUME_GAIN,
3053 struct hpi_response hr; 3124 &an_log_gain[0], &an_log_gain[1]);
3054 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3055 HPI_CONTROL_GET_STATE);
3056 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
3057 hm.u.c.attribute = HPI_VOLUME_GAIN;
3058
3059 hpi_send_recv(&hm, &hr);
3060
3061 memcpy(an_log_gain, hr.u.c.an_log_value,
3062 sizeof(short) * HPI_MAX_CHANNELS);
3063 return hr.error;
3064} 3125}
3065 3126
3066u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, 3127u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
@@ -3068,6 +3129,7 @@ u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3068{ 3129{
3069 struct hpi_message hm; 3130 struct hpi_message hm;
3070 struct hpi_response hr; 3131 struct hpi_response hr;
3132
3071 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 3133 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3072 HPI_CONTROL_GET_STATE); 3134 HPI_CONTROL_GET_STATE);
3073 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 3135 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -3094,6 +3156,7 @@ u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
3094{ 3156{
3095 struct hpi_message hm; 3157 struct hpi_message hm;
3096 struct hpi_response hr; 3158 struct hpi_response hr;
3159
3097 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, 3160 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3098 HPI_CONTROL_SET_STATE); 3161 HPI_CONTROL_SET_STATE);
3099 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); 3162 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -3170,43 +3233,42 @@ static size_t entity_type_to_size[LAST_ENTITY_TYPE] = {
3170 6 * sizeof(char), 3233 6 * sizeof(char),
3171}; 3234};
3172 3235
3173inline size_t hpi_entity_size(struct hpi_entity *entity_ptr) 3236static inline size_t hpi_entity_size(struct hpi_entity *entity_ptr)
3174{ 3237{
3175 return entity_ptr->header.size; 3238 return entity_ptr->header.size;
3176} 3239}
3177 3240
3178inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr) 3241static inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr)
3179{ 3242{
3180 return sizeof(entity_ptr->header); 3243 return sizeof(entity_ptr->header);
3181} 3244}
3182 3245
3183inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr) 3246static inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr)
3184{ 3247{
3185 return hpi_entity_size(entity_ptr) - 3248 return hpi_entity_size(entity_ptr) -
3186 hpi_entity_header_size(entity_ptr); 3249 hpi_entity_header_size(entity_ptr);
3187} 3250}
3188 3251
3189inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr) 3252static inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr)
3190{ 3253{
3191 return hpi_entity_value_size(entity_ptr) / 3254 return hpi_entity_value_size(entity_ptr) /
3192 entity_type_to_size[entity_ptr->header.type]; 3255 entity_type_to_size[entity_ptr->header.type];
3193} 3256}
3194 3257
3195inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity 3258static inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity
3196 *entity_ptr) 3259 *entity_ptr)
3197{ 3260{
3198 return (void *)(((uint8_t *) entity_ptr) + 3261 return (void *)(((u8 *)entity_ptr) + hpi_entity_size(entity_ptr));
3199 hpi_entity_size(entity_ptr));
3200} 3262}
3201 3263
3202inline u16 hpi_entity_check_type(const enum e_entity_type t) 3264static inline u16 hpi_entity_check_type(const enum e_entity_type t)
3203{ 3265{
3204 if (t >= 0 && t < STR_TYPE_FIELD_MAX) 3266 if (t >= 0 && t < STR_TYPE_FIELD_MAX)
3205 return 0; 3267 return 0;
3206 return HPI_ERROR_ENTITY_TYPE_INVALID; 3268 return HPI_ERROR_ENTITY_TYPE_INVALID;
3207} 3269}
3208 3270
3209inline u16 hpi_entity_check_role(const enum e_entity_role r) 3271static inline u16 hpi_entity_check_role(const enum e_entity_role r)
3210{ 3272{
3211 if (r >= 0 && r < STR_ROLE_FIELD_MAX) 3273 if (r >= 0 && r < STR_ROLE_FIELD_MAX)
3212 return 0; 3274 return 0;
@@ -3624,6 +3686,7 @@ u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async,
3624 u16 maximum_events, struct hpi_async_event *p_events, 3686 u16 maximum_events, struct hpi_async_event *p_events,
3625 u16 *pw_number_returned) 3687 u16 *pw_number_returned)
3626{ 3688{
3689
3627 return 0; 3690 return 0;
3628} 3691}
3629 3692
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c
index 2ee90dc3d897..f01ab964f602 100644
--- a/sound/pci/asihpi/hpimsgx.c
+++ b/sound/pci/asihpi/hpimsgx.c
@@ -741,7 +741,7 @@ static void HPIMSGX__reset(u16 adapter_index)
741 hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, 741 hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM,
742 HPI_SUBSYS_FIND_ADAPTERS, 0); 742 HPI_SUBSYS_FIND_ADAPTERS, 0);
743 memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr, 743 memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
744 sizeof(&gRESP_HPI_SUBSYS_FIND_ADAPTERS)); 744 sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
745 745
746 for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) { 746 for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
747 747
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index 7396ac54e99f..62895a719fcb 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -121,11 +121,17 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
121 phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg; 121 phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;
122 122
123 /* Read the message and response pointers from user space. */ 123 /* Read the message and response pointers from user space. */
124 get_user(puhm, &phpi_ioctl_data->phm); 124 if (get_user(puhm, &phpi_ioctl_data->phm) ||
125 get_user(puhr, &phpi_ioctl_data->phr); 125 get_user(puhr, &phpi_ioctl_data->phr)) {
126 err = -EFAULT;
127 goto out;
128 }
126 129
127 /* Now read the message size and data from user space. */ 130 /* Now read the message size and data from user space. */
128 get_user(hm->h.size, (u16 __user *)puhm); 131 if (get_user(hm->h.size, (u16 __user *)puhm)) {
132 err = -EFAULT;
133 goto out;
134 }
129 if (hm->h.size > sizeof(*hm)) 135 if (hm->h.size > sizeof(*hm))
130 hm->h.size = sizeof(*hm); 136 hm->h.size = sizeof(*hm);
131 137
@@ -138,7 +144,10 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
138 goto out; 144 goto out;
139 } 145 }
140 146
141 get_user(res_max_size, (u16 __user *)puhr); 147 if (get_user(res_max_size, (u16 __user *)puhr)) {
148 err = -EFAULT;
149 goto out;
150 }
142 /* printk(KERN_INFO "user response size %d\n", res_max_size); */ 151 /* printk(KERN_INFO "user response size %d\n", res_max_size); */
143 if (res_max_size < sizeof(struct hpi_response_header)) { 152 if (res_max_size < sizeof(struct hpi_response_header)) {
144 HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size); 153 HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size);
@@ -464,9 +473,7 @@ void __init asihpi_init(void)
464 473
465 memset(adapters, 0, sizeof(adapters)); 474 memset(adapters, 0, sizeof(adapters));
466 475
467 printk(KERN_INFO "ASIHPI driver %d.%02d.%02d\n", 476 printk(KERN_INFO "ASIHPI driver " HPI_VER_STRING "\n");
468 HPI_VER_MAJOR(HPI_VER), HPI_VER_MINOR(HPI_VER),
469 HPI_VER_RELEASE(HPI_VER));
470 477
471 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, 478 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
472 HPI_SUBSYS_DRIVER_LOAD); 479 HPI_SUBSYS_DRIVER_LOAD);
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 668a5ec04499..20763dd03fa0 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -2250,6 +2250,8 @@ static int snd_echo_resume(struct pci_dev *pci)
2250 DE_INIT(("resume start\n")); 2250 DE_INIT(("resume start\n"));
2251 pci_restore_state(pci); 2251 pci_restore_state(pci);
2252 commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL); 2252 commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
2253 if (commpage_bak == NULL)
2254 return -ENOMEM;
2253 commpage = chip->comm_page; 2255 commpage = chip->comm_page;
2254 memcpy(commpage_bak, commpage, sizeof(struct comm_page)); 2256 memcpy(commpage_bak, commpage, sizeof(struct comm_page));
2255 2257
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index ba2098d20ccc..a7802b99436c 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -396,15 +396,18 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
396 } 396 }
397 for (n = prev_nid + 1; n <= val; n++) { 397 for (n = prev_nid + 1; n <= val; n++) {
398 if (conns >= max_conns) { 398 if (conns >= max_conns) {
399 snd_printk(KERN_ERR 399 snd_printk(KERN_ERR "hda_codec: "
400 "Too many connections\n"); 400 "Too many connections %d for NID 0x%x\n",
401 conns, nid);
401 return -EINVAL; 402 return -EINVAL;
402 } 403 }
403 conn_list[conns++] = n; 404 conn_list[conns++] = n;
404 } 405 }
405 } else { 406 } else {
406 if (conns >= max_conns) { 407 if (conns >= max_conns) {
407 snd_printk(KERN_ERR "Too many connections\n"); 408 snd_printk(KERN_ERR "hda_codec: "
409 "Too many connections %d for NID 0x%x\n",
410 conns, nid);
408 return -EINVAL; 411 return -EINVAL;
409 } 412 }
410 conn_list[conns++] = val; 413 conn_list[conns++] = val;
@@ -730,15 +733,17 @@ static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
730 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); 733 total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
731 for (i = 0; i < total_nodes; i++, nid++) { 734 for (i = 0; i < total_nodes; i++, nid++) {
732 function_id = snd_hda_param_read(codec, nid, 735 function_id = snd_hda_param_read(codec, nid,
733 AC_PAR_FUNCTION_TYPE) & 0xff; 736 AC_PAR_FUNCTION_TYPE);
734 switch (function_id) { 737 switch (function_id & 0xff) {
735 case AC_GRP_AUDIO_FUNCTION: 738 case AC_GRP_AUDIO_FUNCTION:
736 codec->afg = nid; 739 codec->afg = nid;
737 codec->function_id = function_id; 740 codec->afg_function_id = function_id & 0xff;
741 codec->afg_unsol = (function_id >> 8) & 1;
738 break; 742 break;
739 case AC_GRP_MODEM_FUNCTION: 743 case AC_GRP_MODEM_FUNCTION:
740 codec->mfg = nid; 744 codec->mfg = nid;
741 codec->function_id = function_id; 745 codec->mfg_function_id = function_id & 0xff;
746 codec->mfg_unsol = (function_id >> 8) & 1;
742 break; 747 break;
743 default: 748 default:
744 break; 749 break;
@@ -1565,6 +1570,17 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
1565EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); 1570EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
1566#endif /* SND_HDA_NEEDS_RESUME */ 1571#endif /* SND_HDA_NEEDS_RESUME */
1567 1572
1573static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
1574 unsigned int ofs)
1575{
1576 u32 caps = query_amp_caps(codec, nid, dir);
1577 /* get num steps */
1578 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1579 if (ofs < caps)
1580 caps -= ofs;
1581 return caps;
1582}
1583
1568/** 1584/**
1569 * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer 1585 * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
1570 * 1586 *
@@ -1579,23 +1595,17 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
1579 u8 chs = get_amp_channels(kcontrol); 1595 u8 chs = get_amp_channels(kcontrol);
1580 int dir = get_amp_direction(kcontrol); 1596 int dir = get_amp_direction(kcontrol);
1581 unsigned int ofs = get_amp_offset(kcontrol); 1597 unsigned int ofs = get_amp_offset(kcontrol);
1582 u32 caps;
1583 1598
1584 caps = query_amp_caps(codec, nid, dir); 1599 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1585 /* num steps */ 1600 uinfo->count = chs == 3 ? 2 : 1;
1586 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; 1601 uinfo->value.integer.min = 0;
1587 if (!caps) { 1602 uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs);
1603 if (!uinfo->value.integer.max) {
1588 printk(KERN_WARNING "hda_codec: " 1604 printk(KERN_WARNING "hda_codec: "
1589 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, 1605 "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
1590 kcontrol->id.name); 1606 kcontrol->id.name);
1591 return -EINVAL; 1607 return -EINVAL;
1592 } 1608 }
1593 if (ofs < caps)
1594 caps -= ofs;
1595 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1596 uinfo->count = chs == 3 ? 2 : 1;
1597 uinfo->value.integer.min = 0;
1598 uinfo->value.integer.max = caps;
1599 return 0; 1609 return 0;
1600} 1610}
1601EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); 1611EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
@@ -1620,8 +1630,14 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
1620 int ch, int dir, int idx, unsigned int ofs, 1630 int ch, int dir, int idx, unsigned int ofs,
1621 unsigned int val) 1631 unsigned int val)
1622{ 1632{
1633 unsigned int maxval;
1634
1623 if (val > 0) 1635 if (val > 0)
1624 val += ofs; 1636 val += ofs;
1637 /* ofs = 0: raw max value */
1638 maxval = get_amp_max_value(codec, nid, dir, 0);
1639 if (val > maxval)
1640 val = maxval;
1625 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, 1641 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
1626 HDA_AMP_VOLMASK, val); 1642 HDA_AMP_VOLMASK, val);
1627} 1643}
@@ -2999,26 +3015,31 @@ struct hda_rate_tbl {
2999 unsigned int hda_fmt; 3015 unsigned int hda_fmt;
3000}; 3016};
3001 3017
3018/* rate = base * mult / div */
3019#define HDA_RATE(base, mult, div) \
3020 (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
3021 (((div) - 1) << AC_FMT_DIV_SHIFT))
3022
3002static struct hda_rate_tbl rate_bits[] = { 3023static struct hda_rate_tbl rate_bits[] = {
3003 /* rate in Hz, ALSA rate bitmask, HDA format value */ 3024 /* rate in Hz, ALSA rate bitmask, HDA format value */
3004 3025
3005 /* autodetected value used in snd_hda_query_supported_pcm */ 3026 /* autodetected value used in snd_hda_query_supported_pcm */
3006 { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */ 3027 { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) },
3007 { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */ 3028 { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) },
3008 { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */ 3029 { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) },
3009 { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */ 3030 { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) },
3010 { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */ 3031 { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) },
3011 { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */ 3032 { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) },
3012 { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */ 3033 { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) },
3013 { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */ 3034 { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) },
3014 { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ 3035 { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) },
3015 { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ 3036 { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) },
3016 { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ 3037 { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) },
3017#define AC_PAR_PCM_RATE_BITS 11 3038#define AC_PAR_PCM_RATE_BITS 11
3018 /* up to bits 10, 384kHZ isn't supported properly */ 3039 /* up to bits 10, 384kHZ isn't supported properly */
3019 3040
3020 /* not autodetected value */ 3041 /* not autodetected value */
3021 { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */ 3042 { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) },
3022 3043
3023 { 0 } /* terminator */ 3044 { 0 } /* terminator */
3024}; 3045};
@@ -3037,7 +3058,8 @@ static struct hda_rate_tbl rate_bits[] = {
3037unsigned int snd_hda_calc_stream_format(unsigned int rate, 3058unsigned int snd_hda_calc_stream_format(unsigned int rate,
3038 unsigned int channels, 3059 unsigned int channels,
3039 unsigned int format, 3060 unsigned int format,
3040 unsigned int maxbps) 3061 unsigned int maxbps,
3062 unsigned short spdif_ctls)
3041{ 3063{
3042 int i; 3064 int i;
3043 unsigned int val = 0; 3065 unsigned int val = 0;
@@ -3060,20 +3082,20 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
3060 3082
3061 switch (snd_pcm_format_width(format)) { 3083 switch (snd_pcm_format_width(format)) {
3062 case 8: 3084 case 8:
3063 val |= 0x00; 3085 val |= AC_FMT_BITS_8;
3064 break; 3086 break;
3065 case 16: 3087 case 16:
3066 val |= 0x10; 3088 val |= AC_FMT_BITS_16;
3067 break; 3089 break;
3068 case 20: 3090 case 20:
3069 case 24: 3091 case 24:
3070 case 32: 3092 case 32:
3071 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) 3093 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
3072 val |= 0x40; 3094 val |= AC_FMT_BITS_32;
3073 else if (maxbps >= 24) 3095 else if (maxbps >= 24)
3074 val |= 0x30; 3096 val |= AC_FMT_BITS_24;
3075 else 3097 else
3076 val |= 0x20; 3098 val |= AC_FMT_BITS_20;
3077 break; 3099 break;
3078 default: 3100 default:
3079 snd_printdd("invalid format width %d\n", 3101 snd_printdd("invalid format width %d\n",
@@ -3081,6 +3103,9 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
3081 return 0; 3103 return 0;
3082 } 3104 }
3083 3105
3106 if (spdif_ctls & AC_DIG1_NONAUDIO)
3107 val |= AC_FMT_TYPE_NON_PCM;
3108
3084 return val; 3109 return val;
3085} 3110}
3086EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); 3111EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 5991d14e1ec0..0328cf55cdba 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -224,6 +224,27 @@ enum {
224/* Input converter SDI select */ 224/* Input converter SDI select */
225#define AC_SDI_SELECT (0xf<<0) 225#define AC_SDI_SELECT (0xf<<0)
226 226
227/* stream format id */
228#define AC_FMT_CHAN_SHIFT 0
229#define AC_FMT_CHAN_MASK (0x0f << 0)
230#define AC_FMT_BITS_SHIFT 4
231#define AC_FMT_BITS_MASK (7 << 4)
232#define AC_FMT_BITS_8 (0 << 4)
233#define AC_FMT_BITS_16 (1 << 4)
234#define AC_FMT_BITS_20 (2 << 4)
235#define AC_FMT_BITS_24 (3 << 4)
236#define AC_FMT_BITS_32 (4 << 4)
237#define AC_FMT_DIV_SHIFT 8
238#define AC_FMT_DIV_MASK (7 << 8)
239#define AC_FMT_MULT_SHIFT 11
240#define AC_FMT_MULT_MASK (7 << 11)
241#define AC_FMT_BASE_SHIFT 14
242#define AC_FMT_BASE_48K (0 << 14)
243#define AC_FMT_BASE_44K (1 << 14)
244#define AC_FMT_TYPE_SHIFT 15
245#define AC_FMT_TYPE_PCM (0 << 15)
246#define AC_FMT_TYPE_NON_PCM (1 << 15)
247
227/* Unsolicited response control */ 248/* Unsolicited response control */
228#define AC_UNSOL_TAG (0x3f<<0) 249#define AC_UNSOL_TAG (0x3f<<0)
229#define AC_UNSOL_ENABLED (1<<7) 250#define AC_UNSOL_ENABLED (1<<7)
@@ -364,6 +385,9 @@ enum {
364#define AC_DIG2_CC (0x7f<<0) 385#define AC_DIG2_CC (0x7f<<0)
365 386
366/* Pin widget control - 8bit */ 387/* Pin widget control - 8bit */
388#define AC_PINCTL_EPT (0x3<<0)
389#define AC_PINCTL_EPT_NATIVE 0
390#define AC_PINCTL_EPT_HBR 3
367#define AC_PINCTL_VREFEN (0x7<<0) 391#define AC_PINCTL_VREFEN (0x7<<0)
368#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ 392#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */
369#define AC_PINCTL_VREF_50 1 /* 50% */ 393#define AC_PINCTL_VREF_50 1 /* 50% */
@@ -760,7 +784,10 @@ struct hda_codec {
760 hda_nid_t mfg; /* MFG node id */ 784 hda_nid_t mfg; /* MFG node id */
761 785
762 /* ids */ 786 /* ids */
763 u32 function_id; 787 u8 afg_function_id;
788 u8 mfg_function_id;
789 u8 afg_unsol;
790 u8 mfg_unsol;
764 u32 vendor_id; 791 u32 vendor_id;
765 u32 subsystem_id; 792 u32 subsystem_id;
766 u32 revision_id; 793 u32 revision_id;
@@ -928,7 +955,8 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
928unsigned int snd_hda_calc_stream_format(unsigned int rate, 955unsigned int snd_hda_calc_stream_format(unsigned int rate,
929 unsigned int channels, 956 unsigned int channels,
930 unsigned int format, 957 unsigned int format,
931 unsigned int maxbps); 958 unsigned int maxbps,
959 unsigned short spdif_ctls);
932int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, 960int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
933 unsigned int format); 961 unsigned int format);
934 962
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index a1fc83753cc6..bf3ced51e0f8 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -649,7 +649,9 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus,
649 *codecp = NULL; 649 *codecp = NULL;
650 if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) { 650 if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) {
651 list_for_each_entry(codec, &bus->codec_list, list) { 651 list_for_each_entry(codec, &bus->codec_list, list) {
652 if (codec->addr == caddr) { 652 if (codec->vendor_id == vendorid &&
653 codec->subsystem_id == subid &&
654 codec->addr == caddr) {
653 *codecp = codec; 655 *codecp = codec;
654 break; 656 break;
655 } 657 }
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 1df25cf5ce38..66d420212d9a 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1653,7 +1653,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
1653 format_val = snd_hda_calc_stream_format(runtime->rate, 1653 format_val = snd_hda_calc_stream_format(runtime->rate,
1654 runtime->channels, 1654 runtime->channels,
1655 runtime->format, 1655 runtime->format,
1656 hinfo->maxbps); 1656 hinfo->maxbps,
1657 apcm->codec->spdif_ctls);
1657 if (!format_val) { 1658 if (!format_val) {
1658 snd_printk(KERN_ERR SFX 1659 snd_printk(KERN_ERR SFX
1659 "invalid format_val, rate=%d, ch=%d, format=%d\n", 1660 "invalid format_val, rate=%d, ch=%d, format=%d\n",
@@ -1960,7 +1961,7 @@ static void azx_irq_pending_work(struct work_struct *work)
1960 spin_unlock_irq(&chip->reg_lock); 1961 spin_unlock_irq(&chip->reg_lock);
1961 if (!pending) 1962 if (!pending)
1962 return; 1963 return;
1963 cond_resched(); 1964 msleep(1);
1964 } 1965 }
1965} 1966}
1966 1967
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index f97d35de66c4..f025200f2a62 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -557,7 +557,12 @@ static void print_codec_info(struct snd_info_entry *entry,
557 else 557 else
558 snd_iprintf(buffer, "Not Set\n"); 558 snd_iprintf(buffer, "Not Set\n");
559 snd_iprintf(buffer, "Address: %d\n", codec->addr); 559 snd_iprintf(buffer, "Address: %d\n", codec->addr);
560 snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id); 560 if (codec->afg)
561 snd_iprintf(buffer, "AFG Function Id: 0x%x (unsol %u)\n",
562 codec->afg_function_id, codec->afg_unsol);
563 if (codec->mfg)
564 snd_iprintf(buffer, "MFG Function Id: 0x%x (unsol %u)\n",
565 codec->mfg_function_id, codec->mfg_unsol);
561 snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id); 566 snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
562 snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id); 567 snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
563 snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); 568 snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index afbe314a5bf3..b697fd2a6f8b 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3662,7 +3662,12 @@ static int patch_ad1984(struct hda_codec *codec)
3662 codec->patch_ops.build_pcms = ad1984_build_pcms; 3662 codec->patch_ops.build_pcms = ad1984_build_pcms;
3663 break; 3663 break;
3664 case AD1984_THINKPAD: 3664 case AD1984_THINKPAD:
3665 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; 3665 if (codec->subsystem_id == 0x17aa20fb) {
3666 /* Thinpad X300 does not have the ability to do SPDIF,
3667 or attach to docking station to use SPDIF */
3668 spec->multiout.dig_out_nid = 0;
3669 } else
3670 spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
3666 spec->input_mux = &ad1984_thinkpad_capture_source; 3671 spec->input_mux = &ad1984_thinkpad_capture_source;
3667 spec->mixers[0] = ad1984_thinkpad_mixers; 3672 spec->mixers[0] = ad1984_thinkpad_mixers;
3668 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; 3673 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 2bf2cb5da956..df8b19b17308 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -131,6 +131,8 @@ struct conexant_spec {
131 unsigned int dc_enable; 131 unsigned int dc_enable;
132 unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */ 132 unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */
133 unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ 133 unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
134
135 unsigned int beep_amp;
134}; 136};
135 137
136static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, 138static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -515,6 +517,15 @@ static struct snd_kcontrol_new cxt_capture_mixers[] = {
515 {} 517 {}
516}; 518};
517 519
520#ifdef CONFIG_SND_HDA_INPUT_BEEP
521/* additional beep mixers; the actual parameters are overwritten at build */
522static struct snd_kcontrol_new cxt_beep_mixer[] = {
523 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
524 HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
525 { } /* end */
526};
527#endif
528
518static const char *slave_vols[] = { 529static const char *slave_vols[] = {
519 "Headphone Playback Volume", 530 "Headphone Playback Volume",
520 "Speaker Playback Volume", 531 "Speaker Playback Volume",
@@ -580,16 +591,52 @@ static int conexant_build_controls(struct hda_codec *codec)
580 return err; 591 return err;
581 } 592 }
582 593
594#ifdef CONFIG_SND_HDA_INPUT_BEEP
595 /* create beep controls if needed */
596 if (spec->beep_amp) {
597 struct snd_kcontrol_new *knew;
598 for (knew = cxt_beep_mixer; knew->name; knew++) {
599 struct snd_kcontrol *kctl;
600 kctl = snd_ctl_new1(knew, codec);
601 if (!kctl)
602 return -ENOMEM;
603 kctl->private_value = spec->beep_amp;
604 err = snd_hda_ctl_add(codec, 0, kctl);
605 if (err < 0)
606 return err;
607 }
608 }
609#endif
610
611 return 0;
612}
613
614#ifdef CONFIG_SND_HDA_POWER_SAVE
615static int conexant_suspend(struct hda_codec *codec, pm_message_t state)
616{
617 snd_hda_shutup_pins(codec);
583 return 0; 618 return 0;
584} 619}
620#endif
585 621
586static struct hda_codec_ops conexant_patch_ops = { 622static struct hda_codec_ops conexant_patch_ops = {
587 .build_controls = conexant_build_controls, 623 .build_controls = conexant_build_controls,
588 .build_pcms = conexant_build_pcms, 624 .build_pcms = conexant_build_pcms,
589 .init = conexant_init, 625 .init = conexant_init,
590 .free = conexant_free, 626 .free = conexant_free,
627#ifdef CONFIG_SND_HDA_POWER_SAVE
628 .suspend = conexant_suspend,
629#endif
630 .reboot_notify = snd_hda_shutup_pins,
591}; 631};
592 632
633#ifdef CONFIG_SND_HDA_INPUT_BEEP
634#define set_beep_amp(spec, nid, idx, dir) \
635 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
636#else
637#define set_beep_amp(spec, nid, idx, dir) /* NOP */
638#endif
639
593/* 640/*
594 * EAPD control 641 * EAPD control
595 * the private value = nid | (invert << 8) 642 * the private value = nid | (invert << 8)
@@ -1130,9 +1177,10 @@ static int patch_cxt5045(struct hda_codec *codec)
1130 spec->num_init_verbs = 1; 1177 spec->num_init_verbs = 1;
1131 spec->init_verbs[0] = cxt5045_init_verbs; 1178 spec->init_verbs[0] = cxt5045_init_verbs;
1132 spec->spdif_route = 0; 1179 spec->spdif_route = 0;
1133 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes), 1180 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes);
1134 spec->channel_mode = cxt5045_modes, 1181 spec->channel_mode = cxt5045_modes;
1135 1182
1183 set_beep_amp(spec, 0x16, 0, 1);
1136 1184
1137 codec->patch_ops = conexant_patch_ops; 1185 codec->patch_ops = conexant_patch_ops;
1138 1186
@@ -1211,6 +1259,9 @@ static int patch_cxt5045(struct hda_codec *codec)
1211 break; 1259 break;
1212 } 1260 }
1213 1261
1262 if (spec->beep_amp)
1263 snd_hda_attach_beep_device(codec, spec->beep_amp);
1264
1214 return 0; 1265 return 0;
1215} 1266}
1216 1267
@@ -1632,6 +1683,11 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
1632 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; 1683 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1633 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 1684 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1634 pinctl); 1685 pinctl);
1686 /* on ideapad there is an aditional speaker (subwoofer) to mute */
1687 if (spec->ideapad)
1688 snd_hda_codec_write(codec, 0x1b, 0,
1689 AC_VERB_SET_PIN_WIDGET_CONTROL,
1690 pinctl);
1635} 1691}
1636 1692
1637/* turn on/off EAPD (+ mute HP) as a master switch */ 1693/* turn on/off EAPD (+ mute HP) as a master switch */
@@ -1888,6 +1944,13 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
1888#endif 1944#endif
1889} 1945}
1890 1946
1947static struct hda_verb cxt5051_ideapad_init_verbs[] = {
1948 /* Subwoofer */
1949 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1950 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1951 { } /* end */
1952};
1953
1891/* initialize jack-sensing, too */ 1954/* initialize jack-sensing, too */
1892static int cxt5051_init(struct hda_codec *codec) 1955static int cxt5051_init(struct hda_codec *codec)
1893{ 1956{
@@ -1917,6 +1980,7 @@ enum {
1917 CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */ 1980 CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */
1918 CXT5051_F700, /* HP Compaq Presario F700 */ 1981 CXT5051_F700, /* HP Compaq Presario F700 */
1919 CXT5051_TOSHIBA, /* Toshiba M300 & co */ 1982 CXT5051_TOSHIBA, /* Toshiba M300 & co */
1983 CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */
1920 CXT5051_MODELS 1984 CXT5051_MODELS
1921}; 1985};
1922 1986
@@ -1927,6 +1991,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
1927 [CXT5051_LENOVO_X200] = "lenovo-x200", 1991 [CXT5051_LENOVO_X200] = "lenovo-x200",
1928 [CXT5051_F700] = "hp-700", 1992 [CXT5051_F700] = "hp-700",
1929 [CXT5051_TOSHIBA] = "toshiba", 1993 [CXT5051_TOSHIBA] = "toshiba",
1994 [CXT5051_IDEAPAD] = "ideapad",
1930}; 1995};
1931 1996
1932static struct snd_pci_quirk cxt5051_cfg_tbl[] = { 1997static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
@@ -1938,6 +2003,7 @@ static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
1938 CXT5051_LAPTOP), 2003 CXT5051_LAPTOP),
1939 SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), 2004 SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
1940 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), 2005 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
2006 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD),
1941 {} 2007 {}
1942}; 2008};
1943 2009
@@ -1972,6 +2038,8 @@ static int patch_cxt5051(struct hda_codec *codec)
1972 spec->cur_adc = 0; 2038 spec->cur_adc = 0;
1973 spec->cur_adc_idx = 0; 2039 spec->cur_adc_idx = 0;
1974 2040
2041 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
2042
1975 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; 2043 codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
1976 2044
1977 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, 2045 board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
@@ -1989,6 +2057,10 @@ static int patch_cxt5051(struct hda_codec *codec)
1989 break; 2057 break;
1990 case CXT5051_LENOVO_X200: 2058 case CXT5051_LENOVO_X200:
1991 spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; 2059 spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
2060 /* Thinkpad X301 does not have S/PDIF wired and no ability
2061 to use a docking station. */
2062 if (codec->subsystem_id == 0x17aa211f)
2063 spec->multiout.dig_out_nid = 0;
1992 break; 2064 break;
1993 case CXT5051_F700: 2065 case CXT5051_F700:
1994 spec->init_verbs[0] = cxt5051_f700_init_verbs; 2066 spec->init_verbs[0] = cxt5051_f700_init_verbs;
@@ -1999,8 +2071,16 @@ static int patch_cxt5051(struct hda_codec *codec)
1999 spec->mixers[0] = cxt5051_toshiba_mixers; 2071 spec->mixers[0] = cxt5051_toshiba_mixers;
2000 spec->auto_mic = AUTO_MIC_PORTB; 2072 spec->auto_mic = AUTO_MIC_PORTB;
2001 break; 2073 break;
2074 case CXT5051_IDEAPAD:
2075 spec->init_verbs[spec->num_init_verbs++] =
2076 cxt5051_ideapad_init_verbs;
2077 spec->ideapad = 1;
2078 break;
2002 } 2079 }
2003 2080
2081 if (spec->beep_amp)
2082 snd_hda_attach_beep_device(codec, spec->beep_amp);
2083
2004 return 0; 2084 return 0;
2005} 2085}
2006 2086
@@ -2616,7 +2696,6 @@ static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
2616 .put = cxt5066_mic_boost_mux_enum_put, 2696 .put = cxt5066_mic_boost_mux_enum_put,
2617 .private_value = 0x23 | 0x100, 2697 .private_value = 0x23 | 0x100,
2618 }, 2698 },
2619 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
2620 {} 2699 {}
2621}; 2700};
2622 2701
@@ -2977,8 +3056,10 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2977 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), 3056 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
2978 SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), 3057 SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
2979 SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), 3058 SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
3059 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
3060 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD),
3061 SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G series (AMD)", CXT5066_IDEAPAD),
2980 SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), 3062 SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
2981 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
2982 {} 3063 {}
2983}; 3064};
2984 3065
@@ -3014,6 +3095,8 @@ static int patch_cxt5066(struct hda_codec *codec)
3014 spec->cur_adc = 0; 3095 spec->cur_adc = 0;
3015 spec->cur_adc_idx = 0; 3096 spec->cur_adc_idx = 0;
3016 3097
3098 set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
3099
3017 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS, 3100 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
3018 cxt5066_models, cxt5066_cfg_tbl); 3101 cxt5066_models, cxt5066_cfg_tbl);
3019 switch (board_config) { 3102 switch (board_config) {
@@ -3062,7 +3145,6 @@ static int patch_cxt5066(struct hda_codec *codec)
3062 spec->port_d_mode = 0; 3145 spec->port_d_mode = 0;
3063 spec->dell_vostro = 1; 3146 spec->dell_vostro = 1;
3064 spec->mic_boost = 3; /* default 30dB gain */ 3147 spec->mic_boost = 3; /* default 30dB gain */
3065 snd_hda_attach_beep_device(codec, 0x13);
3066 3148
3067 /* no S/PDIF out */ 3149 /* no S/PDIF out */
3068 spec->multiout.dig_out_nid = 0; 3150 spec->multiout.dig_out_nid = 0;
@@ -3104,6 +3186,9 @@ static int patch_cxt5066(struct hda_codec *codec)
3104 break; 3186 break;
3105 } 3187 }
3106 3188
3189 if (spec->beep_amp)
3190 snd_hda_attach_beep_device(codec, spec->beep_amp);
3191
3107 return 0; 3192 return 0;
3108} 3193}
3109 3194
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 2fc53961054e..522e0748ee99 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -698,11 +698,51 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
698 * Callbacks 698 * Callbacks
699 */ 699 */
700 700
701static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, 701/* HBR should be Non-PCM, 8 channels */
702#define is_hbr_format(format) \
703 ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7)
704
705static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
702 u32 stream_tag, int format) 706 u32 stream_tag, int format)
703{ 707{
708 struct hdmi_spec *spec = codec->spec;
704 int tag; 709 int tag;
705 int fmt; 710 int fmt;
711 int pinctl;
712 int new_pinctl = 0;
713 int i;
714
715 for (i = 0; i < spec->num_pins; i++) {
716 if (spec->pin_cvt[i] != nid)
717 continue;
718 if (!(snd_hda_query_pin_caps(codec, spec->pin[i]) & AC_PINCAP_HBR))
719 continue;
720
721 pinctl = snd_hda_codec_read(codec, spec->pin[i], 0,
722 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
723
724 new_pinctl = pinctl & ~AC_PINCTL_EPT;
725 if (is_hbr_format(format))
726 new_pinctl |= AC_PINCTL_EPT_HBR;
727 else
728 new_pinctl |= AC_PINCTL_EPT_NATIVE;
729
730 snd_printdd("hdmi_setup_stream: "
731 "NID=0x%x, %spinctl=0x%x\n",
732 spec->pin[i],
733 pinctl == new_pinctl ? "" : "new-",
734 new_pinctl);
735
736 if (pinctl != new_pinctl)
737 snd_hda_codec_write(codec, spec->pin[i], 0,
738 AC_VERB_SET_PIN_WIDGET_CONTROL,
739 new_pinctl);
740 }
741
742 if (is_hbr_format(format) && !new_pinctl) {
743 snd_printdd("hdmi_setup_stream: HBR is not supported\n");
744 return -EINVAL;
745 }
706 746
707 tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; 747 tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
708 fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); 748 fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
@@ -722,6 +762,7 @@ static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
722 if (fmt != format) 762 if (fmt != format)
723 snd_hda_codec_write(codec, nid, 0, 763 snd_hda_codec_write(codec, nid, 0,
724 AC_VERB_SET_STREAM_FORMAT, format); 764 AC_VERB_SET_STREAM_FORMAT, format);
765 return 0;
725} 766}
726 767
727/* 768/*
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index b81d23e42ace..5972d5e7d01f 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -66,8 +66,7 @@ static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
66 66
67 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); 67 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
68 68
69 hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); 69 return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
70 return 0;
71} 70}
72 71
73static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 72static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index b0652acee9b2..a281836fd472 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -202,8 +202,7 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
202 202
203 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); 203 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
204 204
205 hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); 205 return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
206 return 0;
207} 206}
208 207
209static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, 208static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 596ea2f12cf6..6ac53f7de549 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -256,6 +256,13 @@ enum {
256 ALC882_MODEL_LAST, 256 ALC882_MODEL_LAST,
257}; 257};
258 258
259/* ALC680 models */
260enum {
261 ALC680_BASE,
262 ALC680_AUTO,
263 ALC680_MODEL_LAST,
264};
265
259/* for GPIO Poll */ 266/* for GPIO Poll */
260#define GPIO_MASK 0x03 267#define GPIO_MASK 0x03
261 268
@@ -326,6 +333,12 @@ struct alc_spec {
326 hda_nid_t *capsrc_nids; 333 hda_nid_t *capsrc_nids;
327 hda_nid_t dig_in_nid; /* digital-in NID; optional */ 334 hda_nid_t dig_in_nid; /* digital-in NID; optional */
328 335
336 /* capture setup for dynamic dual-adc switch */
337 unsigned int cur_adc_idx;
338 hda_nid_t cur_adc;
339 unsigned int cur_adc_stream_tag;
340 unsigned int cur_adc_format;
341
329 /* capture source */ 342 /* capture source */
330 unsigned int num_mux_defs; 343 unsigned int num_mux_defs;
331 const struct hda_input_mux *input_mux; 344 const struct hda_input_mux *input_mux;
@@ -367,6 +380,7 @@ struct alc_spec {
367 380
368 /* other flags */ 381 /* other flags */
369 unsigned int no_analog :1; /* digital I/O only */ 382 unsigned int no_analog :1; /* digital I/O only */
383 unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
370 int init_amp; 384 int init_amp;
371 385
372 /* for virtual master */ 386 /* for virtual master */
@@ -833,9 +847,13 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
833 847
834 if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { 848 if (auto_pin_type <= AUTO_PIN_FRONT_MIC) {
835 unsigned int pincap; 849 unsigned int pincap;
850 unsigned int oldval;
851 oldval = snd_hda_codec_read(codec, nid, 0,
852 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
836 pincap = snd_hda_query_pin_caps(codec, nid); 853 pincap = snd_hda_query_pin_caps(codec, nid);
837 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; 854 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
838 if (pincap & AC_PINCAP_VREF_80) 855 /* if the default pin setup is vref50, we give it priority */
856 if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
839 val = PIN_VREF80; 857 val = PIN_VREF80;
840 else if (pincap & AC_PINCAP_VREF_50) 858 else if (pincap & AC_PINCAP_VREF_50)
841 val = PIN_VREF50; 859 val = PIN_VREF50;
@@ -1003,6 +1021,29 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
1003 return -1; 1021 return -1;
1004} 1022}
1005 1023
1024/* switch the current ADC according to the jack state */
1025static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec)
1026{
1027 struct alc_spec *spec = codec->spec;
1028 unsigned int present;
1029 hda_nid_t new_adc;
1030
1031 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
1032 if (present)
1033 spec->cur_adc_idx = 1;
1034 else
1035 spec->cur_adc_idx = 0;
1036 new_adc = spec->adc_nids[spec->cur_adc_idx];
1037 if (spec->cur_adc && spec->cur_adc != new_adc) {
1038 /* stream is running, let's swap the current ADC */
1039 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
1040 spec->cur_adc = new_adc;
1041 snd_hda_codec_setup_stream(codec, new_adc,
1042 spec->cur_adc_stream_tag, 0,
1043 spec->cur_adc_format);
1044 }
1045}
1046
1006static void alc_mic_automute(struct hda_codec *codec) 1047static void alc_mic_automute(struct hda_codec *codec)
1007{ 1048{
1008 struct alc_spec *spec = codec->spec; 1049 struct alc_spec *spec = codec->spec;
@@ -1017,6 +1058,11 @@ static void alc_mic_automute(struct hda_codec *codec)
1017 if (snd_BUG_ON(!spec->adc_nids)) 1058 if (snd_BUG_ON(!spec->adc_nids))
1018 return; 1059 return;
1019 1060
1061 if (spec->dual_adc_switch) {
1062 alc_dual_mic_adc_auto_switch(codec);
1063 return;
1064 }
1065
1020 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0]; 1066 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
1021 1067
1022 present = snd_hda_jack_detect(codec, spec->ext_mic.pin); 1068 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
@@ -1499,6 +1545,63 @@ static int alc_read_coef_idx(struct hda_codec *codec,
1499 return val; 1545 return val;
1500} 1546}
1501 1547
1548/* set right pin controls for digital I/O */
1549static void alc_auto_init_digital(struct hda_codec *codec)
1550{
1551 struct alc_spec *spec = codec->spec;
1552 int i;
1553 hda_nid_t pin;
1554
1555 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1556 pin = spec->autocfg.dig_out_pins[i];
1557 if (pin) {
1558 snd_hda_codec_write(codec, pin, 0,
1559 AC_VERB_SET_PIN_WIDGET_CONTROL,
1560 PIN_OUT);
1561 }
1562 }
1563 pin = spec->autocfg.dig_in_pin;
1564 if (pin)
1565 snd_hda_codec_write(codec, pin, 0,
1566 AC_VERB_SET_PIN_WIDGET_CONTROL,
1567 PIN_IN);
1568}
1569
1570/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */
1571static void alc_auto_parse_digital(struct hda_codec *codec)
1572{
1573 struct alc_spec *spec = codec->spec;
1574 int i, err;
1575 hda_nid_t dig_nid;
1576
1577 /* support multiple SPDIFs; the secondary is set up as a slave */
1578 for (i = 0; i < spec->autocfg.dig_outs; i++) {
1579 err = snd_hda_get_connections(codec,
1580 spec->autocfg.dig_out_pins[i],
1581 &dig_nid, 1);
1582 if (err < 0)
1583 continue;
1584 if (!i) {
1585 spec->multiout.dig_out_nid = dig_nid;
1586 spec->dig_out_type = spec->autocfg.dig_out_type[0];
1587 } else {
1588 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
1589 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
1590 break;
1591 spec->slave_dig_outs[i - 1] = dig_nid;
1592 }
1593 }
1594
1595 if (spec->autocfg.dig_in_pin) {
1596 hda_nid_t dig_nid;
1597 err = snd_hda_get_connections(codec,
1598 spec->autocfg.dig_in_pin,
1599 &dig_nid, 1);
1600 if (err > 0)
1601 spec->dig_in_nid = dig_nid;
1602 }
1603}
1604
1502/* 1605/*
1503 * ALC888 1606 * ALC888
1504 */ 1607 */
@@ -3607,6 +3710,41 @@ static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3607 return 0; 3710 return 0;
3608} 3711}
3609 3712
3713/* analog capture with dynamic dual-adc changes */
3714static int dualmic_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3715 struct hda_codec *codec,
3716 unsigned int stream_tag,
3717 unsigned int format,
3718 struct snd_pcm_substream *substream)
3719{
3720 struct alc_spec *spec = codec->spec;
3721 spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
3722 spec->cur_adc_stream_tag = stream_tag;
3723 spec->cur_adc_format = format;
3724 snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
3725 return 0;
3726}
3727
3728static int dualmic_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3729 struct hda_codec *codec,
3730 struct snd_pcm_substream *substream)
3731{
3732 struct alc_spec *spec = codec->spec;
3733 snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
3734 spec->cur_adc = 0;
3735 return 0;
3736}
3737
3738static struct hda_pcm_stream dualmic_pcm_analog_capture = {
3739 .substreams = 1,
3740 .channels_min = 2,
3741 .channels_max = 2,
3742 .nid = 0, /* fill later */
3743 .ops = {
3744 .prepare = dualmic_capture_pcm_prepare,
3745 .cleanup = dualmic_capture_pcm_cleanup
3746 },
3747};
3610 3748
3611/* 3749/*
3612 */ 3750 */
@@ -4936,7 +5074,7 @@ static void alc880_auto_init_input_src(struct hda_codec *codec)
4936static int alc880_parse_auto_config(struct hda_codec *codec) 5074static int alc880_parse_auto_config(struct hda_codec *codec)
4937{ 5075{
4938 struct alc_spec *spec = codec->spec; 5076 struct alc_spec *spec = codec->spec;
4939 int i, err; 5077 int err;
4940 static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; 5078 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
4941 5079
4942 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 5080 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
@@ -4967,25 +5105,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
4967 5105
4968 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 5106 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4969 5107
4970 /* check multiple SPDIF-out (for recent codecs) */ 5108 alc_auto_parse_digital(codec);
4971 for (i = 0; i < spec->autocfg.dig_outs; i++) {
4972 hda_nid_t dig_nid;
4973 err = snd_hda_get_connections(codec,
4974 spec->autocfg.dig_out_pins[i],
4975 &dig_nid, 1);
4976 if (err < 0)
4977 continue;
4978 if (!i)
4979 spec->multiout.dig_out_nid = dig_nid;
4980 else {
4981 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
4982 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
4983 break;
4984 spec->slave_dig_outs[i - 1] = dig_nid;
4985 }
4986 }
4987 if (spec->autocfg.dig_in_pin)
4988 spec->dig_in_nid = ALC880_DIGIN_NID;
4989 5109
4990 if (spec->kctls.list) 5110 if (spec->kctls.list)
4991 add_mixer(spec, spec->kctls.list); 5111 add_mixer(spec, spec->kctls.list);
@@ -5008,6 +5128,7 @@ static void alc880_auto_init(struct hda_codec *codec)
5008 alc880_auto_init_extra_out(codec); 5128 alc880_auto_init_extra_out(codec);
5009 alc880_auto_init_analog_input(codec); 5129 alc880_auto_init_analog_input(codec);
5010 alc880_auto_init_input_src(codec); 5130 alc880_auto_init_input_src(codec);
5131 alc_auto_init_digital(codec);
5011 if (spec->unsol_event) 5132 if (spec->unsol_event)
5012 alc_inithook(codec); 5133 alc_inithook(codec);
5013} 5134}
@@ -5045,6 +5166,39 @@ static void fixup_automic_adc(struct hda_codec *codec)
5045 spec->auto_mic = 0; /* disable auto-mic to be sure */ 5166 spec->auto_mic = 0; /* disable auto-mic to be sure */
5046} 5167}
5047 5168
5169/* select or unmute the given capsrc route */
5170static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap,
5171 int idx)
5172{
5173 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
5174 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
5175 HDA_AMP_MUTE, 0);
5176 } else {
5177 snd_hda_codec_write_cache(codec, cap, 0,
5178 AC_VERB_SET_CONNECT_SEL, idx);
5179 }
5180}
5181
5182/* set the default connection to that pin */
5183static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
5184{
5185 struct alc_spec *spec = codec->spec;
5186 int i;
5187
5188 for (i = 0; i < spec->num_adc_nids; i++) {
5189 hda_nid_t cap = spec->capsrc_nids ?
5190 spec->capsrc_nids[i] : spec->adc_nids[i];
5191 int idx;
5192
5193 idx = get_connection_index(codec, cap, pin);
5194 if (idx < 0)
5195 continue;
5196 select_or_unmute_capsrc(codec, cap, idx);
5197 return i; /* return the found index */
5198 }
5199 return -1; /* not found */
5200}
5201
5048/* choose the ADC/MUX containing the input pin and initialize the setup */ 5202/* choose the ADC/MUX containing the input pin and initialize the setup */
5049static void fixup_single_adc(struct hda_codec *codec) 5203static void fixup_single_adc(struct hda_codec *codec)
5050{ 5204{
@@ -5061,33 +5215,24 @@ static void fixup_single_adc(struct hda_codec *codec)
5061 } 5215 }
5062 if (!pin) 5216 if (!pin)
5063 return; 5217 return;
5064 5218 i = init_capsrc_for_pin(codec, pin);
5065 /* set the default connection to that pin */ 5219 if (i >= 0) {
5066 for (i = 0; i < spec->num_adc_nids; i++) {
5067 hda_nid_t cap = spec->capsrc_nids ?
5068 spec->capsrc_nids[i] : spec->adc_nids[i];
5069 int idx;
5070
5071 idx = get_connection_index(codec, cap, pin);
5072 if (idx < 0)
5073 continue;
5074 /* use only this ADC */ 5220 /* use only this ADC */
5075 if (spec->capsrc_nids) 5221 if (spec->capsrc_nids)
5076 spec->capsrc_nids += i; 5222 spec->capsrc_nids += i;
5077 spec->adc_nids += i; 5223 spec->adc_nids += i;
5078 spec->num_adc_nids = 1; 5224 spec->num_adc_nids = 1;
5079 /* select or unmute this route */
5080 if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
5081 snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
5082 HDA_AMP_MUTE, 0);
5083 } else {
5084 snd_hda_codec_write_cache(codec, cap, 0,
5085 AC_VERB_SET_CONNECT_SEL, idx);
5086 }
5087 return;
5088 } 5225 }
5089} 5226}
5090 5227
5228/* initialize dual adcs */
5229static void fixup_dual_adc_switch(struct hda_codec *codec)
5230{
5231 struct alc_spec *spec = codec->spec;
5232 init_capsrc_for_pin(codec, spec->ext_mic.pin);
5233 init_capsrc_for_pin(codec, spec->int_mic.pin);
5234}
5235
5091static void set_capture_mixer(struct hda_codec *codec) 5236static void set_capture_mixer(struct hda_codec *codec)
5092{ 5237{
5093 struct alc_spec *spec = codec->spec; 5238 struct alc_spec *spec = codec->spec;
@@ -5101,7 +5246,10 @@ static void set_capture_mixer(struct hda_codec *codec)
5101 }; 5246 };
5102 if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { 5247 if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
5103 int mux = 0; 5248 int mux = 0;
5104 if (spec->auto_mic) 5249 int num_adcs = spec->num_adc_nids;
5250 if (spec->dual_adc_switch)
5251 fixup_dual_adc_switch(codec);
5252 else if (spec->auto_mic)
5105 fixup_automic_adc(codec); 5253 fixup_automic_adc(codec);
5106 else if (spec->input_mux) { 5254 else if (spec->input_mux) {
5107 if (spec->input_mux->num_items > 1) 5255 if (spec->input_mux->num_items > 1)
@@ -5109,7 +5257,9 @@ static void set_capture_mixer(struct hda_codec *codec)
5109 else if (spec->input_mux->num_items == 1) 5257 else if (spec->input_mux->num_items == 1)
5110 fixup_single_adc(codec); 5258 fixup_single_adc(codec);
5111 } 5259 }
5112 spec->cap_mixer = caps[mux][spec->num_adc_nids - 1]; 5260 if (spec->dual_adc_switch)
5261 num_adcs = 1;
5262 spec->cap_mixer = caps[mux][num_adcs - 1];
5113 } 5263 }
5114} 5264}
5115 5265
@@ -5183,6 +5333,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
5183 5333
5184static struct snd_pci_quirk beep_white_list[] = { 5334static struct snd_pci_quirk beep_white_list[] = {
5185 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), 5335 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
5336 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
5186 {} 5337 {}
5187}; 5338};
5188 5339
@@ -6624,6 +6775,7 @@ static void alc260_auto_init(struct hda_codec *codec)
6624 alc260_auto_init_multi_out(codec); 6775 alc260_auto_init_multi_out(codec);
6625 alc260_auto_init_analog_input(codec); 6776 alc260_auto_init_analog_input(codec);
6626 alc260_auto_init_input_src(codec); 6777 alc260_auto_init_input_src(codec);
6778 alc_auto_init_digital(codec);
6627 if (spec->unsol_event) 6779 if (spec->unsol_event)
6628 alc_inithook(codec); 6780 alc_inithook(codec);
6629} 6781}
@@ -6640,6 +6792,29 @@ static struct hda_amp_list alc260_loopbacks[] = {
6640#endif 6792#endif
6641 6793
6642/* 6794/*
6795 * Pin config fixes
6796 */
6797enum {
6798 PINFIX_HP_DC5750,
6799};
6800
6801static struct alc_pincfg alc260_hp_dc5750_pinfix[] = {
6802 { 0x11, 0x90130110 }, /* speaker */
6803 { }
6804};
6805
6806static const struct alc_fixup alc260_fixups[] = {
6807 [PINFIX_HP_DC5750] = {
6808 .pins = alc260_hp_dc5750_pinfix
6809 },
6810};
6811
6812static struct snd_pci_quirk alc260_fixup_tbl[] = {
6813 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
6814 {}
6815};
6816
6817/*
6643 * ALC260 configurations 6818 * ALC260 configurations
6644 */ 6819 */
6645static const char *alc260_models[ALC260_MODEL_LAST] = { 6820static const char *alc260_models[ALC260_MODEL_LAST] = {
@@ -6838,6 +7013,9 @@ static int patch_alc260(struct hda_codec *codec)
6838 board_config = ALC260_AUTO; 7013 board_config = ALC260_AUTO;
6839 } 7014 }
6840 7015
7016 if (board_config == ALC260_AUTO)
7017 alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 1);
7018
6841 if (board_config == ALC260_AUTO) { 7019 if (board_config == ALC260_AUTO) {
6842 /* automatic parse from the BIOS config */ 7020 /* automatic parse from the BIOS config */
6843 err = alc260_parse_auto_config(codec); 7021 err = alc260_parse_auto_config(codec);
@@ -6883,6 +7061,9 @@ static int patch_alc260(struct hda_codec *codec)
6883 set_capture_mixer(codec); 7061 set_capture_mixer(codec);
6884 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); 7062 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
6885 7063
7064 if (board_config == ALC260_AUTO)
7065 alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 0);
7066
6886 spec->vmaster_nid = 0x08; 7067 spec->vmaster_nid = 0x08;
6887 7068
6888 codec->patch_ops = alc_patch_ops; 7069 codec->patch_ops = alc_patch_ops;
@@ -7003,7 +7184,7 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
7003 .num_items = 4, 7184 .num_items = 4,
7004 .items = { 7185 .items = {
7005 { "Mic", 0x0 }, 7186 { "Mic", 0x0 },
7006 { "iMic", 0x1 }, 7187 { "Int Mic", 0x1 },
7007 { "Line", 0x2 }, 7188 { "Line", 0x2 },
7008 { "CD", 0x4 }, 7189 { "CD", 0x4 },
7009 }, 7190 },
@@ -8573,8 +8754,8 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
8573 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), 8754 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8574 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 8755 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8575 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 8756 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8576 HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), 8757 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8577 HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), 8758 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8578 { } /* end */ 8759 { } /* end */
8579}; 8760};
8580 8761
@@ -10265,7 +10446,8 @@ static struct alc_config_preset alc882_presets[] = {
10265 * Pin config fixes 10446 * Pin config fixes
10266 */ 10447 */
10267enum { 10448enum {
10268 PINFIX_ABIT_AW9D_MAX 10449 PINFIX_ABIT_AW9D_MAX,
10450 PINFIX_PB_M5210,
10269}; 10451};
10270 10452
10271static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { 10453static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
@@ -10275,13 +10457,22 @@ static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
10275 { } 10457 { }
10276}; 10458};
10277 10459
10460static const struct hda_verb pb_m5210_verbs[] = {
10461 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
10462 {}
10463};
10464
10278static const struct alc_fixup alc882_fixups[] = { 10465static const struct alc_fixup alc882_fixups[] = {
10279 [PINFIX_ABIT_AW9D_MAX] = { 10466 [PINFIX_ABIT_AW9D_MAX] = {
10280 .pins = alc882_abit_aw9d_pinfix 10467 .pins = alc882_abit_aw9d_pinfix
10281 }, 10468 },
10469 [PINFIX_PB_M5210] = {
10470 .verbs = pb_m5210_verbs
10471 },
10282}; 10472};
10283 10473
10284static struct snd_pci_quirk alc882_fixup_tbl[] = { 10474static struct snd_pci_quirk alc882_fixup_tbl[] = {
10475 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
10285 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), 10476 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
10286 {} 10477 {}
10287}; 10478};
@@ -10446,7 +10637,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
10446{ 10637{
10447 struct alc_spec *spec = codec->spec; 10638 struct alc_spec *spec = codec->spec;
10448 static hda_nid_t alc882_ignore[] = { 0x1d, 0 }; 10639 static hda_nid_t alc882_ignore[] = { 0x1d, 0 };
10449 int i, err; 10640 int err;
10450 10641
10451 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 10642 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
10452 alc882_ignore); 10643 alc882_ignore);
@@ -10476,25 +10667,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
10476 10667
10477 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 10668 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
10478 10669
10479 /* check multiple SPDIF-out (for recent codecs) */ 10670 alc_auto_parse_digital(codec);
10480 for (i = 0; i < spec->autocfg.dig_outs; i++) {
10481 hda_nid_t dig_nid;
10482 err = snd_hda_get_connections(codec,
10483 spec->autocfg.dig_out_pins[i],
10484 &dig_nid, 1);
10485 if (err < 0)
10486 continue;
10487 if (!i)
10488 spec->multiout.dig_out_nid = dig_nid;
10489 else {
10490 spec->multiout.slave_dig_outs = spec->slave_dig_outs;
10491 if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
10492 break;
10493 spec->slave_dig_outs[i - 1] = dig_nid;
10494 }
10495 }
10496 if (spec->autocfg.dig_in_pin)
10497 spec->dig_in_nid = ALC880_DIGIN_NID;
10498 10671
10499 if (spec->kctls.list) 10672 if (spec->kctls.list)
10500 add_mixer(spec, spec->kctls.list); 10673 add_mixer(spec, spec->kctls.list);
@@ -10524,6 +10697,7 @@ static void alc882_auto_init(struct hda_codec *codec)
10524 alc882_auto_init_hp_out(codec); 10697 alc882_auto_init_hp_out(codec);
10525 alc882_auto_init_analog_input(codec); 10698 alc882_auto_init_analog_input(codec);
10526 alc882_auto_init_input_src(codec); 10699 alc882_auto_init_input_src(codec);
10700 alc_auto_init_digital(codec);
10527 if (spec->unsol_event) 10701 if (spec->unsol_event)
10528 alc_inithook(codec); 10702 alc_inithook(codec);
10529} 10703}
@@ -12054,12 +12228,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
12054 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 12228 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
12055 12229
12056 dig_only: 12230 dig_only:
12057 if (spec->autocfg.dig_outs) { 12231 alc_auto_parse_digital(codec);
12058 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
12059 spec->dig_out_type = spec->autocfg.dig_out_type[0];
12060 }
12061 if (spec->autocfg.dig_in_pin)
12062 spec->dig_in_nid = ALC262_DIGIN_NID;
12063 12232
12064 if (spec->kctls.list) 12233 if (spec->kctls.list)
12065 add_mixer(spec, spec->kctls.list); 12234 add_mixer(spec, spec->kctls.list);
@@ -12091,6 +12260,7 @@ static void alc262_auto_init(struct hda_codec *codec)
12091 alc262_auto_init_hp_out(codec); 12260 alc262_auto_init_hp_out(codec);
12092 alc262_auto_init_analog_input(codec); 12261 alc262_auto_init_analog_input(codec);
12093 alc262_auto_init_input_src(codec); 12262 alc262_auto_init_input_src(codec);
12263 alc_auto_init_digital(codec);
12094 if (spec->unsol_event) 12264 if (spec->unsol_event)
12095 alc_inithook(codec); 12265 alc_inithook(codec);
12096} 12266}
@@ -13024,10 +13194,14 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
13024 dac = 0x02; 13194 dac = 0x02;
13025 break; 13195 break;
13026 case 0x15: 13196 case 0x15:
13197 case 0x1a: /* ALC259/269 only */
13198 case 0x1b: /* ALC259/269 only */
13027 case 0x21: /* ALC269vb has this pin, too */ 13199 case 0x21: /* ALC269vb has this pin, too */
13028 dac = 0x03; 13200 dac = 0x03;
13029 break; 13201 break;
13030 default: 13202 default:
13203 snd_printd(KERN_WARNING "hda_codec: "
13204 "ignoring pin 0x%x as unknown\n", nid);
13031 return 0; 13205 return 0;
13032 } 13206 }
13033 if (spec->multiout.dac_nids[0] != dac && 13207 if (spec->multiout.dac_nids[0] != dac &&
@@ -13078,7 +13252,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
13078 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); 13252 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
13079 if (err < 0) 13253 if (err < 0)
13080 return err; 13254 return err;
13081 } else { 13255 } else if (nid) {
13082 err = alc268_new_analog_output(spec, nid, "Speaker", 0); 13256 err = alc268_new_analog_output(spec, nid, "Speaker", 0);
13083 if (err < 0) 13257 if (err < 0)
13084 return err; 13258 return err;
@@ -13227,10 +13401,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
13227 13401
13228 dig_only: 13402 dig_only:
13229 /* digital only support output */ 13403 /* digital only support output */
13230 if (spec->autocfg.dig_outs) { 13404 alc_auto_parse_digital(codec);
13231 spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
13232 spec->dig_out_type = spec->autocfg.dig_out_type[0];
13233 }
13234 if (spec->kctls.list) 13405 if (spec->kctls.list)
13235 add_mixer(spec, spec->kctls.list); 13406 add_mixer(spec, spec->kctls.list);
13236 13407
@@ -13260,6 +13431,7 @@ static void alc268_auto_init(struct hda_codec *codec)
13260 alc268_auto_init_hp_out(codec); 13431 alc268_auto_init_hp_out(codec);
13261 alc268_auto_init_mono_speaker_out(codec); 13432 alc268_auto_init_mono_speaker_out(codec);
13262 alc268_auto_init_analog_input(codec); 13433 alc268_auto_init_analog_input(codec);
13434 alc_auto_init_digital(codec);
13263 if (spec->unsol_event) 13435 if (spec->unsol_event)
13264 alc_inithook(codec); 13436 alc_inithook(codec);
13265} 13437}
@@ -14152,6 +14324,36 @@ static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
14152} 14324}
14153#endif /* CONFIG_SND_HDA_POWER_SAVE */ 14325#endif /* CONFIG_SND_HDA_POWER_SAVE */
14154 14326
14327static int alc275_setup_dual_adc(struct hda_codec *codec)
14328{
14329 struct alc_spec *spec = codec->spec;
14330
14331 if (codec->vendor_id != 0x10ec0275 || !spec->auto_mic)
14332 return 0;
14333 if ((spec->ext_mic.pin >= 0x18 && spec->int_mic.pin <= 0x13) ||
14334 (spec->ext_mic.pin <= 0x12 && spec->int_mic.pin >= 0x18)) {
14335 if (spec->ext_mic.pin <= 0x12) {
14336 spec->private_adc_nids[0] = 0x08;
14337 spec->private_adc_nids[1] = 0x11;
14338 spec->private_capsrc_nids[0] = 0x23;
14339 spec->private_capsrc_nids[1] = 0x22;
14340 } else {
14341 spec->private_adc_nids[0] = 0x11;
14342 spec->private_adc_nids[1] = 0x08;
14343 spec->private_capsrc_nids[0] = 0x22;
14344 spec->private_capsrc_nids[1] = 0x23;
14345 }
14346 spec->adc_nids = spec->private_adc_nids;
14347 spec->capsrc_nids = spec->private_capsrc_nids;
14348 spec->num_adc_nids = 2;
14349 spec->dual_adc_switch = 1;
14350 snd_printdd("realtek: enabling dual ADC switchg (%02x:%02x)\n",
14351 spec->adc_nids[0], spec->adc_nids[1]);
14352 return 1;
14353 }
14354 return 0;
14355}
14356
14155/* 14357/*
14156 * BIOS auto configuration 14358 * BIOS auto configuration
14157 */ 14359 */
@@ -14175,8 +14377,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
14175 14377
14176 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 14378 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
14177 14379
14178 if (spec->autocfg.dig_outs) 14380 alc_auto_parse_digital(codec);
14179 spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
14180 14381
14181 if (spec->kctls.list) 14382 if (spec->kctls.list)
14182 add_mixer(spec, spec->kctls.list); 14383 add_mixer(spec, spec->kctls.list);
@@ -14191,13 +14392,15 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
14191 14392
14192 spec->num_mux_defs = 1; 14393 spec->num_mux_defs = 1;
14193 spec->input_mux = &spec->private_imux[0]; 14394 spec->input_mux = &spec->private_imux[0];
14194 fillup_priv_adc_nids(codec, alc269_adc_candidates, 14395
14195 sizeof(alc269_adc_candidates)); 14396 if (!alc275_setup_dual_adc(codec))
14397 fillup_priv_adc_nids(codec, alc269_adc_candidates,
14398 sizeof(alc269_adc_candidates));
14196 14399
14197 /* set default input source */ 14400 /* set default input source */
14198 snd_hda_codec_write_cache(codec, spec->capsrc_nids[0], 14401 if (!spec->dual_adc_switch)
14199 0, AC_VERB_SET_CONNECT_SEL, 14402 select_or_unmute_capsrc(codec, spec->capsrc_nids[0],
14200 spec->input_mux->items[0].index); 14403 spec->input_mux->items[0].index);
14201 14404
14202 err = alc_auto_add_mic_boost(codec); 14405 err = alc_auto_add_mic_boost(codec);
14203 if (err < 0) 14406 if (err < 0)
@@ -14221,6 +14424,7 @@ static void alc269_auto_init(struct hda_codec *codec)
14221 alc269_auto_init_multi_out(codec); 14424 alc269_auto_init_multi_out(codec);
14222 alc269_auto_init_hp_out(codec); 14425 alc269_auto_init_hp_out(codec);
14223 alc269_auto_init_analog_input(codec); 14426 alc269_auto_init_analog_input(codec);
14427 alc_auto_init_digital(codec);
14224 if (spec->unsol_event) 14428 if (spec->unsol_event)
14225 alc_inithook(codec); 14429 alc_inithook(codec);
14226} 14430}
@@ -14493,6 +14697,10 @@ static int patch_alc269(struct hda_codec *codec)
14493 */ 14697 */
14494 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback; 14698 spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
14495 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; 14699 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
14700 } else if (spec->dual_adc_switch) {
14701 spec->stream_analog_playback = &alc269_pcm_analog_playback;
14702 /* switch ADC dynamically */
14703 spec->stream_analog_capture = &dualmic_pcm_analog_capture;
14496 } else { 14704 } else {
14497 spec->stream_analog_playback = &alc269_pcm_analog_playback; 14705 spec->stream_analog_playback = &alc269_pcm_analog_playback;
14498 spec->stream_analog_capture = &alc269_pcm_analog_capture; 14706 spec->stream_analog_capture = &alc269_pcm_analog_capture;
@@ -15378,8 +15586,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
15378 15586
15379 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 15587 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
15380 15588
15381 if (spec->autocfg.dig_outs) 15589 alc_auto_parse_digital(codec);
15382 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
15383 15590
15384 if (spec->kctls.list) 15591 if (spec->kctls.list)
15385 add_mixer(spec, spec->kctls.list); 15592 add_mixer(spec, spec->kctls.list);
@@ -15405,6 +15612,7 @@ static void alc861_auto_init(struct hda_codec *codec)
15405 alc861_auto_init_multi_out(codec); 15612 alc861_auto_init_multi_out(codec);
15406 alc861_auto_init_hp_out(codec); 15613 alc861_auto_init_hp_out(codec);
15407 alc861_auto_init_analog_input(codec); 15614 alc861_auto_init_analog_input(codec);
15615 alc_auto_init_digital(codec);
15408 if (spec->unsol_event) 15616 if (spec->unsol_event)
15409 alc_inithook(codec); 15617 alc_inithook(codec);
15410} 15618}
@@ -16509,8 +16717,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
16509 16717
16510 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 16718 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
16511 16719
16512 if (spec->autocfg.dig_outs) 16720 alc_auto_parse_digital(codec);
16513 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
16514 16721
16515 if (spec->kctls.list) 16722 if (spec->kctls.list)
16516 add_mixer(spec, spec->kctls.list); 16723 add_mixer(spec, spec->kctls.list);
@@ -16537,6 +16744,7 @@ static void alc861vd_auto_init(struct hda_codec *codec)
16537 alc861vd_auto_init_hp_out(codec); 16744 alc861vd_auto_init_hp_out(codec);
16538 alc861vd_auto_init_analog_input(codec); 16745 alc861vd_auto_init_analog_input(codec);
16539 alc861vd_auto_init_input_src(codec); 16746 alc861vd_auto_init_input_src(codec);
16747 alc_auto_init_digital(codec);
16540 if (spec->unsol_event) 16748 if (spec->unsol_event)
16541 alc_inithook(codec); 16749 alc_inithook(codec);
16542} 16750}
@@ -18520,7 +18728,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
18520 hda_nid_t dac) 18728 hda_nid_t dac)
18521{ 18729{
18522 int i, num; 18730 int i, num;
18523 hda_nid_t srcs[4]; 18731 hda_nid_t srcs[HDA_MAX_CONNECTIONS];
18524 18732
18525 alc_set_pin_output(codec, nid, pin_type); 18733 alc_set_pin_output(codec, nid, pin_type);
18526 /* need the manual connection? */ 18734 /* need the manual connection? */
@@ -18624,8 +18832,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
18624 18832
18625 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 18833 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
18626 18834
18627 if (spec->autocfg.dig_outs) 18835 alc_auto_parse_digital(codec);
18628 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
18629 18836
18630 if (spec->kctls.list) 18837 if (spec->kctls.list)
18631 add_mixer(spec, spec->kctls.list); 18838 add_mixer(spec, spec->kctls.list);
@@ -18635,7 +18842,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
18635 18842
18636 add_verb(spec, alc662_init_verbs); 18843 add_verb(spec, alc662_init_verbs);
18637 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || 18844 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
18638 codec->vendor_id == 0x10ec0665) 18845 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
18639 add_verb(spec, alc663_init_verbs); 18846 add_verb(spec, alc663_init_verbs);
18640 18847
18641 if (codec->vendor_id == 0x10ec0272) 18848 if (codec->vendor_id == 0x10ec0272)
@@ -18662,6 +18869,7 @@ static void alc662_auto_init(struct hda_codec *codec)
18662 alc662_auto_init_hp_out(codec); 18869 alc662_auto_init_hp_out(codec);
18663 alc662_auto_init_analog_input(codec); 18870 alc662_auto_init_analog_input(codec);
18664 alc662_auto_init_input_src(codec); 18871 alc662_auto_init_input_src(codec);
18872 alc_auto_init_digital(codec);
18665 if (spec->unsol_event) 18873 if (spec->unsol_event)
18666 alc_inithook(codec); 18874 alc_inithook(codec);
18667} 18875}
@@ -18781,6 +18989,333 @@ static int patch_alc888(struct hda_codec *codec)
18781} 18989}
18782 18990
18783/* 18991/*
18992 * ALC680 support
18993 */
18994#define ALC680_DIGOUT_NID ALC880_DIGOUT_NID
18995#define alc680_modes alc260_modes
18996
18997static hda_nid_t alc680_dac_nids[3] = {
18998 /* Lout1, Lout2, hp */
18999 0x02, 0x03, 0x04
19000};
19001
19002static hda_nid_t alc680_adc_nids[3] = {
19003 /* ADC0-2 */
19004 /* DMIC, MIC, Line-in*/
19005 0x07, 0x08, 0x09
19006};
19007
19008static struct snd_kcontrol_new alc680_base_mixer[] = {
19009 /* output mixer control */
19010 HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
19011 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
19012 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
19013 HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
19014 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
19015 { }
19016};
19017
19018static struct snd_kcontrol_new alc680_capture_mixer[] = {
19019 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
19020 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
19021 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
19022 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
19023 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
19024 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
19025 { } /* end */
19026};
19027
19028/*
19029 * generic initialization of ADC, input mixers and output mixers
19030 */
19031static struct hda_verb alc680_init_verbs[] = {
19032 /* Unmute DAC0-1 and set vol = 0 */
19033 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
19034 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
19035 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
19036
19037 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
19038 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
19039 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
19040 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
19041 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
19042
19043 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19044 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19045 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19046 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19047 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
19048 { }
19049};
19050
19051/* create input playback/capture controls for the given pin */
19052static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
19053 const char *ctlname, int idx)
19054{
19055 hda_nid_t dac;
19056 int err;
19057
19058 switch (nid) {
19059 case 0x14:
19060 dac = 0x02;
19061 break;
19062 case 0x15:
19063 dac = 0x03;
19064 break;
19065 case 0x16:
19066 dac = 0x04;
19067 break;
19068 default:
19069 return 0;
19070 }
19071 if (spec->multiout.dac_nids[0] != dac &&
19072 spec->multiout.dac_nids[1] != dac) {
19073 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
19074 HDA_COMPOSE_AMP_VAL(dac, 3, idx,
19075 HDA_OUTPUT));
19076 if (err < 0)
19077 return err;
19078
19079 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
19080 HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT));
19081
19082 if (err < 0)
19083 return err;
19084 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
19085 }
19086
19087 return 0;
19088}
19089
19090/* add playback controls from the parsed DAC table */
19091static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec,
19092 const struct auto_pin_cfg *cfg)
19093{
19094 hda_nid_t nid;
19095 int err;
19096
19097 spec->multiout.dac_nids = spec->private_dac_nids;
19098
19099 nid = cfg->line_out_pins[0];
19100 if (nid) {
19101 const char *name;
19102 if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
19103 name = "Speaker";
19104 else
19105 name = "Front";
19106 err = alc680_new_analog_output(spec, nid, name, 0);
19107 if (err < 0)
19108 return err;
19109 }
19110
19111 nid = cfg->speaker_pins[0];
19112 if (nid) {
19113 err = alc680_new_analog_output(spec, nid, "Speaker", 0);
19114 if (err < 0)
19115 return err;
19116 }
19117 nid = cfg->hp_pins[0];
19118 if (nid) {
19119 err = alc680_new_analog_output(spec, nid, "Headphone", 0);
19120 if (err < 0)
19121 return err;
19122 }
19123
19124 return 0;
19125}
19126
19127static void alc680_auto_set_output_and_unmute(struct hda_codec *codec,
19128 hda_nid_t nid, int pin_type)
19129{
19130 alc_set_pin_output(codec, nid, pin_type);
19131}
19132
19133static void alc680_auto_init_multi_out(struct hda_codec *codec)
19134{
19135 struct alc_spec *spec = codec->spec;
19136 hda_nid_t nid = spec->autocfg.line_out_pins[0];
19137 if (nid) {
19138 int pin_type = get_pin_type(spec->autocfg.line_out_type);
19139 alc680_auto_set_output_and_unmute(codec, nid, pin_type);
19140 }
19141}
19142
19143static void alc680_auto_init_hp_out(struct hda_codec *codec)
19144{
19145 struct alc_spec *spec = codec->spec;
19146 hda_nid_t pin;
19147
19148 pin = spec->autocfg.hp_pins[0];
19149 if (pin)
19150 alc680_auto_set_output_and_unmute(codec, pin, PIN_HP);
19151 pin = spec->autocfg.speaker_pins[0];
19152 if (pin)
19153 alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT);
19154}
19155
19156/* pcm configuration: identical with ALC880 */
19157#define alc680_pcm_analog_playback alc880_pcm_analog_playback
19158#define alc680_pcm_analog_capture alc880_pcm_analog_capture
19159#define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
19160#define alc680_pcm_digital_playback alc880_pcm_digital_playback
19161
19162static struct hda_input_mux alc680_capture_source = {
19163 .num_items = 1,
19164 .items = {
19165 { "Mic", 0x0 },
19166 },
19167};
19168
19169/*
19170 * BIOS auto configuration
19171 */
19172static int alc680_parse_auto_config(struct hda_codec *codec)
19173{
19174 struct alc_spec *spec = codec->spec;
19175 int err;
19176 static hda_nid_t alc680_ignore[] = { 0 };
19177
19178 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
19179 alc680_ignore);
19180 if (err < 0)
19181 return err;
19182 if (!spec->autocfg.line_outs) {
19183 if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
19184 spec->multiout.max_channels = 2;
19185 spec->no_analog = 1;
19186 goto dig_only;
19187 }
19188 return 0; /* can't find valid BIOS pin config */
19189 }
19190 err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg);
19191 if (err < 0)
19192 return err;
19193
19194 spec->multiout.max_channels = 2;
19195
19196 dig_only:
19197 /* digital only support output */
19198 alc_auto_parse_digital(codec);
19199 if (spec->kctls.list)
19200 add_mixer(spec, spec->kctls.list);
19201
19202 add_verb(spec, alc680_init_verbs);
19203 spec->num_mux_defs = 1;
19204 spec->input_mux = &alc680_capture_source;
19205
19206 err = alc_auto_add_mic_boost(codec);
19207 if (err < 0)
19208 return err;
19209
19210 return 1;
19211}
19212
19213#define alc680_auto_init_analog_input alc882_auto_init_analog_input
19214
19215/* init callback for auto-configuration model -- overriding the default init */
19216static void alc680_auto_init(struct hda_codec *codec)
19217{
19218 struct alc_spec *spec = codec->spec;
19219 alc680_auto_init_multi_out(codec);
19220 alc680_auto_init_hp_out(codec);
19221 alc680_auto_init_analog_input(codec);
19222 alc_auto_init_digital(codec);
19223 if (spec->unsol_event)
19224 alc_inithook(codec);
19225}
19226
19227/*
19228 * configuration and preset
19229 */
19230static const char *alc680_models[ALC680_MODEL_LAST] = {
19231 [ALC680_BASE] = "base",
19232 [ALC680_AUTO] = "auto",
19233};
19234
19235static struct snd_pci_quirk alc680_cfg_tbl[] = {
19236 SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
19237 {}
19238};
19239
19240static struct alc_config_preset alc680_presets[] = {
19241 [ALC680_BASE] = {
19242 .mixers = { alc680_base_mixer },
19243 .cap_mixer = alc680_capture_mixer,
19244 .init_verbs = { alc680_init_verbs },
19245 .num_dacs = ARRAY_SIZE(alc680_dac_nids),
19246 .dac_nids = alc680_dac_nids,
19247 .num_adc_nids = ARRAY_SIZE(alc680_adc_nids),
19248 .adc_nids = alc680_adc_nids,
19249 .hp_nid = 0x04,
19250 .dig_out_nid = ALC680_DIGOUT_NID,
19251 .num_channel_mode = ARRAY_SIZE(alc680_modes),
19252 .channel_mode = alc680_modes,
19253 .input_mux = &alc680_capture_source,
19254 },
19255};
19256
19257static int patch_alc680(struct hda_codec *codec)
19258{
19259 struct alc_spec *spec;
19260 int board_config;
19261 int err;
19262
19263 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
19264 if (spec == NULL)
19265 return -ENOMEM;
19266
19267 codec->spec = spec;
19268
19269 board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST,
19270 alc680_models,
19271 alc680_cfg_tbl);
19272
19273 if (board_config < 0 || board_config >= ALC680_MODEL_LAST) {
19274 printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
19275 codec->chip_name);
19276 board_config = ALC680_AUTO;
19277 }
19278
19279 if (board_config == ALC680_AUTO) {
19280 /* automatic parse from the BIOS config */
19281 err = alc680_parse_auto_config(codec);
19282 if (err < 0) {
19283 alc_free(codec);
19284 return err;
19285 } else if (!err) {
19286 printk(KERN_INFO
19287 "hda_codec: Cannot set up configuration "
19288 "from BIOS. Using base mode...\n");
19289 board_config = ALC680_BASE;
19290 }
19291 }
19292
19293 if (board_config != ALC680_AUTO)
19294 setup_preset(codec, &alc680_presets[board_config]);
19295
19296 spec->stream_analog_playback = &alc680_pcm_analog_playback;
19297 spec->stream_analog_capture = &alc680_pcm_analog_capture;
19298 spec->stream_analog_alt_capture = &alc680_pcm_analog_alt_capture;
19299 spec->stream_digital_playback = &alc680_pcm_digital_playback;
19300
19301 if (!spec->adc_nids) {
19302 spec->adc_nids = alc680_adc_nids;
19303 spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids);
19304 }
19305
19306 if (!spec->cap_mixer)
19307 set_capture_mixer(codec);
19308
19309 spec->vmaster_nid = 0x02;
19310
19311 codec->patch_ops = alc_patch_ops;
19312 if (board_config == ALC680_AUTO)
19313 spec->init_hook = alc680_auto_init;
19314
19315 return 0;
19316}
19317
19318/*
18784 * patch entries 19319 * patch entries
18785 */ 19320 */
18786static struct hda_codec_preset snd_hda_preset_realtek[] = { 19321static struct hda_codec_preset snd_hda_preset_realtek[] = {
@@ -18804,6 +19339,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
18804 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, 19339 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
18805 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, 19340 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
18806 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, 19341 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
19342 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
18807 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, 19343 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
18808 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, 19344 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
18809 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, 19345 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index f1e7babd6920..b8d730c47df1 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -202,6 +202,7 @@ struct sigmatel_spec {
202 unsigned int spdif_mute: 1; 202 unsigned int spdif_mute: 1;
203 unsigned int check_volume_offset:1; 203 unsigned int check_volume_offset:1;
204 unsigned int auto_mic:1; 204 unsigned int auto_mic:1;
205 unsigned int linear_tone_beep:1;
205 206
206 /* gpio lines */ 207 /* gpio lines */
207 unsigned int eapd_mask; 208 unsigned int eapd_mask;
@@ -3802,7 +3803,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
3802 return err; 3803 return err;
3803 if (codec->beep) { 3804 if (codec->beep) {
3804 /* IDT/STAC codecs have linear beep tone parameter */ 3805 /* IDT/STAC codecs have linear beep tone parameter */
3805 codec->beep->linear_tone = 1; 3806 codec->beep->linear_tone = spec->linear_tone_beep;
3806 /* if no beep switch is available, make its own one */ 3807 /* if no beep switch is available, make its own one */
3807 caps = query_amp_caps(codec, nid, HDA_OUTPUT); 3808 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
3808 if (!(caps & AC_AMPCAP_MUTE)) { 3809 if (!(caps & AC_AMPCAP_MUTE)) {
@@ -5005,6 +5006,7 @@ static int patch_stac9200(struct hda_codec *codec)
5005 5006
5006 codec->no_trigger_sense = 1; 5007 codec->no_trigger_sense = 1;
5007 codec->spec = spec; 5008 codec->spec = spec;
5009 spec->linear_tone_beep = 1;
5008 spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); 5010 spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
5009 spec->pin_nids = stac9200_pin_nids; 5011 spec->pin_nids = stac9200_pin_nids;
5010 spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, 5012 spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
@@ -5068,6 +5070,7 @@ static int patch_stac925x(struct hda_codec *codec)
5068 5070
5069 codec->no_trigger_sense = 1; 5071 codec->no_trigger_sense = 1;
5070 codec->spec = spec; 5072 codec->spec = spec;
5073 spec->linear_tone_beep = 1;
5071 spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); 5074 spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
5072 spec->pin_nids = stac925x_pin_nids; 5075 spec->pin_nids = stac925x_pin_nids;
5073 5076
@@ -5153,6 +5156,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
5153 5156
5154 codec->no_trigger_sense = 1; 5157 codec->no_trigger_sense = 1;
5155 codec->spec = spec; 5158 codec->spec = spec;
5159 spec->linear_tone_beep = 0;
5156 codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; 5160 codec->slave_dig_outs = stac92hd73xx_slave_dig_outs;
5157 spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); 5161 spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids);
5158 spec->pin_nids = stac92hd73xx_pin_nids; 5162 spec->pin_nids = stac92hd73xx_pin_nids;
@@ -5300,6 +5304,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
5300 5304
5301 codec->no_trigger_sense = 1; 5305 codec->no_trigger_sense = 1;
5302 codec->spec = spec; 5306 codec->spec = spec;
5307 spec->linear_tone_beep = 1;
5303 codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; 5308 codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
5304 spec->digbeep_nid = 0x21; 5309 spec->digbeep_nid = 0x21;
5305 spec->mux_nids = stac92hd83xxx_mux_nids; 5310 spec->mux_nids = stac92hd83xxx_mux_nids;
@@ -5522,6 +5527,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
5522 5527
5523 codec->no_trigger_sense = 1; 5528 codec->no_trigger_sense = 1;
5524 codec->spec = spec; 5529 codec->spec = spec;
5530 spec->linear_tone_beep = 0;
5525 codec->patch_ops = stac92xx_patch_ops; 5531 codec->patch_ops = stac92xx_patch_ops;
5526 spec->num_pins = STAC92HD71BXX_NUM_PINS; 5532 spec->num_pins = STAC92HD71BXX_NUM_PINS;
5527 switch (codec->vendor_id) { 5533 switch (codec->vendor_id) {
@@ -5779,6 +5785,7 @@ static int patch_stac922x(struct hda_codec *codec)
5779 5785
5780 codec->no_trigger_sense = 1; 5786 codec->no_trigger_sense = 1;
5781 codec->spec = spec; 5787 codec->spec = spec;
5788 spec->linear_tone_beep = 1;
5782 spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); 5789 spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
5783 spec->pin_nids = stac922x_pin_nids; 5790 spec->pin_nids = stac922x_pin_nids;
5784 spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, 5791 spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
@@ -5883,6 +5890,7 @@ static int patch_stac927x(struct hda_codec *codec)
5883 5890
5884 codec->no_trigger_sense = 1; 5891 codec->no_trigger_sense = 1;
5885 codec->spec = spec; 5892 codec->spec = spec;
5893 spec->linear_tone_beep = 1;
5886 codec->slave_dig_outs = stac927x_slave_dig_outs; 5894 codec->slave_dig_outs = stac927x_slave_dig_outs;
5887 spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); 5895 spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
5888 spec->pin_nids = stac927x_pin_nids; 5896 spec->pin_nids = stac927x_pin_nids;
@@ -6018,6 +6026,7 @@ static int patch_stac9205(struct hda_codec *codec)
6018 6026
6019 codec->no_trigger_sense = 1; 6027 codec->no_trigger_sense = 1;
6020 codec->spec = spec; 6028 codec->spec = spec;
6029 spec->linear_tone_beep = 1;
6021 spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); 6030 spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
6022 spec->pin_nids = stac9205_pin_nids; 6031 spec->pin_nids = stac9205_pin_nids;
6023 spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, 6032 spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
@@ -6174,6 +6183,7 @@ static int patch_stac9872(struct hda_codec *codec)
6174 return -ENOMEM; 6183 return -ENOMEM;
6175 codec->no_trigger_sense = 1; 6184 codec->no_trigger_sense = 1;
6176 codec->spec = spec; 6185 codec->spec = spec;
6186 spec->linear_tone_beep = 1;
6177 spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); 6187 spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
6178 spec->pin_nids = stac9872_pin_nids; 6188 spec->pin_nids = stac9872_pin_nids;
6179 6189
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 73453814e098..ae3acb2b42d1 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -552,24 +552,30 @@ static void via_auto_init_hp_out(struct hda_codec *codec)
552 } 552 }
553} 553}
554 554
555static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
556
555static void via_auto_init_analog_input(struct hda_codec *codec) 557static void via_auto_init_analog_input(struct hda_codec *codec)
556{ 558{
557 struct via_spec *spec = codec->spec; 559 struct via_spec *spec = codec->spec;
560 unsigned int ctl;
558 int i; 561 int i;
559 562
560 for (i = 0; i < AUTO_PIN_LAST; i++) { 563 for (i = 0; i < AUTO_PIN_LAST; i++) {
561 hda_nid_t nid = spec->autocfg.input_pins[i]; 564 hda_nid_t nid = spec->autocfg.input_pins[i];
565 if (!nid)
566 continue;
562 567
568 if (spec->smart51_enabled && is_smart51_pins(spec, nid))
569 ctl = PIN_OUT;
570 else if (i <= AUTO_PIN_FRONT_MIC)
571 ctl = PIN_VREF50;
572 else
573 ctl = PIN_IN;
563 snd_hda_codec_write(codec, nid, 0, 574 snd_hda_codec_write(codec, nid, 0,
564 AC_VERB_SET_PIN_WIDGET_CONTROL, 575 AC_VERB_SET_PIN_WIDGET_CONTROL, ctl);
565 (i <= AUTO_PIN_FRONT_MIC ?
566 PIN_VREF50 : PIN_IN));
567
568 } 576 }
569} 577}
570 578
571static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
572
573static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, 579static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
574 unsigned int *affected_parm) 580 unsigned int *affected_parm)
575{ 581{
@@ -658,6 +664,8 @@ static void set_jack_power_state(struct hda_codec *codec)
658 /* PW0 (19h), SW1 (18h), AOW1 (11h) */ 664 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
659 parm = AC_PWRST_D3; 665 parm = AC_PWRST_D3;
660 set_pin_power_state(codec, 0x19, &parm); 666 set_pin_power_state(codec, 0x19, &parm);
667 if (spec->smart51_enabled)
668 parm = AC_PWRST_D0;
661 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, 669 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
662 parm); 670 parm);
663 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, 671 snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
@@ -667,6 +675,8 @@ static void set_jack_power_state(struct hda_codec *codec)
667 if (is_8ch) { 675 if (is_8ch) {
668 parm = AC_PWRST_D3; 676 parm = AC_PWRST_D3;
669 set_pin_power_state(codec, 0x22, &parm); 677 set_pin_power_state(codec, 0x22, &parm);
678 if (spec->smart51_enabled)
679 parm = AC_PWRST_D0;
670 snd_hda_codec_write(codec, 0x26, 0, 680 snd_hda_codec_write(codec, 0x26, 0,
671 AC_VERB_SET_POWER_STATE, parm); 681 AC_VERB_SET_POWER_STATE, parm);
672 snd_hda_codec_write(codec, 0x24, 0, 682 snd_hda_codec_write(codec, 0x24, 0,
@@ -3915,6 +3925,13 @@ static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
3915 } 3925 }
3916 } 3926 }
3917 3927
3928 /* for Smart 5.1, line/mic inputs double as output pins */
3929 if (cfg->line_outs == 1) {
3930 spec->multiout.num_dacs = 3;
3931 spec->multiout.dac_nids[AUTO_SEQ_SURROUND] = 0x11;
3932 spec->multiout.dac_nids[AUTO_SEQ_CENLFE] = 0x24;
3933 }
3934
3918 return 0; 3935 return 0;
3919} 3936}
3920 3937
@@ -3932,7 +3949,8 @@ static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
3932 for (i = 0; i <= AUTO_SEQ_SIDE; i++) { 3949 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
3933 nid = cfg->line_out_pins[i]; 3950 nid = cfg->line_out_pins[i];
3934 3951
3935 if (!nid) 3952 /* for Smart 5.1, there are always at least six channels */
3953 if (!nid && i > AUTO_SEQ_CENLFE)
3936 continue; 3954 continue;
3937 3955
3938 nid_vol = nid_vols[i]; 3956 nid_vol = nid_vols[i];
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index ad4462677615..f64fb7d988cb 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -97,6 +97,7 @@
97#include <linux/gameport.h> 97#include <linux/gameport.h>
98#include <linux/device.h> 98#include <linux/device.h>
99#include <linux/firmware.h> 99#include <linux/firmware.h>
100#include <linux/kernel.h>
100#include <asm/io.h> 101#include <asm/io.h>
101#include <sound/core.h> 102#include <sound/core.h>
102#include <sound/info.h> 103#include <sound/info.h>
@@ -667,13 +668,12 @@ static u32 atoh(const unsigned char *in, unsigned int len)
667 unsigned char c; 668 unsigned char c;
668 669
669 while (len) { 670 while (len) {
671 int value;
672
670 c = in[len - 1]; 673 c = in[len - 1];
671 if ((c >= '0') && (c <= '9')) 674 value = hex_to_bin(c);
672 sum += mult * (c - '0'); 675 if (value >= 0)
673 else if ((c >= 'A') && (c <= 'F')) 676 sum += mult * value;
674 sum += mult * (c - ('A' - 10));
675 else if ((c >= 'a') && (c <= 'f'))
676 sum += mult * (c - ('a' - 10));
677 mult *= 16; 677 mult *= 16;
678 --len; 678 --len;
679 } 679 }
@@ -1615,7 +1615,10 @@ static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
1615 1615
1616 chip->playback_substream[sub_num] = substream; 1616 chip->playback_substream[sub_num] = substream;
1617 runtime->hw = snd_riptide_playback; 1617 runtime->hw = snd_riptide_playback;
1618
1618 data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL); 1619 data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
1620 if (data == NULL)
1621 return -ENOMEM;
1619 data->paths = lbus_play_paths[sub_num]; 1622 data->paths = lbus_play_paths[sub_num];
1620 data->id = play_ids[sub_num]; 1623 data->id = play_ids[sub_num];
1621 data->source = play_sources[sub_num]; 1624 data->source = play_sources[sub_num];
@@ -1635,7 +1638,10 @@ static int snd_riptide_capture_open(struct snd_pcm_substream *substream)
1635 1638
1636 chip->capture_substream = substream; 1639 chip->capture_substream = substream;
1637 runtime->hw = snd_riptide_capture; 1640 runtime->hw = snd_riptide_capture;
1641
1638 data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL); 1642 data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
1643 if (data == NULL)
1644 return -ENOMEM;
1639 data->paths = lbus_rec_path; 1645 data->paths = lbus_rec_path;
1640 data->id = PADC; 1646 data->id = PADC;
1641 data->source = ACLNK2PADC; 1647 data->source = ACLNK2PADC;
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 9cc1b5aa0148..1b8f6742b5fa 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -264,11 +264,13 @@ static void sis_update_voice(struct voice *voice)
264 * if using small periods. 264 * if using small periods.
265 * 265 *
266 * If we're less than 9 samples behind, we're on target. 266 * If we're less than 9 samples behind, we're on target.
267 * Otherwise, shorten the next vperiod by the amount we've
268 * been delayed.
267 */ 269 */
268 if (sync > -9) 270 if (sync > -9)
269 voice->vperiod = voice->sync_period_size + 1; 271 voice->vperiod = voice->sync_period_size + 1;
270 else 272 else
271 voice->vperiod = voice->sync_period_size - 4; 273 voice->vperiod = voice->sync_period_size + sync + 10;
272 274
273 if (voice->vperiod < voice->buffer_size) { 275 if (voice->vperiod < voice->buffer_size) {
274 sis_update_sso(voice, voice->vperiod); 276 sis_update_sso(voice, voice->vperiod);
@@ -736,7 +738,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
736 period_size = buffer_size; 738 period_size = buffer_size;
737 739
738 /* Initially, we want to interrupt just a bit behind the end of 740 /* Initially, we want to interrupt just a bit behind the end of
739 * the period we're clocking out. 10 samples seems to give a good 741 * the period we're clocking out. 12 samples seems to give a good
740 * delay. 742 * delay.
741 * 743 *
742 * We want to spread our interrupts throughout the virtual period, 744 * We want to spread our interrupts throughout the virtual period,
@@ -747,7 +749,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
747 * 749 *
748 * This is all moot if we don't need to use virtual periods. 750 * This is all moot if we don't need to use virtual periods.
749 */ 751 */
750 vperiod = runtime->period_size + 10; 752 vperiod = runtime->period_size + 12;
751 if (vperiod > period_size) { 753 if (vperiod > period_size) {
752 u16 tail = vperiod % period_size; 754 u16 tail = vperiod % period_size;
753 u16 quarter_period = period_size / 4; 755 u16 quarter_period = period_size / 4;
@@ -776,7 +778,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
776 */ 778 */
777 timing->flags |= VOICE_SYNC_TIMING; 779 timing->flags |= VOICE_SYNC_TIMING;
778 timing->sync_base = voice->ctrl_base; 780 timing->sync_base = voice->ctrl_base;
779 timing->sync_cso = runtime->period_size - 1; 781 timing->sync_cso = runtime->period_size;
780 timing->sync_period_size = runtime->period_size; 782 timing->sync_period_size = runtime->period_size;
781 timing->sync_buffer_size = runtime->buffer_size; 783 timing->sync_buffer_size = runtime->buffer_size;
782 timing->period_size = period_size; 784 timing->period_size = period_size;
@@ -1047,7 +1049,7 @@ static int sis_chip_free(struct sis7019 *sis)
1047 /* Reset the chip, and disable all interrputs. 1049 /* Reset the chip, and disable all interrputs.
1048 */ 1050 */
1049 outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR); 1051 outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
1050 udelay(10); 1052 udelay(25);
1051 outl(0, sis->ioport + SIS_GCR); 1053 outl(0, sis->ioport + SIS_GCR);
1052 outl(0, sis->ioport + SIS_GIER); 1054 outl(0, sis->ioport + SIS_GIER);
1053 1055
@@ -1083,7 +1085,7 @@ static int sis_chip_init(struct sis7019 *sis)
1083 /* Reset the audio controller 1085 /* Reset the audio controller
1084 */ 1086 */
1085 outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR); 1087 outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR);
1086 udelay(10); 1088 udelay(25);
1087 outl(0, io + SIS_GCR); 1089 outl(0, io + SIS_GCR);
1088 1090
1089 /* Get the AC-link semaphore, and reset the codecs 1091 /* Get the AC-link semaphore, and reset the codecs
@@ -1096,7 +1098,7 @@ static int sis_chip_init(struct sis7019 *sis)
1096 return -EIO; 1098 return -EIO;
1097 1099
1098 outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD); 1100 outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD);
1099 udelay(10); 1101 udelay(250);
1100 1102
1101 count = 0xffff; 1103 count = 0xffff;
1102 while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) 1104 while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 7e494b6a1d0e..8c5f8b5a59f0 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -85,6 +85,7 @@ static int joystick;
85static int ac97_clock = 48000; 85static int ac97_clock = 48000;
86static char *ac97_quirk; 86static char *ac97_quirk;
87static int dxs_support; 87static int dxs_support;
88static int dxs_init_volume = 31;
88static int nodelay; 89static int nodelay;
89 90
90module_param(index, int, 0444); 91module_param(index, int, 0444);
@@ -103,6 +104,8 @@ module_param(ac97_quirk, charp, 0444);
103MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); 104MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
104module_param(dxs_support, int, 0444); 105module_param(dxs_support, int, 0444);
105MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); 106MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
107module_param(dxs_init_volume, int, 0644);
108MODULE_PARM_DESC(dxs_init_volume, "initial DXS volume (0-31)");
106module_param(nodelay, int, 0444); 109module_param(nodelay, int, 0444);
107MODULE_PARM_DESC(nodelay, "Disable 500ms init delay"); 110MODULE_PARM_DESC(nodelay, "Disable 500ms init delay");
108 111
@@ -1245,8 +1248,10 @@ static int snd_via8233_playback_open(struct snd_pcm_substream *substream)
1245 return err; 1248 return err;
1246 stream = viadev->reg_offset / 0x10; 1249 stream = viadev->reg_offset / 0x10;
1247 if (chip->dxs_controls[stream]) { 1250 if (chip->dxs_controls[stream]) {
1248 chip->playback_volume[stream][0] = 0; 1251 chip->playback_volume[stream][0] =
1249 chip->playback_volume[stream][1] = 0; 1252 VIA_DXS_MAX_VOLUME - (dxs_init_volume & 31);
1253 chip->playback_volume[stream][1] =
1254 VIA_DXS_MAX_VOLUME - (dxs_init_volume & 31);
1250 chip->dxs_controls[stream]->vd[0].access &= 1255 chip->dxs_controls[stream]->vd[0].access &=
1251 ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 1256 ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
1252 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | 1257 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index b1749bc67979..3e598e756e54 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -28,9 +28,13 @@ source "sound/soc/atmel/Kconfig"
28source "sound/soc/au1x/Kconfig" 28source "sound/soc/au1x/Kconfig"
29source "sound/soc/blackfin/Kconfig" 29source "sound/soc/blackfin/Kconfig"
30source "sound/soc/davinci/Kconfig" 30source "sound/soc/davinci/Kconfig"
31source "sound/soc/ep93xx/Kconfig"
31source "sound/soc/fsl/Kconfig" 32source "sound/soc/fsl/Kconfig"
32source "sound/soc/imx/Kconfig" 33source "sound/soc/imx/Kconfig"
34source "sound/soc/jz4740/Kconfig"
35source "sound/soc/nuc900/Kconfig"
33source "sound/soc/omap/Kconfig" 36source "sound/soc/omap/Kconfig"
37source "sound/soc/kirkwood/Kconfig"
34source "sound/soc/pxa/Kconfig" 38source "sound/soc/pxa/Kconfig"
35source "sound/soc/s3c24xx/Kconfig" 39source "sound/soc/s3c24xx/Kconfig"
36source "sound/soc/s6000/Kconfig" 40source "sound/soc/s6000/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 1470141d4167..eb183443eee4 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -6,9 +6,13 @@ obj-$(CONFIG_SND_SOC) += atmel/
6obj-$(CONFIG_SND_SOC) += au1x/ 6obj-$(CONFIG_SND_SOC) += au1x/
7obj-$(CONFIG_SND_SOC) += blackfin/ 7obj-$(CONFIG_SND_SOC) += blackfin/
8obj-$(CONFIG_SND_SOC) += davinci/ 8obj-$(CONFIG_SND_SOC) += davinci/
9obj-$(CONFIG_SND_SOC) += ep93xx/
9obj-$(CONFIG_SND_SOC) += fsl/ 10obj-$(CONFIG_SND_SOC) += fsl/
10obj-$(CONFIG_SND_SOC) += imx/ 11obj-$(CONFIG_SND_SOC) += imx/
12obj-$(CONFIG_SND_SOC) += jz4740/
13obj-$(CONFIG_SND_SOC) += nuc900/
11obj-$(CONFIG_SND_SOC) += omap/ 14obj-$(CONFIG_SND_SOC) += omap/
15obj-$(CONFIG_SND_SOC) += kirkwood/
12obj-$(CONFIG_SND_SOC) += pxa/ 16obj-$(CONFIG_SND_SOC) += pxa/
13obj-$(CONFIG_SND_SOC) += s3c24xx/ 17obj-$(CONFIG_SND_SOC) += s3c24xx/
14obj-$(CONFIG_SND_SOC) += s6000/ 18obj-$(CONFIG_SND_SOC) += s6000/
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index f6b3cc04b34b..dc5249fba85c 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -77,7 +77,6 @@ struct atmel_runtime_data {
77 size_t period_size; 77 size_t period_size;
78 78
79 dma_addr_t period_ptr; /* physical address of next period */ 79 dma_addr_t period_ptr; /* physical address of next period */
80 int periods; /* period index of period_ptr */
81 80
82 /* PDC register save */ 81 /* PDC register save */
83 u32 pdc_xpr_save; 82 u32 pdc_xpr_save;
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index 0b59806905d1..c85844d4845b 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -549,7 +549,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
549 printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n", 549 printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
550 ssc_p->daifmt); 550 ssc_p->daifmt);
551 return -EINVAL; 551 return -EINVAL;
552 break;
553 } 552 }
554 pr_debug("atmel_ssc_hw_params: " 553 pr_debug("atmel_ssc_hw_params: "
555 "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", 554 "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index a61ccd2d505f..d14a5a91a465 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -375,12 +375,10 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
375 } 375 }
376 376
377 ret = -EBUSY; 377 ret = -EBUSY;
378 wd->ioarea = request_mem_region(r->start, r->end - r->start + 1, 378 if (!request_mem_region(r->start, resource_size(r), pdev->name))
379 "au1xpsc_ac97");
380 if (!wd->ioarea)
381 goto out0; 379 goto out0;
382 380
383 wd->mmio = ioremap(r->start, 0xffff); 381 wd->mmio = ioremap(r->start, resource_size(r));
384 if (!wd->mmio) 382 if (!wd->mmio)
385 goto out1; 383 goto out1;
386 384
@@ -410,8 +408,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
410 408
411 snd_soc_unregister_dai(&au1xpsc_ac97_dai); 409 snd_soc_unregister_dai(&au1xpsc_ac97_dai);
412out1: 410out1:
413 release_resource(wd->ioarea); 411 release_mem_region(r->start, resource_size(r));
414 kfree(wd->ioarea);
415out0: 412out0:
416 kfree(wd); 413 kfree(wd);
417 return ret; 414 return ret;
@@ -420,6 +417,7 @@ out0:
420static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev) 417static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
421{ 418{
422 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); 419 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
420 struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
423 421
424 if (wd->dmapd) 422 if (wd->dmapd)
425 au1xpsc_pcm_destroy(wd->dmapd); 423 au1xpsc_pcm_destroy(wd->dmapd);
@@ -433,8 +431,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
433 au_sync(); 431 au_sync();
434 432
435 iounmap(wd->mmio); 433 iounmap(wd->mmio);
436 release_resource(wd->ioarea); 434 release_mem_region(r->start, resource_size(r));
437 kfree(wd->ioarea);
438 kfree(wd); 435 kfree(wd);
439 436
440 au1xpsc_ac97_workdata = NULL; /* MDEV */ 437 au1xpsc_ac97_workdata = NULL; /* MDEV */
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 24454c98d0ee..6083fe7799fa 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -321,12 +321,10 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
321 } 321 }
322 322
323 ret = -EBUSY; 323 ret = -EBUSY;
324 wd->ioarea = request_mem_region(r->start, r->end - r->start + 1, 324 if (!request_mem_region(r->start, resource_size(r), pdev->name))
325 "au1xpsc_i2s");
326 if (!wd->ioarea)
327 goto out0; 325 goto out0;
328 326
329 wd->mmio = ioremap(r->start, 0xffff); 327 wd->mmio = ioremap(r->start, resource_size(r));
330 if (!wd->mmio) 328 if (!wd->mmio)
331 goto out1; 329 goto out1;
332 330
@@ -362,8 +360,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
362 360
363 snd_soc_unregister_dai(&au1xpsc_i2s_dai); 361 snd_soc_unregister_dai(&au1xpsc_i2s_dai);
364out1: 362out1:
365 release_resource(wd->ioarea); 363 release_mem_region(r->start, resource_size(r));
366 kfree(wd->ioarea);
367out0: 364out0:
368 kfree(wd); 365 kfree(wd);
369 return ret; 366 return ret;
@@ -372,6 +369,7 @@ out0:
372static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) 369static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
373{ 370{
374 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); 371 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
372 struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
375 373
376 if (wd->dmapd) 374 if (wd->dmapd)
377 au1xpsc_pcm_destroy(wd->dmapd); 375 au1xpsc_pcm_destroy(wd->dmapd);
@@ -384,8 +382,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
384 au_sync(); 382 au_sync();
385 383
386 iounmap(wd->mmio); 384 iounmap(wd->mmio);
387 release_resource(wd->ioarea); 385 release_mem_region(r->start, resource_size(r));
388 kfree(wd->ioarea);
389 kfree(wd); 386 kfree(wd);
390 387
391 au1xpsc_i2s_workdata = NULL; /* MDEV */ 388 au1xpsc_i2s_workdata = NULL; /* MDEV */
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
index 32d3807d3f5a..093775d4dc3e 100644
--- a/sound/soc/au1x/psc.h
+++ b/sound/soc/au1x/psc.h
@@ -32,7 +32,6 @@ struct au1xpsc_audio_data {
32 unsigned long rate; 32 unsigned long rate;
33 33
34 unsigned long pm[2]; 34 unsigned long pm[2];
35 struct resource *ioarea;
36 struct mutex lock; 35 struct mutex lock;
37 struct platform_device *dmapd; 36 struct platform_device *dmapd;
38}; 37};
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 523b7fc33f4e..c0eba5109980 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -255,8 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);
255#ifdef CONFIG_PM 255#ifdef CONFIG_PM
256static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) 256static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
257{ 257{
258 struct sport_device *sport = 258 struct sport_device *sport = dai->private_data;
259 (struct sport_device *)dai->private_data;
260 259
261 pr_debug("%s : sport %d\n", __func__, dai->id); 260 pr_debug("%s : sport %d\n", __func__, dai->id);
262 if (!dai->active) 261 if (!dai->active)
@@ -271,8 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
271static int bf5xx_ac97_resume(struct snd_soc_dai *dai) 270static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
272{ 271{
273 int ret; 272 int ret;
274 struct sport_device *sport = 273 struct sport_device *sport = dai->private_data;
275 (struct sport_device *)dai->private_data;
276 274
277 pr_debug("%s : sport %d\n", __func__, dai->id); 275 pr_debug("%s : sport %d\n", __func__, dai->id);
278 if (!dai->active) 276 if (!dai->active)
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index 4b360124083e..24c14269f4bc 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -210,8 +210,7 @@ static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai,
210#ifdef CONFIG_PM 210#ifdef CONFIG_PM
211static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) 211static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
212{ 212{
213 struct sport_device *sport = 213 struct sport_device *sport = dai->private_data;
214 (struct sport_device *)dai->private_data;
215 214
216 if (!dai->active) 215 if (!dai->active)
217 return 0; 216 return 0;
@@ -225,8 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
225static int bf5xx_tdm_resume(struct snd_soc_dai *dai) 224static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
226{ 225{
227 int ret; 226 int ret;
228 struct sport_device *sport = 227 struct sport_device *sport = dai->private_data;
229 (struct sport_device *)dai->private_data;
230 228
231 if (!dai->active) 229 if (!dai->active)
232 return 0; 230 return 0;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 5da30eb6ad00..83f5c67d3c41 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -22,9 +22,11 @@ config SND_SOC_ALL_CODECS
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_CQ0093VC if MFD_DAVINCI_VOICECODEC
25 select SND_SOC_CS42L51 if I2C
25 select SND_SOC_CS4270 if I2C 26 select SND_SOC_CS4270 if I2C
26 select SND_SOC_MAX9877 if I2C
27 select SND_SOC_DA7210 if I2C 27 select SND_SOC_DA7210 if I2C
28 select SND_SOC_JZ4740 if SOC_JZ4740
29 select SND_SOC_MAX9877 if I2C
28 select SND_SOC_PCM3008 30 select SND_SOC_PCM3008
29 select SND_SOC_SPDIF 31 select SND_SOC_SPDIF
30 select SND_SOC_SSM2602 if I2C 32 select SND_SOC_SSM2602 if I2C
@@ -48,6 +50,7 @@ config SND_SOC_ALL_CODECS
48 select SND_SOC_WM8727 50 select SND_SOC_WM8727
49 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI 51 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
50 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI 52 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
53 select SND_SOC_WM8741 if SND_SOC_I2C_AND_SPI
51 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI 54 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
52 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI 55 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
53 select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI 56 select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
@@ -120,13 +123,13 @@ config SND_SOC_AK4671
120config SND_SOC_CQ0093VC 123config SND_SOC_CQ0093VC
121 tristate 124 tristate
122 125
126config SND_SOC_CS42L51
127 tristate
128
123# Cirrus Logic CS4270 Codec 129# Cirrus Logic CS4270 Codec
124config SND_SOC_CS4270 130config SND_SOC_CS4270
125 tristate 131 tristate
126 132
127config SND_SOC_DA7210
128 tristate
129
130# Cirrus Logic CS4270 Codec VD = 3.3V Errata 133# Cirrus Logic CS4270 Codec VD = 3.3V Errata
131# Select if you are affected by the errata where the part will not function 134# Select if you are affected by the errata where the part will not function
132# if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will 135# if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will
@@ -138,9 +141,15 @@ config SND_SOC_CS4270_VD33_ERRATA
138config SND_SOC_CX20442 141config SND_SOC_CX20442
139 tristate 142 tristate
140 143
144config SND_SOC_JZ4740_CODEC
145 tristate
146
141config SND_SOC_L3 147config SND_SOC_L3
142 tristate 148 tristate
143 149
150config SND_SOC_DA7210
151 tristate
152
144config SND_SOC_PCM3008 153config SND_SOC_PCM3008
145 tristate 154 tristate
146 155
@@ -206,6 +215,9 @@ config SND_SOC_WM8728
206config SND_SOC_WM8731 215config SND_SOC_WM8731
207 tristate 216 tristate
208 217
218config SND_SOC_WM8741
219 tristate
220
209config SND_SOC_WM8750 221config SND_SOC_WM8750
210 tristate 222 tristate
211 223
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 91429eab0707..53524095759c 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -9,6 +9,7 @@ snd-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-cq93vc-objs := cq93vc.o
12snd-soc-cs42l51-objs := cs42l51.o
12snd-soc-cs4270-objs := cs4270.o 13snd-soc-cs4270-objs := cs4270.o
13snd-soc-cx20442-objs := cx20442.o 14snd-soc-cx20442-objs := cx20442.o
14snd-soc-da7210-objs := da7210.o 15snd-soc-da7210-objs := da7210.o
@@ -34,6 +35,7 @@ snd-soc-wm8711-objs := wm8711.o
34snd-soc-wm8727-objs := wm8727.o 35snd-soc-wm8727-objs := wm8727.o
35snd-soc-wm8728-objs := wm8728.o 36snd-soc-wm8728-objs := wm8728.o
36snd-soc-wm8731-objs := wm8731.o 37snd-soc-wm8731-objs := wm8731.o
38snd-soc-wm8741-objs := wm8741.o
37snd-soc-wm8750-objs := wm8750.o 39snd-soc-wm8750-objs := wm8750.o
38snd-soc-wm8753-objs := wm8753.o 40snd-soc-wm8753-objs := wm8753.o
39snd-soc-wm8776-objs := wm8776.o 41snd-soc-wm8776-objs := wm8776.o
@@ -56,6 +58,7 @@ snd-soc-wm9705-objs := wm9705.o
56snd-soc-wm9712-objs := wm9712.o 58snd-soc-wm9712-objs := wm9712.o
57snd-soc-wm9713-objs := wm9713.o 59snd-soc-wm9713-objs := wm9713.o
58snd-soc-wm-hubs-objs := wm_hubs.o 60snd-soc-wm-hubs-objs := wm_hubs.o
61snd-soc-jz4740-codec-objs := jz4740.o
59 62
60# Amp 63# Amp
61snd-soc-max9877-objs := max9877.o 64snd-soc-max9877-objs := max9877.o
@@ -74,10 +77,12 @@ obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
74obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 77obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
75obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o 78obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
76obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o 79obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
80obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
77obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 81obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
78obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 82obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
79obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o 83obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
80obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 84obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
85obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
81obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 86obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
82obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o 87obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
83obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 88obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@@ -99,6 +104,7 @@ obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o
99obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o 104obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o
100obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o 105obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
101obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 106obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
107obj-$(CONFIG_SND_SOC_WM8741) += snd-soc-wm8741.o
102obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 108obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
103obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o 109obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
104obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o 110obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 217538423225..a01006c8c606 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -272,6 +272,7 @@ static int ad1836_register(struct ad1836_priv *ad1836)
272 272
273 if (ad1836_codec) { 273 if (ad1836_codec) {
274 dev_err(codec->dev, "Another ad1836 is registered\n"); 274 dev_err(codec->dev, "Another ad1836 is registered\n");
275 kfree(ad1836);
275 return -EINVAL; 276 return -EINVAL;
276 } 277 }
277 278
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index c8ca1142b2f4..1def75e4862f 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -24,6 +24,7 @@
24 24
25/* codec private data */ 25/* codec private data */
26struct ad193x_priv { 26struct ad193x_priv {
27 unsigned int sysclk;
27 struct snd_soc_codec codec; 28 struct snd_soc_codec codec;
28 u8 reg_cache[AD193X_NUM_REGS]; 29 u8 reg_cache[AD193X_NUM_REGS];
29}; 30};
@@ -251,15 +252,32 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
251 return 0; 252 return 0;
252} 253}
253 254
255static int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
256 int clk_id, unsigned int freq, int dir)
257{
258 struct snd_soc_codec *codec = codec_dai->codec;
259 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
260 switch (freq) {
261 case 12288000:
262 case 18432000:
263 case 24576000:
264 case 36864000:
265 ad193x->sysclk = freq;
266 return 0;
267 }
268 return -EINVAL;
269}
270
254static int ad193x_hw_params(struct snd_pcm_substream *substream, 271static int ad193x_hw_params(struct snd_pcm_substream *substream,
255 struct snd_pcm_hw_params *params, 272 struct snd_pcm_hw_params *params,
256 struct snd_soc_dai *dai) 273 struct snd_soc_dai *dai)
257{ 274{
258 int word_len = 0, reg = 0; 275 int word_len = 0, reg = 0, master_rate = 0;
259 276
260 struct snd_soc_pcm_runtime *rtd = substream->private_data; 277 struct snd_soc_pcm_runtime *rtd = substream->private_data;
261 struct snd_soc_device *socdev = rtd->socdev; 278 struct snd_soc_device *socdev = rtd->socdev;
262 struct snd_soc_codec *codec = socdev->card->codec; 279 struct snd_soc_codec *codec = socdev->card->codec;
280 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
263 281
264 /* bit size */ 282 /* bit size */
265 switch (params_format(params)) { 283 switch (params_format(params)) {
@@ -275,6 +293,25 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
275 break; 293 break;
276 } 294 }
277 295
296 switch (ad193x->sysclk) {
297 case 12288000:
298 master_rate = AD193X_PLL_INPUT_256;
299 break;
300 case 18432000:
301 master_rate = AD193X_PLL_INPUT_384;
302 break;
303 case 24576000:
304 master_rate = AD193X_PLL_INPUT_512;
305 break;
306 case 36864000:
307 master_rate = AD193X_PLL_INPUT_768;
308 break;
309 }
310
311 reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0);
312 reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate;
313 snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg);
314
278 reg = snd_soc_read(codec, AD193X_DAC_CTRL2); 315 reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
279 reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len; 316 reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len;
280 snd_soc_write(codec, AD193X_DAC_CTRL2, reg); 317 snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
@@ -348,6 +385,7 @@ static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
348 /* pll input: mclki/xi */ 385 /* pll input: mclki/xi */
349 snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ 386 snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
350 snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); 387 snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
388 ad193x->sysclk = 12288000;
351 389
352 ret = snd_soc_register_codec(codec); 390 ret = snd_soc_register_codec(codec);
353 if (ret != 0) { 391 if (ret != 0) {
@@ -383,6 +421,7 @@ static struct snd_soc_dai_ops ad193x_dai_ops = {
383 .hw_params = ad193x_hw_params, 421 .hw_params = ad193x_hw_params,
384 .digital_mute = ad193x_mute, 422 .digital_mute = ad193x_mute,
385 .set_tdm_slot = ad193x_set_tdm_slot, 423 .set_tdm_slot = ad193x_set_tdm_slot,
424 .set_sysclk = ad193x_set_dai_sysclk,
386 .set_fmt = ad193x_set_dai_fmt, 425 .set_fmt = ad193x_set_dai_fmt,
387}; 426};
388 427
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index a03c880d52f9..654ba64ae04c 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -11,6 +11,11 @@
11 11
12#define AD193X_PLL_CLK_CTRL0 0x800 12#define AD193X_PLL_CLK_CTRL0 0x800
13#define AD193X_PLL_POWERDOWN 0x01 13#define AD193X_PLL_POWERDOWN 0x01
14#define AD193X_PLL_INPUT_MASK (~0x6)
15#define AD193X_PLL_INPUT_256 (0 << 1)
16#define AD193X_PLL_INPUT_384 (1 << 1)
17#define AD193X_PLL_INPUT_512 (2 << 1)
18#define AD193X_PLL_INPUT_768 (3 << 1)
14#define AD193X_PLL_CLK_CTRL1 0x801 19#define AD193X_PLL_CLK_CTRL1 0x801
15#define AD193X_DAC_CTRL0 0x802 20#define AD193X_DAC_CTRL0 0x802
16#define AD193X_DAC_POWERDOWN 0x01 21#define AD193X_DAC_POWERDOWN 0x01
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 7528a54102b5..3d7dc55305ec 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -22,20 +22,13 @@
22 * AK4643 is tested. 22 * AK4643 is tested.
23 */ 23 */
24 24
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/init.h>
28#include <linux/delay.h> 25#include <linux/delay.h>
29#include <linux/pm.h>
30#include <linux/i2c.h> 26#include <linux/i2c.h>
31#include <linux/platform_device.h> 27#include <linux/platform_device.h>
32#include <linux/slab.h> 28#include <linux/slab.h>
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> 29#include <sound/soc-dapm.h>
38#include <sound/initval.h> 30#include <sound/initval.h>
31#include <sound/tlv.h>
39 32
40#include "ak4642.h" 33#include "ak4642.h"
41 34
@@ -111,6 +104,23 @@
111 104
112struct snd_soc_codec_device soc_codec_dev_ak4642; 105struct snd_soc_codec_device soc_codec_dev_ak4642;
113 106
107/*
108 * Playback Volume (table 39)
109 *
110 * max : 0x00 : +12.0 dB
111 * ( 0.5 dB step )
112 * min : 0xFE : -115.0 dB
113 * mute: 0xFF
114 */
115static const DECLARE_TLV_DB_SCALE(out_tlv, -11500, 50, 1);
116
117static const struct snd_kcontrol_new ak4642_snd_controls[] = {
118
119 SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC,
120 0, 0xFF, 1, out_tlv),
121};
122
123
114/* codec private data */ 124/* codec private data */
115struct ak4642_priv { 125struct ak4642_priv {
116 struct snd_soc_codec codec; 126 struct snd_soc_codec codec;
@@ -204,7 +214,6 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
204 * 214 *
205 * PLL, Master Mode 215 * PLL, Master Mode
206 * Audio I/F Format :MSB justified (ADC & DAC) 216 * Audio I/F Format :MSB justified (ADC & DAC)
207 * Digital Volume: -8dB
208 * Bass Boost Level : Middle 217 * Bass Boost Level : Middle
209 * 218 *
210 * This operation came from example code of 219 * This operation came from example code of
@@ -214,8 +223,6 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
214 ak4642_write(codec, 0x0e, 0x19); 223 ak4642_write(codec, 0x0e, 0x19);
215 ak4642_write(codec, 0x09, 0x91); 224 ak4642_write(codec, 0x09, 0x91);
216 ak4642_write(codec, 0x0c, 0x91); 225 ak4642_write(codec, 0x0c, 0x91);
217 ak4642_write(codec, 0x0a, 0x28);
218 ak4642_write(codec, 0x0d, 0x28);
219 ak4642_write(codec, 0x00, 0x64); 226 ak4642_write(codec, 0x00, 0x64);
220 snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP); 227 snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
221 snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN); 228 snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN);
@@ -491,8 +498,10 @@ static int ak4642_i2c_probe(struct i2c_client *i2c,
491 codec->control_data = i2c; 498 codec->control_data = i2c;
492 499
493 ret = ak4642_init(ak4642); 500 ret = ak4642_init(ak4642);
494 if (ret < 0) 501 if (ret < 0) {
495 printk(KERN_ERR "failed to initialise AK4642\n"); 502 printk(KERN_ERR "failed to initialise AK4642\n");
503 kfree(ak4642);
504 }
496 505
497 return ret; 506 return ret;
498} 507}
@@ -548,6 +557,9 @@ static int ak4642_probe(struct platform_device *pdev)
548 goto pcm_err; 557 goto pcm_err;
549 } 558 }
550 559
560 snd_soc_add_controls(ak4642_codec, ak4642_snd_controls,
561 ARRAY_SIZE(ak4642_snd_controls));
562
551 dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); 563 dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
552 return ret; 564 return ret;
553 565
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
new file mode 100644
index 000000000000..dd9b8550c402
--- /dev/null
+++ b/sound/soc/codecs/cs42l51.c
@@ -0,0 +1,763 @@
1/*
2 * cs42l51.c
3 *
4 * ASoC Driver for Cirrus Logic CS42L51 codecs
5 *
6 * Copyright (c) 2010 Arnaud Patard <apatard@mandriva.com>
7 *
8 * Based on cs4270.c - Copyright (c) Freescale Semiconductor
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * For now:
20 * - Only I2C is support. Not SPI
21 * - master mode *NOT* supported
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/slab.h>
27#include <sound/core.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30#include <sound/tlv.h>
31#include <sound/initval.h>
32#include <sound/pcm_params.h>
33#include <sound/pcm.h>
34#include <linux/i2c.h>
35
36#include "cs42l51.h"
37
38enum master_slave_mode {
39 MODE_SLAVE,
40 MODE_SLAVE_AUTO,
41 MODE_MASTER,
42};
43
44struct cs42l51_private {
45 unsigned int mclk;
46 unsigned int audio_mode; /* The mode (I2S or left-justified) */
47 enum master_slave_mode func;
48 struct snd_soc_codec codec;
49 u8 reg_cache[CS42L51_NUMREGS];
50};
51
52static struct snd_soc_codec *cs42l51_codec;
53
54#define CS42L51_FORMATS ( \
55 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
56 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
57 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
58 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
59
60static int cs42l51_fill_cache(struct snd_soc_codec *codec)
61{
62 u8 *cache = codec->reg_cache + 1;
63 struct i2c_client *i2c_client = codec->control_data;
64 s32 length;
65
66 length = i2c_smbus_read_i2c_block_data(i2c_client,
67 CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache);
68 if (length != CS42L51_NUMREGS) {
69 dev_err(&i2c_client->dev,
70 "I2C read failure, addr=0x%x (ret=%d vs %d)\n",
71 i2c_client->addr, length, CS42L51_NUMREGS);
72 return -EIO;
73 }
74
75 return 0;
76}
77
78static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
79 const struct i2c_device_id *id)
80{
81 struct snd_soc_codec *codec;
82 struct cs42l51_private *cs42l51;
83 int ret = 0;
84 int reg;
85
86 if (cs42l51_codec)
87 return -EBUSY;
88
89 /* Verify that we have a CS42L51 */
90 ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
91 if (ret < 0) {
92 dev_err(&i2c_client->dev, "failed to read I2C\n");
93 goto error;
94 }
95
96 if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
97 (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
98 dev_err(&i2c_client->dev, "Invalid chip id\n");
99 ret = -ENODEV;
100 goto error;
101 }
102
103 dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
104 ret & 7);
105
106 cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
107 if (!cs42l51) {
108 dev_err(&i2c_client->dev, "could not allocate codec\n");
109 return -ENOMEM;
110 }
111 codec = &cs42l51->codec;
112
113 mutex_init(&codec->mutex);
114 INIT_LIST_HEAD(&codec->dapm_widgets);
115 INIT_LIST_HEAD(&codec->dapm_paths);
116
117 codec->dev = &i2c_client->dev;
118 codec->name = "CS42L51";
119 codec->owner = THIS_MODULE;
120 codec->dai = &cs42l51_dai;
121 codec->num_dai = 1;
122 snd_soc_codec_set_drvdata(codec, cs42l51);
123
124 codec->control_data = i2c_client;
125 codec->reg_cache = cs42l51->reg_cache;
126 codec->reg_cache_size = CS42L51_NUMREGS;
127 i2c_set_clientdata(i2c_client, codec);
128
129 ret = cs42l51_fill_cache(codec);
130 if (ret < 0) {
131 dev_err(&i2c_client->dev, "failed to fill register cache\n");
132 goto error_alloc;
133 }
134
135 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
136 if (ret < 0) {
137 dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret);
138 goto error_alloc;
139 }
140
141 /*
142 * DAC configuration
143 * - Use signal processor
144 * - auto mute
145 * - vol changes immediate
146 * - no de-emphasize
147 */
148 reg = CS42L51_DAC_CTL_DATA_SEL(1)
149 | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
150 ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
151 if (ret < 0)
152 goto error_alloc;
153
154 cs42l51_dai.dev = codec->dev;
155 cs42l51_codec = codec;
156
157 ret = snd_soc_register_codec(codec);
158 if (ret != 0) {
159 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
160 goto error_alloc;
161 }
162
163 ret = snd_soc_register_dai(&cs42l51_dai);
164 if (ret < 0) {
165 dev_err(&i2c_client->dev, "failed to register DAIe\n");
166 goto error_reg;
167 }
168
169 return 0;
170
171error_reg:
172 snd_soc_unregister_codec(codec);
173error_alloc:
174 kfree(cs42l51);
175error:
176 return ret;
177}
178
179static int cs42l51_i2c_remove(struct i2c_client *client)
180{
181 struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
182 snd_soc_unregister_dai(&cs42l51_dai);
183 snd_soc_unregister_codec(cs42l51_codec);
184 cs42l51_codec = NULL;
185 kfree(cs42l51);
186 return 0;
187}
188
189
190static const struct i2c_device_id cs42l51_id[] = {
191 {"cs42l51", 0},
192 {}
193};
194MODULE_DEVICE_TABLE(i2c, cs42l51_id);
195
196static struct i2c_driver cs42l51_i2c_driver = {
197 .driver = {
198 .name = "CS42L51 I2C",
199 .owner = THIS_MODULE,
200 },
201 .id_table = cs42l51_id,
202 .probe = cs42l51_i2c_probe,
203 .remove = cs42l51_i2c_remove,
204};
205
206static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
207 struct snd_ctl_elem_value *ucontrol)
208{
209 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
210 unsigned long value = snd_soc_read(codec, CS42L51_PCM_MIXER)&3;
211
212 switch (value) {
213 default:
214 case 0:
215 ucontrol->value.integer.value[0] = 0;
216 break;
217 /* same value : (L+R)/2 and (R+L)/2 */
218 case 1:
219 case 2:
220 ucontrol->value.integer.value[0] = 1;
221 break;
222 case 3:
223 ucontrol->value.integer.value[0] = 2;
224 break;
225 }
226
227 return 0;
228}
229
230#define CHAN_MIX_NORMAL 0x00
231#define CHAN_MIX_BOTH 0x55
232#define CHAN_MIX_SWAP 0xFF
233
234static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
235 struct snd_ctl_elem_value *ucontrol)
236{
237 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
238 unsigned char val;
239
240 switch (ucontrol->value.integer.value[0]) {
241 default:
242 case 0:
243 val = CHAN_MIX_NORMAL;
244 break;
245 case 1:
246 val = CHAN_MIX_BOTH;
247 break;
248 case 2:
249 val = CHAN_MIX_SWAP;
250 break;
251 }
252
253 snd_soc_write(codec, CS42L51_PCM_MIXER, val);
254
255 return 1;
256}
257
258static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0);
259static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
260/* This is a lie. after -102 db, it stays at -102 */
261/* maybe a range would be better */
262static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0);
263
264static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0);
265static const char *chan_mix[] = {
266 "L R",
267 "L+R",
268 "R L",
269};
270
271static const struct soc_enum cs42l51_chan_mix =
272 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix);
273
274static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
275 SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
276 CS42L51_PCMA_VOL, CS42L51_PCMB_VOL,
277 7, 0xffffff99, 0x18, adc_pcm_tlv),
278 SOC_DOUBLE_R("PCM Playback Switch",
279 CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1),
280 SOC_DOUBLE_R_SX_TLV("Analog Playback Volume",
281 CS42L51_AOUTA_VOL, CS42L51_AOUTB_VOL,
282 8, 0xffffff19, 0x18, aout_tlv),
283 SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
284 CS42L51_ADCA_VOL, CS42L51_ADCB_VOL,
285 7, 0xffffff99, 0x18, adc_pcm_tlv),
286 SOC_DOUBLE_R("ADC Mixer Switch",
287 CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1),
288 SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0),
289 SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0),
290 SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0),
291 SOC_SINGLE("Zero Cross Switch", CS42L51_DAC_CTL, 0, 0, 0),
292 SOC_DOUBLE_TLV("Mic Boost Volume",
293 CS42L51_MIC_CTL, 0, 1, 1, 0, boost_tlv),
294 SOC_SINGLE_TLV("Bass Volume", CS42L51_TONE_CTL, 0, 0xf, 1, tone_tlv),
295 SOC_SINGLE_TLV("Treble Volume", CS42L51_TONE_CTL, 4, 0xf, 1, tone_tlv),
296 SOC_ENUM_EXT("PCM channel mixer",
297 cs42l51_chan_mix,
298 cs42l51_get_chan_mix, cs42l51_set_chan_mix),
299};
300
301/*
302 * to power down, one must:
303 * 1.) Enable the PDN bit
304 * 2.) enable power-down for the select channels
305 * 3.) disable the PDN bit.
306 */
307static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
308 struct snd_kcontrol *kcontrol, int event)
309{
310 unsigned long value;
311
312 value = snd_soc_read(w->codec, CS42L51_POWER_CTL1);
313 value &= ~CS42L51_POWER_CTL1_PDN;
314
315 switch (event) {
316 case SND_SOC_DAPM_PRE_PMD:
317 value |= CS42L51_POWER_CTL1_PDN;
318 break;
319 default:
320 case SND_SOC_DAPM_POST_PMD:
321 break;
322 }
323 snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
324 CS42L51_POWER_CTL1_PDN, value);
325
326 return 0;
327}
328
329static const char *cs42l51_dac_names[] = {"Direct PCM",
330 "DSP PCM", "ADC"};
331static const struct soc_enum cs42l51_dac_mux_enum =
332 SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names);
333static const struct snd_kcontrol_new cs42l51_dac_mux_controls =
334 SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum);
335
336static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left",
337 "MIC Left", "MIC+preamp Left"};
338static const struct soc_enum cs42l51_adcl_mux_enum =
339 SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names);
340static const struct snd_kcontrol_new cs42l51_adcl_mux_controls =
341 SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum);
342
343static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right",
344 "MIC Right", "MIC+preamp Right"};
345static const struct soc_enum cs42l51_adcr_mux_enum =
346 SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names);
347static const struct snd_kcontrol_new cs42l51_adcr_mux_controls =
348 SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum);
349
350static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
351 SND_SOC_DAPM_MICBIAS("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1),
352 SND_SOC_DAPM_PGA_E("Left PGA", CS42L51_POWER_CTL1, 3, 1, NULL, 0,
353 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
354 SND_SOC_DAPM_PGA_E("Right PGA", CS42L51_POWER_CTL1, 4, 1, NULL, 0,
355 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
356 SND_SOC_DAPM_ADC_E("Left ADC", "Left HiFi Capture",
357 CS42L51_POWER_CTL1, 1, 1,
358 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
359 SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture",
360 CS42L51_POWER_CTL1, 2, 1,
361 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
362 SND_SOC_DAPM_DAC_E("Left DAC", "Left HiFi Playback",
363 CS42L51_POWER_CTL1, 5, 1,
364 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
365 SND_SOC_DAPM_DAC_E("Right DAC", "Right HiFi Playback",
366 CS42L51_POWER_CTL1, 6, 1,
367 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
368
369 /* analog/mic */
370 SND_SOC_DAPM_INPUT("AIN1L"),
371 SND_SOC_DAPM_INPUT("AIN1R"),
372 SND_SOC_DAPM_INPUT("AIN2L"),
373 SND_SOC_DAPM_INPUT("AIN2R"),
374 SND_SOC_DAPM_INPUT("MICL"),
375 SND_SOC_DAPM_INPUT("MICR"),
376
377 SND_SOC_DAPM_MIXER("Mic Preamp Left",
378 CS42L51_MIC_POWER_CTL, 2, 1, NULL, 0),
379 SND_SOC_DAPM_MIXER("Mic Preamp Right",
380 CS42L51_MIC_POWER_CTL, 3, 1, NULL, 0),
381
382 /* HP */
383 SND_SOC_DAPM_OUTPUT("HPL"),
384 SND_SOC_DAPM_OUTPUT("HPR"),
385
386 /* mux */
387 SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0,
388 &cs42l51_dac_mux_controls),
389 SND_SOC_DAPM_MUX("PGA-ADC Mux Left", SND_SOC_NOPM, 0, 0,
390 &cs42l51_adcl_mux_controls),
391 SND_SOC_DAPM_MUX("PGA-ADC Mux Right", SND_SOC_NOPM, 0, 0,
392 &cs42l51_adcr_mux_controls),
393};
394
395static const struct snd_soc_dapm_route cs42l51_routes[] = {
396 {"HPL", NULL, "Left DAC"},
397 {"HPR", NULL, "Right DAC"},
398
399 {"Left ADC", NULL, "Left PGA"},
400 {"Right ADC", NULL, "Right PGA"},
401
402 {"Mic Preamp Left", NULL, "MICL"},
403 {"Mic Preamp Right", NULL, "MICR"},
404
405 {"PGA-ADC Mux Left", "AIN1 Left", "AIN1L" },
406 {"PGA-ADC Mux Left", "AIN2 Left", "AIN2L" },
407 {"PGA-ADC Mux Left", "MIC Left", "MICL" },
408 {"PGA-ADC Mux Left", "MIC+preamp Left", "Mic Preamp Left" },
409 {"PGA-ADC Mux Right", "AIN1 Right", "AIN1R" },
410 {"PGA-ADC Mux Right", "AIN2 Right", "AIN2R" },
411 {"PGA-ADC Mux Right", "MIC Right", "MICR" },
412 {"PGA-ADC Mux Right", "MIC+preamp Right", "Mic Preamp Right" },
413
414 {"Left PGA", NULL, "PGA-ADC Mux Left"},
415 {"Right PGA", NULL, "PGA-ADC Mux Right"},
416};
417
418static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
419 unsigned int format)
420{
421 struct snd_soc_codec *codec = codec_dai->codec;
422 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
423 int ret = 0;
424
425 switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
426 case SND_SOC_DAIFMT_I2S:
427 case SND_SOC_DAIFMT_LEFT_J:
428 case SND_SOC_DAIFMT_RIGHT_J:
429 cs42l51->audio_mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
430 break;
431 default:
432 dev_err(codec->dev, "invalid DAI format\n");
433 ret = -EINVAL;
434 }
435
436 switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
437 case SND_SOC_DAIFMT_CBM_CFM:
438 cs42l51->func = MODE_MASTER;
439 break;
440 case SND_SOC_DAIFMT_CBS_CFS:
441 cs42l51->func = MODE_SLAVE_AUTO;
442 break;
443 default:
444 ret = -EINVAL;
445 break;
446 }
447
448 return ret;
449}
450
451struct cs42l51_ratios {
452 unsigned int ratio;
453 unsigned char speed_mode;
454 unsigned char mclk;
455};
456
457static struct cs42l51_ratios slave_ratios[] = {
458 { 512, CS42L51_QSM_MODE, 0 }, { 768, CS42L51_QSM_MODE, 0 },
459 { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
460 { 2048, CS42L51_QSM_MODE, 0 }, { 3072, CS42L51_QSM_MODE, 0 },
461 { 256, CS42L51_HSM_MODE, 0 }, { 384, CS42L51_HSM_MODE, 0 },
462 { 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 },
463 { 1024, CS42L51_HSM_MODE, 0 }, { 1536, CS42L51_HSM_MODE, 0 },
464 { 128, CS42L51_SSM_MODE, 0 }, { 192, CS42L51_SSM_MODE, 0 },
465 { 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 },
466 { 512, CS42L51_SSM_MODE, 0 }, { 768, CS42L51_SSM_MODE, 0 },
467 { 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 },
468 { 256, CS42L51_DSM_MODE, 0 }, { 384, CS42L51_DSM_MODE, 0 },
469};
470
471static struct cs42l51_ratios slave_auto_ratios[] = {
472 { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
473 { 2048, CS42L51_QSM_MODE, 1 }, { 3072, CS42L51_QSM_MODE, 1 },
474 { 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 },
475 { 1024, CS42L51_HSM_MODE, 1 }, { 1536, CS42L51_HSM_MODE, 1 },
476 { 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 },
477 { 512, CS42L51_SSM_MODE, 1 }, { 768, CS42L51_SSM_MODE, 1 },
478 { 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 },
479 { 256, CS42L51_DSM_MODE, 1 }, { 384, CS42L51_DSM_MODE, 1 },
480};
481
482static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
483 int clk_id, unsigned int freq, int dir)
484{
485 struct snd_soc_codec *codec = codec_dai->codec;
486 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
487 struct cs42l51_ratios *ratios = NULL;
488 int nr_ratios = 0;
489 unsigned int rates = 0;
490 unsigned int rate_min = -1;
491 unsigned int rate_max = 0;
492 int i;
493
494 cs42l51->mclk = freq;
495
496 switch (cs42l51->func) {
497 case MODE_MASTER:
498 return -EINVAL;
499 case MODE_SLAVE:
500 ratios = slave_ratios;
501 nr_ratios = ARRAY_SIZE(slave_ratios);
502 break;
503 case MODE_SLAVE_AUTO:
504 ratios = slave_auto_ratios;
505 nr_ratios = ARRAY_SIZE(slave_auto_ratios);
506 break;
507 }
508
509 for (i = 0; i < nr_ratios; i++) {
510 unsigned int rate = freq / ratios[i].ratio;
511 rates |= snd_pcm_rate_to_rate_bit(rate);
512 if (rate < rate_min)
513 rate_min = rate;
514 if (rate > rate_max)
515 rate_max = rate;
516 }
517 rates &= ~SNDRV_PCM_RATE_KNOT;
518
519 if (!rates) {
520 dev_err(codec->dev, "could not find a valid sample rate\n");
521 return -EINVAL;
522 }
523
524 codec_dai->playback.rates = rates;
525 codec_dai->playback.rate_min = rate_min;
526 codec_dai->playback.rate_max = rate_max;
527
528 codec_dai->capture.rates = rates;
529 codec_dai->capture.rate_min = rate_min;
530 codec_dai->capture.rate_max = rate_max;
531
532 return 0;
533}
534
535static int cs42l51_hw_params(struct snd_pcm_substream *substream,
536 struct snd_pcm_hw_params *params,
537 struct snd_soc_dai *dai)
538{
539 struct snd_soc_pcm_runtime *rtd = substream->private_data;
540 struct snd_soc_device *socdev = rtd->socdev;
541 struct snd_soc_codec *codec = socdev->card->codec;
542 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
543 int ret;
544 unsigned int i;
545 unsigned int rate;
546 unsigned int ratio;
547 struct cs42l51_ratios *ratios = NULL;
548 int nr_ratios = 0;
549 int intf_ctl, power_ctl, fmt;
550
551 switch (cs42l51->func) {
552 case MODE_MASTER:
553 return -EINVAL;
554 case MODE_SLAVE:
555 ratios = slave_ratios;
556 nr_ratios = ARRAY_SIZE(slave_ratios);
557 break;
558 case MODE_SLAVE_AUTO:
559 ratios = slave_auto_ratios;
560 nr_ratios = ARRAY_SIZE(slave_auto_ratios);
561 break;
562 }
563
564 /* Figure out which MCLK/LRCK ratio to use */
565 rate = params_rate(params); /* Sampling rate, in Hz */
566 ratio = cs42l51->mclk / rate; /* MCLK/LRCK ratio */
567 for (i = 0; i < nr_ratios; i++) {
568 if (ratios[i].ratio == ratio)
569 break;
570 }
571
572 if (i == nr_ratios) {
573 /* We did not find a matching ratio */
574 dev_err(codec->dev, "could not find matching ratio\n");
575 return -EINVAL;
576 }
577
578 intf_ctl = snd_soc_read(codec, CS42L51_INTF_CTL);
579 power_ctl = snd_soc_read(codec, CS42L51_MIC_POWER_CTL);
580
581 intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S
582 | CS42L51_INTF_CTL_DAC_FORMAT(7));
583 power_ctl &= ~(CS42L51_MIC_POWER_CTL_SPEED(3)
584 | CS42L51_MIC_POWER_CTL_MCLK_DIV2);
585
586 switch (cs42l51->func) {
587 case MODE_MASTER:
588 intf_ctl |= CS42L51_INTF_CTL_MASTER;
589 power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
590 break;
591 case MODE_SLAVE:
592 power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
593 break;
594 case MODE_SLAVE_AUTO:
595 power_ctl |= CS42L51_MIC_POWER_CTL_AUTO;
596 break;
597 }
598
599 switch (cs42l51->audio_mode) {
600 case SND_SOC_DAIFMT_I2S:
601 intf_ctl |= CS42L51_INTF_CTL_ADC_I2S;
602 intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_I2S);
603 break;
604 case SND_SOC_DAIFMT_LEFT_J:
605 intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24);
606 break;
607 case SND_SOC_DAIFMT_RIGHT_J:
608 switch (params_format(params)) {
609 case SNDRV_PCM_FORMAT_S16_LE:
610 case SNDRV_PCM_FORMAT_S16_BE:
611 fmt = CS42L51_DAC_DIF_RJ16;
612 break;
613 case SNDRV_PCM_FORMAT_S18_3LE:
614 case SNDRV_PCM_FORMAT_S18_3BE:
615 fmt = CS42L51_DAC_DIF_RJ18;
616 break;
617 case SNDRV_PCM_FORMAT_S20_3LE:
618 case SNDRV_PCM_FORMAT_S20_3BE:
619 fmt = CS42L51_DAC_DIF_RJ20;
620 break;
621 case SNDRV_PCM_FORMAT_S24_LE:
622 case SNDRV_PCM_FORMAT_S24_BE:
623 fmt = CS42L51_DAC_DIF_RJ24;
624 break;
625 default:
626 dev_err(codec->dev, "unknown format\n");
627 return -EINVAL;
628 }
629 intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(fmt);
630 break;
631 default:
632 dev_err(codec->dev, "unknown format\n");
633 return -EINVAL;
634 }
635
636 if (ratios[i].mclk)
637 power_ctl |= CS42L51_MIC_POWER_CTL_MCLK_DIV2;
638
639 ret = snd_soc_write(codec, CS42L51_INTF_CTL, intf_ctl);
640 if (ret < 0)
641 return ret;
642
643 ret = snd_soc_write(codec, CS42L51_MIC_POWER_CTL, power_ctl);
644 if (ret < 0)
645 return ret;
646
647 return 0;
648}
649
650static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute)
651{
652 struct snd_soc_codec *codec = dai->codec;
653 int reg;
654 int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE;
655
656 reg = snd_soc_read(codec, CS42L51_DAC_OUT_CTL);
657
658 if (mute)
659 reg |= mask;
660 else
661 reg &= ~mask;
662
663 return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg);
664}
665
666static struct snd_soc_dai_ops cs42l51_dai_ops = {
667 .hw_params = cs42l51_hw_params,
668 .set_sysclk = cs42l51_set_dai_sysclk,
669 .set_fmt = cs42l51_set_dai_fmt,
670 .digital_mute = cs42l51_dai_mute,
671};
672
673struct snd_soc_dai cs42l51_dai = {
674 .name = "CS42L51 HiFi",
675 .playback = {
676 .stream_name = "Playback",
677 .channels_min = 1,
678 .channels_max = 2,
679 .rates = SNDRV_PCM_RATE_8000_96000,
680 .formats = CS42L51_FORMATS,
681 },
682 .capture = {
683 .stream_name = "Capture",
684 .channels_min = 1,
685 .channels_max = 2,
686 .rates = SNDRV_PCM_RATE_8000_96000,
687 .formats = CS42L51_FORMATS,
688 },
689 .ops = &cs42l51_dai_ops,
690};
691EXPORT_SYMBOL_GPL(cs42l51_dai);
692
693
694static int cs42l51_probe(struct platform_device *pdev)
695{
696 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
697 struct snd_soc_codec *codec;
698 int ret = 0;
699
700 if (!cs42l51_codec) {
701 dev_err(&pdev->dev, "CS42L51 codec not yet registered\n");
702 return -EINVAL;
703 }
704
705 socdev->card->codec = cs42l51_codec;
706 codec = socdev->card->codec;
707
708 /* Register PCMs */
709 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
710 if (ret < 0) {
711 dev_err(&pdev->dev, "failed to create PCMs\n");
712 return ret;
713 }
714
715 snd_soc_add_controls(codec, cs42l51_snd_controls,
716 ARRAY_SIZE(cs42l51_snd_controls));
717 snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
718 ARRAY_SIZE(cs42l51_dapm_widgets));
719 snd_soc_dapm_add_routes(codec, cs42l51_routes,
720 ARRAY_SIZE(cs42l51_routes));
721
722 return 0;
723}
724
725
726static int cs42l51_remove(struct platform_device *pdev)
727{
728 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
729
730 snd_soc_free_pcms(socdev);
731 snd_soc_dapm_free(socdev);
732
733 return 0;
734}
735
736struct snd_soc_codec_device soc_codec_device_cs42l51 = {
737 .probe = cs42l51_probe,
738 .remove = cs42l51_remove
739};
740EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51);
741
742static int __init cs42l51_init(void)
743{
744 int ret;
745
746 ret = i2c_add_driver(&cs42l51_i2c_driver);
747 if (ret != 0) {
748 printk(KERN_ERR "%s: can't add i2c driver\n", __func__);
749 return ret;
750 }
751 return 0;
752}
753module_init(cs42l51_init);
754
755static void __exit cs42l51_exit(void)
756{
757 i2c_del_driver(&cs42l51_i2c_driver);
758}
759module_exit(cs42l51_exit);
760
761MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
762MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
763MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h
new file mode 100644
index 000000000000..8f0bd9786ad2
--- /dev/null
+++ b/sound/soc/codecs/cs42l51.h
@@ -0,0 +1,163 @@
1/*
2 * cs42l51.h
3 *
4 * ASoC Driver for Cirrus Logic CS42L51 codecs
5 *
6 * Copyright (c) 2010 Arnaud Patard <apatard@mandriva.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#ifndef _CS42L51_H
19#define _CS42L51_H
20
21#define CS42L51_CHIP_ID 0x1B
22#define CS42L51_CHIP_REV_A 0x00
23#define CS42L51_CHIP_REV_B 0x01
24
25#define CS42L51_CHIP_REV_ID 0x01
26#define CS42L51_MK_CHIP_REV(a, b) ((a)<<3|(b))
27
28#define CS42L51_POWER_CTL1 0x02
29#define CS42L51_POWER_CTL1_PDN_DACB (1<<6)
30#define CS42L51_POWER_CTL1_PDN_DACA (1<<5)
31#define CS42L51_POWER_CTL1_PDN_PGAB (1<<4)
32#define CS42L51_POWER_CTL1_PDN_PGAA (1<<3)
33#define CS42L51_POWER_CTL1_PDN_ADCB (1<<2)
34#define CS42L51_POWER_CTL1_PDN_ADCA (1<<1)
35#define CS42L51_POWER_CTL1_PDN (1<<0)
36
37#define CS42L51_MIC_POWER_CTL 0x03
38#define CS42L51_MIC_POWER_CTL_AUTO (1<<7)
39#define CS42L51_MIC_POWER_CTL_SPEED(x) (((x)&3)<<5)
40#define CS42L51_QSM_MODE 3
41#define CS42L51_HSM_MODE 2
42#define CS42L51_SSM_MODE 1
43#define CS42L51_DSM_MODE 0
44#define CS42L51_MIC_POWER_CTL_3ST_SP (1<<4)
45#define CS42L51_MIC_POWER_CTL_PDN_MICB (1<<3)
46#define CS42L51_MIC_POWER_CTL_PDN_MICA (1<<2)
47#define CS42L51_MIC_POWER_CTL_PDN_BIAS (1<<1)
48#define CS42L51_MIC_POWER_CTL_MCLK_DIV2 (1<<0)
49
50#define CS42L51_INTF_CTL 0x04
51#define CS42L51_INTF_CTL_LOOPBACK (1<<7)
52#define CS42L51_INTF_CTL_MASTER (1<<6)
53#define CS42L51_INTF_CTL_DAC_FORMAT(x) (((x)&7)<<3)
54#define CS42L51_DAC_DIF_LJ24 0x00
55#define CS42L51_DAC_DIF_I2S 0x01
56#define CS42L51_DAC_DIF_RJ24 0x02
57#define CS42L51_DAC_DIF_RJ20 0x03
58#define CS42L51_DAC_DIF_RJ18 0x04
59#define CS42L51_DAC_DIF_RJ16 0x05
60#define CS42L51_INTF_CTL_ADC_I2S (1<<2)
61#define CS42L51_INTF_CTL_DIGMIX (1<<1)
62#define CS42L51_INTF_CTL_MICMIX (1<<0)
63
64#define CS42L51_MIC_CTL 0x05
65#define CS42L51_MIC_CTL_ADC_SNGVOL (1<<7)
66#define CS42L51_MIC_CTL_ADCD_DBOOST (1<<6)
67#define CS42L51_MIC_CTL_ADCA_DBOOST (1<<5)
68#define CS42L51_MIC_CTL_MICBIAS_SEL (1<<4)
69#define CS42L51_MIC_CTL_MICBIAS_LVL(x) (((x)&3)<<2)
70#define CS42L51_MIC_CTL_MICB_BOOST (1<<1)
71#define CS42L51_MIC_CTL_MICA_BOOST (1<<0)
72
73#define CS42L51_ADC_CTL 0x06
74#define CS42L51_ADC_CTL_ADCB_HPFEN (1<<7)
75#define CS42L51_ADC_CTL_ADCB_HPFRZ (1<<6)
76#define CS42L51_ADC_CTL_ADCA_HPFEN (1<<5)
77#define CS42L51_ADC_CTL_ADCA_HPFRZ (1<<4)
78#define CS42L51_ADC_CTL_SOFTB (1<<3)
79#define CS42L51_ADC_CTL_ZCROSSB (1<<2)
80#define CS42L51_ADC_CTL_SOFTA (1<<1)
81#define CS42L51_ADC_CTL_ZCROSSA (1<<0)
82
83#define CS42L51_ADC_INPUT 0x07
84#define CS42L51_ADC_INPUT_AINB_MUX(x) (((x)&3)<<6)
85#define CS42L51_ADC_INPUT_AINA_MUX(x) (((x)&3)<<4)
86#define CS42L51_ADC_INPUT_INV_ADCB (1<<3)
87#define CS42L51_ADC_INPUT_INV_ADCA (1<<2)
88#define CS42L51_ADC_INPUT_ADCB_MUTE (1<<1)
89#define CS42L51_ADC_INPUT_ADCA_MUTE (1<<0)
90
91#define CS42L51_DAC_OUT_CTL 0x08
92#define CS42L51_DAC_OUT_CTL_HP_GAIN(x) (((x)&7)<<5)
93#define CS42L51_DAC_OUT_CTL_DAC_SNGVOL (1<<4)
94#define CS42L51_DAC_OUT_CTL_INV_PCMB (1<<3)
95#define CS42L51_DAC_OUT_CTL_INV_PCMA (1<<2)
96#define CS42L51_DAC_OUT_CTL_DACB_MUTE (1<<1)
97#define CS42L51_DAC_OUT_CTL_DACA_MUTE (1<<0)
98
99#define CS42L51_DAC_CTL 0x09
100#define CS42L51_DAC_CTL_DATA_SEL(x) (((x)&3)<<6)
101#define CS42L51_DAC_CTL_FREEZE (1<<5)
102#define CS42L51_DAC_CTL_DEEMPH (1<<3)
103#define CS42L51_DAC_CTL_AMUTE (1<<2)
104#define CS42L51_DAC_CTL_DACSZ(x) (((x)&3)<<0)
105
106#define CS42L51_ALC_PGA_CTL 0x0A
107#define CS42L51_ALC_PGB_CTL 0x0B
108#define CS42L51_ALC_PGX_ALCX_SRDIS (1<<7)
109#define CS42L51_ALC_PGX_ALCX_ZCDIS (1<<6)
110#define CS42L51_ALC_PGX_PGX_VOL(x) (((x)&0x1f)<<0)
111
112#define CS42L51_ADCA_ATT 0x0C
113#define CS42L51_ADCB_ATT 0x0D
114
115#define CS42L51_ADCA_VOL 0x0E
116#define CS42L51_ADCB_VOL 0x0F
117#define CS42L51_PCMA_VOL 0x10
118#define CS42L51_PCMB_VOL 0x11
119#define CS42L51_MIX_MUTE_ADCMIX (1<<7)
120#define CS42L51_MIX_VOLUME(x) (((x)&0x7f)<<0)
121
122#define CS42L51_BEEP_FREQ 0x12
123#define CS42L51_BEEP_VOL 0x13
124#define CS42L51_BEEP_CONF 0x14
125
126#define CS42L51_TONE_CTL 0x15
127#define CS42L51_TONE_CTL_TREB(x) (((x)&0xf)<<4)
128#define CS42L51_TONE_CTL_BASS(x) (((x)&0xf)<<0)
129
130#define CS42L51_AOUTA_VOL 0x16
131#define CS42L51_AOUTB_VOL 0x17
132#define CS42L51_PCM_MIXER 0x18
133#define CS42L51_LIMIT_THRES_DIS 0x19
134#define CS42L51_LIMIT_REL 0x1A
135#define CS42L51_LIMIT_ATT 0x1B
136#define CS42L51_ALC_EN 0x1C
137#define CS42L51_ALC_REL 0x1D
138#define CS42L51_ALC_THRES 0x1E
139#define CS42L51_NOISE_CONF 0x1F
140
141#define CS42L51_STATUS 0x20
142#define CS42L51_STATUS_SP_CLKERR (1<<6)
143#define CS42L51_STATUS_SPEA_OVFL (1<<5)
144#define CS42L51_STATUS_SPEB_OVFL (1<<4)
145#define CS42L51_STATUS_PCMA_OVFL (1<<3)
146#define CS42L51_STATUS_PCMB_OVFL (1<<2)
147#define CS42L51_STATUS_ADCA_OVFL (1<<1)
148#define CS42L51_STATUS_ADCB_OVFL (1<<0)
149
150#define CS42L51_CHARGE_FREQ 0x21
151
152#define CS42L51_FIRSTREG 0x01
153/*
154 * Hack: with register 0x21, it makes 33 registers. Looks like someone in the
155 * i2c layer doesn't like i2c smbus block read of 33 regs. Workaround by using
156 * 32 regs
157 */
158#define CS42L51_LASTREG 0x20
159#define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1)
160
161extern struct snd_soc_dai cs42l51_dai;
162extern struct snd_soc_codec_device soc_codec_device_cs42l51;
163#endif
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 75af2d6e0e78..3c51d6a57523 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -15,23 +15,15 @@
15 * option) any later version. 15 * option) any later version.
16 */ 16 */
17 17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/delay.h> 18#include <linux/delay.h>
23#include <linux/pm.h>
24#include <linux/i2c.h> 19#include <linux/i2c.h>
25#include <linux/platform_device.h> 20#include <linux/platform_device.h>
26#include <linux/slab.h> 21#include <linux/slab.h>
27#include <sound/core.h>
28#include <sound/pcm.h> 22#include <sound/pcm.h>
29#include <sound/pcm_params.h> 23#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
32#include <sound/tlv.h>
33#include <sound/initval.h> 25#include <sound/initval.h>
34#include <asm/div64.h> 26#include <sound/tlv.h>
35 27
36#include "da7210.h" 28#include "da7210.h"
37 29
@@ -145,6 +137,29 @@
145 137
146#define DA7210_VERSION "0.0.1" 138#define DA7210_VERSION "0.0.1"
147 139
140/*
141 * Playback Volume
142 *
143 * max : 0x3F (+15.0 dB)
144 * (1.5 dB step)
145 * min : 0x11 (-54.0 dB)
146 * mute : 0x10
147 * reserved : 0x00 - 0x0F
148 *
149 * ** FIXME **
150 *
151 * Reserved area are considered as "mute".
152 * -> min = -79.5 dB
153 */
154static const DECLARE_TLV_DB_SCALE(hp_out_tlv, -7950, 150, 1);
155
156static const struct snd_kcontrol_new da7210_snd_controls[] = {
157
158 SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
159 DA7210_HP_L_VOL, DA7210_HP_R_VOL,
160 0, 0x3F, 0, hp_out_tlv),
161};
162
148/* Codec private data */ 163/* Codec private data */
149struct da7210_priv { 164struct da7210_priv {
150 struct snd_soc_codec codec; 165 struct snd_soc_codec codec;
@@ -227,10 +242,6 @@ static int da7210_startup(struct snd_pcm_substream *substream,
227 struct snd_soc_codec *codec = dai->codec; 242 struct snd_soc_codec *codec = dai->codec;
228 243
229 if (is_play) { 244 if (is_play) {
230 /* PlayBack Volume 40 */
231 snd_soc_update_bits(codec, DA7210_HP_L_VOL, 0x3F, 40);
232 snd_soc_update_bits(codec, DA7210_HP_R_VOL, 0x3F, 40);
233
234 /* Enable Out */ 245 /* Enable Out */
235 snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10); 246 snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10);
236 snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10); 247 snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10);
@@ -488,7 +499,7 @@ static int da7210_init(struct da7210_priv *da7210)
488 ret = snd_soc_register_dai(&da7210_dai); 499 ret = snd_soc_register_dai(&da7210_dai);
489 if (ret) { 500 if (ret) {
490 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 501 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
491 goto init_err; 502 goto codec_err;
492 } 503 }
493 504
494 /* FIXME 505 /* FIXME
@@ -574,6 +585,8 @@ static int da7210_init(struct da7210_priv *da7210)
574 585
575 return ret; 586 return ret;
576 587
588codec_err:
589 snd_soc_unregister_codec(codec);
577init_err: 590init_err:
578 kfree(codec->reg_cache); 591 kfree(codec->reg_cache);
579 codec->reg_cache = NULL; 592 codec->reg_cache = NULL;
@@ -601,8 +614,10 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
601 codec->control_data = i2c; 614 codec->control_data = i2c;
602 615
603 ret = da7210_init(da7210); 616 ret = da7210_init(da7210);
604 if (ret < 0) 617 if (ret < 0) {
605 pr_err("Failed to initialise da7210 audio codec\n"); 618 pr_err("Failed to initialise da7210 audio codec\n");
619 kfree(da7210);
620 }
606 621
607 return ret; 622 return ret;
608} 623}
@@ -656,6 +671,9 @@ static int da7210_probe(struct platform_device *pdev)
656 if (ret < 0) 671 if (ret < 0)
657 goto pcm_err; 672 goto pcm_err;
658 673
674 snd_soc_add_controls(da7210_codec, da7210_snd_controls,
675 ARRAY_SIZE(da7210_snd_controls));
676
659 dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); 677 dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
660 678
661pcm_err: 679pcm_err:
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
new file mode 100644
index 000000000000..66557de1e4fe
--- /dev/null
+++ b/sound/soc/codecs/jz4740.c
@@ -0,0 +1,511 @@
1/*
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
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 * You should have received a copy of the GNU General Public License along
9 * with this program; if not, write to the Free Software Foundation, Inc.,
10 * 675 Mass Ave, Cambridge, MA 02139, USA.
11 *
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/slab.h>
18
19#include <linux/delay.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-dapm.h>
26#include <sound/soc.h>
27
28#define JZ4740_REG_CODEC_1 0x0
29#define JZ4740_REG_CODEC_2 0x1
30
31#define JZ4740_CODEC_1_LINE_ENABLE BIT(29)
32#define JZ4740_CODEC_1_MIC_ENABLE BIT(28)
33#define JZ4740_CODEC_1_SW1_ENABLE BIT(27)
34#define JZ4740_CODEC_1_ADC_ENABLE BIT(26)
35#define JZ4740_CODEC_1_SW2_ENABLE BIT(25)
36#define JZ4740_CODEC_1_DAC_ENABLE BIT(24)
37#define JZ4740_CODEC_1_VREF_DISABLE BIT(20)
38#define JZ4740_CODEC_1_VREF_AMP_DISABLE BIT(19)
39#define JZ4740_CODEC_1_VREF_PULLDOWN BIT(18)
40#define JZ4740_CODEC_1_VREF_LOW_CURRENT BIT(17)
41#define JZ4740_CODEC_1_VREF_HIGH_CURRENT BIT(16)
42#define JZ4740_CODEC_1_HEADPHONE_DISABLE BIT(14)
43#define JZ4740_CODEC_1_HEADPHONE_AMP_CHANGE_ANY BIT(13)
44#define JZ4740_CODEC_1_HEADPHONE_CHARGE BIT(12)
45#define JZ4740_CODEC_1_HEADPHONE_PULLDOWN (BIT(11) | BIT(10))
46#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M BIT(9)
47#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN BIT(8)
48#define JZ4740_CODEC_1_SUSPEND BIT(1)
49#define JZ4740_CODEC_1_RESET BIT(0)
50
51#define JZ4740_CODEC_1_LINE_ENABLE_OFFSET 29
52#define JZ4740_CODEC_1_MIC_ENABLE_OFFSET 28
53#define JZ4740_CODEC_1_SW1_ENABLE_OFFSET 27
54#define JZ4740_CODEC_1_ADC_ENABLE_OFFSET 26
55#define JZ4740_CODEC_1_SW2_ENABLE_OFFSET 25
56#define JZ4740_CODEC_1_DAC_ENABLE_OFFSET 24
57#define JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET 14
58#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN_OFFSET 8
59
60#define JZ4740_CODEC_2_INPUT_VOLUME_MASK 0x1f0000
61#define JZ4740_CODEC_2_SAMPLE_RATE_MASK 0x000f00
62#define JZ4740_CODEC_2_MIC_BOOST_GAIN_MASK 0x000030
63#define JZ4740_CODEC_2_HEADPHONE_VOLUME_MASK 0x000003
64
65#define JZ4740_CODEC_2_INPUT_VOLUME_OFFSET 16
66#define JZ4740_CODEC_2_SAMPLE_RATE_OFFSET 8
67#define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET 4
68#define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET 0
69
70static const uint32_t jz4740_codec_regs[] = {
71 0x021b2302, 0x00170803,
72};
73
74struct jz4740_codec {
75 void __iomem *base;
76 struct resource *mem;
77
78 uint32_t reg_cache[2];
79 struct snd_soc_codec codec;
80};
81
82static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
83{
84 return container_of(codec, struct jz4740_codec, codec);
85}
86
87static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
88 unsigned int reg)
89{
90 struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
91 return readl(jz4740_codec->base + (reg << 2));
92}
93
94static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
95 unsigned int val)
96{
97 struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
98
99 jz4740_codec->reg_cache[reg] = val;
100 writel(val, jz4740_codec->base + (reg << 2));
101
102 return 0;
103}
104
105static const struct snd_kcontrol_new jz4740_codec_controls[] = {
106 SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
107 JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
108 SOC_SINGLE("Master Capture Volume", JZ4740_REG_CODEC_2,
109 JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),
110 SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
111 JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
112 SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
113 JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
114};
115
116static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
117 SOC_DAPM_SINGLE("Bypass Switch", JZ4740_REG_CODEC_1,
118 JZ4740_CODEC_1_SW1_ENABLE_OFFSET, 1, 0),
119 SOC_DAPM_SINGLE("DAC Switch", JZ4740_REG_CODEC_1,
120 JZ4740_CODEC_1_SW2_ENABLE_OFFSET, 1, 0),
121};
122
123static const struct snd_kcontrol_new jz4740_codec_input_controls[] = {
124 SOC_DAPM_SINGLE("Line Capture Switch", JZ4740_REG_CODEC_1,
125 JZ4740_CODEC_1_LINE_ENABLE_OFFSET, 1, 0),
126 SOC_DAPM_SINGLE("Mic Capture Switch", JZ4740_REG_CODEC_1,
127 JZ4740_CODEC_1_MIC_ENABLE_OFFSET, 1, 0),
128};
129
130static const struct snd_soc_dapm_widget jz4740_codec_dapm_widgets[] = {
131 SND_SOC_DAPM_ADC("ADC", "Capture", JZ4740_REG_CODEC_1,
132 JZ4740_CODEC_1_ADC_ENABLE_OFFSET, 0),
133 SND_SOC_DAPM_DAC("DAC", "Playback", JZ4740_REG_CODEC_1,
134 JZ4740_CODEC_1_DAC_ENABLE_OFFSET, 0),
135
136 SND_SOC_DAPM_MIXER("Output Mixer", JZ4740_REG_CODEC_1,
137 JZ4740_CODEC_1_HEADPHONE_POWERDOWN_OFFSET, 1,
138 jz4740_codec_output_controls,
139 ARRAY_SIZE(jz4740_codec_output_controls)),
140
141 SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0,
142 jz4740_codec_input_controls,
143 ARRAY_SIZE(jz4740_codec_input_controls)),
144 SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
145
146 SND_SOC_DAPM_OUTPUT("LOUT"),
147 SND_SOC_DAPM_OUTPUT("ROUT"),
148
149 SND_SOC_DAPM_INPUT("MIC"),
150 SND_SOC_DAPM_INPUT("LIN"),
151 SND_SOC_DAPM_INPUT("RIN"),
152};
153
154static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
155 {"Line Input", NULL, "LIN"},
156 {"Line Input", NULL, "RIN"},
157
158 {"Input Mixer", "Line Capture Switch", "Line Input"},
159 {"Input Mixer", "Mic Capture Switch", "MIC"},
160
161 {"ADC", NULL, "Input Mixer"},
162
163 {"Output Mixer", "Bypass Switch", "Input Mixer"},
164 {"Output Mixer", "DAC Switch", "DAC"},
165
166 {"LOUT", NULL, "Output Mixer"},
167 {"ROUT", NULL, "Output Mixer"},
168};
169
170static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
171 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
172{
173 uint32_t val;
174 struct snd_soc_pcm_runtime *rtd = substream->private_data;
175 struct snd_soc_device *socdev = rtd->socdev;
176 struct snd_soc_codec *codec = socdev->card->codec;
177
178 switch (params_rate(params)) {
179 case 8000:
180 val = 0;
181 break;
182 case 11025:
183 val = 1;
184 break;
185 case 12000:
186 val = 2;
187 break;
188 case 16000:
189 val = 3;
190 break;
191 case 22050:
192 val = 4;
193 break;
194 case 24000:
195 val = 5;
196 break;
197 case 32000:
198 val = 6;
199 break;
200 case 44100:
201 val = 7;
202 break;
203 case 48000:
204 val = 8;
205 break;
206 default:
207 return -EINVAL;
208 }
209
210 val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET;
211
212 snd_soc_update_bits(codec, JZ4740_REG_CODEC_2,
213 JZ4740_CODEC_2_SAMPLE_RATE_MASK, val);
214
215 return 0;
216}
217
218static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
219 .hw_params = jz4740_codec_hw_params,
220};
221
222struct snd_soc_dai jz4740_codec_dai = {
223 .name = "jz4740",
224 .playback = {
225 .stream_name = "Playback",
226 .channels_min = 2,
227 .channels_max = 2,
228 .rates = SNDRV_PCM_RATE_8000_48000,
229 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
230 },
231 .capture = {
232 .stream_name = "Capture",
233 .channels_min = 2,
234 .channels_max = 2,
235 .rates = SNDRV_PCM_RATE_8000_48000,
236 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
237 },
238 .ops = &jz4740_codec_dai_ops,
239 .symmetric_rates = 1,
240};
241EXPORT_SYMBOL_GPL(jz4740_codec_dai);
242
243static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
244{
245 int i;
246 uint32_t *cache = codec->reg_cache;
247
248 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
249 JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
250 udelay(2);
251
252 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
253 JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0);
254
255 for (i = 0; i < ARRAY_SIZE(jz4740_codec_regs); ++i)
256 jz4740_codec_write(codec, i, cache[i]);
257}
258
259static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
260 enum snd_soc_bias_level level)
261{
262 unsigned int mask;
263 unsigned int value;
264
265 switch (level) {
266 case SND_SOC_BIAS_ON:
267 break;
268 case SND_SOC_BIAS_PREPARE:
269 mask = JZ4740_CODEC_1_VREF_DISABLE |
270 JZ4740_CODEC_1_VREF_AMP_DISABLE |
271 JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
272 value = 0;
273
274 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
275 break;
276 case SND_SOC_BIAS_STANDBY:
277 /* The only way to clear the suspend flag is to reset the codec */
278 if (codec->bias_level == SND_SOC_BIAS_OFF)
279 jz4740_codec_wakeup(codec);
280
281 mask = JZ4740_CODEC_1_VREF_DISABLE |
282 JZ4740_CODEC_1_VREF_AMP_DISABLE |
283 JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
284 value = JZ4740_CODEC_1_VREF_DISABLE |
285 JZ4740_CODEC_1_VREF_AMP_DISABLE |
286 JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
287
288 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
289 break;
290 case SND_SOC_BIAS_OFF:
291 mask = JZ4740_CODEC_1_SUSPEND;
292 value = JZ4740_CODEC_1_SUSPEND;
293
294 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
295 break;
296 default:
297 break;
298 }
299
300 codec->bias_level = level;
301
302 return 0;
303}
304
305static struct snd_soc_codec *jz4740_codec_codec;
306
307static int jz4740_codec_dev_probe(struct platform_device *pdev)
308{
309 int ret;
310 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
311 struct snd_soc_codec *codec = jz4740_codec_codec;
312
313 BUG_ON(!codec);
314
315 socdev->card->codec = codec;
316
317 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
318 if (ret) {
319 dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
320 return ret;
321 }
322
323 snd_soc_add_controls(codec, jz4740_codec_controls,
324 ARRAY_SIZE(jz4740_codec_controls));
325
326 snd_soc_dapm_new_controls(codec, jz4740_codec_dapm_widgets,
327 ARRAY_SIZE(jz4740_codec_dapm_widgets));
328
329 snd_soc_dapm_add_routes(codec, jz4740_codec_dapm_routes,
330 ARRAY_SIZE(jz4740_codec_dapm_routes));
331
332 snd_soc_dapm_new_widgets(codec);
333
334 return 0;
335}
336
337static int jz4740_codec_dev_remove(struct platform_device *pdev)
338{
339 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
340
341 snd_soc_free_pcms(socdev);
342 snd_soc_dapm_free(socdev);
343
344 return 0;
345}
346
347#ifdef CONFIG_PM_SLEEP
348
349static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state)
350{
351 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
352 struct snd_soc_codec *codec = socdev->card->codec;
353
354 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
355}
356
357static int jz4740_codec_resume(struct platform_device *pdev)
358{
359 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
360 struct snd_soc_codec *codec = socdev->card->codec;
361
362 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
363}
364
365#else
366#define jz4740_codec_suspend NULL
367#define jz4740_codec_resume NULL
368#endif
369
370struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
371 .probe = jz4740_codec_dev_probe,
372 .remove = jz4740_codec_dev_remove,
373 .suspend = jz4740_codec_suspend,
374 .resume = jz4740_codec_resume,
375};
376EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
377
378static int __devinit jz4740_codec_probe(struct platform_device *pdev)
379{
380 int ret;
381 struct jz4740_codec *jz4740_codec;
382 struct snd_soc_codec *codec;
383 struct resource *mem;
384
385 jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
386 if (!jz4740_codec)
387 return -ENOMEM;
388
389 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
390 if (!mem) {
391 dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
392 ret = -ENOENT;
393 goto err_free_codec;
394 }
395
396 mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
397 if (!mem) {
398 dev_err(&pdev->dev, "Failed to request mmio memory region\n");
399 ret = -EBUSY;
400 goto err_free_codec;
401 }
402
403 jz4740_codec->base = ioremap(mem->start, resource_size(mem));
404 if (!jz4740_codec->base) {
405 dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
406 ret = -EBUSY;
407 goto err_release_mem_region;
408 }
409 jz4740_codec->mem = mem;
410
411 jz4740_codec_dai.dev = &pdev->dev;
412
413 codec = &jz4740_codec->codec;
414
415 codec->dev = &pdev->dev;
416 codec->name = "jz4740";
417 codec->owner = THIS_MODULE;
418
419 codec->read = jz4740_codec_read;
420 codec->write = jz4740_codec_write;
421 codec->set_bias_level = jz4740_codec_set_bias_level;
422 codec->bias_level = SND_SOC_BIAS_OFF;
423
424 codec->dai = &jz4740_codec_dai;
425 codec->num_dai = 1;
426
427 codec->reg_cache = jz4740_codec->reg_cache;
428 codec->reg_cache_size = 2;
429 memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs));
430
431 mutex_init(&codec->mutex);
432 INIT_LIST_HEAD(&codec->dapm_widgets);
433 INIT_LIST_HEAD(&codec->dapm_paths);
434
435 jz4740_codec_codec = codec;
436
437 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
438 JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
439
440 platform_set_drvdata(pdev, jz4740_codec);
441
442 ret = snd_soc_register_codec(codec);
443 if (ret) {
444 dev_err(&pdev->dev, "Failed to register codec\n");
445 goto err_iounmap;
446 }
447
448 ret = snd_soc_register_dai(&jz4740_codec_dai);
449 if (ret) {
450 dev_err(&pdev->dev, "Failed to register codec dai\n");
451 goto err_unregister_codec;
452 }
453
454 jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
455
456 return 0;
457
458err_unregister_codec:
459 snd_soc_unregister_codec(codec);
460err_iounmap:
461 iounmap(jz4740_codec->base);
462err_release_mem_region:
463 release_mem_region(mem->start, resource_size(mem));
464err_free_codec:
465 kfree(jz4740_codec);
466
467 return ret;
468}
469
470static int __devexit jz4740_codec_remove(struct platform_device *pdev)
471{
472 struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
473 struct resource *mem = jz4740_codec->mem;
474
475 snd_soc_unregister_dai(&jz4740_codec_dai);
476 snd_soc_unregister_codec(&jz4740_codec->codec);
477
478 iounmap(jz4740_codec->base);
479 release_mem_region(mem->start, resource_size(mem));
480
481 platform_set_drvdata(pdev, NULL);
482 kfree(jz4740_codec);
483
484 return 0;
485}
486
487static struct platform_driver jz4740_codec_driver = {
488 .probe = jz4740_codec_probe,
489 .remove = __devexit_p(jz4740_codec_remove),
490 .driver = {
491 .name = "jz4740-codec",
492 .owner = THIS_MODULE,
493 },
494};
495
496static int __init jz4740_codec_init(void)
497{
498 return platform_driver_register(&jz4740_codec_driver);
499}
500module_init(jz4740_codec_init);
501
502static void __exit jz4740_codec_exit(void)
503{
504 platform_driver_unregister(&jz4740_codec_driver);
505}
506module_exit(jz4740_codec_exit);
507
508MODULE_DESCRIPTION("JZ4740 SoC internal codec driver");
509MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
510MODULE_LICENSE("GPL v2");
511MODULE_ALIAS("platform:jz4740-codec");
diff --git a/sound/soc/codecs/jz4740.h b/sound/soc/codecs/jz4740.h
new file mode 100644
index 000000000000..b5a0691be763
--- /dev/null
+++ b/sound/soc/codecs/jz4740.h
@@ -0,0 +1,20 @@
1/*
2 * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
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 * You should have received a copy of the GNU General Public License along
9 * with this program; if not, write to the Free Software Foundation, Inc.,
10 * 675 Mass Ave, Cambridge, MA 02139, USA.
11 *
12 */
13
14#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__
15#define __SND_SOC_CODECS_JZ4740_CODEC_H__
16
17extern struct snd_soc_dai jz4740_codec_dai;
18extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec;
19
20#endif
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
index a63191141052..9119836051a4 100644
--- a/sound/soc/codecs/spdif_transciever.c
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -16,8 +16,10 @@
16 16
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/moduleparam.h> 18#include <linux/moduleparam.h>
19#include <linux/slab.h>
19#include <sound/soc.h> 20#include <sound/soc.h>
20#include <sound/pcm.h> 21#include <sound/pcm.h>
22#include <sound/initval.h>
21 23
22#include "spdif_transciever.h" 24#include "spdif_transciever.h"
23 25
@@ -26,6 +28,48 @@ MODULE_LICENSE("GPL");
26#define STUB_RATES SNDRV_PCM_RATE_8000_96000 28#define STUB_RATES SNDRV_PCM_RATE_8000_96000
27#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE 29#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
28 30
31static struct snd_soc_codec *spdif_dit_codec;
32
33static int spdif_dit_codec_probe(struct platform_device *pdev)
34{
35 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
36 struct snd_soc_codec *codec;
37 int ret;
38
39 if (spdif_dit_codec == NULL) {
40 dev_err(&pdev->dev, "Codec device not registered\n");
41 return -ENODEV;
42 }
43
44 socdev->card->codec = spdif_dit_codec;
45 codec = spdif_dit_codec;
46
47 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
48 if (ret < 0) {
49 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
50 goto err_create_pcms;
51 }
52
53 return 0;
54
55err_create_pcms:
56 return ret;
57}
58
59static int spdif_dit_codec_remove(struct platform_device *pdev)
60{
61 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
62
63 snd_soc_free_pcms(socdev);
64
65 return 0;
66}
67
68struct snd_soc_codec_device soc_codec_dev_spdif_dit = {
69 .probe = spdif_dit_codec_probe,
70 .remove = spdif_dit_codec_remove,
71}; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit);
72
29struct snd_soc_dai dit_stub_dai = { 73struct snd_soc_dai dit_stub_dai = {
30 .name = "DIT", 74 .name = "DIT",
31 .playback = { 75 .playback = {
@@ -40,13 +84,61 @@ EXPORT_SYMBOL_GPL(dit_stub_dai);
40 84
41static int spdif_dit_probe(struct platform_device *pdev) 85static int spdif_dit_probe(struct platform_device *pdev)
42{ 86{
87 struct snd_soc_codec *codec;
88 int ret;
89
90 if (spdif_dit_codec) {
91 dev_err(&pdev->dev, "Another Codec is registered\n");
92 ret = -EINVAL;
93 goto err_reg_codec;
94 }
95
96 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
97 if (codec == NULL)
98 return -ENOMEM;
99
100 codec->dev = &pdev->dev;
101
102 mutex_init(&codec->mutex);
103
104 INIT_LIST_HEAD(&codec->dapm_widgets);
105 INIT_LIST_HEAD(&codec->dapm_paths);
106
107 codec->name = "spdif-dit";
108 codec->owner = THIS_MODULE;
109 codec->dai = &dit_stub_dai;
110 codec->num_dai = 1;
111
112 spdif_dit_codec = codec;
113
114 ret = snd_soc_register_codec(codec);
115 if (ret < 0) {
116 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
117 goto err_reg_codec;
118 }
119
43 dit_stub_dai.dev = &pdev->dev; 120 dit_stub_dai.dev = &pdev->dev;
44 return snd_soc_register_dai(&dit_stub_dai); 121 ret = snd_soc_register_dai(&dit_stub_dai);
122 if (ret < 0) {
123 dev_err(codec->dev, "Failed to register dai: %d\n", ret);
124 goto err_reg_dai;
125 }
126
127 return 0;
128
129err_reg_dai:
130 snd_soc_unregister_codec(codec);
131err_reg_codec:
132 kfree(spdif_dit_codec);
133 return ret;
45} 134}
46 135
47static int spdif_dit_remove(struct platform_device *pdev) 136static int spdif_dit_remove(struct platform_device *pdev)
48{ 137{
49 snd_soc_unregister_dai(&dit_stub_dai); 138 snd_soc_unregister_dai(&dit_stub_dai);
139 snd_soc_unregister_codec(spdif_dit_codec);
140 kfree(spdif_dit_codec);
141 spdif_dit_codec = NULL;
50 return 0; 142 return 0;
51} 143}
52 144
diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h
index 296f2eb6c4ef..1e102124f546 100644
--- a/sound/soc/codecs/spdif_transciever.h
+++ b/sound/soc/codecs/spdif_transciever.h
@@ -12,6 +12,7 @@
12#ifndef CODEC_STUBS_H 12#ifndef CODEC_STUBS_H
13#define CODEC_STUBS_H 13#define CODEC_STUBS_H
14 14
15extern struct snd_soc_codec_device soc_codec_dev_spdif_dit;
15extern struct snd_soc_dai dit_stub_dai; 16extern struct snd_soc_dai dit_stub_dai;
16 17
17#endif /* CODEC_STUBS_H */ 18#endif /* CODEC_STUBS_H */
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index b0bae3508b29..0a4b0fef3355 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -560,13 +560,16 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
560 switch (level) { 560 switch (level) {
561 case SND_SOC_BIAS_ON: 561 case SND_SOC_BIAS_ON:
562 /* vref/mid, osc on, dac unmute */ 562 /* vref/mid, osc on, dac unmute */
563 reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \
564 TLV320AIC23_DAC_OFF);
563 tlv320aic23_write(codec, TLV320AIC23_PWR, reg); 565 tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
564 break; 566 break;
565 case SND_SOC_BIAS_PREPARE: 567 case SND_SOC_BIAS_PREPARE:
566 break; 568 break;
567 case SND_SOC_BIAS_STANDBY: 569 case SND_SOC_BIAS_STANDBY:
568 /* everything off except vref/vmid, */ 570 /* everything off except vref/vmid, */
569 tlv320aic23_write(codec, TLV320AIC23_PWR, reg | 0x0040); 571 tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \
572 TLV320AIC23_CLK_OFF);
570 break; 573 break;
571 case SND_SOC_BIAS_OFF: 574 case SND_SOC_BIAS_OFF:
572 /* everything off, dac mute, inactive */ 575 /* everything off, dac mute, inactive */
@@ -615,7 +618,6 @@ static int tlv320aic23_suspend(struct platform_device *pdev,
615 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 618 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
616 struct snd_soc_codec *codec = socdev->card->codec; 619 struct snd_soc_codec *codec = socdev->card->codec;
617 620
618 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
619 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); 621 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
620 622
621 return 0; 623 return 0;
@@ -632,7 +634,6 @@ static int tlv320aic23_resume(struct platform_device *pdev)
632 u16 val = tlv320aic23_read_reg_cache(codec, reg); 634 u16 val = tlv320aic23_read_reg_cache(codec, reg);
633 tlv320aic23_write(codec, reg, val); 635 tlv320aic23_write(codec, reg, val);
634 } 636 }
635
636 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 637 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
637 638
638 return 0; 639 return 0;
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 65adc77eada1..8651b01ed223 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -49,8 +49,6 @@
49 49
50#define NSAMPLE_MAX 5700 50#define NSAMPLE_MAX 5700
51 51
52#define LATENCY_TIME_MS 20
53
54#define MODE7_LTHR 10 52#define MODE7_LTHR 10
55#define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) 53#define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10)
56 54
@@ -62,6 +60,9 @@
62#define US_TO_SAMPLES(rate, us) \ 60#define US_TO_SAMPLES(rate, us) \
63 (rate / (1000000 / us)) 61 (rate / (1000000 / us))
64 62
63#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
64 ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
65
65static void dac33_calculate_times(struct snd_pcm_substream *substream); 66static void dac33_calculate_times(struct snd_pcm_substream *substream);
66static int dac33_prepare_chip(struct snd_pcm_substream *substream); 67static int dac33_prepare_chip(struct snd_pcm_substream *substream);
67 68
@@ -107,6 +108,10 @@ struct tlv320dac33_priv {
107 * this */ 108 * this */
108 enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ 109 enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */
109 unsigned int nsample; /* burst read amount from host */ 110 unsigned int nsample; /* burst read amount from host */
111 int mode1_latency; /* latency caused by the i2c writes in
112 * us */
113 int auto_fifo_config; /* Configure the FIFO based on the
114 * period size */
110 u8 burst_bclkdiv; /* BCLK divider value in burst mode */ 115 u8 burst_bclkdiv; /* BCLK divider value in burst mode */
111 unsigned int burst_rate; /* Interface speed in Burst modes */ 116 unsigned int burst_rate; /* Interface speed in Burst modes */
112 117
@@ -120,6 +125,8 @@ struct tlv320dac33_priv {
120 * samples */ 125 * samples */
121 unsigned int mode7_us_to_lthr; /* Time to reach lthr from uthr */ 126 unsigned int mode7_us_to_lthr; /* Time to reach lthr from uthr */
122 127
128 unsigned int uthr;
129
123 enum dac33_state state; 130 enum dac33_state state;
124}; 131};
125 132
@@ -442,6 +449,39 @@ static int dac33_set_nsample(struct snd_kcontrol *kcontrol,
442 return ret; 449 return ret;
443} 450}
444 451
452static int dac33_get_uthr(struct snd_kcontrol *kcontrol,
453 struct snd_ctl_elem_value *ucontrol)
454{
455 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
456 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
457
458 ucontrol->value.integer.value[0] = dac33->uthr;
459
460 return 0;
461}
462
463static int dac33_set_uthr(struct snd_kcontrol *kcontrol,
464 struct snd_ctl_elem_value *ucontrol)
465{
466 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
467 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
468 int ret = 0;
469
470 if (dac33->substream)
471 return -EBUSY;
472
473 if (dac33->uthr == ucontrol->value.integer.value[0])
474 return 0;
475
476 if (ucontrol->value.integer.value[0] < (MODE7_LTHR + 10) ||
477 ucontrol->value.integer.value[0] > MODE7_UTHR)
478 ret = -EINVAL;
479 else
480 dac33->uthr = ucontrol->value.integer.value[0];
481
482 return ret;
483}
484
445static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol, 485static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
446 struct snd_ctl_elem_value *ucontrol) 486 struct snd_ctl_elem_value *ucontrol)
447{ 487{
@@ -503,13 +543,18 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = {
503 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), 543 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
504}; 544};
505 545
506static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = { 546static const struct snd_kcontrol_new dac33_mode_snd_controls[] = {
507 SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0,
508 dac33_get_nsample, dac33_set_nsample),
509 SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, 547 SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum,
510 dac33_get_fifo_mode, dac33_set_fifo_mode), 548 dac33_get_fifo_mode, dac33_set_fifo_mode),
511}; 549};
512 550
551static const struct snd_kcontrol_new dac33_fifo_snd_controls[] = {
552 SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0,
553 dac33_get_nsample, dac33_set_nsample),
554 SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0,
555 dac33_get_uthr, dac33_set_uthr),
556};
557
513/* Analog bypass */ 558/* Analog bypass */
514static const struct snd_kcontrol_new dac33_dapm_abypassl_control = 559static const struct snd_kcontrol_new dac33_dapm_abypassl_control =
515 SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1); 560 SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1);
@@ -612,7 +657,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
612 switch (dac33->fifo_mode) { 657 switch (dac33->fifo_mode) {
613 case DAC33_FIFO_MODE1: 658 case DAC33_FIFO_MODE1:
614 dac33_write16(codec, DAC33_NSAMPLE_MSB, 659 dac33_write16(codec, DAC33_NSAMPLE_MSB,
615 DAC33_THRREG(dac33->nsample + dac33->alarm_threshold)); 660 DAC33_THRREG(dac33->nsample));
616 661
617 /* Take the timestamps */ 662 /* Take the timestamps */
618 spin_lock_irq(&dac33->lock); 663 spin_lock_irq(&dac33->lock);
@@ -761,6 +806,10 @@ static void dac33_shutdown(struct snd_pcm_substream *substream,
761 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 806 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
762 807
763 dac33->substream = NULL; 808 dac33->substream = NULL;
809
810 /* Reset the nSample restrictions */
811 dac33->nsample_min = 0;
812 dac33->nsample_max = NSAMPLE_MAX;
764} 813}
765 814
766static int dac33_hw_params(struct snd_pcm_substream *substream, 815static int dac33_hw_params(struct snd_pcm_substream *substream,
@@ -985,7 +1034,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
985 * Configure the threshold levels, and leave 10 sample space 1034 * Configure the threshold levels, and leave 10 sample space
986 * at the bottom, and also at the top of the FIFO 1035 * at the bottom, and also at the top of the FIFO
987 */ 1036 */
988 dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(MODE7_UTHR)); 1037 dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(dac33->uthr));
989 dac33_write16(codec, DAC33_LTHR_MSB, DAC33_THRREG(MODE7_LTHR)); 1038 dac33_write16(codec, DAC33_LTHR_MSB, DAC33_THRREG(MODE7_LTHR));
990 break; 1039 break;
991 default: 1040 default:
@@ -1003,57 +1052,71 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
1003 struct snd_soc_device *socdev = rtd->socdev; 1052 struct snd_soc_device *socdev = rtd->socdev;
1004 struct snd_soc_codec *codec = socdev->card->codec; 1053 struct snd_soc_codec *codec = socdev->card->codec;
1005 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 1054 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
1055 unsigned int period_size = substream->runtime->period_size;
1056 unsigned int rate = substream->runtime->rate;
1006 unsigned int nsample_limit; 1057 unsigned int nsample_limit;
1007 1058
1008 /* In bypass mode we don't need to calculate */ 1059 /* In bypass mode we don't need to calculate */
1009 if (!dac33->fifo_mode) 1060 if (!dac33->fifo_mode)
1010 return; 1061 return;
1011 1062
1012 /* Number of samples (16bit, stereo) in one period */
1013 dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4;
1014
1015 /* Number of samples (16bit, stereo) in ALSA buffer */
1016 dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4;
1017 /* Subtract one period from the total */
1018 dac33->nsample_max -= dac33->nsample_min;
1019
1020 /* Number of samples for LATENCY_TIME_MS / 2 */
1021 dac33->alarm_threshold = substream->runtime->rate /
1022 (1000 / (LATENCY_TIME_MS / 2));
1023
1024 /* Find and fix up the lowest nsmaple limit */
1025 nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS);
1026
1027 if (dac33->nsample_min < nsample_limit)
1028 dac33->nsample_min = nsample_limit;
1029
1030 if (dac33->nsample < dac33->nsample_min)
1031 dac33->nsample = dac33->nsample_min;
1032
1033 /*
1034 * Find and fix up the highest nsmaple limit
1035 * In order to not overflow the DAC33 buffer substract the
1036 * alarm_threshold value from the size of the DAC33 buffer
1037 */
1038 nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold;
1039
1040 if (dac33->nsample_max > nsample_limit)
1041 dac33->nsample_max = nsample_limit;
1042
1043 if (dac33->nsample > dac33->nsample_max)
1044 dac33->nsample = dac33->nsample_max;
1045
1046 switch (dac33->fifo_mode) { 1063 switch (dac33->fifo_mode) {
1047 case DAC33_FIFO_MODE1: 1064 case DAC33_FIFO_MODE1:
1065 /* Number of samples under i2c latency */
1066 dac33->alarm_threshold = US_TO_SAMPLES(rate,
1067 dac33->mode1_latency);
1068 if (dac33->auto_fifo_config) {
1069 if (period_size <= dac33->alarm_threshold)
1070 /*
1071 * Configure nSamaple to number of periods,
1072 * which covers the latency requironment.
1073 */
1074 dac33->nsample = period_size *
1075 ((dac33->alarm_threshold / period_size) +
1076 (dac33->alarm_threshold % period_size ?
1077 1 : 0));
1078 else
1079 dac33->nsample = period_size;
1080 } else {
1081 /* nSample time shall not be shorter than i2c latency */
1082 dac33->nsample_min = dac33->alarm_threshold;
1083 /*
1084 * nSample should not be bigger than alsa buffer minus
1085 * size of one period to avoid overruns
1086 */
1087 dac33->nsample_max = substream->runtime->buffer_size -
1088 period_size;
1089 nsample_limit = DAC33_BUFFER_SIZE_SAMPLES -
1090 dac33->alarm_threshold;
1091 if (dac33->nsample_max > nsample_limit)
1092 dac33->nsample_max = nsample_limit;
1093
1094 /* Correct the nSample if it is outside of the ranges */
1095 if (dac33->nsample < dac33->nsample_min)
1096 dac33->nsample = dac33->nsample_min;
1097 if (dac33->nsample > dac33->nsample_max)
1098 dac33->nsample = dac33->nsample_max;
1099 }
1100
1048 dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, 1101 dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate,
1049 dac33->nsample); 1102 dac33->nsample);
1050 dac33->t_stamp1 = 0; 1103 dac33->t_stamp1 = 0;
1051 dac33->t_stamp2 = 0; 1104 dac33->t_stamp2 = 0;
1052 break; 1105 break;
1053 case DAC33_FIFO_MODE7: 1106 case DAC33_FIFO_MODE7:
1107 if (dac33->auto_fifo_config) {
1108 dac33->uthr = UTHR_FROM_PERIOD_SIZE(
1109 period_size,
1110 rate,
1111 dac33->burst_rate) + 9;
1112 if (dac33->uthr > MODE7_UTHR)
1113 dac33->uthr = MODE7_UTHR;
1114 if (dac33->uthr < (MODE7_LTHR + 10))
1115 dac33->uthr = (MODE7_LTHR + 10);
1116 }
1054 dac33->mode7_us_to_lthr = 1117 dac33->mode7_us_to_lthr =
1055 SAMPLES_TO_US(substream->runtime->rate, 1118 SAMPLES_TO_US(substream->runtime->rate,
1056 MODE7_UTHR - MODE7_LTHR + 1); 1119 dac33->uthr - MODE7_LTHR + 1);
1057 dac33->t_stamp1 = 0; 1120 dac33->t_stamp1 = 0;
1058 break; 1121 break;
1059 default: 1122 default:
@@ -1104,7 +1167,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
1104 struct snd_soc_codec *codec = socdev->card->codec; 1167 struct snd_soc_codec *codec = socdev->card->codec;
1105 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 1168 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
1106 unsigned long long t0, t1, t_now; 1169 unsigned long long t0, t1, t_now;
1107 unsigned int time_delta; 1170 unsigned int time_delta, uthr;
1108 int samples_out, samples_in, samples; 1171 int samples_out, samples_in, samples;
1109 snd_pcm_sframes_t delay = 0; 1172 snd_pcm_sframes_t delay = 0;
1110 1173
@@ -1182,6 +1245,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
1182 case DAC33_FIFO_MODE7: 1245 case DAC33_FIFO_MODE7:
1183 spin_lock(&dac33->lock); 1246 spin_lock(&dac33->lock);
1184 t0 = dac33->t_stamp1; 1247 t0 = dac33->t_stamp1;
1248 uthr = dac33->uthr;
1185 spin_unlock(&dac33->lock); 1249 spin_unlock(&dac33->lock);
1186 t_now = ktime_to_us(ktime_get()); 1250 t_now = ktime_to_us(ktime_get());
1187 1251
@@ -1194,7 +1258,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
1194 * Either the timestamps are messed or equal. Report 1258 * Either the timestamps are messed or equal. Report
1195 * maximum delay 1259 * maximum delay
1196 */ 1260 */
1197 delay = MODE7_UTHR; 1261 delay = uthr;
1198 goto out; 1262 goto out;
1199 } 1263 }
1200 1264
@@ -1208,8 +1272,8 @@ static snd_pcm_sframes_t dac33_dai_delay(
1208 substream->runtime->rate, 1272 substream->runtime->rate,
1209 time_delta); 1273 time_delta);
1210 1274
1211 if (likely(MODE7_UTHR > samples_out)) 1275 if (likely(uthr > samples_out))
1212 delay = MODE7_UTHR - samples_out; 1276 delay = uthr - samples_out;
1213 else 1277 else
1214 delay = 0; 1278 delay = 0;
1215 } else { 1279 } else {
@@ -1227,8 +1291,8 @@ static snd_pcm_sframes_t dac33_dai_delay(
1227 time_delta); 1291 time_delta);
1228 delay = MODE7_LTHR + samples_in - samples_out; 1292 delay = MODE7_LTHR + samples_in - samples_out;
1229 1293
1230 if (unlikely(delay > MODE7_UTHR)) 1294 if (unlikely(delay > uthr))
1231 delay = MODE7_UTHR; 1295 delay = uthr;
1232 } 1296 }
1233 break; 1297 break;
1234 default: 1298 default:
@@ -1347,10 +1411,15 @@ static int dac33_soc_probe(struct platform_device *pdev)
1347 1411
1348 snd_soc_add_controls(codec, dac33_snd_controls, 1412 snd_soc_add_controls(codec, dac33_snd_controls,
1349 ARRAY_SIZE(dac33_snd_controls)); 1413 ARRAY_SIZE(dac33_snd_controls));
1350 /* Only add the nSample controls, if we have valid IRQ number */ 1414 /* Only add the FIFO controls, if we have valid IRQ number */
1351 if (dac33->irq >= 0) 1415 if (dac33->irq >= 0) {
1352 snd_soc_add_controls(codec, dac33_nsample_snd_controls, 1416 snd_soc_add_controls(codec, dac33_mode_snd_controls,
1353 ARRAY_SIZE(dac33_nsample_snd_controls)); 1417 ARRAY_SIZE(dac33_mode_snd_controls));
1418 /* FIFO usage controls only, if autoio config is not selected */
1419 if (!dac33->auto_fifo_config)
1420 snd_soc_add_controls(codec, dac33_fifo_snd_controls,
1421 ARRAY_SIZE(dac33_fifo_snd_controls));
1422 }
1354 1423
1355 dac33_add_widgets(codec); 1424 dac33_add_widgets(codec);
1356 1425
@@ -1481,9 +1550,14 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
1481 /* Pre calculate the burst rate */ 1550 /* Pre calculate the burst rate */
1482 dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; 1551 dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32;
1483 dac33->keep_bclk = pdata->keep_bclk; 1552 dac33->keep_bclk = pdata->keep_bclk;
1553 dac33->auto_fifo_config = pdata->auto_fifo_config;
1554 dac33->mode1_latency = pdata->mode1_latency;
1555 if (!dac33->mode1_latency)
1556 dac33->mode1_latency = 10000; /* 10ms */
1484 dac33->irq = client->irq; 1557 dac33->irq = client->irq;
1485 dac33->nsample = NSAMPLE_MAX; 1558 dac33->nsample = NSAMPLE_MAX;
1486 dac33->nsample_max = NSAMPLE_MAX; 1559 dac33->nsample_max = NSAMPLE_MAX;
1560 dac33->uthr = MODE7_UTHR;
1487 /* Disable FIFO use by default */ 1561 /* Disable FIFO use by default */
1488 dac33->fifo_mode = DAC33_FIFO_BYPASS; 1562 dac33->fifo_mode = DAC33_FIFO_BYPASS;
1489 1563
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index b4fcdb01fc49..7b618bbff884 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -43,37 +43,37 @@
43 */ 43 */
44static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { 44static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
45 0x00, /* this register not used */ 45 0x00, /* this register not used */
46 0x91, /* REG_CODEC_MODE (0x1) */ 46 0x00, /* REG_CODEC_MODE (0x1) */
47 0xc3, /* REG_OPTION (0x2) */ 47 0x00, /* REG_OPTION (0x2) */
48 0x00, /* REG_UNKNOWN (0x3) */ 48 0x00, /* REG_UNKNOWN (0x3) */
49 0x00, /* REG_MICBIAS_CTL (0x4) */ 49 0x00, /* REG_MICBIAS_CTL (0x4) */
50 0x20, /* REG_ANAMICL (0x5) */ 50 0x00, /* REG_ANAMICL (0x5) */
51 0x00, /* REG_ANAMICR (0x6) */ 51 0x00, /* REG_ANAMICR (0x6) */
52 0x00, /* REG_AVADC_CTL (0x7) */ 52 0x00, /* REG_AVADC_CTL (0x7) */
53 0x00, /* REG_ADCMICSEL (0x8) */ 53 0x00, /* REG_ADCMICSEL (0x8) */
54 0x00, /* REG_DIGMIXING (0x9) */ 54 0x00, /* REG_DIGMIXING (0x9) */
55 0x0c, /* REG_ATXL1PGA (0xA) */ 55 0x0f, /* REG_ATXL1PGA (0xA) */
56 0x0c, /* REG_ATXR1PGA (0xB) */ 56 0x0f, /* REG_ATXR1PGA (0xB) */
57 0x00, /* REG_AVTXL2PGA (0xC) */ 57 0x0f, /* REG_AVTXL2PGA (0xC) */
58 0x00, /* REG_AVTXR2PGA (0xD) */ 58 0x0f, /* REG_AVTXR2PGA (0xD) */
59 0x00, /* REG_AUDIO_IF (0xE) */ 59 0x00, /* REG_AUDIO_IF (0xE) */
60 0x00, /* REG_VOICE_IF (0xF) */ 60 0x00, /* REG_VOICE_IF (0xF) */
61 0x00, /* REG_ARXR1PGA (0x10) */ 61 0x3f, /* REG_ARXR1PGA (0x10) */
62 0x00, /* REG_ARXL1PGA (0x11) */ 62 0x3f, /* REG_ARXL1PGA (0x11) */
63 0x6c, /* REG_ARXR2PGA (0x12) */ 63 0x3f, /* REG_ARXR2PGA (0x12) */
64 0x6c, /* REG_ARXL2PGA (0x13) */ 64 0x3f, /* REG_ARXL2PGA (0x13) */
65 0x00, /* REG_VRXPGA (0x14) */ 65 0x25, /* REG_VRXPGA (0x14) */
66 0x00, /* REG_VSTPGA (0x15) */ 66 0x00, /* REG_VSTPGA (0x15) */
67 0x00, /* REG_VRX2ARXPGA (0x16) */ 67 0x00, /* REG_VRX2ARXPGA (0x16) */
68 0x00, /* REG_AVDAC_CTL (0x17) */ 68 0x00, /* REG_AVDAC_CTL (0x17) */
69 0x00, /* REG_ARX2VTXPGA (0x18) */ 69 0x00, /* REG_ARX2VTXPGA (0x18) */
70 0x00, /* REG_ARXL1_APGA_CTL (0x19) */ 70 0x32, /* REG_ARXL1_APGA_CTL (0x19) */
71 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */ 71 0x32, /* REG_ARXR1_APGA_CTL (0x1A) */
72 0x4a, /* REG_ARXL2_APGA_CTL (0x1B) */ 72 0x32, /* REG_ARXL2_APGA_CTL (0x1B) */
73 0x4a, /* REG_ARXR2_APGA_CTL (0x1C) */ 73 0x32, /* REG_ARXR2_APGA_CTL (0x1C) */
74 0x00, /* REG_ATX2ARXPGA (0x1D) */ 74 0x00, /* REG_ATX2ARXPGA (0x1D) */
75 0x00, /* REG_BT_IF (0x1E) */ 75 0x00, /* REG_BT_IF (0x1E) */
76 0x00, /* REG_BTPGA (0x1F) */ 76 0x55, /* REG_BTPGA (0x1F) */
77 0x00, /* REG_BTSTPGA (0x20) */ 77 0x00, /* REG_BTSTPGA (0x20) */
78 0x00, /* REG_EAR_CTL (0x21) */ 78 0x00, /* REG_EAR_CTL (0x21) */
79 0x00, /* REG_HS_SEL (0x22) */ 79 0x00, /* REG_HS_SEL (0x22) */
@@ -85,32 +85,32 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
85 0x00, /* REG_PRECKR_CTL (0x28) */ 85 0x00, /* REG_PRECKR_CTL (0x28) */
86 0x00, /* REG_HFL_CTL (0x29) */ 86 0x00, /* REG_HFL_CTL (0x29) */
87 0x00, /* REG_HFR_CTL (0x2A) */ 87 0x00, /* REG_HFR_CTL (0x2A) */
88 0x00, /* REG_ALC_CTL (0x2B) */ 88 0x05, /* REG_ALC_CTL (0x2B) */
89 0x00, /* REG_ALC_SET1 (0x2C) */ 89 0x00, /* REG_ALC_SET1 (0x2C) */
90 0x00, /* REG_ALC_SET2 (0x2D) */ 90 0x00, /* REG_ALC_SET2 (0x2D) */
91 0x00, /* REG_BOOST_CTL (0x2E) */ 91 0x00, /* REG_BOOST_CTL (0x2E) */
92 0x00, /* REG_SOFTVOL_CTL (0x2F) */ 92 0x00, /* REG_SOFTVOL_CTL (0x2F) */
93 0x00, /* REG_DTMF_FREQSEL (0x30) */ 93 0x13, /* REG_DTMF_FREQSEL (0x30) */
94 0x00, /* REG_DTMF_TONEXT1H (0x31) */ 94 0x00, /* REG_DTMF_TONEXT1H (0x31) */
95 0x00, /* REG_DTMF_TONEXT1L (0x32) */ 95 0x00, /* REG_DTMF_TONEXT1L (0x32) */
96 0x00, /* REG_DTMF_TONEXT2H (0x33) */ 96 0x00, /* REG_DTMF_TONEXT2H (0x33) */
97 0x00, /* REG_DTMF_TONEXT2L (0x34) */ 97 0x00, /* REG_DTMF_TONEXT2L (0x34) */
98 0x00, /* REG_DTMF_TONOFF (0x35) */ 98 0x79, /* REG_DTMF_TONOFF (0x35) */
99 0x00, /* REG_DTMF_WANONOFF (0x36) */ 99 0x11, /* REG_DTMF_WANONOFF (0x36) */
100 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */ 100 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */
101 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */ 101 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */
102 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */ 102 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */
103 0x06, /* REG_APLL_CTL (0x3A) */ 103 0x06, /* REG_APLL_CTL (0x3A) */
104 0x00, /* REG_DTMF_CTL (0x3B) */ 104 0x00, /* REG_DTMF_CTL (0x3B) */
105 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */ 105 0x44, /* REG_DTMF_PGA_CTL2 (0x3C) */
106 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */ 106 0x69, /* REG_DTMF_PGA_CTL1 (0x3D) */
107 0x00, /* REG_MISC_SET_1 (0x3E) */ 107 0x00, /* REG_MISC_SET_1 (0x3E) */
108 0x00, /* REG_PCMBTMUX (0x3F) */ 108 0x00, /* REG_PCMBTMUX (0x3F) */
109 0x00, /* not used (0x40) */ 109 0x00, /* not used (0x40) */
110 0x00, /* not used (0x41) */ 110 0x00, /* not used (0x41) */
111 0x00, /* not used (0x42) */ 111 0x00, /* not used (0x42) */
112 0x00, /* REG_RX_PATH_SEL (0x43) */ 112 0x00, /* REG_RX_PATH_SEL (0x43) */
113 0x00, /* REG_VDL_APGA_CTL (0x44) */ 113 0x32, /* REG_VDL_APGA_CTL (0x44) */
114 0x00, /* REG_VIBRA_CTL (0x45) */ 114 0x00, /* REG_VIBRA_CTL (0x45) */
115 0x00, /* REG_VIBRA_SET (0x46) */ 115 0x00, /* REG_VIBRA_SET (0x46) */
116 0x00, /* REG_VIBRA_PWM_SET (0x47) */ 116 0x00, /* REG_VIBRA_PWM_SET (0x47) */
@@ -143,6 +143,9 @@ struct twl4030_priv {
143 u8 earpiece_enabled; 143 u8 earpiece_enabled;
144 u8 predrivel_enabled, predriver_enabled; 144 u8 predrivel_enabled, predriver_enabled;
145 u8 carkitl_enabled, carkitr_enabled; 145 u8 carkitl_enabled, carkitr_enabled;
146
147 /* Delay needed after enabling the digimic interface */
148 unsigned int digimic_delay;
146}; 149};
147 150
148/* 151/*
@@ -244,58 +247,95 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
244 udelay(10); 247 udelay(10);
245} 248}
246 249
247static void twl4030_init_chip(struct snd_soc_codec *codec) 250static inline void twl4030_check_defaults(struct snd_soc_codec *codec)
248{ 251{
249 u8 *cache = codec->reg_cache; 252 int i, difference = 0;
250 int i; 253 u8 val;
254
255 dev_dbg(codec->dev, "Checking TWL audio default configuration\n");
256 for (i = 1; i <= TWL4030_REG_MISC_SET_2; i++) {
257 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val, i);
258 if (val != twl4030_reg[i]) {
259 difference++;
260 dev_dbg(codec->dev,
261 "Reg 0x%02x: chip: 0x%02x driver: 0x%02x\n",
262 i, val, twl4030_reg[i]);
263 }
264 }
265 dev_dbg(codec->dev, "Found %d non maching registers. %s\n",
266 difference, difference ? "Not OK" : "OK");
267}
251 268
252 /* clear CODECPDZ prior to setting register defaults */ 269static inline void twl4030_reset_registers(struct snd_soc_codec *codec)
253 twl4030_codec_enable(codec, 0); 270{
271 int i;
254 272
255 /* set all audio section registers to reasonable defaults */ 273 /* set all audio section registers to reasonable defaults */
256 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) 274 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
257 if (i != TWL4030_REG_APLL_CTL) 275 if (i != TWL4030_REG_APLL_CTL)
258 twl4030_write(codec, i, cache[i]); 276 twl4030_write(codec, i, twl4030_reg[i]);
259 277
260} 278}
261 279
262static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) 280static void twl4030_init_chip(struct platform_device *pdev)
263{ 281{
282 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
283 struct twl4030_setup_data *setup = socdev->codec_data;
284 struct snd_soc_codec *codec = socdev->card->codec;
264 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 285 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
265 int status = -1; 286 u8 reg, byte;
287 int i = 0;
266 288
267 if (enable) { 289 /* Check defaults, if instructed before anything else */
268 twl4030->apll_enabled++; 290 if (setup && setup->check_defaults)
269 if (twl4030->apll_enabled == 1) 291 twl4030_check_defaults(codec);
270 status = twl4030_codec_enable_resource(
271 TWL4030_CODEC_RES_APLL);
272 } else {
273 twl4030->apll_enabled--;
274 if (!twl4030->apll_enabled)
275 status = twl4030_codec_disable_resource(
276 TWL4030_CODEC_RES_APLL);
277 }
278 292
279 if (status >= 0) 293 /* Reset registers, if no setup data or if instructed to do so */
280 twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); 294 if (!setup || (setup && setup->reset_registers))
281} 295 twl4030_reset_registers(codec);
282 296
283static void twl4030_power_up(struct snd_soc_codec *codec) 297 /* Refresh APLL_CTL register from HW */
284{ 298 twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
285 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 299 TWL4030_REG_APLL_CTL);
286 u8 anamicl, regmisc1, byte; 300 twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, byte);
287 int i = 0; 301
302 /* anti-pop when changing analog gain */
303 reg = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
304 twl4030_write(codec, TWL4030_REG_MISC_SET_1,
305 reg | TWL4030_SMOOTH_ANAVOL_EN);
288 306
289 if (twl4030->codec_powered) 307 twl4030_write(codec, TWL4030_REG_OPTION,
308 TWL4030_ATXL1_EN | TWL4030_ATXR1_EN |
309 TWL4030_ARXL2_EN | TWL4030_ARXR2_EN);
310
311 /* REG_ARXR2_APGA_CTL reset according to the TRM: 0dB, DA_EN */
312 twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32);
313
314 /* Machine dependent setup */
315 if (!setup)
290 return; 316 return;
291 317
292 /* set CODECPDZ to turn on codec */ 318 twl4030->digimic_delay = setup->digimic_delay;
293 twl4030_codec_enable(codec, 1); 319
320 /* Configuration for headset ramp delay from setup data */
321 if (setup->sysclk != twl4030->sysclk)
322 dev_warn(codec->dev,
323 "Mismatch in APLL mclk: %u (configured: %u)\n",
324 setup->sysclk, twl4030->sysclk);
325
326 reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
327 reg &= ~TWL4030_RAMP_DELAY;
328 reg |= (setup->ramp_delay_value << 2);
329 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg);
294 330
295 /* initiate offset cancellation */ 331 /* initiate offset cancellation */
296 anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); 332 twl4030_codec_enable(codec, 1);
333
334 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
335 reg &= ~TWL4030_OFFSET_CNCL_SEL;
336 reg |= setup->offset_cncl_path;
297 twl4030_write(codec, TWL4030_REG_ANAMICL, 337 twl4030_write(codec, TWL4030_REG_ANAMICL,
298 anamicl | TWL4030_CNCL_OFFSET_START); 338 reg | TWL4030_CNCL_OFFSET_START);
299 339
300 /* wait for offset cancellation to complete */ 340 /* wait for offset cancellation to complete */
301 do { 341 do {
@@ -310,23 +350,28 @@ static void twl4030_power_up(struct snd_soc_codec *codec)
310 /* Make sure that the reg_cache has the same value as the HW */ 350 /* Make sure that the reg_cache has the same value as the HW */
311 twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); 351 twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte);
312 352
313 /* anti-pop when changing analog gain */
314 regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
315 twl4030_write(codec, TWL4030_REG_MISC_SET_1,
316 regmisc1 | TWL4030_SMOOTH_ANAVOL_EN);
317
318 /* toggle CODECPDZ as per TRM */
319 twl4030_codec_enable(codec, 0); 353 twl4030_codec_enable(codec, 0);
320 twl4030_codec_enable(codec, 1);
321} 354}
322 355
323/* 356static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
324 * Unconditional power down
325 */
326static void twl4030_power_down(struct snd_soc_codec *codec)
327{ 357{
328 /* power down */ 358 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
329 twl4030_codec_enable(codec, 0); 359 int status = -1;
360
361 if (enable) {
362 twl4030->apll_enabled++;
363 if (twl4030->apll_enabled == 1)
364 status = twl4030_codec_enable_resource(
365 TWL4030_CODEC_RES_APLL);
366 } else {
367 twl4030->apll_enabled--;
368 if (!twl4030->apll_enabled)
369 status = twl4030_codec_disable_resource(
370 TWL4030_CODEC_RES_APLL);
371 }
372
373 if (status >= 0)
374 twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status);
330} 375}
331 376
332/* Earpiece */ 377/* Earpiece */
@@ -500,10 +545,11 @@ static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control =
500static const struct snd_kcontrol_new twl4030_dapm_abypassv_control = 545static const struct snd_kcontrol_new twl4030_dapm_abypassv_control =
501 SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0); 546 SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0);
502 547
503/* Digital bypass gain, 0 mutes the bypass */ 548/* Digital bypass gain, mute instead of -30dB */
504static const unsigned int twl4030_dapm_dbypass_tlv[] = { 549static const unsigned int twl4030_dapm_dbypass_tlv[] = {
505 TLV_DB_RANGE_HEAD(2), 550 TLV_DB_RANGE_HEAD(3),
506 0, 3, TLV_DB_SCALE_ITEM(-2400, 0, 1), 551 0, 1, TLV_DB_SCALE_ITEM(-3000, 600, 1),
552 2, 3, TLV_DB_SCALE_ITEM(-2400, 0, 0),
507 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0), 553 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0),
508}; 554};
509 555
@@ -531,36 +577,6 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control =
531 TWL4030_REG_VSTPGA, 0, 0x29, 0, 577 TWL4030_REG_VSTPGA, 0, 0x29, 0,
532 twl4030_dapm_dbypassv_tlv); 578 twl4030_dapm_dbypassv_tlv);
533 579
534static int micpath_event(struct snd_soc_dapm_widget *w,
535 struct snd_kcontrol *kcontrol, int event)
536{
537 struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
538 unsigned char adcmicsel, micbias_ctl;
539
540 adcmicsel = twl4030_read_reg_cache(w->codec, TWL4030_REG_ADCMICSEL);
541 micbias_ctl = twl4030_read_reg_cache(w->codec, TWL4030_REG_MICBIAS_CTL);
542 /* Prepare the bits for the given TX path:
543 * shift_l == 0: TX1 microphone path
544 * shift_l == 2: TX2 microphone path */
545 if (e->shift_l) {
546 /* TX2 microphone path */
547 if (adcmicsel & TWL4030_TX2IN_SEL)
548 micbias_ctl |= TWL4030_MICBIAS2_CTL; /* digimic */
549 else
550 micbias_ctl &= ~TWL4030_MICBIAS2_CTL;
551 } else {
552 /* TX1 microphone path */
553 if (adcmicsel & TWL4030_TX1IN_SEL)
554 micbias_ctl |= TWL4030_MICBIAS1_CTL; /* digimic */
555 else
556 micbias_ctl &= ~TWL4030_MICBIAS1_CTL;
557 }
558
559 twl4030_write(w->codec, TWL4030_REG_MICBIAS_CTL, micbias_ctl);
560
561 return 0;
562}
563
564/* 580/*
565 * Output PGA builder: 581 * Output PGA builder:
566 * Handle the muting and unmuting of the given output (turning off the 582 * Handle the muting and unmuting of the given output (turning off the
@@ -814,6 +830,16 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w,
814 return 0; 830 return 0;
815} 831}
816 832
833static int digimic_event(struct snd_soc_dapm_widget *w,
834 struct snd_kcontrol *kcontrol, int event)
835{
836 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
837
838 if (twl4030->digimic_delay)
839 mdelay(twl4030->digimic_delay);
840 return 0;
841}
842
817/* 843/*
818 * Some of the gain controls in TWL (mostly those which are associated with 844 * Some of the gain controls in TWL (mostly those which are associated with
819 * the outputs) are implemented in an interesting way: 845 * the outputs) are implemented in an interesting way:
@@ -1374,14 +1400,10 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1374 /* Analog/Digital mic path selection. 1400 /* Analog/Digital mic path selection.
1375 TX1 Left/Right: either analog Left/Right or Digimic0 1401 TX1 Left/Right: either analog Left/Right or Digimic0
1376 TX2 Left/Right: either analog Left/Right or Digimic1 */ 1402 TX2 Left/Right: either analog Left/Right or Digimic1 */
1377 SND_SOC_DAPM_MUX_E("TX1 Capture Route", SND_SOC_NOPM, 0, 0, 1403 SND_SOC_DAPM_MUX("TX1 Capture Route", SND_SOC_NOPM, 0, 0,
1378 &twl4030_dapm_micpathtx1_control, micpath_event, 1404 &twl4030_dapm_micpathtx1_control),
1379 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD| 1405 SND_SOC_DAPM_MUX("TX2 Capture Route", SND_SOC_NOPM, 0, 0,
1380 SND_SOC_DAPM_POST_REG), 1406 &twl4030_dapm_micpathtx2_control),
1381 SND_SOC_DAPM_MUX_E("TX2 Capture Route", SND_SOC_NOPM, 0, 0,
1382 &twl4030_dapm_micpathtx2_control, micpath_event,
1383 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD|
1384 SND_SOC_DAPM_POST_REG),
1385 1407
1386 /* Analog input mixers for the capture amplifiers */ 1408 /* Analog input mixers for the capture amplifiers */
1387 SND_SOC_DAPM_MIXER("Analog Left", 1409 SND_SOC_DAPM_MIXER("Analog Left",
@@ -1398,10 +1420,17 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1398 SND_SOC_DAPM_PGA("ADC Physical Right", 1420 SND_SOC_DAPM_PGA("ADC Physical Right",
1399 TWL4030_REG_AVADC_CTL, 1, 0, NULL, 0), 1421 TWL4030_REG_AVADC_CTL, 1, 0, NULL, 0),
1400 1422
1401 SND_SOC_DAPM_PGA("Digimic0 Enable", 1423 SND_SOC_DAPM_PGA_E("Digimic0 Enable",
1402 TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0), 1424 TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0,
1403 SND_SOC_DAPM_PGA("Digimic1 Enable", 1425 digimic_event, SND_SOC_DAPM_POST_PMU),
1404 TWL4030_REG_ADCMICSEL, 3, 0, NULL, 0), 1426 SND_SOC_DAPM_PGA_E("Digimic1 Enable",
1427 TWL4030_REG_ADCMICSEL, 3, 0, NULL, 0,
1428 digimic_event, SND_SOC_DAPM_POST_PMU),
1429
1430 SND_SOC_DAPM_SUPPLY("micbias1 select", TWL4030_REG_MICBIAS_CTL, 5, 0,
1431 NULL, 0),
1432 SND_SOC_DAPM_SUPPLY("micbias2 select", TWL4030_REG_MICBIAS_CTL, 6, 0,
1433 NULL, 0),
1405 1434
1406 SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0), 1435 SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0),
1407 SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0), 1436 SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0),
@@ -1419,8 +1448,11 @@ static const struct snd_soc_dapm_route intercon[] = {
1419 /* Supply for the digital part (APLL) */ 1448 /* Supply for the digital part (APLL) */
1420 {"Digital Voice Playback Mixer", NULL, "APLL Enable"}, 1449 {"Digital Voice Playback Mixer", NULL, "APLL Enable"},
1421 1450
1422 {"Digital R1 Playback Mixer", NULL, "AIF Enable"}, 1451 {"DAC Left1", NULL, "AIF Enable"},
1423 {"Digital L1 Playback Mixer", NULL, "AIF Enable"}, 1452 {"DAC Right1", NULL, "AIF Enable"},
1453 {"DAC Left2", NULL, "AIF Enable"},
1454 {"DAC Right1", NULL, "AIF Enable"},
1455
1424 {"Digital R2 Playback Mixer", NULL, "AIF Enable"}, 1456 {"Digital R2 Playback Mixer", NULL, "AIF Enable"},
1425 {"Digital L2 Playback Mixer", NULL, "AIF Enable"}, 1457 {"Digital L2 Playback Mixer", NULL, "AIF Enable"},
1426 1458
@@ -1491,10 +1523,10 @@ static const struct snd_soc_dapm_route intercon[] = {
1491 1523
1492 /* outputs */ 1524 /* outputs */
1493 /* Must be always connected (for AIF and APLL) */ 1525 /* Must be always connected (for AIF and APLL) */
1494 {"Virtual HiFi OUT", NULL, "Digital L1 Playback Mixer"}, 1526 {"Virtual HiFi OUT", NULL, "DAC Left1"},
1495 {"Virtual HiFi OUT", NULL, "Digital R1 Playback Mixer"}, 1527 {"Virtual HiFi OUT", NULL, "DAC Right1"},
1496 {"Virtual HiFi OUT", NULL, "Digital L2 Playback Mixer"}, 1528 {"Virtual HiFi OUT", NULL, "DAC Left2"},
1497 {"Virtual HiFi OUT", NULL, "Digital R2 Playback Mixer"}, 1529 {"Virtual HiFi OUT", NULL, "DAC Right2"},
1498 /* Must be always connected (for APLL) */ 1530 /* Must be always connected (for APLL) */
1499 {"Virtual Voice OUT", NULL, "Digital Voice Playback Mixer"}, 1531 {"Virtual Voice OUT", NULL, "Digital Voice Playback Mixer"},
1500 /* Physical outputs */ 1532 /* Physical outputs */
@@ -1531,6 +1563,9 @@ static const struct snd_soc_dapm_route intercon[] = {
1531 {"Digimic0 Enable", NULL, "DIGIMIC0"}, 1563 {"Digimic0 Enable", NULL, "DIGIMIC0"},
1532 {"Digimic1 Enable", NULL, "DIGIMIC1"}, 1564 {"Digimic1 Enable", NULL, "DIGIMIC1"},
1533 1565
1566 {"DIGIMIC0", NULL, "micbias1 select"},
1567 {"DIGIMIC1", NULL, "micbias2 select"},
1568
1534 /* TX1 Left capture path */ 1569 /* TX1 Left capture path */
1535 {"TX1 Capture Route", "Analog", "ADC Physical Left"}, 1570 {"TX1 Capture Route", "Analog", "ADC Physical Left"},
1536 {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, 1571 {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"},
@@ -1605,10 +1640,10 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
1605 break; 1640 break;
1606 case SND_SOC_BIAS_STANDBY: 1641 case SND_SOC_BIAS_STANDBY:
1607 if (codec->bias_level == SND_SOC_BIAS_OFF) 1642 if (codec->bias_level == SND_SOC_BIAS_OFF)
1608 twl4030_power_up(codec); 1643 twl4030_codec_enable(codec, 1);
1609 break; 1644 break;
1610 case SND_SOC_BIAS_OFF: 1645 case SND_SOC_BIAS_OFF:
1611 twl4030_power_down(codec); 1646 twl4030_codec_enable(codec, 0);
1612 break; 1647 break;
1613 } 1648 }
1614 codec->bias_level = level; 1649 codec->bias_level = level;
@@ -1794,13 +1829,6 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1794 return -EINVAL; 1829 return -EINVAL;
1795 } 1830 }
1796 1831
1797 if (mode != old_mode) {
1798 /* change rate and set CODECPDZ */
1799 twl4030_codec_enable(codec, 0);
1800 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
1801 twl4030_codec_enable(codec, 1);
1802 }
1803
1804 /* sample size */ 1832 /* sample size */
1805 old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); 1833 old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1806 format = old_format; 1834 format = old_format;
@@ -1818,16 +1846,20 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1818 return -EINVAL; 1846 return -EINVAL;
1819 } 1847 }
1820 1848
1821 if (format != old_format) { 1849 if (format != old_format || mode != old_mode) {
1822 1850 if (twl4030->codec_powered) {
1823 /* clear CODECPDZ before changing format (codec requirement) */ 1851 /*
1824 twl4030_codec_enable(codec, 0); 1852 * If the codec is powered, than we need to toggle the
1825 1853 * codec power.
1826 /* change format */ 1854 */
1827 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); 1855 twl4030_codec_enable(codec, 0);
1828 1856 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
1829 /* set CODECPDZ afterwards */ 1857 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
1830 twl4030_codec_enable(codec, 1); 1858 twl4030_codec_enable(codec, 1);
1859 } else {
1860 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
1861 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
1862 }
1831 } 1863 }
1832 1864
1833 /* Store the important parameters for the DAI configuration and set 1865 /* Store the important parameters for the DAI configuration and set
@@ -1877,6 +1909,7 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1877 unsigned int fmt) 1909 unsigned int fmt)
1878{ 1910{
1879 struct snd_soc_codec *codec = codec_dai->codec; 1911 struct snd_soc_codec *codec = codec_dai->codec;
1912 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
1880 u8 old_format, format; 1913 u8 old_format, format;
1881 1914
1882 /* get format */ 1915 /* get format */
@@ -1911,15 +1944,17 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1911 } 1944 }
1912 1945
1913 if (format != old_format) { 1946 if (format != old_format) {
1914 1947 if (twl4030->codec_powered) {
1915 /* clear CODECPDZ before changing format (codec requirement) */ 1948 /*
1916 twl4030_codec_enable(codec, 0); 1949 * If the codec is powered, than we need to toggle the
1917 1950 * codec power.
1918 /* change format */ 1951 */
1919 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); 1952 twl4030_codec_enable(codec, 0);
1920 1953 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
1921 /* set CODECPDZ afterwards */ 1954 twl4030_codec_enable(codec, 1);
1922 twl4030_codec_enable(codec, 1); 1955 } else {
1956 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
1957 }
1923 } 1958 }
1924 1959
1925 return 0; 1960 return 0;
@@ -2011,6 +2046,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
2011 struct snd_soc_pcm_runtime *rtd = substream->private_data; 2046 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2012 struct snd_soc_device *socdev = rtd->socdev; 2047 struct snd_soc_device *socdev = rtd->socdev;
2013 struct snd_soc_codec *codec = socdev->card->codec; 2048 struct snd_soc_codec *codec = socdev->card->codec;
2049 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
2014 u8 old_mode, mode; 2050 u8 old_mode, mode;
2015 2051
2016 /* Enable voice digital filters */ 2052 /* Enable voice digital filters */
@@ -2035,10 +2071,17 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
2035 } 2071 }
2036 2072
2037 if (mode != old_mode) { 2073 if (mode != old_mode) {
2038 /* change rate and set CODECPDZ */ 2074 if (twl4030->codec_powered) {
2039 twl4030_codec_enable(codec, 0); 2075 /*
2040 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); 2076 * If the codec is powered, than we need to toggle the
2041 twl4030_codec_enable(codec, 1); 2077 * codec power.
2078 */
2079 twl4030_codec_enable(codec, 0);
2080 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
2081 twl4030_codec_enable(codec, 1);
2082 } else {
2083 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
2084 }
2042 } 2085 }
2043 2086
2044 return 0; 2087 return 0;
@@ -2068,6 +2111,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
2068 unsigned int fmt) 2111 unsigned int fmt)
2069{ 2112{
2070 struct snd_soc_codec *codec = codec_dai->codec; 2113 struct snd_soc_codec *codec = codec_dai->codec;
2114 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
2071 u8 old_format, format; 2115 u8 old_format, format;
2072 2116
2073 /* get format */ 2117 /* get format */
@@ -2099,10 +2143,17 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
2099 } 2143 }
2100 2144
2101 if (format != old_format) { 2145 if (format != old_format) {
2102 /* change format and set CODECPDZ */ 2146 if (twl4030->codec_powered) {
2103 twl4030_codec_enable(codec, 0); 2147 /*
2104 twl4030_write(codec, TWL4030_REG_VOICE_IF, format); 2148 * If the codec is powered, than we need to toggle the
2105 twl4030_codec_enable(codec, 1); 2149 * codec power.
2150 */
2151 twl4030_codec_enable(codec, 0);
2152 twl4030_write(codec, TWL4030_REG_VOICE_IF, format);
2153 twl4030_codec_enable(codec, 1);
2154 } else {
2155 twl4030_write(codec, TWL4030_REG_VOICE_IF, format);
2156 }
2106 } 2157 }
2107 2158
2108 return 0; 2159 return 0;
@@ -2202,31 +2253,15 @@ static struct snd_soc_codec *twl4030_codec;
2202static int twl4030_soc_probe(struct platform_device *pdev) 2253static int twl4030_soc_probe(struct platform_device *pdev)
2203{ 2254{
2204 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2255 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2205 struct twl4030_setup_data *setup = socdev->codec_data;
2206 struct snd_soc_codec *codec; 2256 struct snd_soc_codec *codec;
2207 struct twl4030_priv *twl4030;
2208 int ret; 2257 int ret;
2209 2258
2210 BUG_ON(!twl4030_codec); 2259 BUG_ON(!twl4030_codec);
2211 2260
2212 codec = twl4030_codec; 2261 codec = twl4030_codec;
2213 twl4030 = snd_soc_codec_get_drvdata(codec);
2214 socdev->card->codec = codec; 2262 socdev->card->codec = codec;
2215 2263
2216 /* Configuration for headset ramp delay from setup data */ 2264 twl4030_init_chip(pdev);
2217 if (setup) {
2218 unsigned char hs_pop;
2219
2220 if (setup->sysclk != twl4030->sysclk)
2221 dev_warn(&pdev->dev,
2222 "Mismatch in APLL mclk: %u (configured: %u)\n",
2223 setup->sysclk, twl4030->sysclk);
2224
2225 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
2226 hs_pop &= ~TWL4030_RAMP_DELAY;
2227 hs_pop |= (setup->ramp_delay_value << 2);
2228 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
2229 }
2230 2265
2231 /* register pcms */ 2266 /* register pcms */
2232 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 2267 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
@@ -2247,6 +2282,8 @@ static int twl4030_soc_remove(struct platform_device *pdev)
2247 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2282 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2248 struct snd_soc_codec *codec = socdev->card->codec; 2283 struct snd_soc_codec *codec = socdev->card->codec;
2249 2284
2285 /* Reset registers to their chip default before leaving */
2286 twl4030_reset_registers(codec);
2250 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); 2287 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
2251 snd_soc_free_pcms(socdev); 2288 snd_soc_free_pcms(socdev);
2252 snd_soc_dapm_free(socdev); 2289 snd_soc_dapm_free(socdev);
@@ -2287,6 +2324,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
2287 codec->read = twl4030_read_reg_cache; 2324 codec->read = twl4030_read_reg_cache;
2288 codec->write = twl4030_write; 2325 codec->write = twl4030_write;
2289 codec->set_bias_level = twl4030_set_bias_level; 2326 codec->set_bias_level = twl4030_set_bias_level;
2327 codec->idle_bias_off = 1;
2290 codec->dai = twl4030_dai; 2328 codec->dai = twl4030_dai;
2291 codec->num_dai = ARRAY_SIZE(twl4030_dai); 2329 codec->num_dai = ARRAY_SIZE(twl4030_dai);
2292 codec->reg_cache_size = sizeof(twl4030_reg); 2330 codec->reg_cache_size = sizeof(twl4030_reg);
@@ -2302,9 +2340,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
2302 2340
2303 /* Set the defaults, and power up the codec */ 2341 /* Set the defaults, and power up the codec */
2304 twl4030->sysclk = twl4030_codec_get_mclk() / 1000; 2342 twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
2305 twl4030_init_chip(codec);
2306 codec->bias_level = SND_SOC_BIAS_OFF; 2343 codec->bias_level = SND_SOC_BIAS_OFF;
2307 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2308 2344
2309 ret = snd_soc_register_codec(codec); 2345 ret = snd_soc_register_codec(codec);
2310 if (ret != 0) { 2346 if (ret != 0) {
@@ -2322,7 +2358,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
2322 return 0; 2358 return 0;
2323 2359
2324error_codec: 2360error_codec:
2325 twl4030_power_down(codec); 2361 twl4030_codec_enable(codec, 0);
2326 kfree(codec->reg_cache); 2362 kfree(codec->reg_cache);
2327error_cache: 2363error_cache:
2328 kfree(twl4030); 2364 kfree(twl4030);
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index f206d242ca31..6c57430f6e24 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -41,7 +41,11 @@ extern struct snd_soc_codec_device soc_codec_dev_twl4030;
41 41
42struct twl4030_setup_data { 42struct twl4030_setup_data {
43 unsigned int ramp_delay_value; 43 unsigned int ramp_delay_value;
44 unsigned int digimic_delay; /* in ms */
44 unsigned int sysclk; 45 unsigned int sysclk;
46 unsigned int offset_cncl_path;
47 unsigned int check_defaults:1;
48 unsigned int reset_registers:1;
45 unsigned int hs_extmute:1; 49 unsigned int hs_extmute:1;
46 void (*set_hs_extmute)(int mute); 50 void (*set_hs_extmute)(int mute);
47}; 51};
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index af36346ff336..64a807f1a8a1 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -360,6 +360,13 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
360 return 0; 360 return 0;
361} 361}
362 362
363static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
364 struct snd_kcontrol *kcontrol, int event)
365{
366 msleep(1);
367 return 0;
368}
369
363static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w, 370static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
364 struct snd_kcontrol *kcontrol, int event) 371 struct snd_kcontrol *kcontrol, int event)
365{ 372{
@@ -371,6 +378,8 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
371 else 378 else
372 priv->non_lp--; 379 priv->non_lp--;
373 380
381 msleep(1);
382
374 return 0; 383 return 0;
375} 384}
376 385
@@ -471,20 +480,6 @@ static const struct snd_kcontrol_new hfdacl_switch_controls =
471static const struct snd_kcontrol_new hfdacr_switch_controls = 480static const struct snd_kcontrol_new hfdacr_switch_controls =
472 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 2, 1, 0); 481 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 2, 1, 0);
473 482
474/* Headset driver switches */
475static const struct snd_kcontrol_new hsl_driver_switch_controls =
476 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 2, 1, 0);
477
478static const struct snd_kcontrol_new hsr_driver_switch_controls =
479 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 2, 1, 0);
480
481/* Handsfree driver switches */
482static const struct snd_kcontrol_new hfl_driver_switch_controls =
483 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 4, 1, 0);
484
485static const struct snd_kcontrol_new hfr_driver_switch_controls =
486 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 4, 1, 0);
487
488static const struct snd_kcontrol_new ep_driver_switch_controls = 483static const struct snd_kcontrol_new ep_driver_switch_controls =
489 SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0); 484 SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
490 485
@@ -548,10 +543,14 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
548 TWL6040_REG_DMICBCTL, 4, 0), 543 TWL6040_REG_DMICBCTL, 4, 0),
549 544
550 /* DACs */ 545 /* DACs */
551 SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", 546 SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback",
552 TWL6040_REG_HSLCTL, 0, 0), 547 TWL6040_REG_HSLCTL, 0, 0,
553 SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", 548 twl6040_hs_dac_event,
554 TWL6040_REG_HSRCTL, 0, 0), 549 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
550 SND_SOC_DAPM_DAC_E("HSDAC Right", "Headset Playback",
551 TWL6040_REG_HSRCTL, 0, 0,
552 twl6040_hs_dac_event,
553 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
555 SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback", 554 SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
556 TWL6040_REG_HFLCTL, 0, 0, 555 TWL6040_REG_HFLCTL, 0, 0,
557 twl6040_power_mode_event, 556 twl6040_power_mode_event,
@@ -571,18 +570,19 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
571 SND_SOC_DAPM_SWITCH("HFDAC Right Playback", 570 SND_SOC_DAPM_SWITCH("HFDAC Right Playback",
572 SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls), 571 SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls),
573 572
574 SND_SOC_DAPM_SWITCH("Headset Left Driver", 573 /* Analog playback drivers */
575 SND_SOC_NOPM, 0, 0, &hsl_driver_switch_controls), 574 SND_SOC_DAPM_PGA_E("Handsfree Left Driver",
576 SND_SOC_DAPM_SWITCH("Headset Right Driver", 575 TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
577 SND_SOC_NOPM, 0, 0, &hsr_driver_switch_controls),
578 SND_SOC_DAPM_SWITCH_E("Handsfree Left Driver",
579 SND_SOC_NOPM, 0, 0, &hfl_driver_switch_controls,
580 twl6040_power_mode_event, 576 twl6040_power_mode_event,
581 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 577 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
582 SND_SOC_DAPM_SWITCH_E("Handsfree Right Driver", 578 SND_SOC_DAPM_PGA_E("Handsfree Right Driver",
583 SND_SOC_NOPM, 0, 0, &hfr_driver_switch_controls, 579 TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
584 twl6040_power_mode_event, 580 twl6040_power_mode_event,
585 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 581 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
582 SND_SOC_DAPM_PGA("Headset Left Driver",
583 TWL6040_REG_HSLCTL, 2, 0, NULL, 0),
584 SND_SOC_DAPM_PGA("Headset Right Driver",
585 TWL6040_REG_HSRCTL, 2, 0, NULL, 0),
586 SND_SOC_DAPM_SWITCH_E("Earphone Driver", 586 SND_SOC_DAPM_SWITCH_E("Earphone Driver",
587 SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls, 587 SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
588 twl6040_power_mode_event, 588 twl6040_power_mode_event,
@@ -616,8 +616,8 @@ static const struct snd_soc_dapm_route intercon[] = {
616 {"HSDAC Left Playback", "Switch", "HSDAC Left"}, 616 {"HSDAC Left Playback", "Switch", "HSDAC Left"},
617 {"HSDAC Right Playback", "Switch", "HSDAC Right"}, 617 {"HSDAC Right Playback", "Switch", "HSDAC Right"},
618 618
619 {"Headset Left Driver", "Switch", "HSDAC Left Playback"}, 619 {"Headset Left Driver", NULL, "HSDAC Left Playback"},
620 {"Headset Right Driver", "Switch", "HSDAC Right Playback"}, 620 {"Headset Right Driver", NULL, "HSDAC Right Playback"},
621 621
622 {"HSOL", NULL, "Headset Left Driver"}, 622 {"HSOL", NULL, "Headset Left Driver"},
623 {"HSOR", NULL, "Headset Right Driver"}, 623 {"HSOR", NULL, "Headset Right Driver"},
@@ -928,7 +928,7 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
928 case 19200000: 928 case 19200000:
929 /* mclk input, pll disabled */ 929 /* mclk input, pll disabled */
930 hppllctl |= TWL6040_MCLK_19200KHZ | 930 hppllctl |= TWL6040_MCLK_19200KHZ |
931 TWL6040_HPLLSQRBP | 931 TWL6040_HPLLSQRENA |
932 TWL6040_HPLLBP; 932 TWL6040_HPLLBP;
933 break; 933 break;
934 case 26000000: 934 case 26000000:
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 28aac53c97bb..f3b4c1d6a82d 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -28,19 +28,6 @@
28#include "uda134x.h" 28#include "uda134x.h"
29 29
30 30
31#define POWER_OFF_ON_STANDBY 1
32/*
33 ALSA SOC usually puts the device in standby mode when it's not used
34 for sometime. If you define POWER_OFF_ON_STANDBY the driver will
35 turn off the ADC/DAC when this callback is invoked and turn it back
36 on when needed. Unfortunately this will result in a very light bump
37 (it can be audible only with good earphones). If this bothers you
38 just comment this line, you will have slightly higher power
39 consumption . Please note that sending the L3 command for ADC is
40 enough to make the bump, so it doesn't make difference if you
41 completely take off power from the codec.
42 */
43
44#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000 31#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
45#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ 32#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
46 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE) 33 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
@@ -58,7 +45,7 @@ static const char uda134x_reg[UDA134X_REGS_NUM] = {
58 /* Extended address registers */ 45 /* Extended address registers */
59 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 46 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
60 /* Status, data regs */ 47 /* Status, data regs */
61 0x00, 0x83, 0x00, 0x40, 0x80, 0x00, 48 0x00, 0x83, 0x00, 0x40, 0x80, 0xC0, 0x00,
62}; 49};
63 50
64/* 51/*
@@ -117,6 +104,7 @@ static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
117 case UDA134X_DATA000: 104 case UDA134X_DATA000:
118 case UDA134X_DATA001: 105 case UDA134X_DATA001:
119 case UDA134X_DATA010: 106 case UDA134X_DATA010:
107 case UDA134X_DATA011:
120 addr = UDA134X_DATA0_ADDR; 108 addr = UDA134X_DATA0_ADDR;
121 break; 109 break;
122 case UDA134X_DATA1: 110 case UDA134X_DATA1:
@@ -353,8 +341,22 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
353 switch (level) { 341 switch (level) {
354 case SND_SOC_BIAS_ON: 342 case SND_SOC_BIAS_ON:
355 /* ADC, DAC on */ 343 /* ADC, DAC on */
356 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); 344 switch (pd->model) {
357 uda134x_write(codec, UDA134X_STATUS1, reg | 0x03); 345 case UDA134X_UDA1340:
346 case UDA134X_UDA1344:
347 case UDA134X_UDA1345:
348 reg = uda134x_read_reg_cache(codec, UDA134X_DATA011);
349 uda134x_write(codec, UDA134X_DATA011, reg | 0x03);
350 break;
351 case UDA134X_UDA1341:
352 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
353 uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
354 break;
355 default:
356 printk(KERN_ERR "UDA134X SoC codec: "
357 "unsupported model %d\n", pd->model);
358 return -EINVAL;
359 }
358 break; 360 break;
359 case SND_SOC_BIAS_PREPARE: 361 case SND_SOC_BIAS_PREPARE:
360 /* power on */ 362 /* power on */
@@ -367,8 +369,22 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
367 break; 369 break;
368 case SND_SOC_BIAS_STANDBY: 370 case SND_SOC_BIAS_STANDBY:
369 /* ADC, DAC power off */ 371 /* ADC, DAC power off */
370 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); 372 switch (pd->model) {
371 uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03)); 373 case UDA134X_UDA1340:
374 case UDA134X_UDA1344:
375 case UDA134X_UDA1345:
376 reg = uda134x_read_reg_cache(codec, UDA134X_DATA011);
377 uda134x_write(codec, UDA134X_DATA011, reg & ~(0x03));
378 break;
379 case UDA134X_UDA1341:
380 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
381 uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
382 break;
383 default:
384 printk(KERN_ERR "UDA134X SoC codec: "
385 "unsupported model %d\n", pd->model);
386 return -EINVAL;
387 }
372 break; 388 break;
373 case SND_SOC_BIAS_OFF: 389 case SND_SOC_BIAS_OFF:
374 /* power off */ 390 /* power off */
@@ -531,9 +547,7 @@ static int uda134x_soc_probe(struct platform_device *pdev)
531 codec->num_dai = 1; 547 codec->num_dai = 1;
532 codec->read = uda134x_read_reg_cache; 548 codec->read = uda134x_read_reg_cache;
533 codec->write = uda134x_write; 549 codec->write = uda134x_write;
534#ifdef POWER_OFF_ON_STANDBY 550
535 codec->set_bias_level = uda134x_set_bias_level;
536#endif
537 INIT_LIST_HEAD(&codec->dapm_widgets); 551 INIT_LIST_HEAD(&codec->dapm_widgets);
538 INIT_LIST_HEAD(&codec->dapm_paths); 552 INIT_LIST_HEAD(&codec->dapm_paths);
539 553
@@ -544,6 +558,14 @@ static int uda134x_soc_probe(struct platform_device *pdev)
544 558
545 uda134x_reset(codec); 559 uda134x_reset(codec);
546 560
561 if (pd->is_powered_on_standby) {
562 codec->set_bias_level = NULL;
563 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
564 } else {
565 codec->set_bias_level = uda134x_set_bias_level;
566 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
567 }
568
547 /* register pcms */ 569 /* register pcms */
548 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 570 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
549 if (ret < 0) { 571 if (ret < 0) {
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h
index 94f440490b31..205f03b3eaf8 100644
--- a/sound/soc/codecs/uda134x.h
+++ b/sound/soc/codecs/uda134x.h
@@ -23,9 +23,10 @@
23#define UDA134X_DATA000 10 23#define UDA134X_DATA000 10
24#define UDA134X_DATA001 11 24#define UDA134X_DATA001 11
25#define UDA134X_DATA010 12 25#define UDA134X_DATA010 12
26#define UDA134X_DATA1 13 26#define UDA134X_DATA011 13
27#define UDA134X_DATA1 14
27 28
28#define UDA134X_REGS_NUM 14 29#define UDA134X_REGS_NUM 15
29 30
30#define STATUS0_DAIFMT_MASK (~(7<<1)) 31#define STATUS0_DAIFMT_MASK (~(7<<1))
31#define STATUS0_SYSCLK_MASK (~(3<<4)) 32#define STATUS0_SYSCLK_MASK (~(3<<4))
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 002e289d1255..4bcd168794e1 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -795,6 +795,8 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
795 795
796 dev_set_drvdata(&i2c->dev, wm2000); 796 dev_set_drvdata(&i2c->dev, wm2000);
797 wm2000->anc_eng_ena = 1; 797 wm2000->anc_eng_ena = 1;
798 wm2000->anc_active = 1;
799 wm2000->spk_ena = 1;
798 wm2000->i2c = i2c; 800 wm2000->i2c = i2c;
799 801
800 wm2000_reset(wm2000); 802 wm2000_reset(wm2000);
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 37242a7d3077..0ad039b4adf5 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -482,7 +482,8 @@ static int wm8523_register(struct wm8523_priv *wm8523,
482 482
483 if (wm8523_codec) { 483 if (wm8523_codec) {
484 dev_err(codec->dev, "Another WM8523 is registered\n"); 484 dev_err(codec->dev, "Another WM8523 is registered\n");
485 return -EINVAL; 485 ret = -EINVAL;
486 goto err;
486 } 487 }
487 488
488 mutex_init(&codec->mutex); 489 mutex_init(&codec->mutex);
@@ -570,18 +571,19 @@ static int wm8523_register(struct wm8523_priv *wm8523,
570 ret = snd_soc_register_codec(codec); 571 ret = snd_soc_register_codec(codec);
571 if (ret != 0) { 572 if (ret != 0) {
572 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 573 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
573 return ret; 574 goto err_enable;
574 } 575 }
575 576
576 ret = snd_soc_register_dai(&wm8523_dai); 577 ret = snd_soc_register_dai(&wm8523_dai);
577 if (ret != 0) { 578 if (ret != 0) {
578 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 579 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
579 snd_soc_unregister_codec(codec); 580 goto err_codec;
580 return ret;
581 } 581 }
582 582
583 return 0; 583 return 0;
584 584
585err_codec:
586 snd_soc_unregister_codec(codec);
585err_enable: 587err_enable:
586 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 588 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
587err_get: 589err_get:
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index effb14eee7d4..e2dba07f0260 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -439,7 +439,8 @@ static int wm8711_register(struct wm8711_priv *wm8711,
439 439
440 if (wm8711_codec) { 440 if (wm8711_codec) {
441 dev_err(codec->dev, "Another WM8711 is registered\n"); 441 dev_err(codec->dev, "Another WM8711 is registered\n");
442 return -EINVAL; 442 ret = -EINVAL;
443 goto err;
443 } 444 }
444 445
445 mutex_init(&codec->mutex); 446 mutex_init(&codec->mutex);
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
new file mode 100644
index 000000000000..b9ea8904ad4b
--- /dev/null
+++ b/sound/soc/codecs/wm8741.c
@@ -0,0 +1,579 @@
1/*
2 * wm8741.c -- WM8741 ALSA SoC Audio driver
3 *
4 * Copyright 2010 Wolfson Microelectronics plc
5 *
6 * Author: Ian Lartey <ian@opensource.wolfsonmicro.com>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/pm.h>
19#include <linux/i2c.h>
20#include <linux/platform_device.h>
21#include <linux/regulator/consumer.h>
22#include <linux/slab.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29#include <sound/tlv.h>
30
31#include "wm8741.h"
32
33static struct snd_soc_codec *wm8741_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8741;
35
36#define WM8741_NUM_SUPPLIES 2
37static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
38 "AVDD",
39 "DVDD",
40};
41
42#define WM8741_NUM_RATES 4
43
44/* codec private data */
45struct wm8741_priv {
46 struct snd_soc_codec codec;
47 u16 reg_cache[WM8741_REGISTER_COUNT];
48 struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
49 unsigned int sysclk;
50 unsigned int rate_constraint_list[WM8741_NUM_RATES];
51 struct snd_pcm_hw_constraint_list rate_constraint;
52};
53
54static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = {
55 0x0000, /* R0 - DACLLSB Attenuation */
56 0x0000, /* R1 - DACLMSB Attenuation */
57 0x0000, /* R2 - DACRLSB Attenuation */
58 0x0000, /* R3 - DACRMSB Attenuation */
59 0x0000, /* R4 - Volume Control */
60 0x000A, /* R5 - Format Control */
61 0x0000, /* R6 - Filter Control */
62 0x0000, /* R7 - Mode Control 1 */
63 0x0002, /* R8 - Mode Control 2 */
64 0x0000, /* R9 - Reset */
65 0x0002, /* R32 - ADDITONAL_CONTROL_1 */
66};
67
68
69static int wm8741_reset(struct snd_soc_codec *codec)
70{
71 return snd_soc_write(codec, WM8741_RESET, 0);
72}
73
74static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, -12700, 13, 0);
75static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 400, 0);
76
77static const struct snd_kcontrol_new wm8741_snd_controls[] = {
78SOC_DOUBLE_R_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
79 WM8741_DACRLSB_ATTENUATION, 1, 255, 1, dac_tlv_fine),
80SOC_DOUBLE_R_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION,
81 WM8741_DACRMSB_ATTENUATION, 0, 511, 1, dac_tlv),
82};
83
84static const struct snd_soc_dapm_widget wm8741_dapm_widgets[] = {
85SND_SOC_DAPM_DAC("DACL", "Playback", SND_SOC_NOPM, 0, 0),
86SND_SOC_DAPM_DAC("DACR", "Playback", SND_SOC_NOPM, 0, 0),
87SND_SOC_DAPM_OUTPUT("VOUTLP"),
88SND_SOC_DAPM_OUTPUT("VOUTLN"),
89SND_SOC_DAPM_OUTPUT("VOUTRP"),
90SND_SOC_DAPM_OUTPUT("VOUTRN"),
91};
92
93static const struct snd_soc_dapm_route intercon[] = {
94 { "VOUTLP", NULL, "DACL" },
95 { "VOUTLN", NULL, "DACL" },
96 { "VOUTRP", NULL, "DACR" },
97 { "VOUTRN", NULL, "DACR" },
98};
99
100static int wm8741_add_widgets(struct snd_soc_codec *codec)
101{
102 snd_soc_dapm_new_controls(codec, wm8741_dapm_widgets,
103 ARRAY_SIZE(wm8741_dapm_widgets));
104
105 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
106
107 return 0;
108}
109
110static struct {
111 int value;
112 int ratio;
113} lrclk_ratios[WM8741_NUM_RATES] = {
114 { 1, 256 },
115 { 2, 384 },
116 { 3, 512 },
117 { 4, 768 },
118};
119
120
121static int wm8741_startup(struct snd_pcm_substream *substream,
122 struct snd_soc_dai *dai)
123{
124 struct snd_soc_codec *codec = dai->codec;
125 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
126
127 /* The set of sample rates that can be supported depends on the
128 * MCLK supplied to the CODEC - enforce this.
129 */
130 if (!wm8741->sysclk) {
131 dev_err(codec->dev,
132 "No MCLK configured, call set_sysclk() on init\n");
133 return -EINVAL;
134 }
135
136 snd_pcm_hw_constraint_list(substream->runtime, 0,
137 SNDRV_PCM_HW_PARAM_RATE,
138 &wm8741->rate_constraint);
139
140 return 0;
141}
142
143static int wm8741_hw_params(struct snd_pcm_substream *substream,
144 struct snd_pcm_hw_params *params,
145 struct snd_soc_dai *dai)
146{
147 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct snd_soc_device *socdev = rtd->socdev;
149 struct snd_soc_codec *codec = socdev->card->codec;
150 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
151 u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
152 int i;
153
154 /* Find a supported LRCLK ratio */
155 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
156 if (wm8741->sysclk / params_rate(params) ==
157 lrclk_ratios[i].ratio)
158 break;
159 }
160
161 /* Should never happen, should be handled by constraints */
162 if (i == ARRAY_SIZE(lrclk_ratios)) {
163 dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n",
164 wm8741->sysclk / params_rate(params));
165 return -EINVAL;
166 }
167
168 /* bit size */
169 switch (params_format(params)) {
170 case SNDRV_PCM_FORMAT_S16_LE:
171 break;
172 case SNDRV_PCM_FORMAT_S20_3LE:
173 iface |= 0x0001;
174 break;
175 case SNDRV_PCM_FORMAT_S24_LE:
176 iface |= 0x0002;
177 break;
178 case SNDRV_PCM_FORMAT_S32_LE:
179 iface |= 0x0003;
180 break;
181 default:
182 dev_dbg(codec->dev, "wm8741_hw_params: Unsupported bit size param = %d",
183 params_format(params));
184 return -EINVAL;
185 }
186
187 dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d",
188 params_format(params));
189
190 snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface);
191 return 0;
192}
193
194static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
195 int clk_id, unsigned int freq, int dir)
196{
197 struct snd_soc_codec *codec = codec_dai->codec;
198 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
199 unsigned int val;
200 int i;
201
202 dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq);
203
204 wm8741->sysclk = freq;
205
206 wm8741->rate_constraint.count = 0;
207
208 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
209 dev_dbg(codec->dev, "index = %d, ratio = %d, freq = %d",
210 i, lrclk_ratios[i].ratio, freq);
211
212 val = freq / lrclk_ratios[i].ratio;
213 /* Check that it's a standard rate since core can't
214 * cope with others and having the odd rates confuses
215 * constraint matching.
216 */
217 switch (val) {
218 case 32000:
219 case 44100:
220 case 48000:
221 case 64000:
222 case 88200:
223 case 96000:
224 dev_dbg(codec->dev, "Supported sample rate: %dHz\n",
225 val);
226 wm8741->rate_constraint_list[i] = val;
227 wm8741->rate_constraint.count++;
228 break;
229 default:
230 dev_dbg(codec->dev, "Skipping sample rate: %dHz\n",
231 val);
232 }
233 }
234
235 /* Need at least one supported rate... */
236 if (wm8741->rate_constraint.count == 0)
237 return -EINVAL;
238
239 return 0;
240}
241
242static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
243 unsigned int fmt)
244{
245 struct snd_soc_codec *codec = codec_dai->codec;
246 u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1C3;
247
248 /* check master/slave audio interface */
249 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
250 case SND_SOC_DAIFMT_CBS_CFS:
251 break;
252 default:
253 return -EINVAL;
254 }
255
256 /* interface format */
257 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
258 case SND_SOC_DAIFMT_I2S:
259 iface |= 0x0008;
260 break;
261 case SND_SOC_DAIFMT_RIGHT_J:
262 break;
263 case SND_SOC_DAIFMT_LEFT_J:
264 iface |= 0x0004;
265 break;
266 case SND_SOC_DAIFMT_DSP_A:
267 iface |= 0x0003;
268 break;
269 case SND_SOC_DAIFMT_DSP_B:
270 iface |= 0x0013;
271 break;
272 default:
273 return -EINVAL;
274 }
275
276 /* clock inversion */
277 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
278 case SND_SOC_DAIFMT_NB_NF:
279 break;
280 case SND_SOC_DAIFMT_IB_IF:
281 iface |= 0x0010;
282 break;
283 case SND_SOC_DAIFMT_IB_NF:
284 iface |= 0x0020;
285 break;
286 case SND_SOC_DAIFMT_NB_IF:
287 iface |= 0x0030;
288 break;
289 default:
290 return -EINVAL;
291 }
292
293
294 dev_dbg(codec->dev, "wm8741_set_dai_fmt: Format=%x, Clock Inv=%x\n",
295 fmt & SND_SOC_DAIFMT_FORMAT_MASK,
296 ((fmt & SND_SOC_DAIFMT_INV_MASK)));
297
298 snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface);
299 return 0;
300}
301
302#define WM8741_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
303 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
304 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
305 SNDRV_PCM_RATE_192000)
306
307#define WM8741_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
308 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
309
310static struct snd_soc_dai_ops wm8741_dai_ops = {
311 .startup = wm8741_startup,
312 .hw_params = wm8741_hw_params,
313 .set_sysclk = wm8741_set_dai_sysclk,
314 .set_fmt = wm8741_set_dai_fmt,
315};
316
317struct snd_soc_dai wm8741_dai = {
318 .name = "WM8741",
319 .playback = {
320 .stream_name = "Playback",
321 .channels_min = 2, /* Mono modes not yet supported */
322 .channels_max = 2,
323 .rates = WM8741_RATES,
324 .formats = WM8741_FORMATS,
325 },
326 .ops = &wm8741_dai_ops,
327};
328EXPORT_SYMBOL_GPL(wm8741_dai);
329
330#ifdef CONFIG_PM
331static int wm8741_resume(struct platform_device *pdev)
332{
333 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
334 struct snd_soc_codec *codec = socdev->card->codec;
335 u16 *cache = codec->reg_cache;
336 int i;
337
338 /* RESTORE REG Cache */
339 for (i = 0; i < WM8741_REGISTER_COUNT; i++) {
340 if (cache[i] == wm8741_reg_defaults[i] || WM8741_RESET == i)
341 continue;
342 snd_soc_write(codec, i, cache[i]);
343 }
344 return 0;
345}
346#else
347#define wm8741_suspend NULL
348#define wm8741_resume NULL
349#endif
350
351static int wm8741_probe(struct platform_device *pdev)
352{
353 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
354 struct snd_soc_codec *codec;
355 int ret = 0;
356
357 if (wm8741_codec == NULL) {
358 dev_err(&pdev->dev, "Codec device not registered\n");
359 return -ENODEV;
360 }
361
362 socdev->card->codec = wm8741_codec;
363 codec = wm8741_codec;
364
365 /* register pcms */
366 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
367 if (ret < 0) {
368 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
369 goto pcm_err;
370 }
371
372 snd_soc_add_controls(codec, wm8741_snd_controls,
373 ARRAY_SIZE(wm8741_snd_controls));
374 wm8741_add_widgets(codec);
375
376 return ret;
377
378pcm_err:
379 return ret;
380}
381
382static int wm8741_remove(struct platform_device *pdev)
383{
384 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
385
386 snd_soc_free_pcms(socdev);
387 snd_soc_dapm_free(socdev);
388
389 return 0;
390}
391
392struct snd_soc_codec_device soc_codec_dev_wm8741 = {
393 .probe = wm8741_probe,
394 .remove = wm8741_remove,
395 .resume = wm8741_resume,
396};
397EXPORT_SYMBOL_GPL(soc_codec_dev_wm8741);
398
399static int wm8741_register(struct wm8741_priv *wm8741,
400 enum snd_soc_control_type control)
401{
402 int ret;
403 struct snd_soc_codec *codec = &wm8741->codec;
404 int i;
405
406 if (wm8741_codec) {
407 dev_err(codec->dev, "Another WM8741 is registered\n");
408 return -EINVAL;
409 }
410
411 mutex_init(&codec->mutex);
412 INIT_LIST_HEAD(&codec->dapm_widgets);
413 INIT_LIST_HEAD(&codec->dapm_paths);
414
415 snd_soc_codec_set_drvdata(codec, wm8741);
416 codec->name = "WM8741";
417 codec->owner = THIS_MODULE;
418 codec->bias_level = SND_SOC_BIAS_OFF;
419 codec->set_bias_level = NULL;
420 codec->dai = &wm8741_dai;
421 codec->num_dai = 1;
422 codec->reg_cache_size = WM8741_REGISTER_COUNT;
423 codec->reg_cache = &wm8741->reg_cache;
424
425 wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0];
426 wm8741->rate_constraint.count =
427 ARRAY_SIZE(wm8741->rate_constraint_list);
428
429 memcpy(codec->reg_cache, wm8741_reg_defaults,
430 sizeof(wm8741->reg_cache));
431
432 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
433 if (ret != 0) {
434 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
435 goto err;
436 }
437
438 for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
439 wm8741->supplies[i].supply = wm8741_supply_names[i];
440
441 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies),
442 wm8741->supplies);
443 if (ret != 0) {
444 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
445 goto err;
446 }
447
448 ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
449 wm8741->supplies);
450 if (ret != 0) {
451 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
452 goto err_get;
453 }
454
455 ret = wm8741_reset(codec);
456 if (ret < 0) {
457 dev_err(codec->dev, "Failed to issue reset\n");
458 goto err_enable;
459 }
460
461 wm8741_dai.dev = codec->dev;
462
463 /* Change some default settings - latch VU */
464 wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
465 wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
466 wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
467 wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
468
469 wm8741_codec = codec;
470
471 ret = snd_soc_register_codec(codec);
472 if (ret != 0) {
473 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
474 return ret;
475 }
476
477 ret = snd_soc_register_dai(&wm8741_dai);
478 if (ret != 0) {
479 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
480 snd_soc_unregister_codec(codec);
481 return ret;
482 }
483
484 dev_dbg(codec->dev, "Successful registration\n");
485 return 0;
486
487err_enable:
488 regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
489
490err_get:
491 regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
492
493err:
494 kfree(wm8741);
495 return ret;
496}
497
498static void wm8741_unregister(struct wm8741_priv *wm8741)
499{
500 regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
501
502 snd_soc_unregister_dai(&wm8741_dai);
503 snd_soc_unregister_codec(&wm8741->codec);
504 kfree(wm8741);
505 wm8741_codec = NULL;
506}
507
508#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
509static __devinit int wm8741_i2c_probe(struct i2c_client *i2c,
510 const struct i2c_device_id *id)
511{
512 struct wm8741_priv *wm8741;
513 struct snd_soc_codec *codec;
514
515 wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
516 if (wm8741 == NULL)
517 return -ENOMEM;
518
519 codec = &wm8741->codec;
520 codec->hw_write = (hw_write_t)i2c_master_send;
521
522 i2c_set_clientdata(i2c, wm8741);
523 codec->control_data = i2c;
524
525 codec->dev = &i2c->dev;
526
527 return wm8741_register(wm8741, SND_SOC_I2C);
528}
529
530static __devexit int wm8741_i2c_remove(struct i2c_client *client)
531{
532 struct wm8741_priv *wm8741 = i2c_get_clientdata(client);
533 wm8741_unregister(wm8741);
534 return 0;
535}
536
537static const struct i2c_device_id wm8741_i2c_id[] = {
538 { "wm8741", 0 },
539 { }
540};
541MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
542
543
544static struct i2c_driver wm8741_i2c_driver = {
545 .driver = {
546 .name = "WM8741",
547 .owner = THIS_MODULE,
548 },
549 .probe = wm8741_i2c_probe,
550 .remove = __devexit_p(wm8741_i2c_remove),
551 .id_table = wm8741_i2c_id,
552};
553#endif
554
555static int __init wm8741_modinit(void)
556{
557 int ret;
558#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
559 ret = i2c_add_driver(&wm8741_i2c_driver);
560 if (ret != 0) {
561 printk(KERN_ERR "Failed to register WM8741 I2C driver: %d\n",
562 ret);
563 }
564#endif
565 return 0;
566}
567module_init(wm8741_modinit);
568
569static void __exit wm8741_exit(void)
570{
571#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
572 i2c_del_driver(&wm8741_i2c_driver);
573#endif
574}
575module_exit(wm8741_exit);
576
577MODULE_DESCRIPTION("ASoC WM8741 driver");
578MODULE_AUTHOR("Ian Lartey <ian@opensource.wolfsonmicro.com>");
579MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8741.h b/sound/soc/codecs/wm8741.h
new file mode 100644
index 000000000000..fdef6ecd1f6f
--- /dev/null
+++ b/sound/soc/codecs/wm8741.h
@@ -0,0 +1,214 @@
1/*
2 * wm8741.h -- WM8423 ASoC driver
3 *
4 * Copyright 2010 Wolfson Microelectronics, plc
5 *
6 * Author: Ian Lartey <ian@opensource.wolfsonmicro.com>
7 *
8 * Based on wm8753.h
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef _WM8741_H
16#define _WM8741_H
17
18/*
19 * Register values.
20 */
21#define WM8741_DACLLSB_ATTENUATION 0x00
22#define WM8741_DACLMSB_ATTENUATION 0x01
23#define WM8741_DACRLSB_ATTENUATION 0x02
24#define WM8741_DACRMSB_ATTENUATION 0x03
25#define WM8741_VOLUME_CONTROL 0x04
26#define WM8741_FORMAT_CONTROL 0x05
27#define WM8741_FILTER_CONTROL 0x06
28#define WM8741_MODE_CONTROL_1 0x07
29#define WM8741_MODE_CONTROL_2 0x08
30#define WM8741_RESET 0x09
31#define WM8741_ADDITIONAL_CONTROL_1 0x20
32
33#define WM8741_REGISTER_COUNT 11
34#define WM8741_MAX_REGISTER 0x20
35
36/*
37 * Field Definitions.
38 */
39
40/*
41 * R0 (0x00) - DACLLSB_ATTENUATION
42 */
43#define WM8741_UPDATELL 0x0020 /* UPDATELL */
44#define WM8741_UPDATELL_MASK 0x0020 /* UPDATELL */
45#define WM8741_UPDATELL_SHIFT 5 /* UPDATELL */
46#define WM8741_UPDATELL_WIDTH 1 /* UPDATELL */
47#define WM8741_LAT_4_0_MASK 0x001F /* LAT[4:0] - [4:0] */
48#define WM8741_LAT_4_0_SHIFT 0 /* LAT[4:0] - [4:0] */
49#define WM8741_LAT_4_0_WIDTH 5 /* LAT[4:0] - [4:0] */
50
51/*
52 * R1 (0x01) - DACLMSB_ATTENUATION
53 */
54#define WM8741_UPDATELM 0x0020 /* UPDATELM */
55#define WM8741_UPDATELM_MASK 0x0020 /* UPDATELM */
56#define WM8741_UPDATELM_SHIFT 5 /* UPDATELM */
57#define WM8741_UPDATELM_WIDTH 1 /* UPDATELM */
58#define WM8741_LAT_9_5_0_MASK 0x001F /* LAT[9:5] - [4:0] */
59#define WM8741_LAT_9_5_0_SHIFT 0 /* LAT[9:5] - [4:0] */
60#define WM8741_LAT_9_5_0_WIDTH 5 /* LAT[9:5] - [4:0] */
61
62/*
63 * R2 (0x02) - DACRLSB_ATTENUATION
64 */
65#define WM8741_UPDATERL 0x0020 /* UPDATERL */
66#define WM8741_UPDATERL_MASK 0x0020 /* UPDATERL */
67#define WM8741_UPDATERL_SHIFT 5 /* UPDATERL */
68#define WM8741_UPDATERL_WIDTH 1 /* UPDATERL */
69#define WM8741_RAT_4_0_MASK 0x001F /* RAT[4:0] - [4:0] */
70#define WM8741_RAT_4_0_SHIFT 0 /* RAT[4:0] - [4:0] */
71#define WM8741_RAT_4_0_WIDTH 5 /* RAT[4:0] - [4:0] */
72
73/*
74 * R3 (0x03) - DACRMSB_ATTENUATION
75 */
76#define WM8741_UPDATERM 0x0020 /* UPDATERM */
77#define WM8741_UPDATERM_MASK 0x0020 /* UPDATERM */
78#define WM8741_UPDATERM_SHIFT 5 /* UPDATERM */
79#define WM8741_UPDATERM_WIDTH 1 /* UPDATERM */
80#define WM8741_RAT_9_5_0_MASK 0x001F /* RAT[9:5] - [4:0] */
81#define WM8741_RAT_9_5_0_SHIFT 0 /* RAT[9:5] - [4:0] */
82#define WM8741_RAT_9_5_0_WIDTH 5 /* RAT[9:5] - [4:0] */
83
84/*
85 * R4 (0x04) - VOLUME_CONTROL
86 */
87#define WM8741_AMUTE 0x0080 /* AMUTE */
88#define WM8741_AMUTE_MASK 0x0080 /* AMUTE */
89#define WM8741_AMUTE_SHIFT 7 /* AMUTE */
90#define WM8741_AMUTE_WIDTH 1 /* AMUTE */
91#define WM8741_ZFLAG_MASK 0x0060 /* ZFLAG - [6:5] */
92#define WM8741_ZFLAG_SHIFT 5 /* ZFLAG - [6:5] */
93#define WM8741_ZFLAG_WIDTH 2 /* ZFLAG - [6:5] */
94#define WM8741_IZD 0x0010 /* IZD */
95#define WM8741_IZD_MASK 0x0010 /* IZD */
96#define WM8741_IZD_SHIFT 4 /* IZD */
97#define WM8741_IZD_WIDTH 1 /* IZD */
98#define WM8741_SOFT 0x0008 /* SOFT MUTE */
99#define WM8741_SOFT_MASK 0x0008 /* SOFT MUTE */
100#define WM8741_SOFT_SHIFT 3 /* SOFT MUTE */
101#define WM8741_SOFT_WIDTH 1 /* SOFT MUTE */
102#define WM8741_ATC 0x0004 /* ATC */
103#define WM8741_ATC_MASK 0x0004 /* ATC */
104#define WM8741_ATC_SHIFT 2 /* ATC */
105#define WM8741_ATC_WIDTH 1 /* ATC */
106#define WM8741_ATT2DB 0x0002 /* ATT2DB */
107#define WM8741_ATT2DB_MASK 0x0002 /* ATT2DB */
108#define WM8741_ATT2DB_SHIFT 1 /* ATT2DB */
109#define WM8741_ATT2DB_WIDTH 1 /* ATT2DB */
110#define WM8741_VOL_RAMP 0x0001 /* VOL_RAMP */
111#define WM8741_VOL_RAMP_MASK 0x0001 /* VOL_RAMP */
112#define WM8741_VOL_RAMP_SHIFT 0 /* VOL_RAMP */
113#define WM8741_VOL_RAMP_WIDTH 1 /* VOL_RAMP */
114
115/*
116 * R5 (0x05) - FORMAT_CONTROL
117 */
118#define WM8741_PWDN 0x0080 /* PWDN */
119#define WM8741_PWDN_MASK 0x0080 /* PWDN */
120#define WM8741_PWDN_SHIFT 7 /* PWDN */
121#define WM8741_PWDN_WIDTH 1 /* PWDN */
122#define WM8741_REV 0x0040 /* REV */
123#define WM8741_REV_MASK 0x0040 /* REV */
124#define WM8741_REV_SHIFT 6 /* REV */
125#define WM8741_REV_WIDTH 1 /* REV */
126#define WM8741_BCP 0x0020 /* BCP */
127#define WM8741_BCP_MASK 0x0020 /* BCP */
128#define WM8741_BCP_SHIFT 5 /* BCP */
129#define WM8741_BCP_WIDTH 1 /* BCP */
130#define WM8741_LRP 0x0010 /* LRP */
131#define WM8741_LRP_MASK 0x0010 /* LRP */
132#define WM8741_LRP_SHIFT 4 /* LRP */
133#define WM8741_LRP_WIDTH 1 /* LRP */
134#define WM8741_FMT_MASK 0x000C /* FMT - [3:2] */
135#define WM8741_FMT_SHIFT 2 /* FMT - [3:2] */
136#define WM8741_FMT_WIDTH 2 /* FMT - [3:2] */
137#define WM8741_IWL_MASK 0x0003 /* IWL - [1:0] */
138#define WM8741_IWL_SHIFT 0 /* IWL - [1:0] */
139#define WM8741_IWL_WIDTH 2 /* IWL - [1:0] */
140
141/*
142 * R6 (0x06) - FILTER_CONTROL
143 */
144#define WM8741_ZFLAG_HI 0x0080 /* ZFLAG_HI */
145#define WM8741_ZFLAG_HI_MASK 0x0080 /* ZFLAG_HI */
146#define WM8741_ZFLAG_HI_SHIFT 7 /* ZFLAG_HI */
147#define WM8741_ZFLAG_HI_WIDTH 1 /* ZFLAG_HI */
148#define WM8741_DEEMPH_MASK 0x0060 /* DEEMPH - [6:5] */
149#define WM8741_DEEMPH_SHIFT 5 /* DEEMPH - [6:5] */
150#define WM8741_DEEMPH_WIDTH 2 /* DEEMPH - [6:5] */
151#define WM8741_DSDFILT_MASK 0x0018 /* DSDFILT - [4:3] */
152#define WM8741_DSDFILT_SHIFT 3 /* DSDFILT - [4:3] */
153#define WM8741_DSDFILT_WIDTH 2 /* DSDFILT - [4:3] */
154#define WM8741_FIRSEL_MASK 0x0007 /* FIRSEL - [2:0] */
155#define WM8741_FIRSEL_SHIFT 0 /* FIRSEL - [2:0] */
156#define WM8741_FIRSEL_WIDTH 3 /* FIRSEL - [2:0] */
157
158/*
159 * R7 (0x07) - MODE_CONTROL_1
160 */
161#define WM8741_MODE8X 0x0080 /* MODE8X */
162#define WM8741_MODE8X_MASK 0x0080 /* MODE8X */
163#define WM8741_MODE8X_SHIFT 7 /* MODE8X */
164#define WM8741_MODE8X_WIDTH 1 /* MODE8X */
165#define WM8741_OSR_MASK 0x0060 /* OSR - [6:5] */
166#define WM8741_OSR_SHIFT 5 /* OSR - [6:5] */
167#define WM8741_OSR_WIDTH 2 /* OSR - [6:5] */
168#define WM8741_SR_MASK 0x001C /* SR - [4:2] */
169#define WM8741_SR_SHIFT 2 /* SR - [4:2] */
170#define WM8741_SR_WIDTH 3 /* SR - [4:2] */
171#define WM8741_MODESEL_MASK 0x0003 /* MODESEL - [1:0] */
172#define WM8741_MODESEL_SHIFT 0 /* MODESEL - [1:0] */
173#define WM8741_MODESEL_WIDTH 2 /* MODESEL - [1:0] */
174
175/*
176 * R8 (0x08) - MODE_CONTROL_2
177 */
178#define WM8741_DSD_GAIN 0x0040 /* DSD_GAIN */
179#define WM8741_DSD_GAIN_MASK 0x0040 /* DSD_GAIN */
180#define WM8741_DSD_GAIN_SHIFT 6 /* DSD_GAIN */
181#define WM8741_DSD_GAIN_WIDTH 1 /* DSD_GAIN */
182#define WM8741_SDOUT 0x0020 /* SDOUT */
183#define WM8741_SDOUT_MASK 0x0020 /* SDOUT */
184#define WM8741_SDOUT_SHIFT 5 /* SDOUT */
185#define WM8741_SDOUT_WIDTH 1 /* SDOUT */
186#define WM8741_DOUT 0x0010 /* DOUT */
187#define WM8741_DOUT_MASK 0x0010 /* DOUT */
188#define WM8741_DOUT_SHIFT 4 /* DOUT */
189#define WM8741_DOUT_WIDTH 1 /* DOUT */
190#define WM8741_DIFF_MASK 0x000C /* DIFF - [3:2] */
191#define WM8741_DIFF_SHIFT 2 /* DIFF - [3:2] */
192#define WM8741_DIFF_WIDTH 2 /* DIFF - [3:2] */
193#define WM8741_DITHER_MASK 0x0003 /* DITHER - [1:0] */
194#define WM8741_DITHER_SHIFT 0 /* DITHER - [1:0] */
195#define WM8741_DITHER_WIDTH 2 /* DITHER - [1:0] */
196
197/*
198 * R32 (0x20) - ADDITONAL_CONTROL_1
199 */
200#define WM8741_DSD_LEVEL 0x0002 /* DSD_LEVEL */
201#define WM8741_DSD_LEVEL_MASK 0x0002 /* DSD_LEVEL */
202#define WM8741_DSD_LEVEL_SHIFT 1 /* DSD_LEVEL */
203#define WM8741_DSD_LEVEL_WIDTH 1 /* DSD_LEVEL */
204#define WM8741_DSD_NO_NOTCH 0x0001 /* DSD_NO_NOTCH */
205#define WM8741_DSD_NO_NOTCH_MASK 0x0001 /* DSD_NO_NOTCH */
206#define WM8741_DSD_NO_NOTCH_SHIFT 0 /* DSD_NO_NOTCH */
207#define WM8741_DSD_NO_NOTCH_WIDTH 1 /* DSD_NO_NOTCH */
208
209#define WM8741_SYSCLK 0
210
211extern struct snd_soc_dai wm8741_dai;
212extern struct snd_soc_codec_device soc_codec_dev_wm8741;
213
214#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 9407e193fcc3..e2c05e3e323a 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -884,6 +884,7 @@ static int wm8750_i2c_remove(struct i2c_client *client)
884 884
885static const struct i2c_device_id wm8750_i2c_id[] = { 885static const struct i2c_device_id wm8750_i2c_id[] = {
886 { "wm8750", 0 }, 886 { "wm8750", 0 },
887 { "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */
887 { } 888 { }
888}; 889};
889MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); 890MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
@@ -925,14 +926,22 @@ static int __devexit wm8750_spi_remove(struct spi_device *spi)
925 return 0; 926 return 0;
926} 927}
927 928
929static const struct spi_device_id wm8750_spi_id[] = {
930 { "wm8750", 0 },
931 { "wm8987", 0 },
932 { }
933};
934MODULE_DEVICE_TABLE(spi, wm8750_spi_id);
935
928static struct spi_driver wm8750_spi_driver = { 936static struct spi_driver wm8750_spi_driver = {
929 .driver = { 937 .driver = {
930 .name = "wm8750", 938 .name = "WM8750 SPI Codec",
931 .bus = &spi_bus_type, 939 .bus = &spi_bus_type,
932 .owner = THIS_MODULE, 940 .owner = THIS_MODULE,
933 }, 941 },
934 .probe = wm8750_spi_probe, 942 .probe = wm8750_spi_probe,
935 .remove = __devexit_p(wm8750_spi_remove), 943 .remove = __devexit_p(wm8750_spi_remove),
944 .id_table = wm8750_spi_id,
936}; 945};
937#endif 946#endif
938 947
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 87f14f8675fa..f7dcabf6283c 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2433,7 +2433,8 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2433 2433
2434 if (wm8904_codec) { 2434 if (wm8904_codec) {
2435 dev_err(codec->dev, "Another WM8904 is registered\n"); 2435 dev_err(codec->dev, "Another WM8904 is registered\n");
2436 return -EINVAL; 2436 ret = -EINVAL;
2437 goto err;
2437 } 2438 }
2438 2439
2439 mutex_init(&codec->mutex); 2440 mutex_init(&codec->mutex);
@@ -2462,7 +2463,8 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2462 default: 2463 default:
2463 dev_err(codec->dev, "Unknown device type %d\n", 2464 dev_err(codec->dev, "Unknown device type %d\n",
2464 wm8904->devtype); 2465 wm8904->devtype);
2465 return -EINVAL; 2466 ret = -EINVAL;
2467 goto err;
2466 } 2468 }
2467 2469
2468 memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); 2470 memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg));
@@ -2566,18 +2568,19 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2566 ret = snd_soc_register_codec(codec); 2568 ret = snd_soc_register_codec(codec);
2567 if (ret != 0) { 2569 if (ret != 0) {
2568 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 2570 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
2569 return ret; 2571 goto err_enable;
2570 } 2572 }
2571 2573
2572 ret = snd_soc_register_dai(&wm8904_dai); 2574 ret = snd_soc_register_dai(&wm8904_dai);
2573 if (ret != 0) { 2575 if (ret != 0) {
2574 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 2576 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
2575 snd_soc_unregister_codec(codec); 2577 goto err_codec;
2576 return ret;
2577 } 2578 }
2578 2579
2579 return 0; 2580 return 0;
2580 2581
2582err_codec:
2583 snd_soc_unregister_codec(codec);
2581err_enable: 2584err_enable:
2582 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2585 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2583err_get: 2586err_get:
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index e3c4bbfaae27..f0c11138e610 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -845,6 +845,7 @@ static void wm8940_unregister(struct wm8940_priv *wm8940)
845static int wm8940_i2c_probe(struct i2c_client *i2c, 845static int wm8940_i2c_probe(struct i2c_client *i2c,
846 const struct i2c_device_id *id) 846 const struct i2c_device_id *id)
847{ 847{
848 int ret;
848 struct wm8940_priv *wm8940; 849 struct wm8940_priv *wm8940;
849 struct snd_soc_codec *codec; 850 struct snd_soc_codec *codec;
850 851
@@ -858,7 +859,11 @@ static int wm8940_i2c_probe(struct i2c_client *i2c,
858 codec->control_data = i2c; 859 codec->control_data = i2c;
859 codec->dev = &i2c->dev; 860 codec->dev = &i2c->dev;
860 861
861 return wm8940_register(wm8940, SND_SOC_I2C); 862 ret = wm8940_register(wm8940, SND_SOC_I2C);
863 if (ret < 0)
864 kfree(wm8940);
865
866 return ret;
862} 867}
863 868
864static int __devexit wm8940_i2c_remove(struct i2c_client *client) 869static int __devexit wm8940_i2c_remove(struct i2c_client *client)
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index fedb76452f1b..5f025593d84d 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -964,7 +964,8 @@ static int wm8955_register(struct wm8955_priv *wm8955,
964 964
965 if (wm8955_codec) { 965 if (wm8955_codec) {
966 dev_err(codec->dev, "Another WM8955 is registered\n"); 966 dev_err(codec->dev, "Another WM8955 is registered\n");
967 return -EINVAL; 967 ret = -EINVAL;
968 goto err;
968 } 969 }
969 970
970 mutex_init(&codec->mutex); 971 mutex_init(&codec->mutex);
@@ -1047,18 +1048,19 @@ static int wm8955_register(struct wm8955_priv *wm8955,
1047 ret = snd_soc_register_codec(codec); 1048 ret = snd_soc_register_codec(codec);
1048 if (ret != 0) { 1049 if (ret != 0) {
1049 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 1050 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1050 return ret; 1051 goto err_enable;
1051 } 1052 }
1052 1053
1053 ret = snd_soc_register_dai(&wm8955_dai); 1054 ret = snd_soc_register_dai(&wm8955_dai);
1054 if (ret != 0) { 1055 if (ret != 0) {
1055 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 1056 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1056 snd_soc_unregister_codec(codec); 1057 goto err_codec;
1057 return ret;
1058 } 1058 }
1059 1059
1060 return 0; 1060 return 0;
1061 1061
1062err_codec:
1063 snd_soc_unregister_codec(codec);
1062err_enable: 1064err_enable:
1063 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 1065 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1064err_get: 1066err_get:
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 7233cc68435a..3c6ee61f6c95 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -79,12 +79,13 @@ struct wm8960_priv {
79 struct snd_soc_dapm_widget *lout1; 79 struct snd_soc_dapm_widget *lout1;
80 struct snd_soc_dapm_widget *rout1; 80 struct snd_soc_dapm_widget *rout1;
81 struct snd_soc_dapm_widget *out3; 81 struct snd_soc_dapm_widget *out3;
82 bool deemph;
83 int playback_fs;
82}; 84};
83 85
84#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) 86#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
85 87
86/* enumerated controls */ 88/* enumerated controls */
87static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
88static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted", 89static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
89 "Right Inverted", "Stereo Inversion"}; 90 "Right Inverted", "Stereo Inversion"};
90static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"}; 91static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
@@ -93,7 +94,6 @@ static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
93static const char *wm8960_alcmode[] = {"ALC", "Limiter"}; 94static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
94 95
95static const struct soc_enum wm8960_enum[] = { 96static const struct soc_enum wm8960_enum[] = {
96 SOC_ENUM_SINGLE(WM8960_DACCTL1, 1, 4, wm8960_deemph),
97 SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity), 97 SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
98 SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity), 98 SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity),
99 SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff), 99 SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff),
@@ -102,6 +102,59 @@ static const struct soc_enum wm8960_enum[] = {
102 SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode), 102 SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
103}; 103};
104 104
105static const int deemph_settings[] = { 0, 32000, 44100, 48000 };
106
107static int wm8960_set_deemph(struct snd_soc_codec *codec)
108{
109 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
110 int val, i, best;
111
112 /* If we're using deemphasis select the nearest available sample
113 * rate.
114 */
115 if (wm8960->deemph) {
116 best = 1;
117 for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) {
118 if (abs(deemph_settings[i] - wm8960->playback_fs) <
119 abs(deemph_settings[best] - wm8960->playback_fs))
120 best = i;
121 }
122
123 val = best << 1;
124 } else {
125 val = 0;
126 }
127
128 dev_dbg(codec->dev, "Set deemphasis %d\n", val);
129
130 return snd_soc_update_bits(codec, WM8960_DACCTL1,
131 0x6, val);
132}
133
134static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
135 struct snd_ctl_elem_value *ucontrol)
136{
137 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
138 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
139
140 return wm8960->deemph;
141}
142
143static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
144 struct snd_ctl_elem_value *ucontrol)
145{
146 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
147 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
148 int deemph = ucontrol->value.enumerated.item[0];
149
150 if (deemph > 1)
151 return -EINVAL;
152
153 wm8960->deemph = deemph;
154
155 return wm8960_set_deemph(codec);
156}
157
105static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0); 158static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
106static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); 159static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
107static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); 160static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
@@ -131,23 +184,24 @@ SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0),
131SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0), 184SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0),
132 185
133SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0), 186SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0),
134SOC_ENUM("ADC Polarity", wm8960_enum[1]), 187SOC_ENUM("ADC Polarity", wm8960_enum[0]),
135SOC_ENUM("Playback De-emphasis", wm8960_enum[0]),
136SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0), 188SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0),
137 189
138SOC_ENUM("DAC Polarity", wm8960_enum[2]), 190SOC_ENUM("DAC Polarity", wm8960_enum[2]),
191SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0,
192 wm8960_get_deemph, wm8960_put_deemph),
139 193
140SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[3]), 194SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[2]),
141SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[4]), 195SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[3]),
142SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0), 196SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0),
143SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0), 197SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0),
144 198
145SOC_ENUM("ALC Function", wm8960_enum[5]), 199SOC_ENUM("ALC Function", wm8960_enum[4]),
146SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0), 200SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0),
147SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1), 201SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1),
148SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0), 202SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0),
149SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0), 203SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0),
150SOC_ENUM("ALC Mode", wm8960_enum[6]), 204SOC_ENUM("ALC Mode", wm8960_enum[5]),
151SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0), 205SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0),
152SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0), 206SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0),
153 207
@@ -433,6 +487,21 @@ static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,
433 return 0; 487 return 0;
434} 488}
435 489
490static struct {
491 int rate;
492 unsigned int val;
493} alc_rates[] = {
494 { 48000, 0 },
495 { 44100, 0 },
496 { 32000, 1 },
497 { 22050, 2 },
498 { 24000, 2 },
499 { 16000, 3 },
500 { 11250, 4 },
501 { 12000, 4 },
502 { 8000, 5 },
503};
504
436static int wm8960_hw_params(struct snd_pcm_substream *substream, 505static int wm8960_hw_params(struct snd_pcm_substream *substream,
437 struct snd_pcm_hw_params *params, 506 struct snd_pcm_hw_params *params,
438 struct snd_soc_dai *dai) 507 struct snd_soc_dai *dai)
@@ -440,7 +509,9 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
440 struct snd_soc_pcm_runtime *rtd = substream->private_data; 509 struct snd_soc_pcm_runtime *rtd = substream->private_data;
441 struct snd_soc_device *socdev = rtd->socdev; 510 struct snd_soc_device *socdev = rtd->socdev;
442 struct snd_soc_codec *codec = socdev->card->codec; 511 struct snd_soc_codec *codec = socdev->card->codec;
512 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
443 u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; 513 u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
514 int i;
444 515
445 /* bit size */ 516 /* bit size */
446 switch (params_format(params)) { 517 switch (params_format(params)) {
@@ -454,6 +525,18 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
454 break; 525 break;
455 } 526 }
456 527
528 /* Update filters for the new rate */
529 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
530 wm8960->playback_fs = params_rate(params);
531 wm8960_set_deemph(codec);
532 } else {
533 for (i = 0; i < ARRAY_SIZE(alc_rates); i++)
534 if (alc_rates[i].rate == params_rate(params))
535 snd_soc_update_bits(codec,
536 WM8960_ADDCTL3, 0x7,
537 alc_rates[i].val);
538 }
539
457 /* set iface */ 540 /* set iface */
458 snd_soc_write(codec, WM8960_IFACE1, iface); 541 snd_soc_write(codec, WM8960_IFACE1, iface);
459 return 0; 542 return 0;
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 5b9a756242f1..2549d3a297ab 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -1102,7 +1102,7 @@ static int wm8961_register(struct wm8961_priv *wm8961)
1102 ret = wm8961_reset(codec); 1102 ret = wm8961_reset(codec);
1103 if (ret < 0) { 1103 if (ret < 0) {
1104 dev_err(codec->dev, "Failed to issue reset\n"); 1104 dev_err(codec->dev, "Failed to issue reset\n");
1105 return ret; 1105 goto err;
1106 } 1106 }
1107 1107
1108 /* Enable class W */ 1108 /* Enable class W */
@@ -1147,18 +1147,19 @@ static int wm8961_register(struct wm8961_priv *wm8961)
1147 ret = snd_soc_register_codec(codec); 1147 ret = snd_soc_register_codec(codec);
1148 if (ret != 0) { 1148 if (ret != 0) {
1149 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 1149 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1150 return ret; 1150 goto err;
1151 } 1151 }
1152 1152
1153 ret = snd_soc_register_dai(&wm8961_dai); 1153 ret = snd_soc_register_dai(&wm8961_dai);
1154 if (ret != 0) { 1154 if (ret != 0) {
1155 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 1155 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1156 snd_soc_unregister_codec(codec); 1156 goto err_codec;
1157 return ret;
1158 } 1157 }
1159 1158
1160 return 0; 1159 return 0;
1161 1160
1161err_codec:
1162 snd_soc_unregister_codec(codec);
1162err: 1163err:
1163 kfree(wm8961); 1164 kfree(wm8961);
1164 return ret; 1165 return ret;
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index a2c4b2f37cca..1468fe10cbbe 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -670,7 +670,8 @@ static __devinit int wm8974_register(struct wm8974_priv *wm8974)
670 670
671 if (wm8974_codec) { 671 if (wm8974_codec) {
672 dev_err(codec->dev, "Another WM8974 is registered\n"); 672 dev_err(codec->dev, "Another WM8974 is registered\n");
673 return -EINVAL; 673 ret = -EINVAL;
674 goto err;
674 } 675 }
675 676
676 mutex_init(&codec->mutex); 677 mutex_init(&codec->mutex);
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 51d5f433215c..8a1ad778e7e3 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -1076,7 +1076,6 @@ static __devinit int wm8978_register(struct wm8978_priv *wm8978)
1076err_codec: 1076err_codec:
1077 snd_soc_unregister_codec(codec); 1077 snd_soc_unregister_codec(codec);
1078err: 1078err:
1079 kfree(wm8978);
1080 return ret; 1079 return ret;
1081} 1080}
1082 1081
@@ -1085,13 +1084,13 @@ static __devexit void wm8978_unregister(struct wm8978_priv *wm8978)
1085 wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF); 1084 wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF);
1086 snd_soc_unregister_dai(&wm8978_dai); 1085 snd_soc_unregister_dai(&wm8978_dai);
1087 snd_soc_unregister_codec(&wm8978->codec); 1086 snd_soc_unregister_codec(&wm8978->codec);
1088 kfree(wm8978);
1089 wm8978_codec = NULL; 1087 wm8978_codec = NULL;
1090} 1088}
1091 1089
1092static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, 1090static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
1093 const struct i2c_device_id *id) 1091 const struct i2c_device_id *id)
1094{ 1092{
1093 int ret;
1095 struct wm8978_priv *wm8978; 1094 struct wm8978_priv *wm8978;
1096 struct snd_soc_codec *codec; 1095 struct snd_soc_codec *codec;
1097 1096
@@ -1107,13 +1106,18 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
1107 1106
1108 codec->dev = &i2c->dev; 1107 codec->dev = &i2c->dev;
1109 1108
1110 return wm8978_register(wm8978); 1109 ret = wm8978_register(wm8978);
1110 if (ret < 0)
1111 kfree(wm8978);
1112
1113 return ret;
1111} 1114}
1112 1115
1113static __devexit int wm8978_i2c_remove(struct i2c_client *client) 1116static __devexit int wm8978_i2c_remove(struct i2c_client *client)
1114{ 1117{
1115 struct wm8978_priv *wm8978 = i2c_get_clientdata(client); 1118 struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
1116 wm8978_unregister(wm8978); 1119 wm8978_unregister(wm8978);
1120 kfree(wm8978);
1117 return 0; 1121 return 0;
1118} 1122}
1119 1123
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index c018772cc430..dd8d909788c1 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -30,8 +30,6 @@
30 30
31#include "wm8990.h" 31#include "wm8990.h"
32 32
33#define WM8990_VERSION "0.2"
34
35/* codec private data */ 33/* codec private data */
36struct wm8990_priv { 34struct wm8990_priv {
37 unsigned int sysclk; 35 unsigned int sysclk;
@@ -1511,8 +1509,6 @@ static int wm8990_probe(struct platform_device *pdev)
1511 struct wm8990_priv *wm8990; 1509 struct wm8990_priv *wm8990;
1512 int ret; 1510 int ret;
1513 1511
1514 pr_info("WM8990 Audio Codec %s\n", WM8990_VERSION);
1515
1516 setup = socdev->codec_data; 1512 setup = socdev->codec_data;
1517 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 1513 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1518 if (codec == NULL) 1514 if (codec == NULL)
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index e84a1177f350..a87046a96f2a 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -1677,6 +1677,26 @@ static struct {
1677 1677
1678static int wm8994_readable(unsigned int reg) 1678static int wm8994_readable(unsigned int reg)
1679{ 1679{
1680 switch (reg) {
1681 case WM8994_GPIO_1:
1682 case WM8994_GPIO_2:
1683 case WM8994_GPIO_3:
1684 case WM8994_GPIO_4:
1685 case WM8994_GPIO_5:
1686 case WM8994_GPIO_6:
1687 case WM8994_GPIO_7:
1688 case WM8994_GPIO_8:
1689 case WM8994_GPIO_9:
1690 case WM8994_GPIO_10:
1691 case WM8994_GPIO_11:
1692 case WM8994_INTERRUPT_STATUS_1:
1693 case WM8994_INTERRUPT_STATUS_2:
1694 case WM8994_INTERRUPT_RAW_STATUS_2:
1695 return 1;
1696 default:
1697 break;
1698 }
1699
1680 if (reg >= ARRAY_SIZE(access_masks)) 1700 if (reg >= ARRAY_SIZE(access_masks))
1681 return 0; 1701 return 0;
1682 return access_masks[reg].readable != 0; 1702 return access_masks[reg].readable != 0;
@@ -2341,6 +2361,20 @@ SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING,
2341 0, 1, 0), 2361 0, 1, 0),
2342}; 2362};
2343 2363
2364static const struct snd_kcontrol_new aif1adc2l_mix[] = {
2365SOC_DAPM_SINGLE("DMIC Switch", WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING,
2366 1, 1, 0),
2367SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING,
2368 0, 1, 0),
2369};
2370
2371static const struct snd_kcontrol_new aif1adc2r_mix[] = {
2372SOC_DAPM_SINGLE("DMIC Switch", WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING,
2373 1, 1, 0),
2374SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING,
2375 0, 1, 0),
2376};
2377
2344static const struct snd_kcontrol_new aif2dac2l_mix[] = { 2378static const struct snd_kcontrol_new aif2dac2l_mix[] = {
2345SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, 2379SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING,
2346 5, 1, 0), 2380 5, 1, 0),
@@ -2472,6 +2506,7 @@ static const struct snd_kcontrol_new aif3adc_mux =
2472static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { 2506static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
2473SND_SOC_DAPM_INPUT("DMIC1DAT"), 2507SND_SOC_DAPM_INPUT("DMIC1DAT"),
2474SND_SOC_DAPM_INPUT("DMIC2DAT"), 2508SND_SOC_DAPM_INPUT("DMIC2DAT"),
2509SND_SOC_DAPM_INPUT("Clock"),
2475 2510
2476SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, 2511SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event,
2477 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 2512 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -2506,6 +2541,11 @@ SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer", SND_SOC_NOPM, 0, 0,
2506SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer", SND_SOC_NOPM, 0, 0, 2541SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer", SND_SOC_NOPM, 0, 0,
2507 aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)), 2542 aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)),
2508 2543
2544SND_SOC_DAPM_MIXER("AIF1ADC2L Mixer", SND_SOC_NOPM, 0, 0,
2545 aif1adc2l_mix, ARRAY_SIZE(aif1adc2l_mix)),
2546SND_SOC_DAPM_MIXER("AIF1ADC2R Mixer", SND_SOC_NOPM, 0, 0,
2547 aif1adc2r_mix, ARRAY_SIZE(aif1adc2r_mix)),
2548
2509SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer", SND_SOC_NOPM, 0, 0, 2549SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer", SND_SOC_NOPM, 0, 0,
2510 aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)), 2550 aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)),
2511SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0, 2551SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0,
@@ -2668,6 +2708,14 @@ static const struct snd_soc_dapm_route intercon[] = {
2668 { "AIF1ADC1R Mixer", "ADC/DMIC Switch", "ADCR Mux" }, 2708 { "AIF1ADC1R Mixer", "ADC/DMIC Switch", "ADCR Mux" },
2669 { "AIF1ADC1R Mixer", "AIF2 Switch", "AIF2DACR" }, 2709 { "AIF1ADC1R Mixer", "AIF2 Switch", "AIF2DACR" },
2670 2710
2711 { "AIF1ADC2L", NULL, "AIF1ADC2L Mixer" },
2712 { "AIF1ADC2L Mixer", "DMIC Switch", "DMIC2L" },
2713 { "AIF1ADC2L Mixer", "AIF2 Switch", "AIF2DACL" },
2714
2715 { "AIF1ADC2R", NULL, "AIF1ADC2R Mixer" },
2716 { "AIF1ADC2R Mixer", "DMIC Switch", "DMIC2R" },
2717 { "AIF1ADC2R Mixer", "AIF2 Switch", "AIF2DACR" },
2718
2671 /* Pin level routing for AIF3 */ 2719 /* Pin level routing for AIF3 */
2672 { "AIF1DAC1L", NULL, "AIF1DAC Mux" }, 2720 { "AIF1DAC1L", NULL, "AIF1DAC Mux" },
2673 { "AIF1DAC1R", NULL, "AIF1DAC Mux" }, 2721 { "AIF1DAC1R", NULL, "AIF1DAC Mux" },
@@ -2946,11 +2994,14 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
2946 return 0; 2994 return 0;
2947} 2995}
2948 2996
2997static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
2998
2949static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, 2999static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
2950 int clk_id, unsigned int freq, int dir) 3000 int clk_id, unsigned int freq, int dir)
2951{ 3001{
2952 struct snd_soc_codec *codec = dai->codec; 3002 struct snd_soc_codec *codec = dai->codec;
2953 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 3003 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
3004 int i;
2954 3005
2955 switch (dai->id) { 3006 switch (dai->id) {
2956 case 1: 3007 case 1:
@@ -2988,6 +3039,25 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
2988 dev_dbg(dai->dev, "AIF%d using FLL2\n", dai->id); 3039 dev_dbg(dai->dev, "AIF%d using FLL2\n", dai->id);
2989 break; 3040 break;
2990 3041
3042 case WM8994_SYSCLK_OPCLK:
3043 /* Special case - a division (times 10) is given and
3044 * no effect on main clocking.
3045 */
3046 if (freq) {
3047 for (i = 0; i < ARRAY_SIZE(opclk_divs); i++)
3048 if (opclk_divs[i] == freq)
3049 break;
3050 if (i == ARRAY_SIZE(opclk_divs))
3051 return -EINVAL;
3052 snd_soc_update_bits(codec, WM8994_CLOCKING_2,
3053 WM8994_OPCLK_DIV_MASK, i);
3054 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
3055 WM8994_OPCLK_ENA, WM8994_OPCLK_ENA);
3056 } else {
3057 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
3058 WM8994_OPCLK_ENA, 0);
3059 }
3060
2991 default: 3061 default:
2992 return -EINVAL; 3062 return -EINVAL;
2993 } 3063 }
@@ -4004,6 +4074,11 @@ static int wm8994_codec_probe(struct platform_device *pdev)
4004 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, 4074 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT,
4005 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); 4075 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT);
4006 4076
4077 /* Unconditionally enable AIF1 ADC TDM mode; it only affects
4078 * behaviour on idle TDM clock cycles. */
4079 snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1,
4080 WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM);
4081
4007 wm8994_update_class_w(codec); 4082 wm8994_update_class_w(codec);
4008 4083
4009 ret = snd_soc_register_codec(codec); 4084 ret = snd_soc_register_codec(codec);
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 7072dc539354..2e0ca67a8df7 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -20,6 +20,9 @@ extern struct snd_soc_dai wm8994_dai[];
20#define WM8994_SYSCLK_FLL1 3 20#define WM8994_SYSCLK_FLL1 3
21#define WM8994_SYSCLK_FLL2 4 21#define WM8994_SYSCLK_FLL2 4
22 22
23/* OPCLK is also configured with set_dai_sysclk, specify division*10 as rate. */
24#define WM8994_SYSCLK_OPCLK 5
25
23#define WM8994_FLL1 1 26#define WM8994_FLL1 1
24#define WM8994_FLL2 2 27#define WM8994_FLL2 2
25 28
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 13186fb4dcb4..76b37ff6c264 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1356,7 +1356,7 @@ static int wm9081_register(struct wm9081_priv *wm9081,
1356 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); 1356 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
1357 if (ret != 0) { 1357 if (ret != 0) {
1358 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 1358 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1359 return ret; 1359 goto err;
1360 } 1360 }
1361 1361
1362 reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); 1362 reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
@@ -1369,7 +1369,7 @@ static int wm9081_register(struct wm9081_priv *wm9081,
1369 ret = wm9081_reset(codec); 1369 ret = wm9081_reset(codec);
1370 if (ret < 0) { 1370 if (ret < 0) {
1371 dev_err(codec->dev, "Failed to issue reset\n"); 1371 dev_err(codec->dev, "Failed to issue reset\n");
1372 return ret; 1372 goto err;
1373 } 1373 }
1374 1374
1375 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1375 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1388,18 +1388,19 @@ static int wm9081_register(struct wm9081_priv *wm9081,
1388 ret = snd_soc_register_codec(codec); 1388 ret = snd_soc_register_codec(codec);
1389 if (ret != 0) { 1389 if (ret != 0) {
1390 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 1390 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1391 return ret; 1391 goto err;
1392 } 1392 }
1393 1393
1394 ret = snd_soc_register_dai(&wm9081_dai); 1394 ret = snd_soc_register_dai(&wm9081_dai);
1395 if (ret != 0) { 1395 if (ret != 0) {
1396 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 1396 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1397 snd_soc_unregister_codec(codec); 1397 goto err_codec;
1398 return ret;
1399 } 1398 }
1400 1399
1401 return 0; 1400 return 0;
1402 1401
1402err_codec:
1403 snd_soc_unregister_codec(codec);
1403err: 1404err:
1404 kfree(wm9081); 1405 kfree(wm9081);
1405 return ret; 1406 return ret;
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 16f1a57da08a..2cb81538cd91 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -410,6 +410,8 @@ static int hp_event(struct snd_soc_dapm_widget *w,
410 WM8993_HPOUT1L_DLY | 410 WM8993_HPOUT1L_DLY |
411 WM8993_HPOUT1R_DLY, 0); 411 WM8993_HPOUT1R_DLY, 0);
412 412
413 snd_soc_write(codec, WM8993_DC_SERVO_0, 0);
414
413 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, 415 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
414 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, 416 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
415 0); 417 0);
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index adadcd3aa1b1..9e8932abf158 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -26,6 +26,7 @@
26#include <mach/asp.h> 26#include <mach/asp.h>
27 27
28#include "davinci-pcm.h" 28#include "davinci-pcm.h"
29#include "davinci-i2s.h"
29 30
30 31
31/* 32/*
@@ -68,16 +69,21 @@
68#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) 69#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16)
69#define DAVINCI_MCBSP_RCR_RFIG (1 << 18) 70#define DAVINCI_MCBSP_RCR_RFIG (1 << 18)
70#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) 71#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21)
72#define DAVINCI_MCBSP_RCR_RFRLEN2(v) ((v) << 24)
73#define DAVINCI_MCBSP_RCR_RPHASE BIT(31)
71 74
72#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) 75#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5)
73#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8) 76#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8)
74#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16) 77#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16)
75#define DAVINCI_MCBSP_XCR_XFIG (1 << 18) 78#define DAVINCI_MCBSP_XCR_XFIG (1 << 18)
76#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21) 79#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21)
80#define DAVINCI_MCBSP_XCR_XFRLEN2(v) ((v) << 24)
81#define DAVINCI_MCBSP_XCR_XPHASE BIT(31)
77 82
78#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8) 83#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8)
79#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16) 84#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16)
80#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28) 85#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28)
86#define DAVINCI_MCBSP_SRGR_CLKSM BIT(29)
81 87
82#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0) 88#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0)
83#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1) 89#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1)
@@ -116,6 +122,7 @@ static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {
116}; 122};
117 123
118struct davinci_mcbsp_dev { 124struct davinci_mcbsp_dev {
125 struct device *dev;
119 struct davinci_pcm_dma_params dma_params[2]; 126 struct davinci_pcm_dma_params dma_params[2];
120 void __iomem *base; 127 void __iomem *base;
121#define MOD_DSP_A 0 128#define MOD_DSP_A 0
@@ -144,6 +151,11 @@ struct davinci_mcbsp_dev {
144 * won't end up being swapped because of the underrun. 151 * won't end up being swapped because of the underrun.
145 */ 152 */
146 unsigned enable_channel_combine:1; 153 unsigned enable_channel_combine:1;
154
155 unsigned int fmt;
156 int clk_div;
157 int clk_input_pin;
158 bool i2s_accurate_sck;
147}; 159};
148 160
149static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, 161static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -254,10 +266,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
254 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 266 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
255 unsigned int pcr; 267 unsigned int pcr;
256 unsigned int srgr; 268 unsigned int srgr;
269 /* Attention srgr is updated by hw_params! */
257 srgr = DAVINCI_MCBSP_SRGR_FSGM | 270 srgr = DAVINCI_MCBSP_SRGR_FSGM |
258 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | 271 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
259 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); 272 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
260 273
274 dev->fmt = fmt;
261 /* set master/slave audio interface */ 275 /* set master/slave audio interface */
262 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 276 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
263 case SND_SOC_DAIFMT_CBS_CFS: 277 case SND_SOC_DAIFMT_CBS_CFS:
@@ -268,11 +282,26 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
268 DAVINCI_MCBSP_PCR_CLKRM; 282 DAVINCI_MCBSP_PCR_CLKRM;
269 break; 283 break;
270 case SND_SOC_DAIFMT_CBM_CFS: 284 case SND_SOC_DAIFMT_CBM_CFS:
271 /* McBSP CLKR pin is the input for the Sample Rate Generator. 285 pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM;
272 * McBSP FSR and FSX are driven by the Sample Rate Generator. */ 286 /*
273 pcr = DAVINCI_MCBSP_PCR_SCLKME | 287 * Selection of the clock input pin that is the
274 DAVINCI_MCBSP_PCR_FSXM | 288 * input for the Sample Rate Generator.
275 DAVINCI_MCBSP_PCR_FSRM; 289 * McBSP FSR and FSX are driven by the Sample Rate
290 * Generator.
291 */
292 switch (dev->clk_input_pin) {
293 case MCBSP_CLKS:
294 pcr |= DAVINCI_MCBSP_PCR_CLKXM |
295 DAVINCI_MCBSP_PCR_CLKRM;
296 break;
297 case MCBSP_CLKR:
298 pcr |= DAVINCI_MCBSP_PCR_SCLKME;
299 break;
300 default:
301 dev_err(dev->dev, "bad clk_input_pin\n");
302 return -EINVAL;
303 }
304
276 break; 305 break;
277 case SND_SOC_DAIFMT_CBM_CFM: 306 case SND_SOC_DAIFMT_CBM_CFM:
278 /* codec is master */ 307 /* codec is master */
@@ -372,6 +401,18 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
372 return 0; 401 return 0;
373} 402}
374 403
404static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
405 int div_id, int div)
406{
407 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
408
409 if (div_id != DAVINCI_MCBSP_CLKGDV)
410 return -ENODEV;
411
412 dev->clk_div = div;
413 return 0;
414}
415
375static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, 416static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
376 struct snd_pcm_hw_params *params, 417 struct snd_pcm_hw_params *params,
377 struct snd_soc_dai *dai) 418 struct snd_soc_dai *dai)
@@ -380,8 +421,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
380 struct davinci_pcm_dma_params *dma_params = 421 struct davinci_pcm_dma_params *dma_params =
381 &dev->dma_params[substream->stream]; 422 &dev->dma_params[substream->stream];
382 struct snd_interval *i = NULL; 423 struct snd_interval *i = NULL;
383 int mcbsp_word_length; 424 int mcbsp_word_length, master;
384 unsigned int rcr, xcr, srgr; 425 unsigned int rcr, xcr, srgr, clk_div, freq, framesize;
385 u32 spcr; 426 u32 spcr;
386 snd_pcm_format_t fmt; 427 snd_pcm_format_t fmt;
387 unsigned element_cnt = 1; 428 unsigned element_cnt = 1;
@@ -396,12 +437,59 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
396 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); 437 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
397 } 438 }
398 439
399 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 440 master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK;
400 srgr = DAVINCI_MCBSP_SRGR_FSGM; 441 fmt = params_format(params);
401 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); 442 mcbsp_word_length = asp_word_length[fmt];
402 443
403 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); 444 switch (master) {
404 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); 445 case SND_SOC_DAIFMT_CBS_CFS:
446 freq = clk_get_rate(dev->clk);
447 srgr = DAVINCI_MCBSP_SRGR_FSGM |
448 DAVINCI_MCBSP_SRGR_CLKSM;
449 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length *
450 8 - 1);
451 if (dev->i2s_accurate_sck) {
452 clk_div = 256;
453 do {
454 framesize = (freq / (--clk_div)) /
455 params->rate_num *
456 params->rate_den;
457 } while (((framesize < 33) || (framesize > 4095)) &&
458 (clk_div));
459 clk_div--;
460 srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1);
461 } else {
462 /* symmetric waveforms */
463 clk_div = freq / (mcbsp_word_length * 16) /
464 params->rate_num * params->rate_den;
465 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *
466 16 - 1);
467 }
468 clk_div &= 0xFF;
469 srgr |= clk_div;
470 break;
471 case SND_SOC_DAIFMT_CBM_CFS:
472 srgr = DAVINCI_MCBSP_SRGR_FSGM;
473 clk_div = dev->clk_div - 1;
474 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1);
475 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1);
476 clk_div &= 0xFF;
477 srgr |= clk_div;
478 break;
479 case SND_SOC_DAIFMT_CBM_CFM:
480 /* Clock and frame sync given from external sources */
481 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
482 srgr = DAVINCI_MCBSP_SRGR_FSGM;
483 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
484 pr_debug("%s - %d FWID set: re-read srgr = %X\n",
485 __func__, __LINE__, snd_interval_value(i) - 1);
486
487 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
488 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
489 break;
490 default:
491 return -EINVAL;
492 }
405 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); 493 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
406 494
407 rcr = DAVINCI_MCBSP_RCR_RFIG; 495 rcr = DAVINCI_MCBSP_RCR_RFIG;
@@ -426,12 +514,41 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
426 element_cnt = 1; 514 element_cnt = 1;
427 fmt = double_fmt[fmt]; 515 fmt = double_fmt[fmt];
428 } 516 }
517 switch (master) {
518 case SND_SOC_DAIFMT_CBS_CFS:
519 case SND_SOC_DAIFMT_CBS_CFM:
520 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0);
521 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0);
522 rcr |= DAVINCI_MCBSP_RCR_RPHASE;
523 xcr |= DAVINCI_MCBSP_XCR_XPHASE;
524 break;
525 case SND_SOC_DAIFMT_CBM_CFM:
526 case SND_SOC_DAIFMT_CBM_CFS:
527 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1);
528 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1);
529 break;
530 default:
531 return -EINVAL;
532 }
429 } 533 }
430 dma_params->acnt = dma_params->data_type = data_type[fmt]; 534 dma_params->acnt = dma_params->data_type = data_type[fmt];
431 dma_params->fifo_level = 0; 535 dma_params->fifo_level = 0;
432 mcbsp_word_length = asp_word_length[fmt]; 536 mcbsp_word_length = asp_word_length[fmt];
433 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); 537
434 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); 538 switch (master) {
539 case SND_SOC_DAIFMT_CBS_CFS:
540 case SND_SOC_DAIFMT_CBS_CFM:
541 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0);
542 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0);
543 break;
544 case SND_SOC_DAIFMT_CBM_CFM:
545 case SND_SOC_DAIFMT_CBM_CFS:
546 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
547 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
548 break;
549 default:
550 return -EINVAL;
551 }
435 552
436 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | 553 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
437 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); 554 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
@@ -442,6 +559,10 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
442 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); 559 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
443 else 560 else
444 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); 561 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
562
563 pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr);
564 pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr);
565 pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr);
445 return 0; 566 return 0;
446} 567}
447 568
@@ -500,6 +621,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
500 .trigger = davinci_i2s_trigger, 621 .trigger = davinci_i2s_trigger,
501 .hw_params = davinci_i2s_hw_params, 622 .hw_params = davinci_i2s_hw_params,
502 .set_fmt = davinci_i2s_set_dai_fmt, 623 .set_fmt = davinci_i2s_set_dai_fmt,
624 .set_clkdiv = davinci_i2s_dai_set_clkdiv,
503 625
504}; 626};
505 627
@@ -526,6 +648,8 @@ static int davinci_i2s_probe(struct platform_device *pdev)
526 struct snd_platform_data *pdata = pdev->dev.platform_data; 648 struct snd_platform_data *pdata = pdev->dev.platform_data;
527 struct davinci_mcbsp_dev *dev; 649 struct davinci_mcbsp_dev *dev;
528 struct resource *mem, *ioarea, *res; 650 struct resource *mem, *ioarea, *res;
651 enum dma_event_q asp_chan_q = EVENTQ_0;
652 enum dma_event_q ram_chan_q = EVENTQ_1;
529 int ret; 653 int ret;
530 654
531 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 655 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -552,7 +676,17 @@ static int davinci_i2s_probe(struct platform_device *pdev)
552 pdata->sram_size_playback; 676 pdata->sram_size_playback;
553 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size = 677 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
554 pdata->sram_size_capture; 678 pdata->sram_size_capture;
679 dev->clk_input_pin = pdata->clk_input_pin;
680 dev->i2s_accurate_sck = pdata->i2s_accurate_sck;
681 asp_chan_q = pdata->asp_chan_q;
682 ram_chan_q = pdata->ram_chan_q;
555 } 683 }
684
685 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].asp_chan_q = asp_chan_q;
686 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].ram_chan_q = ram_chan_q;
687 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].asp_chan_q = asp_chan_q;
688 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q = ram_chan_q;
689
556 dev->clk = clk_get(&pdev->dev, NULL); 690 dev->clk = clk_get(&pdev->dev, NULL);
557 if (IS_ERR(dev->clk)) { 691 if (IS_ERR(dev->clk)) {
558 ret = -ENODEV; 692 ret = -ENODEV;
@@ -584,6 +718,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
584 goto err_free_mem; 718 goto err_free_mem;
585 } 719 }
586 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; 720 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
721 dev->dev = &pdev->dev;
587 722
588 davinci_i2s_dai.private_data = dev; 723 davinci_i2s_dai.private_data = dev;
589 davinci_i2s_dai.capture.dma_data = dev->dma_params; 724 davinci_i2s_dai.capture.dma_data = dev->dma_params;
diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
index 241648ce8873..0b1e77b8c279 100644
--- a/sound/soc/davinci/davinci-i2s.h
+++ b/sound/soc/davinci/davinci-i2s.h
@@ -12,6 +12,11 @@
12#ifndef _DAVINCI_I2S_H 12#ifndef _DAVINCI_I2S_H
13#define _DAVINCI_I2S_H 13#define _DAVINCI_I2S_H
14 14
15/* McBSP dividers */
16enum davinci_mcbsp_div {
17 DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */
18};
19
15extern struct snd_soc_dai davinci_i2s_dai; 20extern struct snd_soc_dai davinci_i2s_dai;
16 21
17#endif 22#endif
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index d3955096d872..b24720894af6 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -890,7 +890,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
890 dev->rxnumevt = pdata->rxnumevt; 890 dev->rxnumevt = pdata->rxnumevt;
891 891
892 dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; 892 dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
893 dma_data->eventq_no = pdata->eventq_no; 893 dma_data->asp_chan_q = pdata->asp_chan_q;
894 dma_data->ram_chan_q = pdata->ram_chan_q;
894 dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + 895 dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
895 io_v2p(dev->base)); 896 io_v2p(dev->base));
896 897
@@ -904,7 +905,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
904 dma_data->channel = res->start; 905 dma_data->channel = res->start;
905 906
906 dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; 907 dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
907 dma_data->eventq_no = pdata->eventq_no; 908 dma_data->asp_chan_q = pdata->asp_chan_q;
909 dma_data->ram_chan_q = pdata->ram_chan_q;
908 dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + 910 dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
909 io_v2p(dev->base)); 911 io_v2p(dev->base));
910 912
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 2dc406f42fe7..a7124116d2e0 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -381,7 +381,7 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
381 /* Request ram master channel */ 381 /* Request ram master channel */
382 link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY, 382 link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
383 davinci_pcm_dma_irq, substream, 383 davinci_pcm_dma_irq, substream,
384 EVENTQ_1); 384 prtd->params->ram_chan_q);
385 if (link < 0) 385 if (link < 0)
386 goto exit1; 386 goto exit1;
387 387
@@ -477,7 +477,8 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
477 477
478 /* Request asp master DMA channel */ 478 /* Request asp master DMA channel */
479 link = prtd->asp_channel = edma_alloc_channel(params->channel, 479 link = prtd->asp_channel = edma_alloc_channel(params->channel,
480 davinci_pcm_dma_irq, substream, EVENTQ_0); 480 davinci_pcm_dma_irq, substream,
481 prtd->params->asp_chan_q);
481 if (link < 0) 482 if (link < 0)
482 goto exit1; 483 goto exit1;
483 484
@@ -800,7 +801,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
800 dma_free_writecombine(pcm->card->dev, buf->bytes, 801 dma_free_writecombine(pcm->card->dev, buf->bytes,
801 buf->area, buf->addr); 802 buf->area, buf->addr);
802 buf->area = NULL; 803 buf->area = NULL;
803 iram_dma = (struct snd_dma_buffer *)buf->private_data; 804 iram_dma = buf->private_data;
804 if (iram_dma) { 805 if (iram_dma) {
805 sram_free(iram_dma->area, iram_dma->bytes); 806 sram_free(iram_dma->area, iram_dma->bytes);
806 kfree(iram_dma); 807 kfree(iram_dma);
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index 0764944cf10f..b799a02333d8 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -21,7 +21,8 @@ struct davinci_pcm_dma_params {
21 unsigned short acnt; 21 unsigned short acnt;
22 dma_addr_t dma_addr; /* device physical address for DMA */ 22 dma_addr_t dma_addr; /* device physical address for DMA */
23 unsigned sram_size; 23 unsigned sram_size;
24 enum dma_event_q eventq_no; /* event queue number */ 24 enum dma_event_q asp_chan_q; /* event queue number for ASP channel */
25 enum dma_event_q ram_chan_q; /* event queue number for RAM channel */
25 unsigned char data_type; /* xfer data type */ 26 unsigned char data_type; /* xfer data type */
26 unsigned char convert_mono_stereo; 27 unsigned char convert_mono_stereo;
27 unsigned int fifo_level; 28 unsigned int fifo_level;
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 9aa980d38231..48678533da7a 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -203,7 +203,7 @@ static int davinci_vcif_probe(struct platform_device *pdev)
203 int ret; 203 int ret;
204 204
205 davinci_vcif_dev = kzalloc(sizeof(struct davinci_vcif_dev), GFP_KERNEL); 205 davinci_vcif_dev = kzalloc(sizeof(struct davinci_vcif_dev), GFP_KERNEL);
206 if (!davinci_vc) { 206 if (!davinci_vcif_dev) {
207 dev_dbg(&pdev->dev, 207 dev_dbg(&pdev->dev,
208 "could not allocate memory for private data\n"); 208 "could not allocate memory for private data\n");
209 return -ENOMEM; 209 return -ENOMEM;
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
new file mode 100644
index 000000000000..f617f560f46b
--- /dev/null
+++ b/sound/soc/ep93xx/Kconfig
@@ -0,0 +1,18 @@
1config SND_EP93XX_SOC
2 tristate "SoC Audio support for the Cirrus Logic EP93xx series"
3 depends on ARCH_EP93XX && SND_SOC
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the EP93xx I2S interface.
7
8config SND_EP93XX_SOC_I2S
9 tristate
10
11config SND_EP93XX_SOC_SNAPPERCL15
12 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
13 depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
14 select SND_EP93XX_SOC_I2S
15 select SND_SOC_TLV320AIC23
16 help
17 Say Y or M here if you want to add support for I2S audio on the
18 Bluewater Systems Snapper CL15 module.
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile
new file mode 100644
index 000000000000..272e60f57b9a
--- /dev/null
+++ b/sound/soc/ep93xx/Makefile
@@ -0,0 +1,11 @@
1# EP93xx Platform Support
2snd-soc-ep93xx-objs := ep93xx-pcm.o
3snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o
4
5obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o
6obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o
7
8# EP93XX Machine Support
9snd-soc-snappercl15-objs := snappercl15.o
10
11obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
new file mode 100644
index 000000000000..00b946632184
--- /dev/null
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -0,0 +1,487 @@
1/*
2 * linux/sound/soc/ep93xx-i2s.c
3 * EP93xx I2S driver
4 *
5 * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com>
6 *
7 * Based on the original driver by:
8 * Copyright (C) 2007 Chase Douglas <chasedouglas@gmail>
9 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/slab.h>
20#include <linux/clk.h>
21#include <linux/io.h>
22
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28
29#include <mach/hardware.h>
30#include <mach/ep93xx-regs.h>
31#include <mach/dma.h>
32
33#include "ep93xx-pcm.h"
34#include "ep93xx-i2s.h"
35
36#define EP93XX_I2S_TXCLKCFG 0x00
37#define EP93XX_I2S_RXCLKCFG 0x04
38#define EP93XX_I2S_GLCTRL 0x0C
39
40#define EP93XX_I2S_TXLINCTRLDATA 0x28
41#define EP93XX_I2S_TXCTRL 0x2C
42#define EP93XX_I2S_TXWRDLEN 0x30
43#define EP93XX_I2S_TX0EN 0x34
44
45#define EP93XX_I2S_RXLINCTRLDATA 0x58
46#define EP93XX_I2S_RXCTRL 0x5C
47#define EP93XX_I2S_RXWRDLEN 0x60
48#define EP93XX_I2S_RX0EN 0x64
49
50#define EP93XX_I2S_WRDLEN_16 (0 << 0)
51#define EP93XX_I2S_WRDLEN_24 (1 << 0)
52#define EP93XX_I2S_WRDLEN_32 (2 << 0)
53
54#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */
55
56#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */
57#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */
58#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */
59#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */
60#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */
61
62struct ep93xx_i2s_info {
63 struct clk *mclk;
64 struct clk *sclk;
65 struct clk *lrclk;
66 struct ep93xx_pcm_dma_params *dma_params;
67 struct resource *mem;
68 void __iomem *regs;
69};
70
71struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = {
72 [SNDRV_PCM_STREAM_PLAYBACK] = {
73 .name = "i2s-pcm-out",
74 .dma_port = EP93XX_DMA_M2P_PORT_I2S1,
75 },
76 [SNDRV_PCM_STREAM_CAPTURE] = {
77 .name = "i2s-pcm-in",
78 .dma_port = EP93XX_DMA_M2P_PORT_I2S1,
79 },
80};
81
82static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info,
83 unsigned reg, unsigned val)
84{
85 __raw_writel(val, info->regs + reg);
86}
87
88static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info,
89 unsigned reg)
90{
91 return __raw_readl(info->regs + reg);
92}
93
94static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream)
95{
96 unsigned base_reg;
97 int i;
98
99 if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
100 (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
101 /* Enable clocks */
102 clk_enable(info->mclk);
103 clk_enable(info->sclk);
104 clk_enable(info->lrclk);
105
106 /* Enable i2s */
107 ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1);
108 }
109
110 /* Enable fifos */
111 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
112 base_reg = EP93XX_I2S_TX0EN;
113 else
114 base_reg = EP93XX_I2S_RX0EN;
115 for (i = 0; i < 3; i++)
116 ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1);
117}
118
119static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
120{
121 unsigned base_reg;
122 int i;
123
124 /* Disable fifos */
125 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
126 base_reg = EP93XX_I2S_TX0EN;
127 else
128 base_reg = EP93XX_I2S_RX0EN;
129 for (i = 0; i < 3; i++)
130 ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0);
131
132 if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
133 (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
134 /* Disable i2s */
135 ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0);
136
137 /* Disable clocks */
138 clk_disable(info->lrclk);
139 clk_disable(info->sclk);
140 clk_disable(info->mclk);
141 }
142}
143
144static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
145 struct snd_soc_dai *dai)
146{
147 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
149 struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data;
150
151 snd_soc_dai_set_dma_data(cpu_dai, substream,
152 &info->dma_params[substream->stream]);
153 return 0;
154}
155
156static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
157 struct snd_soc_dai *dai)
158{
159 struct snd_soc_pcm_runtime *rtd = substream->private_data;
160 struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data;
161
162 ep93xx_i2s_disable(info, substream->stream);
163}
164
165static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
166 unsigned int fmt)
167{
168 struct ep93xx_i2s_info *info = cpu_dai->private_data;
169 unsigned int clk_cfg, lin_ctrl;
170
171 clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
172 lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA);
173
174 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
175 case SND_SOC_DAIFMT_I2S:
176 clk_cfg |= EP93XX_I2S_CLKCFG_REL;
177 lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
178 break;
179
180 case SND_SOC_DAIFMT_LEFT_J:
181 clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
182 lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
183 break;
184
185 case SND_SOC_DAIFMT_RIGHT_J:
186 clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
187 lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST;
188 break;
189
190 default:
191 return -EINVAL;
192 }
193
194 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
195 case SND_SOC_DAIFMT_CBS_CFS:
196 /* CPU is master */
197 clk_cfg |= EP93XX_I2S_CLKCFG_MASTER;
198 break;
199
200 case SND_SOC_DAIFMT_CBM_CFM:
201 /* Codec is master */
202 clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER;
203 break;
204
205 default:
206 return -EINVAL;
207 }
208
209 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
210 case SND_SOC_DAIFMT_NB_NF:
211 /* Negative bit clock, lrclk low on left word */
212 clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL);
213 break;
214
215 case SND_SOC_DAIFMT_NB_IF:
216 /* Negative bit clock, lrclk low on right word */
217 clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP;
218 clk_cfg |= EP93XX_I2S_CLKCFG_REL;
219 break;
220
221 case SND_SOC_DAIFMT_IB_NF:
222 /* Positive bit clock, lrclk low on left word */
223 clk_cfg |= EP93XX_I2S_CLKCFG_CKP;
224 clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
225 break;
226
227 case SND_SOC_DAIFMT_IB_IF:
228 /* Positive bit clock, lrclk low on right word */
229 clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL;
230 break;
231 }
232
233 /* Write new register values */
234 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg);
235 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg);
236 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl);
237 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl);
238 return 0;
239}
240
241static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
242 struct snd_pcm_hw_params *params,
243 struct snd_soc_dai *dai)
244{
245 struct snd_soc_pcm_runtime *rtd = substream->private_data;
246 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
247 struct ep93xx_i2s_info *info = cpu_dai->private_data;
248 unsigned word_len, div, sdiv, lrdiv;
249 int found = 0, err;
250
251 switch (params_format(params)) {
252 case SNDRV_PCM_FORMAT_S16_LE:
253 word_len = EP93XX_I2S_WRDLEN_16;
254 break;
255
256 case SNDRV_PCM_FORMAT_S24_LE:
257 word_len = EP93XX_I2S_WRDLEN_24;
258 break;
259
260 case SNDRV_PCM_FORMAT_S32_LE:
261 word_len = EP93XX_I2S_WRDLEN_32;
262 break;
263
264 default:
265 return -EINVAL;
266 }
267
268 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
269 ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len);
270 else
271 ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len);
272
273 /*
274 * Calculate the sdiv (bit clock) and lrdiv (left/right clock) values.
275 * If the lrclk is pulse length is larger than the word size, then the
276 * bit clock will be gated for the unused bits.
277 */
278 div = (clk_get_rate(info->mclk) / params_rate(params)) *
279 params_channels(params);
280 for (sdiv = 2; sdiv <= 4; sdiv += 2)
281 for (lrdiv = 32; lrdiv <= 128; lrdiv <<= 1)
282 if (sdiv * lrdiv == div) {
283 found = 1;
284 goto out;
285 }
286out:
287 if (!found)
288 return -EINVAL;
289
290 err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
291 if (err)
292 return err;
293
294 err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv);
295 if (err)
296 return err;
297
298 ep93xx_i2s_enable(info, substream->stream);
299 return 0;
300}
301
302static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
303 unsigned int freq, int dir)
304{
305 struct ep93xx_i2s_info *info = cpu_dai->private_data;
306
307 if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
308 return -EINVAL;
309
310 return clk_set_rate(info->mclk, freq);
311}
312
313#ifdef CONFIG_PM
314static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
315{
316 struct ep93xx_i2s_info *info = dai->private_data;
317
318 if (!dai->active)
319 return;
320
321 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
322 ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
323}
324
325static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
326{
327 struct ep93xx_i2s_info *info = dai->private_data;
328
329 if (!dai->active)
330 return;
331
332 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
333 ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
334}
335#else
336#define ep93xx_i2s_suspend NULL
337#define ep93xx_i2s_resume NULL
338#endif
339
340static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
341 .startup = ep93xx_i2s_startup,
342 .shutdown = ep93xx_i2s_shutdown,
343 .hw_params = ep93xx_i2s_hw_params,
344 .set_sysclk = ep93xx_i2s_set_sysclk,
345 .set_fmt = ep93xx_i2s_set_dai_fmt,
346};
347
348#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
349 SNDRV_PCM_FMTBIT_S24_LE | \
350 SNDRV_PCM_FMTBIT_S32_LE)
351
352struct snd_soc_dai ep93xx_i2s_dai = {
353 .name = "ep93xx-i2s",
354 .id = 0,
355 .symmetric_rates= 1,
356 .suspend = ep93xx_i2s_suspend,
357 .resume = ep93xx_i2s_resume,
358 .playback = {
359 .channels_min = 2,
360 .channels_max = 2,
361 .rates = SNDRV_PCM_RATE_8000_48000,
362 .formats = EP93XX_I2S_FORMATS,
363 },
364 .capture = {
365 .channels_min = 2,
366 .channels_max = 2,
367 .rates = SNDRV_PCM_RATE_8000_48000,
368 .formats = EP93XX_I2S_FORMATS,
369 },
370 .ops = &ep93xx_i2s_dai_ops,
371};
372EXPORT_SYMBOL_GPL(ep93xx_i2s_dai);
373
374static int ep93xx_i2s_probe(struct platform_device *pdev)
375{
376 struct ep93xx_i2s_info *info;
377 struct resource *res;
378 int err;
379
380 info = kzalloc(sizeof(struct ep93xx_i2s_info), GFP_KERNEL);
381 if (!info) {
382 err = -ENOMEM;
383 goto fail;
384 }
385
386 ep93xx_i2s_dai.dev = &pdev->dev;
387 ep93xx_i2s_dai.private_data = info;
388 info->dma_params = ep93xx_i2s_dma_params;
389
390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
391 if (!res) {
392 err = -ENODEV;
393 goto fail;
394 }
395
396 info->mem = request_mem_region(res->start, resource_size(res),
397 pdev->name);
398 if (!info->mem) {
399 err = -EBUSY;
400 goto fail;
401 }
402
403 info->regs = ioremap(info->mem->start, resource_size(info->mem));
404 if (!info->regs) {
405 err = -ENXIO;
406 goto fail_release_mem;
407 }
408
409 info->mclk = clk_get(&pdev->dev, "mclk");
410 if (IS_ERR(info->mclk)) {
411 err = PTR_ERR(info->mclk);
412 goto fail_unmap_mem;
413 }
414
415 info->sclk = clk_get(&pdev->dev, "sclk");
416 if (IS_ERR(info->sclk)) {
417 err = PTR_ERR(info->sclk);
418 goto fail_put_mclk;
419 }
420
421 info->lrclk = clk_get(&pdev->dev, "lrclk");
422 if (IS_ERR(info->lrclk)) {
423 err = PTR_ERR(info->lrclk);
424 goto fail_put_sclk;
425 }
426
427 err = snd_soc_register_dai(&ep93xx_i2s_dai);
428 if (err)
429 goto fail_put_lrclk;
430
431 return 0;
432
433fail_put_lrclk:
434 clk_put(info->lrclk);
435fail_put_sclk:
436 clk_put(info->sclk);
437fail_put_mclk:
438 clk_put(info->mclk);
439fail_unmap_mem:
440 iounmap(info->regs);
441fail_release_mem:
442 release_mem_region(info->mem->start, resource_size(info->mem));
443 kfree(info);
444fail:
445 return err;
446}
447
448static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
449{
450 struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data;
451
452 snd_soc_unregister_dai(&ep93xx_i2s_dai);
453 clk_put(info->lrclk);
454 clk_put(info->sclk);
455 clk_put(info->mclk);
456 iounmap(info->regs);
457 release_mem_region(info->mem->start, resource_size(info->mem));
458 kfree(info);
459 return 0;
460}
461
462static struct platform_driver ep93xx_i2s_driver = {
463 .probe = ep93xx_i2s_probe,
464 .remove = __devexit_p(ep93xx_i2s_remove),
465 .driver = {
466 .name = "ep93xx-i2s",
467 .owner = THIS_MODULE,
468 },
469};
470
471static int __init ep93xx_i2s_init(void)
472{
473 return platform_driver_register(&ep93xx_i2s_driver);
474}
475
476static void __exit ep93xx_i2s_exit(void)
477{
478 platform_driver_unregister(&ep93xx_i2s_driver);
479}
480
481module_init(ep93xx_i2s_init);
482module_exit(ep93xx_i2s_exit);
483
484MODULE_ALIAS("platform:ep93xx-i2s");
485MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
486MODULE_DESCRIPTION("EP93XX I2S driver");
487MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h
new file mode 100644
index 000000000000..3bd4ebfaa1de
--- /dev/null
+++ b/sound/soc/ep93xx/ep93xx-i2s.h
@@ -0,0 +1,18 @@
1/*
2 * linux/sound/soc/ep93xx-i2s.h
3 * EP93xx I2S driver
4 *
5 * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.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
13#ifndef _EP93XX_SND_SOC_I2S_H
14#define _EP93XX_SND_SOC_I2S_H
15
16extern struct snd_soc_dai ep93xx_i2s_dai;
17
18#endif /* _EP93XX_SND_SOC_I2S_H */
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
new file mode 100644
index 000000000000..4ba938400791
--- /dev/null
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -0,0 +1,319 @@
1/*
2 * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface
3 *
4 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
5 * Copyright (C) 2006 Applied Data Systems
6 *
7 * Rewritten for the SoC audio subsystem (Based on PXA2xx code):
8 * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/device.h>
18#include <linux/slab.h>
19#include <linux/dma-mapping.h>
20
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25
26#include <mach/dma.h>
27#include <mach/hardware.h>
28#include <mach/ep93xx-regs.h>
29
30#include "ep93xx-pcm.h"
31
32static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
33 .info = (SNDRV_PCM_INFO_MMAP |
34 SNDRV_PCM_INFO_MMAP_VALID |
35 SNDRV_PCM_INFO_INTERLEAVED |
36 SNDRV_PCM_INFO_BLOCK_TRANSFER),
37
38 .rates = SNDRV_PCM_RATE_8000_48000,
39 .rate_min = SNDRV_PCM_RATE_8000,
40 .rate_max = SNDRV_PCM_RATE_48000,
41
42 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
43 SNDRV_PCM_FMTBIT_S24_LE |
44 SNDRV_PCM_FMTBIT_S32_LE),
45
46 .buffer_bytes_max = 131072,
47 .period_bytes_min = 32,
48 .period_bytes_max = 32768,
49 .periods_min = 1,
50 .periods_max = 32,
51 .fifo_size = 32,
52};
53
54struct ep93xx_runtime_data
55{
56 struct ep93xx_dma_m2p_client cl;
57 struct ep93xx_pcm_dma_params *params;
58 int pointer_bytes;
59 struct tasklet_struct period_tasklet;
60 int periods;
61 struct ep93xx_dma_buffer buf[32];
62};
63
64static void ep93xx_pcm_period_elapsed(unsigned long data)
65{
66 struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
67 snd_pcm_period_elapsed(substream);
68}
69
70static void ep93xx_pcm_buffer_started(void *cookie,
71 struct ep93xx_dma_buffer *buf)
72{
73}
74
75static void ep93xx_pcm_buffer_finished(void *cookie,
76 struct ep93xx_dma_buffer *buf,
77 int bytes, int error)
78{
79 struct snd_pcm_substream *substream = cookie;
80 struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
81
82 if (buf == rtd->buf + rtd->periods - 1)
83 rtd->pointer_bytes = 0;
84 else
85 rtd->pointer_bytes += buf->size;
86
87 if (!error) {
88 ep93xx_dma_m2p_submit_recursive(&rtd->cl, buf);
89 tasklet_schedule(&rtd->period_tasklet);
90 } else {
91 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
92 }
93}
94
95static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
96{
97 struct snd_soc_pcm_runtime *soc_rtd = substream->private_data;
98 struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai;
99 struct ep93xx_pcm_dma_params *dma_params;
100 struct ep93xx_runtime_data *rtd;
101 int ret;
102
103 dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
104 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
105
106 rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
107 if (!rtd)
108 return -ENOMEM;
109
110 memset(&rtd->period_tasklet, 0, sizeof(rtd->period_tasklet));
111 rtd->period_tasklet.func = ep93xx_pcm_period_elapsed;
112 rtd->period_tasklet.data = (unsigned long)substream;
113
114 rtd->cl.name = dma_params->name;
115 rtd->cl.flags = dma_params->dma_port | EP93XX_DMA_M2P_IGNORE_ERROR |
116 ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
117 EP93XX_DMA_M2P_TX : EP93XX_DMA_M2P_RX);
118 rtd->cl.cookie = substream;
119 rtd->cl.buffer_started = ep93xx_pcm_buffer_started;
120 rtd->cl.buffer_finished = ep93xx_pcm_buffer_finished;
121 ret = ep93xx_dma_m2p_client_register(&rtd->cl);
122 if (ret < 0) {
123 kfree(rtd);
124 return ret;
125 }
126
127 substream->runtime->private_data = rtd;
128 return 0;
129}
130
131static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
132{
133 struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
134
135 ep93xx_dma_m2p_client_unregister(&rtd->cl);
136 kfree(rtd);
137 return 0;
138}
139
140static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
141 struct snd_pcm_hw_params *params)
142{
143 struct snd_pcm_runtime *runtime = substream->runtime;
144 struct ep93xx_runtime_data *rtd = runtime->private_data;
145 size_t totsize = params_buffer_bytes(params);
146 size_t period = params_period_bytes(params);
147 int i;
148
149 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
150 runtime->dma_bytes = totsize;
151
152 rtd->periods = (totsize + period - 1) / period;
153 for (i = 0; i < rtd->periods; i++) {
154 rtd->buf[i].bus_addr = runtime->dma_addr + (i * period);
155 rtd->buf[i].size = period;
156 if ((i + 1) * period > totsize)
157 rtd->buf[i].size = totsize - (i * period);
158 }
159
160 return 0;
161}
162
163static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
164{
165 snd_pcm_set_runtime_buffer(substream, NULL);
166 return 0;
167}
168
169static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
170{
171 struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
172 int ret;
173 int i;
174
175 ret = 0;
176 switch (cmd) {
177 case SNDRV_PCM_TRIGGER_START:
178 case SNDRV_PCM_TRIGGER_RESUME:
179 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
180 rtd->pointer_bytes = 0;
181 for (i = 0; i < rtd->periods; i++)
182 ep93xx_dma_m2p_submit(&rtd->cl, rtd->buf + i);
183 break;
184
185 case SNDRV_PCM_TRIGGER_STOP:
186 case SNDRV_PCM_TRIGGER_SUSPEND:
187 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
188 ep93xx_dma_m2p_flush(&rtd->cl);
189 break;
190
191 default:
192 ret = -EINVAL;
193 break;
194 }
195
196 return ret;
197}
198
199static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream)
200{
201 struct snd_pcm_runtime *runtime = substream->runtime;
202 struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
203
204 /* FIXME: implement this with sub-period granularity */
205 return bytes_to_frames(runtime, rtd->pointer_bytes);
206}
207
208static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
209 struct vm_area_struct *vma)
210{
211 struct snd_pcm_runtime *runtime = substream->runtime;
212
213 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
214 runtime->dma_area,
215 runtime->dma_addr,
216 runtime->dma_bytes);
217}
218
219static struct snd_pcm_ops ep93xx_pcm_ops = {
220 .open = ep93xx_pcm_open,
221 .close = ep93xx_pcm_close,
222 .ioctl = snd_pcm_lib_ioctl,
223 .hw_params = ep93xx_pcm_hw_params,
224 .hw_free = ep93xx_pcm_hw_free,
225 .trigger = ep93xx_pcm_trigger,
226 .pointer = ep93xx_pcm_pointer,
227 .mmap = ep93xx_pcm_mmap,
228};
229
230static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
231{
232 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
233 struct snd_dma_buffer *buf = &substream->dma_buffer;
234 size_t size = ep93xx_pcm_hardware.buffer_bytes_max;
235
236 buf->dev.type = SNDRV_DMA_TYPE_DEV;
237 buf->dev.dev = pcm->card->dev;
238 buf->private_data = NULL;
239 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
240 &buf->addr, GFP_KERNEL);
241 buf->bytes = size;
242
243 return (buf->area == NULL) ? -ENOMEM : 0;
244}
245
246static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
247{
248 struct snd_pcm_substream *substream;
249 struct snd_dma_buffer *buf;
250 int stream;
251
252 for (stream = 0; stream < 2; stream++) {
253 substream = pcm->streams[stream].substream;
254 if (!substream)
255 continue;
256
257 buf = &substream->dma_buffer;
258 if (!buf->area)
259 continue;
260
261 dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area,
262 buf->addr);
263 buf->area = NULL;
264 }
265}
266
267static u64 ep93xx_pcm_dmamask = 0xffffffff;
268
269static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
270 struct snd_pcm *pcm)
271{
272 int ret = 0;
273
274 if (!card->dev->dma_mask)
275 card->dev->dma_mask = &ep93xx_pcm_dmamask;
276 if (!card->dev->coherent_dma_mask)
277 card->dev->coherent_dma_mask = 0xffffffff;
278
279 if (dai->playback.channels_min) {
280 ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
281 SNDRV_PCM_STREAM_PLAYBACK);
282 if (ret)
283 return ret;
284 }
285
286 if (dai->capture.channels_min) {
287 ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
288 SNDRV_PCM_STREAM_CAPTURE);
289 if (ret)
290 return ret;
291 }
292
293 return 0;
294}
295
296struct snd_soc_platform ep93xx_soc_platform = {
297 .name = "ep93xx-audio",
298 .pcm_ops = &ep93xx_pcm_ops,
299 .pcm_new = &ep93xx_pcm_new,
300 .pcm_free = &ep93xx_pcm_free_dma_buffers,
301};
302EXPORT_SYMBOL_GPL(ep93xx_soc_platform);
303
304static int __init ep93xx_soc_platform_init(void)
305{
306 return snd_soc_register_platform(&ep93xx_soc_platform);
307}
308
309static void __exit ep93xx_soc_platform_exit(void)
310{
311 snd_soc_unregister_platform(&ep93xx_soc_platform);
312}
313
314module_init(ep93xx_soc_platform_init);
315module_exit(ep93xx_soc_platform_exit);
316
317MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
318MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
319MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h
new file mode 100644
index 000000000000..4ffdd3f62fe9
--- /dev/null
+++ b/sound/soc/ep93xx/ep93xx-pcm.h
@@ -0,0 +1,22 @@
1/*
2 * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface
3 *
4 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
5 * Copyright (C) 2006 Applied Data Systems
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 _EP93XX_SND_SOC_PCM_H
13#define _EP93XX_SND_SOC_PCM_H
14
15struct ep93xx_pcm_dma_params {
16 char *name;
17 int dma_port;
18};
19
20extern struct snd_soc_platform ep93xx_soc_platform;
21
22#endif /* _EP93XX_SND_SOC_PCM_H */
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
new file mode 100644
index 000000000000..64955340ff75
--- /dev/null
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -0,0 +1,150 @@
1/*
2 * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module
3 *
4 * Copyright (C) 2008 Bluewater Systems Ltd
5 * Author: Ryan Mallon <ryan@bluewatersys.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/platform_device.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/soc.h>
18#include <sound/soc-dapm.h>
19
20#include <asm/mach-types.h>
21#include <mach/hardware.h>
22
23#include "../codecs/tlv320aic23.h"
24#include "ep93xx-pcm.h"
25#include "ep93xx-i2s.h"
26
27#define CODEC_CLOCK 5644800
28
29static int snappercl15_hw_params(struct snd_pcm_substream *substream,
30 struct snd_pcm_hw_params *params)
31{
32 struct snd_soc_pcm_runtime *rtd = substream->private_data;
33 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
34 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
35 int err;
36
37 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
38 SND_SOC_DAIFMT_NB_IF |
39 SND_SOC_DAIFMT_CBS_CFS);
40
41 err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
42 SND_SOC_DAIFMT_NB_IF |
43 SND_SOC_DAIFMT_CBS_CFS);
44 if (err)
45 return err;
46
47 err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK,
48 SND_SOC_CLOCK_IN);
49 if (err)
50 return err;
51
52 err = snd_soc_dai_set_sysclk(cpu_dai, 0, CODEC_CLOCK,
53 SND_SOC_CLOCK_OUT);
54 if (err)
55 return err;
56
57 return 0;
58}
59
60static struct snd_soc_ops snappercl15_ops = {
61 .hw_params = snappercl15_hw_params,
62};
63
64static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
65 SND_SOC_DAPM_HP("Headphone Jack", NULL),
66 SND_SOC_DAPM_LINE("Line In", NULL),
67 SND_SOC_DAPM_MIC("Mic Jack", NULL),
68};
69
70static const struct snd_soc_dapm_route audio_map[] = {
71 {"Headphone Jack", NULL, "LHPOUT"},
72 {"Headphone Jack", NULL, "RHPOUT"},
73
74 {"LLINEIN", NULL, "Line In"},
75 {"RLINEIN", NULL, "Line In"},
76
77 {"MICIN", NULL, "Mic Jack"},
78};
79
80static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec)
81{
82 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
83 ARRAY_SIZE(tlv320aic23_dapm_widgets));
84
85 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
86 return 0;
87}
88
89static struct snd_soc_dai_link snappercl15_dai = {
90 .name = "tlv320aic23",
91 .stream_name = "AIC23",
92 .cpu_dai = &ep93xx_i2s_dai,
93 .codec_dai = &tlv320aic23_dai,
94 .init = snappercl15_tlv320aic23_init,
95 .ops = &snappercl15_ops,
96};
97
98static struct snd_soc_card snd_soc_snappercl15 = {
99 .name = "Snapper CL15",
100 .platform = &ep93xx_soc_platform,
101 .dai_link = &snappercl15_dai,
102 .num_links = 1,
103};
104
105static struct snd_soc_device snappercl15_snd_devdata = {
106 .card = &snd_soc_snappercl15,
107 .codec_dev = &soc_codec_dev_tlv320aic23,
108};
109
110static struct platform_device *snappercl15_snd_device;
111
112static int __init snappercl15_init(void)
113{
114 int ret;
115
116 if (!machine_is_snapper_cl15())
117 return -ENODEV;
118
119 ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
120 EP93XX_SYSCON_I2SCLKDIV_ORIDE |
121 EP93XX_SYSCON_I2SCLKDIV_SPOL);
122 if (ret)
123 return ret;
124
125 snappercl15_snd_device = platform_device_alloc("soc-audio", -1);
126 if (!snappercl15_snd_device)
127 return -ENOMEM;
128
129 platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata);
130 snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev;
131 ret = platform_device_add(snappercl15_snd_device);
132 if (ret)
133 platform_device_put(snappercl15_snd_device);
134
135 return ret;
136}
137
138static void __exit snappercl15_exit(void)
139{
140 platform_device_unregister(snappercl15_snd_device);
141 ep93xx_i2s_release();
142}
143
144module_init(snappercl15_init);
145module_exit(snappercl15_exit);
146
147MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
148MODULE_DESCRIPTION("ALSA SoC Snapper CL15");
149MODULE_LICENSE("GPL");
150
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 4f455bd6851f..676841cbae98 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -16,7 +16,6 @@
16 16
17#include <asm/mpc52xx_psc.h> 17#include <asm/mpc52xx_psc.h>
18 18
19#include "mpc5200_psc_i2s.h"
20#include "mpc5200_dma.h" 19#include "mpc5200_dma.h"
21 20
22/** 21/**
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.h b/sound/soc/fsl/mpc5200_psc_i2s.h
deleted file mode 100644
index ce55e070fdf3..000000000000
--- a/sound/soc/fsl/mpc5200_psc_i2s.h
+++ /dev/null
@@ -1,12 +0,0 @@
1/*
2 * Freescale MPC5200 PSC in I2S mode
3 * ALSA SoC Digital Audio Interface (DAI) driver
4 *
5 */
6
7#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_I2S_H__
8#define __SOUND_SOC_FSL_MPC52xx_PSC_I2S_H__
9
10extern struct snd_soc_dai psc_i2s_dai[];
11
12#endif /* __SOUND_SOC_FSL_MPC52xx_PSC_I2S_H__ */
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index 252defea93b5..52dac5e3874c 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -1,4 +1,4 @@
1config SND_IMX_SOC 1menuconfig SND_IMX_SOC
2 tristate "SoC Audio for Freescale i.MX CPUs" 2 tristate "SoC Audio for Freescale i.MX CPUs"
3 depends on ARCH_MXC 3 depends on ARCH_MXC
4 select SND_PCM 4 select SND_PCM
@@ -8,14 +8,12 @@ config SND_IMX_SOC
8 Say Y or M if you want to add support for codecs attached to 8 Say Y or M if you want to add support for codecs attached to
9 the i.MX SSI interface. 9 the i.MX SSI interface.
10 10
11config SND_MXC_SOC_SSI 11if SND_IMX_SOC
12 tristate
13 12
14config SND_MXC_SOC_WM1133_EV1 13config SND_MXC_SOC_WM1133_EV1
15 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" 14 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
16 depends on SND_IMX_SOC && MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL 15 depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
17 select SND_SOC_WM8350 16 select SND_SOC_WM8350
18 select SND_MXC_SOC_SSI
19 help 17 help
20 Enable support for audio on the i.MX31ADS with the WM1133-EV1 18 Enable support for audio on the i.MX31ADS with the WM1133-EV1
21 PMIC board with WM8835x fitted. 19 PMIC board with WM8835x fitted.
@@ -23,8 +21,17 @@ config SND_MXC_SOC_WM1133_EV1
23config SND_SOC_PHYCORE_AC97 21config SND_SOC_PHYCORE_AC97
24 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" 22 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
25 depends on MACH_PCM043 || MACH_PCA100 23 depends on MACH_PCM043 || MACH_PCA100
26 select SND_MXC_SOC_SSI
27 select SND_SOC_WM9712 24 select SND_SOC_WM9712
28 help 25 help
29 Say Y if you want to add support for SoC audio on Phytec phyCORE 26 Say Y if you want to add support for SoC audio on Phytec phyCORE
30 and phyCARD boards in AC97 mode 27 and phyCARD boards in AC97 mode
28
29config SND_SOC_EUKREA_TLV320
30 tristate "Eukrea TLV320"
31 depends on MACH_EUKREA_MBIMX27_BASEBOARD || MACH_EUKREA_MBIMXSD_BASEBOARD
32 select SND_SOC_TLV320AIC23
33 help
34 Enable I2S based access to the TLV320AIC23B codec attached
35 to the SSI interface
36
37endif # SND_IMX_SOC
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index 2d203635ac11..7bc57baf2b0e 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -8,8 +8,10 @@ endif
8obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o 8obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
9 9
10# i.MX Machine Support 10# i.MX Machine Support
11snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
11snd-soc-phycore-ac97-objs := phycore-ac97.o 12snd-soc-phycore-ac97-objs := phycore-ac97.o
12snd-soc-wm1133-ev1-objs := wm1133-ev1.o 13snd-soc-wm1133-ev1-objs := wm1133-ev1.o
13 14
15obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
14obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o 16obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
15obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o 17obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c
new file mode 100644
index 000000000000..f15dfbdc47ee
--- /dev/null
+++ b/sound/soc/imx/eukrea-tlv320.c
@@ -0,0 +1,137 @@
1/*
2 * eukrea-tlv320.c -- SoC audio for eukrea_cpuimxXX in I2S mode
3 *
4 * Copyright 2010 Eric Bénard, Eukréa Electromatique <eric@eukrea.com>
5 *
6 * based on sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
7 * which is Copyright 2009 Simtec Electronics
8 * and on sound/soc/imx/phycore-ac97.c which is
9 * Copyright 2009 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/device.h>
21#include <linux/i2c.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26#include <asm/mach-types.h>
27
28#include "../codecs/tlv320aic23.h"
29#include "imx-ssi.h"
30
31#define CODEC_CLOCK 12000000
32
33static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream,
34 struct snd_pcm_hw_params *params)
35{
36 struct snd_soc_pcm_runtime *rtd = substream->private_data;
37 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
38 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
39 int ret;
40
41 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
42 SND_SOC_DAIFMT_NB_NF |
43 SND_SOC_DAIFMT_CBM_CFM);
44 if (ret) {
45 pr_err("%s: failed set cpu dai format\n", __func__);
46 return ret;
47 }
48
49 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
50 SND_SOC_DAIFMT_NB_NF |
51 SND_SOC_DAIFMT_CBM_CFM);
52 if (ret) {
53 pr_err("%s: failed set codec dai format\n", __func__);
54 return ret;
55 }
56
57 ret = snd_soc_dai_set_sysclk(codec_dai, 0,
58 CODEC_CLOCK, SND_SOC_CLOCK_OUT);
59 if (ret) {
60 pr_err("%s: failed setting codec sysclk\n", __func__);
61 return ret;
62 }
63 snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0);
64
65 ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0,
66 SND_SOC_CLOCK_IN);
67 if (ret) {
68 pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n");
69 return ret;
70 }
71
72 return 0;
73}
74
75static struct snd_soc_ops eukrea_tlv320_snd_ops = {
76 .hw_params = eukrea_tlv320_hw_params,
77};
78
79static struct snd_soc_dai_link eukrea_tlv320_dai = {
80 .name = "tlv320aic23",
81 .stream_name = "TLV320AIC23",
82 .codec_dai = &tlv320aic23_dai,
83 .ops = &eukrea_tlv320_snd_ops,
84};
85
86static struct snd_soc_card eukrea_tlv320 = {
87 .name = "cpuimx-audio",
88 .platform = &imx_soc_platform,
89 .dai_link = &eukrea_tlv320_dai,
90 .num_links = 1,
91};
92
93static struct snd_soc_device eukrea_tlv320_snd_devdata = {
94 .card = &eukrea_tlv320,
95 .codec_dev = &soc_codec_dev_tlv320aic23,
96};
97
98static struct platform_device *eukrea_tlv320_snd_device;
99
100static int __init eukrea_tlv320_init(void)
101{
102 int ret;
103
104 if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd()
105 && !machine_is_eukrea_cpuimx35sd())
106 /* return happy. We might run on a totally different machine */
107 return 0;
108
109 eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1);
110 if (!eukrea_tlv320_snd_device)
111 return -ENOMEM;
112
113 eukrea_tlv320_dai.cpu_dai = &imx_ssi_pcm_dai[0];
114
115 platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320_snd_devdata);
116 eukrea_tlv320_snd_devdata.dev = &eukrea_tlv320_snd_device->dev;
117 ret = platform_device_add(eukrea_tlv320_snd_device);
118
119 if (ret) {
120 printk(KERN_ERR "ASoC: Platform device allocation failed\n");
121 platform_device_put(eukrea_tlv320_snd_device);
122 }
123
124 return ret;
125}
126
127static void __exit eukrea_tlv320_exit(void)
128{
129 platform_device_unregister(eukrea_tlv320_snd_device);
130}
131
132module_init(eukrea_tlv320_init);
133module_exit(eukrea_tlv320_exit);
134
135MODULE_AUTHOR("Eric Bénard <eric@eukrea.com>");
136MODULE_DESCRIPTION("CPUIMX ALSA SoC driver");
137MODULE_LICENSE("GPL");
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 05f19c9284f4..0a595da4811d 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -292,12 +292,16 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
292 int ret; 292 int ret;
293 293
294 iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); 294 iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
295 if (iprtd == NULL)
296 return -ENOMEM;
295 runtime->private_data = iprtd; 297 runtime->private_data = iprtd;
296 298
297 ret = snd_pcm_hw_constraint_integer(substream->runtime, 299 ret = snd_pcm_hw_constraint_integer(substream->runtime,
298 SNDRV_PCM_HW_PARAM_PERIODS); 300 SNDRV_PCM_HW_PARAM_PERIODS);
299 if (ret < 0) 301 if (ret < 0) {
302 kfree(iprtd);
300 return ret; 303 return ret;
304 }
301 305
302 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); 306 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
303 return 0; 307 return 0;
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index 6b518e07eea9..b2bf27282cd2 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -192,6 +192,8 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
192 int ret; 192 int ret;
193 193
194 iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); 194 iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
195 if (iprtd == NULL)
196 return -ENOMEM;
195 runtime->private_data = iprtd; 197 runtime->private_data = iprtd;
196 198
197 iprtd->substream = substream; 199 iprtd->substream = substream;
@@ -202,8 +204,10 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
202 204
203 ret = snd_pcm_hw_constraint_integer(substream->runtime, 205 ret = snd_pcm_hw_constraint_integer(substream->runtime,
204 SNDRV_PCM_HW_PARAM_PERIODS); 206 SNDRV_PCM_HW_PARAM_PERIODS);
205 if (ret < 0) 207 if (ret < 0) {
208 kfree(iprtd);
206 return ret; 209 return ret;
210 }
207 211
208 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); 212 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
209 return 0; 213 return 0;
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 4fd13d0791b8..a11daa1e905b 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -83,8 +83,6 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
83/* 83/*
84 * SSI DAI format configuration. 84 * SSI DAI format configuration.
85 * Should only be called when port is inactive (i.e. SSIEN = 0). 85 * Should only be called when port is inactive (i.e. SSIEN = 0).
86 * Note: We don't use the I2S modes but instead manually configure the
87 * SSI for I2S because the I2S mode is only a register preset.
88 */ 86 */
89static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) 87static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
90{ 88{
@@ -99,6 +97,10 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
99 /* data on rising edge of bclk, frame low 1clk before data */ 97 /* data on rising edge of bclk, frame low 1clk before data */
100 strcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0; 98 strcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0;
101 scr |= SSI_SCR_NET; 99 scr |= SSI_SCR_NET;
100 if (ssi->flags & IMX_SSI_USE_I2S_SLAVE) {
101 scr &= ~SSI_I2S_MODE_MASK;
102 scr |= SSI_SCR_I2S_MODE_SLAVE;
103 }
102 break; 104 break;
103 case SND_SOC_DAIFMT_LEFT_J: 105 case SND_SOC_DAIFMT_LEFT_J:
104 /* data on rising edge of bclk, frame high with data */ 106 /* data on rising edge of bclk, frame high with data */
@@ -143,6 +145,11 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
143 145
144 strcr |= SSI_STCR_TFEN0; 146 strcr |= SSI_STCR_TFEN0;
145 147
148 if (ssi->flags & IMX_SSI_NET)
149 scr |= SSI_SCR_NET;
150 if (ssi->flags & IMX_SSI_SYN)
151 scr |= SSI_SCR_SYN;
152
146 writel(strcr, ssi->base + SSI_STCR); 153 writel(strcr, ssi->base + SSI_STCR);
147 writel(strcr, ssi->base + SSI_SRCR); 154 writel(strcr, ssi->base + SSI_SRCR);
148 writel(scr, ssi->base + SSI_SCR); 155 writel(scr, ssi->base + SSI_SCR);
diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
new file mode 100644
index 000000000000..5351cba66c9e
--- /dev/null
+++ b/sound/soc/jz4740/Kconfig
@@ -0,0 +1,23 @@
1config SND_JZ4740_SOC
2 tristate "SoC Audio for Ingenic JZ4740 SoC"
3 depends on MACH_JZ4740 && SND_SOC
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the JZ4740 I2S interface. You will also need to select the audio
7 interfaces to support below.
8
9config SND_JZ4740_SOC_I2S
10 depends on SND_JZ4740_SOC
11 tristate "SoC Audio (I2S protocol) for Ingenic JZ4740 SoC"
12 help
13 Say Y if you want to use I2S protocol and I2S codec on Ingenic JZ4740
14 based boards.
15
16config SND_JZ4740_SOC_QI_LB60
17 tristate "SoC Audio support for Qi LB60"
18 depends on SND_JZ4740_SOC && JZ4740_QI_LB60
19 select SND_JZ4740_SOC_I2S
20 select SND_SOC_JZ4740_CODEC
21 help
22 Say Y if you want to add support for ASoC audio on the Qi LB60 board
23 a.k.a Qi Ben NanoNote.
diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
new file mode 100644
index 000000000000..be873c1b0c20
--- /dev/null
+++ b/sound/soc/jz4740/Makefile
@@ -0,0 +1,13 @@
1#
2# Jz4740 Platform Support
3#
4snd-soc-jz4740-objs := jz4740-pcm.o
5snd-soc-jz4740-i2s-objs := jz4740-i2s.o
6
7obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o
8obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
9
10# Jz4740 Machine Support
11snd-soc-qi-lb60-objs := qi_lb60.o
12
13obj-$(CONFIG_SND_JZ4740_SOC_QI_LB60) += snd-soc-qi-lb60.o
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
new file mode 100644
index 000000000000..eb518f0c5e01
--- /dev/null
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -0,0 +1,540 @@
1/*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * You should have received a copy of the GNU General Public License along
10 * with this program; if not, write to the Free Software Foundation, Inc.,
11 * 675 Mass Ave, Cambridge, MA 02139, USA.
12 *
13 */
14
15#include <linux/init.h>
16#include <linux/io.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/slab.h>
21
22#include <linux/clk.h>
23#include <linux/delay.h>
24
25#include <linux/dma-mapping.h>
26
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/initval.h>
33
34#include "jz4740-i2s.h"
35#include "jz4740-pcm.h"
36
37#define JZ_REG_AIC_CONF 0x00
38#define JZ_REG_AIC_CTRL 0x04
39#define JZ_REG_AIC_I2S_FMT 0x10
40#define JZ_REG_AIC_FIFO_STATUS 0x14
41#define JZ_REG_AIC_I2S_STATUS 0x1c
42#define JZ_REG_AIC_CLK_DIV 0x30
43#define JZ_REG_AIC_FIFO 0x34
44
45#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_MASK (0xf << 12)
46#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_MASK (0xf << 8)
47#define JZ_AIC_CONF_OVERFLOW_PLAY_LAST BIT(6)
48#define JZ_AIC_CONF_INTERNAL_CODEC BIT(5)
49#define JZ_AIC_CONF_I2S BIT(4)
50#define JZ_AIC_CONF_RESET BIT(3)
51#define JZ_AIC_CONF_BIT_CLK_MASTER BIT(2)
52#define JZ_AIC_CONF_SYNC_CLK_MASTER BIT(1)
53#define JZ_AIC_CONF_ENABLE BIT(0)
54
55#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12
56#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8
57
58#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19)
59#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16)
60#define JZ_AIC_CTRL_ENABLE_RX_DMA BIT(15)
61#define JZ_AIC_CTRL_ENABLE_TX_DMA BIT(14)
62#define JZ_AIC_CTRL_MONO_TO_STEREO BIT(11)
63#define JZ_AIC_CTRL_SWITCH_ENDIANNESS BIT(10)
64#define JZ_AIC_CTRL_SIGNED_TO_UNSIGNED BIT(9)
65#define JZ_AIC_CTRL_FLUSH BIT(8)
66#define JZ_AIC_CTRL_ENABLE_ROR_INT BIT(6)
67#define JZ_AIC_CTRL_ENABLE_TUR_INT BIT(5)
68#define JZ_AIC_CTRL_ENABLE_RFS_INT BIT(4)
69#define JZ_AIC_CTRL_ENABLE_TFS_INT BIT(3)
70#define JZ_AIC_CTRL_ENABLE_LOOPBACK BIT(2)
71#define JZ_AIC_CTRL_ENABLE_PLAYBACK BIT(1)
72#define JZ_AIC_CTRL_ENABLE_CAPTURE BIT(0)
73
74#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET 19
75#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET 16
76
77#define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12)
78#define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4)
79#define JZ_AIC_I2S_FMT_MSB BIT(0)
80
81#define JZ_AIC_I2S_STATUS_BUSY BIT(2)
82
83#define JZ_AIC_CLK_DIV_MASK 0xf
84
85struct jz4740_i2s {
86 struct resource *mem;
87 void __iomem *base;
88 dma_addr_t phys_base;
89
90 struct clk *clk_aic;
91 struct clk *clk_i2s;
92
93 struct jz4740_pcm_config pcm_config_playback;
94 struct jz4740_pcm_config pcm_config_capture;
95};
96
97static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s,
98 unsigned int reg)
99{
100 return readl(i2s->base + reg);
101}
102
103static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s,
104 unsigned int reg, uint32_t value)
105{
106 writel(value, i2s->base + reg);
107}
108
109static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai)
110{
111 return dai->private_data;
112}
113
114static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
115 struct snd_soc_dai *dai)
116{
117 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
118 uint32_t conf, ctrl;
119
120 if (dai->active)
121 return 0;
122
123 ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
124 ctrl |= JZ_AIC_CTRL_FLUSH;
125 jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
126
127 clk_enable(i2s->clk_i2s);
128
129 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
130 conf |= JZ_AIC_CONF_ENABLE;
131 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
132
133 return 0;
134}
135
136static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
137 struct snd_soc_dai *dai)
138{
139 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
140 uint32_t conf;
141
142 if (!dai->active)
143 return;
144
145 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
146 conf &= ~JZ_AIC_CONF_ENABLE;
147 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
148
149 clk_disable(i2s->clk_i2s);
150}
151
152static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
153 struct snd_soc_dai *dai)
154{
155 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
156
157 uint32_t ctrl;
158 uint32_t mask;
159
160 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
161 mask = JZ_AIC_CTRL_ENABLE_PLAYBACK | JZ_AIC_CTRL_ENABLE_TX_DMA;
162 else
163 mask = JZ_AIC_CTRL_ENABLE_CAPTURE | JZ_AIC_CTRL_ENABLE_RX_DMA;
164
165 ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
166
167 switch (cmd) {
168 case SNDRV_PCM_TRIGGER_START:
169 case SNDRV_PCM_TRIGGER_RESUME:
170 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
171 ctrl |= mask;
172 break;
173 case SNDRV_PCM_TRIGGER_STOP:
174 case SNDRV_PCM_TRIGGER_SUSPEND:
175 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
176 ctrl &= ~mask;
177 break;
178 default:
179 return -EINVAL;
180 }
181
182 jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
183
184 return 0;
185}
186
187static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
188{
189 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
190
191 uint32_t format = 0;
192 uint32_t conf;
193
194 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
195
196 conf &= ~(JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER);
197
198 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
199 case SND_SOC_DAIFMT_CBS_CFS:
200 conf |= JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER;
201 format |= JZ_AIC_I2S_FMT_ENABLE_SYS_CLK;
202 break;
203 case SND_SOC_DAIFMT_CBM_CFS:
204 conf |= JZ_AIC_CONF_SYNC_CLK_MASTER;
205 break;
206 case SND_SOC_DAIFMT_CBS_CFM:
207 conf |= JZ_AIC_CONF_BIT_CLK_MASTER;
208 break;
209 case SND_SOC_DAIFMT_CBM_CFM:
210 break;
211 default:
212 return -EINVAL;
213 }
214
215 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
216 case SND_SOC_DAIFMT_MSB:
217 format |= JZ_AIC_I2S_FMT_MSB;
218 break;
219 case SND_SOC_DAIFMT_I2S:
220 break;
221 default:
222 return -EINVAL;
223 }
224
225 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
226 case SND_SOC_DAIFMT_NB_NF:
227 break;
228 default:
229 return -EINVAL;
230 }
231
232 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
233 jz4740_i2s_write(i2s, JZ_REG_AIC_I2S_FMT, format);
234
235 return 0;
236}
237
238static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
239 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
240{
241 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
242 enum jz4740_dma_width dma_width;
243 struct jz4740_pcm_config *pcm_config;
244 unsigned int sample_size;
245 uint32_t ctrl;
246
247 ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL);
248
249 switch (params_format(params)) {
250 case SNDRV_PCM_FORMAT_S8:
251 sample_size = 0;
252 dma_width = JZ4740_DMA_WIDTH_8BIT;
253 break;
254 case SNDRV_PCM_FORMAT_S16:
255 sample_size = 1;
256 dma_width = JZ4740_DMA_WIDTH_16BIT;
257 break;
258 default:
259 return -EINVAL;
260 }
261
262 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
263 ctrl &= ~JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK;
264 ctrl |= sample_size << JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET;
265 if (params_channels(params) == 1)
266 ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO;
267 else
268 ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO;
269
270 pcm_config = &i2s->pcm_config_playback;
271 pcm_config->dma_config.dst_width = dma_width;
272
273 } else {
274 ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK;
275 ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET;
276
277 pcm_config = &i2s->pcm_config_capture;
278 pcm_config->dma_config.src_width = dma_width;
279 }
280
281 jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
282
283 snd_soc_dai_set_dma_data(dai, substream, pcm_config);
284
285 return 0;
286}
287
288static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
289 unsigned int freq, int dir)
290{
291 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
292 struct clk *parent;
293 int ret = 0;
294
295 switch (clk_id) {
296 case JZ4740_I2S_CLKSRC_EXT:
297 parent = clk_get(NULL, "ext");
298 clk_set_parent(i2s->clk_i2s, parent);
299 break;
300 case JZ4740_I2S_CLKSRC_PLL:
301 parent = clk_get(NULL, "pll half");
302 clk_set_parent(i2s->clk_i2s, parent);
303 ret = clk_set_rate(i2s->clk_i2s, freq);
304 break;
305 default:
306 return -EINVAL;
307 }
308 clk_put(parent);
309
310 return ret;
311}
312
313static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
314{
315 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
316 uint32_t conf;
317
318 if (dai->active) {
319 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
320 conf &= ~JZ_AIC_CONF_ENABLE;
321 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
322
323 clk_disable(i2s->clk_i2s);
324 }
325
326 clk_disable(i2s->clk_aic);
327
328 return 0;
329}
330
331static int jz4740_i2s_resume(struct snd_soc_dai *dai)
332{
333 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
334 uint32_t conf;
335
336 clk_enable(i2s->clk_aic);
337
338 if (dai->active) {
339 clk_enable(i2s->clk_i2s);
340
341 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
342 conf |= JZ_AIC_CONF_ENABLE;
343 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
344 }
345
346 return 0;
347}
348
349static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai)
350{
351 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
352 uint32_t conf;
353
354 conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
355 (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
356 JZ_AIC_CONF_OVERFLOW_PLAY_LAST |
357 JZ_AIC_CONF_I2S |
358 JZ_AIC_CONF_INTERNAL_CODEC;
359
360 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET);
361 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
362
363 return 0;
364}
365
366static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
367 .startup = jz4740_i2s_startup,
368 .shutdown = jz4740_i2s_shutdown,
369 .trigger = jz4740_i2s_trigger,
370 .hw_params = jz4740_i2s_hw_params,
371 .set_fmt = jz4740_i2s_set_fmt,
372 .set_sysclk = jz4740_i2s_set_sysclk,
373};
374
375#define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
376 SNDRV_PCM_FMTBIT_S16_LE)
377
378struct snd_soc_dai jz4740_i2s_dai = {
379 .name = "jz4740-i2s",
380 .probe = jz4740_i2s_probe,
381 .playback = {
382 .channels_min = 1,
383 .channels_max = 2,
384 .rates = SNDRV_PCM_RATE_8000_48000,
385 .formats = JZ4740_I2S_FMTS,
386 },
387 .capture = {
388 .channels_min = 2,
389 .channels_max = 2,
390 .rates = SNDRV_PCM_RATE_8000_48000,
391 .formats = JZ4740_I2S_FMTS,
392 },
393 .symmetric_rates = 1,
394 .ops = &jz4740_i2s_dai_ops,
395 .suspend = jz4740_i2s_suspend,
396 .resume = jz4740_i2s_resume,
397};
398EXPORT_SYMBOL_GPL(jz4740_i2s_dai);
399
400static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
401{
402 struct jz4740_dma_config *dma_config;
403
404 /* Playback */
405 dma_config = &i2s->pcm_config_playback.dma_config;
406 dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
407 dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
408 dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
409 dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
410 dma_config->mode = JZ4740_DMA_MODE_SINGLE;
411 i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
412
413 /* Capture */
414 dma_config = &i2s->pcm_config_capture.dma_config;
415 dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
416 dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
417 dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
418 dma_config->flags = JZ4740_DMA_DST_AUTOINC;
419 dma_config->mode = JZ4740_DMA_MODE_SINGLE;
420 i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
421}
422
423static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
424{
425 struct jz4740_i2s *i2s;
426 int ret;
427
428 i2s = kzalloc(sizeof(*i2s), GFP_KERNEL);
429
430 if (!i2s)
431 return -ENOMEM;
432
433 i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
434 if (!i2s->mem) {
435 ret = -ENOENT;
436 goto err_free;
437 }
438
439 i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem),
440 pdev->name);
441 if (!i2s->mem) {
442 ret = -EBUSY;
443 goto err_free;
444 }
445
446 i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem));
447 if (!i2s->base) {
448 ret = -EBUSY;
449 goto err_release_mem_region;
450 }
451
452 i2s->phys_base = i2s->mem->start;
453
454 i2s->clk_aic = clk_get(&pdev->dev, "aic");
455 if (IS_ERR(i2s->clk_aic)) {
456 ret = PTR_ERR(i2s->clk_aic);
457 goto err_iounmap;
458 }
459
460 i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
461 if (IS_ERR(i2s->clk_i2s)) {
462 ret = PTR_ERR(i2s->clk_i2s);
463 goto err_clk_put_aic;
464 }
465
466 clk_enable(i2s->clk_aic);
467
468 jz4740_i2c_init_pcm_config(i2s);
469
470 jz4740_i2s_dai.private_data = i2s;
471 ret = snd_soc_register_dai(&jz4740_i2s_dai);
472
473 if (ret) {
474 dev_err(&pdev->dev, "Failed to register DAI\n");
475 goto err_clk_put_i2s;
476 }
477
478 platform_set_drvdata(pdev, i2s);
479
480 return 0;
481
482err_clk_put_i2s:
483 clk_disable(i2s->clk_aic);
484 clk_put(i2s->clk_i2s);
485err_clk_put_aic:
486 clk_put(i2s->clk_aic);
487err_iounmap:
488 iounmap(i2s->base);
489err_release_mem_region:
490 release_mem_region(i2s->mem->start, resource_size(i2s->mem));
491err_free:
492 kfree(i2s);
493
494 return ret;
495}
496
497static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
498{
499 struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
500
501 snd_soc_unregister_dai(&jz4740_i2s_dai);
502
503 clk_disable(i2s->clk_aic);
504 clk_put(i2s->clk_i2s);
505 clk_put(i2s->clk_aic);
506
507 iounmap(i2s->base);
508 release_mem_region(i2s->mem->start, resource_size(i2s->mem));
509
510 platform_set_drvdata(pdev, NULL);
511 kfree(i2s);
512
513 return 0;
514}
515
516static struct platform_driver jz4740_i2s_driver = {
517 .probe = jz4740_i2s_dev_probe,
518 .remove = __devexit_p(jz4740_i2s_dev_remove),
519 .driver = {
520 .name = "jz4740-i2s",
521 .owner = THIS_MODULE,
522 },
523};
524
525static int __init jz4740_i2s_init(void)
526{
527 return platform_driver_register(&jz4740_i2s_driver);
528}
529module_init(jz4740_i2s_init);
530
531static void __exit jz4740_i2s_exit(void)
532{
533 platform_driver_unregister(&jz4740_i2s_driver);
534}
535module_exit(jz4740_i2s_exit);
536
537MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>");
538MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver");
539MODULE_LICENSE("GPL");
540MODULE_ALIAS("platform:jz4740-i2s");
diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h
new file mode 100644
index 000000000000..da22ed88a589
--- /dev/null
+++ b/sound/soc/jz4740/jz4740-i2s.h
@@ -0,0 +1,18 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 */
6
7#ifndef _JZ4740_I2S_H
8#define _JZ4740_I2S_H
9
10/* I2S clock source */
11#define JZ4740_I2S_CLKSRC_EXT 0
12#define JZ4740_I2S_CLKSRC_PLL 1
13
14#define JZ4740_I2S_BIT_CLK 0
15
16extern struct snd_soc_dai jz4740_i2s_dai;
17
18#endif
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
new file mode 100644
index 000000000000..ee68d850c8dd
--- /dev/null
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -0,0 +1,373 @@
1/*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * You should have received a copy of the GNU General Public License along
10 * with this program; if not, write to the Free Software Foundation, Inc.,
11 * 675 Mass Ave, Cambridge, MA 02139, USA.
12 *
13 */
14
15#include <linux/init.h>
16#include <linux/interrupt.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/slab.h>
21
22#include <linux/dma-mapping.h>
23
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28
29#include <asm/mach-jz4740/dma.h>
30#include "jz4740-pcm.h"
31
32struct jz4740_runtime_data {
33 unsigned long dma_period;
34 dma_addr_t dma_start;
35 dma_addr_t dma_pos;
36 dma_addr_t dma_end;
37
38 struct jz4740_dma_chan *dma;
39
40 dma_addr_t fifo_addr;
41};
42
43/* identify hardware playback capabilities */
44static const struct snd_pcm_hardware jz4740_pcm_hardware = {
45 .info = SNDRV_PCM_INFO_MMAP |
46 SNDRV_PCM_INFO_MMAP_VALID |
47 SNDRV_PCM_INFO_INTERLEAVED |
48 SNDRV_PCM_INFO_BLOCK_TRANSFER,
49 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
50
51 .rates = SNDRV_PCM_RATE_8000_48000,
52 .channels_min = 1,
53 .channels_max = 2,
54 .period_bytes_min = 16,
55 .period_bytes_max = 2 * PAGE_SIZE,
56 .periods_min = 2,
57 .periods_max = 128,
58 .buffer_bytes_max = 128 * 2 * PAGE_SIZE,
59 .fifo_size = 32,
60};
61
62static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd,
63 struct snd_pcm_substream *substream)
64{
65 unsigned long count;
66
67 if (prtd->dma_pos == prtd->dma_end)
68 prtd->dma_pos = prtd->dma_start;
69
70 if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
71 count = prtd->dma_end - prtd->dma_pos;
72 else
73 count = prtd->dma_period;
74
75 jz4740_dma_disable(prtd->dma);
76
77 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
78 jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos);
79 jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr);
80 } else {
81 jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr);
82 jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos);
83 }
84
85 jz4740_dma_set_transfer_count(prtd->dma, count);
86
87 prtd->dma_pos += count;
88
89 jz4740_dma_enable(prtd->dma);
90}
91
92static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err,
93 void *dev_id)
94{
95 struct snd_pcm_substream *substream = dev_id;
96 struct snd_pcm_runtime *runtime = substream->runtime;
97 struct jz4740_runtime_data *prtd = runtime->private_data;
98
99 snd_pcm_period_elapsed(substream);
100
101 jz4740_pcm_start_transfer(prtd, substream);
102}
103
104static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
105 struct snd_pcm_hw_params *params)
106{
107 struct snd_pcm_runtime *runtime = substream->runtime;
108 struct jz4740_runtime_data *prtd = runtime->private_data;
109 struct snd_soc_pcm_runtime *rtd = substream->private_data;
110 struct jz4740_pcm_config *config;
111
112 config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
113
114 if (!config)
115 return 0;
116
117 if (!prtd->dma) {
118 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
119 prtd->dma = jz4740_dma_request(substream, "PCM Capture");
120 else
121 prtd->dma = jz4740_dma_request(substream, "PCM Playback");
122 }
123
124 if (!prtd->dma)
125 return -EBUSY;
126
127 jz4740_dma_configure(prtd->dma, &config->dma_config);
128 prtd->fifo_addr = config->fifo_addr;
129
130 jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done);
131
132 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
133 runtime->dma_bytes = params_buffer_bytes(params);
134
135 prtd->dma_period = params_period_bytes(params);
136 prtd->dma_start = runtime->dma_addr;
137 prtd->dma_pos = prtd->dma_start;
138 prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
139
140 return 0;
141}
142
143static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream)
144{
145 struct jz4740_runtime_data *prtd = substream->runtime->private_data;
146
147 snd_pcm_set_runtime_buffer(substream, NULL);
148 if (prtd->dma) {
149 jz4740_dma_free(prtd->dma);
150 prtd->dma = NULL;
151 }
152
153 return 0;
154}
155
156static int jz4740_pcm_prepare(struct snd_pcm_substream *substream)
157{
158 struct jz4740_runtime_data *prtd = substream->runtime->private_data;
159
160 if (!prtd->dma)
161 return -EBUSY;
162
163 prtd->dma_pos = prtd->dma_start;
164
165 return 0;
166}
167
168static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
169{
170 struct snd_pcm_runtime *runtime = substream->runtime;
171 struct jz4740_runtime_data *prtd = runtime->private_data;
172
173 switch (cmd) {
174 case SNDRV_PCM_TRIGGER_START:
175 case SNDRV_PCM_TRIGGER_RESUME:
176 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
177 jz4740_pcm_start_transfer(prtd, substream);
178 break;
179 case SNDRV_PCM_TRIGGER_STOP:
180 case SNDRV_PCM_TRIGGER_SUSPEND:
181 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
182 jz4740_dma_disable(prtd->dma);
183 break;
184 default:
185 break;
186 }
187
188 return 0;
189}
190
191static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream)
192{
193 struct snd_pcm_runtime *runtime = substream->runtime;
194 struct jz4740_runtime_data *prtd = runtime->private_data;
195 unsigned long byte_offset;
196 snd_pcm_uframes_t offset;
197 struct jz4740_dma_chan *dma = prtd->dma;
198
199 /* prtd->dma_pos points to the end of the current transfer. So by
200 * subtracting prdt->dma_start we get the offset to the end of the
201 * current period in bytes. By subtracting the residue of the transfer
202 * we get the current offset in bytes. */
203 byte_offset = prtd->dma_pos - prtd->dma_start;
204 byte_offset -= jz4740_dma_get_residue(dma);
205
206 offset = bytes_to_frames(runtime, byte_offset);
207 if (offset >= runtime->buffer_size)
208 offset = 0;
209
210 return offset;
211}
212
213static int jz4740_pcm_open(struct snd_pcm_substream *substream)
214{
215 struct snd_pcm_runtime *runtime = substream->runtime;
216 struct jz4740_runtime_data *prtd;
217
218 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
219 if (prtd == NULL)
220 return -ENOMEM;
221
222 snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
223
224 runtime->private_data = prtd;
225
226 return 0;
227}
228
229static int jz4740_pcm_close(struct snd_pcm_substream *substream)
230{
231 struct snd_pcm_runtime *runtime = substream->runtime;
232 struct jz4740_runtime_data *prtd = runtime->private_data;
233
234 kfree(prtd);
235
236 return 0;
237}
238
239static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
240 struct vm_area_struct *vma)
241{
242 return remap_pfn_range(vma, vma->vm_start,
243 substream->dma_buffer.addr >> PAGE_SHIFT,
244 vma->vm_end - vma->vm_start, vma->vm_page_prot);
245}
246
247static struct snd_pcm_ops jz4740_pcm_ops = {
248 .open = jz4740_pcm_open,
249 .close = jz4740_pcm_close,
250 .ioctl = snd_pcm_lib_ioctl,
251 .hw_params = jz4740_pcm_hw_params,
252 .hw_free = jz4740_pcm_hw_free,
253 .prepare = jz4740_pcm_prepare,
254 .trigger = jz4740_pcm_trigger,
255 .pointer = jz4740_pcm_pointer,
256 .mmap = jz4740_pcm_mmap,
257};
258
259static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
260{
261 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
262 struct snd_dma_buffer *buf = &substream->dma_buffer;
263 size_t size = jz4740_pcm_hardware.buffer_bytes_max;
264
265 buf->dev.type = SNDRV_DMA_TYPE_DEV;
266 buf->dev.dev = pcm->card->dev;
267 buf->private_data = NULL;
268
269 buf->area = dma_alloc_noncoherent(pcm->card->dev, size,
270 &buf->addr, GFP_KERNEL);
271 if (!buf->area)
272 return -ENOMEM;
273
274 buf->bytes = size;
275
276 return 0;
277}
278
279static void jz4740_pcm_free(struct snd_pcm *pcm)
280{
281 struct snd_pcm_substream *substream;
282 struct snd_dma_buffer *buf;
283 int stream;
284
285 for (stream = 0; stream < SNDRV_PCM_STREAM_LAST; ++stream) {
286 substream = pcm->streams[stream].substream;
287 if (!substream)
288 continue;
289
290 buf = &substream->dma_buffer;
291 if (!buf->area)
292 continue;
293
294 dma_free_noncoherent(pcm->card->dev, buf->bytes, buf->area,
295 buf->addr);
296 buf->area = NULL;
297 }
298}
299
300static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
301
302int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
303 struct snd_pcm *pcm)
304{
305 int ret = 0;
306
307 if (!card->dev->dma_mask)
308 card->dev->dma_mask = &jz4740_pcm_dmamask;
309
310 if (!card->dev->coherent_dma_mask)
311 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
312
313 if (dai->playback.channels_min) {
314 ret = jz4740_pcm_preallocate_dma_buffer(pcm,
315 SNDRV_PCM_STREAM_PLAYBACK);
316 if (ret)
317 goto err;
318 }
319
320 if (dai->capture.channels_min) {
321 ret = jz4740_pcm_preallocate_dma_buffer(pcm,
322 SNDRV_PCM_STREAM_CAPTURE);
323 if (ret)
324 goto err;
325 }
326
327err:
328 return ret;
329}
330
331struct snd_soc_platform jz4740_soc_platform = {
332 .name = "jz4740-pcm",
333 .pcm_ops = &jz4740_pcm_ops,
334 .pcm_new = jz4740_pcm_new,
335 .pcm_free = jz4740_pcm_free,
336};
337EXPORT_SYMBOL_GPL(jz4740_soc_platform);
338
339static int __devinit jz4740_pcm_probe(struct platform_device *pdev)
340{
341 return snd_soc_register_platform(&jz4740_soc_platform);
342}
343
344static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
345{
346 snd_soc_unregister_platform(&jz4740_soc_platform);
347 return 0;
348}
349
350static struct platform_driver jz4740_pcm_driver = {
351 .probe = jz4740_pcm_probe,
352 .remove = __devexit_p(jz4740_pcm_remove),
353 .driver = {
354 .name = "jz4740-pcm",
355 .owner = THIS_MODULE,
356 },
357};
358
359static int __init jz4740_soc_platform_init(void)
360{
361 return platform_driver_register(&jz4740_pcm_driver);
362}
363module_init(jz4740_soc_platform_init);
364
365static void __exit jz4740_soc_platform_exit(void)
366{
367 return platform_driver_unregister(&jz4740_pcm_driver);
368}
369module_exit(jz4740_soc_platform_exit);
370
371MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
372MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
373MODULE_LICENSE("GPL");
diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h
new file mode 100644
index 000000000000..e3f221e2779c
--- /dev/null
+++ b/sound/soc/jz4740/jz4740-pcm.h
@@ -0,0 +1,22 @@
1/*
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8#ifndef _JZ4740_PCM_H
9#define _JZ4740_PCM_H
10
11#include <linux/dma-mapping.h>
12#include <asm/mach-jz4740/dma.h>
13
14/* platform data */
15extern struct snd_soc_platform jz4740_soc_platform;
16
17struct jz4740_pcm_config {
18 struct jz4740_dma_config dma_config;
19 phys_addr_t fifo_addr;
20};
21
22#endif
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
new file mode 100644
index 000000000000..f15f4918f15f
--- /dev/null
+++ b/sound/soc/jz4740/qi_lb60.c
@@ -0,0 +1,166 @@
1/*
2 * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
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 * You should have received a copy of the GNU General Public License along
9 * with this program; if not, write to the Free Software Foundation, Inc.,
10 * 675 Mass Ave, Cambridge, MA 02139, USA.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/timer.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23#include <linux/gpio.h>
24
25#include "../codecs/jz4740.h"
26#include "jz4740-pcm.h"
27#include "jz4740-i2s.h"
28
29
30#define QI_LB60_SND_GPIO JZ_GPIO_PORTB(29)
31#define QI_LB60_AMP_GPIO JZ_GPIO_PORTD(4)
32
33static int qi_lb60_spk_event(struct snd_soc_dapm_widget *widget,
34 struct snd_kcontrol *ctrl, int event)
35{
36 int on = 0;
37 if (event & SND_SOC_DAPM_POST_PMU)
38 on = 1;
39 else if (event & SND_SOC_DAPM_PRE_PMD)
40 on = 0;
41
42 gpio_set_value(QI_LB60_SND_GPIO, on);
43 gpio_set_value(QI_LB60_AMP_GPIO, on);
44
45 return 0;
46}
47
48static const struct snd_soc_dapm_widget qi_lb60_widgets[] = {
49 SND_SOC_DAPM_SPK("Speaker", qi_lb60_spk_event),
50 SND_SOC_DAPM_MIC("Mic", NULL),
51};
52
53static const struct snd_soc_dapm_route qi_lb60_routes[] = {
54 {"Mic", NULL, "MIC"},
55 {"Speaker", NULL, "LOUT"},
56 {"Speaker", NULL, "ROUT"},
57};
58
59#define QI_LB60_DAIFMT (SND_SOC_DAIFMT_I2S | \
60 SND_SOC_DAIFMT_NB_NF | \
61 SND_SOC_DAIFMT_CBM_CFM)
62
63static int qi_lb60_codec_init(struct snd_soc_codec *codec)
64{
65 int ret;
66 struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;
67
68 snd_soc_dapm_nc_pin(codec, "LIN");
69 snd_soc_dapm_nc_pin(codec, "RIN");
70
71 ret = snd_soc_dai_set_fmt(cpu_dai, QI_LB60_DAIFMT);
72 if (ret < 0) {
73 dev_err(codec->dev, "Failed to set cpu dai format: %d\n", ret);
74 return ret;
75 }
76
77 snd_soc_dapm_new_controls(codec, qi_lb60_widgets, ARRAY_SIZE(qi_lb60_widgets));
78 snd_soc_dapm_add_routes(codec, qi_lb60_routes, ARRAY_SIZE(qi_lb60_routes));
79 snd_soc_dapm_sync(codec);
80
81 return 0;
82}
83
84static struct snd_soc_dai_link qi_lb60_dai = {
85 .name = "jz4740",
86 .stream_name = "jz4740",
87 .cpu_dai = &jz4740_i2s_dai,
88 .codec_dai = &jz4740_codec_dai,
89 .init = qi_lb60_codec_init,
90};
91
92static struct snd_soc_card qi_lb60 = {
93 .name = "QI LB60",
94 .dai_link = &qi_lb60_dai,
95 .num_links = 1,
96 .platform = &jz4740_soc_platform,
97};
98
99static struct snd_soc_device qi_lb60_snd_devdata = {
100 .card = &qi_lb60,
101 .codec_dev = &soc_codec_dev_jz4740_codec,
102};
103
104static struct platform_device *qi_lb60_snd_device;
105
106static int __init qi_lb60_init(void)
107{
108 int ret;
109
110 qi_lb60_snd_device = platform_device_alloc("soc-audio", -1);
111
112 if (!qi_lb60_snd_device)
113 return -ENOMEM;
114
115 ret = gpio_request(QI_LB60_SND_GPIO, "SND");
116 if (ret) {
117 pr_err("qi_lb60 snd: Failed to request SND GPIO(%d): %d\n",
118 QI_LB60_SND_GPIO, ret);
119 goto err_device_put;
120 }
121
122 ret = gpio_request(QI_LB60_AMP_GPIO, "AMP");
123 if (ret) {
124 pr_err("qi_lb60 snd: Failed to request AMP GPIO(%d): %d\n",
125 QI_LB60_AMP_GPIO, ret);
126 goto err_gpio_free_snd;
127 }
128
129 gpio_direction_output(QI_LB60_SND_GPIO, 0);
130 gpio_direction_output(QI_LB60_AMP_GPIO, 0);
131
132 platform_set_drvdata(qi_lb60_snd_device, &qi_lb60_snd_devdata);
133 qi_lb60_snd_devdata.dev = &qi_lb60_snd_device->dev;
134
135 ret = platform_device_add(qi_lb60_snd_device);
136 if (ret) {
137 pr_err("qi_lb60 snd: Failed to add snd soc device: %d\n", ret);
138 goto err_unset_pdata;
139 }
140
141 return 0;
142
143err_unset_pdata:
144 platform_set_drvdata(qi_lb60_snd_device, NULL);
145/*err_gpio_free_amp:*/
146 gpio_free(QI_LB60_AMP_GPIO);
147err_gpio_free_snd:
148 gpio_free(QI_LB60_SND_GPIO);
149err_device_put:
150 platform_device_put(qi_lb60_snd_device);
151
152 return ret;
153}
154module_init(qi_lb60_init);
155
156static void __exit qi_lb60_exit(void)
157{
158 gpio_free(QI_LB60_AMP_GPIO);
159 gpio_free(QI_LB60_SND_GPIO);
160 platform_device_unregister(qi_lb60_snd_device);
161}
162module_exit(qi_lb60_exit);
163
164MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
165MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support");
166MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
new file mode 100644
index 000000000000..16ec2a2dba4d
--- /dev/null
+++ b/sound/soc/kirkwood/Kconfig
@@ -0,0 +1,20 @@
1config SND_KIRKWOOD_SOC
2 tristate "SoC Audio for the Marvell Kirkwood chip"
3 depends on ARCH_KIRKWOOD
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the Kirkwood I2S interface. You will also need to select the
7 audio interfaces to support below.
8
9config SND_KIRKWOOD_SOC_I2S
10 tristate
11
12config SND_KIRKWOOD_SOC_OPENRD
13 tristate "SoC Audio support for Kirkwood Openrd Client"
14 depends on SND_KIRKWOOD_SOC && MACH_OPENRD_CLIENT
15 select SND_KIRKWOOD_SOC_I2S
16 select SND_SOC_CS42L51
17 help
18 Say Y if you want to add support for SoC audio on
19 Openrd Client.
20
diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile
new file mode 100644
index 000000000000..33a16dcab5b5
--- /dev/null
+++ b/sound/soc/kirkwood/Makefile
@@ -0,0 +1,9 @@
1snd-soc-kirkwood-objs := kirkwood-dma.o
2snd-soc-kirkwood-i2s-objs := kirkwood-i2s.o
3
4obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o
5obj-$(CONFIG_SND_KIRKWOOD_SOC_I2S) += snd-soc-kirkwood-i2s.o
6
7snd-soc-openrd-objs := kirkwood-openrd.o
8
9obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
new file mode 100644
index 000000000000..a30205be3e2b
--- /dev/null
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -0,0 +1,383 @@
1/*
2 * kirkwood-dma.c
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/io.h>
16#include <linux/slab.h>
17#include <linux/interrupt.h>
18#include <linux/dma-mapping.h>
19#include <linux/mbus.h>
20#include <sound/soc.h>
21#include "kirkwood-dma.h"
22#include "kirkwood.h"
23
24#define KIRKWOOD_RATES \
25 (SNDRV_PCM_RATE_44100 | \
26 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
27#define KIRKWOOD_FORMATS \
28 (SNDRV_PCM_FMTBIT_S16_LE | \
29 SNDRV_PCM_FMTBIT_S24_LE | \
30 SNDRV_PCM_FMTBIT_S32_LE)
31
32struct kirkwood_dma_priv {
33 struct snd_pcm_substream *play_stream;
34 struct snd_pcm_substream *rec_stream;
35 struct kirkwood_dma_data *data;
36};
37
38static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
39 .info = (SNDRV_PCM_INFO_INTERLEAVED |
40 SNDRV_PCM_INFO_MMAP |
41 SNDRV_PCM_INFO_MMAP_VALID |
42 SNDRV_PCM_INFO_BLOCK_TRANSFER |
43 SNDRV_PCM_INFO_PAUSE),
44 .formats = KIRKWOOD_FORMATS,
45 .rates = KIRKWOOD_RATES,
46 .rate_min = 44100,
47 .rate_max = 96000,
48 .channels_min = 1,
49 .channels_max = 2,
50 .buffer_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS,
51 .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES,
52 .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES,
53 .periods_min = KIRKWOOD_SND_MIN_PERIODS,
54 .periods_max = KIRKWOOD_SND_MAX_PERIODS,
55 .fifo_size = 0,
56};
57
58static u64 kirkwood_dma_dmamask = 0xFFFFFFFFUL;
59
60static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
61{
62 struct kirkwood_dma_priv *prdata = dev_id;
63 struct kirkwood_dma_data *priv = prdata->data;
64 unsigned long mask, status, cause;
65
66 mask = readl(priv->io + KIRKWOOD_INT_MASK);
67 status = readl(priv->io + KIRKWOOD_INT_CAUSE) & mask;
68
69 cause = readl(priv->io + KIRKWOOD_ERR_CAUSE);
70 if (unlikely(cause)) {
71 printk(KERN_WARNING "%s: got err interrupt 0x%lx\n",
72 __func__, cause);
73 writel(cause, priv->io + KIRKWOOD_ERR_CAUSE);
74 return IRQ_HANDLED;
75 }
76
77 /* we've enabled only bytes interrupts ... */
78 if (status & ~(KIRKWOOD_INT_CAUSE_PLAY_BYTES | \
79 KIRKWOOD_INT_CAUSE_REC_BYTES)) {
80 printk(KERN_WARNING "%s: unexpected interrupt %lx\n",
81 __func__, status);
82 return IRQ_NONE;
83 }
84
85 /* ack int */
86 writel(status, priv->io + KIRKWOOD_INT_CAUSE);
87
88 if (status & KIRKWOOD_INT_CAUSE_PLAY_BYTES)
89 snd_pcm_period_elapsed(prdata->play_stream);
90
91 if (status & KIRKWOOD_INT_CAUSE_REC_BYTES)
92 snd_pcm_period_elapsed(prdata->rec_stream);
93
94 return IRQ_HANDLED;
95}
96
97static void kirkwood_dma_conf_mbus_windows(void __iomem *base, int win,
98 unsigned long dma,
99 struct mbus_dram_target_info *dram)
100{
101 int i;
102
103 /* First disable and clear windows */
104 writel(0, base + KIRKWOOD_AUDIO_WIN_CTRL_REG(win));
105 writel(0, base + KIRKWOOD_AUDIO_WIN_BASE_REG(win));
106
107 /* try to find matching cs for current dma address */
108 for (i = 0; i < dram->num_cs; i++) {
109 struct mbus_dram_window *cs = dram->cs + i;
110 if ((cs->base & 0xffff0000) < (dma & 0xffff0000)) {
111 writel(cs->base & 0xffff0000,
112 base + KIRKWOOD_AUDIO_WIN_BASE_REG(win));
113 writel(((cs->size - 1) & 0xffff0000) |
114 (cs->mbus_attr << 8) |
115 (dram->mbus_dram_target_id << 4) | 1,
116 base + KIRKWOOD_AUDIO_WIN_CTRL_REG(win));
117 }
118 }
119}
120
121static int kirkwood_dma_open(struct snd_pcm_substream *substream)
122{
123 int err;
124 struct snd_pcm_runtime *runtime = substream->runtime;
125 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
126 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai;
127 struct kirkwood_dma_data *priv;
128 struct kirkwood_dma_priv *prdata = cpu_dai->private_data;
129 unsigned long addr;
130
131 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
132 snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw);
133
134 /* Ensure that all constraints linked to dma burst are fullfilled */
135 err = snd_pcm_hw_constraint_minmax(runtime,
136 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
137 priv->burst * 2,
138 KIRKWOOD_AUDIO_BUF_MAX-1);
139 if (err < 0)
140 return err;
141
142 err = snd_pcm_hw_constraint_step(runtime, 0,
143 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
144 priv->burst);
145 if (err < 0)
146 return err;
147
148 err = snd_pcm_hw_constraint_step(substream->runtime, 0,
149 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
150 priv->burst);
151 if (err < 0)
152 return err;
153
154 if (soc_runtime->dai->cpu_dai->private_data == NULL) {
155 prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL);
156 if (prdata == NULL)
157 return -ENOMEM;
158
159 prdata->data = priv;
160
161 err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED,
162 "kirkwood-i2s", prdata);
163 if (err) {
164 kfree(prdata);
165 return -EBUSY;
166 }
167
168 soc_runtime->dai->cpu_dai->private_data = prdata;
169
170 /*
171 * Enable Error interrupts. We're only ack'ing them but
172 * it's usefull for diagnostics
173 */
174 writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK);
175 }
176
177 addr = virt_to_phys(substream->dma_buffer.area);
178 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
179 prdata->play_stream = substream;
180 kirkwood_dma_conf_mbus_windows(priv->io,
181 KIRKWOOD_PLAYBACK_WIN, addr, priv->dram);
182 } else {
183 prdata->rec_stream = substream;
184 kirkwood_dma_conf_mbus_windows(priv->io,
185 KIRKWOOD_RECORD_WIN, addr, priv->dram);
186 }
187
188 return 0;
189}
190
191static int kirkwood_dma_close(struct snd_pcm_substream *substream)
192{
193 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
194 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai;
195 struct kirkwood_dma_priv *prdata = cpu_dai->private_data;
196 struct kirkwood_dma_data *priv;
197
198 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
199
200 if (!prdata || !priv)
201 return 0;
202
203 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
204 prdata->play_stream = NULL;
205 else
206 prdata->rec_stream = NULL;
207
208 if (!prdata->play_stream && !prdata->rec_stream) {
209 writel(0, priv->io + KIRKWOOD_ERR_MASK);
210 free_irq(priv->irq, prdata);
211 kfree(prdata);
212 soc_runtime->dai->cpu_dai->private_data = NULL;
213 }
214
215 return 0;
216}
217
218static int kirkwood_dma_hw_params(struct snd_pcm_substream *substream,
219 struct snd_pcm_hw_params *params)
220{
221 struct snd_pcm_runtime *runtime = substream->runtime;
222
223 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
224 runtime->dma_bytes = params_buffer_bytes(params);
225
226 return 0;
227}
228
229static int kirkwood_dma_hw_free(struct snd_pcm_substream *substream)
230{
231 snd_pcm_set_runtime_buffer(substream, NULL);
232 return 0;
233}
234
235static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
236{
237 struct snd_pcm_runtime *runtime = substream->runtime;
238 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
239 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai;
240 struct kirkwood_dma_data *priv;
241 unsigned long size, count;
242
243 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
244
245 /* compute buffer size in term of "words" as requested in specs */
246 size = frames_to_bytes(runtime, runtime->buffer_size);
247 size = (size>>2)-1;
248 count = snd_pcm_lib_period_bytes(substream);
249
250 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
251 writel(count, priv->io + KIRKWOOD_PLAY_BYTE_INT_COUNT);
252 writel(runtime->dma_addr, priv->io + KIRKWOOD_PLAY_BUF_ADDR);
253 writel(size, priv->io + KIRKWOOD_PLAY_BUF_SIZE);
254 } else {
255 writel(count, priv->io + KIRKWOOD_REC_BYTE_INT_COUNT);
256 writel(runtime->dma_addr, priv->io + KIRKWOOD_REC_BUF_ADDR);
257 writel(size, priv->io + KIRKWOOD_REC_BUF_SIZE);
258 }
259
260
261 return 0;
262}
263
264static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream
265 *substream)
266{
267 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
268 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai;
269 struct kirkwood_dma_data *priv;
270 snd_pcm_uframes_t count;
271
272 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
273
274 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
275 count = bytes_to_frames(substream->runtime,
276 readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT));
277 else
278 count = bytes_to_frames(substream->runtime,
279 readl(priv->io + KIRKWOOD_REC_BYTE_COUNT));
280
281 return count;
282}
283
284struct snd_pcm_ops kirkwood_dma_ops = {
285 .open = kirkwood_dma_open,
286 .close = kirkwood_dma_close,
287 .ioctl = snd_pcm_lib_ioctl,
288 .hw_params = kirkwood_dma_hw_params,
289 .hw_free = kirkwood_dma_hw_free,
290 .prepare = kirkwood_dma_prepare,
291 .pointer = kirkwood_dma_pointer,
292};
293
294static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm,
295 int stream)
296{
297 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
298 struct snd_dma_buffer *buf = &substream->dma_buffer;
299 size_t size = kirkwood_dma_snd_hw.buffer_bytes_max;
300
301 buf->dev.type = SNDRV_DMA_TYPE_DEV;
302 buf->dev.dev = pcm->card->dev;
303 buf->area = dma_alloc_coherent(pcm->card->dev, size,
304 &buf->addr, GFP_KERNEL);
305 if (!buf->area)
306 return -ENOMEM;
307 buf->bytes = size;
308 buf->private_data = NULL;
309
310 return 0;
311}
312
313static int kirkwood_dma_new(struct snd_card *card,
314 struct snd_soc_dai *dai, struct snd_pcm *pcm)
315{
316 int ret;
317
318 if (!card->dev->dma_mask)
319 card->dev->dma_mask = &kirkwood_dma_dmamask;
320 if (!card->dev->coherent_dma_mask)
321 card->dev->coherent_dma_mask = 0xffffffff;
322
323 if (dai->playback.channels_min) {
324 ret = kirkwood_dma_preallocate_dma_buffer(pcm,
325 SNDRV_PCM_STREAM_PLAYBACK);
326 if (ret)
327 return ret;
328 }
329
330 if (dai->capture.channels_min) {
331 ret = kirkwood_dma_preallocate_dma_buffer(pcm,
332 SNDRV_PCM_STREAM_CAPTURE);
333 if (ret)
334 return ret;
335 }
336
337 return 0;
338}
339
340static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm)
341{
342 struct snd_pcm_substream *substream;
343 struct snd_dma_buffer *buf;
344 int stream;
345
346 for (stream = 0; stream < 2; stream++) {
347 substream = pcm->streams[stream].substream;
348 if (!substream)
349 continue;
350 buf = &substream->dma_buffer;
351 if (!buf->area)
352 continue;
353
354 dma_free_coherent(pcm->card->dev, buf->bytes,
355 buf->area, buf->addr);
356 buf->area = NULL;
357 }
358}
359
360struct snd_soc_platform kirkwood_soc_platform = {
361 .name = "kirkwood-dma",
362 .pcm_ops = &kirkwood_dma_ops,
363 .pcm_new = kirkwood_dma_new,
364 .pcm_free = kirkwood_dma_free_dma_buffers,
365};
366EXPORT_SYMBOL_GPL(kirkwood_soc_platform);
367
368static int __init kirkwood_soc_platform_init(void)
369{
370 return snd_soc_register_platform(&kirkwood_soc_platform);
371}
372module_init(kirkwood_soc_platform_init);
373
374static void __exit kirkwood_soc_platform_exit(void)
375{
376 snd_soc_unregister_platform(&kirkwood_soc_platform);
377}
378module_exit(kirkwood_soc_platform_exit);
379
380MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
381MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module");
382MODULE_LICENSE("GPL");
383
diff --git a/sound/soc/kirkwood/kirkwood-dma.h b/sound/soc/kirkwood/kirkwood-dma.h
new file mode 100644
index 000000000000..ba4454cd34f1
--- /dev/null
+++ b/sound/soc/kirkwood/kirkwood-dma.h
@@ -0,0 +1,17 @@
1/*
2 * kirkwood-dma.h
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#ifndef _KIRKWOOD_DMA_H
13#define _KIRKWOOD_DMA_H
14
15extern struct snd_soc_platform kirkwood_soc_platform;
16
17#endif
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
new file mode 100644
index 000000000000..981ffc2a13c8
--- /dev/null
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -0,0 +1,495 @@
1/*
2 * kirkwood-i2s.c
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/io.h>
16#include <linux/slab.h>
17#include <linux/mbus.h>
18#include <linux/delay.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <plat/audio.h>
23#include "kirkwood-i2s.h"
24#include "kirkwood.h"
25
26#define DRV_NAME "kirkwood-i2s"
27
28#define KIRKWOOD_I2S_RATES \
29 (SNDRV_PCM_RATE_44100 | \
30 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
31#define KIRKWOOD_I2S_FORMATS \
32 (SNDRV_PCM_FMTBIT_S16_LE | \
33 SNDRV_PCM_FMTBIT_S24_LE | \
34 SNDRV_PCM_FMTBIT_S32_LE)
35
36
37struct snd_soc_dai kirkwood_i2s_dai;
38static struct kirkwood_dma_data *priv;
39
40static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
41 unsigned int fmt)
42{
43 unsigned long mask;
44 unsigned long value;
45
46 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
47 case SND_SOC_DAIFMT_RIGHT_J:
48 mask = KIRKWOOD_I2S_CTL_RJ;
49 break;
50 case SND_SOC_DAIFMT_LEFT_J:
51 mask = KIRKWOOD_I2S_CTL_LJ;
52 break;
53 case SND_SOC_DAIFMT_I2S:
54 mask = KIRKWOOD_I2S_CTL_I2S;
55 break;
56 default:
57 return -EINVAL;
58 }
59
60 /*
61 * Set same format for playback and record
62 * This avoids some troubles.
63 */
64 value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL);
65 value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
66 value |= mask;
67 writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL);
68
69 value = readl(priv->io+KIRKWOOD_I2S_RECCTL);
70 value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
71 value |= mask;
72 writel(value, priv->io+KIRKWOOD_I2S_RECCTL);
73
74 return 0;
75}
76
77static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
78{
79 unsigned long value;
80
81 value = KIRKWOOD_DCO_CTL_OFFSET_0;
82 switch (rate) {
83 default:
84 case 44100:
85 value |= KIRKWOOD_DCO_CTL_FREQ_11;
86 break;
87 case 48000:
88 value |= KIRKWOOD_DCO_CTL_FREQ_12;
89 break;
90 case 96000:
91 value |= KIRKWOOD_DCO_CTL_FREQ_24;
92 break;
93 }
94 writel(value, io + KIRKWOOD_DCO_CTL);
95
96 /* wait for dco locked */
97 do {
98 cpu_relax();
99 value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
100 value &= KIRKWOOD_DCO_SPCR_STATUS;
101 } while (value == 0);
102}
103
104static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
105 struct snd_pcm_hw_params *params,
106 struct snd_soc_dai *dai)
107{
108 unsigned int i2s_reg, reg;
109 unsigned long i2s_value, value;
110
111 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
112 i2s_reg = KIRKWOOD_I2S_PLAYCTL;
113 reg = KIRKWOOD_PLAYCTL;
114 } else {
115 i2s_reg = KIRKWOOD_I2S_RECCTL;
116 reg = KIRKWOOD_RECCTL;
117 }
118
119 /* set dco conf */
120 kirkwood_set_dco(priv->io, params_rate(params));
121
122 i2s_value = readl(priv->io+i2s_reg);
123 i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
124
125 value = readl(priv->io+reg);
126 value &= ~KIRKWOOD_PLAYCTL_SIZE_MASK;
127
128 /*
129 * Size settings in play/rec i2s control regs and play/rec control
130 * regs must be the same.
131 */
132 switch (params_format(params)) {
133 case SNDRV_PCM_FORMAT_S16_LE:
134 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
135 value |= KIRKWOOD_PLAYCTL_SIZE_16_C;
136 break;
137 /*
138 * doesn't work... S20_3LE != kirkwood 20bit format ?
139 *
140 case SNDRV_PCM_FORMAT_S20_3LE:
141 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
142 value |= KIRKWOOD_PLAYCTL_SIZE_20;
143 break;
144 */
145 case SNDRV_PCM_FORMAT_S24_LE:
146 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
147 value |= KIRKWOOD_PLAYCTL_SIZE_24;
148 break;
149 case SNDRV_PCM_FORMAT_S32_LE:
150 i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
151 value |= KIRKWOOD_PLAYCTL_SIZE_32;
152 break;
153 default:
154 return -EINVAL;
155 }
156
157 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
158 value &= ~KIRKWOOD_PLAYCTL_MONO_MASK;
159 if (params_channels(params) == 1)
160 value |= KIRKWOOD_PLAYCTL_MONO_BOTH;
161 else
162 value |= KIRKWOOD_PLAYCTL_MONO_OFF;
163 }
164
165 writel(i2s_value, priv->io+i2s_reg);
166 writel(value, priv->io+reg);
167
168 return 0;
169}
170
171static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
172 int cmd, struct snd_soc_dai *dai)
173{
174 unsigned long value;
175
176 /*
177 * specs says KIRKWOOD_PLAYCTL must be read 2 times before
178 * changing it. So read 1 time here and 1 later.
179 */
180 value = readl(priv->io + KIRKWOOD_PLAYCTL);
181
182 switch (cmd) {
183 case SNDRV_PCM_TRIGGER_START:
184 /* stop audio, enable interrupts */
185 value = readl(priv->io + KIRKWOOD_PLAYCTL);
186 value |= KIRKWOOD_PLAYCTL_PAUSE;
187 writel(value, priv->io + KIRKWOOD_PLAYCTL);
188
189 value = readl(priv->io + KIRKWOOD_INT_MASK);
190 value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
191 writel(value, priv->io + KIRKWOOD_INT_MASK);
192
193 /* configure audio & enable i2s playback */
194 value = readl(priv->io + KIRKWOOD_PLAYCTL);
195 value &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
196 value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
197 | KIRKWOOD_PLAYCTL_SPDIF_EN);
198
199 if (priv->burst == 32)
200 value |= KIRKWOOD_PLAYCTL_BURST_32;
201 else
202 value |= KIRKWOOD_PLAYCTL_BURST_128;
203 value |= KIRKWOOD_PLAYCTL_I2S_EN;
204 writel(value, priv->io + KIRKWOOD_PLAYCTL);
205 break;
206
207 case SNDRV_PCM_TRIGGER_STOP:
208 /* stop audio, disable interrupts */
209 value = readl(priv->io + KIRKWOOD_PLAYCTL);
210 value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
211 writel(value, priv->io + KIRKWOOD_PLAYCTL);
212
213 value = readl(priv->io + KIRKWOOD_INT_MASK);
214 value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
215 writel(value, priv->io + KIRKWOOD_INT_MASK);
216
217 /* disable all playbacks */
218 value = readl(priv->io + KIRKWOOD_PLAYCTL);
219 value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
220 writel(value, priv->io + KIRKWOOD_PLAYCTL);
221 break;
222
223 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
224 case SNDRV_PCM_TRIGGER_SUSPEND:
225 value = readl(priv->io + KIRKWOOD_PLAYCTL);
226 value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
227 writel(value, priv->io + KIRKWOOD_PLAYCTL);
228 break;
229
230 case SNDRV_PCM_TRIGGER_RESUME:
231 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
232 value = readl(priv->io + KIRKWOOD_PLAYCTL);
233 value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
234 writel(value, priv->io + KIRKWOOD_PLAYCTL);
235 break;
236
237 default:
238 return -EINVAL;
239 }
240
241 return 0;
242}
243
244static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
245 int cmd, struct snd_soc_dai *dai)
246{
247 unsigned long value;
248
249 value = readl(priv->io + KIRKWOOD_RECCTL);
250
251 switch (cmd) {
252 case SNDRV_PCM_TRIGGER_START:
253 /* stop audio, enable interrupts */
254 value = readl(priv->io + KIRKWOOD_RECCTL);
255 value |= KIRKWOOD_RECCTL_PAUSE;
256 writel(value, priv->io + KIRKWOOD_RECCTL);
257
258 value = readl(priv->io + KIRKWOOD_INT_MASK);
259 value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
260 writel(value, priv->io + KIRKWOOD_INT_MASK);
261
262 /* configure audio & enable i2s record */
263 value = readl(priv->io + KIRKWOOD_RECCTL);
264 value &= ~KIRKWOOD_RECCTL_BURST_MASK;
265 value &= ~KIRKWOOD_RECCTL_MONO;
266 value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE
267 | KIRKWOOD_RECCTL_SPDIF_EN);
268
269 if (priv->burst == 32)
270 value |= KIRKWOOD_RECCTL_BURST_32;
271 else
272 value |= KIRKWOOD_RECCTL_BURST_128;
273 value |= KIRKWOOD_RECCTL_I2S_EN;
274
275 writel(value, priv->io + KIRKWOOD_RECCTL);
276 break;
277
278 case SNDRV_PCM_TRIGGER_STOP:
279 /* stop audio, disable interrupts */
280 value = readl(priv->io + KIRKWOOD_RECCTL);
281 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
282 writel(value, priv->io + KIRKWOOD_RECCTL);
283
284 value = readl(priv->io + KIRKWOOD_INT_MASK);
285 value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES;
286 writel(value, priv->io + KIRKWOOD_INT_MASK);
287
288 /* disable all records */
289 value = readl(priv->io + KIRKWOOD_RECCTL);
290 value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN);
291 writel(value, priv->io + KIRKWOOD_RECCTL);
292 break;
293
294 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
295 case SNDRV_PCM_TRIGGER_SUSPEND:
296 value = readl(priv->io + KIRKWOOD_RECCTL);
297 value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
298 writel(value, priv->io + KIRKWOOD_RECCTL);
299 break;
300
301 case SNDRV_PCM_TRIGGER_RESUME:
302 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
303 value = readl(priv->io + KIRKWOOD_RECCTL);
304 value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE);
305 writel(value, priv->io + KIRKWOOD_RECCTL);
306 break;
307
308 default:
309 return -EINVAL;
310 }
311
312 return 0;
313}
314
315static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
316 struct snd_soc_dai *dai)
317{
318 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
319 return kirkwood_i2s_play_trigger(substream, cmd, dai);
320 else
321 return kirkwood_i2s_rec_trigger(substream, cmd, dai);
322
323 return 0;
324}
325
326static int kirkwood_i2s_probe(struct platform_device *pdev,
327 struct snd_soc_dai *dai)
328{
329 unsigned long value;
330 unsigned int reg_data;
331
332 /* put system in a "safe" state : */
333 /* disable audio interrupts */
334 writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
335 writel(0, priv->io + KIRKWOOD_INT_MASK);
336
337 reg_data = readl(priv->io + 0x1200);
338 reg_data &= (~(0x333FF8));
339 reg_data |= 0x111D18;
340 writel(reg_data, priv->io + 0x1200);
341
342 msleep(500);
343
344 reg_data = readl(priv->io + 0x1200);
345 reg_data &= (~(0x333FF8));
346 reg_data |= 0x111D18;
347 writel(reg_data, priv->io + 0x1200);
348
349 /* disable playback/record */
350 value = readl(priv->io + KIRKWOOD_PLAYCTL);
351 value &= ~(KIRKWOOD_PLAYCTL_I2S_EN|KIRKWOOD_PLAYCTL_SPDIF_EN);
352 writel(value, priv->io + KIRKWOOD_PLAYCTL);
353
354 value = readl(priv->io + KIRKWOOD_RECCTL);
355 value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN);
356 writel(value, priv->io + KIRKWOOD_RECCTL);
357
358 return 0;
359
360}
361
362static void kirkwood_i2s_remove(struct platform_device *pdev,
363 struct snd_soc_dai *dai)
364{
365}
366
367static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
368 .trigger = kirkwood_i2s_trigger,
369 .hw_params = kirkwood_i2s_hw_params,
370 .set_fmt = kirkwood_i2s_set_fmt,
371};
372
373
374struct snd_soc_dai kirkwood_i2s_dai = {
375 .name = DRV_NAME,
376 .id = 0,
377 .probe = kirkwood_i2s_probe,
378 .remove = kirkwood_i2s_remove,
379 .playback = {
380 .channels_min = 1,
381 .channels_max = 2,
382 .rates = KIRKWOOD_I2S_RATES,
383 .formats = KIRKWOOD_I2S_FORMATS,},
384 .capture = {
385 .channels_min = 1,
386 .channels_max = 2,
387 .rates = KIRKWOOD_I2S_RATES,
388 .formats = KIRKWOOD_I2S_FORMATS,},
389 .ops = &kirkwood_i2s_dai_ops,
390};
391EXPORT_SYMBOL_GPL(kirkwood_i2s_dai);
392
393static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
394{
395 struct resource *mem;
396 struct kirkwood_asoc_platform_data *data =
397 pdev->dev.platform_data;
398 int err;
399
400 priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL);
401 if (!priv) {
402 dev_err(&pdev->dev, "allocation failed\n");
403 err = -ENOMEM;
404 goto error;
405 }
406
407 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
408 if (!mem) {
409 dev_err(&pdev->dev, "platform_get_resource failed\n");
410 err = -ENXIO;
411 goto err_alloc;
412 }
413
414 priv->mem = request_mem_region(mem->start, SZ_16K, DRV_NAME);
415 if (!priv->mem) {
416 dev_err(&pdev->dev, "request_mem_region failed\n");
417 err = -EBUSY;
418 goto error;
419 }
420
421 priv->io = ioremap(priv->mem->start, SZ_16K);
422 if (!priv->io) {
423 dev_err(&pdev->dev, "ioremap failed\n");
424 err = -ENOMEM;
425 goto err_iomem;
426 }
427
428 priv->irq = platform_get_irq(pdev, 0);
429 if (priv->irq <= 0) {
430 dev_err(&pdev->dev, "platform_get_irq failed\n");
431 err = -ENXIO;
432 goto err_ioremap;
433 }
434
435 if (!data || !data->dram) {
436 dev_err(&pdev->dev, "no platform data ?!\n");
437 err = -EINVAL;
438 goto err_ioremap;
439 }
440
441 priv->dram = data->dram;
442 priv->burst = data->burst;
443
444 kirkwood_i2s_dai.capture.dma_data = priv;
445 kirkwood_i2s_dai.playback.dma_data = priv;
446
447 return snd_soc_register_dai(&kirkwood_i2s_dai);
448
449err_ioremap:
450 iounmap(priv->io);
451err_iomem:
452 release_mem_region(priv->mem->start, SZ_16K);
453err_alloc:
454 kfree(priv);
455error:
456 return err;
457}
458
459static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
460{
461 if (priv) {
462 iounmap(priv->io);
463 release_mem_region(priv->mem->start, SZ_16K);
464 kfree(priv);
465 }
466 snd_soc_unregister_dai(&kirkwood_i2s_dai);
467 return 0;
468}
469
470static struct platform_driver kirkwood_i2s_driver = {
471 .probe = kirkwood_i2s_dev_probe,
472 .remove = kirkwood_i2s_dev_remove,
473 .driver = {
474 .name = DRV_NAME,
475 .owner = THIS_MODULE,
476 },
477};
478
479static int __init kirkwood_i2s_init(void)
480{
481 return platform_driver_register(&kirkwood_i2s_driver);
482}
483module_init(kirkwood_i2s_init);
484
485static void __exit kirkwood_i2s_exit(void)
486{
487 platform_driver_unregister(&kirkwood_i2s_driver);
488}
489module_exit(kirkwood_i2s_exit);
490
491/* Module information */
492MODULE_AUTHOR("Arnaud Patard, <apatard@mandriva.com>");
493MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
494MODULE_LICENSE("GPL");
495MODULE_ALIAS("platform:kirkwood-i2s");
diff --git a/sound/soc/kirkwood/kirkwood-i2s.h b/sound/soc/kirkwood/kirkwood-i2s.h
new file mode 100644
index 000000000000..c5595c616d7a
--- /dev/null
+++ b/sound/soc/kirkwood/kirkwood-i2s.h
@@ -0,0 +1,17 @@
1/*
2 * kirkwood-i2s.h
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#ifndef _KIRKWOOD_I2S_H
13#define _KIRKWOOD_I2S_H
14
15extern struct snd_soc_dai kirkwood_i2s_dai;
16
17#endif
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
new file mode 100644
index 000000000000..0353d06bc41a
--- /dev/null
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -0,0 +1,126 @@
1/*
2 * kirkwood-openrd.c
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/interrupt.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <sound/soc.h>
18#include <mach/kirkwood.h>
19#include <plat/audio.h>
20#include <asm/mach-types.h>
21#include "kirkwood-i2s.h"
22#include "kirkwood-dma.h"
23#include "../codecs/cs42l51.h"
24
25static int openrd_client_hw_params(struct snd_pcm_substream *substream,
26 struct snd_pcm_hw_params *params)
27{
28 struct snd_soc_pcm_runtime *rtd = substream->private_data;
29 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
30 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
31 int ret;
32 unsigned int freq, fmt;
33
34 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
35 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
36 if (ret < 0)
37 return ret;
38
39 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
40 if (ret < 0)
41 return ret;
42
43 switch (params_rate(params)) {
44 default:
45 case 44100:
46 freq = 11289600;
47 break;
48 case 48000:
49 freq = 12288000;
50 break;
51 case 96000:
52 freq = 24576000;
53 break;
54 }
55
56 return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN);
57
58}
59
60static struct snd_soc_ops openrd_client_ops = {
61 .hw_params = openrd_client_hw_params,
62};
63
64
65static struct snd_soc_dai_link openrd_client_dai[] = {
66{
67 .name = "CS42L51",
68 .stream_name = "CS42L51 HiFi",
69 .cpu_dai = &kirkwood_i2s_dai,
70 .codec_dai = &cs42l51_dai,
71 .ops = &openrd_client_ops,
72},
73};
74
75
76static struct snd_soc_card openrd_client = {
77 .name = "OpenRD Client",
78 .platform = &kirkwood_soc_platform,
79 .dai_link = openrd_client_dai,
80 .num_links = ARRAY_SIZE(openrd_client_dai),
81};
82
83static struct snd_soc_device openrd_client_snd_devdata = {
84 .card = &openrd_client,
85 .codec_dev = &soc_codec_device_cs42l51,
86};
87
88static struct platform_device *openrd_client_snd_device;
89
90static int __init openrd_client_init(void)
91{
92 int ret;
93
94 if (!machine_is_openrd_client())
95 return 0;
96
97 openrd_client_snd_device = platform_device_alloc("soc-audio", -1);
98 if (!openrd_client_snd_device)
99 return -ENOMEM;
100
101 platform_set_drvdata(openrd_client_snd_device,
102 &openrd_client_snd_devdata);
103 openrd_client_snd_devdata.dev = &openrd_client_snd_device->dev;
104
105 ret = platform_device_add(openrd_client_snd_device);
106 if (ret) {
107 printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
108 platform_device_put(openrd_client_snd_device);
109 }
110
111 return ret;
112}
113
114static void __exit openrd_client_exit(void)
115{
116 platform_device_unregister(openrd_client_snd_device);
117}
118
119module_init(openrd_client_init);
120module_exit(openrd_client_exit);
121
122/* Module information */
123MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
124MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
125MODULE_LICENSE("GPL");
126MODULE_ALIAS("platform:soc-audio");
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h
new file mode 100644
index 000000000000..bb6e6a5648c9
--- /dev/null
+++ b/sound/soc/kirkwood/kirkwood.h
@@ -0,0 +1,129 @@
1/*
2 * kirkwood.h
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#ifndef _KIRKWOOD_AUDIO_H
13#define _KIRKWOOD_AUDIO_H
14
15#define KIRKWOOD_RECORD_WIN 0
16#define KIRKWOOD_PLAYBACK_WIN 1
17#define KIRKWOOD_MAX_AUDIO_WIN 2
18
19#define KIRKWOOD_AUDIO_WIN_BASE_REG(win) (0xA00 + ((win)<<3))
20#define KIRKWOOD_AUDIO_WIN_CTRL_REG(win) (0xA04 + ((win)<<3))
21
22
23#define KIRKWOOD_RECCTL 0x1000
24#define KIRKWOOD_RECCTL_SPDIF_EN (1<<11)
25#define KIRKWOOD_RECCTL_I2S_EN (1<<10)
26#define KIRKWOOD_RECCTL_PAUSE (1<<9)
27#define KIRKWOOD_RECCTL_MUTE (1<<8)
28#define KIRKWOOD_RECCTL_BURST_MASK (3<<5)
29#define KIRKWOOD_RECCTL_BURST_128 (2<<5)
30#define KIRKWOOD_RECCTL_BURST_32 (1<<5)
31#define KIRKWOOD_RECCTL_MONO (1<<4)
32#define KIRKWOOD_RECCTL_MONO_CHAN_RIGHT (1<<3)
33#define KIRKWOOD_RECCTL_MONO_CHAN_LEFT (0<<3)
34#define KIRKWOOD_RECCTL_SIZE_MASK (7<<0)
35#define KIRKWOOD_RECCTL_SIZE_16 (7<<0)
36#define KIRKWOOD_RECCTL_SIZE_16_C (3<<0)
37#define KIRKWOOD_RECCTL_SIZE_20 (2<<0)
38#define KIRKWOOD_RECCTL_SIZE_24 (1<<0)
39#define KIRKWOOD_RECCTL_SIZE_32 (0<<0)
40
41#define KIRKWOOD_REC_BUF_ADDR 0x1004
42#define KIRKWOOD_REC_BUF_SIZE 0x1008
43#define KIRKWOOD_REC_BYTE_COUNT 0x100C
44
45#define KIRKWOOD_PLAYCTL 0x1100
46#define KIRKWOOD_PLAYCTL_PLAY_BUSY (1<<16)
47#define KIRKWOOD_PLAYCTL_BURST_MASK (3<<11)
48#define KIRKWOOD_PLAYCTL_BURST_128 (2<<11)
49#define KIRKWOOD_PLAYCTL_BURST_32 (1<<11)
50#define KIRKWOOD_PLAYCTL_PAUSE (1<<9)
51#define KIRKWOOD_PLAYCTL_SPDIF_MUTE (1<<8)
52#define KIRKWOOD_PLAYCTL_MONO_MASK (3<<5)
53#define KIRKWOOD_PLAYCTL_MONO_BOTH (3<<5)
54#define KIRKWOOD_PLAYCTL_MONO_OFF (0<<5)
55#define KIRKWOOD_PLAYCTL_I2S_MUTE (1<<7)
56#define KIRKWOOD_PLAYCTL_SPDIF_EN (1<<4)
57#define KIRKWOOD_PLAYCTL_I2S_EN (1<<3)
58#define KIRKWOOD_PLAYCTL_SIZE_MASK (7<<0)
59#define KIRKWOOD_PLAYCTL_SIZE_16 (7<<0)
60#define KIRKWOOD_PLAYCTL_SIZE_16_C (3<<0)
61#define KIRKWOOD_PLAYCTL_SIZE_20 (2<<0)
62#define KIRKWOOD_PLAYCTL_SIZE_24 (1<<0)
63#define KIRKWOOD_PLAYCTL_SIZE_32 (0<<0)
64
65#define KIRKWOOD_PLAY_BUF_ADDR 0x1104
66#define KIRKWOOD_PLAY_BUF_SIZE 0x1108
67#define KIRKWOOD_PLAY_BYTE_COUNT 0x110C
68
69#define KIRKWOOD_DCO_CTL 0x1204
70#define KIRKWOOD_DCO_CTL_OFFSET_MASK (0xFFF<<2)
71#define KIRKWOOD_DCO_CTL_OFFSET_0 (0x800<<2)
72#define KIRKWOOD_DCO_CTL_FREQ_MASK (3<<0)
73#define KIRKWOOD_DCO_CTL_FREQ_11 (0<<0)
74#define KIRKWOOD_DCO_CTL_FREQ_12 (1<<0)
75#define KIRKWOOD_DCO_CTL_FREQ_24 (2<<0)
76
77#define KIRKWOOD_DCO_SPCR_STATUS 0x120c
78#define KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK (1<<16)
79
80#define KIRKWOOD_ERR_CAUSE 0x1300
81#define KIRKWOOD_ERR_MASK 0x1304
82
83#define KIRKWOOD_INT_CAUSE 0x1308
84#define KIRKWOOD_INT_MASK 0x130C
85#define KIRKWOOD_INT_CAUSE_PLAY_BYTES (1<<14)
86#define KIRKWOOD_INT_CAUSE_REC_BYTES (1<<13)
87#define KIRKWOOD_INT_CAUSE_DMA_PLAY_END (1<<7)
88#define KIRKWOOD_INT_CAUSE_DMA_PLAY_3Q (1<<6)
89#define KIRKWOOD_INT_CAUSE_DMA_PLAY_HALF (1<<5)
90#define KIRKWOOD_INT_CAUSE_DMA_PLAY_1Q (1<<4)
91#define KIRKWOOD_INT_CAUSE_DMA_REC_END (1<<3)
92#define KIRKWOOD_INT_CAUSE_DMA_REC_3Q (1<<2)
93#define KIRKWOOD_INT_CAUSE_DMA_REC_HALF (1<<1)
94#define KIRKWOOD_INT_CAUSE_DMA_REC_1Q (1<<0)
95
96#define KIRKWOOD_REC_BYTE_INT_COUNT 0x1310
97#define KIRKWOOD_PLAY_BYTE_INT_COUNT 0x1314
98#define KIRKWOOD_BYTE_INT_COUNT_MASK 0xffffff
99
100#define KIRKWOOD_I2S_PLAYCTL 0x2508
101#define KIRKWOOD_I2S_RECCTL 0x2408
102#define KIRKWOOD_I2S_CTL_JUST_MASK (0xf<<26)
103#define KIRKWOOD_I2S_CTL_LJ (0<<26)
104#define KIRKWOOD_I2S_CTL_I2S (5<<26)
105#define KIRKWOOD_I2S_CTL_RJ (8<<26)
106#define KIRKWOOD_I2S_CTL_SIZE_MASK (3<<30)
107#define KIRKWOOD_I2S_CTL_SIZE_16 (3<<30)
108#define KIRKWOOD_I2S_CTL_SIZE_20 (2<<30)
109#define KIRKWOOD_I2S_CTL_SIZE_24 (1<<30)
110#define KIRKWOOD_I2S_CTL_SIZE_32 (0<<30)
111
112#define KIRKWOOD_AUDIO_BUF_MAX (16*1024*1024)
113
114/* Theses values come from the marvell alsa driver */
115/* need to find where they come from */
116#define KIRKWOOD_SND_MIN_PERIODS 8
117#define KIRKWOOD_SND_MAX_PERIODS 16
118#define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x4000
119#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000
120
121struct kirkwood_dma_data {
122 struct resource *mem;
123 void __iomem *io;
124 int irq;
125 int burst;
126 struct mbus_dram_target_info *dram;
127};
128
129#endif
diff --git a/sound/soc/nuc900/Kconfig b/sound/soc/nuc900/Kconfig
new file mode 100644
index 000000000000..a0ed1c618f60
--- /dev/null
+++ b/sound/soc/nuc900/Kconfig
@@ -0,0 +1,27 @@
1##
2## NUC900 series AC97 API
3##
4config SND_SOC_NUC900
5 tristate "SoC Audio for NUC900 series"
6 depends on ARCH_W90X900
7 help
8 This option enables support for AC97 mode on the NUC900 SoC.
9
10config SND_SOC_NUC900_AC97
11 tristate
12 select AC97_BUS
13 select SND_AC97_CODEC
14 select SND_SOC_AC97_BUS
15
16
17##
18## Boards
19##
20config SND_SOC_NUC900EVB
21 tristate "NUC900 AC97 support for demo board"
22 depends on SND_SOC_NUC900
23 select SND_SOC_NUC900_AC97
24 select SND_SOC_AC97_CODEC
25 help
26 Select this option to enable audio (AC97) on the
27 NUC900 demoboard.
diff --git a/sound/soc/nuc900/Makefile b/sound/soc/nuc900/Makefile
new file mode 100644
index 000000000000..7e46c7150316
--- /dev/null
+++ b/sound/soc/nuc900/Makefile
@@ -0,0 +1,11 @@
1# NUC900 series audio
2snd-soc-nuc900-pcm-objs := nuc900-pcm.o
3snd-soc-nuc900-ac97-objs := nuc900-ac97.o
4
5obj-$(CONFIG_SND_SOC_NUC900) += snd-soc-nuc900-pcm.o
6obj-$(CONFIG_SND_SOC_NUC900_AC97) += snd-soc-nuc900-ac97.o
7
8# Boards
9snd-soc-nuc900-audio-objs := nuc900-audio.o
10
11obj-$(CONFIG_SND_SOC_NUC900EVB) += snd-soc-nuc900-audio.o
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
new file mode 100644
index 000000000000..caa7c901bc2e
--- /dev/null
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -0,0 +1,430 @@
1/*
2 * Copyright (c) 2009-2010 Nuvoton technology corporation.
3 *
4 * Wan ZongShun <mcuos.com@gmail.com>
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 as published by
8 * the Free Software Foundation;version 2 of the License.
9 *
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/device.h>
16#include <linux/delay.h>
17#include <linux/mutex.h>
18#include <linux/suspend.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/initval.h>
22#include <sound/soc.h>
23#include <linux/device.h>
24#include <linux/clk.h>
25
26#include <mach/mfp.h>
27
28#include "nuc900-audio.h"
29
30static DEFINE_MUTEX(ac97_mutex);
31struct nuc900_audio *nuc900_ac97_data;
32
33static int nuc900_checkready(void)
34{
35 struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
36
37 if (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS0) & CODEC_READY))
38 return -EPERM;
39
40 return 0;
41}
42
43/* AC97 controller reads codec register */
44static unsigned short nuc900_ac97_read(struct snd_ac97 *ac97,
45 unsigned short reg)
46{
47 struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
48 unsigned long timeout = 0x10000, val;
49
50 mutex_lock(&ac97_mutex);
51
52 val = nuc900_checkready();
53 if (!!val) {
54 dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
55 goto out;
56 }
57
58 /* set the R_WB bit and write register index */
59 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, R_WB | reg);
60
61 /* set the valid frame bit and valid slots */
62 val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
63 val |= (VALID_FRAME | SLOT1_VALID);
64 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val);
65
66 udelay(100);
67
68 /* polling the AC_R_FINISH */
69 while (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_R_FINISH)
70 && timeout--)
71 mdelay(1);
72
73 if (!timeout) {
74 dev_err(nuc900_audio->dev, "AC97 read register time out !\n");
75 val = -EPERM;
76 goto out;
77 }
78
79 val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0) ;
80 val &= ~SLOT1_VALID;
81 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val);
82
83 if (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS1) >> 2 != reg) {
84 dev_err(nuc900_audio->dev,
85 "R_INDEX of REG_ACTL_ACIS1 not match!\n");
86 }
87
88 udelay(100);
89 val = (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS2) & 0xFFFF);
90
91out:
92 mutex_unlock(&ac97_mutex);
93 return val;
94}
95
96/* AC97 controller writes to codec register */
97static void nuc900_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
98 unsigned short val)
99{
100 struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
101 unsigned long tmp, timeout = 0x10000;
102
103 mutex_lock(&ac97_mutex);
104
105 tmp = nuc900_checkready();
106 if (!!tmp)
107 dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
108
109 /* clear the R_WB bit and write register index */
110 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, reg);
111
112 /* write register value */
113 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS2, val);
114
115 /* set the valid frame bit and valid slots */
116 tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
117 tmp |= SLOT1_VALID | SLOT2_VALID | VALID_FRAME;
118 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp);
119
120 udelay(100);
121
122 /* polling the AC_W_FINISH */
123 while ((AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_W_FINISH)
124 && timeout--)
125 mdelay(1);
126
127 if (!timeout)
128 dev_err(nuc900_audio->dev, "AC97 write register time out !\n");
129
130 tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
131 tmp &= ~(SLOT1_VALID | SLOT2_VALID);
132 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp);
133
134 mutex_unlock(&ac97_mutex);
135
136}
137
138static void nuc900_ac97_warm_reset(struct snd_ac97 *ac97)
139{
140 struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
141 unsigned long val;
142
143 mutex_lock(&ac97_mutex);
144
145 /* warm reset AC 97 */
146 val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON);
147 val |= AC_W_RES;
148 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val);
149
150 udelay(100);
151
152 val = nuc900_checkready();
153 if (!!val)
154 dev_err(nuc900_audio->dev, "AC97 codec is not ready\n");
155
156 mutex_unlock(&ac97_mutex);
157}
158
159static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97)
160{
161 struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
162 unsigned long val;
163
164 mutex_lock(&ac97_mutex);
165
166 /* reset Audio Controller */
167 val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
168 val |= ACTL_RESET_BIT;
169 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
170
171 val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
172 val &= (~ACTL_RESET_BIT);
173 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
174
175 /* reset AC-link interface */
176
177 val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
178 val |= AC_RESET;
179 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
180
181 val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
182 val &= ~AC_RESET;
183 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
184
185 /* cold reset AC 97 */
186 val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON);
187 val |= AC_C_RES;
188 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val);
189
190 val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON);
191 val &= (~AC_C_RES);
192 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val);
193
194 udelay(100);
195
196 mutex_unlock(&ac97_mutex);
197
198}
199
200/* AC97 controller operations */
201struct snd_ac97_bus_ops soc_ac97_ops = {
202 .read = nuc900_ac97_read,
203 .write = nuc900_ac97_write,
204 .reset = nuc900_ac97_cold_reset,
205 .warm_reset = nuc900_ac97_warm_reset,
206}
207EXPORT_SYMBOL_GPL(soc_ac97_ops);
208
209static int nuc900_ac97_trigger(struct snd_pcm_substream *substream,
210 int cmd, struct snd_soc_dai *dai)
211{
212 struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
213 int ret;
214 unsigned long val, tmp;
215
216 ret = 0;
217
218 switch (cmd) {
219 case SNDRV_PCM_TRIGGER_START:
220 case SNDRV_PCM_TRIGGER_RESUME:
221 val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
222 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
223 tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
224 tmp |= (SLOT3_VALID | SLOT4_VALID | VALID_FRAME);
225 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp);
226
227 tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR);
228 tmp |= (P_DMA_END_IRQ | P_DMA_MIDDLE_IRQ);
229 AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, tmp);
230 val |= AC_PLAY;
231 } else {
232 tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR);
233 tmp |= (R_DMA_END_IRQ | R_DMA_MIDDLE_IRQ);
234
235 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, tmp);
236 val |= AC_RECORD;
237 }
238
239 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
240
241 break;
242 case SNDRV_PCM_TRIGGER_STOP:
243 case SNDRV_PCM_TRIGGER_SUSPEND:
244 val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
245 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
246 tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0);
247 tmp &= ~(SLOT3_VALID | SLOT4_VALID);
248 AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp);
249
250 AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, RESET_PRSR);
251 val &= ~AC_PLAY;
252 } else {
253 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, RESET_PRSR);
254 val &= ~AC_RECORD;
255 }
256
257 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
258
259 break;
260 default:
261 ret = -EINVAL;
262 }
263
264 return ret;
265}
266
267static int nuc900_ac97_probe(struct platform_device *pdev,
268 struct snd_soc_dai *dai)
269{
270 struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
271 unsigned long val;
272
273 mutex_lock(&ac97_mutex);
274
275 /* enable unit clock */
276 clk_enable(nuc900_audio->clk);
277
278 /* enable audio controller and AC-link interface */
279 val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON);
280 val |= (IIS_AC_PIN_SEL | ACLINK_EN);
281 AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val);
282
283 mutex_unlock(&ac97_mutex);
284
285 return 0;
286}
287
288static void nuc900_ac97_remove(struct platform_device *pdev,
289 struct snd_soc_dai *dai)
290{
291 struct nuc900_audio *nuc900_audio = nuc900_ac97_data;
292
293 clk_disable(nuc900_audio->clk);
294}
295
296static struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
297 .trigger = nuc900_ac97_trigger,
298};
299
300struct snd_soc_dai nuc900_ac97_dai = {
301 .name = "nuc900-ac97",
302 .probe = nuc900_ac97_probe,
303 .remove = nuc900_ac97_remove,
304 .ac97_control = 1,
305 .playback = {
306 .rates = SNDRV_PCM_RATE_8000_48000,
307 .formats = SNDRV_PCM_FMTBIT_S16_LE,
308 .channels_min = 1,
309 .channels_max = 2,
310 },
311 .capture = {
312 .rates = SNDRV_PCM_RATE_8000_48000,
313 .formats = SNDRV_PCM_FMTBIT_S16_LE,
314 .channels_min = 1,
315 .channels_max = 2,
316 },
317 .ops = &nuc900_ac97_dai_ops,
318}
319EXPORT_SYMBOL_GPL(nuc900_ac97_dai);
320
321static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
322{
323 struct nuc900_audio *nuc900_audio;
324 int ret;
325
326 if (nuc900_ac97_data)
327 return -EBUSY;
328
329 nuc900_audio = kzalloc(sizeof(struct nuc900_audio), GFP_KERNEL);
330 if (!nuc900_audio)
331 return -ENOMEM;
332
333 spin_lock_init(&nuc900_audio->lock);
334
335 nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
336 if (!nuc900_audio->res) {
337 ret = -ENODEV;
338 goto out0;
339 }
340
341 if (!request_mem_region(nuc900_audio->res->start,
342 resource_size(nuc900_audio->res), pdev->name)) {
343 ret = -EBUSY;
344 goto out0;
345 }
346
347 nuc900_audio->mmio = ioremap(nuc900_audio->res->start,
348 resource_size(nuc900_audio->res));
349 if (!nuc900_audio->mmio) {
350 ret = -ENOMEM;
351 goto out1;
352 }
353
354 nuc900_audio->clk = clk_get(&pdev->dev, NULL);
355 if (IS_ERR(nuc900_audio->clk)) {
356 ret = PTR_ERR(nuc900_audio->clk);
357 goto out2;
358 }
359
360 nuc900_audio->irq_num = platform_get_irq(pdev, 0);
361 if (!nuc900_audio->irq_num) {
362 ret = -EBUSY;
363 goto out2;
364 }
365
366 nuc900_ac97_data = nuc900_audio;
367
368 nuc900_audio->dev = nuc900_ac97_dai.dev = &pdev->dev;
369
370 ret = snd_soc_register_dai(&nuc900_ac97_dai);
371 if (ret)
372 goto out3;
373
374 mfp_set_groupg(nuc900_audio->dev); /* enbale ac97 multifunction pin*/
375
376 return 0;
377
378out3:
379 clk_put(nuc900_audio->clk);
380out2:
381 iounmap(nuc900_audio->mmio);
382out1:
383 release_mem_region(nuc900_audio->res->start,
384 resource_size(nuc900_audio->res));
385out0:
386 kfree(nuc900_audio);
387 return ret;
388}
389
390static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
391{
392
393 snd_soc_unregister_dai(&nuc900_ac97_dai);
394
395 clk_put(nuc900_ac97_data->clk);
396 iounmap(nuc900_ac97_data->mmio);
397 release_mem_region(nuc900_ac97_data->res->start,
398 resource_size(nuc900_ac97_data->res));
399
400 nuc900_ac97_data = NULL;
401
402 return 0;
403}
404
405static struct platform_driver nuc900_ac97_driver = {
406 .driver = {
407 .name = "nuc900-audio",
408 .owner = THIS_MODULE,
409 },
410 .probe = nuc900_ac97_drvprobe,
411 .remove = __devexit_p(nuc900_ac97_drvremove),
412};
413
414static int __init nuc900_ac97_init(void)
415{
416 return platform_driver_register(&nuc900_ac97_driver);
417}
418
419static void __exit nuc900_ac97_exit(void)
420{
421 platform_driver_unregister(&nuc900_ac97_driver);
422}
423
424module_init(nuc900_ac97_init);
425module_exit(nuc900_ac97_exit);
426
427MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
428MODULE_DESCRIPTION("NUC900 AC97 SoC driver!");
429MODULE_LICENSE("GPL");
430MODULE_ALIAS("platform:nuc900-ac97");
diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c
new file mode 100644
index 000000000000..72e6f518f7b2
--- /dev/null
+++ b/sound/soc/nuc900/nuc900-audio.c
@@ -0,0 +1,81 @@
1/*
2 * Copyright (c) 2010 Nuvoton technology corporation.
3 *
4 * Wan ZongShun <mcuos.com@gmail.com>
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 as published by
8 * the Free Software Foundation;version 2 of the License.
9 *
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
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22
23#include "../codecs/ac97.h"
24#include "nuc900-audio.h"
25
26static struct snd_soc_dai_link nuc900evb_ac97_dai = {
27 .name = "AC97",
28 .stream_name = "AC97 HiFi",
29 .cpu_dai = &nuc900_ac97_dai,
30 .codec_dai = &ac97_dai,
31};
32
33static struct snd_soc_card nuc900evb_audio_machine = {
34 .name = "NUC900EVB_AC97",
35 .dai_link = &nuc900evb_ac97_dai,
36 .num_links = 1,
37 .platform = &nuc900_soc_platform,
38};
39
40static struct snd_soc_device nuc900evb_ac97_devdata = {
41 .card = &nuc900evb_audio_machine,
42 .codec_dev = &soc_codec_dev_ac97,
43};
44
45static struct platform_device *nuc900evb_asoc_dev;
46
47static int __init nuc900evb_audio_init(void)
48{
49 int ret;
50
51 ret = -ENOMEM;
52 nuc900evb_asoc_dev = platform_device_alloc("soc-audio", -1);
53 if (!nuc900evb_asoc_dev)
54 goto out;
55
56 /* nuc900 board audio device */
57 platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_ac97_devdata);
58
59 nuc900evb_ac97_devdata.dev = &nuc900evb_asoc_dev->dev;
60 ret = platform_device_add(nuc900evb_asoc_dev);
61
62 if (ret) {
63 platform_device_put(nuc900evb_asoc_dev);
64 nuc900evb_asoc_dev = NULL;
65 }
66
67out:
68 return ret;
69}
70
71static void __exit nuc900evb_audio_exit(void)
72{
73 platform_device_unregister(nuc900evb_asoc_dev);
74}
75
76module_init(nuc900evb_audio_init);
77module_exit(nuc900evb_audio_exit);
78
79MODULE_LICENSE("GPL");
80MODULE_DESCRIPTION("NUC900 Series ASoC audio support");
81MODULE_AUTHOR("Wan ZongShun");
diff --git a/sound/soc/nuc900/nuc900-audio.h b/sound/soc/nuc900/nuc900-audio.h
new file mode 100644
index 000000000000..3038f519729f
--- /dev/null
+++ b/sound/soc/nuc900/nuc900-audio.h
@@ -0,0 +1,117 @@
1/*
2 * Copyright (c) 2010 Nuvoton technology corporation.
3 *
4 * Wan ZongShun <mcuos.com@gmail.com>
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 as published by
8 * the Free Software Foundation;version 2 of the License.
9 *
10 */
11
12#ifndef _NUC900_AUDIO_H
13#define _NUC900_AUDIO_H
14
15#include <linux/io.h>
16
17/* Audio Control Registers */
18#define ACTL_CON 0x00
19#define ACTL_RESET 0x04
20#define ACTL_RDSTB 0x08
21#define ACTL_RDST_LENGTH 0x0C
22#define ACTL_RDSTC 0x10
23#define ACTL_RSR 0x14
24#define ACTL_PDSTB 0x18
25#define ACTL_PDST_LENGTH 0x1C
26#define ACTL_PDSTC 0x20
27#define ACTL_PSR 0x24
28#define ACTL_IISCON 0x28
29#define ACTL_ACCON 0x2C
30#define ACTL_ACOS0 0x30
31#define ACTL_ACOS1 0x34
32#define ACTL_ACOS2 0x38
33#define ACTL_ACIS0 0x3C
34#define ACTL_ACIS1 0x40
35#define ACTL_ACIS2 0x44
36#define ACTL_COUNTER 0x48
37
38/* bit definition of REG_ACTL_CON register */
39#define R_DMA_IRQ 0x1000
40#define T_DMA_IRQ 0x0800
41#define IIS_AC_PIN_SEL 0x0100
42#define FIFO_TH 0x0080
43#define ADC_EN 0x0010
44#define M80_EN 0x0008
45#define ACLINK_EN 0x0004
46#define IIS_EN 0x0002
47
48/* bit definition of REG_ACTL_RESET register */
49#define W5691_PLAY 0x20000
50#define ACTL_RESET_BIT 0x10000
51#define RECORD_RIGHT_CHNNEL 0x08000
52#define RECORD_LEFT_CHNNEL 0x04000
53#define PLAY_RIGHT_CHNNEL 0x02000
54#define PLAY_LEFT_CHNNEL 0x01000
55#define DAC_PLAY 0x00800
56#define ADC_RECORD 0x00400
57#define M80_PLAY 0x00200
58#define AC_RECORD 0x00100
59#define AC_PLAY 0x00080
60#define IIS_RECORD 0x00040
61#define IIS_PLAY 0x00020
62#define DAC_RESET 0x00010
63#define ADC_RESET 0x00008
64#define M80_RESET 0x00004
65#define AC_RESET 0x00002
66#define IIS_RESET 0x00001
67
68/* bit definition of REG_ACTL_ACCON register */
69#define AC_BCLK_PU_EN 0x20
70#define AC_R_FINISH 0x10
71#define AC_W_FINISH 0x08
72#define AC_W_RES 0x04
73#define AC_C_RES 0x02
74
75/* bit definition of ACTL_RSR register */
76#define R_FIFO_EMPTY 0x04
77#define R_DMA_END_IRQ 0x02
78#define R_DMA_MIDDLE_IRQ 0x01
79
80/* bit definition of ACTL_PSR register */
81#define P_FIFO_EMPTY 0x04
82#define P_DMA_END_IRQ 0x02
83#define P_DMA_MIDDLE_IRQ 0x01
84
85/* bit definition of ACTL_ACOS0 register */
86#define SLOT1_VALID 0x01
87#define SLOT2_VALID 0x02
88#define SLOT3_VALID 0x04
89#define SLOT4_VALID 0x08
90#define VALID_FRAME 0x10
91
92/* bit definition of ACTL_ACOS1 register */
93#define R_WB 0x80
94
95#define CODEC_READY 0x10
96#define RESET_PRSR 0x00
97#define AUDIO_WRITE(addr, val) __raw_writel(val, addr)
98#define AUDIO_READ(addr) __raw_readl(addr)
99
100struct nuc900_audio {
101 void __iomem *mmio;
102 spinlock_t lock;
103 dma_addr_t dma_addr[2];
104 unsigned long buffersize[2];
105 unsigned long irq_num;
106 struct snd_pcm_substream *substream;
107 struct resource *res;
108 struct clk *clk;
109 struct device *dev;
110
111};
112
113extern struct nuc900_audio *nuc900_ac97_data;
114extern struct snd_soc_dai nuc900_ac97_dai;
115extern struct snd_soc_platform nuc900_soc_platform;
116
117#endif /*end _NUC900_AUDIO_H */
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
new file mode 100644
index 000000000000..e81e803b3a63
--- /dev/null
+++ b/sound/soc/nuc900/nuc900-pcm.c
@@ -0,0 +1,354 @@
1/*
2 * Copyright (c) 2010 Nuvoton technology corporation.
3 *
4 * Wan ZongShun <mcuos.com@gmail.com>
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 as published by
8 * the Free Software Foundation;version 2 of the License.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/dma-mapping.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 <mach/hardware.h>
25
26#include "nuc900-audio.h"
27
28static const struct snd_pcm_hardware nuc900_pcm_hardware = {
29 .info = SNDRV_PCM_INFO_INTERLEAVED |
30 SNDRV_PCM_INFO_BLOCK_TRANSFER |
31 SNDRV_PCM_INFO_MMAP |
32 SNDRV_PCM_INFO_MMAP_VALID |
33 SNDRV_PCM_INFO_PAUSE |
34 SNDRV_PCM_INFO_RESUME,
35 .formats = SNDRV_PCM_FMTBIT_S16_LE,
36 .channels_min = 1,
37 .channels_max = 2,
38 .buffer_bytes_max = 4*1024,
39 .period_bytes_min = 1*1024,
40 .period_bytes_max = 4*1024,
41 .periods_min = 1,
42 .periods_max = 1024,
43};
44
45static int nuc900_dma_hw_params(struct snd_pcm_substream *substream,
46 struct snd_pcm_hw_params *params)
47{
48 struct snd_pcm_runtime *runtime = substream->runtime;
49 struct nuc900_audio *nuc900_audio = runtime->private_data;
50 unsigned long flags;
51 int ret = 0;
52
53 spin_lock_irqsave(&nuc900_audio->lock, flags);
54
55 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
56 if (ret < 0)
57 return ret;
58
59 nuc900_audio->substream = substream;
60 nuc900_audio->dma_addr[substream->stream] = runtime->dma_addr;
61 nuc900_audio->buffersize[substream->stream] =
62 params_buffer_bytes(params);
63
64 spin_unlock_irqrestore(&nuc900_audio->lock, flags);
65
66 return ret;
67}
68
69static void nuc900_update_dma_register(struct snd_pcm_substream *substream,
70 dma_addr_t dma_addr, size_t count)
71{
72 struct snd_pcm_runtime *runtime = substream->runtime;
73 struct nuc900_audio *nuc900_audio = runtime->private_data;
74 void __iomem *mmio_addr, *mmio_len;
75
76 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
77 mmio_addr = nuc900_audio->mmio + ACTL_PDSTB;
78 mmio_len = nuc900_audio->mmio + ACTL_PDST_LENGTH;
79 } else {
80 mmio_addr = nuc900_audio->mmio + ACTL_RDSTB;
81 mmio_len = nuc900_audio->mmio + ACTL_RDST_LENGTH;
82 }
83
84 AUDIO_WRITE(mmio_addr, dma_addr);
85 AUDIO_WRITE(mmio_len, count);
86}
87
88static void nuc900_dma_start(struct snd_pcm_substream *substream)
89{
90 struct snd_pcm_runtime *runtime = substream->runtime;
91 struct nuc900_audio *nuc900_audio = runtime->private_data;
92 unsigned long val;
93
94 val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON);
95 val |= (T_DMA_IRQ | R_DMA_IRQ);
96 AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val);
97}
98
99static void nuc900_dma_stop(struct snd_pcm_substream *substream)
100{
101 struct snd_pcm_runtime *runtime = substream->runtime;
102 struct nuc900_audio *nuc900_audio = runtime->private_data;
103 unsigned long val;
104
105 val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON);
106 val &= ~(T_DMA_IRQ | R_DMA_IRQ);
107 AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val);
108}
109
110static irqreturn_t nuc900_dma_interrupt(int irq, void *dev_id)
111{
112 struct snd_pcm_substream *substream = dev_id;
113 struct nuc900_audio *nuc900_audio = substream->runtime->private_data;
114 unsigned long val;
115
116 spin_lock(&nuc900_audio->lock);
117
118 val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON);
119
120 if (val & R_DMA_IRQ) {
121 AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | R_DMA_IRQ);
122
123 val = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR);
124
125 if (val & R_DMA_MIDDLE_IRQ) {
126 val |= R_DMA_MIDDLE_IRQ;
127 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val);
128 }
129
130 if (val & R_DMA_END_IRQ) {
131 val |= R_DMA_END_IRQ;
132 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val);
133 }
134 } else if (val & T_DMA_IRQ) {
135 AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | T_DMA_IRQ);
136
137 val = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR);
138
139 if (val & P_DMA_MIDDLE_IRQ) {
140 val |= P_DMA_MIDDLE_IRQ;
141 AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val);
142 }
143
144 if (val & P_DMA_END_IRQ) {
145 val |= P_DMA_END_IRQ;
146 AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val);
147 }
148 } else {
149 dev_err(nuc900_audio->dev, "Wrong DMA interrupt status!\n");
150 spin_unlock(&nuc900_audio->lock);
151 return IRQ_HANDLED;
152 }
153
154 spin_unlock(&nuc900_audio->lock);
155
156 snd_pcm_period_elapsed(substream);
157
158 return IRQ_HANDLED;
159}
160
161static int nuc900_dma_hw_free(struct snd_pcm_substream *substream)
162{
163 snd_pcm_lib_free_pages(substream);
164 return 0;
165}
166
167static int nuc900_dma_prepare(struct snd_pcm_substream *substream)
168{
169 struct snd_pcm_runtime *runtime = substream->runtime;
170 struct nuc900_audio *nuc900_audio = runtime->private_data;
171 unsigned long flags, val;
172
173 spin_lock_irqsave(&nuc900_audio->lock, flags);
174
175 nuc900_update_dma_register(substream,
176 nuc900_audio->dma_addr[substream->stream],
177 nuc900_audio->buffersize[substream->stream]);
178
179 val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);
180
181 switch (runtime->channels) {
182 case 1:
183 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
184 val &= ~(PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL);
185 val |= PLAY_RIGHT_CHNNEL;
186 } else {
187 val &= ~(RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL);
188 val |= RECORD_RIGHT_CHNNEL;
189 }
190 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
191 break;
192 case 2:
193 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
194 val |= (PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL);
195 else
196 val |= (RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL);
197 AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
198 break;
199 default:
200 return -EINVAL;
201 }
202 spin_unlock_irqrestore(&nuc900_audio->lock, flags);
203 return 0;
204}
205
206static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd)
207{
208 int ret = 0;
209
210 switch (cmd) {
211 case SNDRV_PCM_TRIGGER_START:
212 case SNDRV_PCM_TRIGGER_RESUME:
213 nuc900_dma_start(substream);
214 break;
215
216 case SNDRV_PCM_TRIGGER_STOP:
217 case SNDRV_PCM_TRIGGER_SUSPEND:
218 nuc900_dma_stop(substream);
219 break;
220
221 default:
222 ret = -EINVAL;
223 break;
224 }
225
226 return ret;
227}
228
229int nuc900_dma_getposition(struct snd_pcm_substream *substream,
230 dma_addr_t *src, dma_addr_t *dst)
231{
232 struct snd_pcm_runtime *runtime = substream->runtime;
233 struct nuc900_audio *nuc900_audio = runtime->private_data;
234
235 if (src != NULL)
236 *src = AUDIO_READ(nuc900_audio->mmio + ACTL_PDSTC);
237
238 if (dst != NULL)
239 *dst = AUDIO_READ(nuc900_audio->mmio + ACTL_RDSTC);
240
241 return 0;
242}
243
244static snd_pcm_uframes_t nuc900_dma_pointer(struct snd_pcm_substream *substream)
245{
246 struct snd_pcm_runtime *runtime = substream->runtime;
247 dma_addr_t src, dst;
248 unsigned long res;
249
250 nuc900_dma_getposition(substream, &src, &dst);
251
252 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
253 res = dst - runtime->dma_addr;
254 else
255 res = src - runtime->dma_addr;
256
257 return bytes_to_frames(substream->runtime, res);
258}
259
260static int nuc900_dma_open(struct snd_pcm_substream *substream)
261{
262 struct snd_pcm_runtime *runtime = substream->runtime;
263 struct nuc900_audio *nuc900_audio;
264
265 snd_soc_set_runtime_hwparams(substream, &nuc900_pcm_hardware);
266
267 nuc900_audio = nuc900_ac97_data;
268
269 if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt,
270 IRQF_DISABLED, "nuc900-dma", substream))
271 return -EBUSY;
272
273 runtime->private_data = nuc900_audio;
274
275 return 0;
276}
277
278static int nuc900_dma_close(struct snd_pcm_substream *substream)
279{
280 struct snd_pcm_runtime *runtime = substream->runtime;
281 struct nuc900_audio *nuc900_audio = runtime->private_data;
282
283 free_irq(nuc900_audio->irq_num, substream);
284
285 return 0;
286}
287
288static int nuc900_dma_mmap(struct snd_pcm_substream *substream,
289 struct vm_area_struct *vma)
290{
291 struct snd_pcm_runtime *runtime = substream->runtime;
292
293 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
294 runtime->dma_area,
295 runtime->dma_addr,
296 runtime->dma_bytes);
297}
298
299static struct snd_pcm_ops nuc900_dma_ops = {
300 .open = nuc900_dma_open,
301 .close = nuc900_dma_close,
302 .ioctl = snd_pcm_lib_ioctl,
303 .hw_params = nuc900_dma_hw_params,
304 .hw_free = nuc900_dma_hw_free,
305 .prepare = nuc900_dma_prepare,
306 .trigger = nuc900_dma_trigger,
307 .pointer = nuc900_dma_pointer,
308 .mmap = nuc900_dma_mmap,
309};
310
311static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm)
312{
313 snd_pcm_lib_preallocate_free_for_all(pcm);
314}
315
316static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32);
317static int nuc900_dma_new(struct snd_card *card,
318 struct snd_soc_dai *dai, struct snd_pcm *pcm)
319{
320 if (!card->dev->dma_mask)
321 card->dev->dma_mask = &nuc900_pcm_dmamask;
322 if (!card->dev->coherent_dma_mask)
323 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
324
325 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
326 card->dev, 4 * 1024, (4 * 1024) - 1);
327
328 return 0;
329}
330
331struct snd_soc_platform nuc900_soc_platform = {
332 .name = "nuc900-dma",
333 .pcm_ops = &nuc900_dma_ops,
334 .pcm_new = nuc900_dma_new,
335 .pcm_free = nuc900_dma_free_dma_buffers,
336}
337EXPORT_SYMBOL_GPL(nuc900_soc_platform);
338
339static int __init nuc900_soc_platform_init(void)
340{
341 return snd_soc_register_platform(&nuc900_soc_platform);
342}
343
344static void __exit nuc900_soc_platform_exit(void)
345{
346 snd_soc_unregister_platform(&nuc900_soc_platform);
347}
348
349module_init(nuc900_soc_platform_init);
350module_exit(nuc900_soc_platform_exit);
351
352MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>");
353MODULE_DESCRIPTION("nuc900 Audio DMA module");
354MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 6f44cb4d30b8..86f213905e2c 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -59,6 +59,7 @@ struct omap_mcbsp_data {
59 int configured; 59 int configured;
60 unsigned int in_freq; 60 unsigned int in_freq;
61 int clk_div; 61 int clk_div;
62 int wlen;
62}; 63};
63 64
64#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id) 65#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
@@ -154,20 +155,51 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
154 struct snd_soc_pcm_runtime *rtd = substream->private_data; 155 struct snd_soc_pcm_runtime *rtd = substream->private_data;
155 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 156 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
156 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 157 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
158 struct omap_pcm_dma_data *dma_data;
157 int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); 159 int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
158 int samples; 160 int words;
161
162 dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
159 163
160 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ 164 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
161 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) 165 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
162 samples = snd_pcm_lib_period_bytes(substream) >> 1; 166 /*
167 * Configure McBSP threshold based on either:
168 * packet_size, when the sDMA is in packet mode, or
169 * based on the period size.
170 */
171 if (dma_data->packet_size)
172 words = dma_data->packet_size;
173 else
174 words = snd_pcm_lib_period_bytes(substream) /
175 (mcbsp_data->wlen / 8);
163 else 176 else
164 samples = 1; 177 words = 1;
165 178
166 /* Configure McBSP internal buffer usage */ 179 /* Configure McBSP internal buffer usage */
167 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 180 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
168 omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1); 181 omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words);
169 else 182 else
170 omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1); 183 omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
184}
185
186static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
187 struct snd_pcm_hw_rule *rule)
188{
189 struct snd_interval *buffer_size = hw_param_interval(params,
190 SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
191 struct snd_interval *channels = hw_param_interval(params,
192 SNDRV_PCM_HW_PARAM_CHANNELS);
193 struct omap_mcbsp_data *mcbsp_data = rule->private;
194 struct snd_interval frames;
195 int size;
196
197 snd_interval_any(&frames);
198 size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id);
199
200 frames.min = size / channels->min;
201 frames.integer = 1;
202 return snd_interval_refine(buffer_size, &frames);
171} 203}
172 204
173static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, 205static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
@@ -182,33 +214,35 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
182 if (!cpu_dai->active) 214 if (!cpu_dai->active)
183 err = omap_mcbsp_request(bus_id); 215 err = omap_mcbsp_request(bus_id);
184 216
217 /*
218 * OMAP3 McBSP FIFO is word structured.
219 * McBSP2 has 1024 + 256 = 1280 word long buffer,
220 * McBSP1,3,4,5 has 128 word long buffer
221 * This means that the size of the FIFO depends on the sample format.
222 * For example on McBSP3:
223 * 16bit samples: size is 128 * 2 = 256 bytes
224 * 32bit samples: size is 128 * 4 = 512 bytes
225 * It is simpler to place constraint for buffer and period based on
226 * channels.
227 * McBSP3 as example again (16 or 32 bit samples):
228 * 1 channel (mono): size is 128 frames (128 words)
229 * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
230 * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
231 */
185 if (cpu_is_omap343x()) { 232 if (cpu_is_omap343x()) {
186 int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id);
187 int max_period;
188
189 /* 233 /*
190 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. 234 * Rule for the buffer size. We should not allow
191 * Set constraint for minimum buffer size to the same than FIFO 235 * smaller buffer than the FIFO size to avoid underruns
192 * size in order to avoid underruns in playback startup because 236 */
193 * HW is keeping the DMA request active until FIFO is filled. 237 snd_pcm_hw_rule_add(substream->runtime, 0,
194 */ 238 SNDRV_PCM_HW_PARAM_CHANNELS,
195 if (bus_id == 1) 239 omap_mcbsp_hwrule_min_buffersize,
196 snd_pcm_hw_constraint_minmax(substream->runtime, 240 mcbsp_data,
197 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 241 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
198 4096, UINT_MAX); 242
199 243 /* Make sure, that the period size is always even */
200 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 244 snd_pcm_hw_constraint_step(substream->runtime, 0,
201 max_period = omap_mcbsp_get_max_tx_threshold(bus_id); 245 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
202 else
203 max_period = omap_mcbsp_get_max_rx_threshold(bus_id);
204
205 max_period++;
206 max_period <<= 1;
207
208 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
209 snd_pcm_hw_constraint_minmax(substream->runtime,
210 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
211 32, max_period);
212 } 246 }
213 247
214 return err; 248 return err;
@@ -289,11 +323,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
289 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 323 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
290 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 324 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
291 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 325 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
292 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 326 struct omap_pcm_dma_data *dma_data;
327 int dma, bus_id = mcbsp_data->bus_id;
293 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; 328 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
329 int pkt_size = 0;
294 unsigned long port; 330 unsigned long port;
295 unsigned int format, div, framesize, master; 331 unsigned int format, div, framesize, master;
296 332
333 dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
297 if (cpu_class_is_omap1()) { 334 if (cpu_class_is_omap1()) {
298 dma = omap1_dma_reqs[bus_id][substream->stream]; 335 dma = omap1_dma_reqs[bus_id][substream->stream];
299 port = omap1_mcbsp_port[bus_id][substream->stream]; 336 port = omap1_mcbsp_port[bus_id][substream->stream];
@@ -306,35 +343,74 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
306 } else if (cpu_is_omap343x()) { 343 } else if (cpu_is_omap343x()) {
307 dma = omap24xx_dma_reqs[bus_id][substream->stream]; 344 dma = omap24xx_dma_reqs[bus_id][substream->stream];
308 port = omap34xx_mcbsp_port[bus_id][substream->stream]; 345 port = omap34xx_mcbsp_port[bus_id][substream->stream];
309 omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold =
310 omap_mcbsp_set_threshold;
311 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
312 if (omap_mcbsp_get_dma_op_mode(bus_id) ==
313 MCBSP_DMA_MODE_THRESHOLD)
314 sync_mode = OMAP_DMA_SYNC_FRAME;
315 } else { 346 } else {
316 return -ENODEV; 347 return -ENODEV;
317 } 348 }
318 omap_mcbsp_dai_dma_params[id][substream->stream].name =
319 substream->stream ? "Audio Capture" : "Audio Playback";
320 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
321 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
322 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
323 switch (params_format(params)) { 349 switch (params_format(params)) {
324 case SNDRV_PCM_FORMAT_S16_LE: 350 case SNDRV_PCM_FORMAT_S16_LE:
325 omap_mcbsp_dai_dma_params[id][substream->stream].data_type = 351 dma_data->data_type = OMAP_DMA_DATA_TYPE_S16;
326 OMAP_DMA_DATA_TYPE_S16; 352 wlen = 16;
327 break; 353 break;
328 case SNDRV_PCM_FORMAT_S32_LE: 354 case SNDRV_PCM_FORMAT_S32_LE:
329 omap_mcbsp_dai_dma_params[id][substream->stream].data_type = 355 dma_data->data_type = OMAP_DMA_DATA_TYPE_S32;
330 OMAP_DMA_DATA_TYPE_S32; 356 wlen = 32;
331 break; 357 break;
332 default: 358 default:
333 return -EINVAL; 359 return -EINVAL;
334 } 360 }
361 if (cpu_is_omap343x()) {
362 dma_data->set_threshold = omap_mcbsp_set_threshold;
363 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
364 if (omap_mcbsp_get_dma_op_mode(bus_id) ==
365 MCBSP_DMA_MODE_THRESHOLD) {
366 int period_words, max_thrsh;
367
368 period_words = params_period_bytes(params) / (wlen / 8);
369 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
370 max_thrsh = omap_mcbsp_get_max_tx_threshold(
371 mcbsp_data->bus_id);
372 else
373 max_thrsh = omap_mcbsp_get_max_rx_threshold(
374 mcbsp_data->bus_id);
375 /*
376 * If the period contains less or equal number of words,
377 * we are using the original threshold mode setup:
378 * McBSP threshold = sDMA frame size = period_size
379 * Otherwise we switch to sDMA packet mode:
380 * McBSP threshold = sDMA packet size
381 * sDMA frame size = period size
382 */
383 if (period_words > max_thrsh) {
384 int divider = 0;
385
386 /*
387 * Look for the biggest threshold value, which
388 * divides the period size evenly.
389 */
390 divider = period_words / max_thrsh;
391 if (period_words % max_thrsh)
392 divider++;
393 while (period_words % divider &&
394 divider < period_words)
395 divider++;
396 if (divider == period_words)
397 return -EINVAL;
398
399 pkt_size = period_words / divider;
400 sync_mode = OMAP_DMA_SYNC_PACKET;
401 } else {
402 sync_mode = OMAP_DMA_SYNC_FRAME;
403 }
404 }
405 }
335 406
336 snd_soc_dai_set_dma_data(cpu_dai, substream, 407 dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback";
337 &omap_mcbsp_dai_dma_params[id][substream->stream]); 408 dma_data->dma_req = dma;
409 dma_data->port_addr = port;
410 dma_data->sync_mode = sync_mode;
411 dma_data->packet_size = pkt_size;
412
413 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
338 414
339 if (mcbsp_data->configured) { 415 if (mcbsp_data->configured) {
340 /* McBSP already configured by another stream */ 416 /* McBSP already configured by another stream */
@@ -360,7 +436,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
360 switch (params_format(params)) { 436 switch (params_format(params)) {
361 case SNDRV_PCM_FORMAT_S16_LE: 437 case SNDRV_PCM_FORMAT_S16_LE:
362 /* Set word lengths */ 438 /* Set word lengths */
363 wlen = 16;
364 regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); 439 regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16);
365 regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); 440 regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16);
366 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); 441 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16);
@@ -368,7 +443,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
368 break; 443 break;
369 case SNDRV_PCM_FORMAT_S32_LE: 444 case SNDRV_PCM_FORMAT_S32_LE:
370 /* Set word lengths */ 445 /* Set word lengths */
371 wlen = 32;
372 regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); 446 regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32);
373 regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); 447 regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32);
374 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); 448 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32);
@@ -409,6 +483,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
409 } 483 }
410 484
411 omap_mcbsp_config(bus_id, &mcbsp_data->regs); 485 omap_mcbsp_config(bus_id, &mcbsp_data->regs);
486 mcbsp_data->wlen = wlen;
412 mcbsp_data->configured = 1; 487 mcbsp_data->configured = 1;
413 488
414 return 0; 489 return 0;
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 87ce842fa2e8..9eecac135bbb 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -43,12 +43,14 @@
43 43
44static struct regulator *omap3pandora_dac_reg; 44static struct regulator *omap3pandora_dac_reg;
45 45
46static int omap3pandora_cmn_hw_params(struct snd_pcm_substream *substream, 46static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
47 struct snd_pcm_hw_params *params, unsigned int fmt) 47 struct snd_pcm_hw_params *params)
48{ 48{
49 struct snd_soc_pcm_runtime *rtd = substream->private_data; 49 struct snd_soc_pcm_runtime *rtd = substream->private_data;
50 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 50 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
51 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 51 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
52 int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
53 SND_SOC_DAIFMT_CBS_CFS;
52 int ret; 54 int ret;
53 55
54 /* Set codec DAI configuration */ 56 /* Set codec DAI configuration */
@@ -91,24 +93,6 @@ static int omap3pandora_cmn_hw_params(struct snd_pcm_substream *substream,
91 return 0; 93 return 0;
92} 94}
93 95
94static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
95 struct snd_pcm_hw_params *params)
96{
97 return omap3pandora_cmn_hw_params(substream, params,
98 SND_SOC_DAIFMT_I2S |
99 SND_SOC_DAIFMT_IB_NF |
100 SND_SOC_DAIFMT_CBS_CFS);
101}
102
103static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream,
104 struct snd_pcm_hw_params *params)
105{
106 return omap3pandora_cmn_hw_params(substream, params,
107 SND_SOC_DAIFMT_I2S |
108 SND_SOC_DAIFMT_NB_NF |
109 SND_SOC_DAIFMT_CBS_CFS);
110}
111
112static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w, 96static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
113 struct snd_kcontrol *k, int event) 97 struct snd_kcontrol *k, int event)
114{ 98{
@@ -231,12 +215,8 @@ static int omap3pandora_in_init(struct snd_soc_codec *codec)
231 return snd_soc_dapm_sync(codec); 215 return snd_soc_dapm_sync(codec);
232} 216}
233 217
234static struct snd_soc_ops omap3pandora_out_ops = { 218static struct snd_soc_ops omap3pandora_ops = {
235 .hw_params = omap3pandora_out_hw_params, 219 .hw_params = omap3pandora_hw_params,
236};
237
238static struct snd_soc_ops omap3pandora_in_ops = {
239 .hw_params = omap3pandora_in_hw_params,
240}; 220};
241 221
242/* Digital audio interface glue - connects codec <--> CPU */ 222/* Digital audio interface glue - connects codec <--> CPU */
@@ -246,14 +226,14 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
246 .stream_name = "HiFi Out", 226 .stream_name = "HiFi Out",
247 .cpu_dai = &omap_mcbsp_dai[0], 227 .cpu_dai = &omap_mcbsp_dai[0],
248 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 228 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
249 .ops = &omap3pandora_out_ops, 229 .ops = &omap3pandora_ops,
250 .init = omap3pandora_out_init, 230 .init = omap3pandora_out_init,
251 }, { 231 }, {
252 .name = "TWL4030", 232 .name = "TWL4030",
253 .stream_name = "Line/Mic In", 233 .stream_name = "Line/Mic In",
254 .cpu_dai = &omap_mcbsp_dai[1], 234 .cpu_dai = &omap_mcbsp_dai[1],
255 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 235 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
256 .ops = &omap3pandora_in_ops, 236 .ops = &omap3pandora_ops,
257 .init = omap3pandora_in_init, 237 .init = omap3pandora_in_init,
258 } 238 }
259}; 239};
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 47d831ef2dbb..88052d29617f 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -27,6 +27,7 @@
27#include <linux/gpio.h> 27#include <linux/gpio.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <sound/core.h> 29#include <sound/core.h>
30#include <sound/jack.h>
30#include <sound/pcm.h> 31#include <sound/pcm.h>
31#include <sound/soc.h> 32#include <sound/soc.h>
32#include <sound/soc-dapm.h> 33#include <sound/soc-dapm.h>
@@ -37,14 +38,22 @@
37#include "omap-pcm.h" 38#include "omap-pcm.h"
38#include "../codecs/tlv320aic3x.h" 39#include "../codecs/tlv320aic3x.h"
39 40
41#define RX51_TVOUT_SEL_GPIO 40
42#define RX51_JACK_DETECT_GPIO 177
40/* 43/*
41 * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This 44 * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This
42 * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c 45 * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c
43 */ 46 */
44#define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7) 47#define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7)
45 48
49enum {
50 RX51_JACK_DISABLED,
51 RX51_JACK_TVOUT, /* tv-out */
52};
53
46static int rx51_spk_func; 54static int rx51_spk_func;
47static int rx51_dmic_func; 55static int rx51_dmic_func;
56static int rx51_jack_func;
48 57
49static void rx51_ext_control(struct snd_soc_codec *codec) 58static void rx51_ext_control(struct snd_soc_codec *codec)
50{ 59{
@@ -57,6 +66,9 @@ static void rx51_ext_control(struct snd_soc_codec *codec)
57 else 66 else
58 snd_soc_dapm_disable_pin(codec, "DMic"); 67 snd_soc_dapm_disable_pin(codec, "DMic");
59 68
69 gpio_set_value(RX51_TVOUT_SEL_GPIO,
70 rx51_jack_func == RX51_JACK_TVOUT);
71
60 snd_soc_dapm_sync(codec); 72 snd_soc_dapm_sync(codec);
61} 73}
62 74
@@ -162,6 +174,40 @@ static int rx51_set_input(struct snd_kcontrol *kcontrol,
162 return 1; 174 return 1;
163} 175}
164 176
177static int rx51_get_jack(struct snd_kcontrol *kcontrol,
178 struct snd_ctl_elem_value *ucontrol)
179{
180 ucontrol->value.integer.value[0] = rx51_jack_func;
181
182 return 0;
183}
184
185static int rx51_set_jack(struct snd_kcontrol *kcontrol,
186 struct snd_ctl_elem_value *ucontrol)
187{
188 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
189
190 if (rx51_jack_func == ucontrol->value.integer.value[0])
191 return 0;
192
193 rx51_jack_func = ucontrol->value.integer.value[0];
194 rx51_ext_control(codec);
195
196 return 1;
197}
198
199static struct snd_soc_jack rx51_av_jack;
200
201static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
202 {
203 .gpio = RX51_JACK_DETECT_GPIO,
204 .name = "avdet-gpio",
205 .report = SND_JACK_VIDEOOUT,
206 .invert = 1,
207 .debounce_time = 200,
208 },
209};
210
165static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { 211static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
166 SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), 212 SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
167 SND_SOC_DAPM_MIC("DMic", NULL), 213 SND_SOC_DAPM_MIC("DMic", NULL),
@@ -177,10 +223,12 @@ static const struct snd_soc_dapm_route audio_map[] = {
177 223
178static const char *spk_function[] = {"Off", "On"}; 224static const char *spk_function[] = {"Off", "On"};
179static const char *input_function[] = {"ADC", "Digital Mic"}; 225static const char *input_function[] = {"ADC", "Digital Mic"};
226static const char *jack_function[] = {"Off", "TV-OUT"};
180 227
181static const struct soc_enum rx51_enum[] = { 228static const struct soc_enum rx51_enum[] = {
182 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), 229 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
183 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function), 230 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
231 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
184}; 232};
185 233
186static const struct snd_kcontrol_new aic34_rx51_controls[] = { 234static const struct snd_kcontrol_new aic34_rx51_controls[] = {
@@ -188,10 +236,13 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
188 rx51_get_spk, rx51_set_spk), 236 rx51_get_spk, rx51_set_spk),
189 SOC_ENUM_EXT("Input Select", rx51_enum[1], 237 SOC_ENUM_EXT("Input Select", rx51_enum[1],
190 rx51_get_input, rx51_set_input), 238 rx51_get_input, rx51_set_input),
239 SOC_ENUM_EXT("Jack Function", rx51_enum[2],
240 rx51_get_jack, rx51_set_jack),
191}; 241};
192 242
193static int rx51_aic34_init(struct snd_soc_codec *codec) 243static int rx51_aic34_init(struct snd_soc_codec *codec)
194{ 244{
245 struct snd_soc_card *card = codec->socdev->card;
195 int err; 246 int err;
196 247
197 /* Set up NC codec pins */ 248 /* Set up NC codec pins */
@@ -214,7 +265,16 @@ static int rx51_aic34_init(struct snd_soc_codec *codec)
214 265
215 snd_soc_dapm_sync(codec); 266 snd_soc_dapm_sync(codec);
216 267
217 return 0; 268 /* AV jack detection */
269 err = snd_soc_jack_new(card, "AV Jack",
270 SND_JACK_VIDEOOUT, &rx51_av_jack);
271 if (err)
272 return err;
273 err = snd_soc_jack_add_gpios(&rx51_av_jack,
274 ARRAY_SIZE(rx51_av_jack_gpios),
275 rx51_av_jack_gpios);
276
277 return err;
218} 278}
219 279
220/* Digital audio interface glue - connects codec <--> CPU */ 280/* Digital audio interface glue - connects codec <--> CPU */
@@ -259,6 +319,11 @@ static int __init rx51_soc_init(void)
259 if (!machine_is_nokia_rx51()) 319 if (!machine_is_nokia_rx51())
260 return -ENODEV; 320 return -ENODEV;
261 321
322 err = gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel");
323 if (err)
324 goto err_gpio_tvout_sel;
325 gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0);
326
262 rx51_snd_device = platform_device_alloc("soc-audio", -1); 327 rx51_snd_device = platform_device_alloc("soc-audio", -1);
263 if (!rx51_snd_device) { 328 if (!rx51_snd_device) {
264 err = -ENOMEM; 329 err = -ENOMEM;
@@ -277,13 +342,19 @@ static int __init rx51_soc_init(void)
277err2: 342err2:
278 platform_device_put(rx51_snd_device); 343 platform_device_put(rx51_snd_device);
279err1: 344err1:
345 gpio_free(RX51_TVOUT_SEL_GPIO);
346err_gpio_tvout_sel:
280 347
281 return err; 348 return err;
282} 349}
283 350
284static void __exit rx51_soc_exit(void) 351static void __exit rx51_soc_exit(void)
285{ 352{
353 snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios),
354 rx51_av_jack_gpios);
355
286 platform_device_unregister(rx51_snd_device); 356 platform_device_unregister(rx51_snd_device);
357 gpio_free(RX51_TVOUT_SEL_GPIO);
287} 358}
288 359
289module_init(rx51_soc_init); 360module_init(rx51_soc_init);
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 2a7cc222d098..213963ac3c28 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -1,6 +1,6 @@
1config SND_S3C24XX_SOC 1config SND_S3C24XX_SOC
2 tristate "SoC Audio for the Samsung S3CXXXX chips" 2 tristate "SoC Audio for the Samsung S3CXXXX chips"
3 depends on ARCH_S3C2410 || ARCH_S3C64XX 3 depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210
4 select S3C64XX_DMA if ARCH_S3C64XX 4 select S3C64XX_DMA if ARCH_S3C64XX
5 help 5 help
6 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
@@ -120,8 +120,14 @@ config SND_S3C24XX_SOC_SIMTEC_HERMES
120 120
121config SND_SOC_SMDK_WM9713 121config SND_SOC_SMDK_WM9713
122 tristate "SoC AC97 Audio support for SMDK with WM9713" 122 tristate "SoC AC97 Audio support for SMDK with WM9713"
123 depends on SND_S3C24XX_SOC && MACH_SMDK6410 123 depends on SND_S3C24XX_SOC && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
124 select SND_SOC_WM9713 124 select SND_SOC_WM9713
125 select SND_S3C_SOC_AC97 125 select SND_S3C_SOC_AC97
126 help 126 help
127 Sat Y if you want to add support for SoC audio on the SMDK. 127 Sat Y if you want to add support for SoC audio on the SMDK.
128
129config SND_S3C64XX_SOC_SMARTQ
130 tristate "SoC I2S Audio support for SmartQ board"
131 depends on SND_S3C24XX_SOC && MACH_SMARTQ
132 select SND_S3C64XX_SOC_I2S
133 select SND_SOC_WM8750
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 81d8dc503f87..50172c385d90 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -29,6 +29,7 @@ snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o
29snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o 29snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o
30snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o 30snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o
31snd-soc-smdk-wm9713-objs := smdk_wm9713.o 31snd-soc-smdk-wm9713-objs := smdk_wm9713.o
32snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
32 33
33obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o 34obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
34obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 35obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -41,3 +42,4 @@ obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
41obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o 42obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
42obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o 43obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o
43obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o 44obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o
45obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o
diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c
index ecf4fd04ae96..31f6d45b6384 100644
--- a/sound/soc/s3c24xx/s3c-ac97.c
+++ b/sound/soc/s3c24xx/s3c-ac97.c
@@ -31,7 +31,6 @@
31#define AC_CMD_DATA(x) (x & 0xffff) 31#define AC_CMD_DATA(x) (x & 0xffff)
32 32
33struct s3c_ac97_info { 33struct s3c_ac97_info {
34 unsigned state;
35 struct clk *ac97_clk; 34 struct clk *ac97_clk;
36 void __iomem *regs; 35 void __iomem *regs;
37 struct mutex lock; 36 struct mutex lock;
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index 13311c8cf965..64376b2aac73 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -32,7 +32,8 @@
32 32
33#undef S3C_IIS_V2_SUPPORTED 33#undef S3C_IIS_V2_SUPPORTED
34 34
35#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) 35#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) \
36 || defined(CONFIG_CPU_S5PV210)
36#define S3C_IIS_V2_SUPPORTED 37#define S3C_IIS_V2_SUPPORTED
37#endif 38#endif
38 39
diff --git a/sound/soc/s3c24xx/smartq_wm8987.c b/sound/soc/s3c24xx/smartq_wm8987.c
new file mode 100644
index 000000000000..b480348140b0
--- /dev/null
+++ b/sound/soc/s3c24xx/smartq_wm8987.c
@@ -0,0 +1,295 @@
1/* sound/soc/s3c24xx/smartq_wm8987.c
2 *
3 * Copyright 2010 Maurus Cuelenaere <mcuelenaere@gmail.com>
4 *
5 * Based on smdk6410_wm8987.c
6 * Copyright 2007 Wolfson Microelectronics PLC. - linux@wolfsonmicro.com
7 * Graeme Gregory - graeme.gregory@wolfsonmicro.com
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
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/gpio.h>
19
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/soc-dapm.h>
23#include <sound/jack.h>
24
25#include <asm/mach-types.h>
26
27#include "s3c-dma.h"
28#include "s3c64xx-i2s.h"
29
30#include "../codecs/wm8750.h"
31
32/*
33 * WM8987 is register compatible with WM8750, so using that as base driver.
34 */
35
36static struct snd_soc_card snd_soc_smartq;
37
38static int smartq_hifi_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params)
40{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
44 struct s3c_i2sv2_rate_calc div;
45 unsigned int clk = 0;
46 int ret;
47
48 s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params),
49 s3c_i2sv2_get_clock(cpu_dai));
50
51 switch (params_rate(params)) {
52 case 8000:
53 case 16000:
54 case 32000:
55 case 48000:
56 case 96000:
57 clk = 12288000;
58 break;
59 case 11025:
60 case 22050:
61 case 44100:
62 case 88200:
63 clk = 11289600;
64 break;
65 }
66
67 /* set codec DAI configuration */
68 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
69 SND_SOC_DAIFMT_NB_NF |
70 SND_SOC_DAIFMT_CBS_CFS);
71 if (ret < 0)
72 return ret;
73
74 /* set cpu DAI configuration */
75 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
76 SND_SOC_DAIFMT_NB_NF |
77 SND_SOC_DAIFMT_CBS_CFS);
78 if (ret < 0)
79 return ret;
80
81 /* set the codec system clock for DAC and ADC */
82 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
83 SND_SOC_CLOCK_IN);
84 if (ret < 0)
85 return ret;
86
87 /* set MCLK division for sample rate */
88 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_RCLK, div.fs_div);
89 if (ret < 0)
90 return ret;
91
92 /* set prescaler division for sample rate */
93 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_PRESCALER,
94 div.clk_div - 1);
95 if (ret < 0)
96 return ret;
97
98 return 0;
99}
100
101/*
102 * SmartQ WM8987 HiFi DAI operations.
103 */
104static struct snd_soc_ops smartq_hifi_ops = {
105 .hw_params = smartq_hifi_hw_params,
106};
107
108static struct snd_soc_jack smartq_jack;
109
110static struct snd_soc_jack_pin smartq_jack_pins[] = {
111 /* Disable speaker when headphone is plugged in */
112 {
113 .pin = "Internal Speaker",
114 .mask = SND_JACK_HEADPHONE,
115 },
116};
117
118static struct snd_soc_jack_gpio smartq_jack_gpios[] = {
119 {
120 .gpio = S3C64XX_GPL(12),
121 .name = "headphone detect",
122 .report = SND_JACK_HEADPHONE,
123 .debounce_time = 200,
124 },
125};
126
127static const struct snd_kcontrol_new wm8987_smartq_controls[] = {
128 SOC_DAPM_PIN_SWITCH("Internal Speaker"),
129 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
130 SOC_DAPM_PIN_SWITCH("Internal Mic"),
131};
132
133static int smartq_speaker_event(struct snd_soc_dapm_widget *w,
134 struct snd_kcontrol *k,
135 int event)
136{
137 gpio_set_value(S3C64XX_GPK(12), SND_SOC_DAPM_EVENT_OFF(event));
138
139 return 0;
140}
141
142static const struct snd_soc_dapm_widget wm8987_dapm_widgets[] = {
143 SND_SOC_DAPM_SPK("Internal Speaker", smartq_speaker_event),
144 SND_SOC_DAPM_HP("Headphone Jack", NULL),
145 SND_SOC_DAPM_MIC("Internal Mic", NULL),
146};
147
148static const struct snd_soc_dapm_route audio_map[] = {
149 {"Headphone Jack", NULL, "LOUT2"},
150 {"Headphone Jack", NULL, "ROUT2"},
151
152 {"Internal Speaker", NULL, "LOUT2"},
153 {"Internal Speaker", NULL, "ROUT2"},
154
155 {"Mic Bias", NULL, "Internal Mic"},
156 {"LINPUT2", NULL, "Mic Bias"},
157};
158
159static int smartq_wm8987_init(struct snd_soc_codec *codec)
160{
161 int err = 0;
162
163 /* Add SmartQ specific widgets */
164 snd_soc_dapm_new_controls(codec, wm8987_dapm_widgets,
165 ARRAY_SIZE(wm8987_dapm_widgets));
166
167 /* add SmartQ specific controls */
168 err = snd_soc_add_controls(codec, wm8987_smartq_controls,
169 ARRAY_SIZE(wm8987_smartq_controls));
170
171 if (err < 0)
172 return err;
173
174 /* setup SmartQ specific audio path */
175 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
176
177 /* set endpoints to not connected */
178 snd_soc_dapm_nc_pin(codec, "LINPUT1");
179 snd_soc_dapm_nc_pin(codec, "RINPUT1");
180 snd_soc_dapm_nc_pin(codec, "OUT3");
181 snd_soc_dapm_nc_pin(codec, "ROUT1");
182
183 /* set endpoints to default off mode */
184 snd_soc_dapm_enable_pin(codec, "Internal Speaker");
185 snd_soc_dapm_enable_pin(codec, "Internal Mic");
186 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
187
188 err = snd_soc_dapm_sync(codec);
189 if (err)
190 return err;
191
192 /* Headphone jack detection */
193 err = snd_soc_jack_new(&snd_soc_smartq, "Headphone Jack",
194 SND_JACK_HEADPHONE, &smartq_jack);
195 if (err)
196 return err;
197
198 err = snd_soc_jack_add_pins(&smartq_jack, ARRAY_SIZE(smartq_jack_pins),
199 smartq_jack_pins);
200 if (err)
201 return err;
202
203 err = snd_soc_jack_add_gpios(&smartq_jack,
204 ARRAY_SIZE(smartq_jack_gpios),
205 smartq_jack_gpios);
206
207 return err;
208}
209
210static struct snd_soc_dai_link smartq_dai[] = {
211 {
212 .name = "wm8987",
213 .stream_name = "SmartQ Hi-Fi",
214 .cpu_dai = &s3c64xx_i2s_dai[0],
215 .codec_dai = &wm8750_dai,
216 .init = smartq_wm8987_init,
217 .ops = &smartq_hifi_ops,
218 },
219};
220
221static struct snd_soc_card snd_soc_smartq = {
222 .name = "SmartQ",
223 .platform = &s3c24xx_soc_platform,
224 .dai_link = smartq_dai,
225 .num_links = ARRAY_SIZE(smartq_dai),
226};
227
228static struct snd_soc_device smartq_snd_devdata = {
229 .card = &snd_soc_smartq,
230 .codec_dev = &soc_codec_dev_wm8750,
231};
232
233static struct platform_device *smartq_snd_device;
234
235static int __init smartq_init(void)
236{
237 int ret;
238
239 if (!machine_is_smartq7() && !machine_is_smartq5()) {
240 pr_info("Only SmartQ is supported by this ASoC driver\n");
241 return -ENODEV;
242 }
243
244 smartq_snd_device = platform_device_alloc("soc-audio", -1);
245 if (!smartq_snd_device)
246 return -ENOMEM;
247
248 platform_set_drvdata(smartq_snd_device, &smartq_snd_devdata);
249 smartq_snd_devdata.dev = &smartq_snd_device->dev;
250
251 ret = platform_device_add(smartq_snd_device);
252 if (ret) {
253 platform_device_put(smartq_snd_device);
254 return ret;
255 }
256
257 /* Initialise GPIOs used by amplifiers */
258 ret = gpio_request(S3C64XX_GPK(12), "amplifiers shutdown");
259 if (ret) {
260 dev_err(&smartq_snd_device->dev, "Failed to register GPK12\n");
261 goto err_unregister_device;
262 }
263
264 /* Disable amplifiers */
265 ret = gpio_direction_output(S3C64XX_GPK(12), 1);
266 if (ret) {
267 dev_err(&smartq_snd_device->dev, "Failed to configure GPK12\n");
268 goto err_free_gpio_amp_shut;
269 }
270
271 return 0;
272
273err_free_gpio_amp_shut:
274 gpio_free(S3C64XX_GPK(12));
275err_unregister_device:
276 platform_device_unregister(smartq_snd_device);
277
278 return ret;
279}
280
281static void __exit smartq_exit(void)
282{
283 snd_soc_jack_free_gpios(&smartq_jack, ARRAY_SIZE(smartq_jack_gpios),
284 smartq_jack_gpios);
285
286 platform_device_unregister(smartq_snd_device);
287}
288
289module_init(smartq_init);
290module_exit(smartq_exit);
291
292/* Module information */
293MODULE_AUTHOR("Maurus Cuelenaere <mcuelenaere@gmail.com>");
294MODULE_DESCRIPTION("ALSA SoC SmartQ WM8987");
295MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk_wm9713.c b/sound/soc/s3c24xx/smdk_wm9713.c
index 24fd39f38ccb..5527b9e88c98 100644
--- a/sound/soc/s3c24xx/smdk_wm9713.c
+++ b/sound/soc/s3c24xx/smdk_wm9713.c
@@ -25,6 +25,9 @@ static struct snd_soc_card smdk;
25 * Default CFG switch settings to use this driver: 25 * Default CFG switch settings to use this driver:
26 * 26 *
27 * SMDK6410: Set CFG1 1-3 On, CFG2 1-4 Off 27 * SMDK6410: Set CFG1 1-3 On, CFG2 1-4 Off
28 * SMDKC100: Set CFG6 1-3 On, CFG7 1 On
29 * SMDKC110: Set CFGB10 1-2 Off, CFGB12 1-3 On
30 * SMDKV210: Set CFGB10 1-2 Off, CFGB12 1-3 On
28 */ 31 */
29 32
30/* 33/*
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index 5b9ac1759bd2..59e3fa7bcb05 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -451,16 +451,15 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
451 goto err_release_none; 451 goto err_release_none;
452 } 452 }
453 453
454 region = request_mem_region(scbmem->start, 454 region = request_mem_region(scbmem->start, resource_size(scbmem),
455 scbmem->end - scbmem->start + 1, 455 pdev->name);
456 pdev->name);
457 if (!region) { 456 if (!region) {
458 dev_err(&pdev->dev, "I2S SCB region already claimed\n"); 457 dev_err(&pdev->dev, "I2S SCB region already claimed\n");
459 ret = -EBUSY; 458 ret = -EBUSY;
460 goto err_release_none; 459 goto err_release_none;
461 } 460 }
462 461
463 mmio = ioremap(scbmem->start, scbmem->end - scbmem->start + 1); 462 mmio = ioremap(scbmem->start, resource_size(scbmem));
464 if (!mmio) { 463 if (!mmio) {
465 dev_err(&pdev->dev, "can't ioremap SCB region\n"); 464 dev_err(&pdev->dev, "can't ioremap SCB region\n");
466 ret = -ENOMEM; 465 ret = -ENOMEM;
@@ -474,9 +473,8 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
474 goto err_release_map; 473 goto err_release_map;
475 } 474 }
476 475
477 region = request_mem_region(sifmem->start, 476 region = request_mem_region(sifmem->start, resource_size(sifmem),
478 sifmem->end - sifmem->start + 1, 477 pdev->name);
479 pdev->name);
480 if (!region) { 478 if (!region) {
481 dev_err(&pdev->dev, "I2S SIF region already claimed\n"); 479 dev_err(&pdev->dev, "I2S SIF region already claimed\n");
482 ret = -EBUSY; 480 ret = -EBUSY;
@@ -490,8 +488,8 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
490 goto err_release_sif; 488 goto err_release_sif;
491 } 489 }
492 490
493 region = request_mem_region(dma1->start, dma1->end - dma1->start + 1, 491 region = request_mem_region(dma1->start, resource_size(dma1),
494 pdev->name); 492 pdev->name);
495 if (!region) { 493 if (!region) {
496 dev_err(&pdev->dev, "I2S DMA region already claimed\n"); 494 dev_err(&pdev->dev, "I2S DMA region already claimed\n");
497 ret = -EBUSY; 495 ret = -EBUSY;
@@ -500,9 +498,8 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
500 498
501 dma2 = platform_get_resource(pdev, IORESOURCE_DMA, 1); 499 dma2 = platform_get_resource(pdev, IORESOURCE_DMA, 1);
502 if (dma2) { 500 if (dma2) {
503 region = request_mem_region(dma2->start, 501 region = request_mem_region(dma2->start, resource_size(dma2),
504 dma2->end - dma2->start + 1, 502 pdev->name);
505 pdev->name);
506 if (!region) { 503 if (!region) {
507 dev_err(&pdev->dev, 504 dev_err(&pdev->dev,
508 "I2S DMA region already claimed\n"); 505 "I2S DMA region already claimed\n");
@@ -561,15 +558,15 @@ err_release_dev:
561 kfree(dev); 558 kfree(dev);
562err_release_dma2: 559err_release_dma2:
563 if (dma2) 560 if (dma2)
564 release_mem_region(dma2->start, dma2->end - dma2->start + 1); 561 release_mem_region(dma2->start, resource_size(dma2));
565err_release_dma1: 562err_release_dma1:
566 release_mem_region(dma1->start, dma1->end - dma1->start + 1); 563 release_mem_region(dma1->start, resource_size(dma1));
567err_release_sif: 564err_release_sif:
568 release_mem_region(sifmem->start, (sifmem->end - sifmem->start) + 1); 565 release_mem_region(sifmem->start, resource_size(sifmem));
569err_release_map: 566err_release_map:
570 iounmap(mmio); 567 iounmap(mmio);
571err_release_scb: 568err_release_scb:
572 release_mem_region(scbmem->start, (scbmem->end - scbmem->start) + 1); 569 release_mem_region(scbmem->start, resource_size(scbmem));
573err_release_none: 570err_release_none:
574 return ret; 571 return ret;
575} 572}
@@ -590,19 +587,18 @@ static void __devexit s6000_i2s_remove(struct platform_device *pdev)
590 kfree(dev); 587 kfree(dev);
591 588
592 region = platform_get_resource(pdev, IORESOURCE_DMA, 0); 589 region = platform_get_resource(pdev, IORESOURCE_DMA, 0);
593 release_mem_region(region->start, region->end - region->start + 1); 590 release_mem_region(region->start, resource_size(region));
594 591
595 region = platform_get_resource(pdev, IORESOURCE_DMA, 1); 592 region = platform_get_resource(pdev, IORESOURCE_DMA, 1);
596 if (region) 593 if (region)
597 release_mem_region(region->start, 594 release_mem_region(region->start, resource_size(region));
598 region->end - region->start + 1);
599 595
600 region = platform_get_resource(pdev, IORESOURCE_MEM, 0); 596 region = platform_get_resource(pdev, IORESOURCE_MEM, 0);
601 release_mem_region(region->start, (region->end - region->start) + 1); 597 release_mem_region(region->start, resource_size(region));
602 598
603 iounmap(mmio); 599 iounmap(mmio);
604 region = platform_get_resource(pdev, IORESOURCE_IO, 0); 600 region = platform_get_resource(pdev, IORESOURCE_IO, 0);
605 release_mem_region(region->start, (region->end - region->start) + 1); 601 release_mem_region(region->start, resource_size(region));
606} 602}
607 603
608static struct platform_driver s6000_i2s_driver = { 604static struct platform_driver s6000_i2s_driver = {
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index a1d14bc3c76f..52d7e8ed9c1f 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -48,7 +48,7 @@ config SND_SH7760_AC97
48 48
49config SND_FSI_AK4642 49config SND_FSI_AK4642
50 bool "FSI-AK4642 sound support" 50 bool "FSI-AK4642 sound support"
51 depends on SND_SOC_SH4_FSI 51 depends on SND_SOC_SH4_FSI && I2C_SH_MOBILE
52 select SND_SOC_AK4642 52 select SND_SOC_AK4642
53 help 53 help
54 This option enables generic sound support for the 54 This option enables generic sound support for the
@@ -56,7 +56,7 @@ config SND_FSI_AK4642
56 56
57config SND_FSI_DA7210 57config SND_FSI_DA7210
58 bool "FSI-DA7210 sound support" 58 bool "FSI-DA7210 sound support"
59 depends on SND_SOC_SH4_FSI 59 depends on SND_SOC_SH4_FSI && I2C_SH_MOBILE
60 select SND_SOC_DA7210 60 select SND_SOC_DA7210
61 help 61 help
62 This option enables generic sound support for the 62 This option enables generic sound support for the
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index be018542314e..dad575a22622 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -9,16 +9,7 @@
9 * for more details. 9 * for more details.
10 */ 10 */
11 11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/platform_device.h> 12#include <linux/platform_device.h>
15#include <linux/i2c.h>
16#include <linux/io.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20#include <sound/soc-dapm.h>
21
22#include <sound/sh_fsi.h> 13#include <sound/sh_fsi.h>
23#include <../sound/soc/codecs/ak4642.h> 14#include <../sound/soc/codecs/ak4642.h>
24 15
@@ -38,7 +29,7 @@ static int fsi_ak4642_dai_init(struct snd_soc_codec *codec)
38static struct snd_soc_dai_link fsi_dai_link = { 29static struct snd_soc_dai_link fsi_dai_link = {
39 .name = "AK4642", 30 .name = "AK4642",
40 .stream_name = "AK4642", 31 .stream_name = "AK4642",
41 .cpu_dai = &fsi_soc_dai[0], /* fsi */ 32 .cpu_dai = &fsi_soc_dai[FSI_PORT_A],
42 .codec_dai = &ak4642_dai, 33 .codec_dai = &ak4642_dai,
43 .init = fsi_ak4642_dai_init, 34 .init = fsi_ak4642_dai_init,
44 .ops = NULL, 35 .ops = NULL,
@@ -62,7 +53,7 @@ static int __init fsi_ak4642_init(void)
62{ 53{
63 int ret = -ENOMEM; 54 int ret = -ENOMEM;
64 55
65 fsi_snd_device = platform_device_alloc("soc-audio", -1); 56 fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_A);
66 if (!fsi_snd_device) 57 if (!fsi_snd_device)
67 goto out; 58 goto out;
68 59
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
index 33b4d177f466..121bbb07bb03 100644
--- a/sound/soc/sh/fsi-da7210.c
+++ b/sound/soc/sh/fsi-da7210.c
@@ -10,16 +10,7 @@
10 * option) any later version. 10 * option) any later version.
11 */ 11 */
12 12
13#include <linux/interrupt.h>
14#include <linux/platform_device.h> 13#include <linux/platform_device.h>
15#include <linux/io.h>
16#include <linux/i2c.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22
23#include <sound/sh_fsi.h> 14#include <sound/sh_fsi.h>
24#include "../codecs/da7210.h" 15#include "../codecs/da7210.h"
25 16
@@ -33,7 +24,7 @@ static int fsi_da7210_init(struct snd_soc_codec *codec)
33static struct snd_soc_dai_link fsi_da7210_dai = { 24static struct snd_soc_dai_link fsi_da7210_dai = {
34 .name = "DA7210", 25 .name = "DA7210",
35 .stream_name = "DA7210", 26 .stream_name = "DA7210",
36 .cpu_dai = &fsi_soc_dai[1], /* FSI B */ 27 .cpu_dai = &fsi_soc_dai[FSI_PORT_B],
37 .codec_dai = &da7210_dai, 28 .codec_dai = &da7210_dai,
38 .init = fsi_da7210_init, 29 .init = fsi_da7210_init,
39}; 30};
@@ -56,7 +47,7 @@ static int __init fsi_da7210_sound_init(void)
56{ 47{
57 int ret; 48 int ret;
58 49
59 fsi_da7210_snd_device = platform_device_alloc("soc-audio", -1); 50 fsi_da7210_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B);
60 if (!fsi_da7210_snd_device) 51 if (!fsi_da7210_snd_device)
61 return -ENOMEM; 52 return -ENOMEM;
62 53
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index ec4acac49ebd..58c6bec642de 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -12,21 +12,12 @@
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/platform_device.h>
18#include <linux/delay.h> 15#include <linux/delay.h>
19#include <linux/list.h>
20#include <linux/pm_runtime.h> 16#include <linux/pm_runtime.h>
21#include <linux/io.h> 17#include <linux/io.h>
22#include <linux/slab.h> 18#include <linux/slab.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/initval.h>
26#include <sound/soc.h> 19#include <sound/soc.h>
27#include <sound/pcm_params.h>
28#include <sound/sh_fsi.h> 20#include <sound/sh_fsi.h>
29#include <asm/atomic.h>
30 21
31#define DO_FMT 0x0000 22#define DO_FMT 0x0000
32#define DOFF_CTL 0x0004 23#define DOFF_CTL 0x0004
@@ -39,9 +30,11 @@
39#define DIDT 0x0020 30#define DIDT 0x0020
40#define DODT 0x0024 31#define DODT 0x0024
41#define MUTE_ST 0x0028 32#define MUTE_ST 0x0028
42#define REG_END MUTE_ST 33#define OUT_SEL 0x0030
43 34#define REG_END OUT_SEL
44 35
36#define A_MST_CTLR 0x0180
37#define B_MST_CTLR 0x01A0
45#define CPU_INT_ST 0x01F4 38#define CPU_INT_ST 0x01F4
46#define CPU_IEMSK 0x01F8 39#define CPU_IEMSK 0x01F8
47#define CPU_IMSK 0x01FC 40#define CPU_IMSK 0x01FC
@@ -52,18 +45,18 @@
52#define CLK_RST 0x0210 45#define CLK_RST 0x0210
53#define SOFT_RST 0x0214 46#define SOFT_RST 0x0214
54#define FIFO_SZ 0x0218 47#define FIFO_SZ 0x0218
55#define MREG_START CPU_INT_ST 48#define MREG_START A_MST_CTLR
56#define MREG_END FIFO_SZ 49#define MREG_END FIFO_SZ
57 50
58/* DO_FMT */ 51/* DO_FMT */
59/* DI_FMT */ 52/* DI_FMT */
60#define CR_FMT(param) ((param) << 4) 53#define CR_MONO (0x0 << 4)
61# define CR_MONO 0x0 54#define CR_MONO_D (0x1 << 4)
62# define CR_MONO_D 0x1 55#define CR_PCM (0x2 << 4)
63# define CR_PCM 0x2 56#define CR_I2S (0x3 << 4)
64# define CR_I2S 0x3 57#define CR_TDM (0x4 << 4)
65# define CR_TDM 0x4 58#define CR_TDM_D (0x5 << 4)
66# define CR_TDM_D 0x5 59#define CR_SPDIF 0x00100120
67 60
68/* DOFF_CTL */ 61/* DOFF_CTL */
69/* DIFF_CTL */ 62/* DIFF_CTL */
@@ -75,6 +68,14 @@
75#define ERR_UNDER 0x00000001 68#define ERR_UNDER 0x00000001
76#define ST_ERR (ERR_OVER | ERR_UNDER) 69#define ST_ERR (ERR_OVER | ERR_UNDER)
77 70
71/* CKG1 */
72#define ACKMD_MASK 0x00007000
73#define BPFMD_MASK 0x00000700
74
75/* A/B MST_CTLR */
76#define BP (1 << 4) /* Fix the signal of Biphase output */
77#define SE (1 << 0) /* Fix the master clock */
78
78/* CLK_RST */ 79/* CLK_RST */
79#define B_CLK 0x00000010 80#define B_CLK 0x00000010
80#define A_CLK 0x00000001 81#define A_CLK 0x00000001
@@ -119,9 +120,13 @@ struct fsi_priv {
119 int period_len; 120 int period_len;
120 int buffer_len; 121 int buffer_len;
121 int periods; 122 int periods;
123
124 u32 mst_ctrl;
122}; 125};
123 126
124struct fsi_regs { 127struct fsi_core {
128 int ver;
129
125 u32 int_st; 130 u32 int_st;
126 u32 iemsk; 131 u32 iemsk;
127 u32 imsk; 132 u32 imsk;
@@ -132,7 +137,7 @@ struct fsi_master {
132 int irq; 137 int irq;
133 struct fsi_priv fsia; 138 struct fsi_priv fsia;
134 struct fsi_priv fsib; 139 struct fsi_priv fsib;
135 struct fsi_regs *regs; 140 struct fsi_core *core;
136 struct sh_fsi_platform_info *info; 141 struct sh_fsi_platform_info *info;
137 spinlock_t lock; 142 spinlock_t lock;
138}; 143};
@@ -169,24 +174,30 @@ static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
169 174
170static void fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data) 175static void fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data)
171{ 176{
172 if (reg > REG_END) 177 if (reg > REG_END) {
178 pr_err("fsi: register access err (%s)\n", __func__);
173 return; 179 return;
180 }
174 181
175 __fsi_reg_write((u32)(fsi->base + reg), data); 182 __fsi_reg_write((u32)(fsi->base + reg), data);
176} 183}
177 184
178static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) 185static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg)
179{ 186{
180 if (reg > REG_END) 187 if (reg > REG_END) {
188 pr_err("fsi: register access err (%s)\n", __func__);
181 return 0; 189 return 0;
190 }
182 191
183 return __fsi_reg_read((u32)(fsi->base + reg)); 192 return __fsi_reg_read((u32)(fsi->base + reg));
184} 193}
185 194
186static void fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) 195static void fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data)
187{ 196{
188 if (reg > REG_END) 197 if (reg > REG_END) {
198 pr_err("fsi: register access err (%s)\n", __func__);
189 return; 199 return;
200 }
190 201
191 __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); 202 __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data);
192} 203}
@@ -196,8 +207,10 @@ static void fsi_master_write(struct fsi_master *master, u32 reg, u32 data)
196 unsigned long flags; 207 unsigned long flags;
197 208
198 if ((reg < MREG_START) || 209 if ((reg < MREG_START) ||
199 (reg > MREG_END)) 210 (reg > MREG_END)) {
211 pr_err("fsi: register access err (%s)\n", __func__);
200 return; 212 return;
213 }
201 214
202 spin_lock_irqsave(&master->lock, flags); 215 spin_lock_irqsave(&master->lock, flags);
203 __fsi_reg_write((u32)(master->base + reg), data); 216 __fsi_reg_write((u32)(master->base + reg), data);
@@ -210,8 +223,10 @@ static u32 fsi_master_read(struct fsi_master *master, u32 reg)
210 unsigned long flags; 223 unsigned long flags;
211 224
212 if ((reg < MREG_START) || 225 if ((reg < MREG_START) ||
213 (reg > MREG_END)) 226 (reg > MREG_END)) {
227 pr_err("fsi: register access err (%s)\n", __func__);
214 return 0; 228 return 0;
229 }
215 230
216 spin_lock_irqsave(&master->lock, flags); 231 spin_lock_irqsave(&master->lock, flags);
217 ret = __fsi_reg_read((u32)(master->base + reg)); 232 ret = __fsi_reg_read((u32)(master->base + reg));
@@ -226,8 +241,10 @@ static void fsi_master_mask_set(struct fsi_master *master,
226 unsigned long flags; 241 unsigned long flags;
227 242
228 if ((reg < MREG_START) || 243 if ((reg < MREG_START) ||
229 (reg > MREG_END)) 244 (reg > MREG_END)) {
245 pr_err("fsi: register access err (%s)\n", __func__);
230 return; 246 return;
247 }
231 248
232 spin_lock_irqsave(&master->lock, flags); 249 spin_lock_irqsave(&master->lock, flags);
233 __fsi_reg_mask_set((u32)(master->base + reg), mask, data); 250 __fsi_reg_mask_set((u32)(master->base + reg), mask, data);
@@ -349,8 +366,8 @@ static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
349 u32 data = fsi_port_ab_io_bit(fsi, is_play); 366 u32 data = fsi_port_ab_io_bit(fsi, is_play);
350 struct fsi_master *master = fsi_get_master(fsi); 367 struct fsi_master *master = fsi_get_master(fsi);
351 368
352 fsi_master_mask_set(master, master->regs->imsk, data, data); 369 fsi_master_mask_set(master, master->core->imsk, data, data);
353 fsi_master_mask_set(master, master->regs->iemsk, data, data); 370 fsi_master_mask_set(master, master->core->iemsk, data, data);
354} 371}
355 372
356static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) 373static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
@@ -358,18 +375,18 @@ static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
358 u32 data = fsi_port_ab_io_bit(fsi, is_play); 375 u32 data = fsi_port_ab_io_bit(fsi, is_play);
359 struct fsi_master *master = fsi_get_master(fsi); 376 struct fsi_master *master = fsi_get_master(fsi);
360 377
361 fsi_master_mask_set(master, master->regs->imsk, data, 0); 378 fsi_master_mask_set(master, master->core->imsk, data, 0);
362 fsi_master_mask_set(master, master->regs->iemsk, data, 0); 379 fsi_master_mask_set(master, master->core->iemsk, data, 0);
363} 380}
364 381
365static u32 fsi_irq_get_status(struct fsi_master *master) 382static u32 fsi_irq_get_status(struct fsi_master *master)
366{ 383{
367 return fsi_master_read(master, master->regs->int_st); 384 return fsi_master_read(master, master->core->int_st);
368} 385}
369 386
370static void fsi_irq_clear_all_status(struct fsi_master *master) 387static void fsi_irq_clear_all_status(struct fsi_master *master)
371{ 388{
372 fsi_master_write(master, master->regs->int_st, 0x0000000); 389 fsi_master_write(master, master->core->int_st, 0);
373} 390}
374 391
375static void fsi_irq_clear_status(struct fsi_priv *fsi) 392static void fsi_irq_clear_status(struct fsi_priv *fsi)
@@ -381,7 +398,30 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
381 data |= fsi_port_ab_io_bit(fsi, 1); 398 data |= fsi_port_ab_io_bit(fsi, 1);
382 399
383 /* clear interrupt factor */ 400 /* clear interrupt factor */
384 fsi_master_mask_set(master, master->regs->int_st, data, 0); 401 fsi_master_mask_set(master, master->core->int_st, data, 0);
402}
403
404/************************************************************************
405
406
407 SPDIF master clock function
408
409These functions are used later FSI2
410************************************************************************/
411static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
412{
413 struct fsi_master *master = fsi_get_master(fsi);
414 u32 val = BP | SE;
415
416 if (master->core->ver < 2) {
417 pr_err("fsi: register access err (%s)\n", __func__);
418 return;
419 }
420
421 if (enable)
422 fsi_master_mask_set(master, fsi->mst_ctrl, val, val);
423 else
424 fsi_master_mask_set(master, fsi->mst_ctrl, val, 0);
385} 425}
386 426
387/************************************************************************ 427/************************************************************************
@@ -662,8 +702,8 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
662 struct snd_soc_dai *dai) 702 struct snd_soc_dai *dai)
663{ 703{
664 struct fsi_priv *fsi = fsi_get_priv(substream); 704 struct fsi_priv *fsi = fsi_get_priv(substream);
665 const char *msg;
666 u32 flags = fsi_get_info_flags(fsi); 705 u32 flags = fsi_get_info_flags(fsi);
706 struct fsi_master *master = fsi_get_master(fsi);
667 u32 fmt; 707 u32 fmt;
668 u32 reg; 708 u32 reg;
669 u32 data; 709 u32 data;
@@ -700,36 +740,40 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
700 fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); 740 fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags);
701 switch (fmt) { 741 switch (fmt) {
702 case SH_FSI_FMT_MONO: 742 case SH_FSI_FMT_MONO:
703 msg = "MONO"; 743 data = CR_MONO;
704 data = CR_FMT(CR_MONO);
705 fsi->chan = 1; 744 fsi->chan = 1;
706 break; 745 break;
707 case SH_FSI_FMT_MONO_DELAY: 746 case SH_FSI_FMT_MONO_DELAY:
708 msg = "MONO Delay"; 747 data = CR_MONO_D;
709 data = CR_FMT(CR_MONO_D);
710 fsi->chan = 1; 748 fsi->chan = 1;
711 break; 749 break;
712 case SH_FSI_FMT_PCM: 750 case SH_FSI_FMT_PCM:
713 msg = "PCM"; 751 data = CR_PCM;
714 data = CR_FMT(CR_PCM);
715 fsi->chan = 2; 752 fsi->chan = 2;
716 break; 753 break;
717 case SH_FSI_FMT_I2S: 754 case SH_FSI_FMT_I2S:
718 msg = "I2S"; 755 data = CR_I2S;
719 data = CR_FMT(CR_I2S);
720 fsi->chan = 2; 756 fsi->chan = 2;
721 break; 757 break;
722 case SH_FSI_FMT_TDM: 758 case SH_FSI_FMT_TDM:
723 msg = "TDM";
724 fsi->chan = is_play ? 759 fsi->chan = is_play ?
725 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); 760 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
726 data = CR_FMT(CR_TDM) | (fsi->chan - 1); 761 data = CR_TDM | (fsi->chan - 1);
727 break; 762 break;
728 case SH_FSI_FMT_TDM_DELAY: 763 case SH_FSI_FMT_TDM_DELAY:
729 msg = "TDM Delay";
730 fsi->chan = is_play ? 764 fsi->chan = is_play ?
731 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); 765 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
732 data = CR_FMT(CR_TDM_D) | (fsi->chan - 1); 766 data = CR_TDM_D | (fsi->chan - 1);
767 break;
768 case SH_FSI_FMT_SPDIF:
769 if (master->core->ver < 2) {
770 dev_err(dai->dev, "This FSI can not use SPDIF\n");
771 return -EINVAL;
772 }
773 data = CR_SPDIF;
774 fsi->chan = 2;
775 fsi_spdif_clk_ctrl(fsi, 1);
776 fsi_reg_mask_set(fsi, OUT_SEL, 0x0010, 0x0010);
733 break; 777 break;
734 default: 778 default:
735 dev_err(dai->dev, "unknown format.\n"); 779 dev_err(dai->dev, "unknown format.\n");
@@ -737,12 +781,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
737 } 781 }
738 fsi_reg_write(fsi, reg, data); 782 fsi_reg_write(fsi, reg, data);
739 783
740 /*
741 * clear clk reset if master mode
742 */
743 if (is_master)
744 fsi_clk_ctrl(fsi, 1);
745
746 /* irq clear */ 784 /* irq clear */
747 fsi_irq_disable(fsi, is_play); 785 fsi_irq_disable(fsi, is_play);
748 fsi_irq_clear_status(fsi); 786 fsi_irq_clear_status(fsi);
@@ -789,10 +827,93 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
789 return ret; 827 return ret;
790} 828}
791 829
830static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
831 struct snd_pcm_hw_params *params,
832 struct snd_soc_dai *dai)
833{
834 struct fsi_priv *fsi = fsi_get_priv(substream);
835 struct fsi_master *master = fsi_get_master(fsi);
836 int (*set_rate)(int is_porta, int rate) = master->info->set_rate;
837 int fsi_ver = master->core->ver;
838 int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
839 int ret;
840
841 /* if slave mode, set_rate is not needed */
842 if (!fsi_is_master_mode(fsi, is_play))
843 return 0;
844
845 /* it is error if no set_rate */
846 if (!set_rate)
847 return -EIO;
848
849 ret = set_rate(fsi_is_port_a(fsi), params_rate(params));
850 if (ret > 0) {
851 u32 data = 0;
852
853 switch (ret & SH_FSI_ACKMD_MASK) {
854 default:
855 /* FALL THROUGH */
856 case SH_FSI_ACKMD_512:
857 data |= (0x0 << 12);
858 break;
859 case SH_FSI_ACKMD_256:
860 data |= (0x1 << 12);
861 break;
862 case SH_FSI_ACKMD_128:
863 data |= (0x2 << 12);
864 break;
865 case SH_FSI_ACKMD_64:
866 data |= (0x3 << 12);
867 break;
868 case SH_FSI_ACKMD_32:
869 if (fsi_ver < 2)
870 dev_err(dai->dev, "unsupported ACKMD\n");
871 else
872 data |= (0x4 << 12);
873 break;
874 }
875
876 switch (ret & SH_FSI_BPFMD_MASK) {
877 default:
878 /* FALL THROUGH */
879 case SH_FSI_BPFMD_32:
880 data |= (0x0 << 8);
881 break;
882 case SH_FSI_BPFMD_64:
883 data |= (0x1 << 8);
884 break;
885 case SH_FSI_BPFMD_128:
886 data |= (0x2 << 8);
887 break;
888 case SH_FSI_BPFMD_256:
889 data |= (0x3 << 8);
890 break;
891 case SH_FSI_BPFMD_512:
892 data |= (0x4 << 8);
893 break;
894 case SH_FSI_BPFMD_16:
895 if (fsi_ver < 2)
896 dev_err(dai->dev, "unsupported ACKMD\n");
897 else
898 data |= (0x7 << 8);
899 break;
900 }
901
902 fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data);
903 udelay(10);
904 fsi_clk_ctrl(fsi, 1);
905 ret = 0;
906 }
907
908 return ret;
909
910}
911
792static struct snd_soc_dai_ops fsi_dai_ops = { 912static struct snd_soc_dai_ops fsi_dai_ops = {
793 .startup = fsi_dai_startup, 913 .startup = fsi_dai_startup,
794 .shutdown = fsi_dai_shutdown, 914 .shutdown = fsi_dai_shutdown,
795 .trigger = fsi_dai_trigger, 915 .trigger = fsi_dai_trigger,
916 .hw_params = fsi_dai_hw_params,
796}; 917};
797 918
798/************************************************************************ 919/************************************************************************
@@ -965,11 +1086,6 @@ static int fsi_probe(struct platform_device *pdev)
965 unsigned int irq; 1086 unsigned int irq;
966 int ret; 1087 int ret;
967 1088
968 if (0 != pdev->id) {
969 dev_err(&pdev->dev, "current fsi support id 0 only now\n");
970 return -ENODEV;
971 }
972
973 id_entry = pdev->id_entry; 1089 id_entry = pdev->id_entry;
974 if (!id_entry) { 1090 if (!id_entry) {
975 dev_err(&pdev->dev, "unknown fsi device\n"); 1091 dev_err(&pdev->dev, "unknown fsi device\n");
@@ -998,14 +1114,21 @@ static int fsi_probe(struct platform_device *pdev)
998 goto exit_kfree; 1114 goto exit_kfree;
999 } 1115 }
1000 1116
1117 /* master setting */
1001 master->irq = irq; 1118 master->irq = irq;
1002 master->info = pdev->dev.platform_data; 1119 master->info = pdev->dev.platform_data;
1120 master->core = (struct fsi_core *)id_entry->driver_data;
1121 spin_lock_init(&master->lock);
1122
1123 /* FSI A setting */
1003 master->fsia.base = master->base; 1124 master->fsia.base = master->base;
1004 master->fsia.master = master; 1125 master->fsia.master = master;
1126 master->fsia.mst_ctrl = A_MST_CTLR;
1127
1128 /* FSI B setting */
1005 master->fsib.base = master->base + 0x40; 1129 master->fsib.base = master->base + 0x40;
1006 master->fsib.master = master; 1130 master->fsib.master = master;
1007 master->regs = (struct fsi_regs *)id_entry->driver_data; 1131 master->fsib.mst_ctrl = B_MST_CTLR;
1008 spin_lock_init(&master->lock);
1009 1132
1010 pm_runtime_enable(&pdev->dev); 1133 pm_runtime_enable(&pdev->dev);
1011 pm_runtime_resume(&pdev->dev); 1134 pm_runtime_resume(&pdev->dev);
@@ -1085,21 +1208,27 @@ static struct dev_pm_ops fsi_pm_ops = {
1085 .runtime_resume = fsi_runtime_nop, 1208 .runtime_resume = fsi_runtime_nop,
1086}; 1209};
1087 1210
1088static struct fsi_regs fsi_regs = { 1211static struct fsi_core fsi1_core = {
1212 .ver = 1,
1213
1214 /* Interrupt */
1089 .int_st = INT_ST, 1215 .int_st = INT_ST,
1090 .iemsk = IEMSK, 1216 .iemsk = IEMSK,
1091 .imsk = IMSK, 1217 .imsk = IMSK,
1092}; 1218};
1093 1219
1094static struct fsi_regs fsi2_regs = { 1220static struct fsi_core fsi2_core = {
1221 .ver = 2,
1222
1223 /* Interrupt */
1095 .int_st = CPU_INT_ST, 1224 .int_st = CPU_INT_ST,
1096 .iemsk = CPU_IEMSK, 1225 .iemsk = CPU_IEMSK,
1097 .imsk = CPU_IMSK, 1226 .imsk = CPU_IMSK,
1098}; 1227};
1099 1228
1100static struct platform_device_id fsi_id_table[] = { 1229static struct platform_device_id fsi_id_table[] = {
1101 { "sh_fsi", (kernel_ulong_t)&fsi_regs }, 1230 { "sh_fsi", (kernel_ulong_t)&fsi1_core },
1102 { "sh_fsi2", (kernel_ulong_t)&fsi2_regs }, 1231 { "sh_fsi2", (kernel_ulong_t)&fsi2_core },
1103}; 1232};
1104 1233
1105static struct platform_driver fsi_driver = { 1234static struct platform_driver fsi_driver = {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e048e0910099..844ae8221a3a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -84,7 +84,7 @@ static int run_delayed_work(struct delayed_work *dwork)
84/* codec register dump */ 84/* codec register dump */
85static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) 85static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
86{ 86{
87 int i, step = 1, count = 0; 87 int ret, i, step = 1, count = 0;
88 88
89 if (!codec->reg_cache_size) 89 if (!codec->reg_cache_size)
90 return 0; 90 return 0;
@@ -101,12 +101,24 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
101 if (count >= PAGE_SIZE - 1) 101 if (count >= PAGE_SIZE - 1)
102 break; 102 break;
103 103
104 if (codec->display_register) 104 if (codec->display_register) {
105 count += codec->display_register(codec, buf + count, 105 count += codec->display_register(codec, buf + count,
106 PAGE_SIZE - count, i); 106 PAGE_SIZE - count, i);
107 else 107 } else {
108 count += snprintf(buf + count, PAGE_SIZE - count, 108 /* If the read fails it's almost certainly due to
109 "%4x", codec->read(codec, i)); 109 * the register being volatile and the device being
110 * powered off.
111 */
112 ret = codec->read(codec, i);
113 if (ret >= 0)
114 count += snprintf(buf + count,
115 PAGE_SIZE - count,
116 "%4x", ret);
117 else
118 count += snprintf(buf + count,
119 PAGE_SIZE - count,
120 "<no data: %d>", ret);
121 }
110 122
111 if (count >= PAGE_SIZE - 1) 123 if (count >= PAGE_SIZE - 1)
112 break; 124 break;
@@ -2353,6 +2365,99 @@ int snd_soc_limit_volume(struct snd_soc_codec *codec,
2353EXPORT_SYMBOL_GPL(snd_soc_limit_volume); 2365EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
2354 2366
2355/** 2367/**
2368 * snd_soc_info_volsw_2r_sx - double with tlv and variable data size
2369 * mixer info callback
2370 * @kcontrol: mixer control
2371 * @uinfo: control element information
2372 *
2373 * Returns 0 for success.
2374 */
2375int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol,
2376 struct snd_ctl_elem_info *uinfo)
2377{
2378 struct soc_mixer_control *mc =
2379 (struct soc_mixer_control *)kcontrol->private_value;
2380 int max = mc->max;
2381 int min = mc->min;
2382
2383 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2384 uinfo->count = 2;
2385 uinfo->value.integer.min = 0;
2386 uinfo->value.integer.max = max-min;
2387
2388 return 0;
2389}
2390EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r_sx);
2391
2392/**
2393 * snd_soc_get_volsw_2r_sx - double with tlv and variable data size
2394 * mixer get callback
2395 * @kcontrol: mixer control
2396 * @uinfo: control element information
2397 *
2398 * Returns 0 for success.
2399 */
2400int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol,
2401 struct snd_ctl_elem_value *ucontrol)
2402{
2403 struct soc_mixer_control *mc =
2404 (struct soc_mixer_control *)kcontrol->private_value;
2405 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2406 unsigned int mask = (1<<mc->shift)-1;
2407 int min = mc->min;
2408 int val = snd_soc_read(codec, mc->reg) & mask;
2409 int valr = snd_soc_read(codec, mc->rreg) & mask;
2410
2411 ucontrol->value.integer.value[0] = ((val & 0xff)-min) & mask;
2412 ucontrol->value.integer.value[1] = ((valr & 0xff)-min) & mask;
2413 return 0;
2414}
2415EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r_sx);
2416
2417/**
2418 * snd_soc_put_volsw_2r_sx - double with tlv and variable data size
2419 * mixer put callback
2420 * @kcontrol: mixer control
2421 * @uinfo: control element information
2422 *
2423 * Returns 0 for success.
2424 */
2425int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
2426 struct snd_ctl_elem_value *ucontrol)
2427{
2428 struct soc_mixer_control *mc =
2429 (struct soc_mixer_control *)kcontrol->private_value;
2430 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2431 unsigned int mask = (1<<mc->shift)-1;
2432 int min = mc->min;
2433 int ret;
2434 unsigned int val, valr, oval, ovalr;
2435
2436 val = ((ucontrol->value.integer.value[0]+min) & 0xff);
2437 val &= mask;
2438 valr = ((ucontrol->value.integer.value[1]+min) & 0xff);
2439 valr &= mask;
2440
2441 oval = snd_soc_read(codec, mc->reg) & mask;
2442 ovalr = snd_soc_read(codec, mc->rreg) & mask;
2443
2444 ret = 0;
2445 if (oval != val) {
2446 ret = snd_soc_write(codec, mc->reg, val);
2447 if (ret < 0)
2448 return ret;
2449 }
2450 if (ovalr != valr) {
2451 ret = snd_soc_write(codec, mc->rreg, valr);
2452 if (ret < 0)
2453 return ret;
2454 }
2455
2456 return 0;
2457}
2458EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
2459
2460/**
2356 * snd_soc_dai_set_sysclk - configure DAI system or master clock. 2461 * snd_soc_dai_set_sysclk - configure DAI system or master clock.
2357 * @dai: DAI 2462 * @dai: DAI
2358 * @clk_id: DAI specific clock ID 2463 * @clk_id: DAI specific clock ID
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 7c2d677a2df5..cb61317df509 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -576,8 +576,6 @@ static int soundcore_open(struct inode *inode, struct file *file)
576 struct sound_unit *s; 576 struct sound_unit *s;
577 const struct file_operations *new_fops = NULL; 577 const struct file_operations *new_fops = NULL;
578 578
579 lock_kernel ();
580
581 chain=unit&0x0F; 579 chain=unit&0x0F;
582 if(chain==4 || chain==5) /* dsp/audio/dsp16 */ 580 if(chain==4 || chain==5) /* dsp/audio/dsp16 */
583 { 581 {
@@ -630,18 +628,19 @@ static int soundcore_open(struct inode *inode, struct file *file)
630 const struct file_operations *old_fops = file->f_op; 628 const struct file_operations *old_fops = file->f_op;
631 file->f_op = new_fops; 629 file->f_op = new_fops;
632 spin_unlock(&sound_loader_lock); 630 spin_unlock(&sound_loader_lock);
633 if(file->f_op->open) 631
632 if (file->f_op->open)
634 err = file->f_op->open(inode,file); 633 err = file->f_op->open(inode,file);
634
635 if (err) { 635 if (err) {
636 fops_put(file->f_op); 636 fops_put(file->f_op);
637 file->f_op = fops_get(old_fops); 637 file->f_op = fops_get(old_fops);
638 } 638 }
639
639 fops_put(old_fops); 640 fops_put(old_fops);
640 unlock_kernel();
641 return err; 641 return err;
642 } 642 }
643 spin_unlock(&sound_loader_lock); 643 spin_unlock(&sound_loader_lock);
644 unlock_kernel();
645 return -ENODEV; 644 return -ENODEV;
646} 645}
647 646
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 7a8ac1d81be7..9feb00c831a0 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -217,7 +217,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
217 217
218 switch (protocol) { 218 switch (protocol) {
219 case UAC_VERSION_1: { 219 case UAC_VERSION_1: {
220 struct uac_ac_header_descriptor_v1 *h1 = control_header; 220 struct uac1_ac_header_descriptor *h1 = control_header;
221 221
222 if (!h1->bInCollection) { 222 if (!h1->bInCollection) {
223 snd_printk(KERN_INFO "skipping empty audio interface (v1)\n"); 223 snd_printk(KERN_INFO "skipping empty audio interface (v1)\n");
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index b5855114667e..b853f8df794f 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -19,33 +19,19 @@
19 19
20#include <linux/bitops.h> 20#include <linux/bitops.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/list.h>
23#include <linux/slab.h>
24#include <linux/string.h> 22#include <linux/string.h>
25#include <linux/usb.h> 23#include <linux/usb.h>
26#include <linux/moduleparam.h>
27#include <linux/mutex.h>
28#include <linux/usb/audio.h> 24#include <linux/usb/audio.h>
29#include <linux/usb/audio-v2.h> 25#include <linux/usb/audio-v2.h>
30 26
31#include <sound/core.h> 27#include <sound/core.h>
32#include <sound/info.h> 28#include <sound/info.h>
33#include <sound/pcm.h> 29#include <sound/pcm.h>
34#include <sound/pcm_params.h>
35#include <sound/initval.h>
36 30
37#include "usbaudio.h" 31#include "usbaudio.h"
38#include "card.h" 32#include "card.h"
39#include "midi.h"
40#include "mixer.h"
41#include "proc.h"
42#include "quirks.h"
43#include "endpoint.h"
44#include "helper.h" 33#include "helper.h"
45#include "debug.h" 34#include "clock.h"
46#include "pcm.h"
47#include "urb.h"
48#include "format.h"
49 35
50static struct uac_clock_source_descriptor * 36static struct uac_clock_source_descriptor *
51 snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface, 37 snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
@@ -134,10 +120,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
134 return !!data; 120 return !!data;
135} 121}
136 122
137/* Try to find the clock source ID of a given clock entity */
138
139static int __uac_clock_find_source(struct snd_usb_audio *chip, 123static int __uac_clock_find_source(struct snd_usb_audio *chip,
140 struct usb_host_interface *host_iface,
141 int entity_id, unsigned long *visited) 124 int entity_id, unsigned long *visited)
142{ 125{
143 struct uac_clock_source_descriptor *source; 126 struct uac_clock_source_descriptor *source;
@@ -154,11 +137,11 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
154 } 137 }
155 138
156 /* first, see if the ID we're looking for is a clock source already */ 139 /* first, see if the ID we're looking for is a clock source already */
157 source = snd_usb_find_clock_source(host_iface, entity_id); 140 source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
158 if (source) 141 if (source)
159 return source->bClockID; 142 return source->bClockID;
160 143
161 selector = snd_usb_find_clock_selector(host_iface, entity_id); 144 selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id);
162 if (selector) { 145 if (selector) {
163 int ret; 146 int ret;
164 147
@@ -168,6 +151,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
168 if (ret < 0) 151 if (ret < 0)
169 return ret; 152 return ret;
170 153
154 /* Selector values are one-based */
155
171 if (ret > selector->bNrInPins || ret < 1) { 156 if (ret > selector->bNrInPins || ret < 1) {
172 printk(KERN_ERR 157 printk(KERN_ERR
173 "%s(): selector reported illegal value, id %d, ret %d\n", 158 "%s(): selector reported illegal value, id %d, ret %d\n",
@@ -176,27 +161,35 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
176 return -EINVAL; 161 return -EINVAL;
177 } 162 }
178 163
179 return __uac_clock_find_source(chip, host_iface, 164 return __uac_clock_find_source(chip, selector->baCSourceID[ret-1],
180 selector->baCSourceID[ret-1],
181 visited); 165 visited);
182 } 166 }
183 167
184 /* FIXME: multipliers only act as pass-thru element for now */ 168 /* FIXME: multipliers only act as pass-thru element for now */
185 multiplier = snd_usb_find_clock_multiplier(host_iface, entity_id); 169 multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
186 if (multiplier) 170 if (multiplier)
187 return __uac_clock_find_source(chip, host_iface, 171 return __uac_clock_find_source(chip, multiplier->bCSourceID,
188 multiplier->bCSourceID, visited); 172 visited);
189 173
190 return -EINVAL; 174 return -EINVAL;
191} 175}
192 176
193int snd_usb_clock_find_source(struct snd_usb_audio *chip, 177/*
194 struct usb_host_interface *host_iface, 178 * For all kinds of sample rate settings and other device queries,
195 int entity_id) 179 * the clock source (end-leaf) must be used. However, clock selectors,
180 * clock multipliers and sample rate converters may be specified as
181 * clock source input to terminal. This functions walks the clock path
182 * to its end and tries to find the source.
183 *
184 * The 'visited' bitfield is used internally to detect recursive loops.
185 *
186 * Returns the clock source UnitID (>=0) on success, or an error.
187 */
188int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id)
196{ 189{
197 DECLARE_BITMAP(visited, 256); 190 DECLARE_BITMAP(visited, 256);
198 memset(visited, 0, sizeof(visited)); 191 memset(visited, 0, sizeof(visited));
199 return __uac_clock_find_source(chip, host_iface, entity_id, visited); 192 return __uac_clock_find_source(chip, entity_id, visited);
200} 193}
201 194
202static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, 195static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
@@ -211,11 +204,8 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
211 ep = get_endpoint(alts, 0)->bEndpointAddress; 204 ep = get_endpoint(alts, 0)->bEndpointAddress;
212 205
213 /* if endpoint doesn't have sampling rate control, bail out */ 206 /* if endpoint doesn't have sampling rate control, bail out */
214 if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) { 207 if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE))
215 snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
216 dev->devnum, iface, fmt->altsetting);
217 return 0; 208 return 0;
218 }
219 209
220 data[0] = rate; 210 data[0] = rate;
221 data[1] = rate >> 8; 211 data[1] = rate >> 8;
@@ -254,12 +244,13 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
254 struct usb_device *dev = chip->dev; 244 struct usb_device *dev = chip->dev;
255 unsigned char data[4]; 245 unsigned char data[4];
256 int err, crate; 246 int err, crate;
257 int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fmt->clock); 247 int clock = snd_usb_clock_find_source(chip, fmt->clock);
258 248
259 if (clock < 0) 249 if (clock < 0)
260 return clock; 250 return clock;
261 251
262 if (!uac_clock_source_is_valid(chip, clock)) { 252 if (!uac_clock_source_is_valid(chip, clock)) {
253 /* TODO: should we try to find valid clock setups by ourself? */
263 snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n", 254 snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n",
264 dev->devnum, iface, fmt->altsetting, clock); 255 dev->devnum, iface, fmt->altsetting, clock);
265 return -ENXIO; 256 return -ENXIO;
diff --git a/sound/usb/clock.h b/sound/usb/clock.h
index beb253684e2d..46630936d31f 100644
--- a/sound/usb/clock.h
+++ b/sound/usb/clock.h
@@ -5,8 +5,6 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
5 struct usb_host_interface *alts, 5 struct usb_host_interface *alts,
6 struct audioformat *fmt, int rate); 6 struct audioformat *fmt, int rate);
7 7
8int snd_usb_clock_find_source(struct snd_usb_audio *chip, 8int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id);
9 struct usb_host_interface *host_iface,
10 int entity_id);
11 9
12#endif /* __USBAUDIO_CLOCK_H */ 10#endif /* __USBAUDIO_CLOCK_H */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 6f6596cf2b19..1a701f1e8f50 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -33,6 +33,7 @@
33#include "pcm.h" 33#include "pcm.h"
34#include "helper.h" 34#include "helper.h"
35#include "format.h" 35#include "format.h"
36#include "clock.h"
36 37
37/* 38/*
38 * free a substream 39 * free a substream
@@ -275,7 +276,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
275 /* get audio formats */ 276 /* get audio formats */
276 switch (protocol) { 277 switch (protocol) {
277 case UAC_VERSION_1: { 278 case UAC_VERSION_1: {
278 struct uac_as_header_descriptor_v1 *as = 279 struct uac1_as_header_descriptor *as =
279 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); 280 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
280 281
281 if (!as) { 282 if (!as) {
@@ -297,7 +298,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
297 case UAC_VERSION_2: { 298 case UAC_VERSION_2: {
298 struct uac2_input_terminal_descriptor *input_term; 299 struct uac2_input_terminal_descriptor *input_term;
299 struct uac2_output_terminal_descriptor *output_term; 300 struct uac2_output_terminal_descriptor *output_term;
300 struct uac_as_header_descriptor_v2 *as = 301 struct uac2_as_header_descriptor *as =
301 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); 302 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
302 303
303 if (!as) { 304 if (!as) {
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 30364aba79cc..4387f54d73db 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -264,13 +264,12 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
264 * on the audioformat table (audio class v2). 264 * on the audioformat table (audio class v2).
265 */ 265 */
266static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, 266static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
267 struct audioformat *fp, 267 struct audioformat *fp)
268 struct usb_host_interface *iface)
269{ 268{
270 struct usb_device *dev = chip->dev; 269 struct usb_device *dev = chip->dev;
271 unsigned char tmp[2], *data; 270 unsigned char tmp[2], *data;
272 int nr_triplets, data_size, ret = 0; 271 int nr_triplets, data_size, ret = 0;
273 int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fp->clock); 272 int clock = snd_usb_clock_find_source(chip, fp->clock);
274 273
275 if (clock < 0) { 274 if (clock < 0) {
276 snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n", 275 snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
@@ -391,7 +390,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
391 break; 390 break;
392 case UAC_VERSION_2: 391 case UAC_VERSION_2:
393 /* fp->channels is already set in this case */ 392 /* fp->channels is already set in this case */
394 ret = parse_audio_format_rates_v2(chip, fp, iface); 393 ret = parse_audio_format_rates_v2(chip, fp);
395 break; 394 break;
396 } 395 }
397 396
@@ -450,7 +449,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
450 framesize = le16_to_cpu(fmt->wSamplesPerFrame); 449 framesize = le16_to_cpu(fmt->wSamplesPerFrame);
451 snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); 450 snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
452 fp->frame_size = framesize; 451 fp->frame_size = framesize;
453 ret = parse_audio_format_rates_v2(chip, fp, iface); 452 ret = parse_audio_format_rates_v2(chip, fp);
454 break; 453 break;
455 } 454 }
456 } 455 }
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 46785643c66d..b9c2bc65f51a 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -434,7 +434,7 @@ static void snd_usbmidi_maudio_broken_running_status_input(
434 u8 cin = buffer[i] & 0x0f; 434 u8 cin = buffer[i] & 0x0f;
435 struct usbmidi_in_port *port = &ep->ports[cable]; 435 struct usbmidi_in_port *port = &ep->ports[cable];
436 int length; 436 int length;
437 437
438 length = snd_usbmidi_cin_length[cin]; 438 length = snd_usbmidi_cin_length[cin];
439 if (cin == 0xf && buffer[i + 1] >= 0xf8) 439 if (cin == 0xf && buffer[i + 1] >= 0xf8)
440 ; /* realtime msg: no running status change */ 440 ; /* realtime msg: no running status change */
@@ -628,13 +628,13 @@ static struct usb_protocol_ops snd_usbmidi_standard_ops = {
628 628
629static struct usb_protocol_ops snd_usbmidi_midiman_ops = { 629static struct usb_protocol_ops snd_usbmidi_midiman_ops = {
630 .input = snd_usbmidi_midiman_input, 630 .input = snd_usbmidi_midiman_input,
631 .output = snd_usbmidi_standard_output, 631 .output = snd_usbmidi_standard_output,
632 .output_packet = snd_usbmidi_output_midiman_packet, 632 .output_packet = snd_usbmidi_output_midiman_packet,
633}; 633};
634 634
635static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = { 635static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
636 .input = snd_usbmidi_maudio_broken_running_status_input, 636 .input = snd_usbmidi_maudio_broken_running_status_input,
637 .output = snd_usbmidi_standard_output, 637 .output = snd_usbmidi_standard_output,
638 .output_packet = snd_usbmidi_output_standard_packet, 638 .output_packet = snd_usbmidi_output_standard_packet,
639}; 639};
640 640
@@ -1248,7 +1248,7 @@ static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep
1248 */ 1248 */
1249static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, 1249static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
1250 struct snd_usb_midi_endpoint_info* ep_info, 1250 struct snd_usb_midi_endpoint_info* ep_info,
1251 struct snd_usb_midi_endpoint* rep) 1251 struct snd_usb_midi_endpoint* rep)
1252{ 1252{
1253 struct snd_usb_midi_out_endpoint* ep; 1253 struct snd_usb_midi_out_endpoint* ep;
1254 unsigned int i; 1254 unsigned int i;
@@ -1398,7 +1398,7 @@ static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
1398} 1398}
1399 1399
1400static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi, 1400static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi,
1401 int stream, int number) 1401 int stream, int number)
1402{ 1402{
1403 struct list_head* list; 1403 struct list_head* list;
1404 1404
@@ -1811,7 +1811,7 @@ static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi,
1811 snd_usbmidi_switch_roland_altsetting(umidi); 1811 snd_usbmidi_switch_roland_altsetting(umidi);
1812 1812
1813 if (endpoint[0].out_ep || endpoint[0].in_ep) 1813 if (endpoint[0].out_ep || endpoint[0].in_ep)
1814 return 0; 1814 return 0;
1815 1815
1816 intf = umidi->iface; 1816 intf = umidi->iface;
1817 if (!intf || intf->num_altsetting < 1) 1817 if (!intf || intf->num_altsetting < 1)
@@ -1849,7 +1849,7 @@ static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi,
1849 struct snd_usb_midi_endpoint_info* endpoints) 1849 struct snd_usb_midi_endpoint_info* endpoints)
1850{ 1850{
1851 int err, i; 1851 int err, i;
1852 1852
1853 err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS); 1853 err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS);
1854 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { 1854 for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
1855 if (endpoints[i].out_ep) 1855 if (endpoints[i].out_ep)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 736d134cc03c..c166db0057d3 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -26,6 +26,22 @@
26 * 26 *
27 */ 27 */
28 28
29/*
30 * TODOs, for both the mixer and the streaming interfaces:
31 *
32 * - support for UAC2 effect units
33 * - support for graphical equalizers
34 * - RANGE and MEM set commands (UAC2)
35 * - RANGE and MEM interrupt dispatchers (UAC2)
36 * - audio channel clustering (UAC2)
37 * - audio sample rate converter units (UAC2)
38 * - proper handling of clock multipliers (UAC2)
39 * - dispatch clock change notifications (UAC2)
40 * - stop PCM streams which use a clock that became invalid
41 * - stop PCM streams which use a clock selector that has changed
42 * - parse available sample rates again when clock sources changed
43 */
44
29#include <linux/bitops.h> 45#include <linux/bitops.h>
30#include <linux/init.h> 46#include <linux/init.h>
31#include <linux/list.h> 47#include <linux/list.h>
@@ -275,28 +291,28 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
275 291
276static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) 292static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
277{ 293{
294 struct snd_usb_audio *chip = cval->mixer->chip;
278 unsigned char buf[2]; 295 unsigned char buf[2];
279 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 296 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
280 int timeout = 10; 297 int timeout = 10;
281 298
282 while (timeout-- > 0) { 299 while (timeout-- > 0) {
283 if (snd_usb_ctl_msg(cval->mixer->chip->dev, 300 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
284 usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
285 request,
286 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 301 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
287 validx, cval->mixer->ctrlif | (cval->id << 8), 302 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
288 buf, val_len, 100) >= val_len) { 303 buf, val_len, 100) >= val_len) {
289 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); 304 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
290 return 0; 305 return 0;
291 } 306 }
292 } 307 }
293 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 308 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
294 request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type); 309 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
295 return -EINVAL; 310 return -EINVAL;
296} 311}
297 312
298static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) 313static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
299{ 314{
315 struct snd_usb_audio *chip = cval->mixer->chip;
300 unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ 316 unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
301 unsigned char *val; 317 unsigned char *val;
302 int ret, size; 318 int ret, size;
@@ -312,16 +328,14 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
312 328
313 memset(buf, 0, sizeof(buf)); 329 memset(buf, 0, sizeof(buf));
314 330
315 ret = snd_usb_ctl_msg(cval->mixer->chip->dev, 331 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
316 usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
317 bRequest,
318 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 332 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
319 validx, cval->mixer->ctrlif | (cval->id << 8), 333 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
320 buf, size, 1000); 334 buf, size, 1000);
321 335
322 if (ret < 0) { 336 if (ret < 0) {
323 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 337 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
324 request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type); 338 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
325 return ret; 339 return ret;
326 } 340 }
327 341
@@ -397,6 +411,7 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
397int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, 411int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
398 int request, int validx, int value_set) 412 int request, int validx, int value_set)
399{ 413{
414 struct snd_usb_audio *chip = cval->mixer->chip;
400 unsigned char buf[2]; 415 unsigned char buf[2];
401 int val_len, timeout = 10; 416 int val_len, timeout = 10;
402 417
@@ -419,15 +434,14 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
419 buf[0] = value_set & 0xff; 434 buf[0] = value_set & 0xff;
420 buf[1] = (value_set >> 8) & 0xff; 435 buf[1] = (value_set >> 8) & 0xff;
421 while (timeout-- > 0) 436 while (timeout-- > 0)
422 if (snd_usb_ctl_msg(cval->mixer->chip->dev, 437 if (snd_usb_ctl_msg(chip->dev,
423 usb_sndctrlpipe(cval->mixer->chip->dev, 0), 438 usb_sndctrlpipe(chip->dev, 0), request,
424 request,
425 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 439 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
426 validx, cval->mixer->ctrlif | (cval->id << 8), 440 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
427 buf, val_len, 100) >= 0) 441 buf, val_len, 100) >= 0)
428 return 0; 442 return 0;
429 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", 443 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
430 request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); 444 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
431 return -EINVAL; 445 return -EINVAL;
432} 446}
433 447
@@ -582,9 +596,9 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
582 switch (iterm->type >> 16) { 596 switch (iterm->type >> 16) {
583 case UAC_SELECTOR_UNIT: 597 case UAC_SELECTOR_UNIT:
584 strcpy(name, "Selector"); return 8; 598 strcpy(name, "Selector"); return 8;
585 case UAC_PROCESSING_UNIT_V1: 599 case UAC1_PROCESSING_UNIT:
586 strcpy(name, "Process Unit"); return 12; 600 strcpy(name, "Process Unit"); return 12;
587 case UAC_EXTENSION_UNIT_V1: 601 case UAC1_EXTENSION_UNIT:
588 strcpy(name, "Ext Unit"); return 8; 602 strcpy(name, "Ext Unit"); return 8;
589 case UAC_MIXER_UNIT: 603 case UAC_MIXER_UNIT:
590 strcpy(name, "Mixer"); return 5; 604 strcpy(name, "Mixer"); return 5;
@@ -672,8 +686,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
672 term->name = uac_selector_unit_iSelector(d); 686 term->name = uac_selector_unit_iSelector(d);
673 return 0; 687 return 0;
674 } 688 }
675 case UAC_PROCESSING_UNIT_V1: 689 case UAC1_PROCESSING_UNIT:
676 case UAC_EXTENSION_UNIT_V1: { 690 case UAC1_EXTENSION_UNIT: {
677 struct uac_processing_unit_descriptor *d = p1; 691 struct uac_processing_unit_descriptor *d = p1;
678 if (d->bNrInPins) { 692 if (d->bNrInPins) {
679 id = d->baSourceID[0]; 693 id = d->baSourceID[0];
@@ -745,6 +759,8 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
745 */ 759 */
746static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) 760static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
747{ 761{
762 struct snd_usb_audio *chip = cval->mixer->chip;
763
748 /* for failsafe */ 764 /* for failsafe */
749 cval->min = default_min; 765 cval->min = default_min;
750 cval->max = cval->min + 1; 766 cval->max = cval->min + 1;
@@ -767,7 +783,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
767 if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || 783 if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
768 get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { 784 get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
769 snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", 785 snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
770 cval->id, cval->mixer->ctrlif, cval->control, cval->id); 786 cval->id, snd_usb_ctrl_intf(chip), cval->control, cval->id);
771 return -EINVAL; 787 return -EINVAL;
772 } 788 }
773 if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { 789 if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -1199,14 +1215,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
1199 } 1215 }
1200 } else { /* UAC_VERSION_2 */ 1216 } else { /* UAC_VERSION_2 */
1201 for (i = 0; i < 30/2; i++) { 1217 for (i = 0; i < 30/2; i++) {
1202 /* From the USB Audio spec v2.0:
1203 bmaControls() is a (ch+1)-element array of 4-byte bitmaps,
1204 each containing a set of bit pairs. If a Control is present,
1205 it must be Host readable. If a certain Control is not
1206 present then the bit pair must be set to 0b00.
1207 If a Control is present but read-only, the bit pair must be
1208 set to 0b01. If a Control is also Host programmable, the bit
1209 pair must be set to 0b11. The value 0b10 is not allowed. */
1210 unsigned int ch_bits = 0; 1218 unsigned int ch_bits = 0;
1211 unsigned int ch_read_only = 0; 1219 unsigned int ch_read_only = 0;
1212 1220
@@ -1855,13 +1863,13 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
1855 return parse_audio_selector_unit(state, unitid, p1); 1863 return parse_audio_selector_unit(state, unitid, p1);
1856 case UAC_FEATURE_UNIT: 1864 case UAC_FEATURE_UNIT:
1857 return parse_audio_feature_unit(state, unitid, p1); 1865 return parse_audio_feature_unit(state, unitid, p1);
1858 case UAC_PROCESSING_UNIT_V1: 1866 case UAC1_PROCESSING_UNIT:
1859 /* UAC2_EFFECT_UNIT has the same value */ 1867 /* UAC2_EFFECT_UNIT has the same value */
1860 if (state->mixer->protocol == UAC_VERSION_1) 1868 if (state->mixer->protocol == UAC_VERSION_1)
1861 return parse_audio_processing_unit(state, unitid, p1); 1869 return parse_audio_processing_unit(state, unitid, p1);
1862 else 1870 else
1863 return 0; /* FIXME - effect units not implemented yet */ 1871 return 0; /* FIXME - effect units not implemented yet */
1864 case UAC_EXTENSION_UNIT_V1: 1872 case UAC1_EXTENSION_UNIT:
1865 /* UAC2_PROCESSING_UNIT_V2 has the same value */ 1873 /* UAC2_PROCESSING_UNIT_V2 has the same value */
1866 if (state->mixer->protocol == UAC_VERSION_1) 1874 if (state->mixer->protocol == UAC_VERSION_1)
1867 return parse_audio_extension_unit(state, unitid, p1); 1875 return parse_audio_extension_unit(state, unitid, p1);
@@ -1905,7 +1913,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1905 struct usb_host_interface *hostif; 1913 struct usb_host_interface *hostif;
1906 void *p; 1914 void *p;
1907 1915
1908 hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; 1916 hostif = mixer->chip->ctrl_intf;
1909 memset(&state, 0, sizeof(state)); 1917 memset(&state, 0, sizeof(state));
1910 state.chip = mixer->chip; 1918 state.chip = mixer->chip;
1911 state.mixer = mixer; 1919 state.mixer = mixer;
@@ -1925,7 +1933,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
1925 p = NULL; 1933 p = NULL;
1926 while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) { 1934 while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) {
1927 if (mixer->protocol == UAC_VERSION_1) { 1935 if (mixer->protocol == UAC_VERSION_1) {
1928 struct uac_output_terminal_descriptor_v1 *desc = p; 1936 struct uac1_output_terminal_descriptor *desc = p;
1929 1937
1930 if (desc->bLength < sizeof(*desc)) 1938 if (desc->bLength < sizeof(*desc))
1931 continue; /* invalid descriptor? */ 1939 continue; /* invalid descriptor? */
@@ -1997,7 +2005,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
1997 list_for_each_entry(mixer, &chip->mixer_list, list) { 2005 list_for_each_entry(mixer, &chip->mixer_list, list) {
1998 snd_iprintf(buffer, 2006 snd_iprintf(buffer,
1999 "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n", 2007 "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n",
2000 chip->usb_id, mixer->ctrlif, 2008 chip->usb_id, snd_usb_ctrl_intf(chip),
2001 mixer->ignore_ctl_error); 2009 mixer->ignore_ctl_error);
2002 snd_iprintf(buffer, "Card: %s\n", chip->card->longname); 2010 snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
2003 for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { 2011 for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
@@ -2115,7 +2123,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
2115 int buffer_length; 2123 int buffer_length;
2116 unsigned int epnum; 2124 unsigned int epnum;
2117 2125
2118 hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; 2126 hostif = mixer->chip->ctrl_intf;
2119 /* we need one interrupt input endpoint */ 2127 /* we need one interrupt input endpoint */
2120 if (get_iface_desc(hostif)->bNumEndpoints < 1) 2128 if (get_iface_desc(hostif)->bNumEndpoints < 1)
2121 return 0; 2129 return 0;
@@ -2158,7 +2166,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
2158 if (!mixer) 2166 if (!mixer)
2159 return -ENOMEM; 2167 return -ENOMEM;
2160 mixer->chip = chip; 2168 mixer->chip = chip;
2161 mixer->ctrlif = ctrlif;
2162 mixer->ignore_ctl_error = ignore_error; 2169 mixer->ignore_ctl_error = ignore_error;
2163 mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems), 2170 mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems),
2164 GFP_KERNEL); 2171 GFP_KERNEL);
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index a7cf1007fbb0..26c636c5c93a 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -3,7 +3,6 @@
3 3
4struct usb_mixer_interface { 4struct usb_mixer_interface {
5 struct snd_usb_audio *chip; 5 struct snd_usb_audio *chip;
6 unsigned int ctrlif;
7 struct list_head list; 6 struct list_head list;
8 unsigned int ignore_ctl_error; 7 unsigned int ignore_ctl_error;
9 struct urb *urb; 8 struct urb *urb;
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
index 1c931b68f3b5..ed3e283f618d 100644
--- a/sound/usb/pcm.h
+++ b/sound/usb/pcm.h
@@ -7,8 +7,5 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
7 struct usb_host_interface *alts, 7 struct usb_host_interface *alts,
8 struct audioformat *fmt); 8 struct audioformat *fmt);
9 9
10int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
11 struct usb_host_interface *alts,
12 struct audioformat *fmt, int rate);
13 10
14#endif /* __USBAUDIO_PCM_H */ 11#endif /* __USBAUDIO_PCM_H */
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index f8797f61a24b..2e8003f98fca 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2152,7 +2152,21 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2152 } 2152 }
2153}, 2153},
2154{ 2154{
2155 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7201), 2155 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240),
2156 .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2157 USB_DEVICE_ID_MATCH_INT_CLASS |
2158 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
2159 .bInterfaceClass = USB_CLASS_AUDIO,
2160 .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
2161 .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
2162 .vendor_name = "Hauppauge",
2163 .product_name = "HVR-850",
2164 .ifnum = QUIRK_ANY_INTERFACE,
2165 .type = QUIRK_AUDIO_ALIGN_TRANSFER,
2166 }
2167},
2168{
2169 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210),
2156 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2170 .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2157 USB_DEVICE_ID_MATCH_INT_CLASS | 2171 USB_DEVICE_ID_MATCH_INT_CLASS |
2158 USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2172 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2166,7 +2180,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2166 } 2180 }
2167}, 2181},
2168{ 2182{
2169 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7202), 2183 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217),
2170 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2184 .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2171 USB_DEVICE_ID_MATCH_INT_CLASS | 2185 USB_DEVICE_ID_MATCH_INT_CLASS |
2172 USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2186 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2180,7 +2194,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2180 } 2194 }
2181}, 2195},
2182{ 2196{
2183 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7203), 2197 USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b),
2184 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2198 .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2185 USB_DEVICE_ID_MATCH_INT_CLASS | 2199 USB_DEVICE_ID_MATCH_INT_CLASS |
2186 USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2200 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2194,7 +2208,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2194 } 2208 }
2195}, 2209},
2196{ 2210{
2197 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7204), 2211 USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e),
2198 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2212 .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2199 USB_DEVICE_ID_MATCH_INT_CLASS | 2213 USB_DEVICE_ID_MATCH_INT_CLASS |
2200 USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2214 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2208,7 +2222,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2208 } 2222 }
2209}, 2223},
2210{ 2224{
2211 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7205), 2225 USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f),
2212 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2226 .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2213 USB_DEVICE_ID_MATCH_INT_CLASS | 2227 USB_DEVICE_ID_MATCH_INT_CLASS |
2214 USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2228 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2222,7 +2236,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2222 } 2236 }
2223}, 2237},
2224{ 2238{
2225 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7250), 2239 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7280),
2226 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2240 .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2227 USB_DEVICE_ID_MATCH_INT_CLASS | 2241 USB_DEVICE_ID_MATCH_INT_CLASS |
2228 USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2242 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2236,7 +2250,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2236 } 2250 }
2237}, 2251},
2238{ 2252{
2239 USB_DEVICE_VENDOR_SPEC(0x2040, 0x7230), 2253 USB_DEVICE_VENDOR_SPEC(0x0fd9, 0x0008),
2240 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2254 .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2241 USB_DEVICE_ID_MATCH_INT_CLASS | 2255 USB_DEVICE_ID_MATCH_INT_CLASS |
2242 USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2256 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2244,7 +2258,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2244 .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, 2258 .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
2245 .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { 2259 .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
2246 .vendor_name = "Hauppauge", 2260 .vendor_name = "Hauppauge",
2247 .product_name = "HVR-850", 2261 .product_name = "HVR-950Q",
2248 .ifnum = QUIRK_ANY_INTERFACE, 2262 .ifnum = QUIRK_ANY_INTERFACE,
2249 .type = QUIRK_AUDIO_ALIGN_TRANSFER, 2263 .type = QUIRK_AUDIO_ALIGN_TRANSFER,
2250 } 2264 }
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index b45e54c09ba2..9a9da09586a5 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -32,6 +32,7 @@
32#include "helper.h" 32#include "helper.h"
33#include "endpoint.h" 33#include "endpoint.h"
34#include "pcm.h" 34#include "pcm.h"
35#include "clock.h"
35 36
36/* 37/*
37 * handle the quirks for the contained interfaces 38 * handle the quirks for the contained interfaces