diff options
Diffstat (limited to 'sound')
68 files changed, 2628 insertions, 918 deletions
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 678933721735..3ff8cc5f487a 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c | |||
@@ -437,9 +437,11 @@ static int i2sbus_shutdown(struct macio_dev* dev) | |||
437 | } | 437 | } |
438 | 438 | ||
439 | static struct macio_driver i2sbus_drv = { | 439 | static struct macio_driver i2sbus_drv = { |
440 | .name = "soundbus-i2s", | 440 | .driver = { |
441 | .owner = THIS_MODULE, | 441 | .name = "soundbus-i2s", |
442 | .match_table = i2sbus_match, | 442 | .owner = THIS_MODULE, |
443 | .of_match_table = i2sbus_match, | ||
444 | }, | ||
443 | .probe = i2sbus_probe, | 445 | .probe = i2sbus_probe, |
444 | .remove = i2sbus_remove, | 446 | .remove = i2sbus_remove, |
445 | #ifdef CONFIG_PM | 447 | #ifdef CONFIG_PM |
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 428121a7e705..10c3a871a12d 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c | |||
@@ -657,7 +657,7 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) | |||
657 | if (sr & AC97C_SR_CAEVT) { | 657 | if (sr & AC97C_SR_CAEVT) { |
658 | struct snd_pcm_runtime *runtime; | 658 | struct snd_pcm_runtime *runtime; |
659 | int offset, next_period, block_size; | 659 | int offset, next_period, block_size; |
660 | dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", | 660 | dev_dbg(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", |
661 | casr & AC97C_CSR_OVRUN ? " OVRUN" : "", | 661 | casr & AC97C_CSR_OVRUN ? " OVRUN" : "", |
662 | casr & AC97C_CSR_RXRDY ? " RXRDY" : "", | 662 | casr & AC97C_CSR_RXRDY ? " RXRDY" : "", |
663 | casr & AC97C_CSR_UNRUN ? " UNRUN" : "", | 663 | casr & AC97C_CSR_UNRUN ? " UNRUN" : "", |
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 | */ |
1710 | static int wait_for_avail_min(struct snd_pcm_substream *substream, | 1715 | static 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 84714a65e5c8..32646000ab90 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 | ||
177 | config SND_AC97_POWER_SAVE_DEFAULT | 193 | config 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 | |||
185 | endif # SND_DRIVERS | 203 | endif # 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/ad1848.c b/sound/oss/ad1848.c index 24793c5b65ac..4d2a6ae978f7 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c | |||
@@ -716,7 +716,7 @@ static int ad1848_mixer_ioctl(int dev, unsigned int cmd, void __user *arg) | |||
716 | 716 | ||
717 | default: | 717 | default: |
718 | if (get_user(val, (int __user *)arg)) | 718 | if (get_user(val, (int __user *)arg)) |
719 | return -EFAULT; | 719 | return -EFAULT; |
720 | val = ad1848_mixer_set(devc, cmd & 0xff, val); | 720 | val = ad1848_mixer_set(devc, cmd & 0xff, val); |
721 | break; | 721 | break; |
722 | } | 722 | } |
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index c1070e33b32f..c6f2621221ba 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c | |||
@@ -43,13 +43,13 @@ | |||
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> |
49 | #include <linux/poll.h> | 50 | #include <linux/poll.h> |
50 | #include <linux/bitops.h> | 51 | #include <linux/bitops.h> |
51 | #include <linux/spinlock.h> | 52 | #include <linux/spinlock.h> |
52 | #include <linux/smp_lock.h> | ||
53 | #include <linux/ac97_codec.h> | 53 | #include <linux/ac97_codec.h> |
54 | #include <linux/mutex.h> | 54 | #include <linux/mutex.h> |
55 | 55 | ||
@@ -162,19 +162,10 @@ ld2(unsigned int x) | |||
162 | static void | 162 | static void |
163 | au1550_delay(int msec) | 163 | au1550_delay(int msec) |
164 | { | 164 | { |
165 | unsigned long tmo; | ||
166 | signed long tmo2; | ||
167 | |||
168 | if (in_interrupt()) | 165 | if (in_interrupt()) |
169 | return; | 166 | return; |
170 | 167 | ||
171 | tmo = jiffies + (msec * HZ) / 1000; | 168 | 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 | } | 169 | } |
179 | 170 | ||
180 | static u16 | 171 | static u16 |
@@ -807,7 +798,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin) | |||
807 | static int | 798 | static int |
808 | au1550_open_mixdev(struct inode *inode, struct file *file) | 799 | au1550_open_mixdev(struct inode *inode, struct file *file) |
809 | { | 800 | { |
801 | lock_kernel(); | ||
810 | file->private_data = &au1550_state; | 802 | file->private_data = &au1550_state; |
803 | unlock_kernel(); | ||
811 | return 0; | 804 | return 0; |
812 | } | 805 | } |
813 | 806 | ||
@@ -824,22 +817,26 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, | |||
824 | return codec->mixer_ioctl(codec, cmd, arg); | 817 | return codec->mixer_ioctl(codec, cmd, arg); |
825 | } | 818 | } |
826 | 819 | ||
827 | static int | 820 | static long |
828 | au1550_ioctl_mixdev(struct inode *inode, struct file *file, | 821 | au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg) |
829 | unsigned int cmd, unsigned long arg) | ||
830 | { | 822 | { |
831 | struct au1550_state *s = (struct au1550_state *)file->private_data; | 823 | struct au1550_state *s = (struct au1550_state *)file->private_data; |
832 | struct ac97_codec *codec = s->codec; | 824 | struct ac97_codec *codec = s->codec; |
825 | int ret; | ||
833 | 826 | ||
834 | return mixdev_ioctl(codec, cmd, arg); | 827 | lock_kernel(); |
828 | ret = mixdev_ioctl(codec, cmd, arg); | ||
829 | unlock_kernel(); | ||
830 | |||
831 | return ret; | ||
835 | } | 832 | } |
836 | 833 | ||
837 | static /*const */ struct file_operations au1550_mixer_fops = { | 834 | static /*const */ struct file_operations au1550_mixer_fops = { |
838 | owner:THIS_MODULE, | 835 | .owner = THIS_MODULE, |
839 | llseek:au1550_llseek, | 836 | .llseek = au1550_llseek, |
840 | ioctl:au1550_ioctl_mixdev, | 837 | .unlocked_ioctl = au1550_ioctl_mixdev, |
841 | open:au1550_open_mixdev, | 838 | .open = au1550_open_mixdev, |
842 | release:au1550_release_mixdev, | 839 | .release = au1550_release_mixdev, |
843 | }; | 840 | }; |
844 | 841 | ||
845 | static int | 842 | static int |
@@ -1343,8 +1340,7 @@ dma_count_done(struct dmabuf *db) | |||
1343 | 1340 | ||
1344 | 1341 | ||
1345 | static int | 1342 | static int |
1346 | au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 1343 | au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1347 | unsigned long arg) | ||
1348 | { | 1344 | { |
1349 | struct au1550_state *s = (struct au1550_state *)file->private_data; | 1345 | struct au1550_state *s = (struct au1550_state *)file->private_data; |
1350 | unsigned long flags; | 1346 | unsigned long flags; |
@@ -1780,6 +1776,17 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
1780 | return mixdev_ioctl(s->codec, cmd, arg); | 1776 | return mixdev_ioctl(s->codec, cmd, arg); |
1781 | } | 1777 | } |
1782 | 1778 | ||
1779 | static long | ||
1780 | au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1781 | { | ||
1782 | int ret; | ||
1783 | |||
1784 | lock_kernel(); | ||
1785 | ret = au1550_ioctl(file, cmd, arg); | ||
1786 | unlock_kernel(); | ||
1787 | |||
1788 | return ret; | ||
1789 | } | ||
1783 | 1790 | ||
1784 | static int | 1791 | static int |
1785 | au1550_open(struct inode *inode, struct file *file) | 1792 | au1550_open(struct inode *inode, struct file *file) |
@@ -1797,21 +1804,22 @@ au1550_open(struct inode *inode, struct file *file) | |||
1797 | #endif | 1804 | #endif |
1798 | 1805 | ||
1799 | file->private_data = s; | 1806 | file->private_data = s; |
1807 | lock_kernel(); | ||
1800 | /* wait for device to become free */ | 1808 | /* wait for device to become free */ |
1801 | mutex_lock(&s->open_mutex); | 1809 | mutex_lock(&s->open_mutex); |
1802 | while (s->open_mode & file->f_mode) { | 1810 | while (s->open_mode & file->f_mode) { |
1803 | if (file->f_flags & O_NONBLOCK) { | 1811 | ret = -EBUSY; |
1804 | mutex_unlock(&s->open_mutex); | 1812 | if (file->f_flags & O_NONBLOCK) |
1805 | return -EBUSY; | 1813 | goto out; |
1806 | } | ||
1807 | add_wait_queue(&s->open_wait, &wait); | 1814 | add_wait_queue(&s->open_wait, &wait); |
1808 | __set_current_state(TASK_INTERRUPTIBLE); | 1815 | __set_current_state(TASK_INTERRUPTIBLE); |
1809 | mutex_unlock(&s->open_mutex); | 1816 | mutex_unlock(&s->open_mutex); |
1810 | schedule(); | 1817 | schedule(); |
1811 | remove_wait_queue(&s->open_wait, &wait); | 1818 | remove_wait_queue(&s->open_wait, &wait); |
1812 | set_current_state(TASK_RUNNING); | 1819 | set_current_state(TASK_RUNNING); |
1820 | ret = -ERESTARTSYS; | ||
1813 | if (signal_pending(current)) | 1821 | if (signal_pending(current)) |
1814 | return -ERESTARTSYS; | 1822 | goto out2; |
1815 | mutex_lock(&s->open_mutex); | 1823 | mutex_lock(&s->open_mutex); |
1816 | } | 1824 | } |
1817 | 1825 | ||
@@ -1840,17 +1848,21 @@ au1550_open(struct inode *inode, struct file *file) | |||
1840 | 1848 | ||
1841 | if (file->f_mode & FMODE_READ) { | 1849 | if (file->f_mode & FMODE_READ) { |
1842 | if ((ret = prog_dmabuf_adc(s))) | 1850 | if ((ret = prog_dmabuf_adc(s))) |
1843 | return ret; | 1851 | goto out; |
1844 | } | 1852 | } |
1845 | if (file->f_mode & FMODE_WRITE) { | 1853 | if (file->f_mode & FMODE_WRITE) { |
1846 | if ((ret = prog_dmabuf_dac(s))) | 1854 | if ((ret = prog_dmabuf_dac(s))) |
1847 | return ret; | 1855 | goto out; |
1848 | } | 1856 | } |
1849 | 1857 | ||
1850 | s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | 1858 | s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); |
1851 | mutex_unlock(&s->open_mutex); | ||
1852 | mutex_init(&s->sem); | 1859 | mutex_init(&s->sem); |
1853 | return 0; | 1860 | ret = 0; |
1861 | out: | ||
1862 | mutex_unlock(&s->open_mutex); | ||
1863 | out2: | ||
1864 | unlock_kernel(); | ||
1865 | return ret; | ||
1854 | } | 1866 | } |
1855 | 1867 | ||
1856 | static int | 1868 | static int |
@@ -1885,15 +1897,15 @@ au1550_release(struct inode *inode, struct file *file) | |||
1885 | } | 1897 | } |
1886 | 1898 | ||
1887 | static /*const */ struct file_operations au1550_audio_fops = { | 1899 | static /*const */ struct file_operations au1550_audio_fops = { |
1888 | owner: THIS_MODULE, | 1900 | .owner = THIS_MODULE, |
1889 | llseek: au1550_llseek, | 1901 | .llseek = au1550_llseek, |
1890 | read: au1550_read, | 1902 | .read = au1550_read, |
1891 | write: au1550_write, | 1903 | .write = au1550_write, |
1892 | poll: au1550_poll, | 1904 | .poll = au1550_poll, |
1893 | ioctl: au1550_ioctl, | 1905 | .unlocked_ioctl = au1550_unlocked_ioctl, |
1894 | mmap: au1550_mmap, | 1906 | .mmap = au1550_mmap, |
1895 | open: au1550_open, | 1907 | .open = au1550_open, |
1896 | release: au1550_release, | 1908 | .release = au1550_release, |
1897 | }; | 1909 | }; |
1898 | 1910 | ||
1899 | MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com"); | 1911 | MODULE_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 | ||
324 | static int mixer_open(struct inode *inode, struct file *file) | 324 | static 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 | } |
340 | static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, | 344 | |
341 | u_long arg) | 345 | static 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 | ||
369 | static 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 | |||
365 | static const struct file_operations mixer_fops = | 380 | static 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 | ||
958 | static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, | 977 | static 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 | ||
1140 | static 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 | |||
1122 | static const struct file_operations sq_fops = | 1151 | static 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; |
1331 | out: | ||
1332 | unlock_kernel(); | ||
1333 | return ret; | ||
1297 | } | 1334 | } |
1298 | 1335 | ||
1299 | static int state_release(struct inode *inode, struct file *file) | 1336 | static 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 | ||
642 | static int dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 642 | static 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 | ||
659 | static void dsp_write_flush(void) | 664 | static 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 | 793 | out: | |
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 | ||
95 | static int dac_audio_ioctl(struct inode *inode, struct file *file, | 97 | static 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 | ||
163 | static 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 | |||
161 | static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count, | 174 | static 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 | ||
238 | const struct file_operations dac_audio_fops = { | 255 | const 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 | ||
1569 | static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file, | 1574 | static 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, | |||
1580 | static const struct file_operations cs4297a_mixer_fops = { | 1589 | static 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 | ||
1947 | static int cs4297a_ioctl(struct inode *inode, struct file *file, | 1956 | static 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 | ||
2349 | static 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 | ||
2341 | static int cs4297a_release(struct inode *inode, struct file *file) | 2360 | static 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 | ||
2372 | static int cs4297a_open(struct inode *inode, struct file *file) | 2391 | static 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 | ||
2508 | static 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 | ||
499 | irq_failed: | 496 | irq_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 | ||
2432 | static int vwsnd_audio_do_ioctl(struct inode *inode, | 2432 | static 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 | ||
2888 | static int vwsnd_audio_ioctl(struct inode *inode, | 2887 | static 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 | ||
3206 | static int vwsnd_mixer_ioctl(struct inode *ioctl, | 3215 | static 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 | ||
3231 | static const struct file_operations vwsnd_mixer_fops = { | 3241 | static 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) | |||
184 | static inline int | 184 | static inline int |
185 | waveartist_sleep(int timeout_ms) | 185 | waveartist_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 | ||
197 | static int | 191 | static 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 f74c7372b3d1..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 | ||
1384 | compile_time_assert( | 1386 | compile_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 | ||
1415 | compile_time_assert( | 1417 | compile_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 | ||
1420 | static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl, | 1422 | static 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 | } |
@@ -2578,6 +2580,9 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2578 | if (err) | 2580 | if (err) |
2579 | return -err; | 2581 | return -err; |
2580 | 2582 | ||
2583 | memset(&prev_ctl, 0, sizeof(prev_ctl)); | ||
2584 | prev_ctl.control_type = -1; | ||
2585 | |||
2581 | for (idx = 0; idx < 2000; idx++) { | 2586 | for (idx = 0; idx < 2000; idx++) { |
2582 | err = hpi_mixer_get_control_by_index( | 2587 | err = hpi_mixer_get_control_by_index( |
2583 | ss, asihpi->h_mixer, | 2588 | ss, asihpi->h_mixer, |
@@ -2600,8 +2605,8 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2600 | 2605 | ||
2601 | } | 2606 | } |
2602 | 2607 | ||
2603 | hpi_ctl.src_node_type -= HPI_SOURCENODE_BASE; | 2608 | hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE; |
2604 | hpi_ctl.dst_node_type -= HPI_DESTNODE_BASE; | 2609 | hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE; |
2605 | 2610 | ||
2606 | /* ASI50xx in SSX mode has multiple meters on the same node. | 2611 | /* ASI50xx in SSX mode has multiple meters on the same node. |
2607 | 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) | |||
432 | Property 1 - adapter can do samplerate conversion (MRX) | 429 | Property 1 - adapter can do samplerate conversion (MRX) |
433 | Property 2 - adapter can do timestretch (TSX) | 430 | Property 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. | ||
438 | Indicates the adapter supports SSX2 in some mode setting. The | ||
439 | return value is true (1) or false (0). If the current adapter | ||
440 | mode is MONO SSX2 is disabled, even though this property will | ||
441 | return 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 | ||
829 | Superseded 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 | ||
1830 | u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1830 | u16 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 | |
1833 | u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys, | ||
1834 | u32 h_control, u32 *pon); | ||
1835 | |||
1836 | u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys, | ||
1837 | u32 h_control, short makeup_gain0_01dB); | ||
1838 | |||
1839 | u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys, | ||
1840 | u32 h_control, short *pn_makeup_gain0_01dB); | ||
1841 | |||
1842 | u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys | ||
1843 | *ph_subsys, u32 h_control, u32 index, u32 attack); | ||
1844 | |||
1845 | u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys | ||
1846 | *ph_subsys, u32 h_control, u32 index, u32 *pw_attack); | ||
1847 | |||
1848 | u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys, | ||
1849 | u32 h_control, u32 index, u32 decay); | ||
1850 | |||
1851 | u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys, | ||
1852 | u32 h_control, u32 index, u32 *pw_decay); | ||
1853 | |||
1854 | u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys, | ||
1855 | u32 h_control, u32 index, short threshold0_01dB); | ||
1856 | |||
1857 | u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys, | ||
1858 | u32 h_control, u32 index, short *pn_threshold0_01dB); | ||
1859 | |||
1860 | u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys, | ||
1861 | u32 h_control, u32 index, u32 ratio100); | ||
1833 | 1862 | ||
1834 | u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1863 | u16 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/hpi6205.c b/sound/pci/asihpi/hpi6205.c index e89991ea3543..3b4413448226 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c | |||
@@ -941,11 +941,11 @@ static void outstream_host_buffer_free(struct hpi_adapter_obj *pao, | |||
941 | 941 | ||
942 | } | 942 | } |
943 | 943 | ||
944 | static long outstream_get_space_available(struct hpi_hostbuffer_status | 944 | static u32 outstream_get_space_available(struct hpi_hostbuffer_status |
945 | *status) | 945 | *status) |
946 | { | 946 | { |
947 | return status->size_in_bytes - ((long)(status->host_index) - | 947 | return status->size_in_bytes - (status->host_index - |
948 | (long)(status->dSP_index)); | 948 | status->dSP_index); |
949 | } | 949 | } |
950 | 950 | ||
951 | static void outstream_write(struct hpi_adapter_obj *pao, | 951 | static void outstream_write(struct hpi_adapter_obj *pao, |
@@ -954,7 +954,7 @@ static void outstream_write(struct hpi_adapter_obj *pao, | |||
954 | struct hpi_hw_obj *phw = pao->priv; | 954 | struct hpi_hw_obj *phw = pao->priv; |
955 | struct bus_master_interface *interface = phw->p_interface_buffer; | 955 | struct bus_master_interface *interface = phw->p_interface_buffer; |
956 | struct hpi_hostbuffer_status *status; | 956 | struct hpi_hostbuffer_status *status; |
957 | long space_available; | 957 | u32 space_available; |
958 | 958 | ||
959 | if (!phw->outstream_host_buffer_size[phm->obj_index]) { | 959 | if (!phw->outstream_host_buffer_size[phm->obj_index]) { |
960 | /* there is no BBM buffer, write via message */ | 960 | /* there is no BBM buffer, write via message */ |
@@ -1007,7 +1007,7 @@ static void outstream_write(struct hpi_adapter_obj *pao, | |||
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | space_available = outstream_get_space_available(status); | 1009 | space_available = outstream_get_space_available(status); |
1010 | if (space_available < (long)phm->u.d.u.data.data_size) { | 1010 | if (space_available < phm->u.d.u.data.data_size) { |
1011 | phr->error = HPI_ERROR_INVALID_DATASIZE; | 1011 | phr->error = HPI_ERROR_INVALID_DATASIZE; |
1012 | return; | 1012 | return; |
1013 | } | 1013 | } |
@@ -1018,7 +1018,7 @@ static void outstream_write(struct hpi_adapter_obj *pao, | |||
1018 | && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm-> | 1018 | && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm-> |
1019 | obj_index])) { | 1019 | obj_index])) { |
1020 | u8 *p_bbm_data; | 1020 | u8 *p_bbm_data; |
1021 | long l_first_write; | 1021 | u32 l_first_write; |
1022 | u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data; | 1022 | u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data; |
1023 | 1023 | ||
1024 | if (hpios_locked_mem_get_virt_addr(&phw-> | 1024 | if (hpios_locked_mem_get_virt_addr(&phw-> |
@@ -1248,9 +1248,9 @@ static void instream_start(struct hpi_adapter_obj *pao, | |||
1248 | hw_message(pao, phm, phr); | 1248 | hw_message(pao, phm, phr); |
1249 | } | 1249 | } |
1250 | 1250 | ||
1251 | static long instream_get_bytes_available(struct hpi_hostbuffer_status *status) | 1251 | static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status) |
1252 | { | 1252 | { |
1253 | return (long)(status->dSP_index) - (long)(status->host_index); | 1253 | return status->dSP_index - status->host_index; |
1254 | } | 1254 | } |
1255 | 1255 | ||
1256 | static void instream_read(struct hpi_adapter_obj *pao, | 1256 | static void instream_read(struct hpi_adapter_obj *pao, |
@@ -1259,9 +1259,9 @@ static void instream_read(struct hpi_adapter_obj *pao, | |||
1259 | struct hpi_hw_obj *phw = pao->priv; | 1259 | struct hpi_hw_obj *phw = pao->priv; |
1260 | struct bus_master_interface *interface = phw->p_interface_buffer; | 1260 | struct bus_master_interface *interface = phw->p_interface_buffer; |
1261 | struct hpi_hostbuffer_status *status; | 1261 | struct hpi_hostbuffer_status *status; |
1262 | long data_available; | 1262 | u32 data_available; |
1263 | u8 *p_bbm_data; | 1263 | u8 *p_bbm_data; |
1264 | long l_first_read; | 1264 | u32 l_first_read; |
1265 | u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data; | 1265 | u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data; |
1266 | 1266 | ||
1267 | if (!phw->instream_host_buffer_size[phm->obj_index]) { | 1267 | if (!phw->instream_host_buffer_size[phm->obj_index]) { |
@@ -1272,7 +1272,7 @@ static void instream_read(struct hpi_adapter_obj *pao, | |||
1272 | 1272 | ||
1273 | status = &interface->instream_host_buffer_status[phm->obj_index]; | 1273 | status = &interface->instream_host_buffer_status[phm->obj_index]; |
1274 | data_available = instream_get_bytes_available(status); | 1274 | data_available = instream_get_bytes_available(status); |
1275 | if (data_available < (long)phm->u.d.u.data.data_size) { | 1275 | if (data_available < phm->u.d.u.data.data_size) { |
1276 | phr->error = HPI_ERROR_INVALID_DATASIZE; | 1276 | phr->error = HPI_ERROR_INVALID_DATASIZE; |
1277 | return; | 1277 | return; |
1278 | } | 1278 | } |
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 | ||
106 | struct hpi_entity_str { | 106 | struct 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 | ||
359 | compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_BASE + 1) == | 359 | compile_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 | } |
373 | compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_BASE + 1) == (8), | 373 | compile_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 | ||
97 | static struct hpi_hsubsys gh_subsys; | 97 | static struct hpi_hsubsys gh_subsys; |
98 | 98 | ||
99 | struct hpi_hsubsys *hpi_subsys_create(void | 99 | struct 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 | ||
1596 | static 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 | |||
1594 | static | 1612 | static |
1595 | u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys, | 1613 | u16 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) | 1640 | static 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 | ||
1625 | static | 1657 | static |
1626 | u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys, | 1658 | u16 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 | ||
1646 | static u16 hpi_control_get_string(const struct hpi_hsubsys *ph_subsys, | 1679 | static 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 | ||
2106 | u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2143 | u16 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 | |||
2150 | u16 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 | |||
2157 | u16 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 | |||
2164 | u16 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 | |||
2171 | u16 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 | |||
2178 | u16 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 | |||
2185 | u16 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 | |||
2192 | u16 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 | |||
2200 | u16 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 | ||
2127 | u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2218 | u16 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) | 2236 | u16 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; | 2243 | u16 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 | ||
2155 | u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2250 | u16 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 | ||
2199 | u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2284 | u16 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 | ||
2217 | u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys, | 2292 | u16 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, | |||
2623 | u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys, | 2701 | u16 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 | ||
2630 | u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys, | 2708 | u16 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, | |||
2637 | u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys, | 2715 | u16 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 | ||
2644 | u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys, | 2722 | u16 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, | |||
2651 | u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys, | 2729 | u16 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 | ||
2658 | u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys, | 2736 | u16 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, | |||
2665 | u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys, | 2743 | u16 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 | ||
2672 | u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys, | 2750 | u16 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 | ||
2679 | u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys, | 2757 | u16 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, | |||
2686 | u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys, | 2764 | u16 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 | ||
2693 | u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys, | 2771 | u16 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 | ||
2700 | u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys, | 2778 | u16 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 | ||
2707 | u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys, | 2785 | u16 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 | ||
2714 | u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys, | 2792 | u16 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 | ||
2721 | u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys, | 2799 | u16 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 | ||
2728 | u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys, | 2806 | u16 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 | ||
2735 | u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys, | 2813 | u16 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, | |||
2894 | u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys, | 2974 | u16 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 | ||
2901 | u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys, | 2981 | u16 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, | |||
2942 | u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys, | 3022 | u16 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 | ||
2949 | u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys, | 3029 | u16 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 | ||
2956 | u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys, | 3036 | u16 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, | |||
2981 | u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys, | 3062 | u16 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 | ||
2988 | u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 3069 | u16 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 | ||
2995 | u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 3076 | u16 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 | ||
3002 | u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 3083 | u16 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 | ||
3009 | u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys, | 3090 | u16 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 | ||
3016 | u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 3097 | u16 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 | ||
3023 | u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys, | 3104 | u16 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 | ||
3048 | u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 3119 | u16 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 | ||
3066 | u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 3127 | u16 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 | ||
3173 | inline size_t hpi_entity_size(struct hpi_entity *entity_ptr) | 3236 | static 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 | ||
3178 | inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr) | 3241 | static 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 | ||
3183 | inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr) | 3246 | static 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 | ||
3189 | inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr) | 3252 | static 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 | ||
3195 | inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity | 3258 | static 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 | ||
3202 | inline u16 hpi_entity_check_type(const enum e_entity_type t) | 3264 | static 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 | ||
3209 | inline u16 hpi_entity_check_role(const enum e_entity_role r) | 3271 | static 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 a3d638c8c1fd..720a81d711e3 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; |
@@ -784,6 +789,9 @@ static int read_pin_defaults(struct hda_codec *codec) | |||
784 | pin->nid = nid; | 789 | pin->nid = nid; |
785 | pin->cfg = snd_hda_codec_read(codec, nid, 0, | 790 | pin->cfg = snd_hda_codec_read(codec, nid, 0, |
786 | AC_VERB_GET_CONFIG_DEFAULT, 0); | 791 | AC_VERB_GET_CONFIG_DEFAULT, 0); |
792 | pin->ctrl = snd_hda_codec_read(codec, nid, 0, | ||
793 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
794 | 0); | ||
787 | } | 795 | } |
788 | return 0; | 796 | return 0; |
789 | } | 797 | } |
@@ -912,15 +920,38 @@ static void restore_pincfgs(struct hda_codec *codec) | |||
912 | void snd_hda_shutup_pins(struct hda_codec *codec) | 920 | void snd_hda_shutup_pins(struct hda_codec *codec) |
913 | { | 921 | { |
914 | int i; | 922 | int i; |
923 | /* don't shut up pins when unloading the driver; otherwise it breaks | ||
924 | * the default pin setup at the next load of the driver | ||
925 | */ | ||
926 | if (codec->bus->shutdown) | ||
927 | return; | ||
915 | for (i = 0; i < codec->init_pins.used; i++) { | 928 | for (i = 0; i < codec->init_pins.used; i++) { |
916 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | 929 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); |
917 | /* use read here for syncing after issuing each verb */ | 930 | /* use read here for syncing after issuing each verb */ |
918 | snd_hda_codec_read(codec, pin->nid, 0, | 931 | snd_hda_codec_read(codec, pin->nid, 0, |
919 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | 932 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); |
920 | } | 933 | } |
934 | codec->pins_shutup = 1; | ||
921 | } | 935 | } |
922 | EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); | 936 | EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); |
923 | 937 | ||
938 | /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */ | ||
939 | static void restore_shutup_pins(struct hda_codec *codec) | ||
940 | { | ||
941 | int i; | ||
942 | if (!codec->pins_shutup) | ||
943 | return; | ||
944 | if (codec->bus->shutdown) | ||
945 | return; | ||
946 | for (i = 0; i < codec->init_pins.used; i++) { | ||
947 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
948 | snd_hda_codec_write(codec, pin->nid, 0, | ||
949 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
950 | pin->ctrl); | ||
951 | } | ||
952 | codec->pins_shutup = 0; | ||
953 | } | ||
954 | |||
924 | static void init_hda_cache(struct hda_cache_rec *cache, | 955 | static void init_hda_cache(struct hda_cache_rec *cache, |
925 | unsigned int record_size); | 956 | unsigned int record_size); |
926 | static void free_hda_cache(struct hda_cache_rec *cache); | 957 | static void free_hda_cache(struct hda_cache_rec *cache); |
@@ -940,6 +971,36 @@ static void restore_init_pincfgs(struct hda_codec *codec) | |||
940 | } | 971 | } |
941 | 972 | ||
942 | /* | 973 | /* |
974 | * audio-converter setup caches | ||
975 | */ | ||
976 | struct hda_cvt_setup { | ||
977 | hda_nid_t nid; | ||
978 | u8 stream_tag; | ||
979 | u8 channel_id; | ||
980 | u16 format_id; | ||
981 | unsigned char active; /* cvt is currently used */ | ||
982 | unsigned char dirty; /* setups should be cleared */ | ||
983 | }; | ||
984 | |||
985 | /* get or create a cache entry for the given audio converter NID */ | ||
986 | static struct hda_cvt_setup * | ||
987 | get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) | ||
988 | { | ||
989 | struct hda_cvt_setup *p; | ||
990 | int i; | ||
991 | |||
992 | for (i = 0; i < codec->cvt_setups.used; i++) { | ||
993 | p = snd_array_elem(&codec->cvt_setups, i); | ||
994 | if (p->nid == nid) | ||
995 | return p; | ||
996 | } | ||
997 | p = snd_array_new(&codec->cvt_setups); | ||
998 | if (p) | ||
999 | p->nid = nid; | ||
1000 | return p; | ||
1001 | } | ||
1002 | |||
1003 | /* | ||
943 | * codec destructor | 1004 | * codec destructor |
944 | */ | 1005 | */ |
945 | static void snd_hda_codec_free(struct hda_codec *codec) | 1006 | static void snd_hda_codec_free(struct hda_codec *codec) |
@@ -1007,12 +1068,14 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
1007 | codec->addr = codec_addr; | 1068 | codec->addr = codec_addr; |
1008 | mutex_init(&codec->spdif_mutex); | 1069 | mutex_init(&codec->spdif_mutex); |
1009 | mutex_init(&codec->control_mutex); | 1070 | mutex_init(&codec->control_mutex); |
1071 | mutex_init(&codec->prepare_mutex); | ||
1010 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); | 1072 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
1011 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | 1073 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); |
1012 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); | 1074 | snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); |
1013 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); | 1075 | snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); |
1014 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | 1076 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); |
1015 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | 1077 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); |
1078 | snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); | ||
1016 | if (codec->bus->modelname) { | 1079 | if (codec->bus->modelname) { |
1017 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | 1080 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); |
1018 | if (!codec->modelname) { | 1081 | if (!codec->modelname) { |
@@ -1150,16 +1213,51 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1150 | u32 stream_tag, | 1213 | u32 stream_tag, |
1151 | int channel_id, int format) | 1214 | int channel_id, int format) |
1152 | { | 1215 | { |
1216 | struct hda_cvt_setup *p; | ||
1217 | unsigned int oldval, newval; | ||
1218 | int i; | ||
1219 | |||
1153 | if (!nid) | 1220 | if (!nid) |
1154 | return; | 1221 | return; |
1155 | 1222 | ||
1156 | snd_printdd("hda_codec_setup_stream: " | 1223 | snd_printdd("hda_codec_setup_stream: " |
1157 | "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", | 1224 | "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", |
1158 | nid, stream_tag, channel_id, format); | 1225 | nid, stream_tag, channel_id, format); |
1159 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, | 1226 | p = get_hda_cvt_setup(codec, nid); |
1160 | (stream_tag << 4) | channel_id); | 1227 | if (!p) |
1161 | msleep(1); | 1228 | return; |
1162 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); | 1229 | /* update the stream-id if changed */ |
1230 | if (p->stream_tag != stream_tag || p->channel_id != channel_id) { | ||
1231 | oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); | ||
1232 | newval = (stream_tag << 4) | channel_id; | ||
1233 | if (oldval != newval) | ||
1234 | snd_hda_codec_write(codec, nid, 0, | ||
1235 | AC_VERB_SET_CHANNEL_STREAMID, | ||
1236 | newval); | ||
1237 | p->stream_tag = stream_tag; | ||
1238 | p->channel_id = channel_id; | ||
1239 | } | ||
1240 | /* update the format-id if changed */ | ||
1241 | if (p->format_id != format) { | ||
1242 | oldval = snd_hda_codec_read(codec, nid, 0, | ||
1243 | AC_VERB_GET_STREAM_FORMAT, 0); | ||
1244 | if (oldval != format) { | ||
1245 | msleep(1); | ||
1246 | snd_hda_codec_write(codec, nid, 0, | ||
1247 | AC_VERB_SET_STREAM_FORMAT, | ||
1248 | format); | ||
1249 | } | ||
1250 | p->format_id = format; | ||
1251 | } | ||
1252 | p->active = 1; | ||
1253 | p->dirty = 0; | ||
1254 | |||
1255 | /* make other inactive cvts with the same stream-tag dirty */ | ||
1256 | for (i = 0; i < codec->cvt_setups.used; i++) { | ||
1257 | p = snd_array_elem(&codec->cvt_setups, i); | ||
1258 | if (!p->active && p->stream_tag == stream_tag) | ||
1259 | p->dirty = 1; | ||
1260 | } | ||
1163 | } | 1261 | } |
1164 | EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); | 1262 | EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); |
1165 | 1263 | ||
@@ -1170,17 +1268,54 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); | |||
1170 | */ | 1268 | */ |
1171 | void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) | 1269 | void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) |
1172 | { | 1270 | { |
1271 | struct hda_cvt_setup *p; | ||
1272 | |||
1173 | if (!nid) | 1273 | if (!nid) |
1174 | return; | 1274 | return; |
1175 | 1275 | ||
1176 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); | 1276 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); |
1277 | /* here we just clear the active flag; actual clean-ups will be done | ||
1278 | * in purify_inactive_streams() | ||
1279 | */ | ||
1280 | p = get_hda_cvt_setup(codec, nid); | ||
1281 | if (p) | ||
1282 | p->active = 0; | ||
1283 | } | ||
1284 | EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | ||
1285 | |||
1286 | static void really_cleanup_stream(struct hda_codec *codec, | ||
1287 | struct hda_cvt_setup *q) | ||
1288 | { | ||
1289 | hda_nid_t nid = q->nid; | ||
1177 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | 1290 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); |
1178 | #if 0 /* keep the format */ | ||
1179 | msleep(1); | ||
1180 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); | 1291 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); |
1181 | #endif | 1292 | memset(q, 0, sizeof(*q)); |
1293 | q->nid = nid; | ||
1294 | } | ||
1295 | |||
1296 | /* clean up the all conflicting obsolete streams */ | ||
1297 | static void purify_inactive_streams(struct hda_codec *codec) | ||
1298 | { | ||
1299 | int i; | ||
1300 | |||
1301 | for (i = 0; i < codec->cvt_setups.used; i++) { | ||
1302 | struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i); | ||
1303 | if (p->dirty) | ||
1304 | really_cleanup_stream(codec, p); | ||
1305 | } | ||
1306 | } | ||
1307 | |||
1308 | /* clean up all streams; called from suspend */ | ||
1309 | static void hda_cleanup_all_streams(struct hda_codec *codec) | ||
1310 | { | ||
1311 | int i; | ||
1312 | |||
1313 | for (i = 0; i < codec->cvt_setups.used; i++) { | ||
1314 | struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i); | ||
1315 | if (p->stream_tag) | ||
1316 | really_cleanup_stream(codec, p); | ||
1317 | } | ||
1182 | } | 1318 | } |
1183 | EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | ||
1184 | 1319 | ||
1185 | /* | 1320 | /* |
1186 | * amp access functions | 1321 | * amp access functions |
@@ -1539,6 +1674,17 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec) | |||
1539 | EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); | 1674 | EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); |
1540 | #endif /* SND_HDA_NEEDS_RESUME */ | 1675 | #endif /* SND_HDA_NEEDS_RESUME */ |
1541 | 1676 | ||
1677 | static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, | ||
1678 | unsigned int ofs) | ||
1679 | { | ||
1680 | u32 caps = query_amp_caps(codec, nid, dir); | ||
1681 | /* get num steps */ | ||
1682 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | ||
1683 | if (ofs < caps) | ||
1684 | caps -= ofs; | ||
1685 | return caps; | ||
1686 | } | ||
1687 | |||
1542 | /** | 1688 | /** |
1543 | * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer | 1689 | * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer |
1544 | * | 1690 | * |
@@ -1553,23 +1699,17 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, | |||
1553 | u8 chs = get_amp_channels(kcontrol); | 1699 | u8 chs = get_amp_channels(kcontrol); |
1554 | int dir = get_amp_direction(kcontrol); | 1700 | int dir = get_amp_direction(kcontrol); |
1555 | unsigned int ofs = get_amp_offset(kcontrol); | 1701 | unsigned int ofs = get_amp_offset(kcontrol); |
1556 | u32 caps; | ||
1557 | 1702 | ||
1558 | caps = query_amp_caps(codec, nid, dir); | 1703 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1559 | /* num steps */ | 1704 | uinfo->count = chs == 3 ? 2 : 1; |
1560 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | 1705 | uinfo->value.integer.min = 0; |
1561 | if (!caps) { | 1706 | uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs); |
1707 | if (!uinfo->value.integer.max) { | ||
1562 | printk(KERN_WARNING "hda_codec: " | 1708 | printk(KERN_WARNING "hda_codec: " |
1563 | "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, | 1709 | "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, |
1564 | kcontrol->id.name); | 1710 | kcontrol->id.name); |
1565 | return -EINVAL; | 1711 | return -EINVAL; |
1566 | } | 1712 | } |
1567 | if (ofs < caps) | ||
1568 | caps -= ofs; | ||
1569 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1570 | uinfo->count = chs == 3 ? 2 : 1; | ||
1571 | uinfo->value.integer.min = 0; | ||
1572 | uinfo->value.integer.max = caps; | ||
1573 | return 0; | 1713 | return 0; |
1574 | } | 1714 | } |
1575 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); | 1715 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); |
@@ -1594,8 +1734,14 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid, | |||
1594 | int ch, int dir, int idx, unsigned int ofs, | 1734 | int ch, int dir, int idx, unsigned int ofs, |
1595 | unsigned int val) | 1735 | unsigned int val) |
1596 | { | 1736 | { |
1737 | unsigned int maxval; | ||
1738 | |||
1597 | if (val > 0) | 1739 | if (val > 0) |
1598 | val += ofs; | 1740 | val += ofs; |
1741 | /* ofs = 0: raw max value */ | ||
1742 | maxval = get_amp_max_value(codec, nid, dir, 0); | ||
1743 | if (val > maxval) | ||
1744 | val = maxval; | ||
1599 | return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, | 1745 | return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, |
1600 | HDA_AMP_VOLMASK, val); | 1746 | HDA_AMP_VOLMASK, val); |
1601 | } | 1747 | } |
@@ -2886,6 +3032,7 @@ static void hda_call_codec_suspend(struct hda_codec *codec) | |||
2886 | { | 3032 | { |
2887 | if (codec->patch_ops.suspend) | 3033 | if (codec->patch_ops.suspend) |
2888 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); | 3034 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); |
3035 | hda_cleanup_all_streams(codec); | ||
2889 | hda_set_power_state(codec, | 3036 | hda_set_power_state(codec, |
2890 | codec->afg ? codec->afg : codec->mfg, | 3037 | codec->afg ? codec->afg : codec->mfg, |
2891 | AC_PWRST_D3); | 3038 | AC_PWRST_D3); |
@@ -2907,6 +3054,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
2907 | codec->afg ? codec->afg : codec->mfg, | 3054 | codec->afg ? codec->afg : codec->mfg, |
2908 | AC_PWRST_D0); | 3055 | AC_PWRST_D0); |
2909 | restore_pincfgs(codec); /* restore all current pin configs */ | 3056 | restore_pincfgs(codec); /* restore all current pin configs */ |
3057 | restore_shutup_pins(codec); | ||
2910 | hda_exec_init_verbs(codec); | 3058 | hda_exec_init_verbs(codec); |
2911 | if (codec->patch_ops.resume) | 3059 | if (codec->patch_ops.resume) |
2912 | codec->patch_ops.resume(codec); | 3060 | codec->patch_ops.resume(codec); |
@@ -2972,26 +3120,31 @@ struct hda_rate_tbl { | |||
2972 | unsigned int hda_fmt; | 3120 | unsigned int hda_fmt; |
2973 | }; | 3121 | }; |
2974 | 3122 | ||
3123 | /* rate = base * mult / div */ | ||
3124 | #define HDA_RATE(base, mult, div) \ | ||
3125 | (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ | ||
3126 | (((div) - 1) << AC_FMT_DIV_SHIFT)) | ||
3127 | |||
2975 | static struct hda_rate_tbl rate_bits[] = { | 3128 | static struct hda_rate_tbl rate_bits[] = { |
2976 | /* rate in Hz, ALSA rate bitmask, HDA format value */ | 3129 | /* rate in Hz, ALSA rate bitmask, HDA format value */ |
2977 | 3130 | ||
2978 | /* autodetected value used in snd_hda_query_supported_pcm */ | 3131 | /* autodetected value used in snd_hda_query_supported_pcm */ |
2979 | { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */ | 3132 | { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, |
2980 | { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */ | 3133 | { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, |
2981 | { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */ | 3134 | { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, |
2982 | { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */ | 3135 | { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, |
2983 | { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */ | 3136 | { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, |
2984 | { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */ | 3137 | { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, |
2985 | { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */ | 3138 | { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, |
2986 | { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */ | 3139 | { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, |
2987 | { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ | 3140 | { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, |
2988 | { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ | 3141 | { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, |
2989 | { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ | 3142 | { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, |
2990 | #define AC_PAR_PCM_RATE_BITS 11 | 3143 | #define AC_PAR_PCM_RATE_BITS 11 |
2991 | /* up to bits 10, 384kHZ isn't supported properly */ | 3144 | /* up to bits 10, 384kHZ isn't supported properly */ |
2992 | 3145 | ||
2993 | /* not autodetected value */ | 3146 | /* not autodetected value */ |
2994 | { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */ | 3147 | { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, |
2995 | 3148 | ||
2996 | { 0 } /* terminator */ | 3149 | { 0 } /* terminator */ |
2997 | }; | 3150 | }; |
@@ -3010,7 +3163,8 @@ static struct hda_rate_tbl rate_bits[] = { | |||
3010 | unsigned int snd_hda_calc_stream_format(unsigned int rate, | 3163 | unsigned int snd_hda_calc_stream_format(unsigned int rate, |
3011 | unsigned int channels, | 3164 | unsigned int channels, |
3012 | unsigned int format, | 3165 | unsigned int format, |
3013 | unsigned int maxbps) | 3166 | unsigned int maxbps, |
3167 | unsigned short spdif_ctls) | ||
3014 | { | 3168 | { |
3015 | int i; | 3169 | int i; |
3016 | unsigned int val = 0; | 3170 | unsigned int val = 0; |
@@ -3033,20 +3187,20 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
3033 | 3187 | ||
3034 | switch (snd_pcm_format_width(format)) { | 3188 | switch (snd_pcm_format_width(format)) { |
3035 | case 8: | 3189 | case 8: |
3036 | val |= 0x00; | 3190 | val |= AC_FMT_BITS_8; |
3037 | break; | 3191 | break; |
3038 | case 16: | 3192 | case 16: |
3039 | val |= 0x10; | 3193 | val |= AC_FMT_BITS_16; |
3040 | break; | 3194 | break; |
3041 | case 20: | 3195 | case 20: |
3042 | case 24: | 3196 | case 24: |
3043 | case 32: | 3197 | case 32: |
3044 | if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) | 3198 | if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) |
3045 | val |= 0x40; | 3199 | val |= AC_FMT_BITS_32; |
3046 | else if (maxbps >= 24) | 3200 | else if (maxbps >= 24) |
3047 | val |= 0x30; | 3201 | val |= AC_FMT_BITS_24; |
3048 | else | 3202 | else |
3049 | val |= 0x20; | 3203 | val |= AC_FMT_BITS_20; |
3050 | break; | 3204 | break; |
3051 | default: | 3205 | default: |
3052 | snd_printdd("invalid format width %d\n", | 3206 | snd_printdd("invalid format width %d\n", |
@@ -3054,6 +3208,9 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
3054 | return 0; | 3208 | return 0; |
3055 | } | 3209 | } |
3056 | 3210 | ||
3211 | if (spdif_ctls & AC_DIG1_NONAUDIO) | ||
3212 | val |= AC_FMT_TYPE_NON_PCM; | ||
3213 | |||
3057 | return val; | 3214 | return val; |
3058 | } | 3215 | } |
3059 | EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); | 3216 | EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); |
@@ -3325,6 +3482,35 @@ static int set_pcm_default_values(struct hda_codec *codec, | |||
3325 | return 0; | 3482 | return 0; |
3326 | } | 3483 | } |
3327 | 3484 | ||
3485 | /* | ||
3486 | * codec prepare/cleanup entries | ||
3487 | */ | ||
3488 | int snd_hda_codec_prepare(struct hda_codec *codec, | ||
3489 | struct hda_pcm_stream *hinfo, | ||
3490 | unsigned int stream, | ||
3491 | unsigned int format, | ||
3492 | struct snd_pcm_substream *substream) | ||
3493 | { | ||
3494 | int ret; | ||
3495 | mutex_lock(&codec->prepare_mutex); | ||
3496 | ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream); | ||
3497 | if (ret >= 0) | ||
3498 | purify_inactive_streams(codec); | ||
3499 | mutex_unlock(&codec->prepare_mutex); | ||
3500 | return ret; | ||
3501 | } | ||
3502 | EXPORT_SYMBOL_HDA(snd_hda_codec_prepare); | ||
3503 | |||
3504 | void snd_hda_codec_cleanup(struct hda_codec *codec, | ||
3505 | struct hda_pcm_stream *hinfo, | ||
3506 | struct snd_pcm_substream *substream) | ||
3507 | { | ||
3508 | mutex_lock(&codec->prepare_mutex); | ||
3509 | hinfo->ops.cleanup(hinfo, codec, substream); | ||
3510 | mutex_unlock(&codec->prepare_mutex); | ||
3511 | } | ||
3512 | EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup); | ||
3513 | |||
3328 | /* global */ | 3514 | /* global */ |
3329 | const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { | 3515 | const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { |
3330 | "Audio", "SPDIF", "HDMI", "Modem" | 3516 | "Audio", "SPDIF", "HDMI", "Modem" |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 49e939e7e5cd..3f7a479881e5 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; |
@@ -799,12 +826,14 @@ struct hda_codec { | |||
799 | 826 | ||
800 | struct mutex spdif_mutex; | 827 | struct mutex spdif_mutex; |
801 | struct mutex control_mutex; | 828 | struct mutex control_mutex; |
829 | struct mutex prepare_mutex; | ||
802 | unsigned int spdif_status; /* IEC958 status bits */ | 830 | unsigned int spdif_status; /* IEC958 status bits */ |
803 | unsigned short spdif_ctls; /* SPDIF control bits */ | 831 | unsigned short spdif_ctls; /* SPDIF control bits */ |
804 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 832 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
805 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ | 833 | hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ |
806 | struct snd_array init_pins; /* initial (BIOS) pin configurations */ | 834 | struct snd_array init_pins; /* initial (BIOS) pin configurations */ |
807 | struct snd_array driver_pins; /* pin configs set by codec parser */ | 835 | struct snd_array driver_pins; /* pin configs set by codec parser */ |
836 | struct snd_array cvt_setups; /* audio convert setups */ | ||
808 | 837 | ||
809 | #ifdef CONFIG_SND_HDA_HWDEP | 838 | #ifdef CONFIG_SND_HDA_HWDEP |
810 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | 839 | struct snd_hwdep *hwdep; /* assigned hwdep device */ |
@@ -821,6 +850,7 @@ struct hda_codec { | |||
821 | unsigned int pin_amp_workaround:1; /* pin out-amp takes index | 850 | unsigned int pin_amp_workaround:1; /* pin out-amp takes index |
822 | * (e.g. Conexant codecs) | 851 | * (e.g. Conexant codecs) |
823 | */ | 852 | */ |
853 | unsigned int pins_shutup:1; /* pins are shut up */ | ||
824 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ | 854 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ |
825 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 855 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
826 | unsigned int power_on :1; /* current (global) power-state */ | 856 | unsigned int power_on :1; /* current (global) power-state */ |
@@ -897,7 +927,9 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec); | |||
897 | /* the struct for codec->pin_configs */ | 927 | /* the struct for codec->pin_configs */ |
898 | struct hda_pincfg { | 928 | struct hda_pincfg { |
899 | hda_nid_t nid; | 929 | hda_nid_t nid; |
900 | unsigned int cfg; | 930 | unsigned char ctrl; /* current pin control value */ |
931 | unsigned char pad; /* reserved */ | ||
932 | unsigned int cfg; /* default configuration */ | ||
901 | }; | 933 | }; |
902 | 934 | ||
903 | unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid); | 935 | unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid); |
@@ -918,6 +950,16 @@ int snd_hda_codec_build_controls(struct hda_codec *codec); | |||
918 | */ | 950 | */ |
919 | int snd_hda_build_pcms(struct hda_bus *bus); | 951 | int snd_hda_build_pcms(struct hda_bus *bus); |
920 | int snd_hda_codec_build_pcms(struct hda_codec *codec); | 952 | int snd_hda_codec_build_pcms(struct hda_codec *codec); |
953 | |||
954 | int snd_hda_codec_prepare(struct hda_codec *codec, | ||
955 | struct hda_pcm_stream *hinfo, | ||
956 | unsigned int stream, | ||
957 | unsigned int format, | ||
958 | struct snd_pcm_substream *substream); | ||
959 | void snd_hda_codec_cleanup(struct hda_codec *codec, | ||
960 | struct hda_pcm_stream *hinfo, | ||
961 | struct snd_pcm_substream *substream); | ||
962 | |||
921 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | 963 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, |
922 | u32 stream_tag, | 964 | u32 stream_tag, |
923 | int channel_id, int format); | 965 | int channel_id, int format); |
@@ -925,7 +967,8 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid); | |||
925 | unsigned int snd_hda_calc_stream_format(unsigned int rate, | 967 | unsigned int snd_hda_calc_stream_format(unsigned int rate, |
926 | unsigned int channels, | 968 | unsigned int channels, |
927 | unsigned int format, | 969 | unsigned int format, |
928 | unsigned int maxbps); | 970 | unsigned int maxbps, |
971 | unsigned short spdif_ctls); | ||
929 | int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | 972 | int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, |
930 | unsigned int format); | 973 | unsigned int format); |
931 | 974 | ||
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 dc79564fea30..1053fff4bd0a 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1634,7 +1634,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1634 | azx_dev->period_bytes = 0; | 1634 | azx_dev->period_bytes = 0; |
1635 | azx_dev->format_val = 0; | 1635 | azx_dev->format_val = 0; |
1636 | 1636 | ||
1637 | hinfo->ops.cleanup(hinfo, apcm->codec, substream); | 1637 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); |
1638 | 1638 | ||
1639 | return snd_pcm_lib_free_pages(substream); | 1639 | return snd_pcm_lib_free_pages(substream); |
1640 | } | 1640 | } |
@@ -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", |
@@ -1687,8 +1688,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1687 | else | 1688 | else |
1688 | azx_dev->fifo_size = 0; | 1689 | azx_dev->fifo_size = 0; |
1689 | 1690 | ||
1690 | return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, | 1691 | return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag, |
1691 | azx_dev->format_val, substream); | 1692 | azx_dev->format_val, substream); |
1692 | } | 1693 | } |
1693 | 1694 | ||
1694 | static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 1695 | static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
@@ -1913,11 +1914,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
1913 | if (WARN_ONCE(!azx_dev->period_bytes, | 1914 | if (WARN_ONCE(!azx_dev->period_bytes, |
1914 | "hda-intel: zero azx_dev->period_bytes")) | 1915 | "hda-intel: zero azx_dev->period_bytes")) |
1915 | return -1; /* this shouldn't happen! */ | 1916 | return -1; /* this shouldn't happen! */ |
1916 | if (wallclk <= azx_dev->period_wallclk && | 1917 | if (wallclk < (azx_dev->period_wallclk * 5) / 4 && |
1917 | pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) | 1918 | pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) |
1918 | /* NG - it's below the first next period boundary */ | 1919 | /* NG - it's below the first next period boundary */ |
1919 | return bdl_pos_adj[chip->dev_index] ? 0 : -1; | 1920 | return bdl_pos_adj[chip->dev_index] ? 0 : -1; |
1920 | azx_dev->start_wallclk = wallclk; | 1921 | azx_dev->start_wallclk += wallclk; |
1921 | return 1; /* OK, it's fine */ | 1922 | return 1; /* OK, it's fine */ |
1922 | } | 1923 | } |
1923 | 1924 | ||
@@ -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 | ||
@@ -2288,6 +2289,8 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { | |||
2288 | SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), | 2289 | SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), |
2289 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), | 2290 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), |
2290 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), | 2291 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), |
2292 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), | ||
2293 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), | ||
2291 | SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), | 2294 | SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), |
2292 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), | 2295 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), |
2293 | SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB), | 2296 | SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB), |
@@ -2296,6 +2299,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { | |||
2296 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), | 2299 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), |
2297 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), | 2300 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), |
2298 | SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB), | 2301 | SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB), |
2302 | SND_PCI_QUIRK(0x1849, 0x0888, "775Dual-VSTA", POS_FIX_LPIB), | ||
2299 | SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB), | 2303 | SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB), |
2300 | SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB), | 2304 | SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB), |
2301 | {} | 2305 | {} |
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..f7e234e5ee96 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 | ||
136 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, | 138 | static 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 */ | ||
522 | static 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 | |||
518 | static const char *slave_vols[] = { | 529 | static 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 | ||
615 | static 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 | ||
586 | static struct hda_codec_ops conexant_patch_ops = { | 622 | static 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 | ||
1947 | static 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 */ |
1892 | static int cxt5051_init(struct hda_codec *codec) | 1955 | static 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 | ||
1932 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { | 1997 | static 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 | ||
@@ -3121,6 +3206,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = { | |||
3121 | .patch = patch_cxt5066 }, | 3206 | .patch = patch_cxt5066 }, |
3122 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", | 3207 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", |
3123 | .patch = patch_cxt5066 }, | 3208 | .patch = patch_cxt5066 }, |
3209 | { .id = 0x14f15068, .name = "CX20584", | ||
3210 | .patch = patch_cxt5066 }, | ||
3124 | { .id = 0x14f15069, .name = "CX20585", | 3211 | { .id = 0x14f15069, .name = "CX20585", |
3125 | .patch = patch_cxt5066 }, | 3212 | .patch = patch_cxt5066 }, |
3126 | {} /* terminator */ | 3213 | {} /* terminator */ |
@@ -3131,6 +3218,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15047"); | |||
3131 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); | 3218 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); |
3132 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); | 3219 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); |
3133 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); | 3220 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); |
3221 | MODULE_ALIAS("snd-hda-codec-id:14f15068"); | ||
3134 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); | 3222 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); |
3135 | 3223 | ||
3136 | MODULE_LICENSE("GPL"); | 3224 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 86067ee78632..522e0748ee99 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -52,6 +52,10 @@ struct hdmi_spec { | |||
52 | */ | 52 | */ |
53 | struct hda_multi_out multiout; | 53 | struct hda_multi_out multiout; |
54 | unsigned int codec_type; | 54 | unsigned int codec_type; |
55 | |||
56 | /* misc flags */ | ||
57 | /* PD bit indicates only the update, not the current state */ | ||
58 | unsigned int old_pin_detect:1; | ||
55 | }; | 59 | }; |
56 | 60 | ||
57 | 61 | ||
@@ -616,6 +620,9 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
616 | * Unsolicited events | 620 | * Unsolicited events |
617 | */ | 621 | */ |
618 | 622 | ||
623 | static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | ||
624 | struct hdmi_eld *eld); | ||
625 | |||
619 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | 626 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) |
620 | { | 627 | { |
621 | struct hdmi_spec *spec = codec->spec; | 628 | struct hdmi_spec *spec = codec->spec; |
@@ -632,6 +639,12 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | |||
632 | if (index < 0) | 639 | if (index < 0) |
633 | return; | 640 | return; |
634 | 641 | ||
642 | if (spec->old_pin_detect) { | ||
643 | if (pind) | ||
644 | hdmi_present_sense(codec, tag, &spec->sink_eld[index]); | ||
645 | pind = spec->sink_eld[index].monitor_present; | ||
646 | } | ||
647 | |||
635 | spec->sink_eld[index].monitor_present = pind; | 648 | spec->sink_eld[index].monitor_present = pind; |
636 | spec->sink_eld[index].eld_valid = eldv; | 649 | spec->sink_eld[index].eld_valid = eldv; |
637 | 650 | ||
@@ -685,11 +698,51 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | |||
685 | * Callbacks | 698 | * Callbacks |
686 | */ | 699 | */ |
687 | 700 | ||
688 | static 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 | |||
705 | static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | ||
689 | u32 stream_tag, int format) | 706 | u32 stream_tag, int format) |
690 | { | 707 | { |
708 | struct hdmi_spec *spec = codec->spec; | ||
691 | int tag; | 709 | int tag; |
692 | 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 | } | ||
693 | 746 | ||
694 | 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; |
695 | 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); |
@@ -709,6 +762,7 @@ static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
709 | if (fmt != format) | 762 | if (fmt != format) |
710 | snd_hda_codec_write(codec, nid, 0, | 763 | snd_hda_codec_write(codec, nid, 0, |
711 | AC_VERB_SET_STREAM_FORMAT, format); | 764 | AC_VERB_SET_STREAM_FORMAT, format); |
765 | return 0; | ||
712 | } | 766 | } |
713 | 767 | ||
714 | /* | 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 | ||
73 | static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | 72 | static 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 3c10c0b149f4..77e2b4028b9f 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 | ||
209 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | 208 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, |
@@ -478,6 +477,7 @@ static int patch_nvhdmi_8ch_89(struct hda_codec *codec) | |||
478 | 477 | ||
479 | codec->spec = spec; | 478 | codec->spec = spec; |
480 | spec->codec_type = HDA_CODEC_NVIDIA_MCP89; | 479 | spec->codec_type = HDA_CODEC_NVIDIA_MCP89; |
480 | spec->old_pin_detect = 1; | ||
481 | 481 | ||
482 | if (hdmi_parse_codec(codec) < 0) { | 482 | if (hdmi_parse_codec(codec) < 0) { |
483 | codec->spec = NULL; | 483 | codec->spec = NULL; |
@@ -508,6 +508,7 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | |||
508 | spec->multiout.max_channels = 8; | 508 | spec->multiout.max_channels = 8; |
509 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | 509 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
510 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | 510 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; |
511 | spec->old_pin_detect = 1; | ||
511 | 512 | ||
512 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | 513 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; |
513 | 514 | ||
@@ -528,6 +529,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
528 | spec->multiout.max_channels = 2; | 529 | spec->multiout.max_channels = 2; |
529 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | 530 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
530 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | 531 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; |
532 | spec->old_pin_detect = 1; | ||
531 | 533 | ||
532 | codec->patch_ops = nvhdmi_patch_ops_2ch; | 534 | codec->patch_ops = nvhdmi_patch_ops_2ch; |
533 | 535 | ||
@@ -538,26 +540,32 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
538 | * patch entries | 540 | * patch entries |
539 | */ | 541 | */ |
540 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { | 542 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { |
541 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", | 543 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
542 | .patch = patch_nvhdmi_8ch_7x }, | 544 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
543 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", | 545 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
544 | .patch = patch_nvhdmi_8ch_7x }, | 546 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
545 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", | 547 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, |
546 | .patch = patch_nvhdmi_8ch_7x }, | 548 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
547 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", | 549 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
548 | .patch = patch_nvhdmi_8ch_7x }, | 550 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, |
549 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", | 551 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
550 | .patch = patch_nvhdmi_8ch_7x }, | 552 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
551 | { .id = 0x10de000a, .name = "GT220 HDMI", | 553 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
552 | .patch = patch_nvhdmi_8ch_89 }, | 554 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
553 | { .id = 0x10de000b, .name = "GT21x HDMI", | 555 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
554 | .patch = patch_nvhdmi_8ch_89 }, | 556 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
555 | { .id = 0x10de000c, .name = "MCP89 HDMI", | 557 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
556 | .patch = patch_nvhdmi_8ch_89 }, | 558 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
557 | { .id = 0x10de000d, .name = "GT240 HDMI", | 559 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
558 | .patch = patch_nvhdmi_8ch_89 }, | 560 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
559 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 561 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
560 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 562 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, |
563 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
564 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
565 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
566 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
567 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | ||
568 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | ||
561 | {} /* terminator */ | 569 | {} /* terminator */ |
562 | }; | 570 | }; |
563 | 571 | ||
@@ -570,6 +578,21 @@ MODULE_ALIAS("snd-hda-codec-id:10de000a"); | |||
570 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | 578 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); |
571 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | 579 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); |
572 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | 580 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); |
581 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | ||
582 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | ||
583 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | ||
584 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | ||
585 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | ||
586 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | ||
587 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | ||
588 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | ||
589 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | ||
590 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | ||
591 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | ||
592 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | ||
593 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | ||
594 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | ||
595 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | ||
573 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 596 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
574 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 597 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
575 | 598 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 17d4548cc353..55d6e5b6bb7d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -137,6 +137,7 @@ enum { | |||
137 | ALC269VB_DMIC, | 137 | ALC269VB_DMIC, |
138 | ALC269_FUJITSU, | 138 | ALC269_FUJITSU, |
139 | ALC269_LIFEBOOK, | 139 | ALC269_LIFEBOOK, |
140 | ALC271_ACER, | ||
140 | ALC269_AUTO, | 141 | ALC269_AUTO, |
141 | ALC269_MODEL_LAST /* last tag */ | 142 | ALC269_MODEL_LAST /* last tag */ |
142 | }; | 143 | }; |
@@ -256,6 +257,13 @@ enum { | |||
256 | ALC882_MODEL_LAST, | 257 | ALC882_MODEL_LAST, |
257 | }; | 258 | }; |
258 | 259 | ||
260 | /* ALC680 models */ | ||
261 | enum { | ||
262 | ALC680_BASE, | ||
263 | ALC680_AUTO, | ||
264 | ALC680_MODEL_LAST, | ||
265 | }; | ||
266 | |||
259 | /* for GPIO Poll */ | 267 | /* for GPIO Poll */ |
260 | #define GPIO_MASK 0x03 | 268 | #define GPIO_MASK 0x03 |
261 | 269 | ||
@@ -326,6 +334,12 @@ struct alc_spec { | |||
326 | hda_nid_t *capsrc_nids; | 334 | hda_nid_t *capsrc_nids; |
327 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 335 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
328 | 336 | ||
337 | /* capture setup for dynamic dual-adc switch */ | ||
338 | unsigned int cur_adc_idx; | ||
339 | hda_nid_t cur_adc; | ||
340 | unsigned int cur_adc_stream_tag; | ||
341 | unsigned int cur_adc_format; | ||
342 | |||
329 | /* capture source */ | 343 | /* capture source */ |
330 | unsigned int num_mux_defs; | 344 | unsigned int num_mux_defs; |
331 | const struct hda_input_mux *input_mux; | 345 | const struct hda_input_mux *input_mux; |
@@ -367,6 +381,7 @@ struct alc_spec { | |||
367 | 381 | ||
368 | /* other flags */ | 382 | /* other flags */ |
369 | unsigned int no_analog :1; /* digital I/O only */ | 383 | unsigned int no_analog :1; /* digital I/O only */ |
384 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ | ||
370 | int init_amp; | 385 | int init_amp; |
371 | 386 | ||
372 | /* for virtual master */ | 387 | /* for virtual master */ |
@@ -833,9 +848,13 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | |||
833 | 848 | ||
834 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { | 849 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { |
835 | unsigned int pincap; | 850 | unsigned int pincap; |
851 | unsigned int oldval; | ||
852 | oldval = snd_hda_codec_read(codec, nid, 0, | ||
853 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
836 | pincap = snd_hda_query_pin_caps(codec, nid); | 854 | pincap = snd_hda_query_pin_caps(codec, nid); |
837 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | 855 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; |
838 | if (pincap & AC_PINCAP_VREF_80) | 856 | /* if the default pin setup is vref50, we give it priority */ |
857 | if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50) | ||
839 | val = PIN_VREF80; | 858 | val = PIN_VREF80; |
840 | else if (pincap & AC_PINCAP_VREF_50) | 859 | else if (pincap & AC_PINCAP_VREF_50) |
841 | val = PIN_VREF50; | 860 | val = PIN_VREF50; |
@@ -1003,6 +1022,29 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | |||
1003 | return -1; | 1022 | return -1; |
1004 | } | 1023 | } |
1005 | 1024 | ||
1025 | /* switch the current ADC according to the jack state */ | ||
1026 | static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec) | ||
1027 | { | ||
1028 | struct alc_spec *spec = codec->spec; | ||
1029 | unsigned int present; | ||
1030 | hda_nid_t new_adc; | ||
1031 | |||
1032 | present = snd_hda_jack_detect(codec, spec->ext_mic.pin); | ||
1033 | if (present) | ||
1034 | spec->cur_adc_idx = 1; | ||
1035 | else | ||
1036 | spec->cur_adc_idx = 0; | ||
1037 | new_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
1038 | if (spec->cur_adc && spec->cur_adc != new_adc) { | ||
1039 | /* stream is running, let's swap the current ADC */ | ||
1040 | snd_hda_codec_cleanup_stream(codec, spec->cur_adc); | ||
1041 | spec->cur_adc = new_adc; | ||
1042 | snd_hda_codec_setup_stream(codec, new_adc, | ||
1043 | spec->cur_adc_stream_tag, 0, | ||
1044 | spec->cur_adc_format); | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1006 | static void alc_mic_automute(struct hda_codec *codec) | 1048 | static void alc_mic_automute(struct hda_codec *codec) |
1007 | { | 1049 | { |
1008 | struct alc_spec *spec = codec->spec; | 1050 | struct alc_spec *spec = codec->spec; |
@@ -1017,6 +1059,11 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
1017 | if (snd_BUG_ON(!spec->adc_nids)) | 1059 | if (snd_BUG_ON(!spec->adc_nids)) |
1018 | return; | 1060 | return; |
1019 | 1061 | ||
1062 | if (spec->dual_adc_switch) { | ||
1063 | alc_dual_mic_adc_auto_switch(codec); | ||
1064 | return; | ||
1065 | } | ||
1066 | |||
1020 | cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0]; | 1067 | cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0]; |
1021 | 1068 | ||
1022 | present = snd_hda_jack_detect(codec, spec->ext_mic.pin); | 1069 | present = snd_hda_jack_detect(codec, spec->ext_mic.pin); |
@@ -1267,6 +1314,8 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec) | |||
1267 | unsigned nid = 0; | 1314 | unsigned nid = 0; |
1268 | struct alc_spec *spec = codec->spec; | 1315 | struct alc_spec *spec = codec->spec; |
1269 | 1316 | ||
1317 | spec->cdefine.enable_pcbeep = 1; /* assume always enabled */ | ||
1318 | |||
1270 | ass = codec->subsystem_id & 0xffff; | 1319 | ass = codec->subsystem_id & 0xffff; |
1271 | if (ass != codec->bus->pci->subsystem_device && (ass & 1)) | 1320 | if (ass != codec->bus->pci->subsystem_device && (ass & 1)) |
1272 | goto do_sku; | 1321 | goto do_sku; |
@@ -1497,6 +1546,63 @@ static int alc_read_coef_idx(struct hda_codec *codec, | |||
1497 | return val; | 1546 | return val; |
1498 | } | 1547 | } |
1499 | 1548 | ||
1549 | /* set right pin controls for digital I/O */ | ||
1550 | static void alc_auto_init_digital(struct hda_codec *codec) | ||
1551 | { | ||
1552 | struct alc_spec *spec = codec->spec; | ||
1553 | int i; | ||
1554 | hda_nid_t pin; | ||
1555 | |||
1556 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
1557 | pin = spec->autocfg.dig_out_pins[i]; | ||
1558 | if (pin) { | ||
1559 | snd_hda_codec_write(codec, pin, 0, | ||
1560 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1561 | PIN_OUT); | ||
1562 | } | ||
1563 | } | ||
1564 | pin = spec->autocfg.dig_in_pin; | ||
1565 | if (pin) | ||
1566 | snd_hda_codec_write(codec, pin, 0, | ||
1567 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1568 | PIN_IN); | ||
1569 | } | ||
1570 | |||
1571 | /* parse digital I/Os and set up NIDs in BIOS auto-parse mode */ | ||
1572 | static void alc_auto_parse_digital(struct hda_codec *codec) | ||
1573 | { | ||
1574 | struct alc_spec *spec = codec->spec; | ||
1575 | int i, err; | ||
1576 | hda_nid_t dig_nid; | ||
1577 | |||
1578 | /* support multiple SPDIFs; the secondary is set up as a slave */ | ||
1579 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
1580 | err = snd_hda_get_connections(codec, | ||
1581 | spec->autocfg.dig_out_pins[i], | ||
1582 | &dig_nid, 1); | ||
1583 | if (err < 0) | ||
1584 | continue; | ||
1585 | if (!i) { | ||
1586 | spec->multiout.dig_out_nid = dig_nid; | ||
1587 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
1588 | } else { | ||
1589 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
1590 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
1591 | break; | ||
1592 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
1593 | } | ||
1594 | } | ||
1595 | |||
1596 | if (spec->autocfg.dig_in_pin) { | ||
1597 | hda_nid_t dig_nid; | ||
1598 | err = snd_hda_get_connections(codec, | ||
1599 | spec->autocfg.dig_in_pin, | ||
1600 | &dig_nid, 1); | ||
1601 | if (err > 0) | ||
1602 | spec->dig_in_nid = dig_nid; | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1500 | /* | 1606 | /* |
1501 | * ALC888 | 1607 | * ALC888 |
1502 | */ | 1608 | */ |
@@ -2547,7 +2653,7 @@ static struct snd_kcontrol_new alc_beep_mixer[] = { | |||
2547 | static int alc_build_controls(struct hda_codec *codec) | 2653 | static int alc_build_controls(struct hda_codec *codec) |
2548 | { | 2654 | { |
2549 | struct alc_spec *spec = codec->spec; | 2655 | struct alc_spec *spec = codec->spec; |
2550 | struct snd_kcontrol *kctl; | 2656 | struct snd_kcontrol *kctl = NULL; |
2551 | struct snd_kcontrol_new *knew; | 2657 | struct snd_kcontrol_new *knew; |
2552 | int i, j, err; | 2658 | int i, j, err; |
2553 | unsigned int u; | 2659 | unsigned int u; |
@@ -2619,16 +2725,18 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2619 | } | 2725 | } |
2620 | 2726 | ||
2621 | /* assign Capture Source enums to NID */ | 2727 | /* assign Capture Source enums to NID */ |
2622 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | 2728 | if (spec->capsrc_nids || spec->adc_nids) { |
2623 | if (!kctl) | 2729 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); |
2624 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | 2730 | if (!kctl) |
2625 | for (i = 0; kctl && i < kctl->count; i++) { | 2731 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); |
2626 | hda_nid_t *nids = spec->capsrc_nids; | 2732 | for (i = 0; kctl && i < kctl->count; i++) { |
2627 | if (!nids) | 2733 | hda_nid_t *nids = spec->capsrc_nids; |
2628 | nids = spec->adc_nids; | 2734 | if (!nids) |
2629 | err = snd_hda_add_nid(codec, kctl, i, nids[i]); | 2735 | nids = spec->adc_nids; |
2630 | if (err < 0) | 2736 | err = snd_hda_add_nid(codec, kctl, i, nids[i]); |
2631 | return err; | 2737 | if (err < 0) |
2738 | return err; | ||
2739 | } | ||
2632 | } | 2740 | } |
2633 | if (spec->cap_mixer) { | 2741 | if (spec->cap_mixer) { |
2634 | const char *kname = kctl ? kctl->id.name : NULL; | 2742 | const char *kname = kctl ? kctl->id.name : NULL; |
@@ -3603,6 +3711,41 @@ static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
3603 | return 0; | 3711 | return 0; |
3604 | } | 3712 | } |
3605 | 3713 | ||
3714 | /* analog capture with dynamic dual-adc changes */ | ||
3715 | static int dualmic_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
3716 | struct hda_codec *codec, | ||
3717 | unsigned int stream_tag, | ||
3718 | unsigned int format, | ||
3719 | struct snd_pcm_substream *substream) | ||
3720 | { | ||
3721 | struct alc_spec *spec = codec->spec; | ||
3722 | spec->cur_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
3723 | spec->cur_adc_stream_tag = stream_tag; | ||
3724 | spec->cur_adc_format = format; | ||
3725 | snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); | ||
3726 | return 0; | ||
3727 | } | ||
3728 | |||
3729 | static int dualmic_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3730 | struct hda_codec *codec, | ||
3731 | struct snd_pcm_substream *substream) | ||
3732 | { | ||
3733 | struct alc_spec *spec = codec->spec; | ||
3734 | snd_hda_codec_cleanup_stream(codec, spec->cur_adc); | ||
3735 | spec->cur_adc = 0; | ||
3736 | return 0; | ||
3737 | } | ||
3738 | |||
3739 | static struct hda_pcm_stream dualmic_pcm_analog_capture = { | ||
3740 | .substreams = 1, | ||
3741 | .channels_min = 2, | ||
3742 | .channels_max = 2, | ||
3743 | .nid = 0, /* fill later */ | ||
3744 | .ops = { | ||
3745 | .prepare = dualmic_capture_pcm_prepare, | ||
3746 | .cleanup = dualmic_capture_pcm_cleanup | ||
3747 | }, | ||
3748 | }; | ||
3606 | 3749 | ||
3607 | /* | 3750 | /* |
3608 | */ | 3751 | */ |
@@ -4932,7 +5075,7 @@ static void alc880_auto_init_input_src(struct hda_codec *codec) | |||
4932 | static int alc880_parse_auto_config(struct hda_codec *codec) | 5075 | static int alc880_parse_auto_config(struct hda_codec *codec) |
4933 | { | 5076 | { |
4934 | struct alc_spec *spec = codec->spec; | 5077 | struct alc_spec *spec = codec->spec; |
4935 | int i, err; | 5078 | int err; |
4936 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; | 5079 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; |
4937 | 5080 | ||
4938 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 5081 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
@@ -4963,25 +5106,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4963 | 5106 | ||
4964 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 5107 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
4965 | 5108 | ||
4966 | /* check multiple SPDIF-out (for recent codecs) */ | 5109 | alc_auto_parse_digital(codec); |
4967 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
4968 | hda_nid_t dig_nid; | ||
4969 | err = snd_hda_get_connections(codec, | ||
4970 | spec->autocfg.dig_out_pins[i], | ||
4971 | &dig_nid, 1); | ||
4972 | if (err < 0) | ||
4973 | continue; | ||
4974 | if (!i) | ||
4975 | spec->multiout.dig_out_nid = dig_nid; | ||
4976 | else { | ||
4977 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
4978 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
4979 | break; | ||
4980 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
4981 | } | ||
4982 | } | ||
4983 | if (spec->autocfg.dig_in_pin) | ||
4984 | spec->dig_in_nid = ALC880_DIGIN_NID; | ||
4985 | 5110 | ||
4986 | if (spec->kctls.list) | 5111 | if (spec->kctls.list) |
4987 | add_mixer(spec, spec->kctls.list); | 5112 | add_mixer(spec, spec->kctls.list); |
@@ -5004,6 +5129,7 @@ static void alc880_auto_init(struct hda_codec *codec) | |||
5004 | alc880_auto_init_extra_out(codec); | 5129 | alc880_auto_init_extra_out(codec); |
5005 | alc880_auto_init_analog_input(codec); | 5130 | alc880_auto_init_analog_input(codec); |
5006 | alc880_auto_init_input_src(codec); | 5131 | alc880_auto_init_input_src(codec); |
5132 | alc_auto_init_digital(codec); | ||
5007 | if (spec->unsol_event) | 5133 | if (spec->unsol_event) |
5008 | alc_inithook(codec); | 5134 | alc_inithook(codec); |
5009 | } | 5135 | } |
@@ -5041,6 +5167,39 @@ static void fixup_automic_adc(struct hda_codec *codec) | |||
5041 | spec->auto_mic = 0; /* disable auto-mic to be sure */ | 5167 | spec->auto_mic = 0; /* disable auto-mic to be sure */ |
5042 | } | 5168 | } |
5043 | 5169 | ||
5170 | /* select or unmute the given capsrc route */ | ||
5171 | static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap, | ||
5172 | int idx) | ||
5173 | { | ||
5174 | if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) { | ||
5175 | snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx, | ||
5176 | HDA_AMP_MUTE, 0); | ||
5177 | } else { | ||
5178 | snd_hda_codec_write_cache(codec, cap, 0, | ||
5179 | AC_VERB_SET_CONNECT_SEL, idx); | ||
5180 | } | ||
5181 | } | ||
5182 | |||
5183 | /* set the default connection to that pin */ | ||
5184 | static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) | ||
5185 | { | ||
5186 | struct alc_spec *spec = codec->spec; | ||
5187 | int i; | ||
5188 | |||
5189 | for (i = 0; i < spec->num_adc_nids; i++) { | ||
5190 | hda_nid_t cap = spec->capsrc_nids ? | ||
5191 | spec->capsrc_nids[i] : spec->adc_nids[i]; | ||
5192 | int idx; | ||
5193 | |||
5194 | idx = get_connection_index(codec, cap, pin); | ||
5195 | if (idx < 0) | ||
5196 | continue; | ||
5197 | select_or_unmute_capsrc(codec, cap, idx); | ||
5198 | return i; /* return the found index */ | ||
5199 | } | ||
5200 | return -1; /* not found */ | ||
5201 | } | ||
5202 | |||
5044 | /* choose the ADC/MUX containing the input pin and initialize the setup */ | 5203 | /* choose the ADC/MUX containing the input pin and initialize the setup */ |
5045 | static void fixup_single_adc(struct hda_codec *codec) | 5204 | static void fixup_single_adc(struct hda_codec *codec) |
5046 | { | 5205 | { |
@@ -5057,33 +5216,24 @@ static void fixup_single_adc(struct hda_codec *codec) | |||
5057 | } | 5216 | } |
5058 | if (!pin) | 5217 | if (!pin) |
5059 | return; | 5218 | return; |
5060 | 5219 | i = init_capsrc_for_pin(codec, pin); | |
5061 | /* set the default connection to that pin */ | 5220 | if (i >= 0) { |
5062 | for (i = 0; i < spec->num_adc_nids; i++) { | ||
5063 | hda_nid_t cap = spec->capsrc_nids ? | ||
5064 | spec->capsrc_nids[i] : spec->adc_nids[i]; | ||
5065 | int idx; | ||
5066 | |||
5067 | idx = get_connection_index(codec, cap, pin); | ||
5068 | if (idx < 0) | ||
5069 | continue; | ||
5070 | /* use only this ADC */ | 5221 | /* use only this ADC */ |
5071 | if (spec->capsrc_nids) | 5222 | if (spec->capsrc_nids) |
5072 | spec->capsrc_nids += i; | 5223 | spec->capsrc_nids += i; |
5073 | spec->adc_nids += i; | 5224 | spec->adc_nids += i; |
5074 | spec->num_adc_nids = 1; | 5225 | spec->num_adc_nids = 1; |
5075 | /* select or unmute this route */ | ||
5076 | if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) { | ||
5077 | snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx, | ||
5078 | HDA_AMP_MUTE, 0); | ||
5079 | } else { | ||
5080 | snd_hda_codec_write_cache(codec, cap, 0, | ||
5081 | AC_VERB_SET_CONNECT_SEL, idx); | ||
5082 | } | ||
5083 | return; | ||
5084 | } | 5226 | } |
5085 | } | 5227 | } |
5086 | 5228 | ||
5229 | /* initialize dual adcs */ | ||
5230 | static void fixup_dual_adc_switch(struct hda_codec *codec) | ||
5231 | { | ||
5232 | struct alc_spec *spec = codec->spec; | ||
5233 | init_capsrc_for_pin(codec, spec->ext_mic.pin); | ||
5234 | init_capsrc_for_pin(codec, spec->int_mic.pin); | ||
5235 | } | ||
5236 | |||
5087 | static void set_capture_mixer(struct hda_codec *codec) | 5237 | static void set_capture_mixer(struct hda_codec *codec) |
5088 | { | 5238 | { |
5089 | struct alc_spec *spec = codec->spec; | 5239 | struct alc_spec *spec = codec->spec; |
@@ -5097,7 +5247,10 @@ static void set_capture_mixer(struct hda_codec *codec) | |||
5097 | }; | 5247 | }; |
5098 | if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { | 5248 | if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { |
5099 | int mux = 0; | 5249 | int mux = 0; |
5100 | if (spec->auto_mic) | 5250 | int num_adcs = spec->num_adc_nids; |
5251 | if (spec->dual_adc_switch) | ||
5252 | fixup_dual_adc_switch(codec); | ||
5253 | else if (spec->auto_mic) | ||
5101 | fixup_automic_adc(codec); | 5254 | fixup_automic_adc(codec); |
5102 | else if (spec->input_mux) { | 5255 | else if (spec->input_mux) { |
5103 | if (spec->input_mux->num_items > 1) | 5256 | if (spec->input_mux->num_items > 1) |
@@ -5105,7 +5258,9 @@ static void set_capture_mixer(struct hda_codec *codec) | |||
5105 | else if (spec->input_mux->num_items == 1) | 5258 | else if (spec->input_mux->num_items == 1) |
5106 | fixup_single_adc(codec); | 5259 | fixup_single_adc(codec); |
5107 | } | 5260 | } |
5108 | spec->cap_mixer = caps[mux][spec->num_adc_nids - 1]; | 5261 | if (spec->dual_adc_switch) |
5262 | num_adcs = 1; | ||
5263 | spec->cap_mixer = caps[mux][num_adcs - 1]; | ||
5109 | } | 5264 | } |
5110 | } | 5265 | } |
5111 | 5266 | ||
@@ -5176,8 +5331,25 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
5176 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 5331 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
5177 | #define set_beep_amp(spec, nid, idx, dir) \ | 5332 | #define set_beep_amp(spec, nid, idx, dir) \ |
5178 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) | 5333 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) |
5334 | |||
5335 | static struct snd_pci_quirk beep_white_list[] = { | ||
5336 | SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), | ||
5337 | SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), | ||
5338 | {} | ||
5339 | }; | ||
5340 | |||
5341 | static inline int has_cdefine_beep(struct hda_codec *codec) | ||
5342 | { | ||
5343 | struct alc_spec *spec = codec->spec; | ||
5344 | const struct snd_pci_quirk *q; | ||
5345 | q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list); | ||
5346 | if (q) | ||
5347 | return q->value; | ||
5348 | return spec->cdefine.enable_pcbeep; | ||
5349 | } | ||
5179 | #else | 5350 | #else |
5180 | #define set_beep_amp(spec, nid, idx, dir) /* NOP */ | 5351 | #define set_beep_amp(spec, nid, idx, dir) /* NOP */ |
5352 | #define has_cdefine_beep(codec) 0 | ||
5181 | #endif | 5353 | #endif |
5182 | 5354 | ||
5183 | /* | 5355 | /* |
@@ -6604,6 +6776,7 @@ static void alc260_auto_init(struct hda_codec *codec) | |||
6604 | alc260_auto_init_multi_out(codec); | 6776 | alc260_auto_init_multi_out(codec); |
6605 | alc260_auto_init_analog_input(codec); | 6777 | alc260_auto_init_analog_input(codec); |
6606 | alc260_auto_init_input_src(codec); | 6778 | alc260_auto_init_input_src(codec); |
6779 | alc_auto_init_digital(codec); | ||
6607 | if (spec->unsol_event) | 6780 | if (spec->unsol_event) |
6608 | alc_inithook(codec); | 6781 | alc_inithook(codec); |
6609 | } | 6782 | } |
@@ -6620,6 +6793,29 @@ static struct hda_amp_list alc260_loopbacks[] = { | |||
6620 | #endif | 6793 | #endif |
6621 | 6794 | ||
6622 | /* | 6795 | /* |
6796 | * Pin config fixes | ||
6797 | */ | ||
6798 | enum { | ||
6799 | PINFIX_HP_DC5750, | ||
6800 | }; | ||
6801 | |||
6802 | static struct alc_pincfg alc260_hp_dc5750_pinfix[] = { | ||
6803 | { 0x11, 0x90130110 }, /* speaker */ | ||
6804 | { } | ||
6805 | }; | ||
6806 | |||
6807 | static const struct alc_fixup alc260_fixups[] = { | ||
6808 | [PINFIX_HP_DC5750] = { | ||
6809 | .pins = alc260_hp_dc5750_pinfix | ||
6810 | }, | ||
6811 | }; | ||
6812 | |||
6813 | static struct snd_pci_quirk alc260_fixup_tbl[] = { | ||
6814 | SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750), | ||
6815 | {} | ||
6816 | }; | ||
6817 | |||
6818 | /* | ||
6623 | * ALC260 configurations | 6819 | * ALC260 configurations |
6624 | */ | 6820 | */ |
6625 | static const char *alc260_models[ALC260_MODEL_LAST] = { | 6821 | static const char *alc260_models[ALC260_MODEL_LAST] = { |
@@ -6818,6 +7014,9 @@ static int patch_alc260(struct hda_codec *codec) | |||
6818 | board_config = ALC260_AUTO; | 7014 | board_config = ALC260_AUTO; |
6819 | } | 7015 | } |
6820 | 7016 | ||
7017 | if (board_config == ALC260_AUTO) | ||
7018 | alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 1); | ||
7019 | |||
6821 | if (board_config == ALC260_AUTO) { | 7020 | if (board_config == ALC260_AUTO) { |
6822 | /* automatic parse from the BIOS config */ | 7021 | /* automatic parse from the BIOS config */ |
6823 | err = alc260_parse_auto_config(codec); | 7022 | err = alc260_parse_auto_config(codec); |
@@ -6843,6 +7042,7 @@ static int patch_alc260(struct hda_codec *codec) | |||
6843 | 7042 | ||
6844 | spec->stream_analog_playback = &alc260_pcm_analog_playback; | 7043 | spec->stream_analog_playback = &alc260_pcm_analog_playback; |
6845 | spec->stream_analog_capture = &alc260_pcm_analog_capture; | 7044 | spec->stream_analog_capture = &alc260_pcm_analog_capture; |
7045 | spec->stream_analog_alt_capture = &alc260_pcm_analog_capture; | ||
6846 | 7046 | ||
6847 | spec->stream_digital_playback = &alc260_pcm_digital_playback; | 7047 | spec->stream_digital_playback = &alc260_pcm_digital_playback; |
6848 | spec->stream_digital_capture = &alc260_pcm_digital_capture; | 7048 | spec->stream_digital_capture = &alc260_pcm_digital_capture; |
@@ -6863,6 +7063,9 @@ static int patch_alc260(struct hda_codec *codec) | |||
6863 | set_capture_mixer(codec); | 7063 | set_capture_mixer(codec); |
6864 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); | 7064 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); |
6865 | 7065 | ||
7066 | if (board_config == ALC260_AUTO) | ||
7067 | alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 0); | ||
7068 | |||
6866 | spec->vmaster_nid = 0x08; | 7069 | spec->vmaster_nid = 0x08; |
6867 | 7070 | ||
6868 | codec->patch_ops = alc_patch_ops; | 7071 | codec->patch_ops = alc_patch_ops; |
@@ -6948,7 +7151,7 @@ static struct hda_input_mux mb5_capture_source = { | |||
6948 | .num_items = 3, | 7151 | .num_items = 3, |
6949 | .items = { | 7152 | .items = { |
6950 | { "Mic", 0x1 }, | 7153 | { "Mic", 0x1 }, |
6951 | { "Line", 0x2 }, | 7154 | { "Line", 0x7 }, |
6952 | { "CD", 0x4 }, | 7155 | { "CD", 0x4 }, |
6953 | }, | 7156 | }, |
6954 | }; | 7157 | }; |
@@ -6983,7 +7186,7 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { | |||
6983 | .num_items = 4, | 7186 | .num_items = 4, |
6984 | .items = { | 7187 | .items = { |
6985 | { "Mic", 0x0 }, | 7188 | { "Mic", 0x0 }, |
6986 | { "iMic", 0x1 }, | 7189 | { "Int Mic", 0x1 }, |
6987 | { "Line", 0x2 }, | 7190 | { "Line", 0x2 }, |
6988 | { "CD", 0x4 }, | 7191 | { "CD", 0x4 }, |
6989 | }, | 7192 | }, |
@@ -7469,8 +7672,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = { | |||
7469 | HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), | 7672 | HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), |
7470 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), | 7673 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), |
7471 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), | 7674 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), |
7472 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 7675 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), |
7473 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 7676 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), |
7474 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 7677 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
7475 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 7678 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
7476 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT), | 7679 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT), |
@@ -7853,10 +8056,9 @@ static struct hda_verb alc885_mb5_init_verbs[] = { | |||
7853 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 8056 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
7854 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 8057 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
7855 | 8058 | ||
7856 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 8059 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)}, |
7857 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | 8060 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)}, |
7858 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | 8061 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)}, |
7859 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
7860 | { } | 8062 | { } |
7861 | }; | 8063 | }; |
7862 | 8064 | ||
@@ -8554,8 +8756,8 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { | |||
8554 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 8756 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
8555 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8757 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
8556 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8758 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
8557 | HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8759 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
8558 | HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8760 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
8559 | { } /* end */ | 8761 | { } /* end */ |
8560 | }; | 8762 | }; |
8561 | 8763 | ||
@@ -9476,11 +9678,16 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { | |||
9476 | SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24), | 9678 | SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24), |
9477 | SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24), | 9679 | SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24), |
9478 | SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3), | 9680 | SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3), |
9681 | SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31), | ||
9682 | SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M), | ||
9683 | SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3), | ||
9684 | SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21), | ||
9479 | SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31), | 9685 | SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31), |
9480 | SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3), | 9686 | SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3), |
9481 | SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24), | 9687 | SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24), |
9482 | SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91), | 9688 | SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91), |
9483 | SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5), | 9689 | SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5), |
9690 | SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5), | ||
9484 | /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2, | 9691 | /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2, |
9485 | * so apparently no perfect solution yet | 9692 | * so apparently no perfect solution yet |
9486 | */ | 9693 | */ |
@@ -10241,7 +10448,8 @@ static struct alc_config_preset alc882_presets[] = { | |||
10241 | * Pin config fixes | 10448 | * Pin config fixes |
10242 | */ | 10449 | */ |
10243 | enum { | 10450 | enum { |
10244 | PINFIX_ABIT_AW9D_MAX | 10451 | PINFIX_ABIT_AW9D_MAX, |
10452 | PINFIX_PB_M5210, | ||
10245 | }; | 10453 | }; |
10246 | 10454 | ||
10247 | static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { | 10455 | static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { |
@@ -10251,13 +10459,22 @@ static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { | |||
10251 | { } | 10459 | { } |
10252 | }; | 10460 | }; |
10253 | 10461 | ||
10462 | static const struct hda_verb pb_m5210_verbs[] = { | ||
10463 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
10464 | {} | ||
10465 | }; | ||
10466 | |||
10254 | static const struct alc_fixup alc882_fixups[] = { | 10467 | static const struct alc_fixup alc882_fixups[] = { |
10255 | [PINFIX_ABIT_AW9D_MAX] = { | 10468 | [PINFIX_ABIT_AW9D_MAX] = { |
10256 | .pins = alc882_abit_aw9d_pinfix | 10469 | .pins = alc882_abit_aw9d_pinfix |
10257 | }, | 10470 | }, |
10471 | [PINFIX_PB_M5210] = { | ||
10472 | .verbs = pb_m5210_verbs | ||
10473 | }, | ||
10258 | }; | 10474 | }; |
10259 | 10475 | ||
10260 | static struct snd_pci_quirk alc882_fixup_tbl[] = { | 10476 | static struct snd_pci_quirk alc882_fixup_tbl[] = { |
10477 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), | ||
10261 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), | 10478 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), |
10262 | {} | 10479 | {} |
10263 | }; | 10480 | }; |
@@ -10422,7 +10639,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
10422 | { | 10639 | { |
10423 | struct alc_spec *spec = codec->spec; | 10640 | struct alc_spec *spec = codec->spec; |
10424 | static hda_nid_t alc882_ignore[] = { 0x1d, 0 }; | 10641 | static hda_nid_t alc882_ignore[] = { 0x1d, 0 }; |
10425 | int i, err; | 10642 | int err; |
10426 | 10643 | ||
10427 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 10644 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
10428 | alc882_ignore); | 10645 | alc882_ignore); |
@@ -10452,25 +10669,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
10452 | 10669 | ||
10453 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 10670 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
10454 | 10671 | ||
10455 | /* check multiple SPDIF-out (for recent codecs) */ | 10672 | alc_auto_parse_digital(codec); |
10456 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
10457 | hda_nid_t dig_nid; | ||
10458 | err = snd_hda_get_connections(codec, | ||
10459 | spec->autocfg.dig_out_pins[i], | ||
10460 | &dig_nid, 1); | ||
10461 | if (err < 0) | ||
10462 | continue; | ||
10463 | if (!i) | ||
10464 | spec->multiout.dig_out_nid = dig_nid; | ||
10465 | else { | ||
10466 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
10467 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
10468 | break; | ||
10469 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
10470 | } | ||
10471 | } | ||
10472 | if (spec->autocfg.dig_in_pin) | ||
10473 | spec->dig_in_nid = ALC880_DIGIN_NID; | ||
10474 | 10673 | ||
10475 | if (spec->kctls.list) | 10674 | if (spec->kctls.list) |
10476 | add_mixer(spec, spec->kctls.list); | 10675 | add_mixer(spec, spec->kctls.list); |
@@ -10500,6 +10699,7 @@ static void alc882_auto_init(struct hda_codec *codec) | |||
10500 | alc882_auto_init_hp_out(codec); | 10699 | alc882_auto_init_hp_out(codec); |
10501 | alc882_auto_init_analog_input(codec); | 10700 | alc882_auto_init_analog_input(codec); |
10502 | alc882_auto_init_input_src(codec); | 10701 | alc882_auto_init_input_src(codec); |
10702 | alc_auto_init_digital(codec); | ||
10503 | if (spec->unsol_event) | 10703 | if (spec->unsol_event) |
10504 | alc_inithook(codec); | 10704 | alc_inithook(codec); |
10505 | } | 10705 | } |
@@ -10558,10 +10758,12 @@ static int patch_alc882(struct hda_codec *codec) | |||
10558 | } | 10758 | } |
10559 | } | 10759 | } |
10560 | 10760 | ||
10561 | err = snd_hda_attach_beep_device(codec, 0x1); | 10761 | if (has_cdefine_beep(codec)) { |
10562 | if (err < 0) { | 10762 | err = snd_hda_attach_beep_device(codec, 0x1); |
10563 | alc_free(codec); | 10763 | if (err < 0) { |
10564 | return err; | 10764 | alc_free(codec); |
10765 | return err; | ||
10766 | } | ||
10565 | } | 10767 | } |
10566 | 10768 | ||
10567 | if (board_config != ALC882_AUTO) | 10769 | if (board_config != ALC882_AUTO) |
@@ -10611,7 +10813,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
10611 | 10813 | ||
10612 | set_capture_mixer(codec); | 10814 | set_capture_mixer(codec); |
10613 | 10815 | ||
10614 | if (spec->cdefine.enable_pcbeep) | 10816 | if (has_cdefine_beep(codec)) |
10615 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 10817 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
10616 | 10818 | ||
10617 | if (board_config == ALC882_AUTO) | 10819 | if (board_config == ALC882_AUTO) |
@@ -12028,12 +12230,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
12028 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 12230 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
12029 | 12231 | ||
12030 | dig_only: | 12232 | dig_only: |
12031 | if (spec->autocfg.dig_outs) { | 12233 | alc_auto_parse_digital(codec); |
12032 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; | ||
12033 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
12034 | } | ||
12035 | if (spec->autocfg.dig_in_pin) | ||
12036 | spec->dig_in_nid = ALC262_DIGIN_NID; | ||
12037 | 12234 | ||
12038 | if (spec->kctls.list) | 12235 | if (spec->kctls.list) |
12039 | add_mixer(spec, spec->kctls.list); | 12236 | add_mixer(spec, spec->kctls.list); |
@@ -12065,6 +12262,7 @@ static void alc262_auto_init(struct hda_codec *codec) | |||
12065 | alc262_auto_init_hp_out(codec); | 12262 | alc262_auto_init_hp_out(codec); |
12066 | alc262_auto_init_analog_input(codec); | 12263 | alc262_auto_init_analog_input(codec); |
12067 | alc262_auto_init_input_src(codec); | 12264 | alc262_auto_init_input_src(codec); |
12265 | alc_auto_init_digital(codec); | ||
12068 | if (spec->unsol_event) | 12266 | if (spec->unsol_event) |
12069 | alc_inithook(codec); | 12267 | alc_inithook(codec); |
12070 | } | 12268 | } |
@@ -12427,7 +12625,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
12427 | } | 12625 | } |
12428 | } | 12626 | } |
12429 | 12627 | ||
12430 | if (!spec->no_analog) { | 12628 | if (!spec->no_analog && has_cdefine_beep(codec)) { |
12431 | err = snd_hda_attach_beep_device(codec, 0x1); | 12629 | err = snd_hda_attach_beep_device(codec, 0x1); |
12432 | if (err < 0) { | 12630 | if (err < 0) { |
12433 | alc_free(codec); | 12631 | alc_free(codec); |
@@ -12478,7 +12676,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
12478 | } | 12676 | } |
12479 | if (!spec->cap_mixer && !spec->no_analog) | 12677 | if (!spec->cap_mixer && !spec->no_analog) |
12480 | set_capture_mixer(codec); | 12678 | set_capture_mixer(codec); |
12481 | if (!spec->no_analog && spec->cdefine.enable_pcbeep) | 12679 | if (!spec->no_analog && has_cdefine_beep(codec)) |
12482 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 12680 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
12483 | 12681 | ||
12484 | spec->vmaster_nid = 0x0c; | 12682 | spec->vmaster_nid = 0x0c; |
@@ -12998,10 +13196,14 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | |||
12998 | dac = 0x02; | 13196 | dac = 0x02; |
12999 | break; | 13197 | break; |
13000 | case 0x15: | 13198 | case 0x15: |
13199 | case 0x1a: /* ALC259/269 only */ | ||
13200 | case 0x1b: /* ALC259/269 only */ | ||
13001 | case 0x21: /* ALC269vb has this pin, too */ | 13201 | case 0x21: /* ALC269vb has this pin, too */ |
13002 | dac = 0x03; | 13202 | dac = 0x03; |
13003 | break; | 13203 | break; |
13004 | default: | 13204 | default: |
13205 | snd_printd(KERN_WARNING "hda_codec: " | ||
13206 | "ignoring pin 0x%x as unknown\n", nid); | ||
13005 | return 0; | 13207 | return 0; |
13006 | } | 13208 | } |
13007 | if (spec->multiout.dac_nids[0] != dac && | 13209 | if (spec->multiout.dac_nids[0] != dac && |
@@ -13052,7 +13254,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
13052 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 13254 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); |
13053 | if (err < 0) | 13255 | if (err < 0) |
13054 | return err; | 13256 | return err; |
13055 | } else { | 13257 | } else if (nid) { |
13056 | err = alc268_new_analog_output(spec, nid, "Speaker", 0); | 13258 | err = alc268_new_analog_output(spec, nid, "Speaker", 0); |
13057 | if (err < 0) | 13259 | if (err < 0) |
13058 | return err; | 13260 | return err; |
@@ -13201,10 +13403,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
13201 | 13403 | ||
13202 | dig_only: | 13404 | dig_only: |
13203 | /* digital only support output */ | 13405 | /* digital only support output */ |
13204 | if (spec->autocfg.dig_outs) { | 13406 | alc_auto_parse_digital(codec); |
13205 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | ||
13206 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
13207 | } | ||
13208 | if (spec->kctls.list) | 13407 | if (spec->kctls.list) |
13209 | add_mixer(spec, spec->kctls.list); | 13408 | add_mixer(spec, spec->kctls.list); |
13210 | 13409 | ||
@@ -13234,6 +13433,7 @@ static void alc268_auto_init(struct hda_codec *codec) | |||
13234 | alc268_auto_init_hp_out(codec); | 13433 | alc268_auto_init_hp_out(codec); |
13235 | alc268_auto_init_mono_speaker_out(codec); | 13434 | alc268_auto_init_mono_speaker_out(codec); |
13236 | alc268_auto_init_analog_input(codec); | 13435 | alc268_auto_init_analog_input(codec); |
13436 | alc_auto_init_digital(codec); | ||
13237 | if (spec->unsol_event) | 13437 | if (spec->unsol_event) |
13238 | alc_inithook(codec); | 13438 | alc_inithook(codec); |
13239 | } | 13439 | } |
@@ -13277,7 +13477,6 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { | |||
13277 | SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA), | 13477 | SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA), |
13278 | SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), | 13478 | SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), |
13279 | SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), | 13479 | SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), |
13280 | SND_PCI_QUIRK(0x1854, 0x1775, "LG R510", ALC268_DELL), | ||
13281 | {} | 13480 | {} |
13282 | }; | 13481 | }; |
13283 | 13482 | ||
@@ -13668,6 +13867,12 @@ static struct snd_kcontrol_new alc269vb_laptop_mixer[] = { | |||
13668 | { } /* end */ | 13867 | { } /* end */ |
13669 | }; | 13868 | }; |
13670 | 13869 | ||
13870 | static struct snd_kcontrol_new alc269_asus_mixer[] = { | ||
13871 | HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
13872 | HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT), | ||
13873 | { } /* end */ | ||
13874 | }; | ||
13875 | |||
13671 | /* capture mixer elements */ | 13876 | /* capture mixer elements */ |
13672 | static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = { | 13877 | static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = { |
13673 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 13878 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
@@ -13888,6 +14093,20 @@ static struct hda_verb alc269vb_laptop_amic_init_verbs[] = { | |||
13888 | {} | 14093 | {} |
13889 | }; | 14094 | }; |
13890 | 14095 | ||
14096 | static struct hda_verb alc271_acer_dmic_verbs[] = { | ||
14097 | {0x20, AC_VERB_SET_COEF_INDEX, 0x0d}, | ||
14098 | {0x20, AC_VERB_SET_PROC_COEF, 0x4000}, | ||
14099 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
14100 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
14101 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
14102 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
14103 | {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
14104 | {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
14105 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
14106 | {0x22, AC_VERB_SET_CONNECT_SEL, 6}, | ||
14107 | { } | ||
14108 | }; | ||
14109 | |||
13891 | /* toggle speaker-output according to the hp-jack state */ | 14110 | /* toggle speaker-output according to the hp-jack state */ |
13892 | static void alc269_speaker_automute(struct hda_codec *codec) | 14111 | static void alc269_speaker_automute(struct hda_codec *codec) |
13893 | { | 14112 | { |
@@ -14126,6 +14345,36 @@ static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid) | |||
14126 | } | 14345 | } |
14127 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | 14346 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ |
14128 | 14347 | ||
14348 | static int alc275_setup_dual_adc(struct hda_codec *codec) | ||
14349 | { | ||
14350 | struct alc_spec *spec = codec->spec; | ||
14351 | |||
14352 | if (codec->vendor_id != 0x10ec0275 || !spec->auto_mic) | ||
14353 | return 0; | ||
14354 | if ((spec->ext_mic.pin >= 0x18 && spec->int_mic.pin <= 0x13) || | ||
14355 | (spec->ext_mic.pin <= 0x12 && spec->int_mic.pin >= 0x18)) { | ||
14356 | if (spec->ext_mic.pin <= 0x12) { | ||
14357 | spec->private_adc_nids[0] = 0x08; | ||
14358 | spec->private_adc_nids[1] = 0x11; | ||
14359 | spec->private_capsrc_nids[0] = 0x23; | ||
14360 | spec->private_capsrc_nids[1] = 0x22; | ||
14361 | } else { | ||
14362 | spec->private_adc_nids[0] = 0x11; | ||
14363 | spec->private_adc_nids[1] = 0x08; | ||
14364 | spec->private_capsrc_nids[0] = 0x22; | ||
14365 | spec->private_capsrc_nids[1] = 0x23; | ||
14366 | } | ||
14367 | spec->adc_nids = spec->private_adc_nids; | ||
14368 | spec->capsrc_nids = spec->private_capsrc_nids; | ||
14369 | spec->num_adc_nids = 2; | ||
14370 | spec->dual_adc_switch = 1; | ||
14371 | snd_printdd("realtek: enabling dual ADC switchg (%02x:%02x)\n", | ||
14372 | spec->adc_nids[0], spec->adc_nids[1]); | ||
14373 | return 1; | ||
14374 | } | ||
14375 | return 0; | ||
14376 | } | ||
14377 | |||
14129 | /* | 14378 | /* |
14130 | * BIOS auto configuration | 14379 | * BIOS auto configuration |
14131 | */ | 14380 | */ |
@@ -14149,8 +14398,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14149 | 14398 | ||
14150 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 14399 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
14151 | 14400 | ||
14152 | if (spec->autocfg.dig_outs) | 14401 | alc_auto_parse_digital(codec); |
14153 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | ||
14154 | 14402 | ||
14155 | if (spec->kctls.list) | 14403 | if (spec->kctls.list) |
14156 | add_mixer(spec, spec->kctls.list); | 14404 | add_mixer(spec, spec->kctls.list); |
@@ -14165,13 +14413,15 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14165 | 14413 | ||
14166 | spec->num_mux_defs = 1; | 14414 | spec->num_mux_defs = 1; |
14167 | spec->input_mux = &spec->private_imux[0]; | 14415 | spec->input_mux = &spec->private_imux[0]; |
14168 | fillup_priv_adc_nids(codec, alc269_adc_candidates, | 14416 | |
14169 | sizeof(alc269_adc_candidates)); | 14417 | if (!alc275_setup_dual_adc(codec)) |
14418 | fillup_priv_adc_nids(codec, alc269_adc_candidates, | ||
14419 | sizeof(alc269_adc_candidates)); | ||
14170 | 14420 | ||
14171 | /* set default input source */ | 14421 | /* set default input source */ |
14172 | snd_hda_codec_write_cache(codec, spec->capsrc_nids[0], | 14422 | if (!spec->dual_adc_switch) |
14173 | 0, AC_VERB_SET_CONNECT_SEL, | 14423 | select_or_unmute_capsrc(codec, spec->capsrc_nids[0], |
14174 | spec->input_mux->items[0].index); | 14424 | spec->input_mux->items[0].index); |
14175 | 14425 | ||
14176 | err = alc_auto_add_mic_boost(codec); | 14426 | err = alc_auto_add_mic_boost(codec); |
14177 | if (err < 0) | 14427 | if (err < 0) |
@@ -14195,6 +14445,7 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
14195 | alc269_auto_init_multi_out(codec); | 14445 | alc269_auto_init_multi_out(codec); |
14196 | alc269_auto_init_hp_out(codec); | 14446 | alc269_auto_init_hp_out(codec); |
14197 | alc269_auto_init_analog_input(codec); | 14447 | alc269_auto_init_analog_input(codec); |
14448 | alc_auto_init_digital(codec); | ||
14198 | if (spec->unsol_event) | 14449 | if (spec->unsol_event) |
14199 | alc_inithook(codec); | 14450 | alc_inithook(codec); |
14200 | } | 14451 | } |
@@ -14235,6 +14486,7 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { | |||
14235 | 14486 | ||
14236 | static struct snd_pci_quirk alc269_cfg_tbl[] = { | 14487 | static struct snd_pci_quirk alc269_cfg_tbl[] = { |
14237 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), | 14488 | SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), |
14489 | SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER), | ||
14238 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", | 14490 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", |
14239 | ALC269_AMIC), | 14491 | ALC269_AMIC), |
14240 | SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC), | 14492 | SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC), |
@@ -14396,6 +14648,23 @@ static struct alc_config_preset alc269_presets[] = { | |||
14396 | .unsol_event = alc269_lifebook_unsol_event, | 14648 | .unsol_event = alc269_lifebook_unsol_event, |
14397 | .init_hook = alc269_lifebook_init_hook, | 14649 | .init_hook = alc269_lifebook_init_hook, |
14398 | }, | 14650 | }, |
14651 | [ALC271_ACER] = { | ||
14652 | .mixers = { alc269_asus_mixer }, | ||
14653 | .cap_mixer = alc269vb_laptop_digital_capture_mixer, | ||
14654 | .init_verbs = { alc269_init_verbs, alc271_acer_dmic_verbs }, | ||
14655 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
14656 | .dac_nids = alc269_dac_nids, | ||
14657 | .adc_nids = alc262_dmic_adc_nids, | ||
14658 | .num_adc_nids = ARRAY_SIZE(alc262_dmic_adc_nids), | ||
14659 | .capsrc_nids = alc262_dmic_capsrc_nids, | ||
14660 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
14661 | .channel_mode = alc269_modes, | ||
14662 | .input_mux = &alc269_capture_source, | ||
14663 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
14664 | .unsol_event = alc_sku_unsol_event, | ||
14665 | .setup = alc269vb_laptop_dmic_setup, | ||
14666 | .init_hook = alc_inithook, | ||
14667 | }, | ||
14399 | }; | 14668 | }; |
14400 | 14669 | ||
14401 | static int patch_alc269(struct hda_codec *codec) | 14670 | static int patch_alc269(struct hda_codec *codec) |
@@ -14450,10 +14719,12 @@ static int patch_alc269(struct hda_codec *codec) | |||
14450 | } | 14719 | } |
14451 | } | 14720 | } |
14452 | 14721 | ||
14453 | err = snd_hda_attach_beep_device(codec, 0x1); | 14722 | if (has_cdefine_beep(codec)) { |
14454 | if (err < 0) { | 14723 | err = snd_hda_attach_beep_device(codec, 0x1); |
14455 | alc_free(codec); | 14724 | if (err < 0) { |
14456 | return err; | 14725 | alc_free(codec); |
14726 | return err; | ||
14727 | } | ||
14457 | } | 14728 | } |
14458 | 14729 | ||
14459 | if (board_config != ALC269_AUTO) | 14730 | if (board_config != ALC269_AUTO) |
@@ -14465,6 +14736,10 @@ static int patch_alc269(struct hda_codec *codec) | |||
14465 | */ | 14736 | */ |
14466 | spec->stream_analog_playback = &alc269_44k_pcm_analog_playback; | 14737 | spec->stream_analog_playback = &alc269_44k_pcm_analog_playback; |
14467 | spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; | 14738 | spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; |
14739 | } else if (spec->dual_adc_switch) { | ||
14740 | spec->stream_analog_playback = &alc269_pcm_analog_playback; | ||
14741 | /* switch ADC dynamically */ | ||
14742 | spec->stream_analog_capture = &dualmic_pcm_analog_capture; | ||
14468 | } else { | 14743 | } else { |
14469 | spec->stream_analog_playback = &alc269_pcm_analog_playback; | 14744 | spec->stream_analog_playback = &alc269_pcm_analog_playback; |
14470 | spec->stream_analog_capture = &alc269_pcm_analog_capture; | 14745 | spec->stream_analog_capture = &alc269_pcm_analog_capture; |
@@ -14486,7 +14761,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
14486 | 14761 | ||
14487 | if (!spec->cap_mixer) | 14762 | if (!spec->cap_mixer) |
14488 | set_capture_mixer(codec); | 14763 | set_capture_mixer(codec); |
14489 | if (spec->cdefine.enable_pcbeep) | 14764 | if (has_cdefine_beep(codec)) |
14490 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 14765 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
14491 | 14766 | ||
14492 | if (board_config == ALC269_AUTO) | 14767 | if (board_config == ALC269_AUTO) |
@@ -15350,8 +15625,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
15350 | 15625 | ||
15351 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 15626 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
15352 | 15627 | ||
15353 | if (spec->autocfg.dig_outs) | 15628 | alc_auto_parse_digital(codec); |
15354 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | ||
15355 | 15629 | ||
15356 | if (spec->kctls.list) | 15630 | if (spec->kctls.list) |
15357 | add_mixer(spec, spec->kctls.list); | 15631 | add_mixer(spec, spec->kctls.list); |
@@ -15377,6 +15651,7 @@ static void alc861_auto_init(struct hda_codec *codec) | |||
15377 | alc861_auto_init_multi_out(codec); | 15651 | alc861_auto_init_multi_out(codec); |
15378 | alc861_auto_init_hp_out(codec); | 15652 | alc861_auto_init_hp_out(codec); |
15379 | alc861_auto_init_analog_input(codec); | 15653 | alc861_auto_init_analog_input(codec); |
15654 | alc_auto_init_digital(codec); | ||
15380 | if (spec->unsol_event) | 15655 | if (spec->unsol_event) |
15381 | alc_inithook(codec); | 15656 | alc_inithook(codec); |
15382 | } | 15657 | } |
@@ -16481,8 +16756,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
16481 | 16756 | ||
16482 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 16757 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
16483 | 16758 | ||
16484 | if (spec->autocfg.dig_outs) | 16759 | alc_auto_parse_digital(codec); |
16485 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | ||
16486 | 16760 | ||
16487 | if (spec->kctls.list) | 16761 | if (spec->kctls.list) |
16488 | add_mixer(spec, spec->kctls.list); | 16762 | add_mixer(spec, spec->kctls.list); |
@@ -16509,6 +16783,7 @@ static void alc861vd_auto_init(struct hda_codec *codec) | |||
16509 | alc861vd_auto_init_hp_out(codec); | 16783 | alc861vd_auto_init_hp_out(codec); |
16510 | alc861vd_auto_init_analog_input(codec); | 16784 | alc861vd_auto_init_analog_input(codec); |
16511 | alc861vd_auto_init_input_src(codec); | 16785 | alc861vd_auto_init_input_src(codec); |
16786 | alc_auto_init_digital(codec); | ||
16512 | if (spec->unsol_event) | 16787 | if (spec->unsol_event) |
16513 | alc_inithook(codec); | 16788 | alc_inithook(codec); |
16514 | } | 16789 | } |
@@ -18492,7 +18767,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, | |||
18492 | hda_nid_t dac) | 18767 | hda_nid_t dac) |
18493 | { | 18768 | { |
18494 | int i, num; | 18769 | int i, num; |
18495 | hda_nid_t srcs[4]; | 18770 | hda_nid_t srcs[HDA_MAX_CONNECTIONS]; |
18496 | 18771 | ||
18497 | alc_set_pin_output(codec, nid, pin_type); | 18772 | alc_set_pin_output(codec, nid, pin_type); |
18498 | /* need the manual connection? */ | 18773 | /* need the manual connection? */ |
@@ -18596,8 +18871,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
18596 | 18871 | ||
18597 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 18872 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
18598 | 18873 | ||
18599 | if (spec->autocfg.dig_outs) | 18874 | alc_auto_parse_digital(codec); |
18600 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | ||
18601 | 18875 | ||
18602 | if (spec->kctls.list) | 18876 | if (spec->kctls.list) |
18603 | add_mixer(spec, spec->kctls.list); | 18877 | add_mixer(spec, spec->kctls.list); |
@@ -18607,7 +18881,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
18607 | 18881 | ||
18608 | add_verb(spec, alc662_init_verbs); | 18882 | add_verb(spec, alc662_init_verbs); |
18609 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || | 18883 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || |
18610 | codec->vendor_id == 0x10ec0665) | 18884 | codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670) |
18611 | add_verb(spec, alc663_init_verbs); | 18885 | add_verb(spec, alc663_init_verbs); |
18612 | 18886 | ||
18613 | if (codec->vendor_id == 0x10ec0272) | 18887 | if (codec->vendor_id == 0x10ec0272) |
@@ -18634,6 +18908,7 @@ static void alc662_auto_init(struct hda_codec *codec) | |||
18634 | alc662_auto_init_hp_out(codec); | 18908 | alc662_auto_init_hp_out(codec); |
18635 | alc662_auto_init_analog_input(codec); | 18909 | alc662_auto_init_analog_input(codec); |
18636 | alc662_auto_init_input_src(codec); | 18910 | alc662_auto_init_input_src(codec); |
18911 | alc_auto_init_digital(codec); | ||
18637 | if (spec->unsol_event) | 18912 | if (spec->unsol_event) |
18638 | alc_inithook(codec); | 18913 | alc_inithook(codec); |
18639 | } | 18914 | } |
@@ -18683,10 +18958,12 @@ static int patch_alc662(struct hda_codec *codec) | |||
18683 | } | 18958 | } |
18684 | } | 18959 | } |
18685 | 18960 | ||
18686 | err = snd_hda_attach_beep_device(codec, 0x1); | 18961 | if (has_cdefine_beep(codec)) { |
18687 | if (err < 0) { | 18962 | err = snd_hda_attach_beep_device(codec, 0x1); |
18688 | alc_free(codec); | 18963 | if (err < 0) { |
18689 | return err; | 18964 | alc_free(codec); |
18965 | return err; | ||
18966 | } | ||
18690 | } | 18967 | } |
18691 | 18968 | ||
18692 | if (board_config != ALC662_AUTO) | 18969 | if (board_config != ALC662_AUTO) |
@@ -18708,7 +18985,7 @@ static int patch_alc662(struct hda_codec *codec) | |||
18708 | if (!spec->cap_mixer) | 18985 | if (!spec->cap_mixer) |
18709 | set_capture_mixer(codec); | 18986 | set_capture_mixer(codec); |
18710 | 18987 | ||
18711 | if (spec->cdefine.enable_pcbeep) { | 18988 | if (has_cdefine_beep(codec)) { |
18712 | switch (codec->vendor_id) { | 18989 | switch (codec->vendor_id) { |
18713 | case 0x10ec0662: | 18990 | case 0x10ec0662: |
18714 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 18991 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
@@ -18751,6 +19028,333 @@ static int patch_alc888(struct hda_codec *codec) | |||
18751 | } | 19028 | } |
18752 | 19029 | ||
18753 | /* | 19030 | /* |
19031 | * ALC680 support | ||
19032 | */ | ||
19033 | #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID | ||
19034 | #define alc680_modes alc260_modes | ||
19035 | |||
19036 | static hda_nid_t alc680_dac_nids[3] = { | ||
19037 | /* Lout1, Lout2, hp */ | ||
19038 | 0x02, 0x03, 0x04 | ||
19039 | }; | ||
19040 | |||
19041 | static hda_nid_t alc680_adc_nids[3] = { | ||
19042 | /* ADC0-2 */ | ||
19043 | /* DMIC, MIC, Line-in*/ | ||
19044 | 0x07, 0x08, 0x09 | ||
19045 | }; | ||
19046 | |||
19047 | static struct snd_kcontrol_new alc680_base_mixer[] = { | ||
19048 | /* output mixer control */ | ||
19049 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), | ||
19050 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
19051 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), | ||
19052 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), | ||
19053 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
19054 | { } | ||
19055 | }; | ||
19056 | |||
19057 | static struct snd_kcontrol_new alc680_capture_mixer[] = { | ||
19058 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
19059 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
19060 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
19061 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
19062 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | ||
19063 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
19064 | { } /* end */ | ||
19065 | }; | ||
19066 | |||
19067 | /* | ||
19068 | * generic initialization of ADC, input mixers and output mixers | ||
19069 | */ | ||
19070 | static struct hda_verb alc680_init_verbs[] = { | ||
19071 | /* Unmute DAC0-1 and set vol = 0 */ | ||
19072 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
19073 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
19074 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
19075 | |||
19076 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
19077 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
19078 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, | ||
19079 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
19080 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
19081 | |||
19082 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19083 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19084 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19085 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19086 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19087 | { } | ||
19088 | }; | ||
19089 | |||
19090 | /* create input playback/capture controls for the given pin */ | ||
19091 | static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | ||
19092 | const char *ctlname, int idx) | ||
19093 | { | ||
19094 | hda_nid_t dac; | ||
19095 | int err; | ||
19096 | |||
19097 | switch (nid) { | ||
19098 | case 0x14: | ||
19099 | dac = 0x02; | ||
19100 | break; | ||
19101 | case 0x15: | ||
19102 | dac = 0x03; | ||
19103 | break; | ||
19104 | case 0x16: | ||
19105 | dac = 0x04; | ||
19106 | break; | ||
19107 | default: | ||
19108 | return 0; | ||
19109 | } | ||
19110 | if (spec->multiout.dac_nids[0] != dac && | ||
19111 | spec->multiout.dac_nids[1] != dac) { | ||
19112 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, | ||
19113 | HDA_COMPOSE_AMP_VAL(dac, 3, idx, | ||
19114 | HDA_OUTPUT)); | ||
19115 | if (err < 0) | ||
19116 | return err; | ||
19117 | |||
19118 | err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, | ||
19119 | HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); | ||
19120 | |||
19121 | if (err < 0) | ||
19122 | return err; | ||
19123 | spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; | ||
19124 | } | ||
19125 | |||
19126 | return 0; | ||
19127 | } | ||
19128 | |||
19129 | /* add playback controls from the parsed DAC table */ | ||
19130 | static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec, | ||
19131 | const struct auto_pin_cfg *cfg) | ||
19132 | { | ||
19133 | hda_nid_t nid; | ||
19134 | int err; | ||
19135 | |||
19136 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
19137 | |||
19138 | nid = cfg->line_out_pins[0]; | ||
19139 | if (nid) { | ||
19140 | const char *name; | ||
19141 | if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
19142 | name = "Speaker"; | ||
19143 | else | ||
19144 | name = "Front"; | ||
19145 | err = alc680_new_analog_output(spec, nid, name, 0); | ||
19146 | if (err < 0) | ||
19147 | return err; | ||
19148 | } | ||
19149 | |||
19150 | nid = cfg->speaker_pins[0]; | ||
19151 | if (nid) { | ||
19152 | err = alc680_new_analog_output(spec, nid, "Speaker", 0); | ||
19153 | if (err < 0) | ||
19154 | return err; | ||
19155 | } | ||
19156 | nid = cfg->hp_pins[0]; | ||
19157 | if (nid) { | ||
19158 | err = alc680_new_analog_output(spec, nid, "Headphone", 0); | ||
19159 | if (err < 0) | ||
19160 | return err; | ||
19161 | } | ||
19162 | |||
19163 | return 0; | ||
19164 | } | ||
19165 | |||
19166 | static void alc680_auto_set_output_and_unmute(struct hda_codec *codec, | ||
19167 | hda_nid_t nid, int pin_type) | ||
19168 | { | ||
19169 | alc_set_pin_output(codec, nid, pin_type); | ||
19170 | } | ||
19171 | |||
19172 | static void alc680_auto_init_multi_out(struct hda_codec *codec) | ||
19173 | { | ||
19174 | struct alc_spec *spec = codec->spec; | ||
19175 | hda_nid_t nid = spec->autocfg.line_out_pins[0]; | ||
19176 | if (nid) { | ||
19177 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
19178 | alc680_auto_set_output_and_unmute(codec, nid, pin_type); | ||
19179 | } | ||
19180 | } | ||
19181 | |||
19182 | static void alc680_auto_init_hp_out(struct hda_codec *codec) | ||
19183 | { | ||
19184 | struct alc_spec *spec = codec->spec; | ||
19185 | hda_nid_t pin; | ||
19186 | |||
19187 | pin = spec->autocfg.hp_pins[0]; | ||
19188 | if (pin) | ||
19189 | alc680_auto_set_output_and_unmute(codec, pin, PIN_HP); | ||
19190 | pin = spec->autocfg.speaker_pins[0]; | ||
19191 | if (pin) | ||
19192 | alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT); | ||
19193 | } | ||
19194 | |||
19195 | /* pcm configuration: identical with ALC880 */ | ||
19196 | #define alc680_pcm_analog_playback alc880_pcm_analog_playback | ||
19197 | #define alc680_pcm_analog_capture alc880_pcm_analog_capture | ||
19198 | #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture | ||
19199 | #define alc680_pcm_digital_playback alc880_pcm_digital_playback | ||
19200 | |||
19201 | static struct hda_input_mux alc680_capture_source = { | ||
19202 | .num_items = 1, | ||
19203 | .items = { | ||
19204 | { "Mic", 0x0 }, | ||
19205 | }, | ||
19206 | }; | ||
19207 | |||
19208 | /* | ||
19209 | * BIOS auto configuration | ||
19210 | */ | ||
19211 | static int alc680_parse_auto_config(struct hda_codec *codec) | ||
19212 | { | ||
19213 | struct alc_spec *spec = codec->spec; | ||
19214 | int err; | ||
19215 | static hda_nid_t alc680_ignore[] = { 0 }; | ||
19216 | |||
19217 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | ||
19218 | alc680_ignore); | ||
19219 | if (err < 0) | ||
19220 | return err; | ||
19221 | if (!spec->autocfg.line_outs) { | ||
19222 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { | ||
19223 | spec->multiout.max_channels = 2; | ||
19224 | spec->no_analog = 1; | ||
19225 | goto dig_only; | ||
19226 | } | ||
19227 | return 0; /* can't find valid BIOS pin config */ | ||
19228 | } | ||
19229 | err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg); | ||
19230 | if (err < 0) | ||
19231 | return err; | ||
19232 | |||
19233 | spec->multiout.max_channels = 2; | ||
19234 | |||
19235 | dig_only: | ||
19236 | /* digital only support output */ | ||
19237 | alc_auto_parse_digital(codec); | ||
19238 | if (spec->kctls.list) | ||
19239 | add_mixer(spec, spec->kctls.list); | ||
19240 | |||
19241 | add_verb(spec, alc680_init_verbs); | ||
19242 | spec->num_mux_defs = 1; | ||
19243 | spec->input_mux = &alc680_capture_source; | ||
19244 | |||
19245 | err = alc_auto_add_mic_boost(codec); | ||
19246 | if (err < 0) | ||
19247 | return err; | ||
19248 | |||
19249 | return 1; | ||
19250 | } | ||
19251 | |||
19252 | #define alc680_auto_init_analog_input alc882_auto_init_analog_input | ||
19253 | |||
19254 | /* init callback for auto-configuration model -- overriding the default init */ | ||
19255 | static void alc680_auto_init(struct hda_codec *codec) | ||
19256 | { | ||
19257 | struct alc_spec *spec = codec->spec; | ||
19258 | alc680_auto_init_multi_out(codec); | ||
19259 | alc680_auto_init_hp_out(codec); | ||
19260 | alc680_auto_init_analog_input(codec); | ||
19261 | alc_auto_init_digital(codec); | ||
19262 | if (spec->unsol_event) | ||
19263 | alc_inithook(codec); | ||
19264 | } | ||
19265 | |||
19266 | /* | ||
19267 | * configuration and preset | ||
19268 | */ | ||
19269 | static const char *alc680_models[ALC680_MODEL_LAST] = { | ||
19270 | [ALC680_BASE] = "base", | ||
19271 | [ALC680_AUTO] = "auto", | ||
19272 | }; | ||
19273 | |||
19274 | static struct snd_pci_quirk alc680_cfg_tbl[] = { | ||
19275 | SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE), | ||
19276 | {} | ||
19277 | }; | ||
19278 | |||
19279 | static struct alc_config_preset alc680_presets[] = { | ||
19280 | [ALC680_BASE] = { | ||
19281 | .mixers = { alc680_base_mixer }, | ||
19282 | .cap_mixer = alc680_capture_mixer, | ||
19283 | .init_verbs = { alc680_init_verbs }, | ||
19284 | .num_dacs = ARRAY_SIZE(alc680_dac_nids), | ||
19285 | .dac_nids = alc680_dac_nids, | ||
19286 | .num_adc_nids = ARRAY_SIZE(alc680_adc_nids), | ||
19287 | .adc_nids = alc680_adc_nids, | ||
19288 | .hp_nid = 0x04, | ||
19289 | .dig_out_nid = ALC680_DIGOUT_NID, | ||
19290 | .num_channel_mode = ARRAY_SIZE(alc680_modes), | ||
19291 | .channel_mode = alc680_modes, | ||
19292 | .input_mux = &alc680_capture_source, | ||
19293 | }, | ||
19294 | }; | ||
19295 | |||
19296 | static int patch_alc680(struct hda_codec *codec) | ||
19297 | { | ||
19298 | struct alc_spec *spec; | ||
19299 | int board_config; | ||
19300 | int err; | ||
19301 | |||
19302 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
19303 | if (spec == NULL) | ||
19304 | return -ENOMEM; | ||
19305 | |||
19306 | codec->spec = spec; | ||
19307 | |||
19308 | board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST, | ||
19309 | alc680_models, | ||
19310 | alc680_cfg_tbl); | ||
19311 | |||
19312 | if (board_config < 0 || board_config >= ALC680_MODEL_LAST) { | ||
19313 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
19314 | codec->chip_name); | ||
19315 | board_config = ALC680_AUTO; | ||
19316 | } | ||
19317 | |||
19318 | if (board_config == ALC680_AUTO) { | ||
19319 | /* automatic parse from the BIOS config */ | ||
19320 | err = alc680_parse_auto_config(codec); | ||
19321 | if (err < 0) { | ||
19322 | alc_free(codec); | ||
19323 | return err; | ||
19324 | } else if (!err) { | ||
19325 | printk(KERN_INFO | ||
19326 | "hda_codec: Cannot set up configuration " | ||
19327 | "from BIOS. Using base mode...\n"); | ||
19328 | board_config = ALC680_BASE; | ||
19329 | } | ||
19330 | } | ||
19331 | |||
19332 | if (board_config != ALC680_AUTO) | ||
19333 | setup_preset(codec, &alc680_presets[board_config]); | ||
19334 | |||
19335 | spec->stream_analog_playback = &alc680_pcm_analog_playback; | ||
19336 | spec->stream_analog_capture = &alc680_pcm_analog_capture; | ||
19337 | spec->stream_analog_alt_capture = &alc680_pcm_analog_alt_capture; | ||
19338 | spec->stream_digital_playback = &alc680_pcm_digital_playback; | ||
19339 | |||
19340 | if (!spec->adc_nids) { | ||
19341 | spec->adc_nids = alc680_adc_nids; | ||
19342 | spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids); | ||
19343 | } | ||
19344 | |||
19345 | if (!spec->cap_mixer) | ||
19346 | set_capture_mixer(codec); | ||
19347 | |||
19348 | spec->vmaster_nid = 0x02; | ||
19349 | |||
19350 | codec->patch_ops = alc_patch_ops; | ||
19351 | if (board_config == ALC680_AUTO) | ||
19352 | spec->init_hook = alc680_auto_init; | ||
19353 | |||
19354 | return 0; | ||
19355 | } | ||
19356 | |||
19357 | /* | ||
18754 | * patch entries | 19358 | * patch entries |
18755 | */ | 19359 | */ |
18756 | static struct hda_codec_preset snd_hda_preset_realtek[] = { | 19360 | static struct hda_codec_preset snd_hda_preset_realtek[] = { |
@@ -18774,6 +19378,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
18774 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, | 19378 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, |
18775 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, | 19379 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, |
18776 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, | 19380 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, |
19381 | { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, | ||
18777 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 19382 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
18778 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, | 19383 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, |
18779 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, | 19384 | { .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..f3f861bd1bf8 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -94,6 +94,7 @@ enum { | |||
94 | STAC_92HD83XXX_PWR_REF, | 94 | STAC_92HD83XXX_PWR_REF, |
95 | STAC_DELL_S14, | 95 | STAC_DELL_S14, |
96 | STAC_92HD83XXX_HP, | 96 | STAC_92HD83XXX_HP, |
97 | STAC_HP_DV7_4000, | ||
97 | STAC_92HD83XXX_MODELS | 98 | STAC_92HD83XXX_MODELS |
98 | }; | 99 | }; |
99 | 100 | ||
@@ -202,6 +203,7 @@ struct sigmatel_spec { | |||
202 | unsigned int spdif_mute: 1; | 203 | unsigned int spdif_mute: 1; |
203 | unsigned int check_volume_offset:1; | 204 | unsigned int check_volume_offset:1; |
204 | unsigned int auto_mic:1; | 205 | unsigned int auto_mic:1; |
206 | unsigned int linear_tone_beep:1; | ||
205 | 207 | ||
206 | /* gpio lines */ | 208 | /* gpio lines */ |
207 | unsigned int eapd_mask; | 209 | unsigned int eapd_mask; |
@@ -1631,10 +1633,17 @@ static unsigned int dell_s14_pin_configs[10] = { | |||
1631 | 0x40f000f0, 0x40f000f0, | 1633 | 0x40f000f0, 0x40f000f0, |
1632 | }; | 1634 | }; |
1633 | 1635 | ||
1636 | static unsigned int hp_dv7_4000_pin_configs[10] = { | ||
1637 | 0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110, | ||
1638 | 0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140, | ||
1639 | 0x40f000f0, 0x40f000f0, | ||
1640 | }; | ||
1641 | |||
1634 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | 1642 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { |
1635 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, | 1643 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, |
1636 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, | 1644 | [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, |
1637 | [STAC_DELL_S14] = dell_s14_pin_configs, | 1645 | [STAC_DELL_S14] = dell_s14_pin_configs, |
1646 | [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, | ||
1638 | }; | 1647 | }; |
1639 | 1648 | ||
1640 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | 1649 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { |
@@ -1643,6 +1652,7 @@ static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | |||
1643 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", | 1652 | [STAC_92HD83XXX_PWR_REF] = "mic-ref", |
1644 | [STAC_DELL_S14] = "dell-s14", | 1653 | [STAC_DELL_S14] = "dell-s14", |
1645 | [STAC_92HD83XXX_HP] = "hp", | 1654 | [STAC_92HD83XXX_HP] = "hp", |
1655 | [STAC_HP_DV7_4000] = "hp-dv7-4000", | ||
1646 | }; | 1656 | }; |
1647 | 1657 | ||
1648 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | 1658 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { |
@@ -3802,7 +3812,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3802 | return err; | 3812 | return err; |
3803 | if (codec->beep) { | 3813 | if (codec->beep) { |
3804 | /* IDT/STAC codecs have linear beep tone parameter */ | 3814 | /* IDT/STAC codecs have linear beep tone parameter */ |
3805 | codec->beep->linear_tone = 1; | 3815 | codec->beep->linear_tone = spec->linear_tone_beep; |
3806 | /* if no beep switch is available, make its own one */ | 3816 | /* if no beep switch is available, make its own one */ |
3807 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); | 3817 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); |
3808 | if (!(caps & AC_AMPCAP_MUTE)) { | 3818 | if (!(caps & AC_AMPCAP_MUTE)) { |
@@ -5005,6 +5015,7 @@ static int patch_stac9200(struct hda_codec *codec) | |||
5005 | 5015 | ||
5006 | codec->no_trigger_sense = 1; | 5016 | codec->no_trigger_sense = 1; |
5007 | codec->spec = spec; | 5017 | codec->spec = spec; |
5018 | spec->linear_tone_beep = 1; | ||
5008 | spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); | 5019 | spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); |
5009 | spec->pin_nids = stac9200_pin_nids; | 5020 | spec->pin_nids = stac9200_pin_nids; |
5010 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, | 5021 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, |
@@ -5068,6 +5079,7 @@ static int patch_stac925x(struct hda_codec *codec) | |||
5068 | 5079 | ||
5069 | codec->no_trigger_sense = 1; | 5080 | codec->no_trigger_sense = 1; |
5070 | codec->spec = spec; | 5081 | codec->spec = spec; |
5082 | spec->linear_tone_beep = 1; | ||
5071 | spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); | 5083 | spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); |
5072 | spec->pin_nids = stac925x_pin_nids; | 5084 | spec->pin_nids = stac925x_pin_nids; |
5073 | 5085 | ||
@@ -5153,6 +5165,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec) | |||
5153 | 5165 | ||
5154 | codec->no_trigger_sense = 1; | 5166 | codec->no_trigger_sense = 1; |
5155 | codec->spec = spec; | 5167 | codec->spec = spec; |
5168 | spec->linear_tone_beep = 0; | ||
5156 | codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; | 5169 | codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; |
5157 | spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); | 5170 | spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); |
5158 | spec->pin_nids = stac92hd73xx_pin_nids; | 5171 | spec->pin_nids = stac92hd73xx_pin_nids; |
@@ -5300,6 +5313,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
5300 | 5313 | ||
5301 | codec->no_trigger_sense = 1; | 5314 | codec->no_trigger_sense = 1; |
5302 | codec->spec = spec; | 5315 | codec->spec = spec; |
5316 | spec->linear_tone_beep = 1; | ||
5303 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; | 5317 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; |
5304 | spec->digbeep_nid = 0x21; | 5318 | spec->digbeep_nid = 0x21; |
5305 | spec->mux_nids = stac92hd83xxx_mux_nids; | 5319 | spec->mux_nids = stac92hd83xxx_mux_nids; |
@@ -5335,6 +5349,8 @@ again: | |||
5335 | case 0x111d7667: | 5349 | case 0x111d7667: |
5336 | case 0x111d7668: | 5350 | case 0x111d7668: |
5337 | case 0x111d7669: | 5351 | case 0x111d7669: |
5352 | case 0x111d76d1: | ||
5353 | case 0x111d76d9: | ||
5338 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); | 5354 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); |
5339 | spec->pin_nids = stac92hd88xxx_pin_nids; | 5355 | spec->pin_nids = stac92hd88xxx_pin_nids; |
5340 | spec->mono_nid = 0; | 5356 | spec->mono_nid = 0; |
@@ -5522,6 +5538,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
5522 | 5538 | ||
5523 | codec->no_trigger_sense = 1; | 5539 | codec->no_trigger_sense = 1; |
5524 | codec->spec = spec; | 5540 | codec->spec = spec; |
5541 | spec->linear_tone_beep = 0; | ||
5525 | codec->patch_ops = stac92xx_patch_ops; | 5542 | codec->patch_ops = stac92xx_patch_ops; |
5526 | spec->num_pins = STAC92HD71BXX_NUM_PINS; | 5543 | spec->num_pins = STAC92HD71BXX_NUM_PINS; |
5527 | switch (codec->vendor_id) { | 5544 | switch (codec->vendor_id) { |
@@ -5779,6 +5796,7 @@ static int patch_stac922x(struct hda_codec *codec) | |||
5779 | 5796 | ||
5780 | codec->no_trigger_sense = 1; | 5797 | codec->no_trigger_sense = 1; |
5781 | codec->spec = spec; | 5798 | codec->spec = spec; |
5799 | spec->linear_tone_beep = 1; | ||
5782 | spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); | 5800 | spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); |
5783 | spec->pin_nids = stac922x_pin_nids; | 5801 | spec->pin_nids = stac922x_pin_nids; |
5784 | spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, | 5802 | spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, |
@@ -5883,6 +5901,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
5883 | 5901 | ||
5884 | codec->no_trigger_sense = 1; | 5902 | codec->no_trigger_sense = 1; |
5885 | codec->spec = spec; | 5903 | codec->spec = spec; |
5904 | spec->linear_tone_beep = 1; | ||
5886 | codec->slave_dig_outs = stac927x_slave_dig_outs; | 5905 | codec->slave_dig_outs = stac927x_slave_dig_outs; |
5887 | spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); | 5906 | spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); |
5888 | spec->pin_nids = stac927x_pin_nids; | 5907 | spec->pin_nids = stac927x_pin_nids; |
@@ -6018,6 +6037,7 @@ static int patch_stac9205(struct hda_codec *codec) | |||
6018 | 6037 | ||
6019 | codec->no_trigger_sense = 1; | 6038 | codec->no_trigger_sense = 1; |
6020 | codec->spec = spec; | 6039 | codec->spec = spec; |
6040 | spec->linear_tone_beep = 1; | ||
6021 | spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); | 6041 | spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); |
6022 | spec->pin_nids = stac9205_pin_nids; | 6042 | spec->pin_nids = stac9205_pin_nids; |
6023 | spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, | 6043 | spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, |
@@ -6174,6 +6194,7 @@ static int patch_stac9872(struct hda_codec *codec) | |||
6174 | return -ENOMEM; | 6194 | return -ENOMEM; |
6175 | codec->no_trigger_sense = 1; | 6195 | codec->no_trigger_sense = 1; |
6176 | codec->spec = spec; | 6196 | codec->spec = spec; |
6197 | spec->linear_tone_beep = 1; | ||
6177 | spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); | 6198 | spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); |
6178 | spec->pin_nids = stac9872_pin_nids; | 6199 | spec->pin_nids = stac9872_pin_nids; |
6179 | 6200 | ||
@@ -6264,6 +6285,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
6264 | { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, | 6285 | { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, |
6265 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, | 6286 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, |
6266 | { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, | 6287 | { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, |
6288 | { .id = 0x111d76d1, .name = "92HD87B1/3", .patch = patch_stac92hd83xxx}, | ||
6289 | { .id = 0x111d76d9, .name = "92HD87B2/4", .patch = patch_stac92hd83xxx}, | ||
6267 | { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, | 6290 | { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, |
6268 | { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, | 6291 | { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, |
6269 | { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, | 6292 | { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, |
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 | ||
555 | static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin); | ||
556 | |||
555 | static void via_auto_init_analog_input(struct hda_codec *codec) | 557 | static 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 | ||
571 | static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin); | ||
572 | |||
573 | static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, | 579 | static 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; | |||
85 | static int ac97_clock = 48000; | 85 | static int ac97_clock = 48000; |
86 | static char *ac97_quirk; | 86 | static char *ac97_quirk; |
87 | static int dxs_support; | 87 | static int dxs_support; |
88 | static int dxs_init_volume = 31; | ||
88 | static int nodelay; | 89 | static int nodelay; |
89 | 90 | ||
90 | module_param(index, int, 0444); | 91 | module_param(index, int, 0444); |
@@ -103,6 +104,8 @@ module_param(ac97_quirk, charp, 0444); | |||
103 | MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); | 104 | MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); |
104 | module_param(dxs_support, int, 0444); | 105 | module_param(dxs_support, int, 0444); |
105 | MODULE_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)"); | 106 | MODULE_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)"); |
107 | module_param(dxs_init_volume, int, 0644); | ||
108 | MODULE_PARM_DESC(dxs_init_volume, "initial DXS volume (0-31)"); | ||
106 | module_param(nodelay, int, 0444); | 109 | module_param(nodelay, int, 0444); |
107 | MODULE_PARM_DESC(nodelay, "Disable 500ms init delay"); | 110 | MODULE_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/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index 22208b373fb9..e1ec6d91ea38 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h | |||
@@ -73,7 +73,7 @@ struct psc_dma { | |||
73 | }; | 73 | }; |
74 | 74 | ||
75 | /* Utility for retrieving psc_dma_stream structure from a substream */ | 75 | /* Utility for retrieving psc_dma_stream structure from a substream */ |
76 | inline struct psc_dma_stream * | 76 | static inline struct psc_dma_stream * |
77 | to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) | 77 | to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) |
78 | { | 78 | { |
79 | if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) | 79 | if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) |
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 1941a357e8c4..d256f5f313b5 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -328,38 +328,6 @@ static struct snd_soc_device spitz_snd_devdata = { | |||
328 | .codec_dev = &soc_codec_dev_wm8750, | 328 | .codec_dev = &soc_codec_dev_wm8750, |
329 | }; | 329 | }; |
330 | 330 | ||
331 | /* | ||
332 | * FIXME: This is a temporary bodge to avoid cross-tree merge issues. | ||
333 | * New drivers should register the wm8750 I2C device in the machine | ||
334 | * setup code (under arch/arm for ARM systems). | ||
335 | */ | ||
336 | static int wm8750_i2c_register(void) | ||
337 | { | ||
338 | struct i2c_board_info info; | ||
339 | struct i2c_adapter *adapter; | ||
340 | struct i2c_client *client; | ||
341 | |||
342 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
343 | info.addr = 0x1b; | ||
344 | strlcpy(info.type, "wm8750", I2C_NAME_SIZE); | ||
345 | |||
346 | adapter = i2c_get_adapter(0); | ||
347 | if (!adapter) { | ||
348 | printk(KERN_ERR "can't get i2c adapter 0\n"); | ||
349 | return -ENODEV; | ||
350 | } | ||
351 | |||
352 | client = i2c_new_device(adapter, &info); | ||
353 | i2c_put_adapter(adapter); | ||
354 | if (!client) { | ||
355 | printk(KERN_ERR "can't add i2c device at 0x%x\n", | ||
356 | (unsigned int)info.addr); | ||
357 | return -ENODEV; | ||
358 | } | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static struct platform_device *spitz_snd_device; | 331 | static struct platform_device *spitz_snd_device; |
364 | 332 | ||
365 | static int __init spitz_init(void) | 333 | static int __init spitz_init(void) |
@@ -369,10 +337,6 @@ static int __init spitz_init(void) | |||
369 | if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita())) | 337 | if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita())) |
370 | return -ENODEV; | 338 | return -ENODEV; |
371 | 339 | ||
372 | ret = wm8750_i2c_setup(); | ||
373 | if (ret != 0) | ||
374 | return ret; | ||
375 | |||
376 | spitz_snd_device = platform_device_alloc("soc-audio", -1); | 340 | spitz_snd_device = platform_device_alloc("soc-audio", -1); |
377 | if (!spitz_snd_device) | 341 | if (!spitz_snd_device) |
378 | return -ENOMEM; | 342 | return -ENOMEM; |
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/spi/at73c213.c b/sound/spi/at73c213.c index 4c7b051f9d17..1bc56b2b94e2 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c | |||
@@ -69,7 +69,6 @@ struct snd_at73c213 { | |||
69 | int irq; | 69 | int irq; |
70 | int period; | 70 | int period; |
71 | unsigned long bitrate; | 71 | unsigned long bitrate; |
72 | struct clk *bitclk; | ||
73 | struct ssc_device *ssc; | 72 | struct ssc_device *ssc; |
74 | struct spi_device *spi; | 73 | struct spi_device *spi; |
75 | u8 spi_wbuffer[2]; | 74 | u8 spi_wbuffer[2]; |
diff --git a/sound/usb/Makefile b/sound/usb/Makefile index e7ac7f493a8f..1e362bf8834f 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile | |||
@@ -11,7 +11,8 @@ snd-usb-audio-objs := card.o \ | |||
11 | endpoint.o \ | 11 | endpoint.o \ |
12 | urb.o \ | 12 | urb.o \ |
13 | pcm.o \ | 13 | pcm.o \ |
14 | helper.o | 14 | helper.o \ |
15 | clock.o | ||
15 | 16 | ||
16 | snd-usbmidi-lib-objs := midi.o | 17 | snd-usbmidi-lib-objs := midi.o |
17 | 18 | ||
diff --git a/sound/usb/card.c b/sound/usb/card.c index da1346bd4856..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"); |
@@ -236,7 +236,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) | |||
236 | } | 236 | } |
237 | 237 | ||
238 | case UAC_VERSION_2: { | 238 | case UAC_VERSION_2: { |
239 | struct uac_clock_source_descriptor *cs; | ||
240 | struct usb_interface_assoc_descriptor *assoc = | 239 | struct usb_interface_assoc_descriptor *assoc = |
241 | usb_ifnum_to_if(dev, ctrlif)->intf_assoc; | 240 | usb_ifnum_to_if(dev, ctrlif)->intf_assoc; |
242 | 241 | ||
@@ -245,21 +244,6 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) | |||
245 | return -EINVAL; | 244 | return -EINVAL; |
246 | } | 245 | } |
247 | 246 | ||
248 | /* FIXME: for now, we expect there is at least one clock source | ||
249 | * descriptor and we always take the first one. | ||
250 | * We should properly support devices with multiple clock sources, | ||
251 | * clock selectors and sample rate conversion units. */ | ||
252 | |||
253 | cs = snd_usb_find_csint_desc(host_iface->extra, host_iface->extralen, | ||
254 | NULL, UAC2_CLOCK_SOURCE); | ||
255 | |||
256 | if (!cs) { | ||
257 | snd_printk(KERN_ERR "CLOCK_SOURCE descriptor not found\n"); | ||
258 | return -EINVAL; | ||
259 | } | ||
260 | |||
261 | chip->clock_id = cs->bClockID; | ||
262 | |||
263 | for (i = 0; i < assoc->bInterfaceCount; i++) { | 247 | for (i = 0; i < assoc->bInterfaceCount; i++) { |
264 | int intf = assoc->bFirstInterface + i; | 248 | int intf = assoc->bFirstInterface + i; |
265 | 249 | ||
@@ -481,6 +465,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
481 | goto __error; | 465 | goto __error; |
482 | } | 466 | } |
483 | 467 | ||
468 | chip->ctrl_intf = alts; | ||
469 | |||
484 | if (err > 0) { | 470 | if (err > 0) { |
485 | /* create normal USB audio interfaces */ | 471 | /* create normal USB audio interfaces */ |
486 | if (snd_usb_create_streams(chip, ifnum) < 0 || | 472 | if (snd_usb_create_streams(chip, ifnum) < 0 || |
diff --git a/sound/usb/card.h b/sound/usb/card.h index ed92420c1095..1febf2f23754 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h | |||
@@ -25,6 +25,7 @@ struct audioformat { | |||
25 | unsigned int rate_min, rate_max; /* min/max rates */ | 25 | unsigned int rate_min, rate_max; /* min/max rates */ |
26 | unsigned int nr_rates; /* number of rate table entries */ | 26 | unsigned int nr_rates; /* number of rate table entries */ |
27 | unsigned int *rate_table; /* rate table */ | 27 | unsigned int *rate_table; /* rate table */ |
28 | unsigned char clock; /* associated clock */ | ||
28 | }; | 29 | }; |
29 | 30 | ||
30 | struct snd_usb_substream; | 31 | struct snd_usb_substream; |
diff --git a/sound/usb/clock.c b/sound/usb/clock.c new file mode 100644 index 000000000000..b853f8df794f --- /dev/null +++ b/sound/usb/clock.c | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * Clock domain and sample rate management functions | ||
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 as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/bitops.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/usb.h> | ||
24 | #include <linux/usb/audio.h> | ||
25 | #include <linux/usb/audio-v2.h> | ||
26 | |||
27 | #include <sound/core.h> | ||
28 | #include <sound/info.h> | ||
29 | #include <sound/pcm.h> | ||
30 | |||
31 | #include "usbaudio.h" | ||
32 | #include "card.h" | ||
33 | #include "helper.h" | ||
34 | #include "clock.h" | ||
35 | |||
36 | static struct uac_clock_source_descriptor * | ||
37 | snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface, | ||
38 | int clock_id) | ||
39 | { | ||
40 | struct uac_clock_source_descriptor *cs = NULL; | ||
41 | |||
42 | while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, | ||
43 | ctrl_iface->extralen, | ||
44 | cs, UAC2_CLOCK_SOURCE))) { | ||
45 | if (cs->bClockID == clock_id) | ||
46 | return cs; | ||
47 | } | ||
48 | |||
49 | return NULL; | ||
50 | } | ||
51 | |||
52 | static struct uac_clock_selector_descriptor * | ||
53 | snd_usb_find_clock_selector(struct usb_host_interface *ctrl_iface, | ||
54 | int clock_id) | ||
55 | { | ||
56 | struct uac_clock_selector_descriptor *cs = NULL; | ||
57 | |||
58 | while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, | ||
59 | ctrl_iface->extralen, | ||
60 | cs, UAC2_CLOCK_SELECTOR))) { | ||
61 | if (cs->bClockID == clock_id) | ||
62 | return cs; | ||
63 | } | ||
64 | |||
65 | return NULL; | ||
66 | } | ||
67 | |||
68 | static struct uac_clock_multiplier_descriptor * | ||
69 | snd_usb_find_clock_multiplier(struct usb_host_interface *ctrl_iface, | ||
70 | int clock_id) | ||
71 | { | ||
72 | struct uac_clock_multiplier_descriptor *cs = NULL; | ||
73 | |||
74 | while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, | ||
75 | ctrl_iface->extralen, | ||
76 | cs, UAC2_CLOCK_MULTIPLIER))) { | ||
77 | if (cs->bClockID == clock_id) | ||
78 | return cs; | ||
79 | } | ||
80 | |||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id) | ||
85 | { | ||
86 | unsigned char buf; | ||
87 | int ret; | ||
88 | |||
89 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), | ||
90 | UAC2_CS_CUR, | ||
91 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | ||
92 | UAC2_CX_CLOCK_SELECTOR << 8, | ||
93 | snd_usb_ctrl_intf(chip) | (selector_id << 8), | ||
94 | &buf, sizeof(buf), 1000); | ||
95 | |||
96 | if (ret < 0) | ||
97 | return ret; | ||
98 | |||
99 | return buf; | ||
100 | } | ||
101 | |||
102 | static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) | ||
103 | { | ||
104 | int err; | ||
105 | unsigned char data; | ||
106 | struct usb_device *dev = chip->dev; | ||
107 | |||
108 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, | ||
109 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
110 | UAC2_CS_CONTROL_CLOCK_VALID << 8, | ||
111 | snd_usb_ctrl_intf(chip) | (source_id << 8), | ||
112 | &data, sizeof(data), 1000); | ||
113 | |||
114 | if (err < 0) { | ||
115 | snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n", | ||
116 | __func__, source_id); | ||
117 | return err; | ||
118 | } | ||
119 | |||
120 | return !!data; | ||
121 | } | ||
122 | |||
123 | static int __uac_clock_find_source(struct snd_usb_audio *chip, | ||
124 | int entity_id, unsigned long *visited) | ||
125 | { | ||
126 | struct uac_clock_source_descriptor *source; | ||
127 | struct uac_clock_selector_descriptor *selector; | ||
128 | struct uac_clock_multiplier_descriptor *multiplier; | ||
129 | |||
130 | entity_id &= 0xff; | ||
131 | |||
132 | if (test_and_set_bit(entity_id, visited)) { | ||
133 | snd_printk(KERN_WARNING | ||
134 | "%s(): recursive clock topology detected, id %d.\n", | ||
135 | __func__, entity_id); | ||
136 | return -EINVAL; | ||
137 | } | ||
138 | |||
139 | /* first, see if the ID we're looking for is a clock source already */ | ||
140 | source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id); | ||
141 | if (source) | ||
142 | return source->bClockID; | ||
143 | |||
144 | selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id); | ||
145 | if (selector) { | ||
146 | int ret; | ||
147 | |||
148 | /* the entity ID we are looking for is a selector. | ||
149 | * find out what it currently selects */ | ||
150 | ret = uac_clock_selector_get_val(chip, selector->bClockID); | ||
151 | if (ret < 0) | ||
152 | return ret; | ||
153 | |||
154 | /* Selector values are one-based */ | ||
155 | |||
156 | if (ret > selector->bNrInPins || ret < 1) { | ||
157 | printk(KERN_ERR | ||
158 | "%s(): selector reported illegal value, id %d, ret %d\n", | ||
159 | __func__, selector->bClockID, ret); | ||
160 | |||
161 | return -EINVAL; | ||
162 | } | ||
163 | |||
164 | return __uac_clock_find_source(chip, selector->baCSourceID[ret-1], | ||
165 | visited); | ||
166 | } | ||
167 | |||
168 | /* FIXME: multipliers only act as pass-thru element for now */ | ||
169 | multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id); | ||
170 | if (multiplier) | ||
171 | return __uac_clock_find_source(chip, multiplier->bCSourceID, | ||
172 | visited); | ||
173 | |||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * For all kinds of sample rate settings and other device queries, | ||
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 | */ | ||
188 | int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id) | ||
189 | { | ||
190 | DECLARE_BITMAP(visited, 256); | ||
191 | memset(visited, 0, sizeof(visited)); | ||
192 | return __uac_clock_find_source(chip, entity_id, visited); | ||
193 | } | ||
194 | |||
195 | static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, | ||
196 | struct usb_host_interface *alts, | ||
197 | struct audioformat *fmt, int rate) | ||
198 | { | ||
199 | struct usb_device *dev = chip->dev; | ||
200 | unsigned int ep; | ||
201 | unsigned char data[3]; | ||
202 | int err, crate; | ||
203 | |||
204 | ep = get_endpoint(alts, 0)->bEndpointAddress; | ||
205 | |||
206 | /* if endpoint doesn't have sampling rate control, bail out */ | ||
207 | if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) | ||
208 | return 0; | ||
209 | |||
210 | data[0] = rate; | ||
211 | data[1] = rate >> 8; | ||
212 | data[2] = rate >> 16; | ||
213 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, | ||
214 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, | ||
215 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, | ||
216 | data, sizeof(data), 1000)) < 0) { | ||
217 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n", | ||
218 | dev->devnum, iface, fmt->altsetting, rate, ep); | ||
219 | return err; | ||
220 | } | ||
221 | |||
222 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, | ||
223 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, | ||
224 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, | ||
225 | data, sizeof(data), 1000)) < 0) { | ||
226 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n", | ||
227 | dev->devnum, iface, fmt->altsetting, ep); | ||
228 | return 0; /* some devices don't support reading */ | ||
229 | } | ||
230 | |||
231 | crate = data[0] | (data[1] << 8) | (data[2] << 16); | ||
232 | if (crate != rate) { | ||
233 | snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); | ||
234 | // runtime->rate = crate; | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, | ||
241 | struct usb_host_interface *alts, | ||
242 | struct audioformat *fmt, int rate) | ||
243 | { | ||
244 | struct usb_device *dev = chip->dev; | ||
245 | unsigned char data[4]; | ||
246 | int err, crate; | ||
247 | int clock = snd_usb_clock_find_source(chip, fmt->clock); | ||
248 | |||
249 | if (clock < 0) | ||
250 | return clock; | ||
251 | |||
252 | if (!uac_clock_source_is_valid(chip, clock)) { | ||
253 | /* TODO: should we try to find valid clock setups by ourself? */ | ||
254 | snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n", | ||
255 | dev->devnum, iface, fmt->altsetting, clock); | ||
256 | return -ENXIO; | ||
257 | } | ||
258 | |||
259 | data[0] = rate; | ||
260 | data[1] = rate >> 8; | ||
261 | data[2] = rate >> 16; | ||
262 | data[3] = rate >> 24; | ||
263 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, | ||
264 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
265 | UAC2_CS_CONTROL_SAM_FREQ << 8, | ||
266 | snd_usb_ctrl_intf(chip) | (clock << 8), | ||
267 | data, sizeof(data), 1000)) < 0) { | ||
268 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n", | ||
269 | dev->devnum, iface, fmt->altsetting, rate); | ||
270 | return err; | ||
271 | } | ||
272 | |||
273 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, | ||
274 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
275 | UAC2_CS_CONTROL_SAM_FREQ << 8, | ||
276 | snd_usb_ctrl_intf(chip) | (clock << 8), | ||
277 | data, sizeof(data), 1000)) < 0) { | ||
278 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n", | ||
279 | dev->devnum, iface, fmt->altsetting); | ||
280 | return err; | ||
281 | } | ||
282 | |||
283 | crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); | ||
284 | if (crate != rate) | ||
285 | snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, | ||
291 | struct usb_host_interface *alts, | ||
292 | struct audioformat *fmt, int rate) | ||
293 | { | ||
294 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); | ||
295 | |||
296 | switch (altsd->bInterfaceProtocol) { | ||
297 | case UAC_VERSION_1: | ||
298 | return set_sample_rate_v1(chip, iface, alts, fmt, rate); | ||
299 | |||
300 | case UAC_VERSION_2: | ||
301 | return set_sample_rate_v2(chip, iface, alts, fmt, rate); | ||
302 | } | ||
303 | |||
304 | return -EINVAL; | ||
305 | } | ||
306 | |||
diff --git a/sound/usb/clock.h b/sound/usb/clock.h new file mode 100644 index 000000000000..46630936d31f --- /dev/null +++ b/sound/usb/clock.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __USBAUDIO_CLOCK_H | ||
2 | #define __USBAUDIO_CLOCK_H | ||
3 | |||
4 | int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, | ||
5 | struct usb_host_interface *alts, | ||
6 | struct audioformat *fmt, int rate); | ||
7 | |||
8 | int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id); | ||
9 | |||
10 | #endif /* __USBAUDIO_CLOCK_H */ | ||
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 28ee1ce3971a..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 |
@@ -190,6 +191,38 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, | |||
190 | return attributes; | 191 | return attributes; |
191 | } | 192 | } |
192 | 193 | ||
194 | static struct uac2_input_terminal_descriptor * | ||
195 | snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, | ||
196 | int terminal_id) | ||
197 | { | ||
198 | struct uac2_input_terminal_descriptor *term = NULL; | ||
199 | |||
200 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, | ||
201 | ctrl_iface->extralen, | ||
202 | term, UAC_INPUT_TERMINAL))) { | ||
203 | if (term->bTerminalID == terminal_id) | ||
204 | return term; | ||
205 | } | ||
206 | |||
207 | return NULL; | ||
208 | } | ||
209 | |||
210 | static struct uac2_output_terminal_descriptor * | ||
211 | snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, | ||
212 | int terminal_id) | ||
213 | { | ||
214 | struct uac2_output_terminal_descriptor *term = NULL; | ||
215 | |||
216 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, | ||
217 | ctrl_iface->extralen, | ||
218 | term, UAC_OUTPUT_TERMINAL))) { | ||
219 | if (term->bTerminalID == terminal_id) | ||
220 | return term; | ||
221 | } | ||
222 | |||
223 | return NULL; | ||
224 | } | ||
225 | |||
193 | int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | 226 | int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) |
194 | { | 227 | { |
195 | struct usb_device *dev; | 228 | struct usb_device *dev; |
@@ -199,7 +232,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
199 | int i, altno, err, stream; | 232 | int i, altno, err, stream; |
200 | int format = 0, num_channels = 0; | 233 | int format = 0, num_channels = 0; |
201 | struct audioformat *fp = NULL; | 234 | struct audioformat *fp = NULL; |
202 | int num, protocol; | 235 | int num, protocol, clock = 0; |
203 | struct uac_format_type_i_continuous_descriptor *fmt; | 236 | struct uac_format_type_i_continuous_descriptor *fmt; |
204 | 237 | ||
205 | dev = chip->dev; | 238 | dev = chip->dev; |
@@ -243,7 +276,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
243 | /* get audio formats */ | 276 | /* get audio formats */ |
244 | switch (protocol) { | 277 | switch (protocol) { |
245 | case UAC_VERSION_1: { | 278 | case UAC_VERSION_1: { |
246 | struct uac_as_header_descriptor_v1 *as = | 279 | struct uac1_as_header_descriptor *as = |
247 | 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); |
248 | 281 | ||
249 | if (!as) { | 282 | if (!as) { |
@@ -263,7 +296,9 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
263 | } | 296 | } |
264 | 297 | ||
265 | case UAC_VERSION_2: { | 298 | case UAC_VERSION_2: { |
266 | struct uac_as_header_descriptor_v2 *as = | 299 | struct uac2_input_terminal_descriptor *input_term; |
300 | struct uac2_output_terminal_descriptor *output_term; | ||
301 | struct uac2_as_header_descriptor *as = | ||
267 | 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); |
268 | 303 | ||
269 | if (!as) { | 304 | if (!as) { |
@@ -281,7 +316,25 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
281 | num_channels = as->bNrChannels; | 316 | num_channels = as->bNrChannels; |
282 | format = le32_to_cpu(as->bmFormats); | 317 | format = le32_to_cpu(as->bmFormats); |
283 | 318 | ||
284 | break; | 319 | /* lookup the terminal associated to this interface |
320 | * to extract the clock */ | ||
321 | input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, | ||
322 | as->bTerminalLink); | ||
323 | if (input_term) { | ||
324 | clock = input_term->bCSourceID; | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, | ||
329 | as->bTerminalLink); | ||
330 | if (output_term) { | ||
331 | clock = output_term->bCSourceID; | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n", | ||
336 | dev->devnum, iface_no, altno, as->bTerminalLink); | ||
337 | continue; | ||
285 | } | 338 | } |
286 | 339 | ||
287 | default: | 340 | default: |
@@ -338,6 +391,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
338 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) | 391 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) |
339 | * (fp->maxpacksize & 0x7ff); | 392 | * (fp->maxpacksize & 0x7ff); |
340 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); | 393 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); |
394 | fp->clock = clock; | ||
341 | 395 | ||
342 | /* some quirks for attributes here */ | 396 | /* some quirks for attributes here */ |
343 | 397 | ||
@@ -374,6 +428,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
374 | if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { | 428 | if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { |
375 | kfree(fp->rate_table); | 429 | kfree(fp->rate_table); |
376 | kfree(fp); | 430 | kfree(fp); |
431 | fp = NULL; | ||
377 | continue; | 432 | continue; |
378 | } | 433 | } |
379 | 434 | ||
diff --git a/sound/usb/format.c b/sound/usb/format.c index fe29d61de19b..4387f54d73db 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "quirks.h" | 29 | #include "quirks.h" |
30 | #include "helper.h" | 30 | #include "helper.h" |
31 | #include "debug.h" | 31 | #include "debug.h" |
32 | #include "clock.h" | ||
32 | 33 | ||
33 | /* | 34 | /* |
34 | * parse the audio format type I descriptor | 35 | * parse the audio format type I descriptor |
@@ -205,30 +206,92 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof | |||
205 | } | 206 | } |
206 | 207 | ||
207 | /* | 208 | /* |
209 | * Helper function to walk the array of sample rate triplets reported by | ||
210 | * the device. The problem is that we need to parse whole array first to | ||
211 | * get to know how many sample rates we have to expect. | ||
212 | * Then fp->rate_table can be allocated and filled. | ||
213 | */ | ||
214 | static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets, | ||
215 | const unsigned char *data) | ||
216 | { | ||
217 | int i, nr_rates = 0; | ||
218 | |||
219 | fp->rates = fp->rate_min = fp->rate_max = 0; | ||
220 | |||
221 | for (i = 0; i < nr_triplets; i++) { | ||
222 | int min = combine_quad(&data[2 + 12 * i]); | ||
223 | int max = combine_quad(&data[6 + 12 * i]); | ||
224 | int res = combine_quad(&data[10 + 12 * i]); | ||
225 | int rate; | ||
226 | |||
227 | if ((max < 0) || (min < 0) || (res < 0) || (max < min)) | ||
228 | continue; | ||
229 | |||
230 | /* | ||
231 | * for ranges with res == 1, we announce a continuous sample | ||
232 | * rate range, and this function should return 0 for no further | ||
233 | * parsing. | ||
234 | */ | ||
235 | if (res == 1) { | ||
236 | fp->rate_min = min; | ||
237 | fp->rate_max = max; | ||
238 | fp->rates = SNDRV_PCM_RATE_CONTINUOUS; | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | for (rate = min; rate <= max; rate += res) { | ||
243 | if (fp->rate_table) | ||
244 | fp->rate_table[nr_rates] = rate; | ||
245 | if (!fp->rate_min || rate < fp->rate_min) | ||
246 | fp->rate_min = rate; | ||
247 | if (!fp->rate_max || rate > fp->rate_max) | ||
248 | fp->rate_max = rate; | ||
249 | fp->rates |= snd_pcm_rate_to_rate_bit(rate); | ||
250 | |||
251 | nr_rates++; | ||
252 | |||
253 | /* avoid endless loop */ | ||
254 | if (res == 0) | ||
255 | break; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | return nr_rates; | ||
260 | } | ||
261 | |||
262 | /* | ||
208 | * parse the format descriptor and stores the possible sample rates | 263 | * parse the format descriptor and stores the possible sample rates |
209 | * on the audioformat table (audio class v2). | 264 | * on the audioformat table (audio class v2). |
210 | */ | 265 | */ |
211 | static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, | 266 | static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, |
212 | struct audioformat *fp, | 267 | struct audioformat *fp) |
213 | struct usb_host_interface *iface) | ||
214 | { | 268 | { |
215 | struct usb_device *dev = chip->dev; | 269 | struct usb_device *dev = chip->dev; |
216 | unsigned char tmp[2], *data; | 270 | unsigned char tmp[2], *data; |
217 | int i, nr_rates, data_size, ret = 0; | 271 | int nr_triplets, data_size, ret = 0; |
272 | int clock = snd_usb_clock_find_source(chip, fp->clock); | ||
273 | |||
274 | if (clock < 0) { | ||
275 | snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n", | ||
276 | __func__, clock); | ||
277 | goto err; | ||
278 | } | ||
218 | 279 | ||
219 | /* get the number of sample rates first by only fetching 2 bytes */ | 280 | /* get the number of sample rates first by only fetching 2 bytes */ |
220 | ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, | 281 | ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, |
221 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 282 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
222 | UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, | 283 | UAC2_CS_CONTROL_SAM_FREQ << 8, |
284 | snd_usb_ctrl_intf(chip) | (clock << 8), | ||
223 | tmp, sizeof(tmp), 1000); | 285 | tmp, sizeof(tmp), 1000); |
224 | 286 | ||
225 | if (ret < 0) { | 287 | if (ret < 0) { |
226 | snd_printk(KERN_ERR "unable to retrieve number of sample rates\n"); | 288 | snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n", |
289 | __func__, clock); | ||
227 | goto err; | 290 | goto err; |
228 | } | 291 | } |
229 | 292 | ||
230 | nr_rates = (tmp[1] << 8) | tmp[0]; | 293 | nr_triplets = (tmp[1] << 8) | tmp[0]; |
231 | data_size = 2 + 12 * nr_rates; | 294 | data_size = 2 + 12 * nr_triplets; |
232 | data = kzalloc(data_size, GFP_KERNEL); | 295 | data = kzalloc(data_size, GFP_KERNEL); |
233 | if (!data) { | 296 | if (!data) { |
234 | ret = -ENOMEM; | 297 | ret = -ENOMEM; |
@@ -237,36 +300,40 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, | |||
237 | 300 | ||
238 | /* now get the full information */ | 301 | /* now get the full information */ |
239 | ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, | 302 | ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, |
240 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 303 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
241 | UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, | 304 | UAC2_CS_CONTROL_SAM_FREQ << 8, |
242 | data, data_size, 1000); | 305 | snd_usb_ctrl_intf(chip) | (clock << 8), |
306 | data, data_size, 1000); | ||
243 | 307 | ||
244 | if (ret < 0) { | 308 | if (ret < 0) { |
245 | snd_printk(KERN_ERR "unable to retrieve sample rate range\n"); | 309 | snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n", |
310 | __func__, clock); | ||
246 | ret = -EINVAL; | 311 | ret = -EINVAL; |
247 | goto err_free; | 312 | goto err_free; |
248 | } | 313 | } |
249 | 314 | ||
250 | fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); | 315 | /* Call the triplet parser, and make sure fp->rate_table is NULL. |
316 | * We just use the return value to know how many sample rates we | ||
317 | * will have to deal with. */ | ||
318 | kfree(fp->rate_table); | ||
319 | fp->rate_table = NULL; | ||
320 | fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data); | ||
321 | |||
322 | if (fp->nr_rates == 0) { | ||
323 | /* SNDRV_PCM_RATE_CONTINUOUS */ | ||
324 | ret = 0; | ||
325 | goto err_free; | ||
326 | } | ||
327 | |||
328 | fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL); | ||
251 | if (!fp->rate_table) { | 329 | if (!fp->rate_table) { |
252 | ret = -ENOMEM; | 330 | ret = -ENOMEM; |
253 | goto err_free; | 331 | goto err_free; |
254 | } | 332 | } |
255 | 333 | ||
256 | fp->nr_rates = 0; | 334 | /* Call the triplet parser again, but this time, fp->rate_table is |
257 | fp->rate_min = fp->rate_max = 0; | 335 | * allocated, so the rates will be stored */ |
258 | 336 | parse_uac2_sample_rate_range(fp, nr_triplets, data); | |
259 | for (i = 0; i < nr_rates; i++) { | ||
260 | int rate = combine_quad(&data[2 + 12 * i]); | ||
261 | |||
262 | fp->rate_table[fp->nr_rates] = rate; | ||
263 | if (!fp->rate_min || rate < fp->rate_min) | ||
264 | fp->rate_min = rate; | ||
265 | if (!fp->rate_max || rate > fp->rate_max) | ||
266 | fp->rate_max = rate; | ||
267 | fp->rates |= snd_pcm_rate_to_rate_bit(rate); | ||
268 | fp->nr_rates++; | ||
269 | } | ||
270 | 337 | ||
271 | err_free: | 338 | err_free: |
272 | kfree(data); | 339 | kfree(data); |
@@ -323,7 +390,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
323 | break; | 390 | break; |
324 | case UAC_VERSION_2: | 391 | case UAC_VERSION_2: |
325 | /* fp->channels is already set in this case */ | 392 | /* fp->channels is already set in this case */ |
326 | ret = parse_audio_format_rates_v2(chip, fp, iface); | 393 | ret = parse_audio_format_rates_v2(chip, fp); |
327 | break; | 394 | break; |
328 | } | 395 | } |
329 | 396 | ||
@@ -382,7 +449,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, | |||
382 | framesize = le16_to_cpu(fmt->wSamplesPerFrame); | 449 | framesize = le16_to_cpu(fmt->wSamplesPerFrame); |
383 | 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); |
384 | fp->frame_size = framesize; | 451 | fp->frame_size = framesize; |
385 | ret = parse_audio_format_rates_v2(chip, fp, iface); | 452 | ret = parse_audio_format_rates_v2(chip, fp); |
386 | break; | 453 | break; |
387 | } | 454 | } |
388 | } | 455 | } |
diff --git a/sound/usb/helper.h b/sound/usb/helper.h index a6b0e51b3a9a..09bd943c43bf 100644 --- a/sound/usb/helper.h +++ b/sound/usb/helper.h | |||
@@ -28,5 +28,9 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, | |||
28 | #define snd_usb_get_speed(dev) ((dev)->speed) | 28 | #define snd_usb_get_speed(dev) ((dev)->speed) |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip) | ||
32 | { | ||
33 | return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber; | ||
34 | } | ||
31 | 35 | ||
32 | #endif /* __USBAUDIO_HELPER_H */ | 36 | #endif /* __USBAUDIO_HELPER_H */ |
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 | ||
629 | static struct usb_protocol_ops snd_usbmidi_midiman_ops = { | 629 | static 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 | ||
635 | static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = { | 635 | static 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 | */ |
1249 | static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, | 1249 | static 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 | ||
1400 | static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi, | 1400 | static 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 03ce971e0027..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> |
@@ -78,39 +94,6 @@ enum { | |||
78 | USB_MIXER_U16, | 94 | USB_MIXER_U16, |
79 | }; | 95 | }; |
80 | 96 | ||
81 | enum { | ||
82 | USB_PROC_UPDOWN = 1, | ||
83 | USB_PROC_UPDOWN_SWITCH = 1, | ||
84 | USB_PROC_UPDOWN_MODE_SEL = 2, | ||
85 | |||
86 | USB_PROC_PROLOGIC = 2, | ||
87 | USB_PROC_PROLOGIC_SWITCH = 1, | ||
88 | USB_PROC_PROLOGIC_MODE_SEL = 2, | ||
89 | |||
90 | USB_PROC_3DENH = 3, | ||
91 | USB_PROC_3DENH_SWITCH = 1, | ||
92 | USB_PROC_3DENH_SPACE = 2, | ||
93 | |||
94 | USB_PROC_REVERB = 4, | ||
95 | USB_PROC_REVERB_SWITCH = 1, | ||
96 | USB_PROC_REVERB_LEVEL = 2, | ||
97 | USB_PROC_REVERB_TIME = 3, | ||
98 | USB_PROC_REVERB_DELAY = 4, | ||
99 | |||
100 | USB_PROC_CHORUS = 5, | ||
101 | USB_PROC_CHORUS_SWITCH = 1, | ||
102 | USB_PROC_CHORUS_LEVEL = 2, | ||
103 | USB_PROC_CHORUS_RATE = 3, | ||
104 | USB_PROC_CHORUS_DEPTH = 4, | ||
105 | |||
106 | USB_PROC_DCR = 6, | ||
107 | USB_PROC_DCR_SWITCH = 1, | ||
108 | USB_PROC_DCR_RATIO = 2, | ||
109 | USB_PROC_DCR_MAX_AMP = 3, | ||
110 | USB_PROC_DCR_THRESHOLD = 4, | ||
111 | USB_PROC_DCR_ATTACK = 5, | ||
112 | USB_PROC_DCR_RELEASE = 6, | ||
113 | }; | ||
114 | 97 | ||
115 | /*E-mu 0202(0404) eXtension Unit(XU) control*/ | 98 | /*E-mu 0202(0404) eXtension Unit(XU) control*/ |
116 | enum { | 99 | enum { |
@@ -198,22 +181,24 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid, | |||
198 | 181 | ||
199 | /* | 182 | /* |
200 | * find an audio control unit with the given unit id | 183 | * find an audio control unit with the given unit id |
201 | * this doesn't return any clock related units, so they need to be handled elsewhere | ||
202 | */ | 184 | */ |
203 | static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit) | 185 | static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit) |
204 | { | 186 | { |
205 | unsigned char *p; | 187 | /* we just parse the header */ |
188 | struct uac_feature_unit_descriptor *hdr = NULL; | ||
206 | 189 | ||
207 | p = NULL; | 190 | while ((hdr = snd_usb_find_desc(state->buffer, state->buflen, hdr, |
208 | while ((p = snd_usb_find_desc(state->buffer, state->buflen, p, | 191 | USB_DT_CS_INTERFACE)) != NULL) { |
209 | USB_DT_CS_INTERFACE)) != NULL) { | 192 | if (hdr->bLength >= 4 && |
210 | if (p[0] >= 4 && p[2] >= UAC_INPUT_TERMINAL && p[2] <= UAC2_EXTENSION_UNIT_V2 && p[3] == unit) | 193 | hdr->bDescriptorSubtype >= UAC_INPUT_TERMINAL && |
211 | return p; | 194 | hdr->bDescriptorSubtype <= UAC2_SAMPLE_RATE_CONVERTER && |
195 | hdr->bUnitID == unit) | ||
196 | return hdr; | ||
212 | } | 197 | } |
198 | |||
213 | return NULL; | 199 | return NULL; |
214 | } | 200 | } |
215 | 201 | ||
216 | |||
217 | /* | 202 | /* |
218 | * copy a string with the given id | 203 | * copy a string with the given id |
219 | */ | 204 | */ |
@@ -306,49 +291,56 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val) | |||
306 | 291 | ||
307 | static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 292 | static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
308 | { | 293 | { |
294 | struct snd_usb_audio *chip = cval->mixer->chip; | ||
309 | unsigned char buf[2]; | 295 | unsigned char buf[2]; |
310 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 296 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
311 | int timeout = 10; | 297 | int timeout = 10; |
312 | 298 | ||
313 | while (timeout-- > 0) { | 299 | while (timeout-- > 0) { |
314 | if (snd_usb_ctl_msg(cval->mixer->chip->dev, | 300 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, |
315 | usb_rcvctrlpipe(cval->mixer->chip->dev, 0), | ||
316 | request, | ||
317 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 301 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
318 | validx, cval->mixer->ctrlif | (cval->id << 8), | 302 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
319 | buf, val_len, 100) >= val_len) { | 303 | buf, val_len, 100) >= val_len) { |
320 | *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)); |
321 | return 0; | 305 | return 0; |
322 | } | 306 | } |
323 | } | 307 | } |
324 | 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", |
325 | 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); |
326 | return -EINVAL; | 310 | return -EINVAL; |
327 | } | 311 | } |
328 | 312 | ||
329 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 313 | static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
330 | { | 314 | { |
331 | unsigned char buf[14]; /* enough space for one range of 4 bytes */ | 315 | struct snd_usb_audio *chip = cval->mixer->chip; |
316 | unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ | ||
332 | unsigned char *val; | 317 | unsigned char *val; |
333 | int ret; | 318 | int ret, size; |
334 | __u8 bRequest; | 319 | __u8 bRequest; |
335 | 320 | ||
336 | bRequest = (request == UAC_GET_CUR) ? | 321 | if (request == UAC_GET_CUR) { |
337 | UAC2_CS_CUR : UAC2_CS_RANGE; | 322 | bRequest = UAC2_CS_CUR; |
323 | size = sizeof(__u16); | ||
324 | } else { | ||
325 | bRequest = UAC2_CS_RANGE; | ||
326 | size = sizeof(buf); | ||
327 | } | ||
328 | |||
329 | memset(buf, 0, sizeof(buf)); | ||
338 | 330 | ||
339 | ret = snd_usb_ctl_msg(cval->mixer->chip->dev, | 331 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, |
340 | usb_rcvctrlpipe(cval->mixer->chip->dev, 0), | ||
341 | bRequest, | ||
342 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 332 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
343 | validx, cval->mixer->ctrlif | (cval->id << 8), | 333 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
344 | buf, sizeof(buf), 1000); | 334 | buf, size, 1000); |
345 | 335 | ||
346 | if (ret < 0) { | 336 | if (ret < 0) { |
347 | snd_printdd(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", |
348 | 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); |
349 | return ret; | 339 | return ret; |
350 | } | 340 | } |
351 | 341 | ||
342 | /* FIXME: how should we handle multiple triplets here? */ | ||
343 | |||
352 | switch (request) { | 344 | switch (request) { |
353 | case UAC_GET_CUR: | 345 | case UAC_GET_CUR: |
354 | val = buf; | 346 | val = buf; |
@@ -419,6 +411,7 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | |||
419 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | 411 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, |
420 | int request, int validx, int value_set) | 412 | int request, int validx, int value_set) |
421 | { | 413 | { |
414 | struct snd_usb_audio *chip = cval->mixer->chip; | ||
422 | unsigned char buf[2]; | 415 | unsigned char buf[2]; |
423 | int val_len, timeout = 10; | 416 | int val_len, timeout = 10; |
424 | 417 | ||
@@ -441,15 +434,14 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
441 | buf[0] = value_set & 0xff; | 434 | buf[0] = value_set & 0xff; |
442 | buf[1] = (value_set >> 8) & 0xff; | 435 | buf[1] = (value_set >> 8) & 0xff; |
443 | while (timeout-- > 0) | 436 | while (timeout-- > 0) |
444 | if (snd_usb_ctl_msg(cval->mixer->chip->dev, | 437 | if (snd_usb_ctl_msg(chip->dev, |
445 | usb_sndctrlpipe(cval->mixer->chip->dev, 0), | 438 | usb_sndctrlpipe(chip->dev, 0), request, |
446 | request, | ||
447 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 439 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
448 | validx, cval->mixer->ctrlif | (cval->id << 8), | 440 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
449 | buf, val_len, 100) >= 0) | 441 | buf, val_len, 100) >= 0) |
450 | return 0; | 442 | return 0; |
451 | 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", |
452 | 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]); |
453 | return -EINVAL; | 445 | return -EINVAL; |
454 | } | 446 | } |
455 | 447 | ||
@@ -462,6 +454,16 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, | |||
462 | int index, int value) | 454 | int index, int value) |
463 | { | 455 | { |
464 | int err; | 456 | int err; |
457 | unsigned int read_only = (channel == 0) ? | ||
458 | cval->master_readonly : | ||
459 | cval->ch_readonly & (1 << (channel - 1)); | ||
460 | |||
461 | if (read_only) { | ||
462 | snd_printdd(KERN_INFO "%s(): channel %d of control %d is read_only\n", | ||
463 | __func__, channel, cval->control); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
465 | err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel, | 467 | err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel, |
466 | value); | 468 | value); |
467 | if (err < 0) | 469 | if (err < 0) |
@@ -594,9 +596,9 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm | |||
594 | switch (iterm->type >> 16) { | 596 | switch (iterm->type >> 16) { |
595 | case UAC_SELECTOR_UNIT: | 597 | case UAC_SELECTOR_UNIT: |
596 | strcpy(name, "Selector"); return 8; | 598 | strcpy(name, "Selector"); return 8; |
597 | case UAC_PROCESSING_UNIT_V1: | 599 | case UAC1_PROCESSING_UNIT: |
598 | strcpy(name, "Process Unit"); return 12; | 600 | strcpy(name, "Process Unit"); return 12; |
599 | case UAC_EXTENSION_UNIT_V1: | 601 | case UAC1_EXTENSION_UNIT: |
600 | strcpy(name, "Ext Unit"); return 8; | 602 | strcpy(name, "Ext Unit"); return 8; |
601 | case UAC_MIXER_UNIT: | 603 | case UAC_MIXER_UNIT: |
602 | strcpy(name, "Mixer"); return 5; | 604 | strcpy(name, "Mixer"); return 5; |
@@ -631,6 +633,7 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm | |||
631 | */ | 633 | */ |
632 | static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term) | 634 | static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term) |
633 | { | 635 | { |
636 | int err; | ||
634 | void *p1; | 637 | void *p1; |
635 | 638 | ||
636 | memset(term, 0, sizeof(*term)); | 639 | memset(term, 0, sizeof(*term)); |
@@ -651,6 +654,11 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ | |||
651 | term->channels = d->bNrChannels; | 654 | term->channels = d->bNrChannels; |
652 | term->chconfig = le32_to_cpu(d->bmChannelConfig); | 655 | term->chconfig = le32_to_cpu(d->bmChannelConfig); |
653 | term->name = d->iTerminal; | 656 | term->name = d->iTerminal; |
657 | |||
658 | /* call recursively to get the clock selectors */ | ||
659 | err = check_input_term(state, d->bCSourceID, term); | ||
660 | if (err < 0) | ||
661 | return err; | ||
654 | } | 662 | } |
655 | return 0; | 663 | return 0; |
656 | case UAC_FEATURE_UNIT: { | 664 | case UAC_FEATURE_UNIT: { |
@@ -667,7 +675,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ | |||
667 | term->name = uac_mixer_unit_iMixer(d); | 675 | term->name = uac_mixer_unit_iMixer(d); |
668 | return 0; | 676 | return 0; |
669 | } | 677 | } |
670 | case UAC_SELECTOR_UNIT: { | 678 | case UAC_SELECTOR_UNIT: |
679 | case UAC2_CLOCK_SELECTOR: { | ||
671 | struct uac_selector_unit_descriptor *d = p1; | 680 | struct uac_selector_unit_descriptor *d = p1; |
672 | /* call recursively to retrieve the channel info */ | 681 | /* call recursively to retrieve the channel info */ |
673 | if (check_input_term(state, d->baSourceID[0], term) < 0) | 682 | if (check_input_term(state, d->baSourceID[0], term) < 0) |
@@ -677,8 +686,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ | |||
677 | term->name = uac_selector_unit_iSelector(d); | 686 | term->name = uac_selector_unit_iSelector(d); |
678 | return 0; | 687 | return 0; |
679 | } | 688 | } |
680 | case UAC_PROCESSING_UNIT_V1: | 689 | case UAC1_PROCESSING_UNIT: |
681 | case UAC_EXTENSION_UNIT_V1: { | 690 | case UAC1_EXTENSION_UNIT: { |
682 | struct uac_processing_unit_descriptor *d = p1; | 691 | struct uac_processing_unit_descriptor *d = p1; |
683 | if (d->bNrInPins) { | 692 | if (d->bNrInPins) { |
684 | id = d->baSourceID[0]; | 693 | id = d->baSourceID[0]; |
@@ -690,6 +699,13 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ | |||
690 | term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol); | 699 | term->name = uac_processing_unit_iProcessing(d, state->mixer->protocol); |
691 | return 0; | 700 | return 0; |
692 | } | 701 | } |
702 | case UAC2_CLOCK_SOURCE: { | ||
703 | struct uac_clock_source_descriptor *d = p1; | ||
704 | term->type = d->bDescriptorSubtype << 16; /* virtual type */ | ||
705 | term->id = id; | ||
706 | term->name = d->iClockSource; | ||
707 | return 0; | ||
708 | } | ||
693 | default: | 709 | default: |
694 | return -ENODEV; | 710 | return -ENODEV; |
695 | } | 711 | } |
@@ -709,16 +725,20 @@ struct usb_feature_control_info { | |||
709 | }; | 725 | }; |
710 | 726 | ||
711 | static struct usb_feature_control_info audio_feature_info[] = { | 727 | static struct usb_feature_control_info audio_feature_info[] = { |
712 | { "Mute", USB_MIXER_INV_BOOLEAN }, | 728 | { "Mute", USB_MIXER_INV_BOOLEAN }, |
713 | { "Volume", USB_MIXER_S16 }, | 729 | { "Volume", USB_MIXER_S16 }, |
714 | { "Tone Control - Bass", USB_MIXER_S8 }, | 730 | { "Tone Control - Bass", USB_MIXER_S8 }, |
715 | { "Tone Control - Mid", USB_MIXER_S8 }, | 731 | { "Tone Control - Mid", USB_MIXER_S8 }, |
716 | { "Tone Control - Treble", USB_MIXER_S8 }, | 732 | { "Tone Control - Treble", USB_MIXER_S8 }, |
717 | { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ | 733 | { "Graphic Equalizer", USB_MIXER_S8 }, /* FIXME: not implemeted yet */ |
718 | { "Auto Gain Control", USB_MIXER_BOOLEAN }, | 734 | { "Auto Gain Control", USB_MIXER_BOOLEAN }, |
719 | { "Delay Control", USB_MIXER_U16 }, | 735 | { "Delay Control", USB_MIXER_U16 }, |
720 | { "Bass Boost", USB_MIXER_BOOLEAN }, | 736 | { "Bass Boost", USB_MIXER_BOOLEAN }, |
721 | { "Loudness", USB_MIXER_BOOLEAN }, | 737 | { "Loudness", USB_MIXER_BOOLEAN }, |
738 | /* UAC2 specific */ | ||
739 | { "Input Gain Control", USB_MIXER_U16 }, | ||
740 | { "Input Gain Pad Control", USB_MIXER_BOOLEAN }, | ||
741 | { "Phase Inverter Control", USB_MIXER_BOOLEAN }, | ||
722 | }; | 742 | }; |
723 | 743 | ||
724 | 744 | ||
@@ -739,6 +759,8 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | |||
739 | */ | 759 | */ |
740 | static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | 760 | static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) |
741 | { | 761 | { |
762 | struct snd_usb_audio *chip = cval->mixer->chip; | ||
763 | |||
742 | /* for failsafe */ | 764 | /* for failsafe */ |
743 | cval->min = default_min; | 765 | cval->min = default_min; |
744 | cval->max = cval->min + 1; | 766 | cval->max = cval->min + 1; |
@@ -761,7 +783,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
761 | 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 || |
762 | 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) { |
763 | 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", |
764 | cval->id, cval->mixer->ctrlif, cval->control, cval->id); | 786 | cval->id, snd_usb_ctrl_intf(chip), cval->control, cval->id); |
765 | return -EINVAL; | 787 | return -EINVAL; |
766 | } | 788 | } |
767 | 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) { |
@@ -958,7 +980,7 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) | |||
958 | static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | 980 | static void build_feature_ctl(struct mixer_build *state, void *raw_desc, |
959 | unsigned int ctl_mask, int control, | 981 | unsigned int ctl_mask, int control, |
960 | struct usb_audio_term *iterm, int unitid, | 982 | struct usb_audio_term *iterm, int unitid, |
961 | int read_only) | 983 | int readonly_mask) |
962 | { | 984 | { |
963 | struct uac_feature_unit_descriptor *desc = raw_desc; | 985 | struct uac_feature_unit_descriptor *desc = raw_desc; |
964 | unsigned int len = 0; | 986 | unsigned int len = 0; |
@@ -970,7 +992,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
970 | 992 | ||
971 | control++; /* change from zero-based to 1-based value */ | 993 | control++; /* change from zero-based to 1-based value */ |
972 | 994 | ||
973 | if (control == UAC_GRAPHIC_EQUALIZER_CONTROL) { | 995 | if (control == UAC_FU_GRAPHIC_EQUALIZER) { |
974 | /* FIXME: not supported yet */ | 996 | /* FIXME: not supported yet */ |
975 | return; | 997 | return; |
976 | } | 998 | } |
@@ -989,20 +1011,25 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
989 | cval->control = control; | 1011 | cval->control = control; |
990 | cval->cmask = ctl_mask; | 1012 | cval->cmask = ctl_mask; |
991 | cval->val_type = audio_feature_info[control-1].type; | 1013 | cval->val_type = audio_feature_info[control-1].type; |
992 | if (ctl_mask == 0) | 1014 | if (ctl_mask == 0) { |
993 | cval->channels = 1; /* master channel */ | 1015 | cval->channels = 1; /* master channel */ |
994 | else { | 1016 | cval->master_readonly = readonly_mask; |
1017 | } else { | ||
995 | int i, c = 0; | 1018 | int i, c = 0; |
996 | for (i = 0; i < 16; i++) | 1019 | for (i = 0; i < 16; i++) |
997 | if (ctl_mask & (1 << i)) | 1020 | if (ctl_mask & (1 << i)) |
998 | c++; | 1021 | c++; |
999 | cval->channels = c; | 1022 | cval->channels = c; |
1023 | cval->ch_readonly = readonly_mask; | ||
1000 | } | 1024 | } |
1001 | 1025 | ||
1002 | /* get min/max values */ | 1026 | /* get min/max values */ |
1003 | get_min_max(cval, 0); | 1027 | get_min_max(cval, 0); |
1004 | 1028 | ||
1005 | if (read_only) | 1029 | /* if all channels in the mask are marked read-only, make the control |
1030 | * read-only. set_cur_mix_value() will check the mask again and won't | ||
1031 | * issue write commands to read-only channels. */ | ||
1032 | if (cval->channels == readonly_mask) | ||
1006 | kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); | 1033 | kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval); |
1007 | else | 1034 | else |
1008 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); | 1035 | kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval); |
@@ -1021,8 +1048,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1021 | kctl->id.name, sizeof(kctl->id.name)); | 1048 | kctl->id.name, sizeof(kctl->id.name)); |
1022 | 1049 | ||
1023 | switch (control) { | 1050 | switch (control) { |
1024 | case UAC_MUTE_CONTROL: | 1051 | case UAC_FU_MUTE: |
1025 | case UAC_VOLUME_CONTROL: | 1052 | case UAC_FU_VOLUME: |
1026 | /* determine the control name. the rule is: | 1053 | /* determine the control name. the rule is: |
1027 | * - if a name id is given in descriptor, use it. | 1054 | * - if a name id is given in descriptor, use it. |
1028 | * - if the connected input can be determined, then use the name | 1055 | * - if the connected input can be determined, then use the name |
@@ -1049,9 +1076,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1049 | len = append_ctl_name(kctl, " Playback"); | 1076 | len = append_ctl_name(kctl, " Playback"); |
1050 | } | 1077 | } |
1051 | } | 1078 | } |
1052 | append_ctl_name(kctl, control == UAC_MUTE_CONTROL ? | 1079 | append_ctl_name(kctl, control == UAC_FU_MUTE ? |
1053 | " Switch" : " Volume"); | 1080 | " Switch" : " Volume"); |
1054 | if (control == UAC_VOLUME_CONTROL) { | 1081 | if (control == UAC_FU_VOLUME) { |
1055 | kctl->tlv.c = mixer_vol_tlv; | 1082 | kctl->tlv.c = mixer_vol_tlv; |
1056 | kctl->vd[0].access |= | 1083 | kctl->vd[0].access |= |
1057 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 1084 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
@@ -1096,6 +1123,19 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1096 | } | 1123 | } |
1097 | break; | 1124 | break; |
1098 | 1125 | ||
1126 | case USB_ID(0x046d, 0x0809): | ||
1127 | case USB_ID(0x046d, 0x0991): | ||
1128 | /* Most audio usb devices lie about volume resolution. | ||
1129 | * Most Logitech webcams have res = 384. | ||
1130 | * Proboly there is some logitech magic behind this number --fishor | ||
1131 | */ | ||
1132 | if (!strcmp(kctl->id.name, "Mic Capture Volume")) { | ||
1133 | snd_printk(KERN_INFO | ||
1134 | "set resolution quirk: cval->res = 384\n"); | ||
1135 | cval->res = 384; | ||
1136 | } | ||
1137 | break; | ||
1138 | |||
1099 | } | 1139 | } |
1100 | 1140 | ||
1101 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 1141 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
@@ -1150,7 +1190,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
1150 | snd_printk(KERN_INFO | 1190 | snd_printk(KERN_INFO |
1151 | "usbmixer: master volume quirk for PCM2702 chip\n"); | 1191 | "usbmixer: master volume quirk for PCM2702 chip\n"); |
1152 | /* disable non-functional volume control */ | 1192 | /* disable non-functional volume control */ |
1153 | master_bits &= ~UAC_FU_VOLUME; | 1193 | master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); |
1154 | break; | 1194 | break; |
1155 | } | 1195 | } |
1156 | if (channels > 0) | 1196 | if (channels > 0) |
@@ -1175,32 +1215,27 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
1175 | } | 1215 | } |
1176 | } else { /* UAC_VERSION_2 */ | 1216 | } else { /* UAC_VERSION_2 */ |
1177 | for (i = 0; i < 30/2; i++) { | 1217 | for (i = 0; i < 30/2; i++) { |
1178 | /* From the USB Audio spec v2.0: | ||
1179 | bmaControls() is a (ch+1)-element array of 4-byte bitmaps, | ||
1180 | each containing a set of bit pairs. If a Control is present, | ||
1181 | it must be Host readable. If a certain Control is not | ||
1182 | present then the bit pair must be set to 0b00. | ||
1183 | If a Control is present but read-only, the bit pair must be | ||
1184 | set to 0b01. If a Control is also Host programmable, the bit | ||
1185 | pair must be set to 0b11. The value 0b10 is not allowed. */ | ||
1186 | unsigned int ch_bits = 0; | 1218 | unsigned int ch_bits = 0; |
1187 | unsigned int ch_read_only = 0; | 1219 | unsigned int ch_read_only = 0; |
1188 | 1220 | ||
1189 | for (j = 0; j < channels; j++) { | 1221 | for (j = 0; j < channels; j++) { |
1190 | unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); | 1222 | unsigned int mask = snd_usb_combine_bytes(bmaControls + csize * (j+1), csize); |
1191 | if (mask & (1 << (i * 2))) { | 1223 | if (uac2_control_is_readable(mask, i)) { |
1192 | ch_bits |= (1 << j); | 1224 | ch_bits |= (1 << j); |
1193 | if (~mask & (1 << ((i * 2) + 1))) | 1225 | if (!uac2_control_is_writeable(mask, i)) |
1194 | ch_read_only |= (1 << j); | 1226 | ch_read_only |= (1 << j); |
1195 | } | 1227 | } |
1196 | } | 1228 | } |
1197 | 1229 | ||
1198 | /* FIXME: the whole unit is read-only if any of the channels is marked read-only */ | 1230 | /* NOTE: build_feature_ctl() will mark the control read-only if all channels |
1231 | * are marked read-only in the descriptors. Otherwise, the control will be | ||
1232 | * reported as writeable, but the driver will not actually issue a write | ||
1233 | * command for read-only channels */ | ||
1199 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ | 1234 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ |
1200 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, !!ch_read_only); | 1235 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid, ch_read_only); |
1201 | if (master_bits & (1 << i * 2)) | 1236 | if (uac2_control_is_readable(master_bits, i)) |
1202 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, | 1237 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, |
1203 | ~master_bits & (1 << ((i * 2) + 1))); | 1238 | !uac2_control_is_writeable(master_bits, i)); |
1204 | } | 1239 | } |
1205 | } | 1240 | } |
1206 | 1241 | ||
@@ -1392,51 +1427,51 @@ struct procunit_info { | |||
1392 | }; | 1427 | }; |
1393 | 1428 | ||
1394 | static struct procunit_value_info updown_proc_info[] = { | 1429 | static struct procunit_value_info updown_proc_info[] = { |
1395 | { USB_PROC_UPDOWN_SWITCH, "Switch", USB_MIXER_BOOLEAN }, | 1430 | { UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1396 | { USB_PROC_UPDOWN_MODE_SEL, "Mode Select", USB_MIXER_U8, 1 }, | 1431 | { UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, |
1397 | { 0 } | 1432 | { 0 } |
1398 | }; | 1433 | }; |
1399 | static struct procunit_value_info prologic_proc_info[] = { | 1434 | static struct procunit_value_info prologic_proc_info[] = { |
1400 | { USB_PROC_PROLOGIC_SWITCH, "Switch", USB_MIXER_BOOLEAN }, | 1435 | { UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1401 | { USB_PROC_PROLOGIC_MODE_SEL, "Mode Select", USB_MIXER_U8, 1 }, | 1436 | { UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 }, |
1402 | { 0 } | 1437 | { 0 } |
1403 | }; | 1438 | }; |
1404 | static struct procunit_value_info threed_enh_proc_info[] = { | 1439 | static struct procunit_value_info threed_enh_proc_info[] = { |
1405 | { USB_PROC_3DENH_SWITCH, "Switch", USB_MIXER_BOOLEAN }, | 1440 | { UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1406 | { USB_PROC_3DENH_SPACE, "Spaciousness", USB_MIXER_U8 }, | 1441 | { UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 }, |
1407 | { 0 } | 1442 | { 0 } |
1408 | }; | 1443 | }; |
1409 | static struct procunit_value_info reverb_proc_info[] = { | 1444 | static struct procunit_value_info reverb_proc_info[] = { |
1410 | { USB_PROC_REVERB_SWITCH, "Switch", USB_MIXER_BOOLEAN }, | 1445 | { UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1411 | { USB_PROC_REVERB_LEVEL, "Level", USB_MIXER_U8 }, | 1446 | { UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 }, |
1412 | { USB_PROC_REVERB_TIME, "Time", USB_MIXER_U16 }, | 1447 | { UAC_REVERB_TIME, "Time", USB_MIXER_U16 }, |
1413 | { USB_PROC_REVERB_DELAY, "Delay", USB_MIXER_U8 }, | 1448 | { UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 }, |
1414 | { 0 } | 1449 | { 0 } |
1415 | }; | 1450 | }; |
1416 | static struct procunit_value_info chorus_proc_info[] = { | 1451 | static struct procunit_value_info chorus_proc_info[] = { |
1417 | { USB_PROC_CHORUS_SWITCH, "Switch", USB_MIXER_BOOLEAN }, | 1452 | { UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1418 | { USB_PROC_CHORUS_LEVEL, "Level", USB_MIXER_U8 }, | 1453 | { UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 }, |
1419 | { USB_PROC_CHORUS_RATE, "Rate", USB_MIXER_U16 }, | 1454 | { UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 }, |
1420 | { USB_PROC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 }, | 1455 | { UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 }, |
1421 | { 0 } | 1456 | { 0 } |
1422 | }; | 1457 | }; |
1423 | static struct procunit_value_info dcr_proc_info[] = { | 1458 | static struct procunit_value_info dcr_proc_info[] = { |
1424 | { USB_PROC_DCR_SWITCH, "Switch", USB_MIXER_BOOLEAN }, | 1459 | { UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN }, |
1425 | { USB_PROC_DCR_RATIO, "Ratio", USB_MIXER_U16 }, | 1460 | { UAC_DCR_RATE, "Ratio", USB_MIXER_U16 }, |
1426 | { USB_PROC_DCR_MAX_AMP, "Max Amp", USB_MIXER_S16 }, | 1461 | { UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 }, |
1427 | { USB_PROC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 }, | 1462 | { UAC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 }, |
1428 | { USB_PROC_DCR_ATTACK, "Attack Time", USB_MIXER_U16 }, | 1463 | { UAC_DCR_ATTACK_TIME, "Attack Time", USB_MIXER_U16 }, |
1429 | { USB_PROC_DCR_RELEASE, "Release Time", USB_MIXER_U16 }, | 1464 | { UAC_DCR_RELEASE_TIME, "Release Time", USB_MIXER_U16 }, |
1430 | { 0 } | 1465 | { 0 } |
1431 | }; | 1466 | }; |
1432 | 1467 | ||
1433 | static struct procunit_info procunits[] = { | 1468 | static struct procunit_info procunits[] = { |
1434 | { USB_PROC_UPDOWN, "Up Down", updown_proc_info }, | 1469 | { UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info }, |
1435 | { USB_PROC_PROLOGIC, "Dolby Prologic", prologic_proc_info }, | 1470 | { UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info }, |
1436 | { USB_PROC_3DENH, "3D Stereo Extender", threed_enh_proc_info }, | 1471 | { UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info }, |
1437 | { USB_PROC_REVERB, "Reverb", reverb_proc_info }, | 1472 | { UAC_PROCESS_REVERB, "Reverb", reverb_proc_info }, |
1438 | { USB_PROC_CHORUS, "Chorus", chorus_proc_info }, | 1473 | { UAC_PROCESS_CHORUS, "Chorus", chorus_proc_info }, |
1439 | { USB_PROC_DCR, "DCR", dcr_proc_info }, | 1474 | { UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info }, |
1440 | { 0 }, | 1475 | { 0 }, |
1441 | }; | 1476 | }; |
1442 | /* | 1477 | /* |
@@ -1524,7 +1559,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw | |||
1524 | cval->channels = 1; | 1559 | cval->channels = 1; |
1525 | 1560 | ||
1526 | /* get min/max values */ | 1561 | /* get min/max values */ |
1527 | if (type == USB_PROC_UPDOWN && cval->control == USB_PROC_UPDOWN_MODE_SEL) { | 1562 | if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) { |
1528 | __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol); | 1563 | __u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol); |
1529 | /* FIXME: hard-coded */ | 1564 | /* FIXME: hard-coded */ |
1530 | cval->min = 1; | 1565 | cval->min = 1; |
@@ -1619,7 +1654,7 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1619 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1654 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1620 | int val, err; | 1655 | int val, err; |
1621 | 1656 | ||
1622 | err = get_cur_ctl_value(cval, 0, &val); | 1657 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1623 | if (err < 0) { | 1658 | if (err < 0) { |
1624 | if (cval->mixer->ignore_ctl_error) { | 1659 | if (cval->mixer->ignore_ctl_error) { |
1625 | ucontrol->value.enumerated.item[0] = 0; | 1660 | ucontrol->value.enumerated.item[0] = 0; |
@@ -1638,7 +1673,7 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1638 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1673 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1639 | int val, oval, err; | 1674 | int val, oval, err; |
1640 | 1675 | ||
1641 | err = get_cur_ctl_value(cval, 0, &oval); | 1676 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1642 | if (err < 0) { | 1677 | if (err < 0) { |
1643 | if (cval->mixer->ignore_ctl_error) | 1678 | if (cval->mixer->ignore_ctl_error) |
1644 | return 0; | 1679 | return 0; |
@@ -1647,7 +1682,7 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1647 | val = ucontrol->value.enumerated.item[0]; | 1682 | val = ucontrol->value.enumerated.item[0]; |
1648 | val = get_abs_value(cval, val); | 1683 | val = get_abs_value(cval, val); |
1649 | if (val != oval) { | 1684 | if (val != oval) { |
1650 | set_cur_ctl_value(cval, 0, val); | 1685 | set_cur_ctl_value(cval, cval->control << 8, val); |
1651 | return 1; | 1686 | return 1; |
1652 | } | 1687 | } |
1653 | return 0; | 1688 | return 0; |
@@ -1729,6 +1764,11 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
1729 | cval->res = 1; | 1764 | cval->res = 1; |
1730 | cval->initialized = 1; | 1765 | cval->initialized = 1; |
1731 | 1766 | ||
1767 | if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) | ||
1768 | cval->control = UAC2_CX_CLOCK_SELECTOR; | ||
1769 | else | ||
1770 | cval->control = 0; | ||
1771 | |||
1732 | namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); | 1772 | namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL); |
1733 | if (! namelist) { | 1773 | if (! namelist) { |
1734 | snd_printk(KERN_ERR "cannot malloc\n"); | 1774 | snd_printk(KERN_ERR "cannot malloc\n"); |
@@ -1778,7 +1818,9 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
1778 | if (! len) | 1818 | if (! len) |
1779 | strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); | 1819 | strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); |
1780 | 1820 | ||
1781 | if ((state->oterm.type & 0xff00) == 0x0100) | 1821 | if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) |
1822 | append_ctl_name(kctl, " Clock Source"); | ||
1823 | else if ((state->oterm.type & 0xff00) == 0x0100) | ||
1782 | append_ctl_name(kctl, " Capture Source"); | 1824 | append_ctl_name(kctl, " Capture Source"); |
1783 | else | 1825 | else |
1784 | append_ctl_name(kctl, " Playback Source"); | 1826 | append_ctl_name(kctl, " Playback Source"); |
@@ -1812,20 +1854,22 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) | |||
1812 | 1854 | ||
1813 | switch (p1[2]) { | 1855 | switch (p1[2]) { |
1814 | case UAC_INPUT_TERMINAL: | 1856 | case UAC_INPUT_TERMINAL: |
1857 | case UAC2_CLOCK_SOURCE: | ||
1815 | return 0; /* NOP */ | 1858 | return 0; /* NOP */ |
1816 | case UAC_MIXER_UNIT: | 1859 | case UAC_MIXER_UNIT: |
1817 | return parse_audio_mixer_unit(state, unitid, p1); | 1860 | return parse_audio_mixer_unit(state, unitid, p1); |
1818 | case UAC_SELECTOR_UNIT: | 1861 | case UAC_SELECTOR_UNIT: |
1862 | case UAC2_CLOCK_SELECTOR: | ||
1819 | return parse_audio_selector_unit(state, unitid, p1); | 1863 | return parse_audio_selector_unit(state, unitid, p1); |
1820 | case UAC_FEATURE_UNIT: | 1864 | case UAC_FEATURE_UNIT: |
1821 | return parse_audio_feature_unit(state, unitid, p1); | 1865 | return parse_audio_feature_unit(state, unitid, p1); |
1822 | case UAC_PROCESSING_UNIT_V1: | 1866 | case UAC1_PROCESSING_UNIT: |
1823 | /* UAC2_EFFECT_UNIT has the same value */ | 1867 | /* UAC2_EFFECT_UNIT has the same value */ |
1824 | if (state->mixer->protocol == UAC_VERSION_1) | 1868 | if (state->mixer->protocol == UAC_VERSION_1) |
1825 | return parse_audio_processing_unit(state, unitid, p1); | 1869 | return parse_audio_processing_unit(state, unitid, p1); |
1826 | else | 1870 | else |
1827 | return 0; /* FIXME - effect units not implemented yet */ | 1871 | return 0; /* FIXME - effect units not implemented yet */ |
1828 | case UAC_EXTENSION_UNIT_V1: | 1872 | case UAC1_EXTENSION_UNIT: |
1829 | /* UAC2_PROCESSING_UNIT_V2 has the same value */ | 1873 | /* UAC2_PROCESSING_UNIT_V2 has the same value */ |
1830 | if (state->mixer->protocol == UAC_VERSION_1) | 1874 | if (state->mixer->protocol == UAC_VERSION_1) |
1831 | return parse_audio_extension_unit(state, unitid, p1); | 1875 | return parse_audio_extension_unit(state, unitid, p1); |
@@ -1869,7 +1913,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
1869 | struct usb_host_interface *hostif; | 1913 | struct usb_host_interface *hostif; |
1870 | void *p; | 1914 | void *p; |
1871 | 1915 | ||
1872 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | 1916 | hostif = mixer->chip->ctrl_intf; |
1873 | memset(&state, 0, sizeof(state)); | 1917 | memset(&state, 0, sizeof(state)); |
1874 | state.chip = mixer->chip; | 1918 | state.chip = mixer->chip; |
1875 | state.mixer = mixer; | 1919 | state.mixer = mixer; |
@@ -1889,7 +1933,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
1889 | p = NULL; | 1933 | p = NULL; |
1890 | 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) { |
1891 | if (mixer->protocol == UAC_VERSION_1) { | 1935 | if (mixer->protocol == UAC_VERSION_1) { |
1892 | struct uac_output_terminal_descriptor_v1 *desc = p; | 1936 | struct uac1_output_terminal_descriptor *desc = p; |
1893 | 1937 | ||
1894 | if (desc->bLength < sizeof(*desc)) | 1938 | if (desc->bLength < sizeof(*desc)) |
1895 | continue; /* invalid descriptor? */ | 1939 | continue; /* invalid descriptor? */ |
@@ -1912,6 +1956,11 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
1912 | err = parse_audio_unit(&state, desc->bSourceID); | 1956 | err = parse_audio_unit(&state, desc->bSourceID); |
1913 | if (err < 0) | 1957 | if (err < 0) |
1914 | return err; | 1958 | return err; |
1959 | |||
1960 | /* for UAC2, use the same approach to also add the clock selectors */ | ||
1961 | err = parse_audio_unit(&state, desc->bCSourceID); | ||
1962 | if (err < 0) | ||
1963 | return err; | ||
1915 | } | 1964 | } |
1916 | } | 1965 | } |
1917 | 1966 | ||
@@ -1956,7 +2005,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, | |||
1956 | list_for_each_entry(mixer, &chip->mixer_list, list) { | 2005 | list_for_each_entry(mixer, &chip->mixer_list, list) { |
1957 | snd_iprintf(buffer, | 2006 | snd_iprintf(buffer, |
1958 | "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n", | 2007 | "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n", |
1959 | chip->usb_id, mixer->ctrlif, | 2008 | chip->usb_id, snd_usb_ctrl_intf(chip), |
1960 | mixer->ignore_ctl_error); | 2009 | mixer->ignore_ctl_error); |
1961 | snd_iprintf(buffer, "Card: %s\n", chip->card->longname); | 2010 | snd_iprintf(buffer, "Card: %s\n", chip->card->longname); |
1962 | for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { | 2011 | for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { |
@@ -2074,7 +2123,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | |||
2074 | int buffer_length; | 2123 | int buffer_length; |
2075 | unsigned int epnum; | 2124 | unsigned int epnum; |
2076 | 2125 | ||
2077 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | 2126 | hostif = mixer->chip->ctrl_intf; |
2078 | /* we need one interrupt input endpoint */ | 2127 | /* we need one interrupt input endpoint */ |
2079 | if (get_iface_desc(hostif)->bNumEndpoints < 1) | 2128 | if (get_iface_desc(hostif)->bNumEndpoints < 1) |
2080 | return 0; | 2129 | return 0; |
@@ -2117,7 +2166,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
2117 | if (!mixer) | 2166 | if (!mixer) |
2118 | return -ENOMEM; | 2167 | return -ENOMEM; |
2119 | mixer->chip = chip; | 2168 | mixer->chip = chip; |
2120 | mixer->ctrlif = ctrlif; | ||
2121 | mixer->ignore_ctl_error = ignore_error; | 2169 | mixer->ignore_ctl_error = ignore_error; |
2122 | mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems), | 2170 | mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems), |
2123 | GFP_KERNEL); | 2171 | GFP_KERNEL); |
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 130123854a6c..26c636c5c93a 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h | |||
@@ -3,7 +3,6 @@ | |||
3 | 3 | ||
4 | struct usb_mixer_interface { | 4 | struct 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; |
@@ -34,6 +33,8 @@ struct usb_mixer_elem_info { | |||
34 | unsigned int id; | 33 | unsigned int id; |
35 | unsigned int control; /* CS or ICN (high byte) */ | 34 | unsigned int control; /* CS or ICN (high byte) */ |
36 | unsigned int cmask; /* channel mask bitmap: 0 = master */ | 35 | unsigned int cmask; /* channel mask bitmap: 0 = master */ |
36 | unsigned int ch_readonly; | ||
37 | unsigned int master_readonly; | ||
37 | int channels; | 38 | int channels; |
38 | int val_type; | 39 | int val_type; |
39 | int min, max, res; | 40 | int min, max, res; |
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index d93fc89beba8..f1324c423835 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c | |||
@@ -85,8 +85,8 @@ static struct usbmix_name_map extigy_map[] = { | |||
85 | /* 16: MU (w/o controls) */ | 85 | /* 16: MU (w/o controls) */ |
86 | { 17, NULL, 1 }, /* DISABLED: PU-switch (any effect?) */ | 86 | { 17, NULL, 1 }, /* DISABLED: PU-switch (any effect?) */ |
87 | { 17, "Channel Routing", 2 }, /* PU: mode select */ | 87 | { 17, "Channel Routing", 2 }, /* PU: mode select */ |
88 | { 18, "Tone Control - Bass", UAC_BASS_CONTROL }, /* FU */ | 88 | { 18, "Tone Control - Bass", UAC_FU_BASS }, /* FU */ |
89 | { 18, "Tone Control - Treble", UAC_TREBLE_CONTROL }, /* FU */ | 89 | { 18, "Tone Control - Treble", UAC_FU_TREBLE }, /* FU */ |
90 | { 18, "Master Playback" }, /* FU; others */ | 90 | { 18, "Master Playback" }, /* FU; others */ |
91 | /* 19: OT speaker */ | 91 | /* 19: OT speaker */ |
92 | /* 20: OT headphone */ | 92 | /* 20: OT headphone */ |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 056587de7be4..456829882f40 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "urb.h" | 31 | #include "urb.h" |
32 | #include "helper.h" | 32 | #include "helper.h" |
33 | #include "pcm.h" | 33 | #include "pcm.h" |
34 | #include "clock.h" | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * return the current pcm pointer. just based on the hwptr_done value. | 37 | * return the current pcm pointer. just based on the hwptr_done value. |
@@ -181,103 +182,6 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, | |||
181 | return -EINVAL; | 182 | return -EINVAL; |
182 | } | 183 | } |
183 | 184 | ||
184 | static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, | ||
185 | struct usb_host_interface *alts, | ||
186 | struct audioformat *fmt, int rate) | ||
187 | { | ||
188 | struct usb_device *dev = chip->dev; | ||
189 | unsigned int ep; | ||
190 | unsigned char data[3]; | ||
191 | int err, crate; | ||
192 | |||
193 | ep = get_endpoint(alts, 0)->bEndpointAddress; | ||
194 | /* if endpoint doesn't have sampling rate control, bail out */ | ||
195 | if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) { | ||
196 | snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n", | ||
197 | dev->devnum, iface, fmt->altsetting); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | data[0] = rate; | ||
202 | data[1] = rate >> 8; | ||
203 | data[2] = rate >> 16; | ||
204 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, | ||
205 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, | ||
206 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, | ||
207 | data, sizeof(data), 1000)) < 0) { | ||
208 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n", | ||
209 | dev->devnum, iface, fmt->altsetting, rate, ep); | ||
210 | return err; | ||
211 | } | ||
212 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, | ||
213 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, | ||
214 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, | ||
215 | data, sizeof(data), 1000)) < 0) { | ||
216 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n", | ||
217 | dev->devnum, iface, fmt->altsetting, ep); | ||
218 | return 0; /* some devices don't support reading */ | ||
219 | } | ||
220 | crate = data[0] | (data[1] << 8) | (data[2] << 16); | ||
221 | if (crate != rate) { | ||
222 | snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); | ||
223 | // runtime->rate = crate; | ||
224 | } | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, | ||
230 | struct usb_host_interface *alts, | ||
231 | struct audioformat *fmt, int rate) | ||
232 | { | ||
233 | struct usb_device *dev = chip->dev; | ||
234 | unsigned char data[4]; | ||
235 | int err, crate; | ||
236 | |||
237 | data[0] = rate; | ||
238 | data[1] = rate >> 8; | ||
239 | data[2] = rate >> 16; | ||
240 | data[3] = rate >> 24; | ||
241 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, | ||
242 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
243 | UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, | ||
244 | data, sizeof(data), 1000)) < 0) { | ||
245 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n", | ||
246 | dev->devnum, iface, fmt->altsetting, rate); | ||
247 | return err; | ||
248 | } | ||
249 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, | ||
250 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
251 | UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, | ||
252 | data, sizeof(data), 1000)) < 0) { | ||
253 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n", | ||
254 | dev->devnum, iface, fmt->altsetting); | ||
255 | return err; | ||
256 | } | ||
257 | crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); | ||
258 | if (crate != rate) | ||
259 | snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, | ||
265 | struct usb_host_interface *alts, | ||
266 | struct audioformat *fmt, int rate) | ||
267 | { | ||
268 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); | ||
269 | |||
270 | switch (altsd->bInterfaceProtocol) { | ||
271 | case UAC_VERSION_1: | ||
272 | return set_sample_rate_v1(chip, iface, alts, fmt, rate); | ||
273 | |||
274 | case UAC_VERSION_2: | ||
275 | return set_sample_rate_v2(chip, iface, alts, fmt, rate); | ||
276 | } | ||
277 | |||
278 | return -EINVAL; | ||
279 | } | ||
280 | |||
281 | /* | 185 | /* |
282 | * find a matching format and set up the interface | 186 | * find a matching format and set up the interface |
283 | */ | 187 | */ |
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 | ||
10 | int 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 |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 06ebf24d3a4d..24d3319cc34d 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -40,9 +40,6 @@ struct snd_usb_audio { | |||
40 | int num_interfaces; | 40 | int num_interfaces; |
41 | int num_suspended_intf; | 41 | int num_suspended_intf; |
42 | 42 | ||
43 | /* for audio class v2 */ | ||
44 | int clock_id; | ||
45 | |||
46 | struct list_head pcm_list; /* list of pcm streams */ | 43 | struct list_head pcm_list; /* list of pcm streams */ |
47 | int pcm_devs; | 44 | int pcm_devs; |
48 | 45 | ||
@@ -53,6 +50,8 @@ struct snd_usb_audio { | |||
53 | int setup; /* from the 'device_setup' module param */ | 50 | int setup; /* from the 'device_setup' module param */ |
54 | int nrpacks; /* from the 'nrpacks' module param */ | 51 | int nrpacks; /* from the 'nrpacks' module param */ |
55 | int async_unlink; /* from the 'async_unlink' module param */ | 52 | int async_unlink; /* from the 'async_unlink' module param */ |
53 | |||
54 | struct usb_host_interface *ctrl_intf; /* the audio control interface */ | ||
56 | }; | 55 | }; |
57 | 56 | ||
58 | /* | 57 | /* |