diff options
Diffstat (limited to 'sound/pci')
68 files changed, 3067 insertions, 1037 deletions
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 3020ca2b602b..278319bbdea1 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
31 | #include <linux/mutex.h> | ||
31 | #include <sound/core.h> | 32 | #include <sound/core.h> |
32 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
33 | #include <sound/ac97_codec.h> | 34 | #include <sound/ac97_codec.h> |
@@ -149,7 +150,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
149 | { 0x49544561, 0xffffffff, "IT2646E", patch_it2646, NULL }, | 150 | { 0x49544561, 0xffffffff, "IT2646E", patch_it2646, NULL }, |
150 | { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk | 151 | { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk |
151 | { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, | 152 | { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, |
152 | { 0x4e534350, 0xffffffff, "LM4550", NULL, NULL }, | 153 | { 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume wrap fix |
153 | { 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, | 154 | { 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, |
154 | { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, | 155 | { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, |
155 | { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, | 156 | { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, |
@@ -191,9 +192,6 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
191 | 192 | ||
192 | static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg) | 193 | static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg) |
193 | { | 194 | { |
194 | if (ac97->limited_regs && ! test_bit(reg, ac97->reg_accessed)) | ||
195 | return 0; | ||
196 | |||
197 | /* filter some registers for buggy codecs */ | 195 | /* filter some registers for buggy codecs */ |
198 | switch (ac97->id) { | 196 | switch (ac97->id) { |
199 | case AC97_ID_AK4540: | 197 | case AC97_ID_AK4540: |
@@ -296,11 +294,11 @@ void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned sh | |||
296 | { | 294 | { |
297 | if (!snd_ac97_valid_reg(ac97, reg)) | 295 | if (!snd_ac97_valid_reg(ac97, reg)) |
298 | return; | 296 | return; |
299 | down(&ac97->reg_mutex); | 297 | mutex_lock(&ac97->reg_mutex); |
300 | ac97->regs[reg] = value; | 298 | ac97->regs[reg] = value; |
301 | ac97->bus->ops->write(ac97, reg, value); | 299 | ac97->bus->ops->write(ac97, reg, value); |
302 | set_bit(reg, ac97->reg_accessed); | 300 | set_bit(reg, ac97->reg_accessed); |
303 | up(&ac97->reg_mutex); | 301 | mutex_unlock(&ac97->reg_mutex); |
304 | } | 302 | } |
305 | 303 | ||
306 | /** | 304 | /** |
@@ -321,14 +319,14 @@ int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short va | |||
321 | 319 | ||
322 | if (!snd_ac97_valid_reg(ac97, reg)) | 320 | if (!snd_ac97_valid_reg(ac97, reg)) |
323 | return -EINVAL; | 321 | return -EINVAL; |
324 | down(&ac97->reg_mutex); | 322 | mutex_lock(&ac97->reg_mutex); |
325 | change = ac97->regs[reg] != value; | 323 | change = ac97->regs[reg] != value; |
326 | if (change) { | 324 | if (change) { |
327 | ac97->regs[reg] = value; | 325 | ac97->regs[reg] = value; |
328 | ac97->bus->ops->write(ac97, reg, value); | 326 | ac97->bus->ops->write(ac97, reg, value); |
329 | } | 327 | } |
330 | set_bit(reg, ac97->reg_accessed); | 328 | set_bit(reg, ac97->reg_accessed); |
331 | up(&ac97->reg_mutex); | 329 | mutex_unlock(&ac97->reg_mutex); |
332 | return change; | 330 | return change; |
333 | } | 331 | } |
334 | 332 | ||
@@ -351,9 +349,9 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho | |||
351 | 349 | ||
352 | if (!snd_ac97_valid_reg(ac97, reg)) | 350 | if (!snd_ac97_valid_reg(ac97, reg)) |
353 | return -EINVAL; | 351 | return -EINVAL; |
354 | down(&ac97->reg_mutex); | 352 | mutex_lock(&ac97->reg_mutex); |
355 | change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); | 353 | change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); |
356 | up(&ac97->reg_mutex); | 354 | mutex_unlock(&ac97->reg_mutex); |
357 | return change; | 355 | return change; |
358 | } | 356 | } |
359 | 357 | ||
@@ -380,12 +378,12 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns | |||
380 | int change; | 378 | int change; |
381 | unsigned short old, new, cfg; | 379 | unsigned short old, new, cfg; |
382 | 380 | ||
383 | down(&ac97->page_mutex); | 381 | mutex_lock(&ac97->page_mutex); |
384 | old = ac97->spec.ad18xx.pcmreg[codec]; | 382 | old = ac97->spec.ad18xx.pcmreg[codec]; |
385 | new = (old & ~mask) | value; | 383 | new = (old & ~mask) | value; |
386 | change = old != new; | 384 | change = old != new; |
387 | if (change) { | 385 | if (change) { |
388 | down(&ac97->reg_mutex); | 386 | mutex_lock(&ac97->reg_mutex); |
389 | cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); | 387 | cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); |
390 | ac97->spec.ad18xx.pcmreg[codec] = new; | 388 | ac97->spec.ad18xx.pcmreg[codec] = new; |
391 | /* select single codec */ | 389 | /* select single codec */ |
@@ -397,9 +395,9 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns | |||
397 | /* select all codecs */ | 395 | /* select all codecs */ |
398 | ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, | 396 | ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, |
399 | cfg | 0x7000); | 397 | cfg | 0x7000); |
400 | up(&ac97->reg_mutex); | 398 | mutex_unlock(&ac97->reg_mutex); |
401 | } | 399 | } |
402 | up(&ac97->page_mutex); | 400 | mutex_unlock(&ac97->page_mutex); |
403 | return change; | 401 | return change; |
404 | } | 402 | } |
405 | 403 | ||
@@ -467,7 +465,7 @@ static int snd_ac97_page_save(struct snd_ac97 *ac97, int reg, struct snd_kcontro | |||
467 | (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && | 465 | (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && |
468 | (reg >= 0x60 && reg < 0x70)) { | 466 | (reg >= 0x60 && reg < 0x70)) { |
469 | unsigned short page = (kcontrol->private_value >> 26) & 0x0f; | 467 | unsigned short page = (kcontrol->private_value >> 26) & 0x0f; |
470 | down(&ac97->page_mutex); /* lock paging */ | 468 | mutex_lock(&ac97->page_mutex); /* lock paging */ |
471 | page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; | 469 | page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; |
472 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); | 470 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); |
473 | } | 471 | } |
@@ -478,7 +476,7 @@ static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save) | |||
478 | { | 476 | { |
479 | if (page_save >= 0) { | 477 | if (page_save >= 0) { |
480 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); | 478 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); |
481 | up(&ac97->page_mutex); /* unlock paging */ | 479 | mutex_unlock(&ac97->page_mutex); /* unlock paging */ |
482 | } | 480 | } |
483 | } | 481 | } |
484 | 482 | ||
@@ -674,12 +672,12 @@ static int snd_ac97_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ | |||
674 | { | 672 | { |
675 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 673 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
676 | 674 | ||
677 | down(&ac97->reg_mutex); | 675 | mutex_lock(&ac97->reg_mutex); |
678 | ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff; | 676 | ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff; |
679 | ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff; | 677 | ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff; |
680 | ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff; | 678 | ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff; |
681 | ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff; | 679 | ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff; |
682 | up(&ac97->reg_mutex); | 680 | mutex_unlock(&ac97->reg_mutex); |
683 | return 0; | 681 | return 0; |
684 | } | 682 | } |
685 | 683 | ||
@@ -718,7 +716,7 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ | |||
718 | } | 716 | } |
719 | } | 717 | } |
720 | 718 | ||
721 | down(&ac97->reg_mutex); | 719 | mutex_lock(&ac97->reg_mutex); |
722 | change = ac97->spdif_status != new; | 720 | change = ac97->spdif_status != new; |
723 | ac97->spdif_status = new; | 721 | ac97->spdif_status = new; |
724 | 722 | ||
@@ -746,7 +744,7 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ | |||
746 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ | 744 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ |
747 | } | 745 | } |
748 | } | 746 | } |
749 | up(&ac97->reg_mutex); | 747 | mutex_unlock(&ac97->reg_mutex); |
750 | 748 | ||
751 | return change; | 749 | return change; |
752 | } | 750 | } |
@@ -763,7 +761,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
763 | 761 | ||
764 | value = (ucontrol->value.integer.value[0] & mask); | 762 | value = (ucontrol->value.integer.value[0] & mask); |
765 | 763 | ||
766 | down(&ac97->reg_mutex); | 764 | mutex_lock(&ac97->reg_mutex); |
767 | mask <<= shift; | 765 | mask <<= shift; |
768 | value <<= shift; | 766 | value <<= shift; |
769 | old = snd_ac97_read_cache(ac97, reg); | 767 | old = snd_ac97_read_cache(ac97, reg); |
@@ -777,7 +775,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
777 | if (extst & AC97_EA_SPDIF) | 775 | if (extst & AC97_EA_SPDIF) |
778 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ | 776 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ |
779 | } | 777 | } |
780 | up(&ac97->reg_mutex); | 778 | mutex_unlock(&ac97->reg_mutex); |
781 | return change; | 779 | return change; |
782 | } | 780 | } |
783 | 781 | ||
@@ -888,10 +886,10 @@ static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct | |||
888 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 886 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
889 | int codec = kcontrol->private_value & 3; | 887 | int codec = kcontrol->private_value & 3; |
890 | 888 | ||
891 | down(&ac97->page_mutex); | 889 | mutex_lock(&ac97->page_mutex); |
892 | ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); | 890 | ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); |
893 | ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); | 891 | ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); |
894 | up(&ac97->page_mutex); | 892 | mutex_unlock(&ac97->page_mutex); |
895 | return 0; | 893 | return 0; |
896 | } | 894 | } |
897 | 895 | ||
@@ -1007,9 +1005,6 @@ static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg) | |||
1007 | break; | 1005 | break; |
1008 | } | 1006 | } |
1009 | 1007 | ||
1010 | if (ac97->limited_regs && test_bit(reg, ac97->reg_accessed)) | ||
1011 | return 1; /* allow without check */ | ||
1012 | |||
1013 | val = snd_ac97_read(ac97, reg); | 1008 | val = snd_ac97_read(ac97, reg); |
1014 | if (!(val & mask)) { | 1009 | if (!(val & mask)) { |
1015 | /* nothing seems to be here - mute flag is not set */ | 1010 | /* nothing seems to be here - mute flag is not set */ |
@@ -1029,6 +1024,18 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha | |||
1029 | unsigned char max[3] = { 63, 31, 15 }; | 1024 | unsigned char max[3] = { 63, 31, 15 }; |
1030 | int i; | 1025 | int i; |
1031 | 1026 | ||
1027 | /* first look up the static resolution table */ | ||
1028 | if (ac97->res_table) { | ||
1029 | const struct snd_ac97_res_table *tbl; | ||
1030 | for (tbl = ac97->res_table; tbl->reg; tbl++) { | ||
1031 | if (tbl->reg == reg) { | ||
1032 | *lo_max = tbl->bits & 0xff; | ||
1033 | *hi_max = (tbl->bits >> 8) & 0xff; | ||
1034 | return; | ||
1035 | } | ||
1036 | } | ||
1037 | } | ||
1038 | |||
1032 | *lo_max = *hi_max = 0; | 1039 | *lo_max = *hi_max = 0; |
1033 | for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { | 1040 | for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { |
1034 | unsigned short val; | 1041 | unsigned short val; |
@@ -1853,11 +1860,10 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
1853 | ac97->num = template->num; | 1860 | ac97->num = template->num; |
1854 | ac97->addr = template->addr; | 1861 | ac97->addr = template->addr; |
1855 | ac97->scaps = template->scaps; | 1862 | ac97->scaps = template->scaps; |
1856 | ac97->limited_regs = template->limited_regs; | 1863 | ac97->res_table = template->res_table; |
1857 | memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed)); | ||
1858 | bus->codec[ac97->num] = ac97; | 1864 | bus->codec[ac97->num] = ac97; |
1859 | init_MUTEX(&ac97->reg_mutex); | 1865 | mutex_init(&ac97->reg_mutex); |
1860 | init_MUTEX(&ac97->page_mutex); | 1866 | mutex_init(&ac97->page_mutex); |
1861 | 1867 | ||
1862 | #ifdef CONFIG_PCI | 1868 | #ifdef CONFIG_PCI |
1863 | if (ac97->pci) { | 1869 | if (ac97->pci) { |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index a444a78c7c94..4d9cf37300f7 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/mutex.h> | ||
31 | |||
30 | #include <sound/core.h> | 32 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
32 | #include <sound/control.h> | 34 | #include <sound/control.h> |
@@ -55,12 +57,12 @@ static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsi | |||
55 | unsigned short page_save; | 57 | unsigned short page_save; |
56 | int ret; | 58 | int ret; |
57 | 59 | ||
58 | down(&ac97->page_mutex); | 60 | mutex_lock(&ac97->page_mutex); |
59 | page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; | 61 | page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; |
60 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); | 62 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); |
61 | ret = snd_ac97_update_bits(ac97, reg, mask, value); | 63 | ret = snd_ac97_update_bits(ac97, reg, mask, value); |
62 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); | 64 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); |
63 | up(&ac97->page_mutex); /* unlock paging */ | 65 | mutex_unlock(&ac97->page_mutex); /* unlock paging */ |
64 | return ret; | 66 | return ret; |
65 | } | 67 | } |
66 | 68 | ||
@@ -897,12 +899,12 @@ static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ | |||
897 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 899 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
898 | int err; | 900 | int err; |
899 | 901 | ||
900 | down(&ac97->page_mutex); | 902 | mutex_lock(&ac97->page_mutex); |
901 | snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba); | 903 | snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba); |
902 | err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010, | 904 | err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010, |
903 | (ucontrol->value.integer.value[0] & 1) << 4); | 905 | (ucontrol->value.integer.value[0] & 1) << 4); |
904 | snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0); | 906 | snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0); |
905 | up(&ac97->page_mutex); | 907 | mutex_unlock(&ac97->page_mutex); |
906 | return err; | 908 | return err; |
907 | } | 909 | } |
908 | 910 | ||
@@ -2823,3 +2825,33 @@ int mpatch_si3036(struct snd_ac97 * ac97) | |||
2823 | snd_ac97_write_cache(ac97, 0x68, 0); | 2825 | snd_ac97_write_cache(ac97, 0x68, 0); |
2824 | return 0; | 2826 | return 0; |
2825 | } | 2827 | } |
2828 | |||
2829 | /* | ||
2830 | * LM 4550 Codec | ||
2831 | * | ||
2832 | * We use a static resolution table since LM4550 codec cannot be | ||
2833 | * properly autoprobed to determine the resolution via | ||
2834 | * check_volume_resolution(). | ||
2835 | */ | ||
2836 | |||
2837 | static struct snd_ac97_res_table lm4550_restbl[] = { | ||
2838 | { AC97_MASTER, 0x1f1f }, | ||
2839 | { AC97_HEADPHONE, 0x1f1f }, | ||
2840 | { AC97_MASTER_MONO, 0x001f }, | ||
2841 | { AC97_PC_BEEP, 0x001f }, /* LSB is ignored */ | ||
2842 | { AC97_PHONE, 0x001f }, | ||
2843 | { AC97_MIC, 0x001f }, | ||
2844 | { AC97_LINE, 0x1f1f }, | ||
2845 | { AC97_CD, 0x1f1f }, | ||
2846 | { AC97_VIDEO, 0x1f1f }, | ||
2847 | { AC97_AUX, 0x1f1f }, | ||
2848 | { AC97_PCM, 0x1f1f }, | ||
2849 | { AC97_REC_GAIN, 0x0f0f }, | ||
2850 | { } /* terminator */ | ||
2851 | }; | ||
2852 | |||
2853 | int patch_lm4550(struct snd_ac97 *ac97) | ||
2854 | { | ||
2855 | ac97->res_table = lm4550_restbl; | ||
2856 | return 0; | ||
2857 | } | ||
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h index 5060cb6f2ec3..adcaa04586cb 100644 --- a/sound/pci/ac97/ac97_patch.h +++ b/sound/pci/ac97/ac97_patch.h | |||
@@ -59,3 +59,4 @@ int patch_vt1616(struct snd_ac97 * ac97); | |||
59 | int patch_vt1617a(struct snd_ac97 * ac97); | 59 | int patch_vt1617a(struct snd_ac97 * ac97); |
60 | int patch_it2646(struct snd_ac97 * ac97); | 60 | int patch_it2646(struct snd_ac97 * ac97); |
61 | int mpatch_si3036(struct snd_ac97 * ac97); | 61 | int mpatch_si3036(struct snd_ac97 * ac97); |
62 | int patch_lm4550(struct snd_ac97 * ac97); | ||
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index c3e590bf7a02..512a3583b0ce 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/mutex.h> | ||
31 | |||
30 | #include <sound/core.h> | 32 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 33 | #include <sound/pcm.h> |
32 | #include <sound/control.h> | 34 | #include <sound/control.h> |
@@ -206,7 +208,7 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) | |||
206 | mask = AC97_SC_SPSR_MASK; | 208 | mask = AC97_SC_SPSR_MASK; |
207 | } | 209 | } |
208 | 210 | ||
209 | down(&ac97->reg_mutex); | 211 | mutex_lock(&ac97->reg_mutex); |
210 | old = snd_ac97_read(ac97, reg) & mask; | 212 | old = snd_ac97_read(ac97, reg) & mask; |
211 | if (old != bits) { | 213 | if (old != bits) { |
212 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); | 214 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); |
@@ -231,7 +233,7 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) | |||
231 | ac97->spdif_status = sbits; | 233 | ac97->spdif_status = sbits; |
232 | } | 234 | } |
233 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); | 235 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); |
234 | up(&ac97->reg_mutex); | 236 | mutex_unlock(&ac97->reg_mutex); |
235 | return 0; | 237 | return 0; |
236 | } | 238 | } |
237 | 239 | ||
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 7134b3f55fb5..4d523df79cc7 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c | |||
@@ -24,6 +24,8 @@ | |||
24 | 24 | ||
25 | #include <sound/driver.h> | 25 | #include <sound/driver.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/mutex.h> | ||
28 | |||
27 | #include <sound/core.h> | 29 | #include <sound/core.h> |
28 | #include <sound/ac97_codec.h> | 30 | #include <sound/ac97_codec.h> |
29 | #include <sound/asoundef.h> | 31 | #include <sound/asoundef.h> |
@@ -338,7 +340,7 @@ static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buf | |||
338 | { | 340 | { |
339 | struct snd_ac97 *ac97 = entry->private_data; | 341 | struct snd_ac97 *ac97 = entry->private_data; |
340 | 342 | ||
341 | down(&ac97->page_mutex); | 343 | mutex_lock(&ac97->page_mutex); |
342 | if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 | 344 | if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 |
343 | int idx; | 345 | int idx; |
344 | for (idx = 0; idx < 3; idx++) | 346 | for (idx = 0; idx < 3; idx++) |
@@ -364,7 +366,7 @@ static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buf | |||
364 | } else { | 366 | } else { |
365 | snd_ac97_proc_read_main(ac97, buffer, 0); | 367 | snd_ac97_proc_read_main(ac97, buffer, 0); |
366 | } | 368 | } |
367 | up(&ac97->page_mutex); | 369 | mutex_unlock(&ac97->page_mutex); |
368 | } | 370 | } |
369 | 371 | ||
370 | #ifdef CONFIG_SND_DEBUG | 372 | #ifdef CONFIG_SND_DEBUG |
@@ -374,7 +376,7 @@ static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_in | |||
374 | struct snd_ac97 *ac97 = entry->private_data; | 376 | struct snd_ac97 *ac97 = entry->private_data; |
375 | char line[64]; | 377 | char line[64]; |
376 | unsigned int reg, val; | 378 | unsigned int reg, val; |
377 | down(&ac97->page_mutex); | 379 | mutex_lock(&ac97->page_mutex); |
378 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | 380 | while (!snd_info_get_line(buffer, line, sizeof(line))) { |
379 | if (sscanf(line, "%x %x", ®, &val) != 2) | 381 | if (sscanf(line, "%x %x", ®, &val) != 2) |
380 | continue; | 382 | continue; |
@@ -382,7 +384,7 @@ static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_in | |||
382 | if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff) | 384 | if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff) |
383 | snd_ac97_write_cache(ac97, reg, val); | 385 | snd_ac97_write_cache(ac97, reg, val); |
384 | } | 386 | } |
385 | up(&ac97->page_mutex); | 387 | mutex_unlock(&ac97->page_mutex); |
386 | } | 388 | } |
387 | #endif | 389 | #endif |
388 | 390 | ||
@@ -401,7 +403,7 @@ static void snd_ac97_proc_regs_read(struct snd_info_entry *entry, | |||
401 | { | 403 | { |
402 | struct snd_ac97 *ac97 = entry->private_data; | 404 | struct snd_ac97 *ac97 = entry->private_data; |
403 | 405 | ||
404 | down(&ac97->page_mutex); | 406 | mutex_lock(&ac97->page_mutex); |
405 | if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 | 407 | if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 |
406 | 408 | ||
407 | int idx; | 409 | int idx; |
@@ -417,7 +419,7 @@ static void snd_ac97_proc_regs_read(struct snd_info_entry *entry, | |||
417 | } else { | 419 | } else { |
418 | snd_ac97_proc_regs_read_main(ac97, buffer, 0); | 420 | snd_ac97_proc_regs_read_main(ac97, buffer, 0); |
419 | } | 421 | } |
420 | up(&ac97->page_mutex); | 422 | mutex_unlock(&ac97->page_mutex); |
421 | } | 423 | } |
422 | 424 | ||
423 | void snd_ac97_proc_init(struct snd_ac97 * ac97) | 425 | void snd_ac97_proc_init(struct snd_ac97 * ac97) |
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c index dcfb5036ff8b..0fb7b3407312 100644 --- a/sound/pci/ac97/ak4531_codec.c +++ b/sound/pci/ac97/ak4531_codec.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/mutex.h> | ||
27 | |||
26 | #include <sound/core.h> | 28 | #include <sound/core.h> |
27 | #include <sound/ak4531_codec.h> | 29 | #include <sound/ak4531_codec.h> |
28 | 30 | ||
@@ -82,9 +84,9 @@ static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
82 | int invert = (kcontrol->private_value >> 22) & 1; | 84 | int invert = (kcontrol->private_value >> 22) & 1; |
83 | int val; | 85 | int val; |
84 | 86 | ||
85 | down(&ak4531->reg_mutex); | 87 | mutex_lock(&ak4531->reg_mutex); |
86 | val = (ak4531->regs[reg] >> shift) & mask; | 88 | val = (ak4531->regs[reg] >> shift) & mask; |
87 | up(&ak4531->reg_mutex); | 89 | mutex_unlock(&ak4531->reg_mutex); |
88 | if (invert) { | 90 | if (invert) { |
89 | val = mask - val; | 91 | val = mask - val; |
90 | } | 92 | } |
@@ -107,11 +109,11 @@ static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
107 | val = mask - val; | 109 | val = mask - val; |
108 | } | 110 | } |
109 | val <<= shift; | 111 | val <<= shift; |
110 | down(&ak4531->reg_mutex); | 112 | mutex_lock(&ak4531->reg_mutex); |
111 | val = (ak4531->regs[reg] & ~(mask << shift)) | val; | 113 | val = (ak4531->regs[reg] & ~(mask << shift)) | val; |
112 | change = val != ak4531->regs[reg]; | 114 | change = val != ak4531->regs[reg]; |
113 | ak4531->write(ak4531, reg, ak4531->regs[reg] = val); | 115 | ak4531->write(ak4531, reg, ak4531->regs[reg] = val); |
114 | up(&ak4531->reg_mutex); | 116 | mutex_unlock(&ak4531->reg_mutex); |
115 | return change; | 117 | return change; |
116 | } | 118 | } |
117 | 119 | ||
@@ -143,10 +145,10 @@ static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
143 | int invert = (kcontrol->private_value >> 22) & 1; | 145 | int invert = (kcontrol->private_value >> 22) & 1; |
144 | int left, right; | 146 | int left, right; |
145 | 147 | ||
146 | down(&ak4531->reg_mutex); | 148 | mutex_lock(&ak4531->reg_mutex); |
147 | left = (ak4531->regs[left_reg] >> left_shift) & mask; | 149 | left = (ak4531->regs[left_reg] >> left_shift) & mask; |
148 | right = (ak4531->regs[right_reg] >> right_shift) & mask; | 150 | right = (ak4531->regs[right_reg] >> right_shift) & mask; |
149 | up(&ak4531->reg_mutex); | 151 | mutex_unlock(&ak4531->reg_mutex); |
150 | if (invert) { | 152 | if (invert) { |
151 | left = mask - left; | 153 | left = mask - left; |
152 | right = mask - right; | 154 | right = mask - right; |
@@ -176,7 +178,7 @@ static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
176 | } | 178 | } |
177 | left <<= left_shift; | 179 | left <<= left_shift; |
178 | right <<= right_shift; | 180 | right <<= right_shift; |
179 | down(&ak4531->reg_mutex); | 181 | mutex_lock(&ak4531->reg_mutex); |
180 | if (left_reg == right_reg) { | 182 | if (left_reg == right_reg) { |
181 | left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right; | 183 | left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right; |
182 | change = left != ak4531->regs[left_reg]; | 184 | change = left != ak4531->regs[left_reg]; |
@@ -188,7 +190,7 @@ static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
188 | ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left); | 190 | ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left); |
189 | ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right); | 191 | ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right); |
190 | } | 192 | } |
191 | up(&ak4531->reg_mutex); | 193 | mutex_unlock(&ak4531->reg_mutex); |
192 | return change; | 194 | return change; |
193 | } | 195 | } |
194 | 196 | ||
@@ -215,12 +217,12 @@ static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
215 | int left_shift = (kcontrol->private_value >> 16) & 0x0f; | 217 | int left_shift = (kcontrol->private_value >> 16) & 0x0f; |
216 | int right_shift = (kcontrol->private_value >> 24) & 0x0f; | 218 | int right_shift = (kcontrol->private_value >> 24) & 0x0f; |
217 | 219 | ||
218 | down(&ak4531->reg_mutex); | 220 | mutex_lock(&ak4531->reg_mutex); |
219 | ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1; | 221 | ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1; |
220 | ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1; | 222 | ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1; |
221 | ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1; | 223 | ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1; |
222 | ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1; | 224 | ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1; |
223 | up(&ak4531->reg_mutex); | 225 | mutex_unlock(&ak4531->reg_mutex); |
224 | return 0; | 226 | return 0; |
225 | } | 227 | } |
226 | 228 | ||
@@ -234,7 +236,7 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
234 | int change; | 236 | int change; |
235 | int val1, val2; | 237 | int val1, val2; |
236 | 238 | ||
237 | down(&ak4531->reg_mutex); | 239 | mutex_lock(&ak4531->reg_mutex); |
238 | val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift)); | 240 | val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift)); |
239 | val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift)); | 241 | val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift)); |
240 | val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift; | 242 | val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift; |
@@ -244,7 +246,7 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
244 | change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2]; | 246 | change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2]; |
245 | ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1); | 247 | ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1); |
246 | ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2); | 248 | ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2); |
247 | up(&ak4531->reg_mutex); | 249 | mutex_unlock(&ak4531->reg_mutex); |
248 | return change; | 250 | return change; |
249 | } | 251 | } |
250 | 252 | ||
@@ -366,7 +368,7 @@ int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531, | |||
366 | if (ak4531 == NULL) | 368 | if (ak4531 == NULL) |
367 | return -ENOMEM; | 369 | return -ENOMEM; |
368 | *ak4531 = *_ak4531; | 370 | *ak4531 = *_ak4531; |
369 | init_MUTEX(&ak4531->reg_mutex); | 371 | mutex_init(&ak4531->reg_mutex); |
370 | if ((err = snd_component_add(card, "AK4531")) < 0) { | 372 | if ((err = snd_component_add(card, "AK4531")) < 0) { |
371 | snd_ak4531_free(ak4531); | 373 | snd_ak4531_free(ak4531); |
372 | return err; | 374 | return err; |
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index a208075cdc1e..2aa5a7fdb6e0 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/dma-mapping.h> | ||
37 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
38 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
39 | #include <linux/compiler.h> | 40 | #include <linux/compiler.h> |
@@ -909,10 +910,10 @@ snd_ad1889_create(struct snd_card *card, | |||
909 | 910 | ||
910 | if ((err = pci_enable_device(pci)) < 0) | 911 | if ((err = pci_enable_device(pci)) < 0) |
911 | return err; | 912 | return err; |
912 | 913 | ||
913 | /* check PCI availability (32bit DMA) */ | 914 | /* check PCI availability (32bit DMA) */ |
914 | if (pci_set_dma_mask(pci, 0xffffffff) < 0 || | 915 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || |
915 | pci_set_consistent_dma_mask(pci, 0xffffffff) < 0) { | 916 | pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { |
916 | printk(KERN_ERR PFX "error setting 32-bit DMA mask.\n"); | 917 | printk(KERN_ERR PFX "error setting 32-bit DMA mask.\n"); |
917 | pci_disable_device(pci); | 918 | pci_disable_device(pci); |
918 | return -ENXIO; | 919 | return -ENXIO; |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index b7217adaf1d7..12e618851262 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/mutex.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
32 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
@@ -277,7 +278,7 @@ struct atiixp { | |||
277 | unsigned int codec_not_ready_bits; /* for codec detection */ | 278 | unsigned int codec_not_ready_bits; /* for codec detection */ |
278 | 279 | ||
279 | int spdif_over_aclink; /* passed from the module option */ | 280 | int spdif_over_aclink; /* passed from the module option */ |
280 | struct semaphore open_mutex; /* playback open mutex */ | 281 | struct mutex open_mutex; /* playback open mutex */ |
281 | }; | 282 | }; |
282 | 283 | ||
283 | 284 | ||
@@ -1051,9 +1052,9 @@ static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) | |||
1051 | struct atiixp *chip = snd_pcm_substream_chip(substream); | 1052 | struct atiixp *chip = snd_pcm_substream_chip(substream); |
1052 | int err; | 1053 | int err; |
1053 | 1054 | ||
1054 | down(&chip->open_mutex); | 1055 | mutex_lock(&chip->open_mutex); |
1055 | err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); | 1056 | err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); |
1056 | up(&chip->open_mutex); | 1057 | mutex_unlock(&chip->open_mutex); |
1057 | if (err < 0) | 1058 | if (err < 0) |
1058 | return err; | 1059 | return err; |
1059 | substream->runtime->hw.channels_max = chip->max_channels; | 1060 | substream->runtime->hw.channels_max = chip->max_channels; |
@@ -1068,9 +1069,9 @@ static int snd_atiixp_playback_close(struct snd_pcm_substream *substream) | |||
1068 | { | 1069 | { |
1069 | struct atiixp *chip = snd_pcm_substream_chip(substream); | 1070 | struct atiixp *chip = snd_pcm_substream_chip(substream); |
1070 | int err; | 1071 | int err; |
1071 | down(&chip->open_mutex); | 1072 | mutex_lock(&chip->open_mutex); |
1072 | err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); | 1073 | err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); |
1073 | up(&chip->open_mutex); | 1074 | mutex_unlock(&chip->open_mutex); |
1074 | return err; | 1075 | return err; |
1075 | } | 1076 | } |
1076 | 1077 | ||
@@ -1090,12 +1091,12 @@ static int snd_atiixp_spdif_open(struct snd_pcm_substream *substream) | |||
1090 | { | 1091 | { |
1091 | struct atiixp *chip = snd_pcm_substream_chip(substream); | 1092 | struct atiixp *chip = snd_pcm_substream_chip(substream); |
1092 | int err; | 1093 | int err; |
1093 | down(&chip->open_mutex); | 1094 | mutex_lock(&chip->open_mutex); |
1094 | if (chip->spdif_over_aclink) /* share DMA_PLAYBACK */ | 1095 | if (chip->spdif_over_aclink) /* share DMA_PLAYBACK */ |
1095 | err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 2); | 1096 | err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 2); |
1096 | else | 1097 | else |
1097 | err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_SPDIF], -1); | 1098 | err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_SPDIF], -1); |
1098 | up(&chip->open_mutex); | 1099 | mutex_unlock(&chip->open_mutex); |
1099 | return err; | 1100 | return err; |
1100 | } | 1101 | } |
1101 | 1102 | ||
@@ -1103,12 +1104,12 @@ static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream) | |||
1103 | { | 1104 | { |
1104 | struct atiixp *chip = snd_pcm_substream_chip(substream); | 1105 | struct atiixp *chip = snd_pcm_substream_chip(substream); |
1105 | int err; | 1106 | int err; |
1106 | down(&chip->open_mutex); | 1107 | mutex_lock(&chip->open_mutex); |
1107 | if (chip->spdif_over_aclink) | 1108 | if (chip->spdif_over_aclink) |
1108 | err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); | 1109 | err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); |
1109 | else | 1110 | else |
1110 | err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_SPDIF]); | 1111 | err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_SPDIF]); |
1111 | up(&chip->open_mutex); | 1112 | mutex_unlock(&chip->open_mutex); |
1112 | return err; | 1113 | return err; |
1113 | } | 1114 | } |
1114 | 1115 | ||
@@ -1560,7 +1561,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, | |||
1560 | } | 1561 | } |
1561 | 1562 | ||
1562 | spin_lock_init(&chip->reg_lock); | 1563 | spin_lock_init(&chip->reg_lock); |
1563 | init_MUTEX(&chip->open_mutex); | 1564 | mutex_init(&chip->open_mutex); |
1564 | chip->card = card; | 1565 | chip->card = card; |
1565 | chip->pci = pci; | 1566 | chip->pci = pci; |
1566 | chip->irq = -1; | 1567 | chip->irq = -1; |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 8d8fd5a4ed35..1d3766044643 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/mutex.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
32 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
@@ -255,7 +256,7 @@ struct atiixp_modem { | |||
255 | unsigned int codec_not_ready_bits; /* for codec detection */ | 256 | unsigned int codec_not_ready_bits; /* for codec detection */ |
256 | 257 | ||
257 | int spdif_over_aclink; /* passed from the module option */ | 258 | int spdif_over_aclink; /* passed from the module option */ |
258 | struct semaphore open_mutex; /* playback open mutex */ | 259 | struct mutex open_mutex; /* playback open mutex */ |
259 | }; | 260 | }; |
260 | 261 | ||
261 | 262 | ||
@@ -911,9 +912,9 @@ static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) | |||
911 | struct atiixp_modem *chip = snd_pcm_substream_chip(substream); | 912 | struct atiixp_modem *chip = snd_pcm_substream_chip(substream); |
912 | int err; | 913 | int err; |
913 | 914 | ||
914 | down(&chip->open_mutex); | 915 | mutex_lock(&chip->open_mutex); |
915 | err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); | 916 | err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); |
916 | up(&chip->open_mutex); | 917 | mutex_unlock(&chip->open_mutex); |
917 | if (err < 0) | 918 | if (err < 0) |
918 | return err; | 919 | return err; |
919 | return 0; | 920 | return 0; |
@@ -923,9 +924,9 @@ static int snd_atiixp_playback_close(struct snd_pcm_substream *substream) | |||
923 | { | 924 | { |
924 | struct atiixp_modem *chip = snd_pcm_substream_chip(substream); | 925 | struct atiixp_modem *chip = snd_pcm_substream_chip(substream); |
925 | int err; | 926 | int err; |
926 | down(&chip->open_mutex); | 927 | mutex_lock(&chip->open_mutex); |
927 | err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); | 928 | err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); |
928 | up(&chip->open_mutex); | 929 | mutex_unlock(&chip->open_mutex); |
929 | return err; | 930 | return err; |
930 | } | 931 | } |
931 | 932 | ||
@@ -1233,7 +1234,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, | |||
1233 | } | 1234 | } |
1234 | 1235 | ||
1235 | spin_lock_init(&chip->reg_lock); | 1236 | spin_lock_init(&chip->reg_lock); |
1236 | init_MUTEX(&chip->open_mutex); | 1237 | mutex_init(&chip->open_mutex); |
1237 | chip->card = card; | 1238 | chip->card = card; |
1238 | chip->pci = pci; | 1239 | chip->pci = pci; |
1239 | chip->irq = -1; | 1240 | chip->irq = -1; |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 7d9184f7367a..126870ec063a 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -151,14 +151,18 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
151 | // check PCI availability (DMA). | 151 | // check PCI availability (DMA). |
152 | if ((err = pci_enable_device(pci)) < 0) | 152 | if ((err = pci_enable_device(pci)) < 0) |
153 | return err; | 153 | return err; |
154 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK)) { | 154 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || |
155 | pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { | ||
155 | printk(KERN_ERR "error to set DMA mask\n"); | 156 | printk(KERN_ERR "error to set DMA mask\n"); |
157 | pci_disable_device(pci); | ||
156 | return -ENXIO; | 158 | return -ENXIO; |
157 | } | 159 | } |
158 | 160 | ||
159 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 161 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
160 | if (chip == NULL) | 162 | if (chip == NULL) { |
163 | pci_disable_device(pci); | ||
161 | return -ENOMEM; | 164 | return -ENOMEM; |
165 | } | ||
162 | 166 | ||
163 | chip->card = card; | 167 | chip->card = card; |
164 | 168 | ||
@@ -208,6 +212,8 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
208 | goto alloc_out; | 212 | goto alloc_out; |
209 | } | 213 | } |
210 | 214 | ||
215 | snd_card_set_dev(card, &pci->dev); | ||
216 | |||
211 | *rchip = chip; | 217 | *rchip = chip; |
212 | 218 | ||
213 | return 0; | 219 | return 0; |
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h index c2ad2674bea7..d65ccb1866a0 100644 --- a/sound/pci/au88x0/au88x0.h +++ b/sound/pci/au88x0/au88x0.h | |||
@@ -39,8 +39,8 @@ | |||
39 | #include "au88x0_wt.h" | 39 | #include "au88x0_wt.h" |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #define hwread(x,y) readl((x)+((y)>>2)) | 42 | #define hwread(x,y) readl((x)+(y)) |
43 | #define hwwrite(x,y,z) writel((z),(x)+((y)>>2)) | 43 | #define hwwrite(x,y,z) writel((z),(x)+(y)) |
44 | 44 | ||
45 | /* Vortex MPU401 defines. */ | 45 | /* Vortex MPU401 defines. */ |
46 | #define MIDI_CLOCK_DIV 0x61 | 46 | #define MIDI_CLOCK_DIV 0x61 |
@@ -113,7 +113,7 @@ typedef struct { | |||
113 | //int this_08; /* Still unknown */ | 113 | //int this_08; /* Still unknown */ |
114 | int fifo_enabled; /* this_24 */ | 114 | int fifo_enabled; /* this_24 */ |
115 | int fifo_status; /* this_1c */ | 115 | int fifo_status; /* this_1c */ |
116 | int dma_ctrl; /* this_78 (ADB), this_7c (WT) */ | 116 | u32 dma_ctrl; /* this_78 (ADB), this_7c (WT) */ |
117 | int dma_unknown; /* this_74 (ADB), this_78 (WT). WDM: +8 */ | 117 | int dma_unknown; /* this_74 (ADB), this_78 (WT). WDM: +8 */ |
118 | int cfg0; | 118 | int cfg0; |
119 | int cfg1; | 119 | int cfg1; |
@@ -178,7 +178,7 @@ struct snd_vortex { | |||
178 | 178 | ||
179 | /* PCI hardware resources */ | 179 | /* PCI hardware resources */ |
180 | unsigned long io; | 180 | unsigned long io; |
181 | unsigned long __iomem *mmio; | 181 | void __iomem *mmio; |
182 | unsigned int irq; | 182 | unsigned int irq; |
183 | spinlock_t lock; | 183 | spinlock_t lock; |
184 | 184 | ||
@@ -201,14 +201,14 @@ static void vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, | |||
201 | int count); | 201 | int count); |
202 | static void vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, | 202 | static void vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, |
203 | int dir, int fmt, int d, | 203 | int dir, int fmt, int d, |
204 | unsigned long offset); | 204 | u32 offset); |
205 | static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb); | 205 | static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb); |
206 | #ifndef CHIP_AU8810 | 206 | #ifndef CHIP_AU8810 |
207 | static void vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, | 207 | static void vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, |
208 | struct snd_sg_buf * sgbuf, int size, | 208 | struct snd_sg_buf * sgbuf, int size, |
209 | int count); | 209 | int count); |
210 | static void vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, /*int e, */ | 210 | static void vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, /*int e, */ |
211 | unsigned long offset); | 211 | u32 offset); |
212 | static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb); | 212 | static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb); |
213 | #endif | 213 | #endif |
214 | 214 | ||
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index e3394fe63253..9cac02e93b25 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c | |||
@@ -376,7 +376,7 @@ vortex_mixer_delWTD(vortex_t * vortex, unsigned char mix, unsigned char ch) | |||
376 | 376 | ||
377 | static void vortex_mixer_init(vortex_t * vortex) | 377 | static void vortex_mixer_init(vortex_t * vortex) |
378 | { | 378 | { |
379 | unsigned long addr; | 379 | u32 addr; |
380 | int x; | 380 | int x; |
381 | 381 | ||
382 | // FIXME: get rid of this crap. | 382 | // FIXME: get rid of this crap. |
@@ -639,7 +639,7 @@ static void vortex_src_setupchannel(vortex_t * card, unsigned char src, | |||
639 | 639 | ||
640 | static void vortex_srcblock_init(vortex_t * vortex) | 640 | static void vortex_srcblock_init(vortex_t * vortex) |
641 | { | 641 | { |
642 | unsigned long addr; | 642 | u32 addr; |
643 | int x; | 643 | int x; |
644 | hwwrite(vortex->mmio, VORTEX_SRC_SOURCESIZE, 0x1ff); | 644 | hwwrite(vortex->mmio, VORTEX_SRC_SOURCESIZE, 0x1ff); |
645 | /* | 645 | /* |
@@ -1035,7 +1035,7 @@ vortex_fifo_setwtctrl(vortex_t * vortex, int fifo, int ctrl, int priority, | |||
1035 | static void vortex_fifo_init(vortex_t * vortex) | 1035 | static void vortex_fifo_init(vortex_t * vortex) |
1036 | { | 1036 | { |
1037 | int x; | 1037 | int x; |
1038 | unsigned long addr; | 1038 | u32 addr; |
1039 | 1039 | ||
1040 | /* ADB DMA channels fifos. */ | 1040 | /* ADB DMA channels fifos. */ |
1041 | addr = VORTEX_FIFO_ADBCTRL + ((NR_ADB - 1) * 4); | 1041 | addr = VORTEX_FIFO_ADBCTRL + ((NR_ADB - 1) * 4); |
@@ -1054,7 +1054,7 @@ static void vortex_fifo_init(vortex_t * vortex) | |||
1054 | hwwrite(vortex->mmio, addr, FIFO_U0); | 1054 | hwwrite(vortex->mmio, addr, FIFO_U0); |
1055 | if (hwread(vortex->mmio, addr) != FIFO_U0) | 1055 | if (hwread(vortex->mmio, addr) != FIFO_U0) |
1056 | printk(KERN_ERR | 1056 | printk(KERN_ERR |
1057 | "bad wt fifo reset (0x%08lx, 0x%08x)!\n", | 1057 | "bad wt fifo reset (0x%08x, 0x%08x)!\n", |
1058 | addr, hwread(vortex->mmio, addr)); | 1058 | addr, hwread(vortex->mmio, addr)); |
1059 | vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE); | 1059 | vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE); |
1060 | addr -= 4; | 1060 | addr -= 4; |
@@ -1152,7 +1152,7 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, | |||
1152 | 1152 | ||
1153 | static void | 1153 | static void |
1154 | vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, int dir, | 1154 | vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, int dir, |
1155 | int fmt, int d, unsigned long offset) | 1155 | int fmt, int d, u32 offset) |
1156 | { | 1156 | { |
1157 | stream_t *dma = &vortex->dma_adb[adbdma]; | 1157 | stream_t *dma = &vortex->dma_adb[adbdma]; |
1158 | 1158 | ||
@@ -1411,7 +1411,7 @@ vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, | |||
1411 | 1411 | ||
1412 | static void | 1412 | static void |
1413 | vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, | 1413 | vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, |
1414 | /*int e, */ unsigned long offset) | 1414 | /*int e, */ u32 offset) |
1415 | { | 1415 | { |
1416 | stream_t *dma = &vortex->dma_wt[wtdma]; | 1416 | stream_t *dma = &vortex->dma_wt[wtdma]; |
1417 | 1417 | ||
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index c8280f82eb5a..64fbfbbaf816 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c | |||
@@ -377,23 +377,23 @@ static void vortex_EqHw_GetLevels(vortex_t * vortex, u16 a[]) | |||
377 | 377 | ||
378 | #endif | 378 | #endif |
379 | /* Global Control */ | 379 | /* Global Control */ |
380 | static void vortex_EqHw_SetControlReg(vortex_t * vortex, unsigned long reg) | 380 | static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg) |
381 | { | 381 | { |
382 | hwwrite(vortex->mmio, 0x2b440, reg); | 382 | hwwrite(vortex->mmio, 0x2b440, reg); |
383 | } | 383 | } |
384 | 384 | ||
385 | static void vortex_EqHw_SetSampleRate(vortex_t * vortex, int sr) | 385 | static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr) |
386 | { | 386 | { |
387 | hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800); | 387 | hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800); |
388 | } | 388 | } |
389 | 389 | ||
390 | #if 0 | 390 | #if 0 |
391 | static void vortex_EqHw_GetControlReg(vortex_t * vortex, unsigned long *reg) | 391 | static void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg) |
392 | { | 392 | { |
393 | *reg = hwread(vortex->mmio, 0x2b440); | 393 | *reg = hwread(vortex->mmio, 0x2b440); |
394 | } | 394 | } |
395 | 395 | ||
396 | static void vortex_EqHw_GetSampleRate(vortex_t * vortex, int *sr) | 396 | static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr) |
397 | { | 397 | { |
398 | *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f; | 398 | *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f; |
399 | } | 399 | } |
@@ -554,7 +554,7 @@ static void vortex_Eqlzr_SetRightGain(vortex_t * vortex, u16 index, u16 gain) | |||
554 | 554 | ||
555 | #if 0 | 555 | #if 0 |
556 | static int | 556 | static int |
557 | vortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, unsigned long *cnt) | 557 | vortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, s32 *cnt) |
558 | { | 558 | { |
559 | eqlzr_t *eq = &(vortex->eq); | 559 | eqlzr_t *eq = &(vortex->eq); |
560 | int si = 0; | 560 | int si = 0; |
@@ -586,7 +586,7 @@ static int vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex) | |||
586 | } | 586 | } |
587 | 587 | ||
588 | static int | 588 | static int |
589 | vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], unsigned long count) | 589 | vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], s32 count) |
590 | { | 590 | { |
591 | eqlzr_t *eq = &(vortex->eq); | 591 | eqlzr_t *eq = &(vortex->eq); |
592 | int i; | 592 | int i; |
@@ -604,11 +604,10 @@ vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], unsigned long count) | |||
604 | } | 604 | } |
605 | 605 | ||
606 | static void | 606 | static void |
607 | vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, unsigned long a, | 607 | vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, u32 a, u32 b) |
608 | unsigned long b) | ||
609 | { | 608 | { |
610 | eqlzr_t *eq = &(vortex->eq); | 609 | eqlzr_t *eq = &(vortex->eq); |
611 | int eax, ebx; | 610 | u32 eax, ebx; |
612 | 611 | ||
613 | eq->this58 = a; | 612 | eq->this58 = a; |
614 | eq->this5c = b; | 613 | eq->this5c = b; |
@@ -624,7 +623,7 @@ vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, unsigned long a, | |||
624 | static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex) | 623 | static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex) |
625 | { | 624 | { |
626 | eqlzr_t *eq = &(vortex->eq); | 625 | eqlzr_t *eq = &(vortex->eq); |
627 | int eax, ebx; | 626 | u32 eax, ebx; |
628 | 627 | ||
629 | if (eq->this54) | 628 | if (eq->this54) |
630 | eax = eq->this0e; | 629 | eax = eq->this0e; |
@@ -641,7 +640,7 @@ static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex) | |||
641 | vortex_EqHw_ZeroA3DIO(vortex); | 640 | vortex_EqHw_ZeroA3DIO(vortex); |
642 | } | 641 | } |
643 | 642 | ||
644 | static void vortex_Eqlzr_SetBypass(vortex_t * vortex, long bp) | 643 | static void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp) |
645 | { | 644 | { |
646 | eqlzr_t *eq = &(vortex->eq); | 645 | eqlzr_t *eq = &(vortex->eq); |
647 | 646 | ||
@@ -651,8 +650,8 @@ static void vortex_Eqlzr_SetBypass(vortex_t * vortex, long bp) | |||
651 | vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08); | 650 | vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08); |
652 | } else { | 651 | } else { |
653 | /* EQ disabled. */ | 652 | /* EQ disabled. */ |
654 | vortex_EqHw_SetLeftGainsTarget(vortex, (u16 *) (eq->this14)); | 653 | vortex_EqHw_SetLeftGainsTarget(vortex, eq->this14_array); |
655 | vortex_EqHw_SetRightGainsTarget(vortex, (u16 *) (eq->this14)); | 654 | vortex_EqHw_SetRightGainsTarget(vortex, eq->this14_array); |
656 | vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c); | 655 | vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c); |
657 | } | 656 | } |
658 | vortex_Eqlzr_ProgramA3dBypassGain(vortex); | 657 | vortex_Eqlzr_ProgramA3dBypassGain(vortex); |
@@ -706,7 +705,7 @@ static void vortex_Eqlzr_init(vortex_t * vortex) | |||
706 | eq->this5c = 0xffff; | 705 | eq->this5c = 0xffff; |
707 | 706 | ||
708 | /* Set gains. */ | 707 | /* Set gains. */ |
709 | memset(eq->this14, 0, 2 * 10); | 708 | memset(eq->this14_array, 0, sizeof(eq->this14_array)); |
710 | 709 | ||
711 | /* Actual init. */ | 710 | /* Actual init. */ |
712 | vortex_EqHw_ZeroState(vortex); | 711 | vortex_EqHw_ZeroState(vortex); |
@@ -792,7 +791,7 @@ snd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucon | |||
792 | { | 791 | { |
793 | vortex_t *vortex = snd_kcontrol_chip(kcontrol); | 792 | vortex_t *vortex = snd_kcontrol_chip(kcontrol); |
794 | int i = kcontrol->private_value; | 793 | int i = kcontrol->private_value; |
795 | u16 gainL, gainR; | 794 | u16 gainL = 0, gainR = 0; |
796 | 795 | ||
797 | vortex_Eqlzr_GetLeftGain(vortex, i, &gainL); | 796 | vortex_Eqlzr_GetLeftGain(vortex, i, &gainL); |
798 | vortex_Eqlzr_GetRightGain(vortex, i, &gainR); | 797 | vortex_Eqlzr_GetRightGain(vortex, i, &gainR); |
@@ -806,7 +805,7 @@ snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucon | |||
806 | { | 805 | { |
807 | vortex_t *vortex = snd_kcontrol_chip(kcontrol); | 806 | vortex_t *vortex = snd_kcontrol_chip(kcontrol); |
808 | int changed = 0, i = kcontrol->private_value; | 807 | int changed = 0, i = kcontrol->private_value; |
809 | u16 gainL, gainR; | 808 | u16 gainL = 0, gainR = 0; |
810 | 809 | ||
811 | vortex_Eqlzr_GetLeftGain(vortex, i, &gainL); | 810 | vortex_Eqlzr_GetLeftGain(vortex, i, &gainL); |
812 | vortex_Eqlzr_GetRightGain(vortex, i, &gainR); | 811 | vortex_Eqlzr_GetRightGain(vortex, i, &gainR); |
diff --git a/sound/pci/au88x0/au88x0_eq.h b/sound/pci/au88x0/au88x0_eq.h index e49bc625c873..474cd0046294 100644 --- a/sound/pci/au88x0/au88x0_eq.h +++ b/sound/pci/au88x0/au88x0_eq.h | |||
@@ -13,31 +13,28 @@ | |||
13 | typedef struct { | 13 | typedef struct { |
14 | u16 LeftCoefs[50]; //0x4 | 14 | u16 LeftCoefs[50]; //0x4 |
15 | u16 RightCoefs[50]; // 0x68 | 15 | u16 RightCoefs[50]; // 0x68 |
16 | u16 LeftGains[20]; //0xd0 | 16 | u16 LeftGains[10]; //0xd0 |
17 | u16 RightGains[20]; //0xe4 | 17 | u16 RightGains[10]; //0xe4 |
18 | } auxxEqCoeffSet_t; | 18 | } auxxEqCoeffSet_t; |
19 | 19 | ||
20 | typedef struct { | 20 | typedef struct { |
21 | unsigned int *this00; /*CAsp4HwIO */ | 21 | s32 this04; /* How many filters for each side (default = 10) */ |
22 | long this04; /* How many filters for each side (default = 10) */ | 22 | s32 this08; /* inited to cero. Stereo flag? */ |
23 | long this08; /* inited to cero. Stereo flag? */ | ||
24 | } eqhw_t; | 23 | } eqhw_t; |
25 | 24 | ||
26 | typedef struct { | 25 | typedef struct { |
27 | unsigned int *this00; /*CAsp4Core */ | ||
28 | eqhw_t this04; /* CHwEq */ | 26 | eqhw_t this04; /* CHwEq */ |
29 | short this08; /* Bad codec flag ? SetBypassGain: bypass gain */ | 27 | u16 this08; /* Bad codec flag ? SetBypassGain: bypass gain */ |
30 | short this0a; | 28 | u16 this0a; |
31 | short this0c; /* SetBypassGain: bypass gain when this28 is not set. */ | 29 | u16 this0c; /* SetBypassGain: bypass gain when this28 is not set. */ |
32 | short this0e; | 30 | u16 this0e; |
33 | 31 | ||
34 | long this10; /* How many gains are used for each side (right or left). */ | 32 | s32 this10; /* How many gains are used for each side (right or left). */ |
35 | u16 this14[32]; /* SetLeftGainsTarget: Left (and right?) EQ gains */ | 33 | u16 this14_array[10]; /* SetLeftGainsTarget: Left (and right?) EQ gains */ |
36 | long this24; | 34 | s32 this28; /* flag related to EQ enabled or not. Gang flag ? */ |
37 | long this28; /* flag related to EQ enabled or not. Gang flag ? */ | 35 | s32 this54; /* SetBypass */ |
38 | long this54; /* SetBypass */ | 36 | s32 this58; |
39 | long this58; | 37 | s32 this5c; |
40 | long this5c; | ||
41 | /*0x60 */ auxxEqCoeffSet_t coefset; | 38 | /*0x60 */ auxxEqCoeffSet_t coefset; |
42 | /* 50 u16 word each channel. */ | 39 | /* 50 u16 word each channel. */ |
43 | u16 this130[20]; /* Left and Right gains */ | 40 | u16 this130[20]; /* Left and Right gains */ |
diff --git a/sound/pci/au88x0/au88x0_eqdata.c b/sound/pci/au88x0/au88x0_eqdata.c index abf8d6ac4c15..ce8dca8ce1e2 100644 --- a/sound/pci/au88x0/au88x0_eqdata.c +++ b/sound/pci/au88x0/au88x0_eqdata.c | |||
@@ -104,7 +104,11 @@ static u16 asEqOutStateZeros[48] = { | |||
104 | }; | 104 | }; |
105 | 105 | ||
106 | /*_rodataba0:*/ | 106 | /*_rodataba0:*/ |
107 | static long eq_levels[32] = { | 107 | static u16 eq_levels[64] = { |
108 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
109 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
110 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
111 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
108 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | 112 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
109 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | 113 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
110 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | 114 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 8ba6dd36222b..873f486b07b8 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c | |||
@@ -95,7 +95,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) | |||
95 | return temp; | 95 | return temp; |
96 | } | 96 | } |
97 | #else | 97 | #else |
98 | port = (unsigned long)(vortex->mmio + (VORTEX_MIDI_DATA >> 2)); | 98 | port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); |
99 | if ((temp = | 99 | if ((temp = |
100 | snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, | 100 | snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, |
101 | 1, 0, 0, &rmidi)) != 0) { | 101 | 1, 0, 0, &rmidi)) != 0) { |
@@ -105,7 +105,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) | |||
105 | return temp; | 105 | return temp; |
106 | } | 106 | } |
107 | mpu = rmidi->private_data; | 107 | mpu = rmidi->private_data; |
108 | mpu->cport = (unsigned long)(vortex->mmio + (VORTEX_MIDI_CMD >> 2)); | 108 | mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD); |
109 | #endif | 109 | #endif |
110 | vortex->rmidi = rmidi; | 110 | vortex->rmidi = rmidi; |
111 | return 0; | 111 | return 0; |
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c index 65f375bad43a..d3e662a1285d 100644 --- a/sound/pci/au88x0/au88x0_synth.c +++ b/sound/pci/au88x0/au88x0_synth.c | |||
@@ -32,7 +32,7 @@ static void vortex_connection_mixin_mix(vortex_t * vortex, int en, | |||
32 | unsigned char mix, int a); | 32 | unsigned char mix, int a); |
33 | static void vortex_fifo_wtinitialize(vortex_t * vortex, int fifo, int j); | 33 | static void vortex_fifo_wtinitialize(vortex_t * vortex, int fifo, int j); |
34 | static int vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | 34 | static int vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, |
35 | unsigned long val); | 35 | u32 val); |
36 | 36 | ||
37 | /* WT */ | 37 | /* WT */ |
38 | 38 | ||
@@ -166,7 +166,7 @@ static int vortex_wt_GetReg(vortex_t * vortex, char reg, int wt) | |||
166 | /* WT hardware abstraction layer generic register interface. */ | 166 | /* WT hardware abstraction layer generic register interface. */ |
167 | static int | 167 | static int |
168 | vortex_wt_SetReg2(vortex_t * vortex, unsigned char reg, int wt, | 168 | vortex_wt_SetReg2(vortex_t * vortex, unsigned char reg, int wt, |
169 | unsigned short val) | 169 | u16 val) |
170 | { | 170 | { |
171 | /* | 171 | /* |
172 | int eax, edx; | 172 | int eax, edx; |
@@ -190,7 +190,7 @@ vortex_wt_SetReg2(vortex_t * vortex, unsigned char reg, int wt, | |||
190 | #endif | 190 | #endif |
191 | static int | 191 | static int |
192 | vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | 192 | vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, |
193 | unsigned long val) | 193 | u32 val) |
194 | { | 194 | { |
195 | int ecx; | 195 | int ecx; |
196 | 196 | ||
@@ -279,7 +279,7 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, | |||
279 | 279 | ||
280 | static void vortex_wt_init(vortex_t * vortex) | 280 | static void vortex_wt_init(vortex_t * vortex) |
281 | { | 281 | { |
282 | int var4, var8, varc, var10 = 0, edi; | 282 | u32 var4, var8, varc, var10 = 0, edi; |
283 | 283 | ||
284 | var10 &= 0xFFFFFFE3; | 284 | var10 &= 0xFFFFFFE3; |
285 | var10 |= 0x22; | 285 | var10 |= 0x22; |
@@ -353,7 +353,7 @@ static void vortex_wt_SetVolume(vortex_t * vortex, int wt, int vol[]) | |||
353 | static void vortex_wt_SetFrequency(vortex_t * vortex, int wt, unsigned int sr) | 353 | static void vortex_wt_SetFrequency(vortex_t * vortex, int wt, unsigned int sr) |
354 | { | 354 | { |
355 | wt_voice_t *voice = &(vortex->wt_voice[wt]); | 355 | wt_voice_t *voice = &(vortex->wt_voice[wt]); |
356 | long int eax, edx; | 356 | u32 eax, edx; |
357 | 357 | ||
358 | //FIXME: 64 bit operation. | 358 | //FIXME: 64 bit operation. |
359 | eax = ((sr << 0xf) * 0x57619F1) & 0xffffffff; | 359 | eax = ((sr << 0xf) * 0x57619F1) & 0xffffffff; |
diff --git a/sound/pci/au88x0/au88x0_wt.h b/sound/pci/au88x0/au88x0_wt.h index d536c88b43bf..38d98f88a95c 100644 --- a/sound/pci/au88x0/au88x0_wt.h +++ b/sound/pci/au88x0/au88x0_wt.h | |||
@@ -53,11 +53,11 @@ enum { | |||
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | typedef struct { | 55 | typedef struct { |
56 | unsigned int parm0; /* this_1E4 */ | 56 | u32 parm0; /* this_1E4 */ |
57 | unsigned int parm1; /* this_1E8 */ | 57 | u32 parm1; /* this_1E8 */ |
58 | unsigned int parm2; /* this_1EC */ | 58 | u32 parm2; /* this_1EC */ |
59 | unsigned int parm3; /* this_1F0 */ | 59 | u32 parm3; /* this_1F0 */ |
60 | unsigned int this_1D0; | 60 | u32 this_1D0; |
61 | } wt_voice_t; | 61 | } wt_voice_t; |
62 | 62 | ||
63 | #endif /* _AU88X0_WT_H */ | 63 | #endif /* _AU88X0_WT_H */ |
diff --git a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c index df915fa3f88d..4534e1882ada 100644 --- a/sound/pci/au88x0/au88x0_xtalk.c +++ b/sound/pci/au88x0/au88x0_xtalk.c | |||
@@ -562,7 +562,7 @@ static void | |||
562 | vortex_XtalkHw_SetDelay(vortex_t * vortex, unsigned short right, | 562 | vortex_XtalkHw_SetDelay(vortex_t * vortex, unsigned short right, |
563 | unsigned short left) | 563 | unsigned short left) |
564 | { | 564 | { |
565 | int esp0 = 0; | 565 | u32 esp0 = 0; |
566 | 566 | ||
567 | esp0 &= 0x1FFFFFFF; | 567 | esp0 &= 0x1FFFFFFF; |
568 | esp0 |= 0xA0000000; | 568 | esp0 |= 0xA0000000; |
@@ -632,18 +632,18 @@ static void vortex_XtalkHw_GetRightDline(vortex_t * vortex, xtalk_dline_t dline) | |||
632 | /* Control/Global stuff */ | 632 | /* Control/Global stuff */ |
633 | 633 | ||
634 | #if 0 | 634 | #if 0 |
635 | static void vortex_XtalkHw_SetControlReg(vortex_t * vortex, unsigned long ctrl) | 635 | static void vortex_XtalkHw_SetControlReg(vortex_t * vortex, u32 ctrl) |
636 | { | 636 | { |
637 | hwwrite(vortex->mmio, 0x24660, ctrl); | 637 | hwwrite(vortex->mmio, 0x24660, ctrl); |
638 | } | 638 | } |
639 | static void vortex_XtalkHw_GetControlReg(vortex_t * vortex, unsigned long *ctrl) | 639 | static void vortex_XtalkHw_GetControlReg(vortex_t * vortex, u32 *ctrl) |
640 | { | 640 | { |
641 | *ctrl = hwread(vortex->mmio, 0x24660); | 641 | *ctrl = hwread(vortex->mmio, 0x24660); |
642 | } | 642 | } |
643 | #endif | 643 | #endif |
644 | static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, int sr) | 644 | static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, u32 sr) |
645 | { | 645 | { |
646 | int temp; | 646 | u32 temp; |
647 | 647 | ||
648 | temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; | 648 | temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; |
649 | temp = (temp & 0xffffff07) | ((sr & 0x1f) << 3); | 649 | temp = (temp & 0xffffff07) | ((sr & 0x1f) << 3); |
@@ -651,7 +651,7 @@ static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, int sr) | |||
651 | } | 651 | } |
652 | 652 | ||
653 | #if 0 | 653 | #if 0 |
654 | static void vortex_XtalkHw_GetSampleRate(vortex_t * vortex, int *sr) | 654 | static void vortex_XtalkHw_GetSampleRate(vortex_t * vortex, u32 *sr) |
655 | { | 655 | { |
656 | *sr = (hwread(vortex->mmio, 0x24660) >> 3) & 0x1f; | 656 | *sr = (hwread(vortex->mmio, 0x24660) >> 3) & 0x1f; |
657 | } | 657 | } |
@@ -659,7 +659,7 @@ static void vortex_XtalkHw_GetSampleRate(vortex_t * vortex, int *sr) | |||
659 | #endif | 659 | #endif |
660 | static void vortex_XtalkHw_Enable(vortex_t * vortex) | 660 | static void vortex_XtalkHw_Enable(vortex_t * vortex) |
661 | { | 661 | { |
662 | int temp; | 662 | u32 temp; |
663 | 663 | ||
664 | temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; | 664 | temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; |
665 | temp |= 1; | 665 | temp |= 1; |
@@ -669,7 +669,7 @@ static void vortex_XtalkHw_Enable(vortex_t * vortex) | |||
669 | 669 | ||
670 | static void vortex_XtalkHw_Disable(vortex_t * vortex) | 670 | static void vortex_XtalkHw_Disable(vortex_t * vortex) |
671 | { | 671 | { |
672 | int temp; | 672 | u32 temp; |
673 | 673 | ||
674 | temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; | 674 | temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; |
675 | temp &= 0xfffffffe; | 675 | temp &= 0xfffffffe; |
diff --git a/sound/pci/au88x0/au88x0_xtalk.h b/sound/pci/au88x0/au88x0_xtalk.h index 0b8d7b64012d..7f4534b94d00 100644 --- a/sound/pci/au88x0/au88x0_xtalk.h +++ b/sound/pci/au88x0/au88x0_xtalk.h | |||
@@ -39,16 +39,16 @@ | |||
39 | #define XT_SPEAKER1 3 | 39 | #define XT_SPEAKER1 3 |
40 | #define XT_DIAMOND 4 | 40 | #define XT_DIAMOND 4 |
41 | 41 | ||
42 | typedef long xtalk_dline_t[XTDLINE_SZ]; | 42 | typedef u32 xtalk_dline_t[XTDLINE_SZ]; |
43 | typedef short xtalk_gains_t[XTGAINS_SZ]; | 43 | typedef u16 xtalk_gains_t[XTGAINS_SZ]; |
44 | typedef short xtalk_instate_t[XTINST_SZ]; | 44 | typedef u16 xtalk_instate_t[XTINST_SZ]; |
45 | typedef short xtalk_coefs_t[5][5]; | 45 | typedef u16 xtalk_coefs_t[5][5]; |
46 | typedef short xtalk_state_t[5][4]; | 46 | typedef u16 xtalk_state_t[5][4]; |
47 | 47 | ||
48 | static void vortex_XtalkHw_SetGains(vortex_t * vortex, | 48 | static void vortex_XtalkHw_SetGains(vortex_t * vortex, |
49 | xtalk_gains_t const gains); | 49 | xtalk_gains_t const gains); |
50 | static void vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex); | 50 | static void vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex); |
51 | static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, int sr); | 51 | static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, u32 sr); |
52 | static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex); | 52 | static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex); |
53 | static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex); | 53 | static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex); |
54 | static void vortex_XtalkHw_ProgramXtalkWide(vortex_t * vortex); | 54 | static void vortex_XtalkHw_ProgramXtalkWide(vortex_t * vortex); |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index c840a4c08e98..7b44a8db033d 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -783,6 +783,8 @@ static struct pci_device_id snd_bt87x_ids[] = { | |||
783 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), | 783 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), |
784 | /* AVerMedia Studio No. 103, 203, ...? */ | 784 | /* AVerMedia Studio No. 103, 203, ...? */ |
785 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), | 785 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), |
786 | /* Leadtek Winfast tv 2000xp delux */ | ||
787 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), | ||
786 | { } | 788 | { } |
787 | }; | 789 | }; |
788 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); | 790 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); |
@@ -793,12 +795,15 @@ static struct { | |||
793 | unsigned short subvendor, subdevice; | 795 | unsigned short subvendor, subdevice; |
794 | } blacklist[] __devinitdata = { | 796 | } blacklist[] __devinitdata = { |
795 | {0x0071, 0x0101}, /* Nebula Electronics DigiTV */ | 797 | {0x0071, 0x0101}, /* Nebula Electronics DigiTV */ |
798 | {0x11bd, 0x001c}, /* Pinnacle PCTV Sat */ | ||
796 | {0x11bd, 0x0026}, /* Pinnacle PCTV SAT CI */ | 799 | {0x11bd, 0x0026}, /* Pinnacle PCTV SAT CI */ |
797 | {0x1461, 0x0761}, /* AVermedia AverTV DVB-T */ | 800 | {0x1461, 0x0761}, /* AVermedia AverTV DVB-T */ |
798 | {0x1461, 0x0771}, /* AVermedia DVB-T 771 */ | 801 | {0x1461, 0x0771}, /* AVermedia DVB-T 771 */ |
799 | {0x1822, 0x0001}, /* Twinhan VisionPlus DVB-T */ | 802 | {0x1822, 0x0001}, /* Twinhan VisionPlus DVB-T */ |
803 | {0x18ac, 0xd500}, /* DVICO FusionHDTV 5 Lite */ | ||
800 | {0x18ac, 0xdb10}, /* DVICO FusionHDTV DVB-T Lite */ | 804 | {0x18ac, 0xdb10}, /* DVICO FusionHDTV DVB-T Lite */ |
801 | {0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */ | 805 | {0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */ |
806 | {0x7063, 0x2000}, /* pcHDTV HD-2000 TV */ | ||
802 | }; | 807 | }; |
803 | 808 | ||
804 | static struct pci_driver driver; | 809 | static struct pci_driver driver; |
@@ -816,13 +821,13 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) | |||
816 | for (i = 0; i < ARRAY_SIZE(blacklist); ++i) | 821 | for (i = 0; i < ARRAY_SIZE(blacklist); ++i) |
817 | if (blacklist[i].subvendor == pci->subsystem_vendor && | 822 | if (blacklist[i].subvendor == pci->subsystem_vendor && |
818 | blacklist[i].subdevice == pci->subsystem_device) { | 823 | blacklist[i].subdevice == pci->subsystem_device) { |
819 | snd_printdd(KERN_INFO "card %#04x:%#04x has no audio\n", | 824 | snd_printdd(KERN_INFO "card %#04x-%#04x:%#04x has no audio\n", |
820 | pci->subsystem_vendor, pci->subsystem_device); | 825 | pci->device, pci->subsystem_vendor, pci->subsystem_device); |
821 | return -EBUSY; | 826 | return -EBUSY; |
822 | } | 827 | } |
823 | 828 | ||
824 | snd_printk(KERN_INFO "unknown card %#04x:%#04x, using default rate 32000\n", | 829 | snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x, using default rate 32000\n", |
825 | pci->subsystem_vendor, pci->subsystem_device); | 830 | pci->device, pci->subsystem_vendor, pci->subsystem_device); |
826 | snd_printk(KERN_DEBUG "please mail id, board name, and, " | 831 | snd_printk(KERN_DEBUG "please mail id, board name, and, " |
827 | "if it works, the correct digital_rate option to " | 832 | "if it works, the correct digital_rate option to " |
828 | "<alsa-devel@lists.sf.net>\n"); | 833 | "<alsa-devel@lists.sf.net>\n"); |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index c03b0a0a3b27..2ecbddbbdcf0 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/gameport.h> | 30 | #include <linux/gameport.h> |
31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
32 | #include <linux/mutex.h> | ||
32 | #include <sound/core.h> | 33 | #include <sound/core.h> |
33 | #include <sound/info.h> | 34 | #include <sound/info.h> |
34 | #include <sound/control.h> | 35 | #include <sound/control.h> |
@@ -439,7 +440,7 @@ struct cmipci { | |||
439 | struct snd_pcm_hardware *hw_info[3]; /* for playbacks */ | 440 | struct snd_pcm_hardware *hw_info[3]; /* for playbacks */ |
440 | 441 | ||
441 | int opened[2]; /* open mode */ | 442 | int opened[2]; /* open mode */ |
442 | struct semaphore open_mutex; | 443 | struct mutex open_mutex; |
443 | 444 | ||
444 | unsigned int mixer_insensitive: 1; | 445 | unsigned int mixer_insensitive: 1; |
445 | struct snd_kcontrol *mixer_res_ctl[CM_SAVED_MIXERS]; | 446 | struct snd_kcontrol *mixer_res_ctl[CM_SAVED_MIXERS]; |
@@ -641,14 +642,14 @@ static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream, | |||
641 | { | 642 | { |
642 | struct cmipci *cm = snd_pcm_substream_chip(substream); | 643 | struct cmipci *cm = snd_pcm_substream_chip(substream); |
643 | if (params_channels(hw_params) > 2) { | 644 | if (params_channels(hw_params) > 2) { |
644 | down(&cm->open_mutex); | 645 | mutex_lock(&cm->open_mutex); |
645 | if (cm->opened[CM_CH_PLAY]) { | 646 | if (cm->opened[CM_CH_PLAY]) { |
646 | up(&cm->open_mutex); | 647 | mutex_unlock(&cm->open_mutex); |
647 | return -EBUSY; | 648 | return -EBUSY; |
648 | } | 649 | } |
649 | /* reserve the channel A */ | 650 | /* reserve the channel A */ |
650 | cm->opened[CM_CH_PLAY] = CM_OPEN_PLAYBACK_MULTI; | 651 | cm->opened[CM_CH_PLAY] = CM_OPEN_PLAYBACK_MULTI; |
651 | up(&cm->open_mutex); | 652 | mutex_unlock(&cm->open_mutex); |
652 | } | 653 | } |
653 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 654 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); |
654 | } | 655 | } |
@@ -1461,9 +1462,9 @@ static int open_device_check(struct cmipci *cm, int mode, struct snd_pcm_substre | |||
1461 | * pcm framework doesn't pass file pointer before actually opened, | 1462 | * pcm framework doesn't pass file pointer before actually opened, |
1462 | * we can't know whether blocking mode or not in open callback.. | 1463 | * we can't know whether blocking mode or not in open callback.. |
1463 | */ | 1464 | */ |
1464 | down(&cm->open_mutex); | 1465 | mutex_lock(&cm->open_mutex); |
1465 | if (cm->opened[ch]) { | 1466 | if (cm->opened[ch]) { |
1466 | up(&cm->open_mutex); | 1467 | mutex_unlock(&cm->open_mutex); |
1467 | return -EBUSY; | 1468 | return -EBUSY; |
1468 | } | 1469 | } |
1469 | cm->opened[ch] = mode; | 1470 | cm->opened[ch] = mode; |
@@ -1475,7 +1476,7 @@ static int open_device_check(struct cmipci *cm, int mode, struct snd_pcm_substre | |||
1475 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC); | 1476 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC); |
1476 | spin_unlock_irq(&cm->reg_lock); | 1477 | spin_unlock_irq(&cm->reg_lock); |
1477 | } | 1478 | } |
1478 | up(&cm->open_mutex); | 1479 | mutex_unlock(&cm->open_mutex); |
1479 | return 0; | 1480 | return 0; |
1480 | } | 1481 | } |
1481 | 1482 | ||
@@ -1483,7 +1484,7 @@ static void close_device_check(struct cmipci *cm, int mode) | |||
1483 | { | 1484 | { |
1484 | int ch = mode & CM_OPEN_CH_MASK; | 1485 | int ch = mode & CM_OPEN_CH_MASK; |
1485 | 1486 | ||
1486 | down(&cm->open_mutex); | 1487 | mutex_lock(&cm->open_mutex); |
1487 | if (cm->opened[ch] == mode) { | 1488 | if (cm->opened[ch] == mode) { |
1488 | if (cm->channel[ch].substream) { | 1489 | if (cm->channel[ch].substream) { |
1489 | snd_cmipci_ch_reset(cm, ch); | 1490 | snd_cmipci_ch_reset(cm, ch); |
@@ -1499,7 +1500,7 @@ static void close_device_check(struct cmipci *cm, int mode) | |||
1499 | spin_unlock_irq(&cm->reg_lock); | 1500 | spin_unlock_irq(&cm->reg_lock); |
1500 | } | 1501 | } |
1501 | } | 1502 | } |
1502 | up(&cm->open_mutex); | 1503 | mutex_unlock(&cm->open_mutex); |
1503 | } | 1504 | } |
1504 | 1505 | ||
1505 | /* | 1506 | /* |
@@ -1546,7 +1547,7 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) | |||
1546 | if ((err = open_device_check(cm, CM_OPEN_PLAYBACK2, substream)) < 0) /* use channel B */ | 1547 | if ((err = open_device_check(cm, CM_OPEN_PLAYBACK2, substream)) < 0) /* use channel B */ |
1547 | return err; | 1548 | return err; |
1548 | runtime->hw = snd_cmipci_playback2; | 1549 | runtime->hw = snd_cmipci_playback2; |
1549 | down(&cm->open_mutex); | 1550 | mutex_lock(&cm->open_mutex); |
1550 | if (! cm->opened[CM_CH_PLAY]) { | 1551 | if (! cm->opened[CM_CH_PLAY]) { |
1551 | if (cm->can_multi_ch) { | 1552 | if (cm->can_multi_ch) { |
1552 | runtime->hw.channels_max = cm->max_channels; | 1553 | runtime->hw.channels_max = cm->max_channels; |
@@ -1559,7 +1560,7 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) | |||
1559 | } | 1560 | } |
1560 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | 1561 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); |
1561 | } | 1562 | } |
1562 | up(&cm->open_mutex); | 1563 | mutex_unlock(&cm->open_mutex); |
1563 | return 0; | 1564 | return 0; |
1564 | } | 1565 | } |
1565 | 1566 | ||
@@ -2844,7 +2845,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2844 | } | 2845 | } |
2845 | 2846 | ||
2846 | spin_lock_init(&cm->reg_lock); | 2847 | spin_lock_init(&cm->reg_lock); |
2847 | init_MUTEX(&cm->open_mutex); | 2848 | mutex_init(&cm->open_mutex); |
2848 | cm->device = pci->device; | 2849 | cm->device = pci->device; |
2849 | cm->card = card; | 2850 | cm->card = card; |
2850 | cm->pci = pci; | 2851 | cm->pci = pci; |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 8fb275d6eb77..69dbf542a6de 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -53,6 +53,8 @@ | |||
53 | #include <linux/interrupt.h> | 53 | #include <linux/interrupt.h> |
54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
55 | #include <linux/gameport.h> | 55 | #include <linux/gameport.h> |
56 | #include <linux/mutex.h> | ||
57 | |||
56 | 58 | ||
57 | #include <sound/core.h> | 59 | #include <sound/core.h> |
58 | #include <sound/control.h> | 60 | #include <sound/control.h> |
@@ -909,22 +911,22 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, | |||
909 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 911 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
910 | snd_assert (sample_rate != 0, return -ENXIO); | 912 | snd_assert (sample_rate != 0, return -ENXIO); |
911 | 913 | ||
912 | down (&chip->spos_mutex); | 914 | mutex_lock(&chip->spos_mutex); |
913 | 915 | ||
914 | if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) { | 916 | if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) { |
915 | up (&chip->spos_mutex); | 917 | mutex_unlock(&chip->spos_mutex); |
916 | return -ENXIO; | 918 | return -ENXIO; |
917 | } | 919 | } |
918 | 920 | ||
919 | snd_assert (cpcm->pcm_channel != NULL); | 921 | snd_assert (cpcm->pcm_channel != NULL); |
920 | if (!cpcm->pcm_channel) { | 922 | if (!cpcm->pcm_channel) { |
921 | up (&chip->spos_mutex); | 923 | mutex_unlock(&chip->spos_mutex); |
922 | return -ENXIO; | 924 | return -ENXIO; |
923 | } | 925 | } |
924 | 926 | ||
925 | 927 | ||
926 | if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) { | 928 | if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) { |
927 | up (&chip->spos_mutex); | 929 | mutex_unlock(&chip->spos_mutex); |
928 | return -EINVAL; | 930 | return -EINVAL; |
929 | } | 931 | } |
930 | 932 | ||
@@ -965,7 +967,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, | |||
965 | } | 967 | } |
966 | if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) { | 968 | if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) { |
967 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 969 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
968 | up (&chip->spos_mutex); | 970 | mutex_unlock(&chip->spos_mutex); |
969 | #endif | 971 | #endif |
970 | return err; | 972 | return err; |
971 | } | 973 | } |
@@ -989,7 +991,7 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, | |||
989 | } | 991 | } |
990 | 992 | ||
991 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 993 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
992 | up (&chip->spos_mutex); | 994 | mutex_unlock(&chip->spos_mutex); |
993 | #endif | 995 | #endif |
994 | 996 | ||
995 | return 0; | 997 | return 0; |
@@ -1319,7 +1321,7 @@ static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,in | |||
1319 | 1321 | ||
1320 | cpcm->substream = substream; | 1322 | cpcm->substream = substream; |
1321 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 1323 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
1322 | down (&chip->spos_mutex); | 1324 | mutex_lock(&chip->spos_mutex); |
1323 | cpcm->pcm_channel = NULL; | 1325 | cpcm->pcm_channel = NULL; |
1324 | cpcm->pcm_channel_id = pcm_channel_id; | 1326 | cpcm->pcm_channel_id = pcm_channel_id; |
1325 | 1327 | ||
@@ -1328,7 +1330,7 @@ static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,in | |||
1328 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | 1330 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, |
1329 | &hw_constraints_period_sizes); | 1331 | &hw_constraints_period_sizes); |
1330 | 1332 | ||
1331 | up (&chip->spos_mutex); | 1333 | mutex_unlock(&chip->spos_mutex); |
1332 | #else | 1334 | #else |
1333 | chip->playback_pcm = cpcm; /* HACK */ | 1335 | chip->playback_pcm = cpcm; /* HACK */ |
1334 | #endif | 1336 | #endif |
@@ -1367,9 +1369,9 @@ static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream) | |||
1367 | 1369 | ||
1368 | snd_printdd("open raw iec958 channel\n"); | 1370 | snd_printdd("open raw iec958 channel\n"); |
1369 | 1371 | ||
1370 | down (&chip->spos_mutex); | 1372 | mutex_lock(&chip->spos_mutex); |
1371 | cs46xx_iec958_pre_open (chip); | 1373 | cs46xx_iec958_pre_open (chip); |
1372 | up (&chip->spos_mutex); | 1374 | mutex_unlock(&chip->spos_mutex); |
1373 | 1375 | ||
1374 | return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL); | 1376 | return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL); |
1375 | } | 1377 | } |
@@ -1385,9 +1387,9 @@ static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream) | |||
1385 | 1387 | ||
1386 | err = snd_cs46xx_playback_close(substream); | 1388 | err = snd_cs46xx_playback_close(substream); |
1387 | 1389 | ||
1388 | down (&chip->spos_mutex); | 1390 | mutex_lock(&chip->spos_mutex); |
1389 | cs46xx_iec958_post_close (chip); | 1391 | cs46xx_iec958_post_close (chip); |
1390 | up (&chip->spos_mutex); | 1392 | mutex_unlock(&chip->spos_mutex); |
1391 | 1393 | ||
1392 | return err; | 1394 | return err; |
1393 | } | 1395 | } |
@@ -1428,12 +1430,12 @@ static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream) | |||
1428 | if (!cpcm) return -ENXIO; | 1430 | if (!cpcm) return -ENXIO; |
1429 | 1431 | ||
1430 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 1432 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
1431 | down (&chip->spos_mutex); | 1433 | mutex_lock(&chip->spos_mutex); |
1432 | if (cpcm->pcm_channel) { | 1434 | if (cpcm->pcm_channel) { |
1433 | cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel); | 1435 | cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel); |
1434 | cpcm->pcm_channel = NULL; | 1436 | cpcm->pcm_channel = NULL; |
1435 | } | 1437 | } |
1436 | up (&chip->spos_mutex); | 1438 | mutex_unlock(&chip->spos_mutex); |
1437 | #else | 1439 | #else |
1438 | chip->playback_pcm = NULL; | 1440 | chip->playback_pcm = NULL; |
1439 | #endif | 1441 | #endif |
@@ -1848,7 +1850,7 @@ static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, | |||
1848 | 1850 | ||
1849 | switch (kcontrol->private_value) { | 1851 | switch (kcontrol->private_value) { |
1850 | case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT: | 1852 | case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT: |
1851 | down (&chip->spos_mutex); | 1853 | mutex_lock(&chip->spos_mutex); |
1852 | change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); | 1854 | change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); |
1853 | if (ucontrol->value.integer.value[0] && !change) | 1855 | if (ucontrol->value.integer.value[0] && !change) |
1854 | cs46xx_dsp_enable_spdif_out(chip); | 1856 | cs46xx_dsp_enable_spdif_out(chip); |
@@ -1856,7 +1858,7 @@ static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, | |||
1856 | cs46xx_dsp_disable_spdif_out(chip); | 1858 | cs46xx_dsp_disable_spdif_out(chip); |
1857 | 1859 | ||
1858 | res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED)); | 1860 | res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED)); |
1859 | up (&chip->spos_mutex); | 1861 | mutex_unlock(&chip->spos_mutex); |
1860 | break; | 1862 | break; |
1861 | case CS46XX_MIXER_SPDIF_INPUT_ELEMENT: | 1863 | case CS46XX_MIXER_SPDIF_INPUT_ELEMENT: |
1862 | change = chip->dsp_spos_instance->spdif_status_in; | 1864 | change = chip->dsp_spos_instance->spdif_status_in; |
@@ -1997,12 +1999,12 @@ static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol, | |||
1997 | struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); | 1999 | struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); |
1998 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 2000 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
1999 | 2001 | ||
2000 | down (&chip->spos_mutex); | 2002 | mutex_lock(&chip->spos_mutex); |
2001 | ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff); | 2003 | ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff); |
2002 | ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff); | 2004 | ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff); |
2003 | ucontrol->value.iec958.status[2] = 0; | 2005 | ucontrol->value.iec958.status[2] = 0; |
2004 | ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff); | 2006 | ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff); |
2005 | up (&chip->spos_mutex); | 2007 | mutex_unlock(&chip->spos_mutex); |
2006 | 2008 | ||
2007 | return 0; | 2009 | return 0; |
2008 | } | 2010 | } |
@@ -2015,7 +2017,7 @@ static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol, | |||
2015 | unsigned int val; | 2017 | unsigned int val; |
2016 | int change; | 2018 | int change; |
2017 | 2019 | ||
2018 | down (&chip->spos_mutex); | 2020 | mutex_lock(&chip->spos_mutex); |
2019 | val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | | 2021 | val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | |
2020 | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) | | 2022 | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) | |
2021 | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | | 2023 | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | |
@@ -2029,7 +2031,7 @@ static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol, | |||
2029 | if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) ) | 2031 | if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) ) |
2030 | cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); | 2032 | cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); |
2031 | 2033 | ||
2032 | up (&chip->spos_mutex); | 2034 | mutex_unlock(&chip->spos_mutex); |
2033 | 2035 | ||
2034 | return change; | 2036 | return change; |
2035 | } | 2037 | } |
@@ -2050,12 +2052,12 @@ static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol, | |||
2050 | struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); | 2052 | struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); |
2051 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 2053 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
2052 | 2054 | ||
2053 | down (&chip->spos_mutex); | 2055 | mutex_lock(&chip->spos_mutex); |
2054 | ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff); | 2056 | ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff); |
2055 | ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff); | 2057 | ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff); |
2056 | ucontrol->value.iec958.status[2] = 0; | 2058 | ucontrol->value.iec958.status[2] = 0; |
2057 | ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff); | 2059 | ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff); |
2058 | up (&chip->spos_mutex); | 2060 | mutex_unlock(&chip->spos_mutex); |
2059 | 2061 | ||
2060 | return 0; | 2062 | return 0; |
2061 | } | 2063 | } |
@@ -2068,7 +2070,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, | |||
2068 | unsigned int val; | 2070 | unsigned int val; |
2069 | int change; | 2071 | int change; |
2070 | 2072 | ||
2071 | down (&chip->spos_mutex); | 2073 | mutex_lock(&chip->spos_mutex); |
2072 | val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | | 2074 | val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | |
2073 | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) | | 2075 | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) | |
2074 | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | | 2076 | ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | |
@@ -2082,7 +2084,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, | |||
2082 | if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN ) | 2084 | if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN ) |
2083 | cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); | 2085 | cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); |
2084 | 2086 | ||
2085 | up (&chip->spos_mutex); | 2087 | mutex_unlock(&chip->spos_mutex); |
2086 | 2088 | ||
2087 | return change; | 2089 | return change; |
2088 | } | 2090 | } |
@@ -3755,7 +3757,7 @@ int __devinit snd_cs46xx_create(struct snd_card *card, | |||
3755 | } | 3757 | } |
3756 | spin_lock_init(&chip->reg_lock); | 3758 | spin_lock_init(&chip->reg_lock); |
3757 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 3759 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
3758 | init_MUTEX(&chip->spos_mutex); | 3760 | mutex_init(&chip->spos_mutex); |
3759 | #endif | 3761 | #endif |
3760 | chip->card = card; | 3762 | chip->card = card; |
3761 | chip->pci = pci; | 3763 | chip->pci = pci; |
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 445a448949e7..f407d2a5ce3b 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
31 | #include <linux/mutex.h> | ||
32 | |||
31 | #include <sound/core.h> | 33 | #include <sound/core.h> |
32 | #include <sound/control.h> | 34 | #include <sound/control.h> |
33 | #include <sound/info.h> | 35 | #include <sound/info.h> |
@@ -235,7 +237,7 @@ struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip) | |||
235 | 237 | ||
236 | if (ins->symbol_table.symbols == NULL) { | 238 | if (ins->symbol_table.symbols == NULL) { |
237 | cs46xx_dsp_spos_destroy(chip); | 239 | cs46xx_dsp_spos_destroy(chip); |
238 | return NULL; | 240 | goto error; |
239 | } | 241 | } |
240 | 242 | ||
241 | ins->code.offset = 0; | 243 | ins->code.offset = 0; |
@@ -244,7 +246,7 @@ struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip) | |||
244 | 246 | ||
245 | if (ins->code.data == NULL) { | 247 | if (ins->code.data == NULL) { |
246 | cs46xx_dsp_spos_destroy(chip); | 248 | cs46xx_dsp_spos_destroy(chip); |
247 | return NULL; | 249 | goto error; |
248 | } | 250 | } |
249 | 251 | ||
250 | ins->nscb = 0; | 252 | ins->nscb = 0; |
@@ -255,7 +257,7 @@ struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip) | |||
255 | 257 | ||
256 | if (ins->modules == NULL) { | 258 | if (ins->modules == NULL) { |
257 | cs46xx_dsp_spos_destroy(chip); | 259 | cs46xx_dsp_spos_destroy(chip); |
258 | return NULL; | 260 | goto error; |
259 | } | 261 | } |
260 | 262 | ||
261 | /* default SPDIF input sample rate | 263 | /* default SPDIF input sample rate |
@@ -278,6 +280,10 @@ struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip) | |||
278 | /* left and right validity bits */ (1 << 13) | (1 << 12); | 280 | /* left and right validity bits */ (1 << 13) | (1 << 12); |
279 | 281 | ||
280 | return ins; | 282 | return ins; |
283 | |||
284 | error: | ||
285 | kfree(ins); | ||
286 | return NULL; | ||
281 | } | 287 | } |
282 | 288 | ||
283 | void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) | 289 | void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) |
@@ -287,7 +293,7 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) | |||
287 | 293 | ||
288 | snd_assert(ins != NULL, return); | 294 | snd_assert(ins != NULL, return); |
289 | 295 | ||
290 | down(&chip->spos_mutex); | 296 | mutex_lock(&chip->spos_mutex); |
291 | for (i = 0; i < ins->nscb; ++i) { | 297 | for (i = 0; i < ins->nscb; ++i) { |
292 | if (ins->scbs[i].deleted) continue; | 298 | if (ins->scbs[i].deleted) continue; |
293 | 299 | ||
@@ -298,7 +304,7 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) | |||
298 | vfree(ins->symbol_table.symbols); | 304 | vfree(ins->symbol_table.symbols); |
299 | kfree(ins->modules); | 305 | kfree(ins->modules); |
300 | kfree(ins); | 306 | kfree(ins); |
301 | up(&chip->spos_mutex); | 307 | mutex_unlock(&chip->spos_mutex); |
302 | } | 308 | } |
303 | 309 | ||
304 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) | 310 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) |
@@ -497,7 +503,7 @@ static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry, | |||
497 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 503 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
498 | int i,j; | 504 | int i,j; |
499 | 505 | ||
500 | down(&chip->spos_mutex); | 506 | mutex_lock(&chip->spos_mutex); |
501 | snd_iprintf(buffer, "MODULES:\n"); | 507 | snd_iprintf(buffer, "MODULES:\n"); |
502 | for ( i = 0; i < ins->nmodules; ++i ) { | 508 | for ( i = 0; i < ins->nmodules; ++i ) { |
503 | snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name); | 509 | snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name); |
@@ -510,7 +516,7 @@ static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry, | |||
510 | desc->segment_type,desc->offset, desc->size); | 516 | desc->segment_type,desc->offset, desc->size); |
511 | } | 517 | } |
512 | } | 518 | } |
513 | up(&chip->spos_mutex); | 519 | mutex_unlock(&chip->spos_mutex); |
514 | } | 520 | } |
515 | 521 | ||
516 | static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, | 522 | static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, |
@@ -521,7 +527,7 @@ static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, | |||
521 | int i, j, col; | 527 | int i, j, col; |
522 | void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; | 528 | void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; |
523 | 529 | ||
524 | down(&chip->spos_mutex); | 530 | mutex_lock(&chip->spos_mutex); |
525 | snd_iprintf(buffer, "TASK TREES:\n"); | 531 | snd_iprintf(buffer, "TASK TREES:\n"); |
526 | for ( i = 0; i < ins->ntask; ++i) { | 532 | for ( i = 0; i < ins->ntask; ++i) { |
527 | snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name); | 533 | snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name); |
@@ -538,7 +544,7 @@ static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, | |||
538 | } | 544 | } |
539 | 545 | ||
540 | snd_iprintf(buffer,"\n"); | 546 | snd_iprintf(buffer,"\n"); |
541 | up(&chip->spos_mutex); | 547 | mutex_unlock(&chip->spos_mutex); |
542 | } | 548 | } |
543 | 549 | ||
544 | static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, | 550 | static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, |
@@ -548,7 +554,7 @@ static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, | |||
548 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 554 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
549 | int i; | 555 | int i; |
550 | 556 | ||
551 | down(&chip->spos_mutex); | 557 | mutex_lock(&chip->spos_mutex); |
552 | snd_iprintf(buffer, "SCB's:\n"); | 558 | snd_iprintf(buffer, "SCB's:\n"); |
553 | for ( i = 0; i < ins->nscb; ++i) { | 559 | for ( i = 0; i < ins->nscb; ++i) { |
554 | if (ins->scbs[i].deleted) | 560 | if (ins->scbs[i].deleted) |
@@ -571,7 +577,7 @@ static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, | |||
571 | } | 577 | } |
572 | 578 | ||
573 | snd_iprintf(buffer,"\n"); | 579 | snd_iprintf(buffer,"\n"); |
574 | up(&chip->spos_mutex); | 580 | mutex_unlock(&chip->spos_mutex); |
575 | } | 581 | } |
576 | 582 | ||
577 | static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry, | 583 | static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry, |
@@ -852,14 +858,14 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) | |||
852 | } | 858 | } |
853 | ins->proc_scb_info_entry = entry; | 859 | ins->proc_scb_info_entry = entry; |
854 | 860 | ||
855 | down(&chip->spos_mutex); | 861 | mutex_lock(&chip->spos_mutex); |
856 | /* register/update SCB's entries on proc */ | 862 | /* register/update SCB's entries on proc */ |
857 | for (i = 0; i < ins->nscb; ++i) { | 863 | for (i = 0; i < ins->nscb; ++i) { |
858 | if (ins->scbs[i].deleted) continue; | 864 | if (ins->scbs[i].deleted) continue; |
859 | 865 | ||
860 | cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i)); | 866 | cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i)); |
861 | } | 867 | } |
862 | up(&chip->spos_mutex); | 868 | mutex_unlock(&chip->spos_mutex); |
863 | 869 | ||
864 | return 0; | 870 | return 0; |
865 | } | 871 | } |
@@ -899,12 +905,12 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) | |||
899 | ins->proc_task_info_entry = NULL; | 905 | ins->proc_task_info_entry = NULL; |
900 | } | 906 | } |
901 | 907 | ||
902 | down(&chip->spos_mutex); | 908 | mutex_lock(&chip->spos_mutex); |
903 | for (i = 0; i < ins->nscb; ++i) { | 909 | for (i = 0; i < ins->nscb; ++i) { |
904 | if (ins->scbs[i].deleted) continue; | 910 | if (ins->scbs[i].deleted) continue; |
905 | cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); | 911 | cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); |
906 | } | 912 | } |
907 | up(&chip->spos_mutex); | 913 | mutex_unlock(&chip->spos_mutex); |
908 | 914 | ||
909 | if (ins->proc_dsp_dir) { | 915 | if (ins->proc_dsp_dir) { |
910 | snd_info_unregister (ins->proc_dsp_dir); | 916 | snd_info_unregister (ins->proc_dsp_dir); |
@@ -1694,7 +1700,7 @@ int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) | |||
1694 | snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL); | 1700 | snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL); |
1695 | snd_assert (ins->spdif_in_src != NULL,return -EINVAL); | 1701 | snd_assert (ins->spdif_in_src != NULL,return -EINVAL); |
1696 | 1702 | ||
1697 | down(&chip->spos_mutex); | 1703 | mutex_lock(&chip->spos_mutex); |
1698 | 1704 | ||
1699 | if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) { | 1705 | if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) { |
1700 | /* time countdown enable */ | 1706 | /* time countdown enable */ |
@@ -1738,7 +1744,7 @@ int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) | |||
1738 | 1744 | ||
1739 | /* monitor state */ | 1745 | /* monitor state */ |
1740 | ins->spdif_status_in = 1; | 1746 | ins->spdif_status_in = 1; |
1741 | up(&chip->spos_mutex); | 1747 | mutex_unlock(&chip->spos_mutex); |
1742 | 1748 | ||
1743 | return 0; | 1749 | return 0; |
1744 | } | 1750 | } |
@@ -1750,7 +1756,7 @@ int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip) | |||
1750 | snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL); | 1756 | snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL); |
1751 | snd_assert (ins->spdif_in_src != NULL,return -EINVAL); | 1757 | snd_assert (ins->spdif_in_src != NULL,return -EINVAL); |
1752 | 1758 | ||
1753 | down(&chip->spos_mutex); | 1759 | mutex_lock(&chip->spos_mutex); |
1754 | 1760 | ||
1755 | /* Remove the asynchronous receiver SCB */ | 1761 | /* Remove the asynchronous receiver SCB */ |
1756 | cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb); | 1762 | cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb); |
@@ -1760,7 +1766,7 @@ int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip) | |||
1760 | 1766 | ||
1761 | /* monitor state */ | 1767 | /* monitor state */ |
1762 | ins->spdif_status_in = 0; | 1768 | ins->spdif_status_in = 0; |
1763 | up(&chip->spos_mutex); | 1769 | mutex_unlock(&chip->spos_mutex); |
1764 | 1770 | ||
1765 | /* restore amplifier */ | 1771 | /* restore amplifier */ |
1766 | chip->active_ctrl(chip, -1); | 1772 | chip->active_ctrl(chip, -1); |
@@ -1776,10 +1782,10 @@ int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip) | |||
1776 | snd_assert (ins->pcm_input == NULL,return -EINVAL); | 1782 | snd_assert (ins->pcm_input == NULL,return -EINVAL); |
1777 | snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL); | 1783 | snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL); |
1778 | 1784 | ||
1779 | down(&chip->spos_mutex); | 1785 | mutex_lock(&chip->spos_mutex); |
1780 | ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR, | 1786 | ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR, |
1781 | "PCMSerialInput_Wave"); | 1787 | "PCMSerialInput_Wave"); |
1782 | up(&chip->spos_mutex); | 1788 | mutex_unlock(&chip->spos_mutex); |
1783 | 1789 | ||
1784 | return 0; | 1790 | return 0; |
1785 | } | 1791 | } |
@@ -1790,10 +1796,10 @@ int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip) | |||
1790 | 1796 | ||
1791 | snd_assert (ins->pcm_input != NULL,return -EINVAL); | 1797 | snd_assert (ins->pcm_input != NULL,return -EINVAL); |
1792 | 1798 | ||
1793 | down(&chip->spos_mutex); | 1799 | mutex_lock(&chip->spos_mutex); |
1794 | cs46xx_dsp_remove_scb (chip,ins->pcm_input); | 1800 | cs46xx_dsp_remove_scb (chip,ins->pcm_input); |
1795 | ins->pcm_input = NULL; | 1801 | ins->pcm_input = NULL; |
1796 | up(&chip->spos_mutex); | 1802 | mutex_unlock(&chip->spos_mutex); |
1797 | 1803 | ||
1798 | return 0; | 1804 | return 0; |
1799 | } | 1805 | } |
@@ -1805,10 +1811,10 @@ int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip) | |||
1805 | snd_assert (ins->adc_input == NULL,return -EINVAL); | 1811 | snd_assert (ins->adc_input == NULL,return -EINVAL); |
1806 | snd_assert (ins->codec_in_scb != NULL,return -EINVAL); | 1812 | snd_assert (ins->codec_in_scb != NULL,return -EINVAL); |
1807 | 1813 | ||
1808 | down(&chip->spos_mutex); | 1814 | mutex_lock(&chip->spos_mutex); |
1809 | ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR, | 1815 | ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR, |
1810 | "PCMSerialInput_ADC"); | 1816 | "PCMSerialInput_ADC"); |
1811 | up(&chip->spos_mutex); | 1817 | mutex_unlock(&chip->spos_mutex); |
1812 | 1818 | ||
1813 | return 0; | 1819 | return 0; |
1814 | } | 1820 | } |
@@ -1819,10 +1825,10 @@ int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip) | |||
1819 | 1825 | ||
1820 | snd_assert (ins->adc_input != NULL,return -EINVAL); | 1826 | snd_assert (ins->adc_input != NULL,return -EINVAL); |
1821 | 1827 | ||
1822 | down(&chip->spos_mutex); | 1828 | mutex_lock(&chip->spos_mutex); |
1823 | cs46xx_dsp_remove_scb (chip,ins->adc_input); | 1829 | cs46xx_dsp_remove_scb (chip,ins->adc_input); |
1824 | ins->adc_input = NULL; | 1830 | ins->adc_input = NULL; |
1825 | up(&chip->spos_mutex); | 1831 | mutex_unlock(&chip->spos_mutex); |
1826 | 1832 | ||
1827 | return 0; | 1833 | return 0; |
1828 | } | 1834 | } |
@@ -1869,7 +1875,7 @@ int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right) | |||
1869 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 1875 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
1870 | struct dsp_scb_descriptor * scb; | 1876 | struct dsp_scb_descriptor * scb; |
1871 | 1877 | ||
1872 | down(&chip->spos_mutex); | 1878 | mutex_lock(&chip->spos_mutex); |
1873 | 1879 | ||
1874 | /* main output */ | 1880 | /* main output */ |
1875 | scb = ins->master_mix_scb->sub_list_ptr; | 1881 | scb = ins->master_mix_scb->sub_list_ptr; |
@@ -1888,7 +1894,7 @@ int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right) | |||
1888 | ins->dac_volume_left = left; | 1894 | ins->dac_volume_left = left; |
1889 | ins->dac_volume_right = right; | 1895 | ins->dac_volume_right = right; |
1890 | 1896 | ||
1891 | up(&chip->spos_mutex); | 1897 | mutex_unlock(&chip->spos_mutex); |
1892 | 1898 | ||
1893 | return 0; | 1899 | return 0; |
1894 | } | 1900 | } |
@@ -1897,7 +1903,7 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) | |||
1897 | { | 1903 | { |
1898 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 1904 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
1899 | 1905 | ||
1900 | down(&chip->spos_mutex); | 1906 | mutex_lock(&chip->spos_mutex); |
1901 | 1907 | ||
1902 | if (ins->asynch_rx_scb != NULL) | 1908 | if (ins->asynch_rx_scb != NULL) |
1903 | cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb, | 1909 | cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb, |
@@ -1906,7 +1912,7 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) | |||
1906 | ins->spdif_input_volume_left = left; | 1912 | ins->spdif_input_volume_left = left; |
1907 | ins->spdif_input_volume_right = right; | 1913 | ins->spdif_input_volume_right = right; |
1908 | 1914 | ||
1909 | up(&chip->spos_mutex); | 1915 | mutex_unlock(&chip->spos_mutex); |
1910 | 1916 | ||
1911 | return 0; | 1917 | return 0; |
1912 | } | 1918 | } |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index d4e0fb39bd06..2c4ee45fe10c 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/pm.h> | 28 | #include <linux/pm.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/mutex.h> | ||
32 | |||
31 | #include <sound/core.h> | 33 | #include <sound/core.h> |
32 | #include <sound/control.h> | 34 | #include <sound/control.h> |
33 | #include <sound/info.h> | 35 | #include <sound/info.h> |
@@ -77,7 +79,7 @@ static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, | |||
77 | 79 | ||
78 | ins = chip->dsp_spos_instance; | 80 | ins = chip->dsp_spos_instance; |
79 | 81 | ||
80 | down(&chip->spos_mutex); | 82 | mutex_lock(&chip->spos_mutex); |
81 | snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name); | 83 | snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name); |
82 | 84 | ||
83 | for (col = 0,j = 0;j < 0x10; j++,col++) { | 85 | for (col = 0,j = 0;j < 0x10; j++,col++) { |
@@ -105,7 +107,7 @@ static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, | |||
105 | scb->task_entry->address); | 107 | scb->task_entry->address); |
106 | 108 | ||
107 | snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count); | 109 | snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count); |
108 | up(&chip->spos_mutex); | 110 | mutex_unlock(&chip->spos_mutex); |
109 | } | 111 | } |
110 | #endif | 112 | #endif |
111 | 113 | ||
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 02e3721030b7..9fc7f3827461 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -62,7 +62,7 @@ static void wait_till_cmd_acked(struct cs5535audio *cs5535au, unsigned long time | |||
62 | tmp = cs_readl(cs5535au, ACC_CODEC_CNTL); | 62 | tmp = cs_readl(cs5535au, ACC_CODEC_CNTL); |
63 | if (!(tmp & CMD_NEW)) | 63 | if (!(tmp & CMD_NEW)) |
64 | break; | 64 | break; |
65 | msleep(10); | 65 | udelay(1); |
66 | } while (--timeout); | 66 | } while (--timeout); |
67 | if (!timeout) | 67 | if (!timeout) |
68 | snd_printk(KERN_ERR "Failure writing to cs5535 codec\n"); | 68 | snd_printk(KERN_ERR "Failure writing to cs5535 codec\n"); |
@@ -80,14 +80,14 @@ static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au, | |||
80 | regdata |= CMD_NEW; | 80 | regdata |= CMD_NEW; |
81 | 81 | ||
82 | cs_writel(cs5535au, ACC_CODEC_CNTL, regdata); | 82 | cs_writel(cs5535au, ACC_CODEC_CNTL, regdata); |
83 | wait_till_cmd_acked(cs5535au, 500); | 83 | wait_till_cmd_acked(cs5535au, 50); |
84 | 84 | ||
85 | timeout = 50; | 85 | timeout = 50; |
86 | do { | 86 | do { |
87 | val = cs_readl(cs5535au, ACC_CODEC_STATUS); | 87 | val = cs_readl(cs5535au, ACC_CODEC_STATUS); |
88 | if ((val & STS_NEW) && reg == (val >> 24)) | 88 | if ((val & STS_NEW) && reg == (val >> 24)) |
89 | break; | 89 | break; |
90 | msleep(10); | 90 | udelay(1); |
91 | } while (--timeout); | 91 | } while (--timeout); |
92 | if (!timeout) | 92 | if (!timeout) |
93 | snd_printk(KERN_ERR "Failure reading cs5535 codec\n"); | 93 | snd_printk(KERN_ERR "Failure reading cs5535 codec\n"); |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 3c7043b7d4c9..31cb9b48bb59 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -36,6 +36,8 @@ | |||
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/vmalloc.h> | 38 | #include <linux/vmalloc.h> |
39 | #include <linux/mutex.h> | ||
40 | |||
39 | 41 | ||
40 | #include <sound/core.h> | 42 | #include <sound/core.h> |
41 | #include <sound/emu10k1.h> | 43 | #include <sound/emu10k1.h> |
@@ -775,6 +777,14 @@ static int snd_emu10k1_dev_free(struct snd_device *device) | |||
775 | 777 | ||
776 | static struct snd_emu_chip_details emu_chip_details[] = { | 778 | static struct snd_emu_chip_details emu_chip_details[] = { |
777 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ | 779 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ |
780 | /* Audigy4 SB0400 */ | ||
781 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, | ||
782 | .driver = "Audigy2", .name = "Audigy 4 [SB0400]", | ||
783 | .id = "Audigy2", | ||
784 | .emu10k2_chip = 1, | ||
785 | .ca0108_chip = 1, | ||
786 | .spk71 = 1, | ||
787 | .ac97_chip = 1} , | ||
778 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | 788 | /* Tested by James@superbug.co.uk 3rd July 2005 */ |
779 | /* DSP: CA0108-IAT | 789 | /* DSP: CA0108-IAT |
780 | * DAC: CS4382-KQ | 790 | * DAC: CS4382-KQ |
@@ -1097,8 +1107,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1097 | spin_lock_init(&emu->voice_lock); | 1107 | spin_lock_init(&emu->voice_lock); |
1098 | spin_lock_init(&emu->synth_lock); | 1108 | spin_lock_init(&emu->synth_lock); |
1099 | spin_lock_init(&emu->memblk_lock); | 1109 | spin_lock_init(&emu->memblk_lock); |
1100 | init_MUTEX(&emu->ptb_lock); | 1110 | mutex_init(&emu->fx8010.lock); |
1101 | init_MUTEX(&emu->fx8010.lock); | ||
1102 | INIT_LIST_HEAD(&emu->mapped_link_head); | 1111 | INIT_LIST_HEAD(&emu->mapped_link_head); |
1103 | INIT_LIST_HEAD(&emu->mapped_order_link_head); | 1112 | INIT_LIST_HEAD(&emu->mapped_order_link_head); |
1104 | emu->pci = pci; | 1113 | emu->pci = pci; |
diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c index 1fa393f22a99..204995a1dfbd 100644 --- a/sound/pci/emu10k1/emu10k1_synth.c +++ b/sound/pci/emu10k1/emu10k1_synth.c | |||
@@ -62,7 +62,6 @@ static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) | |||
62 | 62 | ||
63 | if (snd_emux_register(emu, dev->card, arg->index, "Emu10k1") < 0) { | 63 | if (snd_emux_register(emu, dev->card, arg->index, "Emu10k1") < 0) { |
64 | snd_emux_free(emu); | 64 | snd_emux_free(emu); |
65 | emu->hw = NULL; | ||
66 | return -ENOMEM; | 65 | return -ENOMEM; |
67 | } | 66 | } |
68 | 67 | ||
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 1107c8ec7f78..2208dbd48be9 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/dma-mapping.h> | ||
36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
37 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
38 | #include <sound/core.h> | 39 | #include <sound/core.h> |
@@ -893,24 +894,24 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card, | |||
893 | static struct snd_device_ops ops = { | 894 | static struct snd_device_ops ops = { |
894 | .dev_free = snd_emu10k1x_dev_free, | 895 | .dev_free = snd_emu10k1x_dev_free, |
895 | }; | 896 | }; |
896 | 897 | ||
897 | *rchip = NULL; | 898 | *rchip = NULL; |
898 | 899 | ||
899 | if ((err = pci_enable_device(pci)) < 0) | 900 | if ((err = pci_enable_device(pci)) < 0) |
900 | return err; | 901 | return err; |
901 | if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || | 902 | if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || |
902 | pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { | 903 | pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { |
903 | snd_printk(KERN_ERR "error to set 28bit mask DMA\n"); | 904 | snd_printk(KERN_ERR "error to set 28bit mask DMA\n"); |
904 | pci_disable_device(pci); | 905 | pci_disable_device(pci); |
905 | return -ENXIO; | 906 | return -ENXIO; |
906 | } | 907 | } |
907 | 908 | ||
908 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 909 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
909 | if (chip == NULL) { | 910 | if (chip == NULL) { |
910 | pci_disable_device(pci); | 911 | pci_disable_device(pci); |
911 | return -ENOMEM; | 912 | return -ENOMEM; |
912 | } | 913 | } |
913 | 914 | ||
914 | chip->card = card; | 915 | chip->card = card; |
915 | chip->pci = pci; | 916 | chip->pci = pci; |
916 | chip->irq = -1; | 917 | chip->irq = -1; |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 509837252735..dfba00230d4d 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/mutex.h> | ||
36 | |||
35 | #include <sound/core.h> | 37 | #include <sound/core.h> |
36 | #include <sound/emu10k1.h> | 38 | #include <sound/emu10k1.h> |
37 | 39 | ||
@@ -874,7 +876,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, | |||
874 | { | 876 | { |
875 | int err = 0; | 877 | int err = 0; |
876 | 878 | ||
877 | down(&emu->fx8010.lock); | 879 | mutex_lock(&emu->fx8010.lock); |
878 | if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0) | 880 | if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0) |
879 | goto __error; | 881 | goto __error; |
880 | strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); | 882 | strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); |
@@ -897,7 +899,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, | |||
897 | else | 899 | else |
898 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); | 900 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); |
899 | __error: | 901 | __error: |
900 | up(&emu->fx8010.lock); | 902 | mutex_unlock(&emu->fx8010.lock); |
901 | return err; | 903 | return err; |
902 | } | 904 | } |
903 | 905 | ||
@@ -906,7 +908,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, | |||
906 | { | 908 | { |
907 | int err; | 909 | int err; |
908 | 910 | ||
909 | down(&emu->fx8010.lock); | 911 | mutex_lock(&emu->fx8010.lock); |
910 | strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name)); | 912 | strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name)); |
911 | /* ok, do the main job */ | 913 | /* ok, do the main job */ |
912 | err = snd_emu10k1_gpr_peek(emu, icode); | 914 | err = snd_emu10k1_gpr_peek(emu, icode); |
@@ -916,7 +918,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, | |||
916 | err = snd_emu10k1_code_peek(emu, icode); | 918 | err = snd_emu10k1_code_peek(emu, icode); |
917 | if (err >= 0) | 919 | if (err >= 0) |
918 | err = snd_emu10k1_list_controls(emu, icode); | 920 | err = snd_emu10k1_list_controls(emu, icode); |
919 | up(&emu->fx8010.lock); | 921 | mutex_unlock(&emu->fx8010.lock); |
920 | return err; | 922 | return err; |
921 | } | 923 | } |
922 | 924 | ||
@@ -932,7 +934,7 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, | |||
932 | if (ipcm->channels > 32) | 934 | if (ipcm->channels > 32) |
933 | return -EINVAL; | 935 | return -EINVAL; |
934 | pcm = &emu->fx8010.pcm[ipcm->substream]; | 936 | pcm = &emu->fx8010.pcm[ipcm->substream]; |
935 | down(&emu->fx8010.lock); | 937 | mutex_lock(&emu->fx8010.lock); |
936 | spin_lock_irq(&emu->reg_lock); | 938 | spin_lock_irq(&emu->reg_lock); |
937 | if (pcm->opened) { | 939 | if (pcm->opened) { |
938 | err = -EBUSY; | 940 | err = -EBUSY; |
@@ -962,7 +964,7 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, | |||
962 | } | 964 | } |
963 | __error: | 965 | __error: |
964 | spin_unlock_irq(&emu->reg_lock); | 966 | spin_unlock_irq(&emu->reg_lock); |
965 | up(&emu->fx8010.lock); | 967 | mutex_unlock(&emu->fx8010.lock); |
966 | return err; | 968 | return err; |
967 | } | 969 | } |
968 | 970 | ||
@@ -976,7 +978,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, | |||
976 | if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) | 978 | if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) |
977 | return -EINVAL; | 979 | return -EINVAL; |
978 | pcm = &emu->fx8010.pcm[ipcm->substream]; | 980 | pcm = &emu->fx8010.pcm[ipcm->substream]; |
979 | down(&emu->fx8010.lock); | 981 | mutex_lock(&emu->fx8010.lock); |
980 | spin_lock_irq(&emu->reg_lock); | 982 | spin_lock_irq(&emu->reg_lock); |
981 | ipcm->channels = pcm->channels; | 983 | ipcm->channels = pcm->channels; |
982 | ipcm->tram_start = pcm->tram_start; | 984 | ipcm->tram_start = pcm->tram_start; |
@@ -992,7 +994,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, | |||
992 | ipcm->res1 = ipcm->res2 = 0; | 994 | ipcm->res1 = ipcm->res2 = 0; |
993 | ipcm->pad = 0; | 995 | ipcm->pad = 0; |
994 | spin_unlock_irq(&emu->reg_lock); | 996 | spin_unlock_irq(&emu->reg_lock); |
995 | up(&emu->fx8010.lock); | 997 | mutex_unlock(&emu->fx8010.lock); |
996 | return err; | 998 | return err; |
997 | } | 999 | } |
998 | 1000 | ||
@@ -2308,9 +2310,9 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un | |||
2308 | return -EPERM; | 2310 | return -EPERM; |
2309 | if (get_user(addr, (unsigned int __user *)argp)) | 2311 | if (get_user(addr, (unsigned int __user *)argp)) |
2310 | return -EFAULT; | 2312 | return -EFAULT; |
2311 | down(&emu->fx8010.lock); | 2313 | mutex_lock(&emu->fx8010.lock); |
2312 | res = snd_emu10k1_fx8010_tram_setup(emu, addr); | 2314 | res = snd_emu10k1_fx8010_tram_setup(emu, addr); |
2313 | up(&emu->fx8010.lock); | 2315 | mutex_unlock(&emu->fx8010.lock); |
2314 | return res; | 2316 | return res; |
2315 | case SNDRV_EMU10K1_IOCTL_STOP: | 2317 | case SNDRV_EMU10K1_IOCTL_STOP: |
2316 | if (!capable(CAP_SYS_ADMIN)) | 2318 | if (!capable(CAP_SYS_ADMIN)) |
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 68c795c03109..e7ec98649f04 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <sound/driver.h> | 24 | #include <sound/driver.h> |
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
27 | #include <linux/mutex.h> | ||
28 | |||
27 | #include <sound/core.h> | 29 | #include <sound/core.h> |
28 | #include <sound/emu10k1.h> | 30 | #include <sound/emu10k1.h> |
29 | 31 | ||
@@ -302,10 +304,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst | |||
302 | hdr = emu->memhdr; | 304 | hdr = emu->memhdr; |
303 | snd_assert(hdr, return NULL); | 305 | snd_assert(hdr, return NULL); |
304 | 306 | ||
305 | down(&hdr->block_mutex); | 307 | mutex_lock(&hdr->block_mutex); |
306 | blk = search_empty(emu, runtime->dma_bytes); | 308 | blk = search_empty(emu, runtime->dma_bytes); |
307 | if (blk == NULL) { | 309 | if (blk == NULL) { |
308 | up(&hdr->block_mutex); | 310 | mutex_unlock(&hdr->block_mutex); |
309 | return NULL; | 311 | return NULL; |
310 | } | 312 | } |
311 | /* fill buffer addresses but pointers are not stored so that | 313 | /* fill buffer addresses but pointers are not stored so that |
@@ -318,14 +320,14 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst | |||
318 | if (idx >= sgbuf->pages) { | 320 | if (idx >= sgbuf->pages) { |
319 | printk(KERN_ERR "emu: pages overflow! (%d-%d) for %d\n", | 321 | printk(KERN_ERR "emu: pages overflow! (%d-%d) for %d\n", |
320 | blk->first_page, blk->last_page, sgbuf->pages); | 322 | blk->first_page, blk->last_page, sgbuf->pages); |
321 | up(&hdr->block_mutex); | 323 | mutex_unlock(&hdr->block_mutex); |
322 | return NULL; | 324 | return NULL; |
323 | } | 325 | } |
324 | #endif | 326 | #endif |
325 | addr = sgbuf->table[idx].addr; | 327 | addr = sgbuf->table[idx].addr; |
326 | if (! is_valid_page(emu, addr)) { | 328 | if (! is_valid_page(emu, addr)) { |
327 | printk(KERN_ERR "emu: failure page = %d\n", idx); | 329 | printk(KERN_ERR "emu: failure page = %d\n", idx); |
328 | up(&hdr->block_mutex); | 330 | mutex_unlock(&hdr->block_mutex); |
329 | return NULL; | 331 | return NULL; |
330 | } | 332 | } |
331 | emu->page_addr_table[page] = addr; | 333 | emu->page_addr_table[page] = addr; |
@@ -337,10 +339,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst | |||
337 | err = snd_emu10k1_memblk_map(emu, blk); | 339 | err = snd_emu10k1_memblk_map(emu, blk); |
338 | if (err < 0) { | 340 | if (err < 0) { |
339 | __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); | 341 | __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); |
340 | up(&hdr->block_mutex); | 342 | mutex_unlock(&hdr->block_mutex); |
341 | return NULL; | 343 | return NULL; |
342 | } | 344 | } |
343 | up(&hdr->block_mutex); | 345 | mutex_unlock(&hdr->block_mutex); |
344 | return (struct snd_util_memblk *)blk; | 346 | return (struct snd_util_memblk *)blk; |
345 | } | 347 | } |
346 | 348 | ||
@@ -369,19 +371,19 @@ snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size) | |||
369 | struct snd_emu10k1_memblk *blk; | 371 | struct snd_emu10k1_memblk *blk; |
370 | struct snd_util_memhdr *hdr = hw->memhdr; | 372 | struct snd_util_memhdr *hdr = hw->memhdr; |
371 | 373 | ||
372 | down(&hdr->block_mutex); | 374 | mutex_lock(&hdr->block_mutex); |
373 | blk = (struct snd_emu10k1_memblk *)__snd_util_mem_alloc(hdr, size); | 375 | blk = (struct snd_emu10k1_memblk *)__snd_util_mem_alloc(hdr, size); |
374 | if (blk == NULL) { | 376 | if (blk == NULL) { |
375 | up(&hdr->block_mutex); | 377 | mutex_unlock(&hdr->block_mutex); |
376 | return NULL; | 378 | return NULL; |
377 | } | 379 | } |
378 | if (synth_alloc_pages(hw, blk)) { | 380 | if (synth_alloc_pages(hw, blk)) { |
379 | __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); | 381 | __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); |
380 | up(&hdr->block_mutex); | 382 | mutex_unlock(&hdr->block_mutex); |
381 | return NULL; | 383 | return NULL; |
382 | } | 384 | } |
383 | snd_emu10k1_memblk_map(hw, blk); | 385 | snd_emu10k1_memblk_map(hw, blk); |
384 | up(&hdr->block_mutex); | 386 | mutex_unlock(&hdr->block_mutex); |
385 | return (struct snd_util_memblk *)blk; | 387 | return (struct snd_util_memblk *)blk; |
386 | } | 388 | } |
387 | 389 | ||
@@ -396,14 +398,14 @@ snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk) | |||
396 | struct snd_emu10k1_memblk *blk = (struct snd_emu10k1_memblk *)memblk; | 398 | struct snd_emu10k1_memblk *blk = (struct snd_emu10k1_memblk *)memblk; |
397 | unsigned long flags; | 399 | unsigned long flags; |
398 | 400 | ||
399 | down(&hdr->block_mutex); | 401 | mutex_lock(&hdr->block_mutex); |
400 | spin_lock_irqsave(&emu->memblk_lock, flags); | 402 | spin_lock_irqsave(&emu->memblk_lock, flags); |
401 | if (blk->mapped_page >= 0) | 403 | if (blk->mapped_page >= 0) |
402 | unmap_memblk(emu, blk); | 404 | unmap_memblk(emu, blk); |
403 | spin_unlock_irqrestore(&emu->memblk_lock, flags); | 405 | spin_unlock_irqrestore(&emu->memblk_lock, flags); |
404 | synth_free_pages(emu, blk); | 406 | synth_free_pages(emu, blk); |
405 | __snd_util_mem_free(hdr, memblk); | 407 | __snd_util_mem_free(hdr, memblk); |
406 | up(&hdr->block_mutex); | 408 | mutex_unlock(&hdr->block_mutex); |
407 | return 0; | 409 | return 0; |
408 | } | 410 | } |
409 | 411 | ||
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 55aaf110331a..a5533c86b0b6 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/gameport.h> | 36 | #include <linux/gameport.h> |
37 | #include <linux/moduleparam.h> | 37 | #include <linux/moduleparam.h> |
38 | #include <linux/mutex.h> | ||
39 | |||
38 | #include <sound/core.h> | 40 | #include <sound/core.h> |
39 | #include <sound/control.h> | 41 | #include <sound/control.h> |
40 | #include <sound/pcm.h> | 42 | #include <sound/pcm.h> |
@@ -379,7 +381,7 @@ MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force)."); | |||
379 | 381 | ||
380 | struct ensoniq { | 382 | struct ensoniq { |
381 | spinlock_t reg_lock; | 383 | spinlock_t reg_lock; |
382 | struct semaphore src_mutex; | 384 | struct mutex src_mutex; |
383 | 385 | ||
384 | int irq; | 386 | int irq; |
385 | 387 | ||
@@ -609,7 +611,7 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, | |||
609 | struct ensoniq *ensoniq = ac97->private_data; | 611 | struct ensoniq *ensoniq = ac97->private_data; |
610 | unsigned int t, x; | 612 | unsigned int t, x; |
611 | 613 | ||
612 | down(&ensoniq->src_mutex); | 614 | mutex_lock(&ensoniq->src_mutex); |
613 | for (t = 0; t < POLL_COUNT; t++) { | 615 | for (t = 0; t < POLL_COUNT; t++) { |
614 | if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { | 616 | if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { |
615 | /* save the current state for latter */ | 617 | /* save the current state for latter */ |
@@ -634,11 +636,11 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97, | |||
634 | /* restore SRC reg */ | 636 | /* restore SRC reg */ |
635 | snd_es1371_wait_src_ready(ensoniq); | 637 | snd_es1371_wait_src_ready(ensoniq); |
636 | outl(x, ES_REG(ensoniq, 1371_SMPRATE)); | 638 | outl(x, ES_REG(ensoniq, 1371_SMPRATE)); |
637 | up(&ensoniq->src_mutex); | 639 | mutex_unlock(&ensoniq->src_mutex); |
638 | return; | 640 | return; |
639 | } | 641 | } |
640 | } | 642 | } |
641 | up(&ensoniq->src_mutex); | 643 | mutex_unlock(&ensoniq->src_mutex); |
642 | snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n", | 644 | snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n", |
643 | ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); | 645 | ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); |
644 | } | 646 | } |
@@ -650,7 +652,7 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, | |||
650 | unsigned int t, x, fail = 0; | 652 | unsigned int t, x, fail = 0; |
651 | 653 | ||
652 | __again: | 654 | __again: |
653 | down(&ensoniq->src_mutex); | 655 | mutex_lock(&ensoniq->src_mutex); |
654 | for (t = 0; t < POLL_COUNT; t++) { | 656 | for (t = 0; t < POLL_COUNT; t++) { |
655 | if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { | 657 | if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { |
656 | /* save the current state for latter */ | 658 | /* save the current state for latter */ |
@@ -683,11 +685,11 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, | |||
683 | /* now wait for the stinkin' data (RDY) */ | 685 | /* now wait for the stinkin' data (RDY) */ |
684 | for (t = 0; t < POLL_COUNT; t++) { | 686 | for (t = 0; t < POLL_COUNT; t++) { |
685 | if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { | 687 | if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { |
686 | up(&ensoniq->src_mutex); | 688 | mutex_unlock(&ensoniq->src_mutex); |
687 | return ES_1371_CODEC_READ(x); | 689 | return ES_1371_CODEC_READ(x); |
688 | } | 690 | } |
689 | } | 691 | } |
690 | up(&ensoniq->src_mutex); | 692 | mutex_unlock(&ensoniq->src_mutex); |
691 | if (++fail > 10) { | 693 | if (++fail > 10) { |
692 | snd_printk(KERN_ERR "codec read timeout (final) " | 694 | snd_printk(KERN_ERR "codec read timeout (final) " |
693 | "at 0x%lx, reg = 0x%x [0x%x]\n", | 695 | "at 0x%lx, reg = 0x%x [0x%x]\n", |
@@ -698,7 +700,7 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, | |||
698 | goto __again; | 700 | goto __again; |
699 | } | 701 | } |
700 | } | 702 | } |
701 | up(&ensoniq->src_mutex); | 703 | mutex_unlock(&ensoniq->src_mutex); |
702 | snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n", | 704 | snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n", |
703 | ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); | 705 | ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); |
704 | return 0; | 706 | return 0; |
@@ -717,7 +719,7 @@ static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate) | |||
717 | { | 719 | { |
718 | unsigned int n, truncm, freq, result; | 720 | unsigned int n, truncm, freq, result; |
719 | 721 | ||
720 | down(&ensoniq->src_mutex); | 722 | mutex_lock(&ensoniq->src_mutex); |
721 | n = rate / 3000; | 723 | n = rate / 3000; |
722 | if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) | 724 | if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) |
723 | n--; | 725 | n--; |
@@ -742,14 +744,14 @@ static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate) | |||
742 | snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); | 744 | snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); |
743 | snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8); | 745 | snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8); |
744 | snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8); | 746 | snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8); |
745 | up(&ensoniq->src_mutex); | 747 | mutex_unlock(&ensoniq->src_mutex); |
746 | } | 748 | } |
747 | 749 | ||
748 | static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) | 750 | static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) |
749 | { | 751 | { |
750 | unsigned int freq, r; | 752 | unsigned int freq, r; |
751 | 753 | ||
752 | down(&ensoniq->src_mutex); | 754 | mutex_lock(&ensoniq->src_mutex); |
753 | freq = ((rate << 15) + 1500) / 3000; | 755 | freq = ((rate << 15) + 1500) / 3000; |
754 | r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | | 756 | r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | |
755 | ES_1371_DIS_P2 | ES_1371_DIS_R1)) | | 757 | ES_1371_DIS_P2 | ES_1371_DIS_R1)) | |
@@ -763,14 +765,14 @@ static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) | |||
763 | r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | | 765 | r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | |
764 | ES_1371_DIS_P2 | ES_1371_DIS_R1)); | 766 | ES_1371_DIS_P2 | ES_1371_DIS_R1)); |
765 | outl(r, ES_REG(ensoniq, 1371_SMPRATE)); | 767 | outl(r, ES_REG(ensoniq, 1371_SMPRATE)); |
766 | up(&ensoniq->src_mutex); | 768 | mutex_unlock(&ensoniq->src_mutex); |
767 | } | 769 | } |
768 | 770 | ||
769 | static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) | 771 | static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) |
770 | { | 772 | { |
771 | unsigned int freq, r; | 773 | unsigned int freq, r; |
772 | 774 | ||
773 | down(&ensoniq->src_mutex); | 775 | mutex_lock(&ensoniq->src_mutex); |
774 | freq = ((rate << 15) + 1500) / 3000; | 776 | freq = ((rate << 15) + 1500) / 3000; |
775 | r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | | 777 | r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | |
776 | ES_1371_DIS_P1 | ES_1371_DIS_R1)) | | 778 | ES_1371_DIS_P1 | ES_1371_DIS_R1)) | |
@@ -785,7 +787,7 @@ static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) | |||
785 | r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | | 787 | r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | |
786 | ES_1371_DIS_P1 | ES_1371_DIS_R1)); | 788 | ES_1371_DIS_P1 | ES_1371_DIS_R1)); |
787 | outl(r, ES_REG(ensoniq, 1371_SMPRATE)); | 789 | outl(r, ES_REG(ensoniq, 1371_SMPRATE)); |
788 | up(&ensoniq->src_mutex); | 790 | mutex_unlock(&ensoniq->src_mutex); |
789 | } | 791 | } |
790 | 792 | ||
791 | #endif /* CHIP1371 */ | 793 | #endif /* CHIP1371 */ |
@@ -2061,6 +2063,13 @@ static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state) | |||
2061 | #ifdef CHIP1371 | 2063 | #ifdef CHIP1371 |
2062 | snd_ac97_suspend(ensoniq->u.es1371.ac97); | 2064 | snd_ac97_suspend(ensoniq->u.es1371.ac97); |
2063 | #else | 2065 | #else |
2066 | /* try to reset AK4531 */ | ||
2067 | outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x02), ES_REG(ensoniq, 1370_CODEC)); | ||
2068 | inw(ES_REG(ensoniq, 1370_CODEC)); | ||
2069 | udelay(100); | ||
2070 | outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x03), ES_REG(ensoniq, 1370_CODEC)); | ||
2071 | inw(ES_REG(ensoniq, 1370_CODEC)); | ||
2072 | udelay(100); | ||
2064 | snd_ak4531_suspend(ensoniq->u.es1370.ak4531); | 2073 | snd_ak4531_suspend(ensoniq->u.es1370.ak4531); |
2065 | #endif | 2074 | #endif |
2066 | pci_set_power_state(pci, PCI_D3hot); | 2075 | pci_set_power_state(pci, PCI_D3hot); |
@@ -2116,7 +2125,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card, | |||
2116 | return -ENOMEM; | 2125 | return -ENOMEM; |
2117 | } | 2126 | } |
2118 | spin_lock_init(&ensoniq->reg_lock); | 2127 | spin_lock_init(&ensoniq->reg_lock); |
2119 | init_MUTEX(&ensoniq->src_mutex); | 2128 | mutex_init(&ensoniq->src_mutex); |
2120 | ensoniq->card = card; | 2129 | ensoniq->card = card; |
2121 | ensoniq->pci = pci; | 2130 | ensoniq->pci = pci; |
2122 | ensoniq->irq = -1; | 2131 | ensoniq->irq = -1; |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 3747a436f0cd..dd465a186e11 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -100,9 +100,12 @@ | |||
100 | #include <linux/interrupt.h> | 100 | #include <linux/interrupt.h> |
101 | #include <linux/init.h> | 101 | #include <linux/init.h> |
102 | #include <linux/pci.h> | 102 | #include <linux/pci.h> |
103 | #include <linux/dma-mapping.h> | ||
103 | #include <linux/slab.h> | 104 | #include <linux/slab.h> |
104 | #include <linux/gameport.h> | 105 | #include <linux/gameport.h> |
105 | #include <linux/moduleparam.h> | 106 | #include <linux/moduleparam.h> |
107 | #include <linux/mutex.h> | ||
108 | |||
106 | #include <sound/core.h> | 109 | #include <sound/core.h> |
107 | #include <sound/pcm.h> | 110 | #include <sound/pcm.h> |
108 | #include <sound/mpu401.h> | 111 | #include <sound/mpu401.h> |
@@ -569,7 +572,7 @@ struct es1968 { | |||
569 | u16 maestro_map[32]; | 572 | u16 maestro_map[32]; |
570 | int bobclient; /* active timer instancs */ | 573 | int bobclient; /* active timer instancs */ |
571 | int bob_freq; /* timer frequency */ | 574 | int bob_freq; /* timer frequency */ |
572 | struct semaphore memory_mutex; /* memory lock */ | 575 | struct mutex memory_mutex; /* memory lock */ |
573 | 576 | ||
574 | /* APU states */ | 577 | /* APU states */ |
575 | unsigned char apu[NR_APUS]; | 578 | unsigned char apu[NR_APUS]; |
@@ -1356,13 +1359,13 @@ static int calc_available_memory_size(struct es1968 *chip) | |||
1356 | struct list_head *p; | 1359 | struct list_head *p; |
1357 | int max_size = 0; | 1360 | int max_size = 0; |
1358 | 1361 | ||
1359 | down(&chip->memory_mutex); | 1362 | mutex_lock(&chip->memory_mutex); |
1360 | list_for_each(p, &chip->buf_list) { | 1363 | list_for_each(p, &chip->buf_list) { |
1361 | struct esm_memory *buf = list_entry(p, struct esm_memory, list); | 1364 | struct esm_memory *buf = list_entry(p, struct esm_memory, list); |
1362 | if (buf->empty && buf->buf.bytes > max_size) | 1365 | if (buf->empty && buf->buf.bytes > max_size) |
1363 | max_size = buf->buf.bytes; | 1366 | max_size = buf->buf.bytes; |
1364 | } | 1367 | } |
1365 | up(&chip->memory_mutex); | 1368 | mutex_unlock(&chip->memory_mutex); |
1366 | if (max_size >= 128*1024) | 1369 | if (max_size >= 128*1024) |
1367 | max_size = 127*1024; | 1370 | max_size = 127*1024; |
1368 | return max_size; | 1371 | return max_size; |
@@ -1375,20 +1378,20 @@ static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size) | |||
1375 | struct list_head *p; | 1378 | struct list_head *p; |
1376 | 1379 | ||
1377 | size = ((size + ESM_MEM_ALIGN - 1) / ESM_MEM_ALIGN) * ESM_MEM_ALIGN; | 1380 | size = ((size + ESM_MEM_ALIGN - 1) / ESM_MEM_ALIGN) * ESM_MEM_ALIGN; |
1378 | down(&chip->memory_mutex); | 1381 | mutex_lock(&chip->memory_mutex); |
1379 | list_for_each(p, &chip->buf_list) { | 1382 | list_for_each(p, &chip->buf_list) { |
1380 | buf = list_entry(p, struct esm_memory, list); | 1383 | buf = list_entry(p, struct esm_memory, list); |
1381 | if (buf->empty && buf->buf.bytes >= size) | 1384 | if (buf->empty && buf->buf.bytes >= size) |
1382 | goto __found; | 1385 | goto __found; |
1383 | } | 1386 | } |
1384 | up(&chip->memory_mutex); | 1387 | mutex_unlock(&chip->memory_mutex); |
1385 | return NULL; | 1388 | return NULL; |
1386 | 1389 | ||
1387 | __found: | 1390 | __found: |
1388 | if (buf->buf.bytes > size) { | 1391 | if (buf->buf.bytes > size) { |
1389 | struct esm_memory *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL); | 1392 | struct esm_memory *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL); |
1390 | if (chunk == NULL) { | 1393 | if (chunk == NULL) { |
1391 | up(&chip->memory_mutex); | 1394 | mutex_unlock(&chip->memory_mutex); |
1392 | return NULL; | 1395 | return NULL; |
1393 | } | 1396 | } |
1394 | chunk->buf = buf->buf; | 1397 | chunk->buf = buf->buf; |
@@ -1400,7 +1403,7 @@ __found: | |||
1400 | list_add(&chunk->list, &buf->list); | 1403 | list_add(&chunk->list, &buf->list); |
1401 | } | 1404 | } |
1402 | buf->empty = 0; | 1405 | buf->empty = 0; |
1403 | up(&chip->memory_mutex); | 1406 | mutex_unlock(&chip->memory_mutex); |
1404 | return buf; | 1407 | return buf; |
1405 | } | 1408 | } |
1406 | 1409 | ||
@@ -1409,7 +1412,7 @@ static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf) | |||
1409 | { | 1412 | { |
1410 | struct esm_memory *chunk; | 1413 | struct esm_memory *chunk; |
1411 | 1414 | ||
1412 | down(&chip->memory_mutex); | 1415 | mutex_lock(&chip->memory_mutex); |
1413 | buf->empty = 1; | 1416 | buf->empty = 1; |
1414 | if (buf->list.prev != &chip->buf_list) { | 1417 | if (buf->list.prev != &chip->buf_list) { |
1415 | chunk = list_entry(buf->list.prev, struct esm_memory, list); | 1418 | chunk = list_entry(buf->list.prev, struct esm_memory, list); |
@@ -1428,7 +1431,7 @@ static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf) | |||
1428 | kfree(chunk); | 1431 | kfree(chunk); |
1429 | } | 1432 | } |
1430 | } | 1433 | } |
1431 | up(&chip->memory_mutex); | 1434 | mutex_unlock(&chip->memory_mutex); |
1432 | } | 1435 | } |
1433 | 1436 | ||
1434 | static void snd_es1968_free_dmabuf(struct es1968 *chip) | 1437 | static void snd_es1968_free_dmabuf(struct es1968 *chip) |
@@ -2559,8 +2562,8 @@ static int __devinit snd_es1968_create(struct snd_card *card, | |||
2559 | if ((err = pci_enable_device(pci)) < 0) | 2562 | if ((err = pci_enable_device(pci)) < 0) |
2560 | return err; | 2563 | return err; |
2561 | /* check, if we can restrict PCI DMA transfers to 28 bits */ | 2564 | /* check, if we can restrict PCI DMA transfers to 28 bits */ |
2562 | if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || | 2565 | if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || |
2563 | pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { | 2566 | pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { |
2564 | snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); | 2567 | snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); |
2565 | pci_disable_device(pci); | 2568 | pci_disable_device(pci); |
2566 | return -ENXIO; | 2569 | return -ENXIO; |
@@ -2579,7 +2582,7 @@ static int __devinit snd_es1968_create(struct snd_card *card, | |||
2579 | INIT_LIST_HEAD(&chip->buf_list); | 2582 | INIT_LIST_HEAD(&chip->buf_list); |
2580 | INIT_LIST_HEAD(&chip->substream_list); | 2583 | INIT_LIST_HEAD(&chip->substream_list); |
2581 | spin_lock_init(&chip->ac97_lock); | 2584 | spin_lock_init(&chip->ac97_lock); |
2582 | init_MUTEX(&chip->memory_mutex); | 2585 | mutex_init(&chip->memory_mutex); |
2583 | tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip); | 2586 | tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip); |
2584 | chip->card = card; | 2587 | chip->card = card; |
2585 | chip->pci = pci; | 2588 | chip->pci = pci; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4a6dd97deba6..b42dff7ceed0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
28 | #include <linux/mutex.h> | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
30 | #include <sound/asoundef.h> | 31 | #include <sound/asoundef.h> |
@@ -76,12 +77,12 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int dire | |||
76 | unsigned int verb, unsigned int parm) | 77 | unsigned int verb, unsigned int parm) |
77 | { | 78 | { |
78 | unsigned int res; | 79 | unsigned int res; |
79 | down(&codec->bus->cmd_mutex); | 80 | mutex_lock(&codec->bus->cmd_mutex); |
80 | if (! codec->bus->ops.command(codec, nid, direct, verb, parm)) | 81 | if (! codec->bus->ops.command(codec, nid, direct, verb, parm)) |
81 | res = codec->bus->ops.get_response(codec); | 82 | res = codec->bus->ops.get_response(codec); |
82 | else | 83 | else |
83 | res = (unsigned int)-1; | 84 | res = (unsigned int)-1; |
84 | up(&codec->bus->cmd_mutex); | 85 | mutex_unlock(&codec->bus->cmd_mutex); |
85 | return res; | 86 | return res; |
86 | } | 87 | } |
87 | 88 | ||
@@ -101,9 +102,9 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
101 | unsigned int verb, unsigned int parm) | 102 | unsigned int verb, unsigned int parm) |
102 | { | 103 | { |
103 | int err; | 104 | int err; |
104 | down(&codec->bus->cmd_mutex); | 105 | mutex_lock(&codec->bus->cmd_mutex); |
105 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | 106 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); |
106 | up(&codec->bus->cmd_mutex); | 107 | mutex_unlock(&codec->bus->cmd_mutex); |
107 | return err; | 108 | return err; |
108 | } | 109 | } |
109 | 110 | ||
@@ -371,7 +372,7 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, | |||
371 | bus->modelname = temp->modelname; | 372 | bus->modelname = temp->modelname; |
372 | bus->ops = temp->ops; | 373 | bus->ops = temp->ops; |
373 | 374 | ||
374 | init_MUTEX(&bus->cmd_mutex); | 375 | mutex_init(&bus->cmd_mutex); |
375 | INIT_LIST_HEAD(&bus->codec_list); | 376 | INIT_LIST_HEAD(&bus->codec_list); |
376 | 377 | ||
377 | if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { | 378 | if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { |
@@ -523,13 +524,19 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
523 | 524 | ||
524 | codec->bus = bus; | 525 | codec->bus = bus; |
525 | codec->addr = codec_addr; | 526 | codec->addr = codec_addr; |
526 | init_MUTEX(&codec->spdif_mutex); | 527 | mutex_init(&codec->spdif_mutex); |
527 | init_amp_hash(codec); | 528 | init_amp_hash(codec); |
528 | 529 | ||
529 | list_add_tail(&codec->list, &bus->codec_list); | 530 | list_add_tail(&codec->list, &bus->codec_list); |
530 | bus->caddr_tbl[codec_addr] = codec; | 531 | bus->caddr_tbl[codec_addr] = codec; |
531 | 532 | ||
532 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID); | 533 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID); |
534 | if (codec->vendor_id == -1) | ||
535 | /* read again, hopefully the access method was corrected | ||
536 | * in the last read... | ||
537 | */ | ||
538 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, | ||
539 | AC_PAR_VENDOR_ID); | ||
533 | codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID); | 540 | codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID); |
534 | codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID); | 541 | codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID); |
535 | 542 | ||
@@ -722,7 +729,8 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, | |||
722 | /* | 729 | /* |
723 | * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. | 730 | * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. |
724 | */ | 731 | */ |
725 | static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index) | 732 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, |
733 | int direction, int index) | ||
726 | { | 734 | { |
727 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); | 735 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); |
728 | if (! info) | 736 | if (! info) |
@@ -733,7 +741,8 @@ static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch | |||
733 | /* | 741 | /* |
734 | * update the AMP value, mask = bit mask to set, val = the value | 742 | * update the AMP value, mask = bit mask to set, val = the value |
735 | */ | 743 | */ |
736 | static int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int mask, int val) | 744 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, |
745 | int direction, int idx, int mask, int val) | ||
737 | { | 746 | { |
738 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); | 747 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); |
739 | 748 | ||
@@ -881,12 +890,12 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
881 | unsigned long pval; | 890 | unsigned long pval; |
882 | int err; | 891 | int err; |
883 | 892 | ||
884 | down(&codec->spdif_mutex); /* reuse spdif_mutex */ | 893 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ |
885 | pval = kcontrol->private_value; | 894 | pval = kcontrol->private_value; |
886 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ | 895 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ |
887 | err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | 896 | err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); |
888 | kcontrol->private_value = pval; | 897 | kcontrol->private_value = pval; |
889 | up(&codec->spdif_mutex); | 898 | mutex_unlock(&codec->spdif_mutex); |
890 | return err; | 899 | return err; |
891 | } | 900 | } |
892 | 901 | ||
@@ -896,7 +905,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
896 | unsigned long pval; | 905 | unsigned long pval; |
897 | int i, indices, err = 0, change = 0; | 906 | int i, indices, err = 0, change = 0; |
898 | 907 | ||
899 | down(&codec->spdif_mutex); /* reuse spdif_mutex */ | 908 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ |
900 | pval = kcontrol->private_value; | 909 | pval = kcontrol->private_value; |
901 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; | 910 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; |
902 | for (i = 0; i < indices; i++) { | 911 | for (i = 0; i < indices; i++) { |
@@ -907,7 +916,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
907 | change |= err; | 916 | change |= err; |
908 | } | 917 | } |
909 | kcontrol->private_value = pval; | 918 | kcontrol->private_value = pval; |
910 | up(&codec->spdif_mutex); | 919 | mutex_unlock(&codec->spdif_mutex); |
911 | return err < 0 ? err : change; | 920 | return err < 0 ? err : change; |
912 | } | 921 | } |
913 | 922 | ||
@@ -1011,7 +1020,7 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_c | |||
1011 | unsigned short val; | 1020 | unsigned short val; |
1012 | int change; | 1021 | int change; |
1013 | 1022 | ||
1014 | down(&codec->spdif_mutex); | 1023 | mutex_lock(&codec->spdif_mutex); |
1015 | codec->spdif_status = ucontrol->value.iec958.status[0] | | 1024 | codec->spdif_status = ucontrol->value.iec958.status[0] | |
1016 | ((unsigned int)ucontrol->value.iec958.status[1] << 8) | | 1025 | ((unsigned int)ucontrol->value.iec958.status[1] << 8) | |
1017 | ((unsigned int)ucontrol->value.iec958.status[2] << 16) | | 1026 | ((unsigned int)ucontrol->value.iec958.status[2] << 16) | |
@@ -1026,7 +1035,7 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_c | |||
1026 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8); | 1035 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8); |
1027 | } | 1036 | } |
1028 | 1037 | ||
1029 | up(&codec->spdif_mutex); | 1038 | mutex_unlock(&codec->spdif_mutex); |
1030 | return change; | 1039 | return change; |
1031 | } | 1040 | } |
1032 | 1041 | ||
@@ -1054,7 +1063,7 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct sn | |||
1054 | unsigned short val; | 1063 | unsigned short val; |
1055 | int change; | 1064 | int change; |
1056 | 1065 | ||
1057 | down(&codec->spdif_mutex); | 1066 | mutex_lock(&codec->spdif_mutex); |
1058 | val = codec->spdif_ctls & ~1; | 1067 | val = codec->spdif_ctls & ~1; |
1059 | if (ucontrol->value.integer.value[0]) | 1068 | if (ucontrol->value.integer.value[0]) |
1060 | val |= 1; | 1069 | val |= 1; |
@@ -1066,7 +1075,7 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct sn | |||
1066 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | | 1075 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | |
1067 | AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80)); | 1076 | AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80)); |
1068 | } | 1077 | } |
1069 | up(&codec->spdif_mutex); | 1078 | mutex_unlock(&codec->spdif_mutex); |
1070 | return change; | 1079 | return change; |
1071 | } | 1080 | } |
1072 | 1081 | ||
@@ -1150,13 +1159,13 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd | |||
1150 | unsigned int val = !!ucontrol->value.integer.value[0]; | 1159 | unsigned int val = !!ucontrol->value.integer.value[0]; |
1151 | int change; | 1160 | int change; |
1152 | 1161 | ||
1153 | down(&codec->spdif_mutex); | 1162 | mutex_lock(&codec->spdif_mutex); |
1154 | change = codec->spdif_in_enable != val; | 1163 | change = codec->spdif_in_enable != val; |
1155 | if (change || codec->in_resume) { | 1164 | if (change || codec->in_resume) { |
1156 | codec->spdif_in_enable = val; | 1165 | codec->spdif_in_enable = val; |
1157 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val); | 1166 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val); |
1158 | } | 1167 | } |
1159 | up(&codec->spdif_mutex); | 1168 | mutex_unlock(&codec->spdif_mutex); |
1160 | return change; | 1169 | return change; |
1161 | } | 1170 | } |
1162 | 1171 | ||
@@ -1824,13 +1833,13 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i | |||
1824 | */ | 1833 | */ |
1825 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout) | 1834 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout) |
1826 | { | 1835 | { |
1827 | down(&codec->spdif_mutex); | 1836 | mutex_lock(&codec->spdif_mutex); |
1828 | if (mout->dig_out_used) { | 1837 | if (mout->dig_out_used) { |
1829 | up(&codec->spdif_mutex); | 1838 | mutex_unlock(&codec->spdif_mutex); |
1830 | return -EBUSY; /* already being used */ | 1839 | return -EBUSY; /* already being used */ |
1831 | } | 1840 | } |
1832 | mout->dig_out_used = HDA_DIG_EXCLUSIVE; | 1841 | mout->dig_out_used = HDA_DIG_EXCLUSIVE; |
1833 | up(&codec->spdif_mutex); | 1842 | mutex_unlock(&codec->spdif_mutex); |
1834 | return 0; | 1843 | return 0; |
1835 | } | 1844 | } |
1836 | 1845 | ||
@@ -1839,9 +1848,9 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mo | |||
1839 | */ | 1848 | */ |
1840 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout) | 1849 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout) |
1841 | { | 1850 | { |
1842 | down(&codec->spdif_mutex); | 1851 | mutex_lock(&codec->spdif_mutex); |
1843 | mout->dig_out_used = 0; | 1852 | mout->dig_out_used = 0; |
1844 | up(&codec->spdif_mutex); | 1853 | mutex_unlock(&codec->spdif_mutex); |
1845 | return 0; | 1854 | return 0; |
1846 | } | 1855 | } |
1847 | 1856 | ||
@@ -1869,7 +1878,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1869 | int chs = substream->runtime->channels; | 1878 | int chs = substream->runtime->channels; |
1870 | int i; | 1879 | int i; |
1871 | 1880 | ||
1872 | down(&codec->spdif_mutex); | 1881 | mutex_lock(&codec->spdif_mutex); |
1873 | if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { | 1882 | if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { |
1874 | if (chs == 2 && | 1883 | if (chs == 2 && |
1875 | snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && | 1884 | snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && |
@@ -1883,13 +1892,20 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1883 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); | 1892 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); |
1884 | } | 1893 | } |
1885 | } | 1894 | } |
1886 | up(&codec->spdif_mutex); | 1895 | mutex_unlock(&codec->spdif_mutex); |
1887 | 1896 | ||
1888 | /* front */ | 1897 | /* front */ |
1889 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); | 1898 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); |
1890 | if (mout->hp_nid) | 1899 | if (mout->hp_nid) |
1891 | /* headphone out will just decode front left/right (stereo) */ | 1900 | /* headphone out will just decode front left/right (stereo) */ |
1892 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); | 1901 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); |
1902 | /* extra outputs copied from front */ | ||
1903 | for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) | ||
1904 | if (mout->extra_out_nid[i]) | ||
1905 | snd_hda_codec_setup_stream(codec, | ||
1906 | mout->extra_out_nid[i], | ||
1907 | stream_tag, 0, format); | ||
1908 | |||
1893 | /* surrounds */ | 1909 | /* surrounds */ |
1894 | for (i = 1; i < mout->num_dacs; i++) { | 1910 | for (i = 1; i < mout->num_dacs; i++) { |
1895 | if (chs >= (i + 1) * 2) /* independent out */ | 1911 | if (chs >= (i + 1) * 2) /* independent out */ |
@@ -1914,12 +1930,17 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o | |||
1914 | snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); | 1930 | snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); |
1915 | if (mout->hp_nid) | 1931 | if (mout->hp_nid) |
1916 | snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0); | 1932 | snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0); |
1917 | down(&codec->spdif_mutex); | 1933 | for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) |
1934 | if (mout->extra_out_nid[i]) | ||
1935 | snd_hda_codec_setup_stream(codec, | ||
1936 | mout->extra_out_nid[i], | ||
1937 | 0, 0, 0); | ||
1938 | mutex_lock(&codec->spdif_mutex); | ||
1918 | if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { | 1939 | if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { |
1919 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); | 1940 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); |
1920 | mout->dig_out_used = 0; | 1941 | mout->dig_out_used = 0; |
1921 | } | 1942 | } |
1922 | up(&codec->spdif_mutex); | 1943 | mutex_unlock(&codec->spdif_mutex); |
1923 | return 0; | 1944 | return 0; |
1924 | } | 1945 | } |
1925 | 1946 | ||
@@ -1935,13 +1956,29 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
1935 | return 0; | 1956 | return 0; |
1936 | } | 1957 | } |
1937 | 1958 | ||
1938 | /* parse all pin widgets and store the useful pin nids to cfg */ | 1959 | /* |
1960 | * Parse all pin widgets and store the useful pin nids to cfg | ||
1961 | * | ||
1962 | * The number of line-outs or any primary output is stored in line_outs, | ||
1963 | * and the corresponding output pins are assigned to line_out_pins[], | ||
1964 | * in the order of front, rear, CLFE, side, ... | ||
1965 | * | ||
1966 | * If more extra outputs (speaker and headphone) are found, the pins are | ||
1967 | * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack | ||
1968 | * is detected, one of speaker of HP pins is assigned as the primary | ||
1969 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | ||
1970 | * if any analog output exists. | ||
1971 | * | ||
1972 | * The analog input pins are assigned to input_pins array. | ||
1973 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | ||
1974 | * respectively. | ||
1975 | */ | ||
1939 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, | 1976 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, |
1940 | hda_nid_t *ignore_nids) | 1977 | hda_nid_t *ignore_nids) |
1941 | { | 1978 | { |
1942 | hda_nid_t nid, nid_start; | 1979 | hda_nid_t nid, nid_start; |
1943 | int i, j, nodes; | 1980 | int i, j, nodes; |
1944 | short seq, sequences[4], assoc_line_out; | 1981 | short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)]; |
1945 | 1982 | ||
1946 | memset(cfg, 0, sizeof(*cfg)); | 1983 | memset(cfg, 0, sizeof(*cfg)); |
1947 | 1984 | ||
@@ -1983,7 +2020,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
1983 | cfg->line_outs++; | 2020 | cfg->line_outs++; |
1984 | break; | 2021 | break; |
1985 | case AC_JACK_SPEAKER: | 2022 | case AC_JACK_SPEAKER: |
1986 | cfg->speaker_pin = nid; | 2023 | if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) |
2024 | continue; | ||
2025 | cfg->speaker_pins[cfg->speaker_outs] = nid; | ||
2026 | cfg->speaker_outs++; | ||
1987 | break; | 2027 | break; |
1988 | case AC_JACK_HP_OUT: | 2028 | case AC_JACK_HP_OUT: |
1989 | cfg->hp_pin = nid; | 2029 | cfg->hp_pin = nid; |
@@ -2048,6 +2088,46 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2048 | break; | 2088 | break; |
2049 | } | 2089 | } |
2050 | 2090 | ||
2091 | /* | ||
2092 | * debug prints of the parsed results | ||
2093 | */ | ||
2094 | snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | ||
2095 | cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1], | ||
2096 | cfg->line_out_pins[2], cfg->line_out_pins[3], | ||
2097 | cfg->line_out_pins[4]); | ||
2098 | snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | ||
2099 | cfg->speaker_outs, cfg->speaker_pins[0], | ||
2100 | cfg->speaker_pins[1], cfg->speaker_pins[2], | ||
2101 | cfg->speaker_pins[3], cfg->speaker_pins[4]); | ||
2102 | snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", | ||
2103 | cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); | ||
2104 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | ||
2105 | " cd=0x%x, aux=0x%x\n", | ||
2106 | cfg->input_pins[AUTO_PIN_MIC], | ||
2107 | cfg->input_pins[AUTO_PIN_FRONT_MIC], | ||
2108 | cfg->input_pins[AUTO_PIN_LINE], | ||
2109 | cfg->input_pins[AUTO_PIN_FRONT_LINE], | ||
2110 | cfg->input_pins[AUTO_PIN_CD], | ||
2111 | cfg->input_pins[AUTO_PIN_AUX]); | ||
2112 | |||
2113 | /* | ||
2114 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | ||
2115 | * as a primary output | ||
2116 | */ | ||
2117 | if (! cfg->line_outs) { | ||
2118 | if (cfg->speaker_outs) { | ||
2119 | cfg->line_outs = cfg->speaker_outs; | ||
2120 | memcpy(cfg->line_out_pins, cfg->speaker_pins, | ||
2121 | sizeof(cfg->speaker_pins)); | ||
2122 | cfg->speaker_outs = 0; | ||
2123 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | ||
2124 | } else if (cfg->hp_pin) { | ||
2125 | cfg->line_outs = 1; | ||
2126 | cfg->line_out_pins[0] = cfg->hp_pin; | ||
2127 | cfg->hp_pin = 0; | ||
2128 | } | ||
2129 | } | ||
2130 | |||
2051 | return 0; | 2131 | return 0; |
2052 | } | 2132 | } |
2053 | 2133 | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 63e26c7a2b7a..40520e9d5a4b 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -438,7 +438,7 @@ struct hda_bus { | |||
438 | struct list_head codec_list; | 438 | struct list_head codec_list; |
439 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */ | 439 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */ |
440 | 440 | ||
441 | struct semaphore cmd_mutex; | 441 | struct mutex cmd_mutex; |
442 | 442 | ||
443 | /* unsolicited event queue */ | 443 | /* unsolicited event queue */ |
444 | struct hda_bus_unsolicited *unsol; | 444 | struct hda_bus_unsolicited *unsol; |
@@ -559,7 +559,7 @@ struct hda_codec { | |||
559 | int amp_info_size; | 559 | int amp_info_size; |
560 | struct hda_amp_info *amp_info; | 560 | struct hda_amp_info *amp_info; |
561 | 561 | ||
562 | struct semaphore spdif_mutex; | 562 | struct mutex spdif_mutex; |
563 | unsigned int spdif_status; /* IEC958 status bits */ | 563 | unsigned int spdif_status; /* IEC958 status bits */ |
564 | unsigned short spdif_ctls; /* SPDIF control bits */ | 564 | unsigned short spdif_ctls; /* SPDIF control bits */ |
565 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 565 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 39edfcfd3abd..85ad164ada59 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -47,10 +47,10 @@ struct hda_gnode { | |||
47 | 47 | ||
48 | /* patch-specific record */ | 48 | /* patch-specific record */ |
49 | struct hda_gspec { | 49 | struct hda_gspec { |
50 | struct hda_gnode *dac_node; /* DAC node */ | 50 | struct hda_gnode *dac_node[2]; /* DAC node */ |
51 | struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */ | 51 | struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ |
52 | struct hda_gnode *pcm_vol_node; /* Node for PCM volume */ | 52 | struct hda_gnode *pcm_vol_node[2]; /* Node for PCM volume */ |
53 | unsigned int pcm_vol_index; /* connection of PCM volume */ | 53 | unsigned int pcm_vol_index[2]; /* connection of PCM volume */ |
54 | 54 | ||
55 | struct hda_gnode *adc_node; /* ADC node */ | 55 | struct hda_gnode *adc_node; /* ADC node */ |
56 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ | 56 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ |
@@ -69,8 +69,12 @@ struct hda_gspec { | |||
69 | /* | 69 | /* |
70 | * retrieve the default device type from the default config value | 70 | * retrieve the default device type from the default config value |
71 | */ | 71 | */ |
72 | #define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | 72 | #define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> \ |
73 | #define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | 73 | AC_DEFCFG_DEVICE_SHIFT) |
74 | #define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> \ | ||
75 | AC_DEFCFG_LOCATION_SHIFT) | ||
76 | #define defcfg_port_conn(node) (((node)->def_cfg & AC_DEFCFG_PORT_CONN) >> \ | ||
77 | AC_DEFCFG_PORT_CONN_SHIFT) | ||
74 | 78 | ||
75 | /* | 79 | /* |
76 | * destructor | 80 | * destructor |
@@ -261,7 +265,7 @@ static void clear_check_flags(struct hda_gspec *spec) | |||
261 | * returns 0 if not found, 1 if found, or a negative error code. | 265 | * returns 0 if not found, 1 if found, or a negative error code. |
262 | */ | 266 | */ |
263 | static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | 267 | static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, |
264 | struct hda_gnode *node) | 268 | struct hda_gnode *node, int dac_idx) |
265 | { | 269 | { |
266 | int i, err; | 270 | int i, err; |
267 | struct hda_gnode *child; | 271 | struct hda_gnode *child; |
@@ -276,14 +280,14 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
276 | return 0; | 280 | return 0; |
277 | } | 281 | } |
278 | snd_printdd("AUD_OUT found %x\n", node->nid); | 282 | snd_printdd("AUD_OUT found %x\n", node->nid); |
279 | if (spec->dac_node) { | 283 | if (spec->dac_node[dac_idx]) { |
280 | /* already DAC node is assigned, just unmute & connect */ | 284 | /* already DAC node is assigned, just unmute & connect */ |
281 | return node == spec->dac_node; | 285 | return node == spec->dac_node[dac_idx]; |
282 | } | 286 | } |
283 | spec->dac_node = node; | 287 | spec->dac_node[dac_idx] = node; |
284 | if (node->wid_caps & AC_WCAP_OUT_AMP) { | 288 | if (node->wid_caps & AC_WCAP_OUT_AMP) { |
285 | spec->pcm_vol_node = node; | 289 | spec->pcm_vol_node[dac_idx] = node; |
286 | spec->pcm_vol_index = 0; | 290 | spec->pcm_vol_index[dac_idx] = 0; |
287 | } | 291 | } |
288 | return 1; /* found */ | 292 | return 1; /* found */ |
289 | } | 293 | } |
@@ -292,7 +296,7 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
292 | child = hda_get_node(spec, node->conn_list[i]); | 296 | child = hda_get_node(spec, node->conn_list[i]); |
293 | if (! child) | 297 | if (! child) |
294 | continue; | 298 | continue; |
295 | err = parse_output_path(codec, spec, child); | 299 | err = parse_output_path(codec, spec, child, dac_idx); |
296 | if (err < 0) | 300 | if (err < 0) |
297 | return err; | 301 | return err; |
298 | else if (err > 0) { | 302 | else if (err > 0) { |
@@ -303,13 +307,13 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
303 | select_input_connection(codec, node, i); | 307 | select_input_connection(codec, node, i); |
304 | unmute_input(codec, node, i); | 308 | unmute_input(codec, node, i); |
305 | unmute_output(codec, node); | 309 | unmute_output(codec, node); |
306 | if (! spec->pcm_vol_node) { | 310 | if (! spec->pcm_vol_node[dac_idx]) { |
307 | if (node->wid_caps & AC_WCAP_IN_AMP) { | 311 | if (node->wid_caps & AC_WCAP_IN_AMP) { |
308 | spec->pcm_vol_node = node; | 312 | spec->pcm_vol_node[dac_idx] = node; |
309 | spec->pcm_vol_index = i; | 313 | spec->pcm_vol_index[dac_idx] = i; |
310 | } else if (node->wid_caps & AC_WCAP_OUT_AMP) { | 314 | } else if (node->wid_caps & AC_WCAP_OUT_AMP) { |
311 | spec->pcm_vol_node = node; | 315 | spec->pcm_vol_node[dac_idx] = node; |
312 | spec->pcm_vol_index = 0; | 316 | spec->pcm_vol_index[dac_idx] = 0; |
313 | } | 317 | } |
314 | } | 318 | } |
315 | return 1; | 319 | return 1; |
@@ -339,6 +343,8 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
339 | /* output capable? */ | 343 | /* output capable? */ |
340 | if (! (node->pin_caps & AC_PINCAP_OUT)) | 344 | if (! (node->pin_caps & AC_PINCAP_OUT)) |
341 | continue; | 345 | continue; |
346 | if (defcfg_port_conn(node) == AC_JACK_PORT_NONE) | ||
347 | continue; /* unconnected */ | ||
342 | if (jack_type >= 0) { | 348 | if (jack_type >= 0) { |
343 | if (jack_type != defcfg_type(node)) | 349 | if (jack_type != defcfg_type(node)) |
344 | continue; | 350 | continue; |
@@ -350,10 +356,15 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
350 | continue; | 356 | continue; |
351 | } | 357 | } |
352 | clear_check_flags(spec); | 358 | clear_check_flags(spec); |
353 | err = parse_output_path(codec, spec, node); | 359 | err = parse_output_path(codec, spec, node, 0); |
354 | if (err < 0) | 360 | if (err < 0) |
355 | return NULL; | 361 | return NULL; |
356 | else if (err > 0) { | 362 | if (! err && spec->out_pin_node[0]) { |
363 | err = parse_output_path(codec, spec, node, 1); | ||
364 | if (err < 0) | ||
365 | return NULL; | ||
366 | } | ||
367 | if (err > 0) { | ||
357 | /* unmute the PIN output */ | 368 | /* unmute the PIN output */ |
358 | unmute_output(codec, node); | 369 | unmute_output(codec, node); |
359 | /* set PIN-Out enable */ | 370 | /* set PIN-Out enable */ |
@@ -381,20 +392,28 @@ static int parse_output(struct hda_codec *codec) | |||
381 | /* first, look for the line-out pin */ | 392 | /* first, look for the line-out pin */ |
382 | node = parse_output_jack(codec, spec, AC_JACK_LINE_OUT); | 393 | node = parse_output_jack(codec, spec, AC_JACK_LINE_OUT); |
383 | if (node) /* found, remember the PIN node */ | 394 | if (node) /* found, remember the PIN node */ |
384 | spec->out_pin_node = node; | 395 | spec->out_pin_node[0] = node; |
396 | else { | ||
397 | /* if no line-out is found, try speaker out */ | ||
398 | node = parse_output_jack(codec, spec, AC_JACK_SPEAKER); | ||
399 | if (node) | ||
400 | spec->out_pin_node[0] = node; | ||
401 | } | ||
385 | /* look for the HP-out pin */ | 402 | /* look for the HP-out pin */ |
386 | node = parse_output_jack(codec, spec, AC_JACK_HP_OUT); | 403 | node = parse_output_jack(codec, spec, AC_JACK_HP_OUT); |
387 | if (node) { | 404 | if (node) { |
388 | if (! spec->out_pin_node) | 405 | if (! spec->out_pin_node[0]) |
389 | spec->out_pin_node = node; | 406 | spec->out_pin_node[0] = node; |
407 | else | ||
408 | spec->out_pin_node[1] = node; | ||
390 | } | 409 | } |
391 | 410 | ||
392 | if (! spec->out_pin_node) { | 411 | if (! spec->out_pin_node[0]) { |
393 | /* no line-out or HP pins found, | 412 | /* no line-out or HP pins found, |
394 | * then choose for the first output pin | 413 | * then choose for the first output pin |
395 | */ | 414 | */ |
396 | spec->out_pin_node = parse_output_jack(codec, spec, -1); | 415 | spec->out_pin_node[0] = parse_output_jack(codec, spec, -1); |
397 | if (! spec->out_pin_node) | 416 | if (! spec->out_pin_node[0]) |
398 | snd_printd("hda_generic: no proper output path found\n"); | 417 | snd_printd("hda_generic: no proper output path found\n"); |
399 | } | 418 | } |
400 | 419 | ||
@@ -505,6 +524,9 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
505 | if (! (node->pin_caps & AC_PINCAP_IN)) | 524 | if (! (node->pin_caps & AC_PINCAP_IN)) |
506 | return 0; | 525 | return 0; |
507 | 526 | ||
527 | if (defcfg_port_conn(node) == AC_JACK_PORT_NONE) | ||
528 | return 0; /* unconnected */ | ||
529 | |||
508 | if (node->wid_caps & AC_WCAP_DIGITAL) | 530 | if (node->wid_caps & AC_WCAP_DIGITAL) |
509 | return 0; /* skip SPDIF */ | 531 | return 0; /* skip SPDIF */ |
510 | 532 | ||
@@ -703,12 +725,16 @@ static int check_existing_control(struct hda_codec *codec, const char *type, con | |||
703 | static int build_output_controls(struct hda_codec *codec) | 725 | static int build_output_controls(struct hda_codec *codec) |
704 | { | 726 | { |
705 | struct hda_gspec *spec = codec->spec; | 727 | struct hda_gspec *spec = codec->spec; |
706 | int err; | 728 | static const char *types[2] = { "Master", "Headphone" }; |
729 | int i, err; | ||
707 | 730 | ||
708 | err = create_mixer(codec, spec->pcm_vol_node, spec->pcm_vol_index, | 731 | for (i = 0; i < 2 && spec->pcm_vol_node[i]; i++) { |
709 | "PCM", "Playback"); | 732 | err = create_mixer(codec, spec->pcm_vol_node[i], |
710 | if (err < 0) | 733 | spec->pcm_vol_index[i], |
711 | return err; | 734 | types[i], "Playback"); |
735 | if (err < 0) | ||
736 | return err; | ||
737 | } | ||
712 | return 0; | 738 | return 0; |
713 | } | 739 | } |
714 | 740 | ||
@@ -805,7 +831,7 @@ static int build_loopback_controls(struct hda_codec *codec) | |||
805 | int err; | 831 | int err; |
806 | const char *type; | 832 | const char *type; |
807 | 833 | ||
808 | if (! spec->out_pin_node) | 834 | if (! spec->out_pin_node[0]) |
809 | return 0; | 835 | return 0; |
810 | 836 | ||
811 | list_for_each(p, &spec->nid_list) { | 837 | list_for_each(p, &spec->nid_list) { |
@@ -820,7 +846,8 @@ static int build_loopback_controls(struct hda_codec *codec) | |||
820 | if (check_existing_control(codec, type, "Playback")) | 846 | if (check_existing_control(codec, type, "Playback")) |
821 | continue; | 847 | continue; |
822 | clear_check_flags(spec); | 848 | clear_check_flags(spec); |
823 | err = parse_loopback_path(codec, spec, spec->out_pin_node, | 849 | err = parse_loopback_path(codec, spec, |
850 | spec->out_pin_node[0], | ||
824 | node, type); | 851 | node, type); |
825 | if (err < 0) | 852 | if (err < 0) |
826 | return err; | 853 | return err; |
@@ -855,12 +882,37 @@ static struct hda_pcm_stream generic_pcm_playback = { | |||
855 | .channels_max = 2, | 882 | .channels_max = 2, |
856 | }; | 883 | }; |
857 | 884 | ||
885 | static int generic_pcm2_prepare(struct hda_pcm_stream *hinfo, | ||
886 | struct hda_codec *codec, | ||
887 | unsigned int stream_tag, | ||
888 | unsigned int format, | ||
889 | struct snd_pcm_substream *substream) | ||
890 | { | ||
891 | struct hda_gspec *spec = codec->spec; | ||
892 | |||
893 | snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format); | ||
894 | snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, | ||
895 | stream_tag, 0, format); | ||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | static int generic_pcm2_cleanup(struct hda_pcm_stream *hinfo, | ||
900 | struct hda_codec *codec, | ||
901 | struct snd_pcm_substream *substream) | ||
902 | { | ||
903 | struct hda_gspec *spec = codec->spec; | ||
904 | |||
905 | snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0); | ||
906 | snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, 0, 0, 0); | ||
907 | return 0; | ||
908 | } | ||
909 | |||
858 | static int build_generic_pcms(struct hda_codec *codec) | 910 | static int build_generic_pcms(struct hda_codec *codec) |
859 | { | 911 | { |
860 | struct hda_gspec *spec = codec->spec; | 912 | struct hda_gspec *spec = codec->spec; |
861 | struct hda_pcm *info = &spec->pcm_rec; | 913 | struct hda_pcm *info = &spec->pcm_rec; |
862 | 914 | ||
863 | if (! spec->dac_node && ! spec->adc_node) { | 915 | if (! spec->dac_node[0] && ! spec->adc_node) { |
864 | snd_printd("hda_generic: no PCM found\n"); | 916 | snd_printd("hda_generic: no PCM found\n"); |
865 | return 0; | 917 | return 0; |
866 | } | 918 | } |
@@ -869,9 +921,13 @@ static int build_generic_pcms(struct hda_codec *codec) | |||
869 | codec->pcm_info = info; | 921 | codec->pcm_info = info; |
870 | 922 | ||
871 | info->name = "HDA Generic"; | 923 | info->name = "HDA Generic"; |
872 | if (spec->dac_node) { | 924 | if (spec->dac_node[0]) { |
873 | info->stream[0] = generic_pcm_playback; | 925 | info->stream[0] = generic_pcm_playback; |
874 | info->stream[0].nid = spec->dac_node->nid; | 926 | info->stream[0].nid = spec->dac_node[0]->nid; |
927 | if (spec->dac_node[1]) { | ||
928 | info->stream[0].ops.prepare = generic_pcm2_prepare; | ||
929 | info->stream[0].ops.cleanup = generic_pcm2_cleanup; | ||
930 | } | ||
875 | } | 931 | } |
876 | if (spec->adc_node) { | 932 | if (spec->adc_node) { |
877 | info->stream[1] = generic_pcm_playback; | 933 | info->stream[1] = generic_pcm_playback; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fd12b6991fe4..c096606970ff 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/init.h> | 43 | #include <linux/init.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/pci.h> | 45 | #include <linux/pci.h> |
46 | #include <linux/mutex.h> | ||
46 | #include <sound/core.h> | 47 | #include <sound/core.h> |
47 | #include <sound/initval.h> | 48 | #include <sound/initval.h> |
48 | #include "hda_codec.h" | 49 | #include "hda_codec.h" |
@@ -53,6 +54,7 @@ static char *id = SNDRV_DEFAULT_STR1; | |||
53 | static char *model; | 54 | static char *model; |
54 | static int position_fix; | 55 | static int position_fix; |
55 | static int probe_mask = -1; | 56 | static int probe_mask = -1; |
57 | static int single_cmd; | ||
56 | 58 | ||
57 | module_param(index, int, 0444); | 59 | module_param(index, int, 0444); |
58 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); | 60 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); |
@@ -64,6 +66,8 @@ module_param(position_fix, int, 0444); | |||
64 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); | 66 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); |
65 | module_param(probe_mask, int, 0444); | 67 | module_param(probe_mask, int, 0444); |
66 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); | 68 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); |
69 | module_param(single_cmd, bool, 0444); | ||
70 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); | ||
67 | 71 | ||
68 | 72 | ||
69 | /* just for backward compatibility */ | 73 | /* just for backward compatibility */ |
@@ -235,12 +239,6 @@ enum { | |||
235 | #define NVIDIA_HDA_ENABLE_COHBITS 0x0f | 239 | #define NVIDIA_HDA_ENABLE_COHBITS 0x0f |
236 | 240 | ||
237 | /* | 241 | /* |
238 | * Use CORB/RIRB for communication from/to codecs. | ||
239 | * This is the way recommended by Intel (see below). | ||
240 | */ | ||
241 | #define USE_CORB_RIRB | ||
242 | |||
243 | /* | ||
244 | */ | 242 | */ |
245 | 243 | ||
246 | struct azx_dev { | 244 | struct azx_dev { |
@@ -252,7 +250,6 @@ struct azx_dev { | |||
252 | unsigned int fragsize; /* size of each period in bytes */ | 250 | unsigned int fragsize; /* size of each period in bytes */ |
253 | unsigned int frags; /* number for period in the play buffer */ | 251 | unsigned int frags; /* number for period in the play buffer */ |
254 | unsigned int fifo_size; /* FIFO size */ | 252 | unsigned int fifo_size; /* FIFO size */ |
255 | unsigned int last_pos; /* last updated period position */ | ||
256 | 253 | ||
257 | void __iomem *sd_addr; /* stream descriptor pointer */ | 254 | void __iomem *sd_addr; /* stream descriptor pointer */ |
258 | 255 | ||
@@ -263,10 +260,11 @@ struct azx_dev { | |||
263 | unsigned int format_val; /* format value to be set in the controller and the codec */ | 260 | unsigned int format_val; /* format value to be set in the controller and the codec */ |
264 | unsigned char stream_tag; /* assigned stream */ | 261 | unsigned char stream_tag; /* assigned stream */ |
265 | unsigned char index; /* stream index */ | 262 | unsigned char index; /* stream index */ |
263 | /* for sanity check of position buffer */ | ||
264 | unsigned int period_intr; | ||
266 | 265 | ||
267 | unsigned int opened: 1; | 266 | unsigned int opened: 1; |
268 | unsigned int running: 1; | 267 | unsigned int running: 1; |
269 | unsigned int period_updating: 1; | ||
270 | }; | 268 | }; |
271 | 269 | ||
272 | /* CORB/RIRB */ | 270 | /* CORB/RIRB */ |
@@ -300,7 +298,7 @@ struct azx { | |||
300 | 298 | ||
301 | /* locks */ | 299 | /* locks */ |
302 | spinlock_t reg_lock; | 300 | spinlock_t reg_lock; |
303 | struct semaphore open_mutex; | 301 | struct mutex open_mutex; |
304 | 302 | ||
305 | /* streams (x num_streams) */ | 303 | /* streams (x num_streams) */ |
306 | struct azx_dev *azx_dev; | 304 | struct azx_dev *azx_dev; |
@@ -325,6 +323,7 @@ struct azx { | |||
325 | /* flags */ | 323 | /* flags */ |
326 | int position_fix; | 324 | int position_fix; |
327 | unsigned int initialized: 1; | 325 | unsigned int initialized: 1; |
326 | unsigned int single_cmd: 1; | ||
328 | }; | 327 | }; |
329 | 328 | ||
330 | /* driver types */ | 329 | /* driver types */ |
@@ -388,7 +387,6 @@ static char *driver_short_names[] __devinitdata = { | |||
388 | * Interface for HD codec | 387 | * Interface for HD codec |
389 | */ | 388 | */ |
390 | 389 | ||
391 | #ifdef USE_CORB_RIRB | ||
392 | /* | 390 | /* |
393 | * CORB / RIRB interface | 391 | * CORB / RIRB interface |
394 | */ | 392 | */ |
@@ -436,11 +434,7 @@ static void azx_init_cmd_io(struct azx *chip) | |||
436 | /* set N=1, get RIRB response interrupt for new entry */ | 434 | /* set N=1, get RIRB response interrupt for new entry */ |
437 | azx_writew(chip, RINTCNT, 1); | 435 | azx_writew(chip, RINTCNT, 1); |
438 | /* enable rirb dma and response irq */ | 436 | /* enable rirb dma and response irq */ |
439 | #ifdef USE_CORB_RIRB | ||
440 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); | 437 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); |
441 | #else | ||
442 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN); | ||
443 | #endif | ||
444 | chip->rirb.rp = chip->rirb.cmds = 0; | 438 | chip->rirb.rp = chip->rirb.cmds = 0; |
445 | } | 439 | } |
446 | 440 | ||
@@ -452,8 +446,8 @@ static void azx_free_cmd_io(struct azx *chip) | |||
452 | } | 446 | } |
453 | 447 | ||
454 | /* send a command */ | 448 | /* send a command */ |
455 | static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | 449 | static int azx_corb_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, |
456 | unsigned int verb, unsigned int para) | 450 | unsigned int verb, unsigned int para) |
457 | { | 451 | { |
458 | struct azx *chip = codec->bus->private_data; | 452 | struct azx *chip = codec->bus->private_data; |
459 | unsigned int wp; | 453 | unsigned int wp; |
@@ -509,18 +503,21 @@ static void azx_update_rirb(struct azx *chip) | |||
509 | } | 503 | } |
510 | 504 | ||
511 | /* receive a response */ | 505 | /* receive a response */ |
512 | static unsigned int azx_get_response(struct hda_codec *codec) | 506 | static unsigned int azx_rirb_get_response(struct hda_codec *codec) |
513 | { | 507 | { |
514 | struct azx *chip = codec->bus->private_data; | 508 | struct azx *chip = codec->bus->private_data; |
515 | int timeout = 50; | 509 | int timeout = 50; |
516 | 510 | ||
517 | while (chip->rirb.cmds) { | 511 | while (chip->rirb.cmds) { |
518 | if (! --timeout) { | 512 | if (! --timeout) { |
519 | if (printk_ratelimit()) | 513 | snd_printk(KERN_ERR |
520 | snd_printk(KERN_ERR | 514 | "hda_intel: azx_get_response timeout, " |
521 | "azx_get_response timeout\n"); | 515 | "switching to single_cmd mode...\n"); |
522 | chip->rirb.rp = azx_readb(chip, RIRBWP); | 516 | chip->rirb.rp = azx_readb(chip, RIRBWP); |
523 | chip->rirb.cmds = 0; | 517 | chip->rirb.cmds = 0; |
518 | /* switch to single_cmd mode */ | ||
519 | chip->single_cmd = 1; | ||
520 | azx_free_cmd_io(chip); | ||
524 | return -1; | 521 | return -1; |
525 | } | 522 | } |
526 | msleep(1); | 523 | msleep(1); |
@@ -528,7 +525,6 @@ static unsigned int azx_get_response(struct hda_codec *codec) | |||
528 | return chip->rirb.res; /* the last value */ | 525 | return chip->rirb.res; /* the last value */ |
529 | } | 526 | } |
530 | 527 | ||
531 | #else | ||
532 | /* | 528 | /* |
533 | * Use the single immediate command instead of CORB/RIRB for simplicity | 529 | * Use the single immediate command instead of CORB/RIRB for simplicity |
534 | * | 530 | * |
@@ -539,13 +535,10 @@ static unsigned int azx_get_response(struct hda_codec *codec) | |||
539 | * I left the codes, however, for debugging/testing purposes. | 535 | * I left the codes, however, for debugging/testing purposes. |
540 | */ | 536 | */ |
541 | 537 | ||
542 | #define azx_alloc_cmd_io(chip) 0 | ||
543 | #define azx_init_cmd_io(chip) | ||
544 | #define azx_free_cmd_io(chip) | ||
545 | |||
546 | /* send a command */ | 538 | /* send a command */ |
547 | static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | 539 | static int azx_single_send_cmd(struct hda_codec *codec, hda_nid_t nid, |
548 | unsigned int verb, unsigned int para) | 540 | int direct, unsigned int verb, |
541 | unsigned int para) | ||
549 | { | 542 | { |
550 | struct azx *chip = codec->bus->private_data; | 543 | struct azx *chip = codec->bus->private_data; |
551 | u32 val; | 544 | u32 val; |
@@ -573,7 +566,7 @@ static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
573 | } | 566 | } |
574 | 567 | ||
575 | /* receive a response */ | 568 | /* receive a response */ |
576 | static unsigned int azx_get_response(struct hda_codec *codec) | 569 | static unsigned int azx_single_get_response(struct hda_codec *codec) |
577 | { | 570 | { |
578 | struct azx *chip = codec->bus->private_data; | 571 | struct azx *chip = codec->bus->private_data; |
579 | int timeout = 50; | 572 | int timeout = 50; |
@@ -588,9 +581,35 @@ static unsigned int azx_get_response(struct hda_codec *codec) | |||
588 | return (unsigned int)-1; | 581 | return (unsigned int)-1; |
589 | } | 582 | } |
590 | 583 | ||
591 | #define azx_update_rirb(chip) | 584 | /* |
585 | * The below are the main callbacks from hda_codec. | ||
586 | * | ||
587 | * They are just the skeleton to call sub-callbacks according to the | ||
588 | * current setting of chip->single_cmd. | ||
589 | */ | ||
590 | |||
591 | /* send a command */ | ||
592 | static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, | ||
593 | int direct, unsigned int verb, | ||
594 | unsigned int para) | ||
595 | { | ||
596 | struct azx *chip = codec->bus->private_data; | ||
597 | if (chip->single_cmd) | ||
598 | return azx_single_send_cmd(codec, nid, direct, verb, para); | ||
599 | else | ||
600 | return azx_corb_send_cmd(codec, nid, direct, verb, para); | ||
601 | } | ||
602 | |||
603 | /* get a response */ | ||
604 | static unsigned int azx_get_response(struct hda_codec *codec) | ||
605 | { | ||
606 | struct azx *chip = codec->bus->private_data; | ||
607 | if (chip->single_cmd) | ||
608 | return azx_single_get_response(codec); | ||
609 | else | ||
610 | return azx_rirb_get_response(codec); | ||
611 | } | ||
592 | 612 | ||
593 | #endif /* USE_CORB_RIRB */ | ||
594 | 613 | ||
595 | /* reset codec link */ | 614 | /* reset codec link */ |
596 | static int azx_reset(struct azx *chip) | 615 | static int azx_reset(struct azx *chip) |
@@ -737,7 +756,8 @@ static void azx_init_chip(struct azx *chip) | |||
737 | azx_int_enable(chip); | 756 | azx_int_enable(chip); |
738 | 757 | ||
739 | /* initialize the codec command I/O */ | 758 | /* initialize the codec command I/O */ |
740 | azx_init_cmd_io(chip); | 759 | if (! chip->single_cmd) |
760 | azx_init_cmd_io(chip); | ||
741 | 761 | ||
742 | /* program the position buffer */ | 762 | /* program the position buffer */ |
743 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); | 763 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); |
@@ -784,11 +804,10 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) | |||
784 | if (status & azx_dev->sd_int_sta_mask) { | 804 | if (status & azx_dev->sd_int_sta_mask) { |
785 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); | 805 | azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); |
786 | if (azx_dev->substream && azx_dev->running) { | 806 | if (azx_dev->substream && azx_dev->running) { |
787 | azx_dev->period_updating = 1; | 807 | azx_dev->period_intr++; |
788 | spin_unlock(&chip->reg_lock); | 808 | spin_unlock(&chip->reg_lock); |
789 | snd_pcm_period_elapsed(azx_dev->substream); | 809 | snd_pcm_period_elapsed(azx_dev->substream); |
790 | spin_lock(&chip->reg_lock); | 810 | spin_lock(&chip->reg_lock); |
791 | azx_dev->period_updating = 0; | ||
792 | } | 811 | } |
793 | } | 812 | } |
794 | } | 813 | } |
@@ -796,7 +815,7 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) | |||
796 | /* clear rirb int */ | 815 | /* clear rirb int */ |
797 | status = azx_readb(chip, RIRBSTS); | 816 | status = azx_readb(chip, RIRBSTS); |
798 | if (status & RIRB_INT_MASK) { | 817 | if (status & RIRB_INT_MASK) { |
799 | if (status & RIRB_INT_RESPONSE) | 818 | if (! chip->single_cmd && (status & RIRB_INT_RESPONSE)) |
800 | azx_update_rirb(chip); | 819 | azx_update_rirb(chip); |
801 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 820 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
802 | } | 821 | } |
@@ -1002,10 +1021,10 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
1002 | unsigned long flags; | 1021 | unsigned long flags; |
1003 | int err; | 1022 | int err; |
1004 | 1023 | ||
1005 | down(&chip->open_mutex); | 1024 | mutex_lock(&chip->open_mutex); |
1006 | azx_dev = azx_assign_device(chip, substream->stream); | 1025 | azx_dev = azx_assign_device(chip, substream->stream); |
1007 | if (azx_dev == NULL) { | 1026 | if (azx_dev == NULL) { |
1008 | up(&chip->open_mutex); | 1027 | mutex_unlock(&chip->open_mutex); |
1009 | return -EBUSY; | 1028 | return -EBUSY; |
1010 | } | 1029 | } |
1011 | runtime->hw = azx_pcm_hw; | 1030 | runtime->hw = azx_pcm_hw; |
@@ -1017,7 +1036,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
1017 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | 1036 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); |
1018 | if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) { | 1037 | if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) { |
1019 | azx_release_device(azx_dev); | 1038 | azx_release_device(azx_dev); |
1020 | up(&chip->open_mutex); | 1039 | mutex_unlock(&chip->open_mutex); |
1021 | return err; | 1040 | return err; |
1022 | } | 1041 | } |
1023 | spin_lock_irqsave(&chip->reg_lock, flags); | 1042 | spin_lock_irqsave(&chip->reg_lock, flags); |
@@ -1026,7 +1045,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
1026 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1045 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1027 | 1046 | ||
1028 | runtime->private_data = azx_dev; | 1047 | runtime->private_data = azx_dev; |
1029 | up(&chip->open_mutex); | 1048 | mutex_unlock(&chip->open_mutex); |
1030 | return 0; | 1049 | return 0; |
1031 | } | 1050 | } |
1032 | 1051 | ||
@@ -1038,14 +1057,14 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) | |||
1038 | struct azx_dev *azx_dev = get_azx_dev(substream); | 1057 | struct azx_dev *azx_dev = get_azx_dev(substream); |
1039 | unsigned long flags; | 1058 | unsigned long flags; |
1040 | 1059 | ||
1041 | down(&chip->open_mutex); | 1060 | mutex_lock(&chip->open_mutex); |
1042 | spin_lock_irqsave(&chip->reg_lock, flags); | 1061 | spin_lock_irqsave(&chip->reg_lock, flags); |
1043 | azx_dev->substream = NULL; | 1062 | azx_dev->substream = NULL; |
1044 | azx_dev->running = 0; | 1063 | azx_dev->running = 0; |
1045 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1064 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1046 | azx_release_device(azx_dev); | 1065 | azx_release_device(azx_dev); |
1047 | hinfo->ops.close(hinfo, apcm->codec, substream); | 1066 | hinfo->ops.close(hinfo, apcm->codec, substream); |
1048 | up(&chip->open_mutex); | 1067 | mutex_unlock(&chip->open_mutex); |
1049 | return 0; | 1068 | return 0; |
1050 | } | 1069 | } |
1051 | 1070 | ||
@@ -1099,7 +1118,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1099 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; | 1118 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; |
1100 | else | 1119 | else |
1101 | azx_dev->fifo_size = 0; | 1120 | azx_dev->fifo_size = 0; |
1102 | azx_dev->last_pos = 0; | ||
1103 | 1121 | ||
1104 | return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, | 1122 | return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, |
1105 | azx_dev->format_val, substream); | 1123 | azx_dev->format_val, substream); |
@@ -1147,10 +1165,20 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
1147 | struct azx_dev *azx_dev = get_azx_dev(substream); | 1165 | struct azx_dev *azx_dev = get_azx_dev(substream); |
1148 | unsigned int pos; | 1166 | unsigned int pos; |
1149 | 1167 | ||
1150 | if (chip->position_fix == POS_FIX_POSBUF) { | 1168 | if (chip->position_fix == POS_FIX_POSBUF || |
1169 | chip->position_fix == POS_FIX_AUTO) { | ||
1151 | /* use the position buffer */ | 1170 | /* use the position buffer */ |
1152 | pos = *azx_dev->posbuf; | 1171 | pos = *azx_dev->posbuf; |
1172 | if (chip->position_fix == POS_FIX_AUTO && | ||
1173 | azx_dev->period_intr == 1 && ! pos) { | ||
1174 | printk(KERN_WARNING | ||
1175 | "hda-intel: Invalid position buffer, " | ||
1176 | "using LPIB read method instead.\n"); | ||
1177 | chip->position_fix = POS_FIX_NONE; | ||
1178 | goto read_lpib; | ||
1179 | } | ||
1153 | } else { | 1180 | } else { |
1181 | read_lpib: | ||
1154 | /* read LPIB */ | 1182 | /* read LPIB */ |
1155 | pos = azx_sd_readl(azx_dev, SD_LPIB); | 1183 | pos = azx_sd_readl(azx_dev, SD_LPIB); |
1156 | if (chip->position_fix == POS_FIX_FIFO) | 1184 | if (chip->position_fix == POS_FIX_FIFO) |
@@ -1415,13 +1443,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1415 | } | 1443 | } |
1416 | 1444 | ||
1417 | spin_lock_init(&chip->reg_lock); | 1445 | spin_lock_init(&chip->reg_lock); |
1418 | init_MUTEX(&chip->open_mutex); | 1446 | mutex_init(&chip->open_mutex); |
1419 | chip->card = card; | 1447 | chip->card = card; |
1420 | chip->pci = pci; | 1448 | chip->pci = pci; |
1421 | chip->irq = -1; | 1449 | chip->irq = -1; |
1422 | chip->driver_type = driver_type; | 1450 | chip->driver_type = driver_type; |
1423 | 1451 | ||
1424 | chip->position_fix = position_fix ? position_fix : POS_FIX_POSBUF; | 1452 | chip->position_fix = position_fix; |
1453 | chip->single_cmd = single_cmd; | ||
1425 | 1454 | ||
1426 | #if BITS_PER_LONG != 64 | 1455 | #if BITS_PER_LONG != 64 |
1427 | /* Fix up base address on ULI M5461 */ | 1456 | /* Fix up base address on ULI M5461 */ |
@@ -1492,8 +1521,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1492 | goto errout; | 1521 | goto errout; |
1493 | } | 1522 | } |
1494 | /* allocate CORB/RIRB */ | 1523 | /* allocate CORB/RIRB */ |
1495 | if ((err = azx_alloc_cmd_io(chip)) < 0) | 1524 | if (! chip->single_cmd) |
1496 | goto errout; | 1525 | if ((err = azx_alloc_cmd_io(chip)) < 0) |
1526 | goto errout; | ||
1497 | 1527 | ||
1498 | /* initialize streams */ | 1528 | /* initialize streams */ |
1499 | azx_init_stream(chip); | 1529 | azx_init_stream(chip); |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index c82d2a72d13e..14e8aa2806ed 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -66,6 +66,11 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
66 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 66 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); |
67 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 67 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
68 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 68 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
69 | /* lowlevel accessor with caching; use carefully */ | ||
70 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | ||
71 | int direction, int index); | ||
72 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | ||
73 | int direction, int idx, int mask, int val); | ||
69 | 74 | ||
70 | /* mono switch binding multiple inputs */ | 75 | /* mono switch binding multiple inputs */ |
71 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ | 76 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ |
@@ -130,6 +135,7 @@ struct hda_multi_out { | |||
130 | int num_dacs; /* # of DACs, must be more than 1 */ | 135 | int num_dacs; /* # of DACs, must be more than 1 */ |
131 | hda_nid_t *dac_nids; /* DAC list */ | 136 | hda_nid_t *dac_nids; /* DAC list */ |
132 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ | 137 | hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ |
138 | hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ | ||
133 | hda_nid_t dig_out_nid; /* digital out audio widget */ | 139 | hda_nid_t dig_out_nid; /* digital out audio widget */ |
134 | int max_channels; /* currently supported analog channels */ | 140 | int max_channels; /* currently supported analog channels */ |
135 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ | 141 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ |
@@ -216,7 +222,8 @@ extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | |||
216 | struct auto_pin_cfg { | 222 | struct auto_pin_cfg { |
217 | int line_outs; | 223 | int line_outs; |
218 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ | 224 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ |
219 | hda_nid_t speaker_pin; | 225 | int speaker_outs; |
226 | hda_nid_t speaker_pins[5]; | ||
220 | hda_nid_t hp_pin; | 227 | hda_nid_t hp_pin; |
221 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 228 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
222 | hda_nid_t dig_out_pin; | 229 | hda_nid_t dig_out_pin; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 1ada1b075c9a..32401bd8c229 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/mutex.h> | ||
27 | |||
26 | #include <sound/core.h> | 28 | #include <sound/core.h> |
27 | #include "hda_codec.h" | 29 | #include "hda_codec.h" |
28 | #include "hda_local.h" | 30 | #include "hda_local.h" |
@@ -60,7 +62,7 @@ struct ad198x_spec { | |||
60 | /* PCM information */ | 62 | /* PCM information */ |
61 | struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ | 63 | struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ |
62 | 64 | ||
63 | struct semaphore amp_mutex; /* PCM volume/mute control mutex */ | 65 | struct mutex amp_mutex; /* PCM volume/mute control mutex */ |
64 | unsigned int spdif_route; | 66 | unsigned int spdif_route; |
65 | 67 | ||
66 | /* dynamic controls, init_verbs and input_mux */ | 68 | /* dynamic controls, init_verbs and input_mux */ |
@@ -308,7 +310,7 @@ static int ad198x_resume(struct hda_codec *codec) | |||
308 | struct ad198x_spec *spec = codec->spec; | 310 | struct ad198x_spec *spec = codec->spec; |
309 | int i; | 311 | int i; |
310 | 312 | ||
311 | ad198x_init(codec); | 313 | codec->patch_ops.init(codec); |
312 | for (i = 0; i < spec->num_mixers; i++) | 314 | for (i = 0; i < spec->num_mixers; i++) |
313 | snd_hda_resume_ctls(codec, spec->mixers[i]); | 315 | snd_hda_resume_ctls(codec, spec->mixers[i]); |
314 | if (spec->multiout.dig_out_nid) | 316 | if (spec->multiout.dig_out_nid) |
@@ -331,6 +333,61 @@ static struct hda_codec_ops ad198x_patch_ops = { | |||
331 | 333 | ||
332 | 334 | ||
333 | /* | 335 | /* |
336 | * EAPD control | ||
337 | * the private value = nid | (invert << 8) | ||
338 | */ | ||
339 | static int ad198x_eapd_info(struct snd_kcontrol *kcontrol, | ||
340 | struct snd_ctl_elem_info *uinfo) | ||
341 | { | ||
342 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
343 | uinfo->count = 1; | ||
344 | uinfo->value.integer.min = 0; | ||
345 | uinfo->value.integer.max = 1; | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, | ||
350 | struct snd_ctl_elem_value *ucontrol) | ||
351 | { | ||
352 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
353 | struct ad198x_spec *spec = codec->spec; | ||
354 | int invert = (kcontrol->private_value >> 8) & 1; | ||
355 | if (invert) | ||
356 | ucontrol->value.integer.value[0] = ! spec->cur_eapd; | ||
357 | else | ||
358 | ucontrol->value.integer.value[0] = spec->cur_eapd; | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int ad198x_eapd_put(struct snd_kcontrol *kcontrol, | ||
363 | struct snd_ctl_elem_value *ucontrol) | ||
364 | { | ||
365 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
366 | struct ad198x_spec *spec = codec->spec; | ||
367 | int invert = (kcontrol->private_value >> 8) & 1; | ||
368 | hda_nid_t nid = kcontrol->private_value & 0xff; | ||
369 | unsigned int eapd; | ||
370 | eapd = ucontrol->value.integer.value[0]; | ||
371 | if (invert) | ||
372 | eapd = !eapd; | ||
373 | if (eapd == spec->cur_eapd && ! codec->in_resume) | ||
374 | return 0; | ||
375 | spec->cur_eapd = eapd; | ||
376 | snd_hda_codec_write(codec, nid, | ||
377 | 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
378 | eapd ? 0x02 : 0x00); | ||
379 | return 1; | ||
380 | } | ||
381 | |||
382 | static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, | ||
383 | struct snd_ctl_elem_info *uinfo); | ||
384 | static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, | ||
385 | struct snd_ctl_elem_value *ucontrol); | ||
386 | static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, | ||
387 | struct snd_ctl_elem_value *ucontrol); | ||
388 | |||
389 | |||
390 | /* | ||
334 | * AD1986A specific | 391 | * AD1986A specific |
335 | */ | 392 | */ |
336 | 393 | ||
@@ -344,6 +401,7 @@ static hda_nid_t ad1986a_dac_nids[3] = { | |||
344 | AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC | 401 | AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC |
345 | }; | 402 | }; |
346 | static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC }; | 403 | static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC }; |
404 | static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 }; | ||
347 | 405 | ||
348 | static struct hda_input_mux ad1986a_capture_source = { | 406 | static struct hda_input_mux ad1986a_capture_source = { |
349 | .num_items = 7, | 407 | .num_items = 7, |
@@ -371,9 +429,9 @@ static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
371 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 429 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
372 | struct ad198x_spec *ad = codec->spec; | 430 | struct ad198x_spec *ad = codec->spec; |
373 | 431 | ||
374 | down(&ad->amp_mutex); | 432 | mutex_lock(&ad->amp_mutex); |
375 | snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); | 433 | snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); |
376 | up(&ad->amp_mutex); | 434 | mutex_unlock(&ad->amp_mutex); |
377 | return 0; | 435 | return 0; |
378 | } | 436 | } |
379 | 437 | ||
@@ -383,13 +441,13 @@ static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
383 | struct ad198x_spec *ad = codec->spec; | 441 | struct ad198x_spec *ad = codec->spec; |
384 | int i, change = 0; | 442 | int i, change = 0; |
385 | 443 | ||
386 | down(&ad->amp_mutex); | 444 | mutex_lock(&ad->amp_mutex); |
387 | for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { | 445 | for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { |
388 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); | 446 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); |
389 | change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); | 447 | change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); |
390 | } | 448 | } |
391 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); | 449 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); |
392 | up(&ad->amp_mutex); | 450 | mutex_unlock(&ad->amp_mutex); |
393 | return change; | 451 | return change; |
394 | } | 452 | } |
395 | 453 | ||
@@ -400,9 +458,9 @@ static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
400 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 458 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
401 | struct ad198x_spec *ad = codec->spec; | 459 | struct ad198x_spec *ad = codec->spec; |
402 | 460 | ||
403 | down(&ad->amp_mutex); | 461 | mutex_lock(&ad->amp_mutex); |
404 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | 462 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); |
405 | up(&ad->amp_mutex); | 463 | mutex_unlock(&ad->amp_mutex); |
406 | return 0; | 464 | return 0; |
407 | } | 465 | } |
408 | 466 | ||
@@ -412,13 +470,13 @@ static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
412 | struct ad198x_spec *ad = codec->spec; | 470 | struct ad198x_spec *ad = codec->spec; |
413 | int i, change = 0; | 471 | int i, change = 0; |
414 | 472 | ||
415 | down(&ad->amp_mutex); | 473 | mutex_lock(&ad->amp_mutex); |
416 | for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { | 474 | for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { |
417 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); | 475 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); |
418 | change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | 476 | change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); |
419 | } | 477 | } |
420 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); | 478 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); |
421 | up(&ad->amp_mutex); | 479 | mutex_unlock(&ad->amp_mutex); |
422 | return change; | 480 | return change; |
423 | } | 481 | } |
424 | 482 | ||
@@ -477,6 +535,143 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { | |||
477 | { } /* end */ | 535 | { } /* end */ |
478 | }; | 536 | }; |
479 | 537 | ||
538 | /* additional mixers for 3stack mode */ | ||
539 | static struct snd_kcontrol_new ad1986a_3st_mixers[] = { | ||
540 | { | ||
541 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
542 | .name = "Channel Mode", | ||
543 | .info = ad198x_ch_mode_info, | ||
544 | .get = ad198x_ch_mode_get, | ||
545 | .put = ad198x_ch_mode_put, | ||
546 | }, | ||
547 | { } /* end */ | ||
548 | }; | ||
549 | |||
550 | /* laptop model - 2ch only */ | ||
551 | static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC }; | ||
552 | |||
553 | static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { | ||
554 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
555 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
556 | HDA_CODEC_VOLUME("Master Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | ||
557 | HDA_CODEC_MUTE("Master Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
558 | /* HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
559 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), */ | ||
560 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), | ||
561 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
562 | HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), | ||
563 | HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT), | ||
564 | HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT), | ||
565 | HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), | ||
566 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
567 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
568 | /* HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT), | ||
569 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
570 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), | ||
571 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ | ||
572 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
573 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | ||
574 | { | ||
575 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
576 | .name = "Capture Source", | ||
577 | .info = ad198x_mux_enum_info, | ||
578 | .get = ad198x_mux_enum_get, | ||
579 | .put = ad198x_mux_enum_put, | ||
580 | }, | ||
581 | { } /* end */ | ||
582 | }; | ||
583 | |||
584 | /* laptop-eapd model - 2ch only */ | ||
585 | |||
586 | /* master controls both pins 0x1a and 0x1b */ | ||
587 | static int ad1986a_laptop_master_vol_put(struct snd_kcontrol *kcontrol, | ||
588 | struct snd_ctl_elem_value *ucontrol) | ||
589 | { | ||
590 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
591 | long *valp = ucontrol->value.integer.value; | ||
592 | int change; | ||
593 | |||
594 | change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | ||
595 | 0x7f, valp[0] & 0x7f); | ||
596 | change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | ||
597 | 0x7f, valp[1] & 0x7f); | ||
598 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | ||
599 | 0x7f, valp[0] & 0x7f); | ||
600 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | ||
601 | 0x7f, valp[1] & 0x7f); | ||
602 | return change; | ||
603 | } | ||
604 | |||
605 | static int ad1986a_laptop_master_sw_put(struct snd_kcontrol *kcontrol, | ||
606 | struct snd_ctl_elem_value *ucontrol) | ||
607 | { | ||
608 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
609 | long *valp = ucontrol->value.integer.value; | ||
610 | int change; | ||
611 | |||
612 | change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | ||
613 | 0x80, valp[0] ? 0 : 0x80); | ||
614 | change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | ||
615 | 0x80, valp[1] ? 0 : 0x80); | ||
616 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | ||
617 | 0x80, valp[0] ? 0 : 0x80); | ||
618 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | ||
619 | 0x80, valp[1] ? 0 : 0x80); | ||
620 | return change; | ||
621 | } | ||
622 | |||
623 | static struct hda_input_mux ad1986a_laptop_eapd_capture_source = { | ||
624 | .num_items = 3, | ||
625 | .items = { | ||
626 | { "Mic", 0x0 }, | ||
627 | { "Internal Mic", 0x4 }, | ||
628 | { "Mix", 0x5 }, | ||
629 | }, | ||
630 | }; | ||
631 | |||
632 | static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | ||
633 | { | ||
634 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
635 | .name = "Master Playback Volume", | ||
636 | .info = snd_hda_mixer_amp_volume_info, | ||
637 | .get = snd_hda_mixer_amp_volume_get, | ||
638 | .put = ad1986a_laptop_master_vol_put, | ||
639 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | ||
640 | }, | ||
641 | { | ||
642 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
643 | .name = "Master Playback Switch", | ||
644 | .info = snd_hda_mixer_amp_switch_info, | ||
645 | .get = snd_hda_mixer_amp_switch_get, | ||
646 | .put = ad1986a_laptop_master_sw_put, | ||
647 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | ||
648 | }, | ||
649 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
650 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
651 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), | ||
652 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), | ||
653 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
654 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
655 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
656 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | ||
657 | { | ||
658 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
659 | .name = "Capture Source", | ||
660 | .info = ad198x_mux_enum_info, | ||
661 | .get = ad198x_mux_enum_get, | ||
662 | .put = ad198x_mux_enum_put, | ||
663 | }, | ||
664 | { | ||
665 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
666 | .name = "External Amplifier", | ||
667 | .info = ad198x_eapd_info, | ||
668 | .get = ad198x_eapd_get, | ||
669 | .put = ad198x_eapd_put, | ||
670 | .private_value = 0x1b | (1 << 8), /* port-D, inversed */ | ||
671 | }, | ||
672 | { } /* end */ | ||
673 | }; | ||
674 | |||
480 | /* | 675 | /* |
481 | * initialization verbs | 676 | * initialization verbs |
482 | */ | 677 | */ |
@@ -535,16 +730,89 @@ static struct hda_verb ad1986a_init_verbs[] = { | |||
535 | { } /* end */ | 730 | { } /* end */ |
536 | }; | 731 | }; |
537 | 732 | ||
733 | /* additional verbs for 3-stack model */ | ||
734 | static struct hda_verb ad1986a_3st_init_verbs[] = { | ||
735 | /* Mic and line-in selectors */ | ||
736 | {0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, | ||
737 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
738 | { } /* end */ | ||
739 | }; | ||
740 | |||
741 | static struct hda_verb ad1986a_ch2_init[] = { | ||
742 | /* Surround out -> Line In */ | ||
743 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
744 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
745 | /* CLFE -> Mic in */ | ||
746 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
747 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
748 | { } /* end */ | ||
749 | }; | ||
750 | |||
751 | static struct hda_verb ad1986a_ch4_init[] = { | ||
752 | /* Surround out -> Surround */ | ||
753 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
754 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
755 | /* CLFE -> Mic in */ | ||
756 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
757 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
758 | { } /* end */ | ||
759 | }; | ||
760 | |||
761 | static struct hda_verb ad1986a_ch6_init[] = { | ||
762 | /* Surround out -> Surround out */ | ||
763 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
764 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
765 | /* CLFE -> CLFE */ | ||
766 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
767 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
768 | { } /* end */ | ||
769 | }; | ||
770 | |||
771 | static struct hda_channel_mode ad1986a_modes[3] = { | ||
772 | { 2, ad1986a_ch2_init }, | ||
773 | { 4, ad1986a_ch4_init }, | ||
774 | { 6, ad1986a_ch6_init }, | ||
775 | }; | ||
776 | |||
777 | /* eapd initialization */ | ||
778 | static struct hda_verb ad1986a_eapd_init_verbs[] = { | ||
779 | {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, | ||
780 | {} | ||
781 | }; | ||
782 | |||
783 | /* models */ | ||
784 | enum { AD1986A_6STACK, AD1986A_3STACK, AD1986A_LAPTOP, AD1986A_LAPTOP_EAPD }; | ||
785 | |||
786 | static struct hda_board_config ad1986a_cfg_tbl[] = { | ||
787 | { .modelname = "6stack", .config = AD1986A_6STACK }, | ||
788 | { .modelname = "3stack", .config = AD1986A_3STACK }, | ||
789 | { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84, | ||
790 | .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ | ||
791 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, | ||
792 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, | ||
793 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ | ||
794 | { .pci_subvendor = 0x17c0, .pci_subdevice = 0x2017, | ||
795 | .config = AD1986A_LAPTOP }, /* Samsung M50 */ | ||
796 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x818f, | ||
797 | .config = AD1986A_LAPTOP }, /* ASUS P5GV-MX */ | ||
798 | { .modelname = "laptop-eapd", .config = AD1986A_LAPTOP_EAPD }, | ||
799 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, | ||
800 | .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ | ||
801 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213, | ||
802 | .config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */ | ||
803 | {} | ||
804 | }; | ||
538 | 805 | ||
539 | static int patch_ad1986a(struct hda_codec *codec) | 806 | static int patch_ad1986a(struct hda_codec *codec) |
540 | { | 807 | { |
541 | struct ad198x_spec *spec; | 808 | struct ad198x_spec *spec; |
809 | int board_config; | ||
542 | 810 | ||
543 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 811 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
544 | if (spec == NULL) | 812 | if (spec == NULL) |
545 | return -ENOMEM; | 813 | return -ENOMEM; |
546 | 814 | ||
547 | init_MUTEX(&spec->amp_mutex); | 815 | mutex_init(&spec->amp_mutex); |
548 | codec->spec = spec; | 816 | codec->spec = spec; |
549 | 817 | ||
550 | spec->multiout.max_channels = 6; | 818 | spec->multiout.max_channels = 6; |
@@ -553,7 +821,7 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
553 | spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; | 821 | spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; |
554 | spec->num_adc_nids = 1; | 822 | spec->num_adc_nids = 1; |
555 | spec->adc_nids = ad1986a_adc_nids; | 823 | spec->adc_nids = ad1986a_adc_nids; |
556 | spec->capsrc_nids = ad1986a_adc_nids; | 824 | spec->capsrc_nids = ad1986a_capsrc_nids; |
557 | spec->input_mux = &ad1986a_capture_source; | 825 | spec->input_mux = &ad1986a_capture_source; |
558 | spec->num_mixers = 1; | 826 | spec->num_mixers = 1; |
559 | spec->mixers[0] = ad1986a_mixers; | 827 | spec->mixers[0] = ad1986a_mixers; |
@@ -562,6 +830,35 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
562 | 830 | ||
563 | codec->patch_ops = ad198x_patch_ops; | 831 | codec->patch_ops = ad198x_patch_ops; |
564 | 832 | ||
833 | /* override some parameters */ | ||
834 | board_config = snd_hda_check_board_config(codec, ad1986a_cfg_tbl); | ||
835 | switch (board_config) { | ||
836 | case AD1986A_3STACK: | ||
837 | spec->num_mixers = 2; | ||
838 | spec->mixers[1] = ad1986a_3st_mixers; | ||
839 | spec->num_init_verbs = 2; | ||
840 | spec->init_verbs[1] = ad1986a_3st_init_verbs; | ||
841 | spec->channel_mode = ad1986a_modes; | ||
842 | spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); | ||
843 | break; | ||
844 | case AD1986A_LAPTOP: | ||
845 | spec->mixers[0] = ad1986a_laptop_mixers; | ||
846 | spec->multiout.max_channels = 2; | ||
847 | spec->multiout.num_dacs = 1; | ||
848 | spec->multiout.dac_nids = ad1986a_laptop_dac_nids; | ||
849 | break; | ||
850 | case AD1986A_LAPTOP_EAPD: | ||
851 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; | ||
852 | spec->num_init_verbs = 2; | ||
853 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | ||
854 | spec->multiout.max_channels = 2; | ||
855 | spec->multiout.num_dacs = 1; | ||
856 | spec->multiout.dac_nids = ad1986a_laptop_dac_nids; | ||
857 | spec->multiout.dig_out_nid = 0; | ||
858 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; | ||
859 | break; | ||
860 | } | ||
861 | |||
565 | return 0; | 862 | return 0; |
566 | } | 863 | } |
567 | 864 | ||
@@ -575,6 +872,7 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
575 | 872 | ||
576 | static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; | 873 | static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; |
577 | static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC }; | 874 | static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC }; |
875 | static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 }; | ||
578 | 876 | ||
579 | static struct hda_input_mux ad1983_capture_source = { | 877 | static struct hda_input_mux ad1983_capture_source = { |
580 | .num_items = 4, | 878 | .num_items = 4, |
@@ -708,7 +1006,7 @@ static int patch_ad1983(struct hda_codec *codec) | |||
708 | if (spec == NULL) | 1006 | if (spec == NULL) |
709 | return -ENOMEM; | 1007 | return -ENOMEM; |
710 | 1008 | ||
711 | init_MUTEX(&spec->amp_mutex); | 1009 | mutex_init(&spec->amp_mutex); |
712 | codec->spec = spec; | 1010 | codec->spec = spec; |
713 | 1011 | ||
714 | spec->multiout.max_channels = 2; | 1012 | spec->multiout.max_channels = 2; |
@@ -717,7 +1015,7 @@ static int patch_ad1983(struct hda_codec *codec) | |||
717 | spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; | 1015 | spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; |
718 | spec->num_adc_nids = 1; | 1016 | spec->num_adc_nids = 1; |
719 | spec->adc_nids = ad1983_adc_nids; | 1017 | spec->adc_nids = ad1983_adc_nids; |
720 | spec->capsrc_nids = ad1983_adc_nids; | 1018 | spec->capsrc_nids = ad1983_capsrc_nids; |
721 | spec->input_mux = &ad1983_capture_source; | 1019 | spec->input_mux = &ad1983_capture_source; |
722 | spec->num_mixers = 1; | 1020 | spec->num_mixers = 1; |
723 | spec->mixers[0] = ad1983_mixers; | 1021 | spec->mixers[0] = ad1983_mixers; |
@@ -741,6 +1039,7 @@ static int patch_ad1983(struct hda_codec *codec) | |||
741 | 1039 | ||
742 | static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; | 1040 | static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; |
743 | static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC }; | 1041 | static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC }; |
1042 | static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 }; | ||
744 | 1043 | ||
745 | /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ | 1044 | /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ |
746 | static struct hda_input_mux ad1981_capture_source = { | 1045 | static struct hda_input_mux ad1981_capture_source = { |
@@ -846,15 +1145,200 @@ static struct hda_verb ad1981_init_verbs[] = { | |||
846 | { } /* end */ | 1145 | { } /* end */ |
847 | }; | 1146 | }; |
848 | 1147 | ||
1148 | /* | ||
1149 | * Patch for HP nx6320 | ||
1150 | * | ||
1151 | * nx6320 uses EAPD in the reserve way - EAPD-on means the internal | ||
1152 | * speaker output enabled _and_ mute-LED off. | ||
1153 | */ | ||
1154 | |||
1155 | #define AD1981_HP_EVENT 0x37 | ||
1156 | #define AD1981_MIC_EVENT 0x38 | ||
1157 | |||
1158 | static struct hda_verb ad1981_hp_init_verbs[] = { | ||
1159 | {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */ | ||
1160 | /* pin sensing on HP and Mic jacks */ | ||
1161 | {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, | ||
1162 | {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, | ||
1163 | {} | ||
1164 | }; | ||
1165 | |||
1166 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1167 | static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1168 | struct snd_ctl_elem_value *ucontrol) | ||
1169 | { | ||
1170 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1171 | struct ad198x_spec *spec = codec->spec; | ||
1172 | |||
1173 | if (! ad198x_eapd_put(kcontrol, ucontrol)) | ||
1174 | return 0; | ||
1175 | |||
1176 | /* toggle HP mute appropriately */ | ||
1177 | snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0, | ||
1178 | 0x80, spec->cur_eapd ? 0 : 0x80); | ||
1179 | snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0, | ||
1180 | 0x80, spec->cur_eapd ? 0 : 0x80); | ||
1181 | return 1; | ||
1182 | } | ||
1183 | |||
1184 | /* bind volumes of both NID 0x05 and 0x06 */ | ||
1185 | static int ad1981_hp_master_vol_put(struct snd_kcontrol *kcontrol, | ||
1186 | struct snd_ctl_elem_value *ucontrol) | ||
1187 | { | ||
1188 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1189 | long *valp = ucontrol->value.integer.value; | ||
1190 | int change; | ||
1191 | |||
1192 | change = snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | ||
1193 | 0x7f, valp[0] & 0x7f); | ||
1194 | change |= snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
1195 | 0x7f, valp[1] & 0x7f); | ||
1196 | snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0, | ||
1197 | 0x7f, valp[0] & 0x7f); | ||
1198 | snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0, | ||
1199 | 0x7f, valp[1] & 0x7f); | ||
1200 | return change; | ||
1201 | } | ||
1202 | |||
1203 | /* mute internal speaker if HP is plugged */ | ||
1204 | static void ad1981_hp_automute(struct hda_codec *codec) | ||
1205 | { | ||
1206 | unsigned int present; | ||
1207 | |||
1208 | present = snd_hda_codec_read(codec, 0x06, 0, | ||
1209 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1210 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | ||
1211 | 0x80, present ? 0x80 : 0); | ||
1212 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
1213 | 0x80, present ? 0x80 : 0); | ||
1214 | } | ||
1215 | |||
1216 | /* toggle input of built-in and mic jack appropriately */ | ||
1217 | static void ad1981_hp_automic(struct hda_codec *codec) | ||
1218 | { | ||
1219 | static struct hda_verb mic_jack_on[] = { | ||
1220 | {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1221 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
1222 | {} | ||
1223 | }; | ||
1224 | static struct hda_verb mic_jack_off[] = { | ||
1225 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1226 | {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
1227 | {} | ||
1228 | }; | ||
1229 | unsigned int present; | ||
1230 | |||
1231 | present = snd_hda_codec_read(codec, 0x08, 0, | ||
1232 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1233 | if (present) | ||
1234 | snd_hda_sequence_write(codec, mic_jack_on); | ||
1235 | else | ||
1236 | snd_hda_sequence_write(codec, mic_jack_off); | ||
1237 | } | ||
1238 | |||
1239 | /* unsolicited event for HP jack sensing */ | ||
1240 | static void ad1981_hp_unsol_event(struct hda_codec *codec, | ||
1241 | unsigned int res) | ||
1242 | { | ||
1243 | res >>= 26; | ||
1244 | switch (res) { | ||
1245 | case AD1981_HP_EVENT: | ||
1246 | ad1981_hp_automute(codec); | ||
1247 | break; | ||
1248 | case AD1981_MIC_EVENT: | ||
1249 | ad1981_hp_automic(codec); | ||
1250 | break; | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | static struct hda_input_mux ad1981_hp_capture_source = { | ||
1255 | .num_items = 3, | ||
1256 | .items = { | ||
1257 | { "Mic", 0x0 }, | ||
1258 | { "Docking-Station", 0x1 }, | ||
1259 | { "Mix", 0x2 }, | ||
1260 | }, | ||
1261 | }; | ||
1262 | |||
1263 | static struct snd_kcontrol_new ad1981_hp_mixers[] = { | ||
1264 | { | ||
1265 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1266 | .name = "Master Playback Volume", | ||
1267 | .info = snd_hda_mixer_amp_volume_info, | ||
1268 | .get = snd_hda_mixer_amp_volume_get, | ||
1269 | .put = ad1981_hp_master_vol_put, | ||
1270 | .private_value = HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | ||
1271 | }, | ||
1272 | { | ||
1273 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1274 | .name = "Master Playback Switch", | ||
1275 | .info = ad198x_eapd_info, | ||
1276 | .get = ad198x_eapd_get, | ||
1277 | .put = ad1981_hp_master_sw_put, | ||
1278 | .private_value = 0x05, | ||
1279 | }, | ||
1280 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
1281 | HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
1282 | #if 0 | ||
1283 | /* FIXME: analog mic/line loopback doesn't work with my tests... | ||
1284 | * (although recording is OK) | ||
1285 | */ | ||
1286 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
1287 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
1288 | HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
1289 | HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
1290 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), | ||
1291 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), | ||
1292 | /* FIXME: does this laptop have analog CD connection? */ | ||
1293 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | ||
1294 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
1295 | #endif | ||
1296 | HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT), | ||
1297 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT), | ||
1298 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
1299 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | ||
1300 | { | ||
1301 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1302 | .name = "Capture Source", | ||
1303 | .info = ad198x_mux_enum_info, | ||
1304 | .get = ad198x_mux_enum_get, | ||
1305 | .put = ad198x_mux_enum_put, | ||
1306 | }, | ||
1307 | { } /* end */ | ||
1308 | }; | ||
1309 | |||
1310 | /* initialize jack-sensing, too */ | ||
1311 | static int ad1981_hp_init(struct hda_codec *codec) | ||
1312 | { | ||
1313 | ad198x_init(codec); | ||
1314 | ad1981_hp_automute(codec); | ||
1315 | ad1981_hp_automic(codec); | ||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1319 | /* models */ | ||
1320 | enum { AD1981_BASIC, AD1981_HP }; | ||
1321 | |||
1322 | static struct hda_board_config ad1981_cfg_tbl[] = { | ||
1323 | { .modelname = "hp", .config = AD1981_HP }, | ||
1324 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x30aa, | ||
1325 | .config = AD1981_HP }, /* HP nx6320 */ | ||
1326 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x309f, | ||
1327 | .config = AD1981_HP }, /* HP nx9420 AngelFire */ | ||
1328 | { .modelname = "basic", .config = AD1981_BASIC }, | ||
1329 | {} | ||
1330 | }; | ||
1331 | |||
849 | static int patch_ad1981(struct hda_codec *codec) | 1332 | static int patch_ad1981(struct hda_codec *codec) |
850 | { | 1333 | { |
851 | struct ad198x_spec *spec; | 1334 | struct ad198x_spec *spec; |
1335 | int board_config; | ||
852 | 1336 | ||
853 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1337 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
854 | if (spec == NULL) | 1338 | if (spec == NULL) |
855 | return -ENOMEM; | 1339 | return -ENOMEM; |
856 | 1340 | ||
857 | init_MUTEX(&spec->amp_mutex); | 1341 | mutex_init(&spec->amp_mutex); |
858 | codec->spec = spec; | 1342 | codec->spec = spec; |
859 | 1343 | ||
860 | spec->multiout.max_channels = 2; | 1344 | spec->multiout.max_channels = 2; |
@@ -863,7 +1347,7 @@ static int patch_ad1981(struct hda_codec *codec) | |||
863 | spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; | 1347 | spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; |
864 | spec->num_adc_nids = 1; | 1348 | spec->num_adc_nids = 1; |
865 | spec->adc_nids = ad1981_adc_nids; | 1349 | spec->adc_nids = ad1981_adc_nids; |
866 | spec->capsrc_nids = ad1981_adc_nids; | 1350 | spec->capsrc_nids = ad1981_capsrc_nids; |
867 | spec->input_mux = &ad1981_capture_source; | 1351 | spec->input_mux = &ad1981_capture_source; |
868 | spec->num_mixers = 1; | 1352 | spec->num_mixers = 1; |
869 | spec->mixers[0] = ad1981_mixers; | 1353 | spec->mixers[0] = ad1981_mixers; |
@@ -873,6 +1357,21 @@ static int patch_ad1981(struct hda_codec *codec) | |||
873 | 1357 | ||
874 | codec->patch_ops = ad198x_patch_ops; | 1358 | codec->patch_ops = ad198x_patch_ops; |
875 | 1359 | ||
1360 | /* override some parameters */ | ||
1361 | board_config = snd_hda_check_board_config(codec, ad1981_cfg_tbl); | ||
1362 | switch (board_config) { | ||
1363 | case AD1981_HP: | ||
1364 | spec->mixers[0] = ad1981_hp_mixers; | ||
1365 | spec->num_init_verbs = 2; | ||
1366 | spec->init_verbs[1] = ad1981_hp_init_verbs; | ||
1367 | spec->multiout.dig_out_nid = 0; | ||
1368 | spec->input_mux = &ad1981_hp_capture_source; | ||
1369 | |||
1370 | codec->patch_ops.init = ad1981_hp_init; | ||
1371 | codec->patch_ops.unsol_event = ad1981_hp_unsol_event; | ||
1372 | break; | ||
1373 | } | ||
1374 | |||
876 | return 0; | 1375 | return 0; |
877 | } | 1376 | } |
878 | 1377 | ||
@@ -1060,44 +1559,6 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, | |||
1060 | spec->num_channel_mode, &spec->multiout.max_channels); | 1559 | spec->num_channel_mode, &spec->multiout.max_channels); |
1061 | } | 1560 | } |
1062 | 1561 | ||
1063 | /* | ||
1064 | * EAPD control | ||
1065 | */ | ||
1066 | static int ad1988_eapd_info(struct snd_kcontrol *kcontrol, | ||
1067 | struct snd_ctl_elem_info *uinfo) | ||
1068 | { | ||
1069 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1070 | uinfo->count = 1; | ||
1071 | uinfo->value.integer.min = 0; | ||
1072 | uinfo->value.integer.max = 1; | ||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | static int ad1988_eapd_get(struct snd_kcontrol *kcontrol, | ||
1077 | struct snd_ctl_elem_value *ucontrol) | ||
1078 | { | ||
1079 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1080 | struct ad198x_spec *spec = codec->spec; | ||
1081 | ucontrol->value.enumerated.item[0] = ! spec->cur_eapd; | ||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | static int ad1988_eapd_put(struct snd_kcontrol *kcontrol, | ||
1086 | struct snd_ctl_elem_value *ucontrol) | ||
1087 | { | ||
1088 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1089 | struct ad198x_spec *spec = codec->spec; | ||
1090 | unsigned int eapd; | ||
1091 | eapd = ! ucontrol->value.enumerated.item[0]; | ||
1092 | if (eapd == spec->cur_eapd && ! codec->in_resume) | ||
1093 | return 0; | ||
1094 | spec->cur_eapd = eapd; | ||
1095 | snd_hda_codec_write(codec, 0x12 /* port-D */, | ||
1096 | 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
1097 | eapd ? 0x02 : 0x00); | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | /* 6-stack mode */ | 1562 | /* 6-stack mode */ |
1102 | static struct snd_kcontrol_new ad1988_6stack_mixers1[] = { | 1563 | static struct snd_kcontrol_new ad1988_6stack_mixers1[] = { |
1103 | HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), | 1564 | HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), |
@@ -1220,9 +1681,10 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = { | |||
1220 | { | 1681 | { |
1221 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1682 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1222 | .name = "External Amplifier", | 1683 | .name = "External Amplifier", |
1223 | .info = ad1988_eapd_info, | 1684 | .info = ad198x_eapd_info, |
1224 | .get = ad1988_eapd_get, | 1685 | .get = ad198x_eapd_get, |
1225 | .put = ad1988_eapd_put, | 1686 | .put = ad198x_eapd_put, |
1687 | .private_value = 0x12 | (1 << 8), /* port-D, inversed */ | ||
1226 | }, | 1688 | }, |
1227 | 1689 | ||
1228 | { } /* end */ | 1690 | { } /* end */ |
@@ -1795,14 +2257,11 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
1795 | 2257 | ||
1796 | idx = ad1988_pin_idx(pin); | 2258 | idx = ad1988_pin_idx(pin); |
1797 | nid = ad1988_idx_to_dac(codec, idx); | 2259 | nid = ad1988_idx_to_dac(codec, idx); |
1798 | if (! spec->multiout.dac_nids[0]) { | 2260 | /* specify the DAC as the extra output */ |
1799 | /* use this as the primary output */ | 2261 | if (! spec->multiout.hp_nid) |
1800 | spec->multiout.dac_nids[0] = nid; | ||
1801 | if (! spec->multiout.num_dacs) | ||
1802 | spec->multiout.num_dacs = 1; | ||
1803 | } else | ||
1804 | /* specify the DAC as the extra output */ | ||
1805 | spec->multiout.hp_nid = nid; | 2262 | spec->multiout.hp_nid = nid; |
2263 | else | ||
2264 | spec->multiout.extra_out_nid[0] = nid; | ||
1806 | /* control HP volume/switch on the output mixer amp */ | 2265 | /* control HP volume/switch on the output mixer amp */ |
1807 | sprintf(name, "%s Playback Volume", pfx); | 2266 | sprintf(name, "%s Playback Volume", pfx); |
1808 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, | 2267 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, |
@@ -1921,7 +2380,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) | |||
1921 | struct ad198x_spec *spec = codec->spec; | 2380 | struct ad198x_spec *spec = codec->spec; |
1922 | hda_nid_t pin; | 2381 | hda_nid_t pin; |
1923 | 2382 | ||
1924 | pin = spec->autocfg.speaker_pin; | 2383 | pin = spec->autocfg.speaker_pins[0]; |
1925 | if (pin) /* connect to front */ | 2384 | if (pin) /* connect to front */ |
1926 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2385 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
1927 | pin = spec->autocfg.hp_pin; | 2386 | pin = spec->autocfg.hp_pin; |
@@ -1970,13 +2429,13 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
1970 | return err; | 2429 | return err; |
1971 | if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 2430 | if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) |
1972 | return err; | 2431 | return err; |
1973 | if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && | 2432 | if (! spec->autocfg.line_outs) |
1974 | ! spec->autocfg.hp_pin) | ||
1975 | return 0; /* can't find valid BIOS pin config */ | 2433 | return 0; /* can't find valid BIOS pin config */ |
1976 | if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 2434 | if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
1977 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin, | 2435 | (err = ad1988_auto_create_extra_out(codec, |
2436 | spec->autocfg.speaker_pins[0], | ||
1978 | "Speaker")) < 0 || | 2437 | "Speaker")) < 0 || |
1979 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin, | 2438 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin, |
1980 | "Headphone")) < 0 || | 2439 | "Headphone")) < 0 || |
1981 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2440 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
1982 | return err; | 2441 | return err; |
@@ -2032,7 +2491,7 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2032 | if (spec == NULL) | 2491 | if (spec == NULL) |
2033 | return -ENOMEM; | 2492 | return -ENOMEM; |
2034 | 2493 | ||
2035 | init_MUTEX(&spec->amp_mutex); | 2494 | mutex_init(&spec->amp_mutex); |
2036 | codec->spec = spec; | 2495 | codec->spec = spec; |
2037 | 2496 | ||
2038 | if (codec->revision_id == AD1988A_REV2) | 2497 | if (codec->revision_id == AD1988A_REV2) |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b76755264730..4c6c9ec8ea5b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw> | 6 | * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw> |
7 | * PeiSen Hou <pshou@realtek.com.tw> | 7 | * PeiSen Hou <pshou@realtek.com.tw> |
8 | * Takashi Iwai <tiwai@suse.de> | 8 | * Takashi Iwai <tiwai@suse.de> |
9 | * Jonathan Woithe <jwoithe@physics.adelaide.edu.au> | ||
9 | * | 10 | * |
10 | * This driver is free software; you can redistribute it and/or modify | 11 | * This driver is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -50,6 +51,7 @@ enum { | |||
50 | ALC880_UNIWILL_DIG, | 51 | ALC880_UNIWILL_DIG, |
51 | ALC880_CLEVO, | 52 | ALC880_CLEVO, |
52 | ALC880_TCL_S700, | 53 | ALC880_TCL_S700, |
54 | ALC880_LG, | ||
53 | #ifdef CONFIG_SND_DEBUG | 55 | #ifdef CONFIG_SND_DEBUG |
54 | ALC880_TEST, | 56 | ALC880_TEST, |
55 | #endif | 57 | #endif |
@@ -63,6 +65,10 @@ enum { | |||
63 | ALC260_HP, | 65 | ALC260_HP, |
64 | ALC260_HP_3013, | 66 | ALC260_HP_3013, |
65 | ALC260_FUJITSU_S702X, | 67 | ALC260_FUJITSU_S702X, |
68 | ALC260_ACER, | ||
69 | #ifdef CONFIG_SND_DEBUG | ||
70 | ALC260_TEST, | ||
71 | #endif | ||
66 | ALC260_AUTO, | 72 | ALC260_AUTO, |
67 | ALC260_MODEL_LAST /* last tag */ | 73 | ALC260_MODEL_LAST /* last tag */ |
68 | }; | 74 | }; |
@@ -70,6 +76,7 @@ enum { | |||
70 | /* ALC262 models */ | 76 | /* ALC262 models */ |
71 | enum { | 77 | enum { |
72 | ALC262_BASIC, | 78 | ALC262_BASIC, |
79 | ALC262_FUJITSU, | ||
73 | ALC262_AUTO, | 80 | ALC262_AUTO, |
74 | ALC262_MODEL_LAST /* last tag */ | 81 | ALC262_MODEL_LAST /* last tag */ |
75 | }; | 82 | }; |
@@ -132,7 +139,7 @@ struct alc_spec { | |||
132 | int num_channel_mode; | 139 | int num_channel_mode; |
133 | 140 | ||
134 | /* PCM information */ | 141 | /* PCM information */ |
135 | struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ | 142 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
136 | 143 | ||
137 | /* dynamic controls, init_verbs and input_mux */ | 144 | /* dynamic controls, init_verbs and input_mux */ |
138 | struct auto_pin_cfg autocfg; | 145 | struct auto_pin_cfg autocfg; |
@@ -140,6 +147,14 @@ struct alc_spec { | |||
140 | struct snd_kcontrol_new *kctl_alloc; | 147 | struct snd_kcontrol_new *kctl_alloc; |
141 | struct hda_input_mux private_imux; | 148 | struct hda_input_mux private_imux; |
142 | hda_nid_t private_dac_nids[5]; | 149 | hda_nid_t private_dac_nids[5]; |
150 | |||
151 | /* hooks */ | ||
152 | void (*init_hook)(struct hda_codec *codec); | ||
153 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | ||
154 | |||
155 | /* for pin sensing */ | ||
156 | unsigned int sense_updated: 1; | ||
157 | unsigned int jack_present: 1; | ||
143 | }; | 158 | }; |
144 | 159 | ||
145 | /* | 160 | /* |
@@ -158,6 +173,8 @@ struct alc_config_preset { | |||
158 | unsigned int num_channel_mode; | 173 | unsigned int num_channel_mode; |
159 | const struct hda_channel_mode *channel_mode; | 174 | const struct hda_channel_mode *channel_mode; |
160 | const struct hda_input_mux *input_mux; | 175 | const struct hda_input_mux *input_mux; |
176 | void (*unsol_event)(struct hda_codec *, unsigned int); | ||
177 | void (*init_hook)(struct hda_codec *); | ||
161 | }; | 178 | }; |
162 | 179 | ||
163 | 180 | ||
@@ -218,56 +235,231 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va | |||
218 | spec->num_channel_mode, &spec->multiout.max_channels); | 235 | spec->num_channel_mode, &spec->multiout.max_channels); |
219 | } | 236 | } |
220 | 237 | ||
221 | |||
222 | /* | 238 | /* |
223 | * Control of pin widget settings via the mixer. Only boolean settings are | 239 | * Control the mode of pin widget settings via the mixer. "pc" is used |
224 | * supported, so VrefEn can't be controlled using these functions as they | 240 | * instead of "%" to avoid consequences of accidently treating the % as |
225 | * stand. | 241 | * being part of a format specifier. Maximum allowed length of a value is |
242 | * 63 characters plus NULL terminator. | ||
243 | * | ||
244 | * Note: some retasking pin complexes seem to ignore requests for input | ||
245 | * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these | ||
246 | * are requested. Therefore order this list so that this behaviour will not | ||
247 | * cause problems when mixer clients move through the enum sequentially. | ||
248 | * NIDs 0x0f and 0x10 have been observed to have this behaviour. | ||
226 | */ | 249 | */ |
227 | static int alc_pinctl_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 250 | static char *alc_pin_mode_names[] = { |
251 | "Mic 50pc bias", "Mic 80pc bias", | ||
252 | "Line in", "Line out", "Headphone out", | ||
253 | }; | ||
254 | static unsigned char alc_pin_mode_values[] = { | ||
255 | PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, | ||
256 | }; | ||
257 | /* The control can present all 5 options, or it can limit the options based | ||
258 | * in the pin being assumed to be exclusively an input or an output pin. | ||
259 | */ | ||
260 | #define ALC_PIN_DIR_IN 0x00 | ||
261 | #define ALC_PIN_DIR_OUT 0x01 | ||
262 | #define ALC_PIN_DIR_INOUT 0x02 | ||
263 | |||
264 | /* Info about the pin modes supported by the three different pin directions. | ||
265 | * For each direction the minimum and maximum values are given. | ||
266 | */ | ||
267 | static signed char alc_pin_mode_dir_info[3][2] = { | ||
268 | { 0, 2 }, /* ALC_PIN_DIR_IN */ | ||
269 | { 3, 4 }, /* ALC_PIN_DIR_OUT */ | ||
270 | { 0, 4 }, /* ALC_PIN_DIR_INOUT */ | ||
271 | }; | ||
272 | #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) | ||
273 | #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) | ||
274 | #define alc_pin_mode_n_items(_dir) \ | ||
275 | (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) | ||
276 | |||
277 | static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
228 | { | 278 | { |
229 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 279 | unsigned int item_num = uinfo->value.enumerated.item; |
280 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; | ||
281 | |||
282 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
230 | uinfo->count = 1; | 283 | uinfo->count = 1; |
231 | uinfo->value.integer.min = 0; | 284 | uinfo->value.enumerated.items = alc_pin_mode_n_items(dir); |
232 | uinfo->value.integer.max = 1; | 285 | |
286 | if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir)) | ||
287 | item_num = alc_pin_mode_min(dir); | ||
288 | strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]); | ||
233 | return 0; | 289 | return 0; |
234 | } | 290 | } |
235 | 291 | ||
236 | static int alc_pinctl_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 292 | static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
237 | { | 293 | { |
294 | unsigned int i; | ||
238 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 295 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
239 | hda_nid_t nid = kcontrol->private_value & 0xffff; | 296 | hda_nid_t nid = kcontrol->private_value & 0xffff; |
240 | long mask = (kcontrol->private_value >> 16) & 0xff; | 297 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; |
241 | long *valp = ucontrol->value.integer.value; | 298 | long *valp = ucontrol->value.integer.value; |
299 | unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); | ||
242 | 300 | ||
243 | *valp = 0; | 301 | /* Find enumerated value for current pinctl setting */ |
244 | if (snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00) & mask) | 302 | i = alc_pin_mode_min(dir); |
245 | *valp = 1; | 303 | while (alc_pin_mode_values[i]!=pinctl && i<=alc_pin_mode_max(dir)) |
304 | i++; | ||
305 | *valp = i<=alc_pin_mode_max(dir)?i:alc_pin_mode_min(dir); | ||
246 | return 0; | 306 | return 0; |
247 | } | 307 | } |
248 | 308 | ||
249 | static int alc_pinctl_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 309 | static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
250 | { | 310 | { |
311 | signed int change; | ||
251 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 312 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
252 | hda_nid_t nid = kcontrol->private_value & 0xffff; | 313 | hda_nid_t nid = kcontrol->private_value & 0xffff; |
253 | long mask = (kcontrol->private_value >> 16) & 0xff; | 314 | unsigned char dir = (kcontrol->private_value >> 16) & 0xff; |
254 | long *valp = ucontrol->value.integer.value; | 315 | long val = *ucontrol->value.integer.value; |
255 | unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); | 316 | unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); |
256 | int change = ((pinctl & mask)!=0) != *valp; | ||
257 | 317 | ||
258 | if (change) | 318 | if (val<alc_pin_mode_min(dir) || val>alc_pin_mode_max(dir)) |
319 | val = alc_pin_mode_min(dir); | ||
320 | |||
321 | change = pinctl != alc_pin_mode_values[val]; | ||
322 | if (change) { | ||
323 | /* Set pin mode to that requested */ | ||
259 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, | 324 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, |
260 | *valp?(pinctl|mask):(pinctl&~mask)); | 325 | alc_pin_mode_values[val]); |
326 | |||
327 | /* Also enable the retasking pin's input/output as required | ||
328 | * for the requested pin mode. Enum values of 2 or less are | ||
329 | * input modes. | ||
330 | * | ||
331 | * Dynamically switching the input/output buffers probably | ||
332 | * reduces noise slightly, particularly on input. However, | ||
333 | * havingboth input and output buffers enabled | ||
334 | * simultaneously doesn't seem to be problematic. | ||
335 | */ | ||
336 | if (val <= 2) { | ||
337 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | ||
338 | AMP_OUT_MUTE); | ||
339 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | ||
340 | AMP_IN_UNMUTE(0)); | ||
341 | } else { | ||
342 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | ||
343 | AMP_IN_MUTE(0)); | ||
344 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | ||
345 | AMP_OUT_UNMUTE); | ||
346 | } | ||
347 | } | ||
261 | return change; | 348 | return change; |
262 | } | 349 | } |
263 | 350 | ||
264 | #define ALC_PINCTL_SWITCH(xname, nid, mask) \ | 351 | #define ALC_PIN_MODE(xname, nid, dir) \ |
265 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | 352 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ |
266 | .info = alc_pinctl_switch_info, \ | 353 | .info = alc_pin_mode_info, \ |
267 | .get = alc_pinctl_switch_get, \ | 354 | .get = alc_pin_mode_get, \ |
268 | .put = alc_pinctl_switch_put, \ | 355 | .put = alc_pin_mode_put, \ |
269 | .private_value = (nid) | (mask<<16) } | 356 | .private_value = nid | (dir<<16) } |
357 | |||
358 | /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged | ||
359 | * together using a mask with more than one bit set. This control is | ||
360 | * currently used only by the ALC260 test model. At this stage they are not | ||
361 | * needed for any "production" models. | ||
362 | */ | ||
363 | #ifdef CONFIG_SND_DEBUG | ||
364 | static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
365 | { | ||
366 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
367 | uinfo->count = 1; | ||
368 | uinfo->value.integer.min = 0; | ||
369 | uinfo->value.integer.max = 1; | ||
370 | return 0; | ||
371 | } | ||
372 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
373 | { | ||
374 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
375 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
376 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
377 | long *valp = ucontrol->value.integer.value; | ||
378 | unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00); | ||
270 | 379 | ||
380 | *valp = (val & mask) != 0; | ||
381 | return 0; | ||
382 | } | ||
383 | static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
384 | { | ||
385 | signed int change; | ||
386 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
387 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
388 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
389 | long val = *ucontrol->value.integer.value; | ||
390 | unsigned int gpio_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00); | ||
391 | |||
392 | /* Set/unset the masked GPIO bit(s) as needed */ | ||
393 | change = (val==0?0:mask) != (gpio_data & mask); | ||
394 | if (val==0) | ||
395 | gpio_data &= ~mask; | ||
396 | else | ||
397 | gpio_data |= mask; | ||
398 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_GPIO_DATA,gpio_data); | ||
399 | |||
400 | return change; | ||
401 | } | ||
402 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ | ||
403 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
404 | .info = alc_gpio_data_info, \ | ||
405 | .get = alc_gpio_data_get, \ | ||
406 | .put = alc_gpio_data_put, \ | ||
407 | .private_value = nid | (mask<<16) } | ||
408 | #endif /* CONFIG_SND_DEBUG */ | ||
409 | |||
410 | /* A switch control to allow the enabling of the digital IO pins on the | ||
411 | * ALC260. This is incredibly simplistic; the intention of this control is | ||
412 | * to provide something in the test model allowing digital outputs to be | ||
413 | * identified if present. If models are found which can utilise these | ||
414 | * outputs a more complete mixer control can be devised for those models if | ||
415 | * necessary. | ||
416 | */ | ||
417 | #ifdef CONFIG_SND_DEBUG | ||
418 | static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
419 | { | ||
420 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
421 | uinfo->count = 1; | ||
422 | uinfo->value.integer.min = 0; | ||
423 | uinfo->value.integer.max = 1; | ||
424 | return 0; | ||
425 | } | ||
426 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
427 | { | ||
428 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
429 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
430 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
431 | long *valp = ucontrol->value.integer.value; | ||
432 | unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_DIGI_CONVERT,0x00); | ||
433 | |||
434 | *valp = (val & mask) != 0; | ||
435 | return 0; | ||
436 | } | ||
437 | static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
438 | { | ||
439 | signed int change; | ||
440 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
441 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
442 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
443 | long val = *ucontrol->value.integer.value; | ||
444 | unsigned int ctrl_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_DIGI_CONVERT,0x00); | ||
445 | |||
446 | /* Set/unset the masked control bit(s) as needed */ | ||
447 | change = (val==0?0:mask) != (ctrl_data & mask); | ||
448 | if (val==0) | ||
449 | ctrl_data &= ~mask; | ||
450 | else | ||
451 | ctrl_data |= mask; | ||
452 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_DIGI_CONVERT_1,ctrl_data); | ||
453 | |||
454 | return change; | ||
455 | } | ||
456 | #define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \ | ||
457 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
458 | .info = alc_spdif_ctrl_info, \ | ||
459 | .get = alc_spdif_ctrl_get, \ | ||
460 | .put = alc_spdif_ctrl_put, \ | ||
461 | .private_value = nid | (mask<<16) } | ||
462 | #endif /* CONFIG_SND_DEBUG */ | ||
271 | 463 | ||
272 | /* | 464 | /* |
273 | * set up from the preset table | 465 | * set up from the preset table |
@@ -296,6 +488,9 @@ static void setup_preset(struct alc_spec *spec, const struct alc_config_preset * | |||
296 | spec->num_adc_nids = preset->num_adc_nids; | 488 | spec->num_adc_nids = preset->num_adc_nids; |
297 | spec->adc_nids = preset->adc_nids; | 489 | spec->adc_nids = preset->adc_nids; |
298 | spec->dig_in_nid = preset->dig_in_nid; | 490 | spec->dig_in_nid = preset->dig_in_nid; |
491 | |||
492 | spec->unsol_event = preset->unsol_event; | ||
493 | spec->init_hook = preset->init_hook; | ||
299 | } | 494 | } |
300 | 495 | ||
301 | /* | 496 | /* |
@@ -1098,6 +1293,141 @@ static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { | |||
1098 | }; | 1293 | }; |
1099 | 1294 | ||
1100 | /* | 1295 | /* |
1296 | * LG m1 express dual | ||
1297 | * | ||
1298 | * Pin assignment: | ||
1299 | * Rear Line-In/Out (blue): 0x14 | ||
1300 | * Build-in Mic-In: 0x15 | ||
1301 | * Speaker-out: 0x17 | ||
1302 | * HP-Out (green): 0x1b | ||
1303 | * Mic-In/Out (red): 0x19 | ||
1304 | * SPDIF-Out: 0x1e | ||
1305 | */ | ||
1306 | |||
1307 | /* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */ | ||
1308 | static hda_nid_t alc880_lg_dac_nids[3] = { | ||
1309 | 0x05, 0x02, 0x03 | ||
1310 | }; | ||
1311 | |||
1312 | /* seems analog CD is not working */ | ||
1313 | static struct hda_input_mux alc880_lg_capture_source = { | ||
1314 | .num_items = 3, | ||
1315 | .items = { | ||
1316 | { "Mic", 0x1 }, | ||
1317 | { "Line", 0x5 }, | ||
1318 | { "Internal Mic", 0x6 }, | ||
1319 | }, | ||
1320 | }; | ||
1321 | |||
1322 | /* 2,4,6 channel modes */ | ||
1323 | static struct hda_verb alc880_lg_ch2_init[] = { | ||
1324 | /* set line-in and mic-in to input */ | ||
1325 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
1326 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
1327 | { } | ||
1328 | }; | ||
1329 | |||
1330 | static struct hda_verb alc880_lg_ch4_init[] = { | ||
1331 | /* set line-in to out and mic-in to input */ | ||
1332 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
1333 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
1334 | { } | ||
1335 | }; | ||
1336 | |||
1337 | static struct hda_verb alc880_lg_ch6_init[] = { | ||
1338 | /* set line-in and mic-in to output */ | ||
1339 | { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
1340 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
1341 | { } | ||
1342 | }; | ||
1343 | |||
1344 | static struct hda_channel_mode alc880_lg_ch_modes[3] = { | ||
1345 | { 2, alc880_lg_ch2_init }, | ||
1346 | { 4, alc880_lg_ch4_init }, | ||
1347 | { 6, alc880_lg_ch6_init }, | ||
1348 | }; | ||
1349 | |||
1350 | static struct snd_kcontrol_new alc880_lg_mixer[] = { | ||
1351 | /* FIXME: it's not really "master" but front channels */ | ||
1352 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
1353 | HDA_BIND_MUTE("Master Playback Switch", 0x0f, 2, HDA_INPUT), | ||
1354 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1355 | HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT), | ||
1356 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
1357 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), | ||
1358 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), | ||
1359 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), | ||
1360 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
1361 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
1362 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT), | ||
1363 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT), | ||
1364 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT), | ||
1365 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT), | ||
1366 | { | ||
1367 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1368 | .name = "Channel Mode", | ||
1369 | .info = alc_ch_mode_info, | ||
1370 | .get = alc_ch_mode_get, | ||
1371 | .put = alc_ch_mode_put, | ||
1372 | }, | ||
1373 | { } /* end */ | ||
1374 | }; | ||
1375 | |||
1376 | static struct hda_verb alc880_lg_init_verbs[] = { | ||
1377 | /* set capture source to mic-in */ | ||
1378 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1379 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1380 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1381 | /* mute all amp mixer inputs */ | ||
1382 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | ||
1383 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | ||
1384 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | ||
1385 | /* line-in to input */ | ||
1386 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1387 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1388 | /* built-in mic */ | ||
1389 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1390 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1391 | /* speaker-out */ | ||
1392 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1393 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1394 | /* mic-in to input */ | ||
1395 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
1396 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1397 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1398 | /* HP-out */ | ||
1399 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
1400 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1401 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1402 | /* jack sense */ | ||
1403 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, | ||
1404 | { } | ||
1405 | }; | ||
1406 | |||
1407 | /* toggle speaker-output according to the hp-jack state */ | ||
1408 | static void alc880_lg_automute(struct hda_codec *codec) | ||
1409 | { | ||
1410 | unsigned int present; | ||
1411 | |||
1412 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
1413 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1414 | snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0, | ||
1415 | 0x80, present ? 0x80 : 0); | ||
1416 | snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0, | ||
1417 | 0x80, present ? 0x80 : 0); | ||
1418 | } | ||
1419 | |||
1420 | static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1421 | { | ||
1422 | /* Looks like the unsol event is incompatible with the standard | ||
1423 | * definition. 4bit tag is placed at 28 bit! | ||
1424 | */ | ||
1425 | if ((res >> 28) == 0x01) | ||
1426 | alc880_lg_automute(codec); | ||
1427 | } | ||
1428 | |||
1429 | /* | ||
1430 | * Common callbacks | ||
1101 | */ | 1431 | */ |
1102 | 1432 | ||
1103 | static int alc_init(struct hda_codec *codec) | 1433 | static int alc_init(struct hda_codec *codec) |
@@ -1107,9 +1437,21 @@ static int alc_init(struct hda_codec *codec) | |||
1107 | 1437 | ||
1108 | for (i = 0; i < spec->num_init_verbs; i++) | 1438 | for (i = 0; i < spec->num_init_verbs; i++) |
1109 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 1439 | snd_hda_sequence_write(codec, spec->init_verbs[i]); |
1440 | |||
1441 | if (spec->init_hook) | ||
1442 | spec->init_hook(codec); | ||
1443 | |||
1110 | return 0; | 1444 | return 0; |
1111 | } | 1445 | } |
1112 | 1446 | ||
1447 | static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1448 | { | ||
1449 | struct alc_spec *spec = codec->spec; | ||
1450 | |||
1451 | if (spec->unsol_event) | ||
1452 | spec->unsol_event(codec, res); | ||
1453 | } | ||
1454 | |||
1113 | #ifdef CONFIG_PM | 1455 | #ifdef CONFIG_PM |
1114 | /* | 1456 | /* |
1115 | * resume | 1457 | * resume |
@@ -1250,6 +1592,13 @@ static struct hda_pcm_stream alc880_pcm_digital_capture = { | |||
1250 | /* NID is set in alc_build_pcms */ | 1592 | /* NID is set in alc_build_pcms */ |
1251 | }; | 1593 | }; |
1252 | 1594 | ||
1595 | /* Used by alc_build_pcms to flag that a PCM has no playback stream */ | ||
1596 | static struct hda_pcm_stream alc_pcm_null_playback = { | ||
1597 | .substreams = 0, | ||
1598 | .channels_min = 0, | ||
1599 | .channels_max = 0, | ||
1600 | }; | ||
1601 | |||
1253 | static int alc_build_pcms(struct hda_codec *codec) | 1602 | static int alc_build_pcms(struct hda_codec *codec) |
1254 | { | 1603 | { |
1255 | struct alc_spec *spec = codec->spec; | 1604 | struct alc_spec *spec = codec->spec; |
@@ -1280,6 +1629,23 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
1280 | } | 1629 | } |
1281 | } | 1630 | } |
1282 | 1631 | ||
1632 | /* If the use of more than one ADC is requested for the current | ||
1633 | * model, configure a second analog capture-only PCM. | ||
1634 | */ | ||
1635 | if (spec->num_adc_nids > 1) { | ||
1636 | codec->num_pcms++; | ||
1637 | info++; | ||
1638 | info->name = spec->stream_name_analog; | ||
1639 | /* No playback stream for second PCM */ | ||
1640 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; | ||
1641 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; | ||
1642 | if (spec->stream_analog_capture) { | ||
1643 | snd_assert(spec->adc_nids, return -EINVAL); | ||
1644 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); | ||
1645 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; | ||
1646 | } | ||
1647 | } | ||
1648 | |||
1283 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 1649 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { |
1284 | codec->num_pcms++; | 1650 | codec->num_pcms++; |
1285 | info++; | 1651 | info++; |
@@ -1322,6 +1688,7 @@ static struct hda_codec_ops alc_patch_ops = { | |||
1322 | .build_pcms = alc_build_pcms, | 1688 | .build_pcms = alc_build_pcms, |
1323 | .init = alc_init, | 1689 | .init = alc_init, |
1324 | .free = alc_free, | 1690 | .free = alc_free, |
1691 | .unsol_event = alc_unsol_event, | ||
1325 | #ifdef CONFIG_PM | 1692 | #ifdef CONFIG_PM |
1326 | .resume = alc_resume, | 1693 | .resume = alc_resume, |
1327 | #endif | 1694 | #endif |
@@ -1340,13 +1707,15 @@ static hda_nid_t alc880_test_dac_nids[4] = { | |||
1340 | }; | 1707 | }; |
1341 | 1708 | ||
1342 | static struct hda_input_mux alc880_test_capture_source = { | 1709 | static struct hda_input_mux alc880_test_capture_source = { |
1343 | .num_items = 5, | 1710 | .num_items = 7, |
1344 | .items = { | 1711 | .items = { |
1345 | { "In-1", 0x0 }, | 1712 | { "In-1", 0x0 }, |
1346 | { "In-2", 0x1 }, | 1713 | { "In-2", 0x1 }, |
1347 | { "In-3", 0x2 }, | 1714 | { "In-3", 0x2 }, |
1348 | { "In-4", 0x3 }, | 1715 | { "In-4", 0x3 }, |
1349 | { "CD", 0x4 }, | 1716 | { "CD", 0x4 }, |
1717 | { "Front", 0x5 }, | ||
1718 | { "Surround", 0x6 }, | ||
1350 | }, | 1719 | }, |
1351 | }; | 1720 | }; |
1352 | 1721 | ||
@@ -1653,6 +2022,8 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
1653 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, | 2022 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, |
1654 | { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, | 2023 | { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, |
1655 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG }, | 2024 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG }, |
2025 | { .pci_subvendor = 0xa0a0, .pci_subdevice = 0x0560, | ||
2026 | .config = ALC880_5ST_DIG }, /* Aopen i915GMm-HFS */ | ||
1656 | /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */ | 2027 | /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */ |
1657 | { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG }, | 2028 | { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG }, |
1658 | /* note subvendor = 0 below */ | 2029 | /* note subvendor = 0 below */ |
@@ -1680,6 +2051,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
1680 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG }, | 2051 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG }, |
1681 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG }, | 2052 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG }, |
1682 | { .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */ | 2053 | { .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */ |
2054 | { .pci_subvendor = 0x1509, .pci_subdevice = 0x925d, .config = ALC880_6ST_DIG }, /* FIC P4M-915GD1 */ | ||
1683 | 2055 | ||
1684 | { .modelname = "asus", .config = ALC880_ASUS }, | 2056 | { .modelname = "asus", .config = ALC880_ASUS }, |
1685 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG }, | 2057 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG }, |
@@ -1693,6 +2065,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
1693 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, | 2065 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, |
1694 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, | 2066 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, |
1695 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, | 2067 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, |
2068 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x8181, .config = ALC880_ASUS_DIG }, /* ASUS P4GPL-X */ | ||
1696 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 }, | 2069 | { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 }, |
1697 | 2070 | ||
1698 | { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, | 2071 | { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, |
@@ -1702,6 +2075,9 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
1702 | { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 }, | 2075 | { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 }, |
1703 | { .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 }, | 2076 | { .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 }, |
1704 | 2077 | ||
2078 | { .modelname = "lg", .config = ALC880_LG }, | ||
2079 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, | ||
2080 | |||
1705 | #ifdef CONFIG_SND_DEBUG | 2081 | #ifdef CONFIG_SND_DEBUG |
1706 | { .modelname = "test", .config = ALC880_TEST }, | 2082 | { .modelname = "test", .config = ALC880_TEST }, |
1707 | #endif | 2083 | #endif |
@@ -1879,6 +2255,19 @@ static struct alc_config_preset alc880_presets[] = { | |||
1879 | .channel_mode = alc880_threestack_modes, | 2255 | .channel_mode = alc880_threestack_modes, |
1880 | .input_mux = &alc880_capture_source, | 2256 | .input_mux = &alc880_capture_source, |
1881 | }, | 2257 | }, |
2258 | [ALC880_LG] = { | ||
2259 | .mixers = { alc880_lg_mixer }, | ||
2260 | .init_verbs = { alc880_volume_init_verbs, | ||
2261 | alc880_lg_init_verbs }, | ||
2262 | .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids), | ||
2263 | .dac_nids = alc880_lg_dac_nids, | ||
2264 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
2265 | .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), | ||
2266 | .channel_mode = alc880_lg_ch_modes, | ||
2267 | .input_mux = &alc880_lg_capture_source, | ||
2268 | .unsol_event = alc880_lg_unsol_event, | ||
2269 | .init_hook = alc880_lg_automute, | ||
2270 | }, | ||
1882 | #ifdef CONFIG_SND_DEBUG | 2271 | #ifdef CONFIG_SND_DEBUG |
1883 | [ALC880_TEST] = { | 2272 | [ALC880_TEST] = { |
1884 | .mixers = { alc880_test_mixer }, | 2273 | .mixers = { alc880_test_mixer }, |
@@ -2043,14 +2432,11 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
2043 | 2432 | ||
2044 | if (alc880_is_fixed_pin(pin)) { | 2433 | if (alc880_is_fixed_pin(pin)) { |
2045 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | 2434 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); |
2046 | if (! spec->multiout.dac_nids[0]) { | 2435 | /* specify the DAC as the extra output */ |
2047 | /* use this as the primary output */ | 2436 | if (! spec->multiout.hp_nid) |
2048 | spec->multiout.dac_nids[0] = nid; | ||
2049 | if (! spec->multiout.num_dacs) | ||
2050 | spec->multiout.num_dacs = 1; | ||
2051 | } else | ||
2052 | /* specify the DAC as the extra output */ | ||
2053 | spec->multiout.hp_nid = nid; | 2437 | spec->multiout.hp_nid = nid; |
2438 | else | ||
2439 | spec->multiout.extra_out_nid[0] = nid; | ||
2054 | /* control HP volume/switch on the output mixer amp */ | 2440 | /* control HP volume/switch on the output mixer amp */ |
2055 | nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); | 2441 | nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); |
2056 | sprintf(name, "%s Playback Volume", pfx); | 2442 | sprintf(name, "%s Playback Volume", pfx); |
@@ -2063,12 +2449,6 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
2063 | return err; | 2449 | return err; |
2064 | } else if (alc880_is_multi_pin(pin)) { | 2450 | } else if (alc880_is_multi_pin(pin)) { |
2065 | /* set manual connection */ | 2451 | /* set manual connection */ |
2066 | if (! spec->multiout.dac_nids[0]) { | ||
2067 | /* use this as the primary output */ | ||
2068 | spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin)); | ||
2069 | if (! spec->multiout.num_dacs) | ||
2070 | spec->multiout.num_dacs = 1; | ||
2071 | } | ||
2072 | /* we have only a switch on HP-out PIN */ | 2452 | /* we have only a switch on HP-out PIN */ |
2073 | sprintf(name, "%s Playback Switch", pfx); | 2453 | sprintf(name, "%s Playback Switch", pfx); |
2074 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | 2454 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, |
@@ -2152,7 +2532,7 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) | |||
2152 | struct alc_spec *spec = codec->spec; | 2532 | struct alc_spec *spec = codec->spec; |
2153 | hda_nid_t pin; | 2533 | hda_nid_t pin; |
2154 | 2534 | ||
2155 | pin = spec->autocfg.speaker_pin; | 2535 | pin = spec->autocfg.speaker_pins[0]; |
2156 | if (pin) /* connect to front */ | 2536 | if (pin) /* connect to front */ |
2157 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2537 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2158 | pin = spec->autocfg.hp_pin; | 2538 | pin = spec->autocfg.hp_pin; |
@@ -2188,15 +2568,15 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
2188 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 2568 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
2189 | alc880_ignore)) < 0) | 2569 | alc880_ignore)) < 0) |
2190 | return err; | 2570 | return err; |
2191 | if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && | 2571 | if (! spec->autocfg.line_outs) |
2192 | ! spec->autocfg.hp_pin) | ||
2193 | return 0; /* can't find valid BIOS pin config */ | 2572 | return 0; /* can't find valid BIOS pin config */ |
2194 | 2573 | ||
2195 | if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 2574 | if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || |
2196 | (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 2575 | (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
2197 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin, | 2576 | (err = alc880_auto_create_extra_out(spec, |
2577 | spec->autocfg.speaker_pins[0], | ||
2198 | "Speaker")) < 0 || | 2578 | "Speaker")) < 0 || |
2199 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin, | 2579 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin, |
2200 | "Headphone")) < 0 || | 2580 | "Headphone")) < 0 || |
2201 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2581 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2202 | return err; | 2582 | return err; |
@@ -2218,14 +2598,12 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
2218 | return 1; | 2598 | return 1; |
2219 | } | 2599 | } |
2220 | 2600 | ||
2221 | /* init callback for auto-configuration model -- overriding the default init */ | 2601 | /* additional initialization for auto-configuration model */ |
2222 | static int alc880_auto_init(struct hda_codec *codec) | 2602 | static void alc880_auto_init(struct hda_codec *codec) |
2223 | { | 2603 | { |
2224 | alc_init(codec); | ||
2225 | alc880_auto_init_multi_out(codec); | 2604 | alc880_auto_init_multi_out(codec); |
2226 | alc880_auto_init_extra_out(codec); | 2605 | alc880_auto_init_extra_out(codec); |
2227 | alc880_auto_init_analog_input(codec); | 2606 | alc880_auto_init_analog_input(codec); |
2228 | return 0; | ||
2229 | } | 2607 | } |
2230 | 2608 | ||
2231 | /* | 2609 | /* |
@@ -2292,7 +2670,7 @@ static int patch_alc880(struct hda_codec *codec) | |||
2292 | 2670 | ||
2293 | codec->patch_ops = alc_patch_ops; | 2671 | codec->patch_ops = alc_patch_ops; |
2294 | if (board_config == ALC880_AUTO) | 2672 | if (board_config == ALC880_AUTO) |
2295 | codec->patch_ops.init = alc880_auto_init; | 2673 | spec->init_hook = alc880_auto_init; |
2296 | 2674 | ||
2297 | return 0; | 2675 | return 0; |
2298 | } | 2676 | } |
@@ -2322,6 +2700,14 @@ static hda_nid_t alc260_hp_adc_nids[2] = { | |||
2322 | 0x05, 0x04 | 2700 | 0x05, 0x04 |
2323 | }; | 2701 | }; |
2324 | 2702 | ||
2703 | /* NIDs used when simultaneous access to both ADCs makes sense. Note that | ||
2704 | * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC. | ||
2705 | */ | ||
2706 | static hda_nid_t alc260_dual_adc_nids[2] = { | ||
2707 | /* ADC0, ADC1 */ | ||
2708 | 0x04, 0x05 | ||
2709 | }; | ||
2710 | |||
2325 | #define ALC260_DIGOUT_NID 0x03 | 2711 | #define ALC260_DIGOUT_NID 0x03 |
2326 | #define ALC260_DIGIN_NID 0x06 | 2712 | #define ALC260_DIGIN_NID 0x06 |
2327 | 2713 | ||
@@ -2335,14 +2721,28 @@ static struct hda_input_mux alc260_capture_source = { | |||
2335 | }, | 2721 | }, |
2336 | }; | 2722 | }; |
2337 | 2723 | ||
2338 | /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack | 2724 | /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, |
2339 | * and the internal CD lines. | 2725 | * headphone jack and the internal CD lines. |
2340 | */ | 2726 | */ |
2341 | static struct hda_input_mux alc260_fujitsu_capture_source = { | 2727 | static struct hda_input_mux alc260_fujitsu_capture_source = { |
2342 | .num_items = 2, | 2728 | .num_items = 3, |
2343 | .items = { | 2729 | .items = { |
2344 | { "Mic/Line", 0x0 }, | 2730 | { "Mic/Line", 0x0 }, |
2345 | { "CD", 0x4 }, | 2731 | { "CD", 0x4 }, |
2732 | { "Headphone", 0x2 }, | ||
2733 | }, | ||
2734 | }; | ||
2735 | |||
2736 | /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to | ||
2737 | * the Fujitsu S702x, but jacks are marked differently. We won't allow | ||
2738 | * retasking the Headphone jack, so it won't be available here. | ||
2739 | */ | ||
2740 | static struct hda_input_mux alc260_acer_capture_source = { | ||
2741 | .num_items = 3, | ||
2742 | .items = { | ||
2743 | { "Mic", 0x0 }, | ||
2744 | { "Line", 0x2 }, | ||
2745 | { "CD", 0x4 }, | ||
2346 | }, | 2746 | }, |
2347 | }; | 2747 | }; |
2348 | 2748 | ||
@@ -2363,6 +2763,7 @@ static struct hda_channel_mode alc260_modes[1] = { | |||
2363 | * HP: base_output + input + capture_alt | 2763 | * HP: base_output + input + capture_alt |
2364 | * HP_3013: hp_3013 + input + capture | 2764 | * HP_3013: hp_3013 + input + capture |
2365 | * fujitsu: fujitsu + capture | 2765 | * fujitsu: fujitsu + capture |
2766 | * acer: acer + capture | ||
2366 | */ | 2767 | */ |
2367 | 2768 | ||
2368 | static struct snd_kcontrol_new alc260_base_output_mixer[] = { | 2769 | static struct snd_kcontrol_new alc260_base_output_mixer[] = { |
@@ -2408,11 +2809,12 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { | |||
2408 | static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | 2809 | static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { |
2409 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 2810 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
2410 | HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), | 2811 | HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), |
2411 | ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP), | 2812 | ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT), |
2412 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 2813 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
2413 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 2814 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
2414 | HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), | 2815 | HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), |
2415 | HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), | 2816 | HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), |
2817 | ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
2416 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | 2818 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), |
2417 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | 2819 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), |
2418 | HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), | 2820 | HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), |
@@ -2420,6 +2822,22 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | |||
2420 | { } /* end */ | 2822 | { } /* end */ |
2421 | }; | 2823 | }; |
2422 | 2824 | ||
2825 | static struct snd_kcontrol_new alc260_acer_mixer[] = { | ||
2826 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
2827 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | ||
2828 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
2829 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
2830 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
2831 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
2832 | ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN), | ||
2833 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
2834 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
2835 | ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT), | ||
2836 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
2837 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
2838 | { } /* end */ | ||
2839 | }; | ||
2840 | |||
2423 | /* capture mixer elements */ | 2841 | /* capture mixer elements */ |
2424 | static struct snd_kcontrol_new alc260_capture_mixer[] = { | 2842 | static struct snd_kcontrol_new alc260_capture_mixer[] = { |
2425 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), | 2843 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), |
@@ -2629,52 +3047,327 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = { | |||
2629 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 3047 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
2630 | /* Headphone/Line-out jack connects to Line1 pin; make it an output */ | 3048 | /* Headphone/Line-out jack connects to Line1 pin; make it an output */ |
2631 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 3049 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
2632 | /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ | 3050 | /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ |
2633 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 3051 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
2634 | /* Ensure all other unused pins are disabled and muted. | 3052 | /* Ensure all other unused pins are disabled and muted. */ |
2635 | * Note: trying to set widget 0x15 to anything blocks all audio | 3053 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2636 | * output for some reason, so just leave that at the default. | 3054 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3055 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
3056 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3057 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
3058 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3059 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
3060 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3061 | |||
3062 | /* Disable digital (SPDIF) pins */ | ||
3063 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
3064 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
3065 | |||
3066 | /* Ensure Line1 pin widget takes its input from the OUT1 sum bus | ||
3067 | * when acting as an output. | ||
3068 | */ | ||
3069 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
3070 | |||
3071 | /* Start with output sum widgets muted and their output gains at min */ | ||
3072 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3073 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3074 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3075 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3076 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3077 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3078 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3079 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3080 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3081 | |||
3082 | /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ | ||
3083 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3084 | /* Unmute Line1 pin widget output buffer since it starts as an output. | ||
3085 | * If the pin mode is changed by the user the pin mode control will | ||
3086 | * take care of enabling the pin's input/output buffers as needed. | ||
3087 | * Therefore there's no need to enable the input buffer at this | ||
3088 | * stage. | ||
3089 | */ | ||
3090 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3091 | /* Unmute input buffer of pin widget used for Line-in (no equiv | ||
3092 | * mixer ctrl) | ||
3093 | */ | ||
3094 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3095 | |||
3096 | /* Mute capture amp left and right */ | ||
3097 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3098 | /* Set ADC connection select to match default mixer setting - line | ||
3099 | * in (on mic1 pin) | ||
2637 | */ | 3100 | */ |
2638 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 3101 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, |
2639 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3102 | |
3103 | /* Do the same for the second ADC: mute capture input amp and | ||
3104 | * set ADC connection to line in (on mic1 pin) | ||
3105 | */ | ||
3106 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3107 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
3108 | |||
3109 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
3110 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
3111 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
3112 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
3113 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
3114 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
3115 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
3116 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
3117 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
3118 | |||
3119 | { } | ||
3120 | }; | ||
3121 | |||
3122 | /* Initialisation sequence for ALC260 as configured in Acer TravelMate and | ||
3123 | * similar laptops (adapted from Fujitsu init verbs). | ||
3124 | */ | ||
3125 | static struct hda_verb alc260_acer_init_verbs[] = { | ||
3126 | /* On TravelMate laptops, GPIO 0 enables the internal speaker and | ||
3127 | * the headphone jack. Turn this on and rely on the standard mute | ||
3128 | * methods whenever the user wants to turn these outputs off. | ||
3129 | */ | ||
3130 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
3131 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
3132 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
3133 | /* Internal speaker/Headphone jack is connected to Line-out pin */ | ||
3134 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
3135 | /* Internal microphone/Mic jack is connected to Mic1 pin */ | ||
3136 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, | ||
3137 | /* Line In jack is connected to Line1 pin */ | ||
3138 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
3139 | /* Ensure all other unused pins are disabled and muted. */ | ||
3140 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
3141 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2640 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 3142 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2641 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3143 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2642 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 3144 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2643 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3145 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2644 | /* Disable digital (SPDIF) pins */ | 3146 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
2645 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | 3147 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2646 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | 3148 | /* Disable digital (SPDIF) pins */ |
2647 | 3149 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | |
2648 | /* Start with mixer outputs muted */ | 3150 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, |
2649 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3151 | |
2650 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3152 | /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum |
2651 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3153 | * bus when acting as outputs. |
2652 | 3154 | */ | |
2653 | /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ | 3155 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, |
2654 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 3156 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, |
2655 | /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */ | 3157 | |
2656 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 3158 | /* Start with output sum widgets muted and their output gains at min */ |
2657 | /* Unmute pin widget used for Line-in (no equiv mixer ctrl) */ | 3159 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2658 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 3160 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
2659 | 3161 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | |
2660 | /* Mute capture amp left and right */ | 3162 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2661 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3163 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
2662 | /* Set ADC connection select to line in (on mic1 pin) */ | 3164 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
2663 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | 3165 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2664 | 3166 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | |
2665 | /* Mute all inputs to mixer widget (even unconnected ones) */ | 3167 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
2666 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | 3168 | |
2667 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | 3169 | /* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */ |
2668 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | 3170 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
2669 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | 3171 | /* Unmute Mic1 and Line1 pin widget input buffers since they start as |
2670 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | 3172 | * inputs. If the pin mode is changed by the user the pin mode control |
2671 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | 3173 | * will take care of enabling the pin's input/output buffers as needed. |
2672 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | 3174 | * Therefore there's no need to enable the input buffer at this |
2673 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | 3175 | * stage. |
3176 | */ | ||
3177 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3178 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3179 | |||
3180 | /* Mute capture amp left and right */ | ||
3181 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3182 | /* Set ADC connection select to match default mixer setting - mic | ||
3183 | * (on mic1 pin) | ||
3184 | */ | ||
3185 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
3186 | |||
3187 | /* Do similar with the second ADC: mute capture input amp and | ||
3188 | * set ADC connection to line (on line1 pin) | ||
3189 | */ | ||
3190 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3191 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
3192 | |||
3193 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
3194 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
3195 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
3196 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
3197 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
3198 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
3199 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
3200 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
3201 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
2674 | 3202 | ||
2675 | { } | 3203 | { } |
2676 | }; | 3204 | }; |
2677 | 3205 | ||
3206 | /* Test configuration for debugging, modelled after the ALC880 test | ||
3207 | * configuration. | ||
3208 | */ | ||
3209 | #ifdef CONFIG_SND_DEBUG | ||
3210 | static hda_nid_t alc260_test_dac_nids[1] = { | ||
3211 | 0x02, | ||
3212 | }; | ||
3213 | static hda_nid_t alc260_test_adc_nids[2] = { | ||
3214 | 0x04, 0x05, | ||
3215 | }; | ||
3216 | /* This is a bit messy since the two input muxes in the ALC260 have slight | ||
3217 | * variations in their signal assignments. The ideal way to deal with this | ||
3218 | * is to extend alc_spec.input_mux to allow a different input MUX for each | ||
3219 | * ADC. For the purposes of the test model it's sufficient to just list | ||
3220 | * both options for affected signal indices. The separate input mux | ||
3221 | * functionality only needs to be considered if a model comes along which | ||
3222 | * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to | ||
3223 | * record. | ||
3224 | */ | ||
3225 | static struct hda_input_mux alc260_test_capture_source = { | ||
3226 | .num_items = 8, | ||
3227 | .items = { | ||
3228 | { "MIC1 pin", 0x0 }, | ||
3229 | { "MIC2 pin", 0x1 }, | ||
3230 | { "LINE1 pin", 0x2 }, | ||
3231 | { "LINE2 pin", 0x3 }, | ||
3232 | { "CD pin", 0x4 }, | ||
3233 | { "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 }, | ||
3234 | { "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 }, | ||
3235 | { "HP-OUT pin (cap2 only)", 0x7 }, | ||
3236 | }, | ||
3237 | }; | ||
3238 | static struct snd_kcontrol_new alc260_test_mixer[] = { | ||
3239 | /* Output driver widgets */ | ||
3240 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | ||
3241 | HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), | ||
3242 | HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
3243 | HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT), | ||
3244 | HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
3245 | HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), | ||
3246 | |||
3247 | /* Modes for retasking pin widgets */ | ||
3248 | ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), | ||
3249 | ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
3250 | ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), | ||
3251 | ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT), | ||
3252 | ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT), | ||
3253 | ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT), | ||
3254 | |||
3255 | /* Loopback mixer controls */ | ||
3256 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT), | ||
3257 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT), | ||
3258 | HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT), | ||
3259 | HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT), | ||
3260 | HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
3261 | HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
3262 | HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT), | ||
3263 | HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT), | ||
3264 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
3265 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
3266 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), | ||
3267 | HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), | ||
3268 | HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT), | ||
3269 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), | ||
3270 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), | ||
3271 | HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), | ||
3272 | |||
3273 | /* Controls for GPIO pins, assuming they are configured as outputs */ | ||
3274 | ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), | ||
3275 | ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), | ||
3276 | ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), | ||
3277 | ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), | ||
3278 | |||
3279 | /* Switches to allow the digital IO pins to be enabled. The datasheet | ||
3280 | * is ambigious as to which NID is which; testing on laptops which | ||
3281 | * make this output available should provide clarification. | ||
3282 | */ | ||
3283 | ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01), | ||
3284 | ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01), | ||
3285 | |||
3286 | { } /* end */ | ||
3287 | }; | ||
3288 | static struct hda_verb alc260_test_init_verbs[] = { | ||
3289 | /* Enable all GPIOs as outputs with an initial value of 0 */ | ||
3290 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f}, | ||
3291 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | ||
3292 | {0x01, AC_VERB_SET_GPIO_MASK, 0x0f}, | ||
3293 | |||
3294 | /* Enable retasking pins as output, initially without power amp */ | ||
3295 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3296 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3297 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3298 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3299 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3300 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3301 | |||
3302 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
3303 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
3304 | * payload also sets the generation to 0, output to be in "consumer" | ||
3305 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
3306 | * control. | ||
3307 | */ | ||
3308 | {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
3309 | {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
3310 | |||
3311 | /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the | ||
3312 | * OUT1 sum bus when acting as an output. | ||
3313 | */ | ||
3314 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
3315 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0}, | ||
3316 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0}, | ||
3317 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0}, | ||
3318 | |||
3319 | /* Start with output sum widgets muted and their output gains at min */ | ||
3320 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3321 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3322 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3323 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3324 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3325 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3326 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3327 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3328 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3329 | |||
3330 | /* Unmute retasking pin widget output buffers since the default | ||
3331 | * state appears to be output. As the pin mode is changed by the | ||
3332 | * user the pin mode control will take care of enabling the pin's | ||
3333 | * input/output buffers as needed. | ||
3334 | */ | ||
3335 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3336 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3337 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3338 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3339 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3340 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3341 | /* Also unmute the mono-out pin widget */ | ||
3342 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
3343 | |||
3344 | /* Mute capture amp left and right */ | ||
3345 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3346 | /* Set ADC connection select to match default mixer setting (mic1 | ||
3347 | * pin) | ||
3348 | */ | ||
3349 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
3350 | |||
3351 | /* Do the same for the second ADC: mute capture input amp and | ||
3352 | * set ADC connection to mic1 pin | ||
3353 | */ | ||
3354 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3355 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
3356 | |||
3357 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
3358 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
3359 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
3360 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
3361 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
3362 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
3363 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
3364 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
3365 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
3366 | |||
3367 | { } | ||
3368 | }; | ||
3369 | #endif | ||
3370 | |||
2678 | static struct hda_pcm_stream alc260_pcm_analog_playback = { | 3371 | static struct hda_pcm_stream alc260_pcm_analog_playback = { |
2679 | .substreams = 1, | 3372 | .substreams = 1, |
2680 | .channels_min = 2, | 3373 | .channels_min = 2, |
@@ -2744,7 +3437,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
2744 | return err; | 3437 | return err; |
2745 | } | 3438 | } |
2746 | 3439 | ||
2747 | nid = cfg->speaker_pin; | 3440 | nid = cfg->speaker_pins[0]; |
2748 | if (nid) { | 3441 | if (nid) { |
2749 | err = alc260_add_playback_controls(spec, nid, "Speaker"); | 3442 | err = alc260_add_playback_controls(spec, nid, "Speaker"); |
2750 | if (err < 0) | 3443 | if (err < 0) |
@@ -2817,7 +3510,7 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
2817 | if (nid) | 3510 | if (nid) |
2818 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3511 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
2819 | 3512 | ||
2820 | nid = spec->autocfg.speaker_pin; | 3513 | nid = spec->autocfg.speaker_pins[0]; |
2821 | if (nid) | 3514 | if (nid) |
2822 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3515 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
2823 | 3516 | ||
@@ -2932,13 +3625,11 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
2932 | return 1; | 3625 | return 1; |
2933 | } | 3626 | } |
2934 | 3627 | ||
2935 | /* init callback for auto-configuration model -- overriding the default init */ | 3628 | /* additional initialization for auto-configuration model */ |
2936 | static int alc260_auto_init(struct hda_codec *codec) | 3629 | static void alc260_auto_init(struct hda_codec *codec) |
2937 | { | 3630 | { |
2938 | alc_init(codec); | ||
2939 | alc260_auto_init_multi_out(codec); | 3631 | alc260_auto_init_multi_out(codec); |
2940 | alc260_auto_init_analog_input(codec); | 3632 | alc260_auto_init_analog_input(codec); |
2941 | return 0; | ||
2942 | } | 3633 | } |
2943 | 3634 | ||
2944 | /* | 3635 | /* |
@@ -2948,6 +3639,8 @@ static struct hda_board_config alc260_cfg_tbl[] = { | |||
2948 | { .modelname = "basic", .config = ALC260_BASIC }, | 3639 | { .modelname = "basic", .config = ALC260_BASIC }, |
2949 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, | 3640 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, |
2950 | .config = ALC260_BASIC }, /* Sony VAIO */ | 3641 | .config = ALC260_BASIC }, /* Sony VAIO */ |
3642 | { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, | ||
3643 | .config = ALC260_BASIC }, /* CTL Travel Master U553W */ | ||
2951 | { .modelname = "hp", .config = ALC260_HP }, | 3644 | { .modelname = "hp", .config = ALC260_HP }, |
2952 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, | 3645 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, |
2953 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, | 3646 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, |
@@ -2958,6 +3651,11 @@ static struct hda_board_config alc260_cfg_tbl[] = { | |||
2958 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP }, | 3651 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP }, |
2959 | { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X }, | 3652 | { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X }, |
2960 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X }, | 3653 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X }, |
3654 | { .modelname = "acer", .config = ALC260_ACER }, | ||
3655 | { .pci_subvendor = 0x1025, .pci_subdevice = 0x008f, .config = ALC260_ACER }, | ||
3656 | #ifdef CONFIG_SND_DEBUG | ||
3657 | { .modelname = "test", .config = ALC260_TEST }, | ||
3658 | #endif | ||
2961 | { .modelname = "auto", .config = ALC260_AUTO }, | 3659 | { .modelname = "auto", .config = ALC260_AUTO }, |
2962 | {} | 3660 | {} |
2963 | }; | 3661 | }; |
@@ -3009,12 +3707,38 @@ static struct alc_config_preset alc260_presets[] = { | |||
3009 | .init_verbs = { alc260_fujitsu_init_verbs }, | 3707 | .init_verbs = { alc260_fujitsu_init_verbs }, |
3010 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 3708 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
3011 | .dac_nids = alc260_dac_nids, | 3709 | .dac_nids = alc260_dac_nids, |
3012 | .num_adc_nids = ARRAY_SIZE(alc260_adc_nids), | 3710 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), |
3013 | .adc_nids = alc260_adc_nids, | 3711 | .adc_nids = alc260_dual_adc_nids, |
3014 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 3712 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
3015 | .channel_mode = alc260_modes, | 3713 | .channel_mode = alc260_modes, |
3016 | .input_mux = &alc260_fujitsu_capture_source, | 3714 | .input_mux = &alc260_fujitsu_capture_source, |
3017 | }, | 3715 | }, |
3716 | [ALC260_ACER] = { | ||
3717 | .mixers = { alc260_acer_mixer, | ||
3718 | alc260_capture_mixer }, | ||
3719 | .init_verbs = { alc260_acer_init_verbs }, | ||
3720 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | ||
3721 | .dac_nids = alc260_dac_nids, | ||
3722 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | ||
3723 | .adc_nids = alc260_dual_adc_nids, | ||
3724 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
3725 | .channel_mode = alc260_modes, | ||
3726 | .input_mux = &alc260_acer_capture_source, | ||
3727 | }, | ||
3728 | #ifdef CONFIG_SND_DEBUG | ||
3729 | [ALC260_TEST] = { | ||
3730 | .mixers = { alc260_test_mixer, | ||
3731 | alc260_capture_mixer }, | ||
3732 | .init_verbs = { alc260_test_init_verbs }, | ||
3733 | .num_dacs = ARRAY_SIZE(alc260_test_dac_nids), | ||
3734 | .dac_nids = alc260_test_dac_nids, | ||
3735 | .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids), | ||
3736 | .adc_nids = alc260_test_adc_nids, | ||
3737 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | ||
3738 | .channel_mode = alc260_modes, | ||
3739 | .input_mux = &alc260_test_capture_source, | ||
3740 | }, | ||
3741 | #endif | ||
3018 | }; | 3742 | }; |
3019 | 3743 | ||
3020 | static int patch_alc260(struct hda_codec *codec) | 3744 | static int patch_alc260(struct hda_codec *codec) |
@@ -3059,7 +3783,7 @@ static int patch_alc260(struct hda_codec *codec) | |||
3059 | 3783 | ||
3060 | codec->patch_ops = alc_patch_ops; | 3784 | codec->patch_ops = alc_patch_ops; |
3061 | if (board_config == ALC260_AUTO) | 3785 | if (board_config == ALC260_AUTO) |
3062 | codec->patch_ops.init = alc260_auto_init; | 3786 | spec->init_hook = alc260_auto_init; |
3063 | 3787 | ||
3064 | return 0; | 3788 | return 0; |
3065 | } | 3789 | } |
@@ -3534,14 +4258,12 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
3534 | return err; | 4258 | return err; |
3535 | } | 4259 | } |
3536 | 4260 | ||
3537 | /* init callback for auto-configuration model -- overriding the default init */ | 4261 | /* additional initialization for auto-configuration model */ |
3538 | static int alc882_auto_init(struct hda_codec *codec) | 4262 | static void alc882_auto_init(struct hda_codec *codec) |
3539 | { | 4263 | { |
3540 | alc_init(codec); | ||
3541 | alc882_auto_init_multi_out(codec); | 4264 | alc882_auto_init_multi_out(codec); |
3542 | alc882_auto_init_hp_out(codec); | 4265 | alc882_auto_init_hp_out(codec); |
3543 | alc882_auto_init_analog_input(codec); | 4266 | alc882_auto_init_analog_input(codec); |
3544 | return 0; | ||
3545 | } | 4267 | } |
3546 | 4268 | ||
3547 | /* | 4269 | /* |
@@ -3608,7 +4330,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
3608 | 4330 | ||
3609 | codec->patch_ops = alc_patch_ops; | 4331 | codec->patch_ops = alc_patch_ops; |
3610 | if (board_config == ALC882_AUTO) | 4332 | if (board_config == ALC882_AUTO) |
3611 | codec->patch_ops.init = alc882_auto_init; | 4333 | spec->init_hook = alc882_auto_init; |
3612 | 4334 | ||
3613 | return 0; | 4335 | return 0; |
3614 | } | 4336 | } |
@@ -3644,19 +4366,9 @@ static struct snd_kcontrol_new alc262_base_mixer[] = { | |||
3644 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 4366 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
3645 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 4367 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
3646 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | 4368 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), |
3647 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
3648 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
3649 | { | ||
3650 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3651 | .name = "Capture Source", | ||
3652 | .count = 1, | ||
3653 | .info = alc882_mux_enum_info, | ||
3654 | .get = alc882_mux_enum_get, | ||
3655 | .put = alc882_mux_enum_put, | ||
3656 | }, | ||
3657 | { } /* end */ | 4369 | { } /* end */ |
3658 | }; | 4370 | }; |
3659 | 4371 | ||
3660 | #define alc262_capture_mixer alc882_capture_mixer | 4372 | #define alc262_capture_mixer alc882_capture_mixer |
3661 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer | 4373 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer |
3662 | 4374 | ||
@@ -3739,6 +4451,129 @@ static struct hda_verb alc262_init_verbs[] = { | |||
3739 | { } | 4451 | { } |
3740 | }; | 4452 | }; |
3741 | 4453 | ||
4454 | /* | ||
4455 | * fujitsu model | ||
4456 | * 0x14 = headphone/spdif-out, 0x15 = internal speaker | ||
4457 | */ | ||
4458 | |||
4459 | #define ALC_HP_EVENT 0x37 | ||
4460 | |||
4461 | static struct hda_verb alc262_fujitsu_unsol_verbs[] = { | ||
4462 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
4463 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
4464 | {} | ||
4465 | }; | ||
4466 | |||
4467 | static struct hda_input_mux alc262_fujitsu_capture_source = { | ||
4468 | .num_items = 2, | ||
4469 | .items = { | ||
4470 | { "Mic", 0x0 }, | ||
4471 | { "CD", 0x4 }, | ||
4472 | }, | ||
4473 | }; | ||
4474 | |||
4475 | /* mute/unmute internal speaker according to the hp jack and mute state */ | ||
4476 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) | ||
4477 | { | ||
4478 | struct alc_spec *spec = codec->spec; | ||
4479 | unsigned int mute; | ||
4480 | |||
4481 | if (force || ! spec->sense_updated) { | ||
4482 | unsigned int present; | ||
4483 | /* need to execute and sync at first */ | ||
4484 | snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); | ||
4485 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
4486 | AC_VERB_GET_PIN_SENSE, 0); | ||
4487 | spec->jack_present = (present & 0x80000000) != 0; | ||
4488 | spec->sense_updated = 1; | ||
4489 | } | ||
4490 | if (spec->jack_present) { | ||
4491 | /* mute internal speaker */ | ||
4492 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
4493 | 0x80, 0x80); | ||
4494 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
4495 | 0x80, 0x80); | ||
4496 | } else { | ||
4497 | /* unmute internal speaker if necessary */ | ||
4498 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); | ||
4499 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
4500 | 0x80, mute & 0x80); | ||
4501 | mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0); | ||
4502 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
4503 | 0x80, mute & 0x80); | ||
4504 | } | ||
4505 | } | ||
4506 | |||
4507 | /* unsolicited event for HP jack sensing */ | ||
4508 | static void alc262_fujitsu_unsol_event(struct hda_codec *codec, | ||
4509 | unsigned int res) | ||
4510 | { | ||
4511 | if ((res >> 26) != ALC_HP_EVENT) | ||
4512 | return; | ||
4513 | alc262_fujitsu_automute(codec, 1); | ||
4514 | } | ||
4515 | |||
4516 | /* bind volumes of both NID 0x0c and 0x0d */ | ||
4517 | static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol, | ||
4518 | struct snd_ctl_elem_value *ucontrol) | ||
4519 | { | ||
4520 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4521 | long *valp = ucontrol->value.integer.value; | ||
4522 | int change; | ||
4523 | |||
4524 | change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, | ||
4525 | 0x7f, valp[0] & 0x7f); | ||
4526 | change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, | ||
4527 | 0x7f, valp[1] & 0x7f); | ||
4528 | snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, | ||
4529 | 0x7f, valp[0] & 0x7f); | ||
4530 | snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, | ||
4531 | 0x7f, valp[1] & 0x7f); | ||
4532 | return change; | ||
4533 | } | ||
4534 | |||
4535 | /* bind hp and internal speaker mute (with plug check) */ | ||
4536 | static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, | ||
4537 | struct snd_ctl_elem_value *ucontrol) | ||
4538 | { | ||
4539 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4540 | long *valp = ucontrol->value.integer.value; | ||
4541 | int change; | ||
4542 | |||
4543 | change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
4544 | 0x80, valp[0] ? 0 : 0x80); | ||
4545 | change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
4546 | 0x80, valp[1] ? 0 : 0x80); | ||
4547 | if (change || codec->in_resume) | ||
4548 | alc262_fujitsu_automute(codec, codec->in_resume); | ||
4549 | return change; | ||
4550 | } | ||
4551 | |||
4552 | static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | ||
4553 | { | ||
4554 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4555 | .name = "Master Playback Volume", | ||
4556 | .info = snd_hda_mixer_amp_volume_info, | ||
4557 | .get = snd_hda_mixer_amp_volume_get, | ||
4558 | .put = alc262_fujitsu_master_vol_put, | ||
4559 | .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), | ||
4560 | }, | ||
4561 | { | ||
4562 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4563 | .name = "Master Playback Switch", | ||
4564 | .info = snd_hda_mixer_amp_switch_info, | ||
4565 | .get = snd_hda_mixer_amp_switch_get, | ||
4566 | .put = alc262_fujitsu_master_sw_put, | ||
4567 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | ||
4568 | }, | ||
4569 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
4570 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
4571 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
4572 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
4573 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
4574 | { } /* end */ | ||
4575 | }; | ||
4576 | |||
3742 | /* add playback controls from the parsed DAC table */ | 4577 | /* add playback controls from the parsed DAC table */ |
3743 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | 4578 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) |
3744 | { | 4579 | { |
@@ -3759,7 +4594,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
3759 | return err; | 4594 | return err; |
3760 | } | 4595 | } |
3761 | 4596 | ||
3762 | nid = cfg->speaker_pin; | 4597 | nid = cfg->speaker_pins[0]; |
3763 | if (nid) { | 4598 | if (nid) { |
3764 | if (nid == 0x16) { | 4599 | if (nid == 0x16) { |
3765 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", | 4600 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", |
@@ -3769,10 +4604,6 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
3769 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 4604 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) |
3770 | return err; | 4605 | return err; |
3771 | } else { | 4606 | } else { |
3772 | if (! cfg->line_out_pins[0]) | ||
3773 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", | ||
3774 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0) | ||
3775 | return err; | ||
3776 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", | 4607 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", |
3777 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 4608 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) |
3778 | return err; | 4609 | return err; |
@@ -3789,10 +4620,6 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
3789 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 4620 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) |
3790 | return err; | 4621 | return err; |
3791 | } else { | 4622 | } else { |
3792 | if (! cfg->line_out_pins[0]) | ||
3793 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", | ||
3794 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0) | ||
3795 | return err; | ||
3796 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | 4623 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", |
3797 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 4624 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) |
3798 | return err; | 4625 | return err; |
@@ -3886,8 +4713,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
3886 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 4713 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
3887 | alc262_ignore)) < 0) | 4714 | alc262_ignore)) < 0) |
3888 | return err; | 4715 | return err; |
3889 | if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && | 4716 | if (! spec->autocfg.line_outs) |
3890 | ! spec->autocfg.hp_pin) | ||
3891 | return 0; /* can't find valid BIOS pin config */ | 4717 | return 0; /* can't find valid BIOS pin config */ |
3892 | if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 4718 | if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
3893 | (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 4719 | (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
@@ -3915,13 +4741,11 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
3915 | 4741 | ||
3916 | 4742 | ||
3917 | /* init callback for auto-configuration model -- overriding the default init */ | 4743 | /* init callback for auto-configuration model -- overriding the default init */ |
3918 | static int alc262_auto_init(struct hda_codec *codec) | 4744 | static void alc262_auto_init(struct hda_codec *codec) |
3919 | { | 4745 | { |
3920 | alc_init(codec); | ||
3921 | alc262_auto_init_multi_out(codec); | 4746 | alc262_auto_init_multi_out(codec); |
3922 | alc262_auto_init_hp_out(codec); | 4747 | alc262_auto_init_hp_out(codec); |
3923 | alc262_auto_init_analog_input(codec); | 4748 | alc262_auto_init_analog_input(codec); |
3924 | return 0; | ||
3925 | } | 4749 | } |
3926 | 4750 | ||
3927 | /* | 4751 | /* |
@@ -3929,6 +4753,8 @@ static int alc262_auto_init(struct hda_codec *codec) | |||
3929 | */ | 4753 | */ |
3930 | static struct hda_board_config alc262_cfg_tbl[] = { | 4754 | static struct hda_board_config alc262_cfg_tbl[] = { |
3931 | { .modelname = "basic", .config = ALC262_BASIC }, | 4755 | { .modelname = "basic", .config = ALC262_BASIC }, |
4756 | { .modelname = "fujitsu", .config = ALC262_FUJITSU }, | ||
4757 | { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, .config = ALC262_FUJITSU }, | ||
3932 | { .modelname = "auto", .config = ALC262_AUTO }, | 4758 | { .modelname = "auto", .config = ALC262_AUTO }, |
3933 | {} | 4759 | {} |
3934 | }; | 4760 | }; |
@@ -3944,6 +4770,18 @@ static struct alc_config_preset alc262_presets[] = { | |||
3944 | .channel_mode = alc262_modes, | 4770 | .channel_mode = alc262_modes, |
3945 | .input_mux = &alc262_capture_source, | 4771 | .input_mux = &alc262_capture_source, |
3946 | }, | 4772 | }, |
4773 | [ALC262_FUJITSU] = { | ||
4774 | .mixers = { alc262_fujitsu_mixer }, | ||
4775 | .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs }, | ||
4776 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
4777 | .dac_nids = alc262_dac_nids, | ||
4778 | .hp_nid = 0x03, | ||
4779 | .dig_out_nid = ALC262_DIGOUT_NID, | ||
4780 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
4781 | .channel_mode = alc262_modes, | ||
4782 | .input_mux = &alc262_fujitsu_capture_source, | ||
4783 | .unsol_event = alc262_fujitsu_unsol_event, | ||
4784 | }, | ||
3947 | }; | 4785 | }; |
3948 | 4786 | ||
3949 | static int patch_alc262(struct hda_codec *codec) | 4787 | static int patch_alc262(struct hda_codec *codec) |
@@ -4017,8 +4855,8 @@ static int patch_alc262(struct hda_codec *codec) | |||
4017 | 4855 | ||
4018 | codec->patch_ops = alc_patch_ops; | 4856 | codec->patch_ops = alc_patch_ops; |
4019 | if (board_config == ALC262_AUTO) | 4857 | if (board_config == ALC262_AUTO) |
4020 | codec->patch_ops.init = alc262_auto_init; | 4858 | spec->init_hook = alc262_auto_init; |
4021 | 4859 | ||
4022 | return 0; | 4860 | return 0; |
4023 | } | 4861 | } |
4024 | 4862 | ||
@@ -4549,8 +5387,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
4549 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 5387 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
4550 | alc861_ignore)) < 0) | 5388 | alc861_ignore)) < 0) |
4551 | return err; | 5389 | return err; |
4552 | if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && | 5390 | if (! spec->autocfg.line_outs) |
4553 | ! spec->autocfg.hp_pin) | ||
4554 | return 0; /* can't find valid BIOS pin config */ | 5391 | return 0; /* can't find valid BIOS pin config */ |
4555 | 5392 | ||
4556 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 5393 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || |
@@ -4579,15 +5416,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
4579 | return 1; | 5416 | return 1; |
4580 | } | 5417 | } |
4581 | 5418 | ||
4582 | /* init callback for auto-configuration model -- overriding the default init */ | 5419 | /* additional initialization for auto-configuration model */ |
4583 | static int alc861_auto_init(struct hda_codec *codec) | 5420 | static void alc861_auto_init(struct hda_codec *codec) |
4584 | { | 5421 | { |
4585 | alc_init(codec); | ||
4586 | alc861_auto_init_multi_out(codec); | 5422 | alc861_auto_init_multi_out(codec); |
4587 | alc861_auto_init_hp_out(codec); | 5423 | alc861_auto_init_hp_out(codec); |
4588 | alc861_auto_init_analog_input(codec); | 5424 | alc861_auto_init_analog_input(codec); |
4589 | |||
4590 | return 0; | ||
4591 | } | 5425 | } |
4592 | 5426 | ||
4593 | 5427 | ||
@@ -4685,7 +5519,7 @@ static int patch_alc861(struct hda_codec *codec) | |||
4685 | 5519 | ||
4686 | codec->patch_ops = alc_patch_ops; | 5520 | codec->patch_ops = alc_patch_ops; |
4687 | if (board_config == ALC861_AUTO) | 5521 | if (board_config == ALC861_AUTO) |
4688 | codec->patch_ops.init = alc861_auto_init; | 5522 | spec->init_hook = alc861_auto_init; |
4689 | 5523 | ||
4690 | return 0; | 5524 | return 0; |
4691 | } | 5525 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 35c2823a0a2b..b56ca4019392 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -51,6 +51,7 @@ struct sigmatel_spec { | |||
51 | unsigned int line_switch: 1; | 51 | unsigned int line_switch: 1; |
52 | unsigned int mic_switch: 1; | 52 | unsigned int mic_switch: 1; |
53 | unsigned int alt_switch: 1; | 53 | unsigned int alt_switch: 1; |
54 | unsigned int hp_detect: 1; | ||
54 | 55 | ||
55 | /* playback */ | 56 | /* playback */ |
56 | struct hda_multi_out multiout; | 57 | struct hda_multi_out multiout; |
@@ -303,6 +304,12 @@ static struct hda_board_config stac922x_cfg_tbl[] = { | |||
303 | .pci_subdevice = 0x0101, | 304 | .pci_subdevice = 0x0101, |
304 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ | 305 | .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ |
305 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 306 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
307 | .pci_subdevice = 0x0202, | ||
308 | .config = STAC_D945GTP3 }, /* Intel D945GNT - 3 Stack, 9221 A1 */ | ||
309 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
310 | .pci_subdevice = 0x0b0b, | ||
311 | .config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack, 9221 A1 */ | ||
312 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
306 | .pci_subdevice = 0x0404, | 313 | .pci_subdevice = 0x0404, |
307 | .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */ | 314 | .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */ |
308 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 315 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
@@ -691,13 +698,7 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct aut | |||
691 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 698 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; |
692 | } | 699 | } |
693 | 700 | ||
694 | if (cfg->line_outs) | 701 | spec->multiout.num_dacs = cfg->line_outs; |
695 | spec->multiout.num_dacs = cfg->line_outs; | ||
696 | else if (cfg->hp_pin) { | ||
697 | spec->multiout.dac_nids[0] = snd_hda_codec_read(codec, cfg->hp_pin, 0, | ||
698 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
699 | spec->multiout.num_dacs = 1; | ||
700 | } | ||
701 | 702 | ||
702 | return 0; | 703 | return 0; |
703 | } | 704 | } |
@@ -766,11 +767,13 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin | |||
766 | return 0; | 767 | return 0; |
767 | 768 | ||
768 | wid_caps = get_wcaps(codec, pin); | 769 | wid_caps = get_wcaps(codec, pin); |
769 | if (wid_caps & AC_WCAP_UNSOL_CAP) | 770 | if (wid_caps & AC_WCAP_UNSOL_CAP) { |
770 | /* Enable unsolicited responses on the HP widget */ | 771 | /* Enable unsolicited responses on the HP widget */ |
771 | snd_hda_codec_write(codec, pin, 0, | 772 | snd_hda_codec_write(codec, pin, 0, |
772 | AC_VERB_SET_UNSOLICITED_ENABLE, | 773 | AC_VERB_SET_UNSOLICITED_ENABLE, |
773 | STAC_UNSOL_ENABLE); | 774 | STAC_UNSOL_ENABLE); |
775 | spec->hp_detect = 1; | ||
776 | } | ||
774 | 777 | ||
775 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 778 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; |
776 | for (i = 0; i < cfg->line_outs; i++) { | 779 | for (i = 0; i < cfg->line_outs; i++) { |
@@ -804,9 +807,6 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
804 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 807 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
805 | int index = -1; | 808 | int index = -1; |
806 | if (cfg->input_pins[i]) { | 809 | if (cfg->input_pins[i]) { |
807 | /* Enable active pin widget as an input */ | ||
808 | stac92xx_auto_set_pinctl(codec, cfg->input_pins[i], AC_PINCTL_IN_EN); | ||
809 | |||
810 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 810 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; |
811 | 811 | ||
812 | for (j=0; j<spec->num_muxes; j++) { | 812 | for (j=0; j<spec->num_muxes; j++) { |
@@ -855,10 +855,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
855 | 855 | ||
856 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) | 856 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) |
857 | return err; | 857 | return err; |
858 | if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) | 858 | if (! spec->autocfg.line_outs) |
859 | return 0; /* can't find valid pin config */ | 859 | return 0; /* can't find valid pin config */ |
860 | stac92xx_auto_init_multi_out(codec); | ||
861 | stac92xx_auto_init_hp_out(codec); | ||
862 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) | 860 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) |
863 | return err; | 861 | return err; |
864 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 862 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) |
@@ -873,14 +871,10 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
873 | if (spec->multiout.max_channels > 2) | 871 | if (spec->multiout.max_channels > 2) |
874 | spec->surr_switch = 1; | 872 | spec->surr_switch = 1; |
875 | 873 | ||
876 | if (spec->autocfg.dig_out_pin) { | 874 | if (spec->autocfg.dig_out_pin) |
877 | spec->multiout.dig_out_nid = dig_out; | 875 | spec->multiout.dig_out_nid = dig_out; |
878 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | 876 | if (spec->autocfg.dig_in_pin) |
879 | } | ||
880 | if (spec->autocfg.dig_in_pin) { | ||
881 | spec->dig_in_nid = dig_in; | 877 | spec->dig_in_nid = dig_in; |
882 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | ||
883 | } | ||
884 | 878 | ||
885 | if (spec->kctl_alloc) | 879 | if (spec->kctl_alloc) |
886 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 880 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
@@ -890,6 +884,29 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
890 | return 1; | 884 | return 1; |
891 | } | 885 | } |
892 | 886 | ||
887 | /* add playback controls for HP output */ | ||
888 | static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | ||
889 | struct auto_pin_cfg *cfg) | ||
890 | { | ||
891 | struct sigmatel_spec *spec = codec->spec; | ||
892 | hda_nid_t pin = cfg->hp_pin; | ||
893 | unsigned int wid_caps; | ||
894 | |||
895 | if (! pin) | ||
896 | return 0; | ||
897 | |||
898 | wid_caps = get_wcaps(codec, pin); | ||
899 | if (wid_caps & AC_WCAP_UNSOL_CAP) { | ||
900 | /* Enable unsolicited responses on the HP widget */ | ||
901 | snd_hda_codec_write(codec, pin, 0, | ||
902 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
903 | STAC_UNSOL_ENABLE); | ||
904 | spec->hp_detect = 1; | ||
905 | } | ||
906 | |||
907 | return 0; | ||
908 | } | ||
909 | |||
893 | static int stac9200_parse_auto_config(struct hda_codec *codec) | 910 | static int stac9200_parse_auto_config(struct hda_codec *codec) |
894 | { | 911 | { |
895 | struct sigmatel_spec *spec = codec->spec; | 912 | struct sigmatel_spec *spec = codec->spec; |
@@ -901,14 +918,13 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
901 | if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | 918 | if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) |
902 | return err; | 919 | return err; |
903 | 920 | ||
904 | if (spec->autocfg.dig_out_pin) { | 921 | if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) |
922 | return err; | ||
923 | |||
924 | if (spec->autocfg.dig_out_pin) | ||
905 | spec->multiout.dig_out_nid = 0x05; | 925 | spec->multiout.dig_out_nid = 0x05; |
906 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | 926 | if (spec->autocfg.dig_in_pin) |
907 | } | ||
908 | if (spec->autocfg.dig_in_pin) { | ||
909 | spec->dig_in_nid = 0x04; | 927 | spec->dig_in_nid = 0x04; |
910 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | ||
911 | } | ||
912 | 928 | ||
913 | if (spec->kctl_alloc) | 929 | if (spec->kctl_alloc) |
914 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 930 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
@@ -921,9 +937,31 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
921 | static int stac92xx_init(struct hda_codec *codec) | 937 | static int stac92xx_init(struct hda_codec *codec) |
922 | { | 938 | { |
923 | struct sigmatel_spec *spec = codec->spec; | 939 | struct sigmatel_spec *spec = codec->spec; |
940 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
941 | int i; | ||
924 | 942 | ||
925 | snd_hda_sequence_write(codec, spec->init); | 943 | snd_hda_sequence_write(codec, spec->init); |
926 | 944 | ||
945 | /* set up pins */ | ||
946 | if (spec->hp_detect) { | ||
947 | /* fake event to set up pins */ | ||
948 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
949 | } else { | ||
950 | stac92xx_auto_init_multi_out(codec); | ||
951 | stac92xx_auto_init_hp_out(codec); | ||
952 | } | ||
953 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
954 | if (cfg->input_pins[i]) | ||
955 | stac92xx_auto_set_pinctl(codec, cfg->input_pins[i], | ||
956 | AC_PINCTL_IN_EN); | ||
957 | } | ||
958 | if (cfg->dig_out_pin) | ||
959 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, | ||
960 | AC_PINCTL_OUT_EN); | ||
961 | if (cfg->dig_in_pin) | ||
962 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, | ||
963 | AC_PINCTL_IN_EN); | ||
964 | |||
927 | return 0; | 965 | return 0; |
928 | } | 966 | } |
929 | 967 | ||
@@ -1142,6 +1180,166 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1142 | } | 1180 | } |
1143 | 1181 | ||
1144 | /* | 1182 | /* |
1183 | * STAC 7661(?) hack | ||
1184 | */ | ||
1185 | |||
1186 | /* static config for Sony VAIO FE550G */ | ||
1187 | static hda_nid_t vaio_dacs[] = { 0x2 }; | ||
1188 | #define VAIO_HP_DAC 0x5 | ||
1189 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | ||
1190 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; | ||
1191 | |||
1192 | static struct hda_input_mux vaio_mux = { | ||
1193 | .num_items = 2, | ||
1194 | .items = { | ||
1195 | /* { "HP", 0x0 }, | ||
1196 | { "Unknown", 0x1 }, */ | ||
1197 | { "Mic", 0x2 }, | ||
1198 | { "PCM", 0x3 }, | ||
1199 | } | ||
1200 | }; | ||
1201 | |||
1202 | static struct hda_verb vaio_init[] = { | ||
1203 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | ||
1204 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | ||
1205 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | ||
1206 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | ||
1207 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | ||
1208 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */ | ||
1209 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | ||
1210 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | ||
1211 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | ||
1212 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | ||
1213 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | ||
1214 | {} | ||
1215 | }; | ||
1216 | |||
1217 | /* bind volumes of both NID 0x02 and 0x05 */ | ||
1218 | static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, | ||
1219 | struct snd_ctl_elem_value *ucontrol) | ||
1220 | { | ||
1221 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1222 | long *valp = ucontrol->value.integer.value; | ||
1223 | int change; | ||
1224 | |||
1225 | change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, | ||
1226 | 0x7f, valp[0] & 0x7f); | ||
1227 | change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, | ||
1228 | 0x7f, valp[1] & 0x7f); | ||
1229 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | ||
1230 | 0x7f, valp[0] & 0x7f); | ||
1231 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
1232 | 0x7f, valp[1] & 0x7f); | ||
1233 | return change; | ||
1234 | } | ||
1235 | |||
1236 | /* bind volumes of both NID 0x02 and 0x05 */ | ||
1237 | static int vaio_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1238 | struct snd_ctl_elem_value *ucontrol) | ||
1239 | { | ||
1240 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1241 | long *valp = ucontrol->value.integer.value; | ||
1242 | int change; | ||
1243 | |||
1244 | change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, | ||
1245 | 0x80, valp[0] & 0x80); | ||
1246 | change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, | ||
1247 | 0x80, valp[1] & 0x80); | ||
1248 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | ||
1249 | 0x80, valp[0] & 0x80); | ||
1250 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
1251 | 0x80, valp[1] & 0x80); | ||
1252 | return change; | ||
1253 | } | ||
1254 | |||
1255 | static struct snd_kcontrol_new vaio_mixer[] = { | ||
1256 | { | ||
1257 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1258 | .name = "Master Playback Volume", | ||
1259 | .info = snd_hda_mixer_amp_volume_info, | ||
1260 | .get = snd_hda_mixer_amp_volume_get, | ||
1261 | .put = vaio_master_vol_put, | ||
1262 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
1263 | }, | ||
1264 | { | ||
1265 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1266 | .name = "Master Playback Switch", | ||
1267 | .info = snd_hda_mixer_amp_switch_info, | ||
1268 | .get = snd_hda_mixer_amp_switch_get, | ||
1269 | .put = vaio_master_sw_put, | ||
1270 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
1271 | }, | ||
1272 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | ||
1273 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | ||
1274 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | ||
1275 | { | ||
1276 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1277 | .name = "Capture Source", | ||
1278 | .count = 1, | ||
1279 | .info = stac92xx_mux_enum_info, | ||
1280 | .get = stac92xx_mux_enum_get, | ||
1281 | .put = stac92xx_mux_enum_put, | ||
1282 | }, | ||
1283 | {} | ||
1284 | }; | ||
1285 | |||
1286 | static struct hda_codec_ops stac7661_patch_ops = { | ||
1287 | .build_controls = stac92xx_build_controls, | ||
1288 | .build_pcms = stac92xx_build_pcms, | ||
1289 | .init = stac92xx_init, | ||
1290 | .free = stac92xx_free, | ||
1291 | #ifdef CONFIG_PM | ||
1292 | .resume = stac92xx_resume, | ||
1293 | #endif | ||
1294 | }; | ||
1295 | |||
1296 | enum { STAC7661_VAIO }; | ||
1297 | |||
1298 | static struct hda_board_config stac7661_cfg_tbl[] = { | ||
1299 | { .modelname = "vaio", .config = STAC7661_VAIO }, | ||
1300 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6, | ||
1301 | .config = STAC7661_VAIO }, | ||
1302 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef, | ||
1303 | .config = STAC7661_VAIO }, | ||
1304 | {} | ||
1305 | }; | ||
1306 | |||
1307 | static int patch_stac7661(struct hda_codec *codec) | ||
1308 | { | ||
1309 | struct sigmatel_spec *spec; | ||
1310 | int board_config; | ||
1311 | |||
1312 | board_config = snd_hda_check_board_config(codec, stac7661_cfg_tbl); | ||
1313 | if (board_config < 0) | ||
1314 | /* unknown config, let generic-parser do its job... */ | ||
1315 | return snd_hda_parse_generic_codec(codec); | ||
1316 | |||
1317 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1318 | if (spec == NULL) | ||
1319 | return -ENOMEM; | ||
1320 | |||
1321 | codec->spec = spec; | ||
1322 | switch (board_config) { | ||
1323 | case STAC7661_VAIO: | ||
1324 | spec->mixer = vaio_mixer; | ||
1325 | spec->init = vaio_init; | ||
1326 | spec->multiout.max_channels = 2; | ||
1327 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | ||
1328 | spec->multiout.dac_nids = vaio_dacs; | ||
1329 | spec->multiout.hp_nid = VAIO_HP_DAC; | ||
1330 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | ||
1331 | spec->adc_nids = vaio_adcs; | ||
1332 | spec->input_mux = &vaio_mux; | ||
1333 | spec->mux_nids = vaio_mux_nids; | ||
1334 | break; | ||
1335 | } | ||
1336 | |||
1337 | codec->patch_ops = stac7661_patch_ops; | ||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1341 | |||
1342 | /* | ||
1145 | * patch entries | 1343 | * patch entries |
1146 | */ | 1344 | */ |
1147 | struct hda_codec_preset snd_hda_preset_sigmatel[] = { | 1345 | struct hda_codec_preset snd_hda_preset_sigmatel[] = { |
@@ -1162,5 +1360,6 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
1162 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, | 1360 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, |
1163 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, | 1361 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, |
1164 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, | 1362 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, |
1363 | { .id = 0x83847661, .name = "STAC7661", .patch = patch_stac7661 }, | ||
1165 | {} /* terminator */ | 1364 | {} /* terminator */ |
1166 | }; | 1365 | }; |
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 8809812a1c22..7e6608b14abc 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c | |||
@@ -53,6 +53,8 @@ | |||
53 | #include <linux/interrupt.h> | 53 | #include <linux/interrupt.h> |
54 | #include <linux/init.h> | 54 | #include <linux/init.h> |
55 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
56 | #include <linux/mutex.h> | ||
57 | |||
56 | #include <sound/core.h> | 58 | #include <sound/core.h> |
57 | 59 | ||
58 | #include "ice1712.h" | 60 | #include "ice1712.h" |
@@ -210,14 +212,14 @@ static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
210 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 212 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
211 | unsigned short vol; | 213 | unsigned short vol; |
212 | 214 | ||
213 | down(&ice->gpio_mutex); | 215 | mutex_lock(&ice->gpio_mutex); |
214 | 216 | ||
215 | vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); | 217 | vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); |
216 | ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F); | 218 | ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F); |
217 | if (kcontrol->private_value & AUREON_AC97_STEREO) | 219 | if (kcontrol->private_value & AUREON_AC97_STEREO) |
218 | ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F); | 220 | ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F); |
219 | 221 | ||
220 | up(&ice->gpio_mutex); | 222 | mutex_unlock(&ice->gpio_mutex); |
221 | return 0; | 223 | return 0; |
222 | } | 224 | } |
223 | 225 | ||
@@ -252,11 +254,11 @@ static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
252 | { | 254 | { |
253 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 255 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
254 | 256 | ||
255 | down(&ice->gpio_mutex); | 257 | mutex_lock(&ice->gpio_mutex); |
256 | 258 | ||
257 | ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1; | 259 | ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1; |
258 | 260 | ||
259 | up(&ice->gpio_mutex); | 261 | mutex_unlock(&ice->gpio_mutex); |
260 | return 0; | 262 | return 0; |
261 | } | 263 | } |
262 | 264 | ||
@@ -288,11 +290,11 @@ static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ct | |||
288 | { | 290 | { |
289 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 291 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
290 | 292 | ||
291 | down(&ice->gpio_mutex); | 293 | mutex_lock(&ice->gpio_mutex); |
292 | 294 | ||
293 | ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1; | 295 | ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1; |
294 | 296 | ||
295 | up(&ice->gpio_mutex); | 297 | mutex_unlock(&ice->gpio_mutex); |
296 | return 0; | 298 | return 0; |
297 | } | 299 | } |
298 | 300 | ||
@@ -322,36 +324,48 @@ static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned | |||
322 | { | 324 | { |
323 | unsigned int tmp; | 325 | unsigned int tmp; |
324 | int i; | 326 | int i; |
327 | unsigned int mosi, clk; | ||
325 | 328 | ||
326 | tmp = snd_ice1712_gpio_read(ice); | 329 | tmp = snd_ice1712_gpio_read(ice); |
327 | 330 | ||
328 | snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK| | 331 | if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT) { |
329 | AUREON_WM_CS|AUREON_CS8415_CS)); | 332 | snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS)); |
330 | tmp |= AUREON_WM_RW; | 333 | mosi = PRODIGY_SPI_MOSI; |
334 | clk = PRODIGY_SPI_CLK; | ||
335 | } | ||
336 | else { | ||
337 | snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK| | ||
338 | AUREON_WM_CS|AUREON_CS8415_CS)); | ||
339 | mosi = AUREON_SPI_MOSI; | ||
340 | clk = AUREON_SPI_CLK; | ||
341 | |||
342 | tmp |= AUREON_WM_RW; | ||
343 | } | ||
344 | |||
331 | tmp &= ~cs; | 345 | tmp &= ~cs; |
332 | snd_ice1712_gpio_write(ice, tmp); | 346 | snd_ice1712_gpio_write(ice, tmp); |
333 | udelay(1); | 347 | udelay(1); |
334 | 348 | ||
335 | for (i = bits - 1; i >= 0; i--) { | 349 | for (i = bits - 1; i >= 0; i--) { |
336 | tmp &= ~AUREON_SPI_CLK; | 350 | tmp &= ~clk; |
337 | snd_ice1712_gpio_write(ice, tmp); | 351 | snd_ice1712_gpio_write(ice, tmp); |
338 | udelay(1); | 352 | udelay(1); |
339 | if (data & (1 << i)) | 353 | if (data & (1 << i)) |
340 | tmp |= AUREON_SPI_MOSI; | 354 | tmp |= mosi; |
341 | else | 355 | else |
342 | tmp &= ~AUREON_SPI_MOSI; | 356 | tmp &= ~mosi; |
343 | snd_ice1712_gpio_write(ice, tmp); | 357 | snd_ice1712_gpio_write(ice, tmp); |
344 | udelay(1); | 358 | udelay(1); |
345 | tmp |= AUREON_SPI_CLK; | 359 | tmp |= clk; |
346 | snd_ice1712_gpio_write(ice, tmp); | 360 | snd_ice1712_gpio_write(ice, tmp); |
347 | udelay(1); | 361 | udelay(1); |
348 | } | 362 | } |
349 | 363 | ||
350 | tmp &= ~AUREON_SPI_CLK; | 364 | tmp &= ~clk; |
351 | tmp |= cs; | 365 | tmp |= cs; |
352 | snd_ice1712_gpio_write(ice, tmp); | 366 | snd_ice1712_gpio_write(ice, tmp); |
353 | udelay(1); | 367 | udelay(1); |
354 | tmp |= AUREON_SPI_CLK; | 368 | tmp |= clk; |
355 | snd_ice1712_gpio_write(ice, tmp); | 369 | snd_ice1712_gpio_write(ice, tmp); |
356 | udelay(1); | 370 | udelay(1); |
357 | } | 371 | } |
@@ -440,7 +454,9 @@ static unsigned short wm_get(struct snd_ice1712 *ice, int reg) | |||
440 | */ | 454 | */ |
441 | static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) | 455 | static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) |
442 | { | 456 | { |
443 | aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16); | 457 | aureon_spi_write(ice, |
458 | (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ? PRODIGY_WM_CS : AUREON_WM_CS), | ||
459 | (reg << 9) | (val & 0x1ff), 16); | ||
444 | } | 460 | } |
445 | 461 | ||
446 | /* | 462 | /* |
@@ -474,11 +490,11 @@ static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
474 | { | 490 | { |
475 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 491 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
476 | 492 | ||
477 | down(&ice->gpio_mutex); | 493 | mutex_lock(&ice->gpio_mutex); |
478 | 494 | ||
479 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01; | 495 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01; |
480 | 496 | ||
481 | up(&ice->gpio_mutex); | 497 | mutex_unlock(&ice->gpio_mutex); |
482 | return 0; | 498 | return 0; |
483 | } | 499 | } |
484 | 500 | ||
@@ -543,9 +559,9 @@ static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va | |||
543 | { | 559 | { |
544 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 560 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
545 | 561 | ||
546 | down(&ice->gpio_mutex); | 562 | mutex_lock(&ice->gpio_mutex); |
547 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; | 563 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; |
548 | up(&ice->gpio_mutex); | 564 | mutex_unlock(&ice->gpio_mutex); |
549 | return 0; | 565 | return 0; |
550 | } | 566 | } |
551 | 567 | ||
@@ -768,11 +784,11 @@ static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
768 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 784 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
769 | unsigned short val; | 785 | unsigned short val; |
770 | 786 | ||
771 | down(&ice->gpio_mutex); | 787 | mutex_lock(&ice->gpio_mutex); |
772 | val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; | 788 | val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; |
773 | val = val > PCM_MIN ? (val - PCM_MIN) : 0; | 789 | val = val > PCM_MIN ? (val - PCM_MIN) : 0; |
774 | ucontrol->value.integer.value[0] = val; | 790 | ucontrol->value.integer.value[0] = val; |
775 | up(&ice->gpio_mutex); | 791 | mutex_unlock(&ice->gpio_mutex); |
776 | return 0; | 792 | return 0; |
777 | } | 793 | } |
778 | 794 | ||
@@ -813,12 +829,12 @@ static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va | |||
813 | unsigned short val; | 829 | unsigned short val; |
814 | int i; | 830 | int i; |
815 | 831 | ||
816 | down(&ice->gpio_mutex); | 832 | mutex_lock(&ice->gpio_mutex); |
817 | for (i = 0; i < 2; i++) { | 833 | for (i = 0; i < 2; i++) { |
818 | val = wm_get(ice, WM_ADC_GAIN + i); | 834 | val = wm_get(ice, WM_ADC_GAIN + i); |
819 | ucontrol->value.integer.value[i] = ~val>>5 & 0x1; | 835 | ucontrol->value.integer.value[i] = ~val>>5 & 0x1; |
820 | } | 836 | } |
821 | up(&ice->gpio_mutex); | 837 | mutex_unlock(&ice->gpio_mutex); |
822 | return 0; | 838 | return 0; |
823 | } | 839 | } |
824 | 840 | ||
@@ -860,13 +876,13 @@ static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
860 | int i, idx; | 876 | int i, idx; |
861 | unsigned short vol; | 877 | unsigned short vol; |
862 | 878 | ||
863 | down(&ice->gpio_mutex); | 879 | mutex_lock(&ice->gpio_mutex); |
864 | for (i = 0; i < 2; i++) { | 880 | for (i = 0; i < 2; i++) { |
865 | idx = WM_ADC_GAIN + i; | 881 | idx = WM_ADC_GAIN + i; |
866 | vol = wm_get(ice, idx) & 0x1f; | 882 | vol = wm_get(ice, idx) & 0x1f; |
867 | ucontrol->value.integer.value[i] = vol; | 883 | ucontrol->value.integer.value[i] = vol; |
868 | } | 884 | } |
869 | up(&ice->gpio_mutex); | 885 | mutex_unlock(&ice->gpio_mutex); |
870 | return 0; | 886 | return 0; |
871 | } | 887 | } |
872 | 888 | ||
@@ -937,11 +953,11 @@ static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
937 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 953 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
938 | unsigned short val; | 954 | unsigned short val; |
939 | 955 | ||
940 | down(&ice->gpio_mutex); | 956 | mutex_lock(&ice->gpio_mutex); |
941 | val = wm_get(ice, WM_ADC_MUX); | 957 | val = wm_get(ice, WM_ADC_MUX); |
942 | ucontrol->value.integer.value[0] = val & 7; | 958 | ucontrol->value.enumerated.item[0] = val & 7; |
943 | ucontrol->value.integer.value[1] = (val >> 4) & 7; | 959 | ucontrol->value.enumerated.item[1] = (val >> 4) & 7; |
944 | up(&ice->gpio_mutex); | 960 | mutex_unlock(&ice->gpio_mutex); |
945 | return 0; | 961 | return 0; |
946 | } | 962 | } |
947 | 963 | ||
@@ -954,8 +970,8 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
954 | snd_ice1712_save_gpio_status(ice); | 970 | snd_ice1712_save_gpio_status(ice); |
955 | oval = wm_get(ice, WM_ADC_MUX); | 971 | oval = wm_get(ice, WM_ADC_MUX); |
956 | nval = oval & ~0x77; | 972 | nval = oval & ~0x77; |
957 | nval |= ucontrol->value.integer.value[0] & 7; | 973 | nval |= ucontrol->value.enumerated.item[0] & 7; |
958 | nval |= (ucontrol->value.integer.value[1] & 7) << 4; | 974 | nval |= (ucontrol->value.enumerated.item[1] & 7) << 4; |
959 | change = (oval != nval); | 975 | change = (oval != nval); |
960 | if (change) | 976 | if (change) |
961 | wm_put(ice, WM_ADC_MUX, nval); | 977 | wm_put(ice, WM_ADC_MUX, nval); |
@@ -995,7 +1011,7 @@ static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
995 | 1011 | ||
996 | //snd_ice1712_save_gpio_status(ice); | 1012 | //snd_ice1712_save_gpio_status(ice); |
997 | //val = aureon_cs8415_get(ice, CS8415_CTRL2); | 1013 | //val = aureon_cs8415_get(ice, CS8415_CTRL2); |
998 | ucontrol->value.integer.value[0] = ice->spec.aureon.cs8415_mux; | 1014 | ucontrol->value.enumerated.item[0] = ice->spec.aureon.cs8415_mux; |
999 | //snd_ice1712_restore_gpio_status(ice); | 1015 | //snd_ice1712_restore_gpio_status(ice); |
1000 | return 0; | 1016 | return 0; |
1001 | } | 1017 | } |
@@ -1009,12 +1025,12 @@ static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1009 | snd_ice1712_save_gpio_status(ice); | 1025 | snd_ice1712_save_gpio_status(ice); |
1010 | oval = aureon_cs8415_get(ice, CS8415_CTRL2); | 1026 | oval = aureon_cs8415_get(ice, CS8415_CTRL2); |
1011 | nval = oval & ~0x07; | 1027 | nval = oval & ~0x07; |
1012 | nval |= ucontrol->value.integer.value[0] & 7; | 1028 | nval |= ucontrol->value.enumerated.item[0] & 7; |
1013 | change = (oval != nval); | 1029 | change = (oval != nval); |
1014 | if (change) | 1030 | if (change) |
1015 | aureon_cs8415_put(ice, CS8415_CTRL2, nval); | 1031 | aureon_cs8415_put(ice, CS8415_CTRL2, nval); |
1016 | snd_ice1712_restore_gpio_status(ice); | 1032 | snd_ice1712_restore_gpio_status(ice); |
1017 | ice->spec.aureon.cs8415_mux = ucontrol->value.integer.value[0]; | 1033 | ice->spec.aureon.cs8415_mux = ucontrol->value.enumerated.item[0]; |
1018 | return change; | 1034 | return change; |
1019 | } | 1035 | } |
1020 | 1036 | ||
@@ -1659,7 +1675,7 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice) | |||
1659 | return err; | 1675 | return err; |
1660 | } | 1676 | } |
1661 | } | 1677 | } |
1662 | else { | 1678 | else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) { |
1663 | for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) { | 1679 | for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) { |
1664 | err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice)); | 1680 | err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice)); |
1665 | if (err < 0) | 1681 | if (err < 0) |
@@ -1667,7 +1683,7 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice) | |||
1667 | } | 1683 | } |
1668 | } | 1684 | } |
1669 | 1685 | ||
1670 | { | 1686 | if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) { |
1671 | unsigned char id; | 1687 | unsigned char id; |
1672 | snd_ice1712_save_gpio_status(ice); | 1688 | snd_ice1712_save_gpio_status(ice); |
1673 | id = aureon_cs8415_get(ice, CS8415_ID); | 1689 | id = aureon_cs8415_get(ice, CS8415_ID); |
@@ -1822,7 +1838,8 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) | |||
1822 | udelay(1); | 1838 | udelay(1); |
1823 | 1839 | ||
1824 | /* initialize WM8770 codec */ | 1840 | /* initialize WM8770 codec */ |
1825 | if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71) | 1841 | if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 || |
1842 | ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT) | ||
1826 | p = wm_inits_prodigy; | 1843 | p = wm_inits_prodigy; |
1827 | else | 1844 | else |
1828 | p = wm_inits_aureon; | 1845 | p = wm_inits_aureon; |
@@ -1830,11 +1847,13 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) | |||
1830 | wm_put(ice, p[0], p[1]); | 1847 | wm_put(ice, p[0], p[1]); |
1831 | 1848 | ||
1832 | /* initialize CS8415A codec */ | 1849 | /* initialize CS8415A codec */ |
1833 | for (p = cs_inits; *p != (unsigned short)-1; p++) | 1850 | if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) { |
1834 | aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); | 1851 | for (p = cs_inits; *p != (unsigned short)-1; p++) |
1835 | ice->spec.aureon.cs8415_mux = 1; | 1852 | aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); |
1853 | ice->spec.aureon.cs8415_mux = 1; | ||
1836 | 1854 | ||
1837 | aureon_set_headphone_amp(ice, 1); | 1855 | aureon_set_headphone_amp(ice, 1); |
1856 | } | ||
1838 | 1857 | ||
1839 | snd_ice1712_restore_gpio_status(ice); | 1858 | snd_ice1712_restore_gpio_status(ice); |
1840 | 1859 | ||
@@ -1902,6 +1921,23 @@ static unsigned char prodigy71_eeprom[] __devinitdata = { | |||
1902 | 0x00, /* GPIO_STATE2 */ | 1921 | 0x00, /* GPIO_STATE2 */ |
1903 | }; | 1922 | }; |
1904 | 1923 | ||
1924 | static unsigned char prodigy71lt_eeprom[] __devinitdata = { | ||
1925 | 0x0b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */ | ||
1926 | 0x80, /* ACLINK: I2S */ | ||
1927 | 0xfc, /* I2S: vol, 96k, 24bit, 192k */ | ||
1928 | 0xc3, /* SPDUF: out-en, out-int */ | ||
1929 | 0x00, /* GPIO_DIR */ | ||
1930 | 0x07, /* GPIO_DIR1 */ | ||
1931 | 0x00, /* GPIO_DIR2 */ | ||
1932 | 0xff, /* GPIO_MASK */ | ||
1933 | 0xf8, /* GPIO_MASK1 */ | ||
1934 | 0xff, /* GPIO_MASK2 */ | ||
1935 | 0x00, /* GPIO_STATE */ | ||
1936 | 0x00, /* GPIO_STATE1 */ | ||
1937 | 0x00, /* GPIO_STATE2 */ | ||
1938 | }; | ||
1939 | |||
1940 | |||
1905 | /* entry point */ | 1941 | /* entry point */ |
1906 | struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = { | 1942 | struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = { |
1907 | { | 1943 | { |
@@ -1944,5 +1980,15 @@ struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = { | |||
1944 | .eeprom_data = prodigy71_eeprom, | 1980 | .eeprom_data = prodigy71_eeprom, |
1945 | .driver = "Prodigy71", /* should be identical with Aureon71 */ | 1981 | .driver = "Prodigy71", /* should be identical with Aureon71 */ |
1946 | }, | 1982 | }, |
1983 | { | ||
1984 | .subvendor = VT1724_SUBDEVICE_PRODIGY71LT, | ||
1985 | .name = "Audiotrak Prodigy 7.1 LT", | ||
1986 | .model = "prodigy71lt", | ||
1987 | .chip_init = aureon_init, | ||
1988 | .build_controls = aureon_add_controls, | ||
1989 | .eeprom_size = sizeof(prodigy71lt_eeprom), | ||
1990 | .eeprom_data = prodigy71lt_eeprom, | ||
1991 | .driver = "Prodigy71LT", | ||
1992 | }, | ||
1947 | { } /* terminator */ | 1993 | { } /* terminator */ |
1948 | }; | 1994 | }; |
diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h index 95d515f36f23..98a6752280f2 100644 --- a/sound/pci/ice1712/aureon.h +++ b/sound/pci/ice1712/aureon.h | |||
@@ -27,12 +27,14 @@ | |||
27 | #define AUREON_DEVICE_DESC "{Terratec,Aureon 5.1 Sky},"\ | 27 | #define AUREON_DEVICE_DESC "{Terratec,Aureon 5.1 Sky},"\ |
28 | "{Terratec,Aureon 7.1 Space},"\ | 28 | "{Terratec,Aureon 7.1 Space},"\ |
29 | "{Terratec,Aureon 7.1 Universe}," \ | 29 | "{Terratec,Aureon 7.1 Universe}," \ |
30 | "{AudioTrak,Prodigy 7.1}," | 30 | "{AudioTrak,Prodigy 7.1}," \ |
31 | "{AudioTrak,Prodigy 7.1 LT}," | ||
31 | 32 | ||
32 | #define VT1724_SUBDEVICE_AUREON51_SKY 0x3b154711 /* Aureon 5.1 Sky */ | 33 | #define VT1724_SUBDEVICE_AUREON51_SKY 0x3b154711 /* Aureon 5.1 Sky */ |
33 | #define VT1724_SUBDEVICE_AUREON71_SPACE 0x3b154511 /* Aureon 7.1 Space */ | 34 | #define VT1724_SUBDEVICE_AUREON71_SPACE 0x3b154511 /* Aureon 7.1 Space */ |
34 | #define VT1724_SUBDEVICE_AUREON71_UNIVERSE 0x3b155311 /* Aureon 7.1 Universe */ | 35 | #define VT1724_SUBDEVICE_AUREON71_UNIVERSE 0x3b155311 /* Aureon 7.1 Universe */ |
35 | #define VT1724_SUBDEVICE_PRODIGY71 0x33495345 /* PRODIGY 7.1 */ | 36 | #define VT1724_SUBDEVICE_PRODIGY71 0x33495345 /* PRODIGY 7.1 */ |
37 | #define VT1724_SUBDEVICE_PRODIGY71LT 0x32315441 /* PRODIGY 7.1 LT */ | ||
36 | 38 | ||
37 | extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; | 39 | extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; |
38 | 40 | ||
@@ -53,4 +55,8 @@ extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; | |||
53 | #define AUREON_AC97_DATA_HIGH (1 << 8) | 55 | #define AUREON_AC97_DATA_HIGH (1 << 8) |
54 | #define AUREON_AC97_DATA_MASK 0xFF | 56 | #define AUREON_AC97_DATA_MASK 0xFF |
55 | 57 | ||
58 | #define PRODIGY_WM_CS (1 << 8) | ||
59 | #define PRODIGY_SPI_MOSI (1 << 10) | ||
60 | #define PRODIGY_SPI_CLK (1 << 9) | ||
61 | |||
56 | #endif /* __SOUND_AUREON_H */ | 62 | #endif /* __SOUND_AUREON_H */ |
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 9a51d34e6817..af659800c9b0 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/mutex.h> | ||
32 | |||
31 | #include <sound/core.h> | 33 | #include <sound/core.h> |
32 | #include <sound/cs8427.h> | 34 | #include <sound/cs8427.h> |
33 | #include <sound/asoundef.h> | 35 | #include <sound/asoundef.h> |
@@ -130,13 +132,13 @@ static int ap_cs8427_sendbytes(struct snd_i2c_device *device, unsigned char *byt | |||
130 | int res = count; | 132 | int res = count; |
131 | unsigned char tmp; | 133 | unsigned char tmp; |
132 | 134 | ||
133 | down(&ice->gpio_mutex); | 135 | mutex_lock(&ice->gpio_mutex); |
134 | tmp = ap_cs8427_codec_select(ice); | 136 | tmp = ap_cs8427_codec_select(ice); |
135 | ap_cs8427_write_byte(ice, (device->addr << 1) | 0, tmp); /* address + write mode */ | 137 | ap_cs8427_write_byte(ice, (device->addr << 1) | 0, tmp); /* address + write mode */ |
136 | while (count-- > 0) | 138 | while (count-- > 0) |
137 | ap_cs8427_write_byte(ice, *bytes++, tmp); | 139 | ap_cs8427_write_byte(ice, *bytes++, tmp); |
138 | ap_cs8427_codec_deassert(ice, tmp); | 140 | ap_cs8427_codec_deassert(ice, tmp); |
139 | up(&ice->gpio_mutex); | 141 | mutex_unlock(&ice->gpio_mutex); |
140 | return res; | 142 | return res; |
141 | } | 143 | } |
142 | 144 | ||
@@ -147,13 +149,13 @@ static int ap_cs8427_readbytes(struct snd_i2c_device *device, unsigned char *byt | |||
147 | int res = count; | 149 | int res = count; |
148 | unsigned char tmp; | 150 | unsigned char tmp; |
149 | 151 | ||
150 | down(&ice->gpio_mutex); | 152 | mutex_lock(&ice->gpio_mutex); |
151 | tmp = ap_cs8427_codec_select(ice); | 153 | tmp = ap_cs8427_codec_select(ice); |
152 | ap_cs8427_write_byte(ice, (device->addr << 1) | 1, tmp); /* address + read mode */ | 154 | ap_cs8427_write_byte(ice, (device->addr << 1) | 1, tmp); /* address + read mode */ |
153 | while (count-- > 0) | 155 | while (count-- > 0) |
154 | *bytes++ = ap_cs8427_read_byte(ice, tmp); | 156 | *bytes++ = ap_cs8427_read_byte(ice, tmp); |
155 | ap_cs8427_codec_deassert(ice, tmp); | 157 | ap_cs8427_codec_deassert(ice, tmp); |
156 | up(&ice->gpio_mutex); | 158 | mutex_unlock(&ice->gpio_mutex); |
157 | return res; | 159 | return res; |
158 | } | 160 | } |
159 | 161 | ||
@@ -180,7 +182,7 @@ static void snd_ice1712_delta_cs8403_spdif_write(struct snd_ice1712 *ice, unsign | |||
180 | /* send byte to transmitter */ | 182 | /* send byte to transmitter */ |
181 | mask1 = ICE1712_DELTA_SPDIF_OUT_STAT_CLOCK; | 183 | mask1 = ICE1712_DELTA_SPDIF_OUT_STAT_CLOCK; |
182 | mask2 = ICE1712_DELTA_SPDIF_OUT_STAT_DATA; | 184 | mask2 = ICE1712_DELTA_SPDIF_OUT_STAT_DATA; |
183 | down(&ice->gpio_mutex); | 185 | mutex_lock(&ice->gpio_mutex); |
184 | tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); | 186 | tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); |
185 | for (idx = 7; idx >= 0; idx--) { | 187 | for (idx = 7; idx >= 0; idx--) { |
186 | tmp &= ~(mask1 | mask2); | 188 | tmp &= ~(mask1 | mask2); |
@@ -194,7 +196,7 @@ static void snd_ice1712_delta_cs8403_spdif_write(struct snd_ice1712 *ice, unsign | |||
194 | } | 196 | } |
195 | tmp &= ~mask1; | 197 | tmp &= ~mask1; |
196 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); | 198 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); |
197 | up(&ice->gpio_mutex); | 199 | mutex_unlock(&ice->gpio_mutex); |
198 | } | 200 | } |
199 | 201 | ||
200 | 202 | ||
@@ -296,14 +298,14 @@ static void delta_1010_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) | |||
296 | if (rate == 0) /* no hint - S/PDIF input is master, simply return */ | 298 | if (rate == 0) /* no hint - S/PDIF input is master, simply return */ |
297 | return; | 299 | return; |
298 | 300 | ||
299 | down(&ice->gpio_mutex); | 301 | mutex_lock(&ice->gpio_mutex); |
300 | tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); | 302 | tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); |
301 | tmp2 = tmp & ~ICE1712_DELTA_DFS; | 303 | tmp2 = tmp & ~ICE1712_DELTA_DFS; |
302 | if (rate > 48000) | 304 | if (rate > 48000) |
303 | tmp2 |= ICE1712_DELTA_DFS; | 305 | tmp2 |= ICE1712_DELTA_DFS; |
304 | if (tmp != tmp2) | 306 | if (tmp != tmp2) |
305 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp2); | 307 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp2); |
306 | up(&ice->gpio_mutex); | 308 | mutex_unlock(&ice->gpio_mutex); |
307 | } | 309 | } |
308 | 310 | ||
309 | /* | 311 | /* |
@@ -318,9 +320,9 @@ static void delta_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) | |||
318 | return; | 320 | return; |
319 | 321 | ||
320 | /* check before reset ak4524 to avoid unnecessary clicks */ | 322 | /* check before reset ak4524 to avoid unnecessary clicks */ |
321 | down(&ice->gpio_mutex); | 323 | mutex_lock(&ice->gpio_mutex); |
322 | tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); | 324 | tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); |
323 | up(&ice->gpio_mutex); | 325 | mutex_unlock(&ice->gpio_mutex); |
324 | tmp2 = tmp & ~ICE1712_DELTA_DFS; | 326 | tmp2 = tmp & ~ICE1712_DELTA_DFS; |
325 | if (rate > 48000) | 327 | if (rate > 48000) |
326 | tmp2 |= ICE1712_DELTA_DFS; | 328 | tmp2 |= ICE1712_DELTA_DFS; |
@@ -329,12 +331,12 @@ static void delta_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) | |||
329 | 331 | ||
330 | /* do it again */ | 332 | /* do it again */ |
331 | snd_akm4xxx_reset(ak, 1); | 333 | snd_akm4xxx_reset(ak, 1); |
332 | down(&ice->gpio_mutex); | 334 | mutex_lock(&ice->gpio_mutex); |
333 | tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ~ICE1712_DELTA_DFS; | 335 | tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ~ICE1712_DELTA_DFS; |
334 | if (rate > 48000) | 336 | if (rate > 48000) |
335 | tmp |= ICE1712_DELTA_DFS; | 337 | tmp |= ICE1712_DELTA_DFS; |
336 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); | 338 | snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); |
337 | up(&ice->gpio_mutex); | 339 | mutex_unlock(&ice->gpio_mutex); |
338 | snd_akm4xxx_reset(ak, 0); | 340 | snd_akm4xxx_reset(ak, 0); |
339 | } | 341 | } |
340 | 342 | ||
@@ -391,6 +393,37 @@ static void delta_setup_spdif(struct snd_ice1712 *ice, int rate) | |||
391 | snd_ice1712_delta_cs8403_spdif_write(ice, tmp); | 393 | snd_ice1712_delta_cs8403_spdif_write(ice, tmp); |
392 | } | 394 | } |
393 | 395 | ||
396 | static int snd_ice1712_delta1010lt_wordclock_status_info(struct snd_kcontrol *kcontrol, | ||
397 | struct snd_ctl_elem_info *uinfo) | ||
398 | { | ||
399 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
400 | uinfo->count = 1; | ||
401 | uinfo->value.integer.min = 0; | ||
402 | uinfo->value.integer.max = 1; | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kcontrol, | ||
407 | struct snd_ctl_elem_value *ucontrol) | ||
408 | { | ||
409 | char reg = 0x10; // cs8427 receiver error register | ||
410 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
411 | |||
412 | if (snd_i2c_sendbytes(ice->cs8427, ®, 1) != 1) | ||
413 | snd_printk(KERN_ERR "unable to send register 0x%x byte to CS8427\n", reg); | ||
414 | snd_i2c_readbytes(ice->cs8427, ®, 1); | ||
415 | ucontrol->value.integer.value[0] = (reg ? 1 : 0); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata = | ||
420 | { | ||
421 | .access = (SNDRV_CTL_ELEM_ACCESS_READ), | ||
422 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
423 | .name = "Word Clock Status", | ||
424 | .info = snd_ice1712_delta1010lt_wordclock_status_info, | ||
425 | .get = snd_ice1712_delta1010lt_wordclock_status_get, | ||
426 | }; | ||
394 | 427 | ||
395 | /* | 428 | /* |
396 | * initialize the chips on M-Audio cards | 429 | * initialize the chips on M-Audio cards |
@@ -620,7 +653,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) | |||
620 | static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata = | 653 | static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata = |
621 | ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0); | 654 | ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0); |
622 | static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata = | 655 | static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata = |
623 | ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 1, 0); | 656 | ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0); |
624 | static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata = | 657 | static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata = |
625 | ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE); | 658 | ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE); |
626 | static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata = | 659 | static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata = |
@@ -653,6 +686,9 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice) | |||
653 | err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_select, ice)); | 686 | err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_select, ice)); |
654 | if (err < 0) | 687 | if (err < 0) |
655 | return err; | 688 | return err; |
689 | err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_status, ice)); | ||
690 | if (err < 0) | ||
691 | return err; | ||
656 | break; | 692 | break; |
657 | } | 693 | } |
658 | 694 | ||
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c index 3f2f918536f5..3f27d04e7d3c 100644 --- a/sound/pci/ice1712/hoontech.c +++ b/sound/pci/ice1712/hoontech.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/mutex.h> | ||
31 | |||
30 | #include <sound/core.h> | 32 | #include <sound/core.h> |
31 | 33 | ||
32 | #include "ice1712.h" | 34 | #include "ice1712.h" |
@@ -48,31 +50,31 @@ static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, un | |||
48 | 50 | ||
49 | static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate) | 51 | static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate) |
50 | { | 52 | { |
51 | down(&ice->gpio_mutex); | 53 | mutex_lock(&ice->gpio_mutex); |
52 | ICE1712_STDSP24_0_DAREAR(ice->spec.hoontech.boxbits, activate); | 54 | ICE1712_STDSP24_0_DAREAR(ice->spec.hoontech.boxbits, activate); |
53 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]); | 55 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]); |
54 | up(&ice->gpio_mutex); | 56 | mutex_unlock(&ice->gpio_mutex); |
55 | } | 57 | } |
56 | 58 | ||
57 | static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate) | 59 | static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate) |
58 | { | 60 | { |
59 | down(&ice->gpio_mutex); | 61 | mutex_lock(&ice->gpio_mutex); |
60 | ICE1712_STDSP24_3_MUTE(ice->spec.hoontech.boxbits, activate); | 62 | ICE1712_STDSP24_3_MUTE(ice->spec.hoontech.boxbits, activate); |
61 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); | 63 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); |
62 | up(&ice->gpio_mutex); | 64 | mutex_unlock(&ice->gpio_mutex); |
63 | } | 65 | } |
64 | 66 | ||
65 | static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate) | 67 | static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate) |
66 | { | 68 | { |
67 | down(&ice->gpio_mutex); | 69 | mutex_lock(&ice->gpio_mutex); |
68 | ICE1712_STDSP24_3_INSEL(ice->spec.hoontech.boxbits, activate); | 70 | ICE1712_STDSP24_3_INSEL(ice->spec.hoontech.boxbits, activate); |
69 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); | 71 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); |
70 | up(&ice->gpio_mutex); | 72 | mutex_unlock(&ice->gpio_mutex); |
71 | } | 73 | } |
72 | 74 | ||
73 | static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate) | 75 | static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate) |
74 | { | 76 | { |
75 | down(&ice->gpio_mutex); | 77 | mutex_lock(&ice->gpio_mutex); |
76 | 78 | ||
77 | /* select box */ | 79 | /* select box */ |
78 | ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box); | 80 | ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box); |
@@ -115,12 +117,12 @@ static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, i | |||
115 | ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, 0); | 117 | ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, 0); |
116 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 118 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); |
117 | 119 | ||
118 | up(&ice->gpio_mutex); | 120 | mutex_unlock(&ice->gpio_mutex); |
119 | } | 121 | } |
120 | 122 | ||
121 | static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master) | 123 | static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master) |
122 | { | 124 | { |
123 | down(&ice->gpio_mutex); | 125 | mutex_lock(&ice->gpio_mutex); |
124 | 126 | ||
125 | /* select box */ | 127 | /* select box */ |
126 | ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box); | 128 | ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box); |
@@ -141,15 +143,15 @@ static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int | |||
141 | ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1); | 143 | ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1); |
142 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 144 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); |
143 | 145 | ||
144 | up(&ice->gpio_mutex); | 146 | mutex_unlock(&ice->gpio_mutex); |
145 | } | 147 | } |
146 | 148 | ||
147 | static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate) | 149 | static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate) |
148 | { | 150 | { |
149 | down(&ice->gpio_mutex); | 151 | mutex_lock(&ice->gpio_mutex); |
150 | ICE1712_STDSP24_3_MIDI2(ice->spec.hoontech.boxbits, activate); | 152 | ICE1712_STDSP24_3_MIDI2(ice->spec.hoontech.boxbits, activate); |
151 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); | 153 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); |
152 | up(&ice->gpio_mutex); | 154 | mutex_unlock(&ice->gpio_mutex); |
153 | } | 155 | } |
154 | 156 | ||
155 | static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice) | 157 | static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice) |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index ef6f18558c95..672e198317e1 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -53,8 +53,10 @@ | |||
53 | #include <linux/interrupt.h> | 53 | #include <linux/interrupt.h> |
54 | #include <linux/init.h> | 54 | #include <linux/init.h> |
55 | #include <linux/pci.h> | 55 | #include <linux/pci.h> |
56 | #include <linux/dma-mapping.h> | ||
56 | #include <linux/slab.h> | 57 | #include <linux/slab.h> |
57 | #include <linux/moduleparam.h> | 58 | #include <linux/moduleparam.h> |
59 | #include <linux/mutex.h> | ||
58 | #include <sound/core.h> | 60 | #include <sound/core.h> |
59 | #include <sound/cs8427.h> | 61 | #include <sound/cs8427.h> |
60 | #include <sound/info.h> | 62 | #include <sound/info.h> |
@@ -82,10 +84,11 @@ MODULE_SUPPORTED_DEVICE("{" | |||
82 | 84 | ||
83 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 85 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
84 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 86 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
85 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 87 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ |
86 | static char *model[SNDRV_CARDS]; | 88 | static char *model[SNDRV_CARDS]; |
87 | static int omni[SNDRV_CARDS]; /* Delta44 & 66 Omni I/O support */ | 89 | static int omni[SNDRV_CARDS]; /* Delta44 & 66 Omni I/O support */ |
88 | static int cs8427_timeout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 500}; /* CS8427 S/PDIF transciever reset timeout value in msec */ | 90 | static int cs8427_timeout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 500}; /* CS8427 S/PDIF transciever reset timeout value in msec */ |
91 | static int dxr_enable[SNDRV_CARDS]; /* DXR enable for DMX6FIRE */ | ||
89 | 92 | ||
90 | module_param_array(index, int, NULL, 0444); | 93 | module_param_array(index, int, NULL, 0444); |
91 | MODULE_PARM_DESC(index, "Index value for ICE1712 soundcard."); | 94 | MODULE_PARM_DESC(index, "Index value for ICE1712 soundcard."); |
@@ -99,6 +102,8 @@ module_param_array(cs8427_timeout, int, NULL, 0444); | |||
99 | MODULE_PARM_DESC(cs8427_timeout, "Define reset timeout for cs8427 chip in msec resolution."); | 102 | MODULE_PARM_DESC(cs8427_timeout, "Define reset timeout for cs8427 chip in msec resolution."); |
100 | module_param_array(model, charp, NULL, 0444); | 103 | module_param_array(model, charp, NULL, 0444); |
101 | MODULE_PARM_DESC(model, "Use the given board model."); | 104 | MODULE_PARM_DESC(model, "Use the given board model."); |
105 | module_param_array(dxr_enable, int, NULL, 0444); | ||
106 | MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE."); | ||
102 | 107 | ||
103 | 108 | ||
104 | static struct pci_device_id snd_ice1712_ids[] = { | 109 | static struct pci_device_id snd_ice1712_ids[] = { |
@@ -316,7 +321,6 @@ static void snd_ice1712_set_gpio_data(struct snd_ice1712 *ice, unsigned int val) | |||
316 | inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ | 321 | inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ |
317 | } | 322 | } |
318 | 323 | ||
319 | |||
320 | /* | 324 | /* |
321 | * | 325 | * |
322 | * CS8427 interface | 326 | * CS8427 interface |
@@ -396,6 +400,20 @@ int __devinit snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr) | |||
396 | return 0; | 400 | return 0; |
397 | } | 401 | } |
398 | 402 | ||
403 | static void snd_ice1712_set_input_clock_source(struct snd_ice1712 *ice, int spdif_is_master) | ||
404 | { | ||
405 | /* change CS8427 clock source too */ | ||
406 | if (ice->cs8427) | ||
407 | snd_ice1712_cs8427_set_input_clock(ice, spdif_is_master); | ||
408 | /* notify ak4524 chip as well */ | ||
409 | if (spdif_is_master) { | ||
410 | unsigned int i; | ||
411 | for (i = 0; i < ice->akm_codecs; i++) { | ||
412 | if (ice->akm[i].ops.set_rate_val) | ||
413 | ice->akm[i].ops.set_rate_val(&ice->akm[i], 0); | ||
414 | } | ||
415 | } | ||
416 | } | ||
399 | 417 | ||
400 | /* | 418 | /* |
401 | * Interrupt handler | 419 | * Interrupt handler |
@@ -1567,6 +1585,9 @@ static void snd_ice1712_proc_read(struct snd_info_entry *entry, | |||
1567 | snd_iprintf(buffer, " CAPTURE : 0x%08x\n", inl(ICEMT(ice, ROUTE_CAPTURE))); | 1585 | snd_iprintf(buffer, " CAPTURE : 0x%08x\n", inl(ICEMT(ice, ROUTE_CAPTURE))); |
1568 | snd_iprintf(buffer, " SPDOUT : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_SPDOUT))); | 1586 | snd_iprintf(buffer, " SPDOUT : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_SPDOUT))); |
1569 | snd_iprintf(buffer, " RATE : 0x%02x\n", (unsigned)inb(ICEMT(ice, RATE))); | 1587 | snd_iprintf(buffer, " RATE : 0x%02x\n", (unsigned)inb(ICEMT(ice, RATE))); |
1588 | snd_iprintf(buffer, " GPIO_DATA : 0x%02x\n", (unsigned)snd_ice1712_get_gpio_data(ice)); | ||
1589 | snd_iprintf(buffer, " GPIO_WRITE_MASK : 0x%02x\n", (unsigned)snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK)); | ||
1590 | snd_iprintf(buffer, " GPIO_DIRECTION : 0x%02x\n", (unsigned)snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION)); | ||
1570 | } | 1591 | } |
1571 | 1592 | ||
1572 | static void __devinit snd_ice1712_proc_init(struct snd_ice1712 * ice) | 1593 | static void __devinit snd_ice1712_proc_init(struct snd_ice1712 * ice) |
@@ -1856,20 +1877,8 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol, | |||
1856 | spin_unlock_irq(&ice->reg_lock); | 1877 | spin_unlock_irq(&ice->reg_lock); |
1857 | 1878 | ||
1858 | if ((oval & ICE1712_SPDIF_MASTER) != | 1879 | if ((oval & ICE1712_SPDIF_MASTER) != |
1859 | (inb(ICEMT(ice, RATE)) & ICE1712_SPDIF_MASTER)) { | 1880 | (inb(ICEMT(ice, RATE)) & ICE1712_SPDIF_MASTER)) |
1860 | /* change CS8427 clock source too */ | 1881 | snd_ice1712_set_input_clock_source(ice, is_spdif_master(ice)); |
1861 | if (ice->cs8427) { | ||
1862 | snd_ice1712_cs8427_set_input_clock(ice, is_spdif_master(ice)); | ||
1863 | } | ||
1864 | /* notify ak4524 chip as well */ | ||
1865 | if (is_spdif_master(ice)) { | ||
1866 | unsigned int i; | ||
1867 | for (i = 0; i < ice->akm_codecs; i++) { | ||
1868 | if (ice->akm[i].ops.set_rate_val) | ||
1869 | ice->akm[i].ops.set_rate_val(&ice->akm[i], 0); | ||
1870 | } | ||
1871 | } | ||
1872 | } | ||
1873 | 1882 | ||
1874 | return change; | 1883 | return change; |
1875 | } | 1884 | } |
@@ -2388,7 +2397,13 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice) | |||
2388 | udelay(200); | 2397 | udelay(200); |
2389 | outb(ICE1712_NATIVE, ICEREG(ice, CONTROL)); | 2398 | outb(ICE1712_NATIVE, ICEREG(ice, CONTROL)); |
2390 | udelay(200); | 2399 | udelay(200); |
2391 | pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); | 2400 | if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) { |
2401 | /* Limit active ADCs and DACs to 6; */ | ||
2402 | /* Note: DXR extension not supported */ | ||
2403 | pci_write_config_byte(ice->pci, 0x60, 0x0a); | ||
2404 | } else { | ||
2405 | pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); | ||
2406 | } | ||
2392 | pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]); | 2407 | pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]); |
2393 | pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]); | 2408 | pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]); |
2394 | pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]); | 2409 | pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]); |
@@ -2524,6 +2539,7 @@ static int __devinit snd_ice1712_create(struct snd_card *card, | |||
2524 | const char *modelname, | 2539 | const char *modelname, |
2525 | int omni, | 2540 | int omni, |
2526 | int cs8427_timeout, | 2541 | int cs8427_timeout, |
2542 | int dxr_enable, | ||
2527 | struct snd_ice1712 ** r_ice1712) | 2543 | struct snd_ice1712 ** r_ice1712) |
2528 | { | 2544 | { |
2529 | struct snd_ice1712 *ice; | 2545 | struct snd_ice1712 *ice; |
@@ -2538,8 +2554,8 @@ static int __devinit snd_ice1712_create(struct snd_card *card, | |||
2538 | if ((err = pci_enable_device(pci)) < 0) | 2554 | if ((err = pci_enable_device(pci)) < 0) |
2539 | return err; | 2555 | return err; |
2540 | /* check, if we can restrict PCI DMA transfers to 28 bits */ | 2556 | /* check, if we can restrict PCI DMA transfers to 28 bits */ |
2541 | if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || | 2557 | if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || |
2542 | pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { | 2558 | pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { |
2543 | snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); | 2559 | snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); |
2544 | pci_disable_device(pci); | 2560 | pci_disable_device(pci); |
2545 | return -ENXIO; | 2561 | return -ENXIO; |
@@ -2556,10 +2572,11 @@ static int __devinit snd_ice1712_create(struct snd_card *card, | |||
2556 | else if (cs8427_timeout > 1000) | 2572 | else if (cs8427_timeout > 1000) |
2557 | cs8427_timeout = 1000; | 2573 | cs8427_timeout = 1000; |
2558 | ice->cs8427_timeout = cs8427_timeout; | 2574 | ice->cs8427_timeout = cs8427_timeout; |
2575 | ice->dxr_enable = dxr_enable; | ||
2559 | spin_lock_init(&ice->reg_lock); | 2576 | spin_lock_init(&ice->reg_lock); |
2560 | init_MUTEX(&ice->gpio_mutex); | 2577 | mutex_init(&ice->gpio_mutex); |
2561 | init_MUTEX(&ice->i2c_mutex); | 2578 | mutex_init(&ice->i2c_mutex); |
2562 | init_MUTEX(&ice->open_mutex); | 2579 | mutex_init(&ice->open_mutex); |
2563 | ice->gpio.set_mask = snd_ice1712_set_gpio_mask; | 2580 | ice->gpio.set_mask = snd_ice1712_set_gpio_mask; |
2564 | ice->gpio.set_dir = snd_ice1712_set_gpio_dir; | 2581 | ice->gpio.set_dir = snd_ice1712_set_gpio_dir; |
2565 | ice->gpio.set_data = snd_ice1712_set_gpio_data; | 2582 | ice->gpio.set_data = snd_ice1712_set_gpio_data; |
@@ -2658,7 +2675,8 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, | |||
2658 | strcpy(card->shortname, "ICEnsemble ICE1712"); | 2675 | strcpy(card->shortname, "ICEnsemble ICE1712"); |
2659 | 2676 | ||
2660 | if ((err = snd_ice1712_create(card, pci, model[dev], omni[dev], | 2677 | if ((err = snd_ice1712_create(card, pci, model[dev], omni[dev], |
2661 | cs8427_timeout[dev], &ice)) < 0) { | 2678 | cs8427_timeout[dev], dxr_enable[dev], |
2679 | &ice)) < 0) { | ||
2662 | snd_card_free(card); | 2680 | snd_card_free(card); |
2663 | return err; | 2681 | return err; |
2664 | } | 2682 | } |
@@ -2735,6 +2753,8 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, | |||
2735 | } | 2753 | } |
2736 | } | 2754 | } |
2737 | 2755 | ||
2756 | snd_ice1712_set_input_clock_source(ice, 0); | ||
2757 | |||
2738 | sprintf(card->longname, "%s at 0x%lx, irq %i", | 2758 | sprintf(card->longname, "%s at 0x%lx, irq %i", |
2739 | card->shortname, ice->port, ice->irq); | 2759 | card->shortname, ice->port, ice->irq); |
2740 | 2760 | ||
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index ce96b3bb6531..f9b22d4a3932 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -325,6 +325,7 @@ struct snd_ice1712 { | |||
325 | 325 | ||
326 | unsigned int pro_volumes[20]; | 326 | unsigned int pro_volumes[20]; |
327 | unsigned int omni: 1; /* Delta Omni I/O */ | 327 | unsigned int omni: 1; /* Delta Omni I/O */ |
328 | unsigned int dxr_enable: 1; /* Terratec DXR enable for DMX6FIRE */ | ||
328 | unsigned int vt1724: 1; | 329 | unsigned int vt1724: 1; |
329 | unsigned int vt1720: 1; | 330 | unsigned int vt1720: 1; |
330 | unsigned int has_spdif: 1; /* VT1720/4 - has SPDIF I/O */ | 331 | unsigned int has_spdif: 1; /* VT1720/4 - has SPDIF I/O */ |
@@ -334,7 +335,7 @@ struct snd_ice1712 { | |||
334 | unsigned int num_total_adcs; /* total ADCs */ | 335 | unsigned int num_total_adcs; /* total ADCs */ |
335 | unsigned int cur_rate; /* current rate */ | 336 | unsigned int cur_rate; /* current rate */ |
336 | 337 | ||
337 | struct semaphore open_mutex; | 338 | struct mutex open_mutex; |
338 | struct snd_pcm_substream *pcm_reserved[4]; | 339 | struct snd_pcm_substream *pcm_reserved[4]; |
339 | struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */ | 340 | struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */ |
340 | 341 | ||
@@ -342,7 +343,7 @@ struct snd_ice1712 { | |||
342 | struct snd_akm4xxx *akm; | 343 | struct snd_akm4xxx *akm; |
343 | struct snd_ice1712_spdif spdif; | 344 | struct snd_ice1712_spdif spdif; |
344 | 345 | ||
345 | struct semaphore i2c_mutex; /* I2C mutex for ICE1724 registers */ | 346 | struct mutex i2c_mutex; /* I2C mutex for ICE1724 registers */ |
346 | struct snd_i2c_bus *i2c; /* I2C bus */ | 347 | struct snd_i2c_bus *i2c; /* I2C bus */ |
347 | struct snd_i2c_device *cs8427; /* CS8427 I2C device */ | 348 | struct snd_i2c_device *cs8427; /* CS8427 I2C device */ |
348 | unsigned int cs8427_timeout; /* CS8427 reset timeout in HZ/100 */ | 349 | unsigned int cs8427_timeout; /* CS8427 reset timeout in HZ/100 */ |
@@ -360,7 +361,7 @@ struct snd_ice1712 { | |||
360 | void (*set_pro_rate)(struct snd_ice1712 *ice, unsigned int rate); | 361 | void (*set_pro_rate)(struct snd_ice1712 *ice, unsigned int rate); |
361 | void (*i2s_mclk_changed)(struct snd_ice1712 *ice); | 362 | void (*i2s_mclk_changed)(struct snd_ice1712 *ice); |
362 | } gpio; | 363 | } gpio; |
363 | struct semaphore gpio_mutex; | 364 | struct mutex gpio_mutex; |
364 | 365 | ||
365 | /* other board-specific data */ | 366 | /* other board-specific data */ |
366 | union { | 367 | union { |
@@ -423,7 +424,7 @@ static inline unsigned int snd_ice1712_gpio_read(struct snd_ice1712 *ice) | |||
423 | */ | 424 | */ |
424 | static inline void snd_ice1712_save_gpio_status(struct snd_ice1712 *ice) | 425 | static inline void snd_ice1712_save_gpio_status(struct snd_ice1712 *ice) |
425 | { | 426 | { |
426 | down(&ice->gpio_mutex); | 427 | mutex_lock(&ice->gpio_mutex); |
427 | ice->gpio.saved[0] = ice->gpio.direction; | 428 | ice->gpio.saved[0] = ice->gpio.direction; |
428 | ice->gpio.saved[1] = ice->gpio.write_mask; | 429 | ice->gpio.saved[1] = ice->gpio.write_mask; |
429 | } | 430 | } |
@@ -434,7 +435,7 @@ static inline void snd_ice1712_restore_gpio_status(struct snd_ice1712 *ice) | |||
434 | ice->gpio.set_mask(ice, ice->gpio.saved[1]); | 435 | ice->gpio.set_mask(ice, ice->gpio.saved[1]); |
435 | ice->gpio.direction = ice->gpio.saved[0]; | 436 | ice->gpio.direction = ice->gpio.saved[0]; |
436 | ice->gpio.write_mask = ice->gpio.saved[1]; | 437 | ice->gpio.write_mask = ice->gpio.saved[1]; |
437 | up(&ice->gpio_mutex); | 438 | mutex_unlock(&ice->gpio_mutex); |
438 | } | 439 | } |
439 | 440 | ||
440 | /* for bit controls */ | 441 | /* for bit controls */ |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 71f08c036019..fce616c2761f 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/moduleparam.h> | 32 | #include <linux/moduleparam.h> |
33 | #include <linux/mutex.h> | ||
33 | #include <sound/core.h> | 34 | #include <sound/core.h> |
34 | #include <sound/info.h> | 35 | #include <sound/info.h> |
35 | #include <sound/mpu401.h> | 36 | #include <sound/mpu401.h> |
@@ -487,7 +488,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, | |||
487 | int i, chs; | 488 | int i, chs; |
488 | 489 | ||
489 | chs = params_channels(hw_params); | 490 | chs = params_channels(hw_params); |
490 | down(&ice->open_mutex); | 491 | mutex_lock(&ice->open_mutex); |
491 | /* mark surround channels */ | 492 | /* mark surround channels */ |
492 | if (substream == ice->playback_pro_substream) { | 493 | if (substream == ice->playback_pro_substream) { |
493 | /* PDMA0 can be multi-channel up to 8 */ | 494 | /* PDMA0 can be multi-channel up to 8 */ |
@@ -495,7 +496,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, | |||
495 | for (i = 0; i < chs; i++) { | 496 | for (i = 0; i < chs; i++) { |
496 | if (ice->pcm_reserved[i] && | 497 | if (ice->pcm_reserved[i] && |
497 | ice->pcm_reserved[i] != substream) { | 498 | ice->pcm_reserved[i] != substream) { |
498 | up(&ice->open_mutex); | 499 | mutex_unlock(&ice->open_mutex); |
499 | return -EBUSY; | 500 | return -EBUSY; |
500 | } | 501 | } |
501 | ice->pcm_reserved[i] = substream; | 502 | ice->pcm_reserved[i] = substream; |
@@ -510,7 +511,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, | |||
510 | if (ice->playback_con_substream_ds[i] == substream) { | 511 | if (ice->playback_con_substream_ds[i] == substream) { |
511 | if (ice->pcm_reserved[i] && | 512 | if (ice->pcm_reserved[i] && |
512 | ice->pcm_reserved[i] != substream) { | 513 | ice->pcm_reserved[i] != substream) { |
513 | up(&ice->open_mutex); | 514 | mutex_unlock(&ice->open_mutex); |
514 | return -EBUSY; | 515 | return -EBUSY; |
515 | } | 516 | } |
516 | ice->pcm_reserved[i] = substream; | 517 | ice->pcm_reserved[i] = substream; |
@@ -518,7 +519,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, | |||
518 | } | 519 | } |
519 | } | 520 | } |
520 | } | 521 | } |
521 | up(&ice->open_mutex); | 522 | mutex_unlock(&ice->open_mutex); |
522 | snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0); | 523 | snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0); |
523 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 524 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); |
524 | } | 525 | } |
@@ -528,12 +529,12 @@ static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream) | |||
528 | struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); | 529 | struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); |
529 | int i; | 530 | int i; |
530 | 531 | ||
531 | down(&ice->open_mutex); | 532 | mutex_lock(&ice->open_mutex); |
532 | /* unmark surround channels */ | 533 | /* unmark surround channels */ |
533 | for (i = 0; i < 3; i++) | 534 | for (i = 0; i < 3; i++) |
534 | if (ice->pcm_reserved[i] == substream) | 535 | if (ice->pcm_reserved[i] == substream) |
535 | ice->pcm_reserved[i] = NULL; | 536 | ice->pcm_reserved[i] = NULL; |
536 | up(&ice->open_mutex); | 537 | mutex_unlock(&ice->open_mutex); |
537 | return snd_pcm_lib_free_pages(substream); | 538 | return snd_pcm_lib_free_pages(substream); |
538 | } | 539 | } |
539 | 540 | ||
@@ -778,7 +779,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) | |||
778 | snd_pcm_set_sync(substream); | 779 | snd_pcm_set_sync(substream); |
779 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | 780 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); |
780 | set_rate_constraints(ice, substream); | 781 | set_rate_constraints(ice, substream); |
781 | down(&ice->open_mutex); | 782 | mutex_lock(&ice->open_mutex); |
782 | /* calculate the currently available channels */ | 783 | /* calculate the currently available channels */ |
783 | for (chs = 0; chs < 3; chs++) { | 784 | for (chs = 0; chs < 3; chs++) { |
784 | if (ice->pcm_reserved[chs]) | 785 | if (ice->pcm_reserved[chs]) |
@@ -788,7 +789,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) | |||
788 | runtime->hw.channels_max = chs; | 789 | runtime->hw.channels_max = chs; |
789 | if (chs > 2) /* channels must be even */ | 790 | if (chs > 2) /* channels must be even */ |
790 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); | 791 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); |
791 | up(&ice->open_mutex); | 792 | mutex_unlock(&ice->open_mutex); |
792 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | 793 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, |
793 | VT1724_BUFFER_ALIGN); | 794 | VT1724_BUFFER_ALIGN); |
794 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | 795 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, |
@@ -1128,13 +1129,13 @@ static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream) | |||
1128 | struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); | 1129 | struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); |
1129 | struct snd_pcm_runtime *runtime = substream->runtime; | 1130 | struct snd_pcm_runtime *runtime = substream->runtime; |
1130 | 1131 | ||
1131 | down(&ice->open_mutex); | 1132 | mutex_lock(&ice->open_mutex); |
1132 | /* already used by PDMA0? */ | 1133 | /* already used by PDMA0? */ |
1133 | if (ice->pcm_reserved[substream->number]) { | 1134 | if (ice->pcm_reserved[substream->number]) { |
1134 | up(&ice->open_mutex); | 1135 | mutex_unlock(&ice->open_mutex); |
1135 | return -EBUSY; /* FIXME: should handle blocking mode properly */ | 1136 | return -EBUSY; /* FIXME: should handle blocking mode properly */ |
1136 | } | 1137 | } |
1137 | up(&ice->open_mutex); | 1138 | mutex_unlock(&ice->open_mutex); |
1138 | runtime->private_data = &vt1724_playback_dma_regs[substream->number]; | 1139 | runtime->private_data = &vt1724_playback_dma_regs[substream->number]; |
1139 | ice->playback_con_substream_ds[substream->number] = substream; | 1140 | ice->playback_con_substream_ds[substream->number] = substream; |
1140 | runtime->hw = snd_vt1724_2ch_stereo; | 1141 | runtime->hw = snd_vt1724_2ch_stereo; |
@@ -1978,12 +1979,12 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, | |||
1978 | { | 1979 | { |
1979 | unsigned char val; | 1980 | unsigned char val; |
1980 | 1981 | ||
1981 | down(&ice->i2c_mutex); | 1982 | mutex_lock(&ice->i2c_mutex); |
1982 | outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); | 1983 | outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); |
1983 | outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); | 1984 | outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); |
1984 | wait_i2c_busy(ice); | 1985 | wait_i2c_busy(ice); |
1985 | val = inb(ICEREG1724(ice, I2C_DATA)); | 1986 | val = inb(ICEREG1724(ice, I2C_DATA)); |
1986 | up(&ice->i2c_mutex); | 1987 | mutex_unlock(&ice->i2c_mutex); |
1987 | //printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); | 1988 | //printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); |
1988 | return val; | 1989 | return val; |
1989 | } | 1990 | } |
@@ -1991,14 +1992,14 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, | |||
1991 | void snd_vt1724_write_i2c(struct snd_ice1712 *ice, | 1992 | void snd_vt1724_write_i2c(struct snd_ice1712 *ice, |
1992 | unsigned char dev, unsigned char addr, unsigned char data) | 1993 | unsigned char dev, unsigned char addr, unsigned char data) |
1993 | { | 1994 | { |
1994 | down(&ice->i2c_mutex); | 1995 | mutex_lock(&ice->i2c_mutex); |
1995 | wait_i2c_busy(ice); | 1996 | wait_i2c_busy(ice); |
1996 | //printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); | 1997 | //printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); |
1997 | outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); | 1998 | outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); |
1998 | outb(data, ICEREG1724(ice, I2C_DATA)); | 1999 | outb(data, ICEREG1724(ice, I2C_DATA)); |
1999 | outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); | 2000 | outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); |
2000 | wait_i2c_busy(ice); | 2001 | wait_i2c_busy(ice); |
2001 | up(&ice->i2c_mutex); | 2002 | mutex_unlock(&ice->i2c_mutex); |
2002 | } | 2003 | } |
2003 | 2004 | ||
2004 | static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, | 2005 | static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, |
@@ -2229,9 +2230,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
2229 | } | 2230 | } |
2230 | ice->vt1724 = 1; | 2231 | ice->vt1724 = 1; |
2231 | spin_lock_init(&ice->reg_lock); | 2232 | spin_lock_init(&ice->reg_lock); |
2232 | init_MUTEX(&ice->gpio_mutex); | 2233 | mutex_init(&ice->gpio_mutex); |
2233 | init_MUTEX(&ice->open_mutex); | 2234 | mutex_init(&ice->open_mutex); |
2234 | init_MUTEX(&ice->i2c_mutex); | 2235 | mutex_init(&ice->i2c_mutex); |
2235 | ice->gpio.set_mask = snd_vt1724_set_gpio_mask; | 2236 | ice->gpio.set_mask = snd_vt1724_set_gpio_mask; |
2236 | ice->gpio.set_dir = snd_vt1724_set_gpio_dir; | 2237 | ice->gpio.set_dir = snd_vt1724_set_gpio_dir; |
2237 | ice->gpio.set_data = snd_vt1724_set_gpio_data; | 2238 | ice->gpio.set_data = snd_vt1724_set_gpio_data; |
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index ec3757834b93..502da1c8b5f7 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c | |||
@@ -39,6 +39,8 @@ | |||
39 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/mutex.h> | ||
43 | |||
42 | #include <sound/core.h> | 44 | #include <sound/core.h> |
43 | 45 | ||
44 | #include "ice1712.h" | 46 | #include "ice1712.h" |
@@ -273,9 +275,9 @@ static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va | |||
273 | { | 275 | { |
274 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 276 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
275 | 277 | ||
276 | down(&ice->gpio_mutex); | 278 | mutex_lock(&ice->gpio_mutex); |
277 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; | 279 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; |
278 | up(&ice->gpio_mutex); | 280 | mutex_unlock(&ice->gpio_mutex); |
279 | return 0; | 281 | return 0; |
280 | } | 282 | } |
281 | 283 | ||
@@ -584,11 +586,11 @@ static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
584 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 586 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
585 | unsigned short val; | 587 | unsigned short val; |
586 | 588 | ||
587 | down(&ice->gpio_mutex); | 589 | mutex_lock(&ice->gpio_mutex); |
588 | val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; | 590 | val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; |
589 | val = val > PCM_MIN ? (val - PCM_MIN) : 0; | 591 | val = val > PCM_MIN ? (val - PCM_MIN) : 0; |
590 | ucontrol->value.integer.value[0] = val; | 592 | ucontrol->value.integer.value[0] = val; |
591 | up(&ice->gpio_mutex); | 593 | mutex_unlock(&ice->gpio_mutex); |
592 | return 0; | 594 | return 0; |
593 | } | 595 | } |
594 | 596 | ||
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index 0dccd7707a4b..d23fb3fc2133 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/mutex.h> | ||
31 | |||
30 | #include <sound/core.h> | 32 | #include <sound/core.h> |
31 | #include <sound/info.h> | 33 | #include <sound/info.h> |
32 | 34 | ||
@@ -124,13 +126,13 @@ static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
124 | unsigned short val; | 126 | unsigned short val; |
125 | int i; | 127 | int i; |
126 | 128 | ||
127 | down(&ice->gpio_mutex); | 129 | mutex_lock(&ice->gpio_mutex); |
128 | for (i = 0; i < 2; i++) { | 130 | for (i = 0; i < 2; i++) { |
129 | val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff; | 131 | val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff; |
130 | val = val > DAC_MIN ? (val - DAC_MIN) : 0; | 132 | val = val > DAC_MIN ? (val - DAC_MIN) : 0; |
131 | ucontrol->value.integer.value[i] = val; | 133 | ucontrol->value.integer.value[i] = val; |
132 | } | 134 | } |
133 | up(&ice->gpio_mutex); | 135 | mutex_unlock(&ice->gpio_mutex); |
134 | return 0; | 136 | return 0; |
135 | } | 137 | } |
136 | 138 | ||
@@ -140,7 +142,7 @@ static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
140 | unsigned short oval, nval; | 142 | unsigned short oval, nval; |
141 | int i, idx, change = 0; | 143 | int i, idx, change = 0; |
142 | 144 | ||
143 | down(&ice->gpio_mutex); | 145 | mutex_lock(&ice->gpio_mutex); |
144 | for (i = 0; i < 2; i++) { | 146 | for (i = 0; i < 2; i++) { |
145 | nval = ucontrol->value.integer.value[i]; | 147 | nval = ucontrol->value.integer.value[i]; |
146 | nval = (nval ? (nval + DAC_MIN) : 0) & 0xff; | 148 | nval = (nval ? (nval + DAC_MIN) : 0) & 0xff; |
@@ -152,7 +154,7 @@ static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
152 | change = 1; | 154 | change = 1; |
153 | } | 155 | } |
154 | } | 156 | } |
155 | up(&ice->gpio_mutex); | 157 | mutex_unlock(&ice->gpio_mutex); |
156 | return change; | 158 | return change; |
157 | } | 159 | } |
158 | 160 | ||
@@ -179,13 +181,13 @@ static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
179 | unsigned short val; | 181 | unsigned short val; |
180 | int i; | 182 | int i; |
181 | 183 | ||
182 | down(&ice->gpio_mutex); | 184 | mutex_lock(&ice->gpio_mutex); |
183 | for (i = 0; i < 2; i++) { | 185 | for (i = 0; i < 2; i++) { |
184 | val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff; | 186 | val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff; |
185 | val = val > ADC_MIN ? (val - ADC_MIN) : 0; | 187 | val = val > ADC_MIN ? (val - ADC_MIN) : 0; |
186 | ucontrol->value.integer.value[i] = val; | 188 | ucontrol->value.integer.value[i] = val; |
187 | } | 189 | } |
188 | up(&ice->gpio_mutex); | 190 | mutex_unlock(&ice->gpio_mutex); |
189 | return 0; | 191 | return 0; |
190 | } | 192 | } |
191 | 193 | ||
@@ -195,7 +197,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
195 | unsigned short ovol, nvol; | 197 | unsigned short ovol, nvol; |
196 | int i, idx, change = 0; | 198 | int i, idx, change = 0; |
197 | 199 | ||
198 | down(&ice->gpio_mutex); | 200 | mutex_lock(&ice->gpio_mutex); |
199 | for (i = 0; i < 2; i++) { | 201 | for (i = 0; i < 2; i++) { |
200 | nvol = ucontrol->value.integer.value[i]; | 202 | nvol = ucontrol->value.integer.value[i]; |
201 | nvol = nvol ? (nvol + ADC_MIN) : 0; | 203 | nvol = nvol ? (nvol + ADC_MIN) : 0; |
@@ -206,7 +208,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
206 | change = 1; | 208 | change = 1; |
207 | } | 209 | } |
208 | } | 210 | } |
209 | up(&ice->gpio_mutex); | 211 | mutex_unlock(&ice->gpio_mutex); |
210 | return change; | 212 | return change; |
211 | } | 213 | } |
212 | 214 | ||
@@ -227,9 +229,9 @@ static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
227 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 229 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
228 | int bit = kcontrol->private_value; | 230 | int bit = kcontrol->private_value; |
229 | 231 | ||
230 | down(&ice->gpio_mutex); | 232 | mutex_lock(&ice->gpio_mutex); |
231 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0; | 233 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0; |
232 | up(&ice->gpio_mutex); | 234 | mutex_unlock(&ice->gpio_mutex); |
233 | return 0; | 235 | return 0; |
234 | } | 236 | } |
235 | 237 | ||
@@ -240,7 +242,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
240 | unsigned short oval, nval; | 242 | unsigned short oval, nval; |
241 | int change; | 243 | int change; |
242 | 244 | ||
243 | down(&ice->gpio_mutex); | 245 | mutex_lock(&ice->gpio_mutex); |
244 | nval = oval = wm_get(ice, WM_ADC_MUX); | 246 | nval = oval = wm_get(ice, WM_ADC_MUX); |
245 | if (ucontrol->value.integer.value[0]) | 247 | if (ucontrol->value.integer.value[0]) |
246 | nval |= (1 << bit); | 248 | nval |= (1 << bit); |
@@ -250,7 +252,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
250 | if (change) { | 252 | if (change) { |
251 | wm_put(ice, WM_ADC_MUX, nval); | 253 | wm_put(ice, WM_ADC_MUX, nval); |
252 | } | 254 | } |
253 | up(&ice->gpio_mutex); | 255 | mutex_unlock(&ice->gpio_mutex); |
254 | return 0; | 256 | return 0; |
255 | } | 257 | } |
256 | 258 | ||
@@ -270,9 +272,9 @@ static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
270 | { | 272 | { |
271 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 273 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
272 | 274 | ||
273 | down(&ice->gpio_mutex); | 275 | mutex_lock(&ice->gpio_mutex); |
274 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0; | 276 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0; |
275 | up(&ice->gpio_mutex); | 277 | mutex_unlock(&ice->gpio_mutex); |
276 | return 0; | 278 | return 0; |
277 | } | 279 | } |
278 | 280 | ||
@@ -282,7 +284,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
282 | unsigned short val, oval; | 284 | unsigned short val, oval; |
283 | int change = 0; | 285 | int change = 0; |
284 | 286 | ||
285 | down(&ice->gpio_mutex); | 287 | mutex_lock(&ice->gpio_mutex); |
286 | val = oval = wm_get(ice, WM_OUT_MUX); | 288 | val = oval = wm_get(ice, WM_OUT_MUX); |
287 | if (ucontrol->value.integer.value[0]) | 289 | if (ucontrol->value.integer.value[0]) |
288 | val |= 0x04; | 290 | val |= 0x04; |
@@ -292,7 +294,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
292 | wm_put(ice, WM_OUT_MUX, val); | 294 | wm_put(ice, WM_OUT_MUX, val); |
293 | change = 1; | 295 | change = 1; |
294 | } | 296 | } |
295 | up(&ice->gpio_mutex); | 297 | mutex_unlock(&ice->gpio_mutex); |
296 | return change; | 298 | return change; |
297 | } | 299 | } |
298 | 300 | ||
@@ -312,9 +314,9 @@ static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
312 | { | 314 | { |
313 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 315 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
314 | 316 | ||
315 | down(&ice->gpio_mutex); | 317 | mutex_lock(&ice->gpio_mutex); |
316 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90; | 318 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90; |
317 | up(&ice->gpio_mutex); | 319 | mutex_unlock(&ice->gpio_mutex); |
318 | return 0; | 320 | return 0; |
319 | } | 321 | } |
320 | 322 | ||
@@ -324,7 +326,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
324 | unsigned short val, oval; | 326 | unsigned short val, oval; |
325 | int change = 0; | 327 | int change = 0; |
326 | 328 | ||
327 | down(&ice->gpio_mutex); | 329 | mutex_lock(&ice->gpio_mutex); |
328 | oval = wm_get(ice, WM_DAC_CTRL1); | 330 | oval = wm_get(ice, WM_DAC_CTRL1); |
329 | val = oval & 0x0f; | 331 | val = oval & 0x0f; |
330 | if (ucontrol->value.integer.value[0]) | 332 | if (ucontrol->value.integer.value[0]) |
@@ -336,7 +338,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
336 | wm_put_nocache(ice, WM_DAC_CTRL1, val); | 338 | wm_put_nocache(ice, WM_DAC_CTRL1, val); |
337 | change = 1; | 339 | change = 1; |
338 | } | 340 | } |
339 | up(&ice->gpio_mutex); | 341 | mutex_unlock(&ice->gpio_mutex); |
340 | return change; | 342 | return change; |
341 | } | 343 | } |
342 | 344 | ||
@@ -449,9 +451,9 @@ static int cs_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
449 | { | 451 | { |
450 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 452 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
451 | 453 | ||
452 | down(&ice->gpio_mutex); | 454 | mutex_lock(&ice->gpio_mutex); |
453 | ucontrol->value.enumerated.item[0] = ice->gpio.saved[0]; | 455 | ucontrol->value.enumerated.item[0] = ice->gpio.saved[0]; |
454 | up(&ice->gpio_mutex); | 456 | mutex_unlock(&ice->gpio_mutex); |
455 | return 0; | 457 | return 0; |
456 | } | 458 | } |
457 | 459 | ||
@@ -461,14 +463,14 @@ static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
461 | unsigned char val; | 463 | unsigned char val; |
462 | int change = 0; | 464 | int change = 0; |
463 | 465 | ||
464 | down(&ice->gpio_mutex); | 466 | mutex_lock(&ice->gpio_mutex); |
465 | if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) { | 467 | if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) { |
466 | ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3; | 468 | ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3; |
467 | val = 0x80 | (ice->gpio.saved[0] << 3); | 469 | val = 0x80 | (ice->gpio.saved[0] << 3); |
468 | spi_write(ice, CS_DEV, 0x04, val); | 470 | spi_write(ice, CS_DEV, 0x04, val); |
469 | change = 1; | 471 | change = 1; |
470 | } | 472 | } |
471 | up(&ice->gpio_mutex); | 473 | mutex_unlock(&ice->gpio_mutex); |
472 | return 0; | 474 | return 0; |
473 | } | 475 | } |
474 | 476 | ||
@@ -488,10 +490,10 @@ static int pontis_gpio_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
488 | static int pontis_gpio_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 490 | static int pontis_gpio_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
489 | { | 491 | { |
490 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 492 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
491 | down(&ice->gpio_mutex); | 493 | mutex_lock(&ice->gpio_mutex); |
492 | /* 4-7 reserved */ | 494 | /* 4-7 reserved */ |
493 | ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0; | 495 | ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0; |
494 | up(&ice->gpio_mutex); | 496 | mutex_unlock(&ice->gpio_mutex); |
495 | return 0; | 497 | return 0; |
496 | } | 498 | } |
497 | 499 | ||
@@ -500,22 +502,22 @@ static int pontis_gpio_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
500 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 502 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
501 | unsigned int val; | 503 | unsigned int val; |
502 | int changed; | 504 | int changed; |
503 | down(&ice->gpio_mutex); | 505 | mutex_lock(&ice->gpio_mutex); |
504 | /* 4-7 reserved */ | 506 | /* 4-7 reserved */ |
505 | val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0; | 507 | val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0; |
506 | changed = val != ice->gpio.write_mask; | 508 | changed = val != ice->gpio.write_mask; |
507 | ice->gpio.write_mask = val; | 509 | ice->gpio.write_mask = val; |
508 | up(&ice->gpio_mutex); | 510 | mutex_unlock(&ice->gpio_mutex); |
509 | return changed; | 511 | return changed; |
510 | } | 512 | } |
511 | 513 | ||
512 | static int pontis_gpio_dir_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 514 | static int pontis_gpio_dir_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
513 | { | 515 | { |
514 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 516 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
515 | down(&ice->gpio_mutex); | 517 | mutex_lock(&ice->gpio_mutex); |
516 | /* 4-7 reserved */ | 518 | /* 4-7 reserved */ |
517 | ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f; | 519 | ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f; |
518 | up(&ice->gpio_mutex); | 520 | mutex_unlock(&ice->gpio_mutex); |
519 | return 0; | 521 | return 0; |
520 | } | 522 | } |
521 | 523 | ||
@@ -524,23 +526,23 @@ static int pontis_gpio_dir_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
524 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 526 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
525 | unsigned int val; | 527 | unsigned int val; |
526 | int changed; | 528 | int changed; |
527 | down(&ice->gpio_mutex); | 529 | mutex_lock(&ice->gpio_mutex); |
528 | /* 4-7 reserved */ | 530 | /* 4-7 reserved */ |
529 | val = ucontrol->value.integer.value[0] & 0xff0f; | 531 | val = ucontrol->value.integer.value[0] & 0xff0f; |
530 | changed = (val != ice->gpio.direction); | 532 | changed = (val != ice->gpio.direction); |
531 | ice->gpio.direction = val; | 533 | ice->gpio.direction = val; |
532 | up(&ice->gpio_mutex); | 534 | mutex_unlock(&ice->gpio_mutex); |
533 | return changed; | 535 | return changed; |
534 | } | 536 | } |
535 | 537 | ||
536 | static int pontis_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 538 | static int pontis_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
537 | { | 539 | { |
538 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 540 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
539 | down(&ice->gpio_mutex); | 541 | mutex_lock(&ice->gpio_mutex); |
540 | snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); | 542 | snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); |
541 | snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); | 543 | snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); |
542 | ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff; | 544 | ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff; |
543 | up(&ice->gpio_mutex); | 545 | mutex_unlock(&ice->gpio_mutex); |
544 | return 0; | 546 | return 0; |
545 | } | 547 | } |
546 | 548 | ||
@@ -549,7 +551,7 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
549 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 551 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
550 | unsigned int val, nval; | 552 | unsigned int val, nval; |
551 | int changed = 0; | 553 | int changed = 0; |
552 | down(&ice->gpio_mutex); | 554 | mutex_lock(&ice->gpio_mutex); |
553 | snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); | 555 | snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); |
554 | snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); | 556 | snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); |
555 | val = snd_ice1712_gpio_read(ice) & 0xffff; | 557 | val = snd_ice1712_gpio_read(ice) & 0xffff; |
@@ -558,7 +560,7 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
558 | snd_ice1712_gpio_write(ice, nval); | 560 | snd_ice1712_gpio_write(ice, nval); |
559 | changed = 1; | 561 | changed = 1; |
560 | } | 562 | } |
561 | up(&ice->gpio_mutex); | 563 | mutex_unlock(&ice->gpio_mutex); |
562 | return changed; | 564 | return changed; |
563 | } | 565 | } |
564 | 566 | ||
@@ -651,14 +653,14 @@ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buf | |||
651 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | 653 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; |
652 | char line[64]; | 654 | char line[64]; |
653 | unsigned int reg, val; | 655 | unsigned int reg, val; |
654 | down(&ice->gpio_mutex); | 656 | mutex_lock(&ice->gpio_mutex); |
655 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | 657 | while (!snd_info_get_line(buffer, line, sizeof(line))) { |
656 | if (sscanf(line, "%x %x", ®, &val) != 2) | 658 | if (sscanf(line, "%x %x", ®, &val) != 2) |
657 | continue; | 659 | continue; |
658 | if (reg <= 0x17 && val <= 0xffff) | 660 | if (reg <= 0x17 && val <= 0xffff) |
659 | wm_put(ice, reg, val); | 661 | wm_put(ice, reg, val); |
660 | } | 662 | } |
661 | up(&ice->gpio_mutex); | 663 | mutex_unlock(&ice->gpio_mutex); |
662 | } | 664 | } |
663 | 665 | ||
664 | static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 666 | static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
@@ -666,12 +668,12 @@ static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff | |||
666 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | 668 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; |
667 | int reg, val; | 669 | int reg, val; |
668 | 670 | ||
669 | down(&ice->gpio_mutex); | 671 | mutex_lock(&ice->gpio_mutex); |
670 | for (reg = 0; reg <= 0x17; reg++) { | 672 | for (reg = 0; reg <= 0x17; reg++) { |
671 | val = wm_get(ice, reg); | 673 | val = wm_get(ice, reg); |
672 | snd_iprintf(buffer, "%02x = %04x\n", reg, val); | 674 | snd_iprintf(buffer, "%02x = %04x\n", reg, val); |
673 | } | 675 | } |
674 | up(&ice->gpio_mutex); | 676 | mutex_unlock(&ice->gpio_mutex); |
675 | } | 677 | } |
676 | 678 | ||
677 | static void wm_proc_init(struct snd_ice1712 *ice) | 679 | static void wm_proc_init(struct snd_ice1712 *ice) |
@@ -690,14 +692,14 @@ static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff | |||
690 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | 692 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; |
691 | int reg, val; | 693 | int reg, val; |
692 | 694 | ||
693 | down(&ice->gpio_mutex); | 695 | mutex_lock(&ice->gpio_mutex); |
694 | for (reg = 0; reg <= 0x26; reg++) { | 696 | for (reg = 0; reg <= 0x26; reg++) { |
695 | val = spi_read(ice, CS_DEV, reg); | 697 | val = spi_read(ice, CS_DEV, reg); |
696 | snd_iprintf(buffer, "%02x = %02x\n", reg, val); | 698 | snd_iprintf(buffer, "%02x = %02x\n", reg, val); |
697 | } | 699 | } |
698 | val = spi_read(ice, CS_DEV, 0x7f); | 700 | val = spi_read(ice, CS_DEV, 0x7f); |
699 | snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val); | 701 | snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val); |
700 | up(&ice->gpio_mutex); | 702 | mutex_unlock(&ice->gpio_mutex); |
701 | } | 703 | } |
702 | 704 | ||
703 | static void cs_proc_init(struct snd_ice1712 *ice) | 705 | static void cs_proc_init(struct snd_ice1712 *ice) |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 174237f4a22c..ebbf2cf4ca0f 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -178,6 +178,8 @@ DEFINE_REGSET(SP, 0x60); /* SPDIF out */ | |||
178 | #define ICH_SAMPLE_CAP 0x00c00000 /* ICH4: sample capability bits (RO) */ | 178 | #define ICH_SAMPLE_CAP 0x00c00000 /* ICH4: sample capability bits (RO) */ |
179 | #define ICH_SAMPLE_16_20 0x00400000 /* ICH4: 16- and 20-bit samples */ | 179 | #define ICH_SAMPLE_16_20 0x00400000 /* ICH4: 16- and 20-bit samples */ |
180 | #define ICH_MULTICHAN_CAP 0x00300000 /* ICH4: multi-channel capability bits (RO) */ | 180 | #define ICH_MULTICHAN_CAP 0x00300000 /* ICH4: multi-channel capability bits (RO) */ |
181 | #define ICH_SIS_TRI 0x00080000 /* SIS: tertiary resume irq */ | ||
182 | #define ICH_SIS_TCR 0x00040000 /* SIS: tertiary codec ready */ | ||
181 | #define ICH_MD3 0x00020000 /* modem power down semaphore */ | 183 | #define ICH_MD3 0x00020000 /* modem power down semaphore */ |
182 | #define ICH_AD3 0x00010000 /* audio power down semaphore */ | 184 | #define ICH_AD3 0x00010000 /* audio power down semaphore */ |
183 | #define ICH_RCS 0x00008000 /* read completion status */ | 185 | #define ICH_RCS 0x00008000 /* read completion status */ |
@@ -398,6 +400,10 @@ struct intel8x0 { | |||
398 | struct snd_ac97_bus *ac97_bus; | 400 | struct snd_ac97_bus *ac97_bus; |
399 | struct snd_ac97 *ac97[3]; | 401 | struct snd_ac97 *ac97[3]; |
400 | unsigned int ac97_sdin[3]; | 402 | unsigned int ac97_sdin[3]; |
403 | unsigned int max_codecs, ncodecs; | ||
404 | unsigned int *codec_bit; | ||
405 | unsigned int codec_isr_bits; | ||
406 | unsigned int codec_ready_bits; | ||
401 | 407 | ||
402 | spinlock_t reg_lock; | 408 | spinlock_t reg_lock; |
403 | 409 | ||
@@ -516,18 +522,6 @@ static void iaputword(struct intel8x0 *chip, u32 offset, u16 val) | |||
516 | * access to AC97 codec via normal i/o (for ICH and SIS7012) | 522 | * access to AC97 codec via normal i/o (for ICH and SIS7012) |
517 | */ | 523 | */ |
518 | 524 | ||
519 | /* return the GLOB_STA bit for the corresponding codec */ | ||
520 | static unsigned int get_ich_codec_bit(struct intel8x0 *chip, unsigned int codec) | ||
521 | { | ||
522 | static unsigned int codec_bit[3] = { | ||
523 | ICH_PCR, ICH_SCR, ICH_TCR | ||
524 | }; | ||
525 | snd_assert(codec < 3, return ICH_PCR); | ||
526 | if (chip->device_type == DEVICE_INTEL_ICH4) | ||
527 | codec = chip->ac97_sdin[codec]; | ||
528 | return codec_bit[codec]; | ||
529 | } | ||
530 | |||
531 | static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int codec) | 525 | static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int codec) |
532 | { | 526 | { |
533 | int time; | 527 | int time; |
@@ -537,9 +531,9 @@ static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int code | |||
537 | if (chip->in_sdin_init) { | 531 | if (chip->in_sdin_init) { |
538 | /* we don't know the ready bit assignment at the moment */ | 532 | /* we don't know the ready bit assignment at the moment */ |
539 | /* so we check any */ | 533 | /* so we check any */ |
540 | codec = ICH_PCR | ICH_SCR | ICH_TCR; | 534 | codec = chip->codec_isr_bits; |
541 | } else { | 535 | } else { |
542 | codec = get_ich_codec_bit(chip, codec); | 536 | codec = chip->codec_bit[chip->ac97_sdin[codec]]; |
543 | } | 537 | } |
544 | 538 | ||
545 | /* codec ready ? */ | 539 | /* codec ready ? */ |
@@ -596,7 +590,7 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, | |||
596 | if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { | 590 | if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { |
597 | /* reset RCS and preserve other R/WC bits */ | 591 | /* reset RCS and preserve other R/WC bits */ |
598 | iputdword(chip, ICHREG(GLOB_STA), tmp & | 592 | iputdword(chip, ICHREG(GLOB_STA), tmp & |
599 | ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); | 593 | ~(chip->codec_ready_bits | ICH_GSCI)); |
600 | if (! chip->in_ac97_init) | 594 | if (! chip->in_ac97_init) |
601 | snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); | 595 | snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); |
602 | res = 0xffff; | 596 | res = 0xffff; |
@@ -605,7 +599,8 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, | |||
605 | return res; | 599 | return res; |
606 | } | 600 | } |
607 | 601 | ||
608 | static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, unsigned int codec) | 602 | static void __devinit snd_intel8x0_codec_read_test(struct intel8x0 *chip, |
603 | unsigned int codec) | ||
609 | { | 604 | { |
610 | unsigned int tmp; | 605 | unsigned int tmp; |
611 | 606 | ||
@@ -614,7 +609,7 @@ static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, unsigned int cod | |||
614 | if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { | 609 | if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { |
615 | /* reset RCS and preserve other R/WC bits */ | 610 | /* reset RCS and preserve other R/WC bits */ |
616 | iputdword(chip, ICHREG(GLOB_STA), tmp & | 611 | iputdword(chip, ICHREG(GLOB_STA), tmp & |
617 | ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); | 612 | ~(chip->codec_ready_bits | ICH_GSCI)); |
618 | } | 613 | } |
619 | } | 614 | } |
620 | } | 615 | } |
@@ -2078,23 +2073,24 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, | |||
2078 | if (chip->device_type != DEVICE_ALI) { | 2073 | if (chip->device_type != DEVICE_ALI) { |
2079 | glob_sta = igetdword(chip, ICHREG(GLOB_STA)); | 2074 | glob_sta = igetdword(chip, ICHREG(GLOB_STA)); |
2080 | ops = &standard_bus_ops; | 2075 | ops = &standard_bus_ops; |
2081 | if (chip->device_type == DEVICE_INTEL_ICH4) { | 2076 | chip->in_sdin_init = 1; |
2082 | codecs = 0; | 2077 | codecs = 0; |
2083 | if (glob_sta & ICH_PCR) | 2078 | for (i = 0; i < chip->max_codecs; i++) { |
2084 | codecs++; | 2079 | if (! (glob_sta & chip->codec_bit[i])) |
2085 | if (glob_sta & ICH_SCR) | 2080 | continue; |
2086 | codecs++; | 2081 | if (chip->device_type == DEVICE_INTEL_ICH4) { |
2087 | if (glob_sta & ICH_TCR) | 2082 | snd_intel8x0_codec_read_test(chip, codecs); |
2088 | codecs++; | 2083 | chip->ac97_sdin[codecs] = |
2089 | chip->in_sdin_init = 1; | 2084 | igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; |
2090 | for (i = 0; i < codecs; i++) { | 2085 | snd_assert(chip->ac97_sdin[codecs] < 3, |
2091 | snd_intel8x0_codec_read_test(chip, i); | 2086 | chip->ac97_sdin[codecs] = 0); |
2092 | chip->ac97_sdin[i] = igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; | 2087 | } else |
2093 | } | 2088 | chip->ac97_sdin[codecs] = i; |
2094 | chip->in_sdin_init = 0; | 2089 | codecs++; |
2095 | } else { | ||
2096 | codecs = glob_sta & ICH_SCR ? 2 : 1; | ||
2097 | } | 2090 | } |
2091 | chip->in_sdin_init = 0; | ||
2092 | if (! codecs) | ||
2093 | codecs = 1; | ||
2098 | } else { | 2094 | } else { |
2099 | ops = &ali_bus_ops; | 2095 | ops = &ali_bus_ops; |
2100 | codecs = 1; | 2096 | codecs = 1; |
@@ -2120,6 +2116,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, | |||
2120 | else | 2116 | else |
2121 | pbus->dra = 1; | 2117 | pbus->dra = 1; |
2122 | chip->ac97_bus = pbus; | 2118 | chip->ac97_bus = pbus; |
2119 | chip->ncodecs = codecs; | ||
2123 | 2120 | ||
2124 | ac97.pci = chip->pci; | 2121 | ac97.pci = chip->pci; |
2125 | for (i = 0; i < codecs; i++) { | 2122 | for (i = 0; i < codecs; i++) { |
@@ -2264,7 +2261,7 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | |||
2264 | end_time = jiffies + HZ; | 2261 | end_time = jiffies + HZ; |
2265 | do { | 2262 | do { |
2266 | status = igetdword(chip, ICHREG(GLOB_STA)) & | 2263 | status = igetdword(chip, ICHREG(GLOB_STA)) & |
2267 | (ICH_PCR | ICH_SCR | ICH_TCR); | 2264 | chip->codec_isr_bits; |
2268 | if (status) | 2265 | if (status) |
2269 | break; | 2266 | break; |
2270 | schedule_timeout_uninterruptible(1); | 2267 | schedule_timeout_uninterruptible(1); |
@@ -2276,32 +2273,27 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | |||
2276 | return -EIO; | 2273 | return -EIO; |
2277 | } | 2274 | } |
2278 | 2275 | ||
2279 | if (chip->device_type == DEVICE_INTEL_ICH4) | ||
2280 | /* ICH4 can have three codecs */ | ||
2281 | nstatus = ICH_PCR | ICH_SCR | ICH_TCR; | ||
2282 | else | ||
2283 | /* others up to two codecs */ | ||
2284 | nstatus = ICH_PCR | ICH_SCR; | ||
2285 | |||
2286 | /* wait for other codecs ready status. */ | 2276 | /* wait for other codecs ready status. */ |
2287 | end_time = jiffies + HZ / 4; | 2277 | end_time = jiffies + HZ / 4; |
2288 | while (status != nstatus && time_after_eq(end_time, jiffies)) { | 2278 | while (status != chip->codec_isr_bits && |
2279 | time_after_eq(end_time, jiffies)) { | ||
2289 | schedule_timeout_uninterruptible(1); | 2280 | schedule_timeout_uninterruptible(1); |
2290 | status |= igetdword(chip, ICHREG(GLOB_STA)) & nstatus; | 2281 | status |= igetdword(chip, ICHREG(GLOB_STA)) & |
2282 | chip->codec_isr_bits; | ||
2291 | } | 2283 | } |
2292 | 2284 | ||
2293 | } else { | 2285 | } else { |
2294 | /* resume phase */ | 2286 | /* resume phase */ |
2295 | int i; | 2287 | int i; |
2296 | status = 0; | 2288 | status = 0; |
2297 | for (i = 0; i < 3; i++) | 2289 | for (i = 0; i < chip->ncodecs; i++) |
2298 | if (chip->ac97[i]) | 2290 | if (chip->ac97[i]) |
2299 | status |= get_ich_codec_bit(chip, i); | 2291 | status |= chip->codec_bit[chip->ac97_sdin[i]]; |
2300 | /* wait until all the probed codecs are ready */ | 2292 | /* wait until all the probed codecs are ready */ |
2301 | end_time = jiffies + HZ; | 2293 | end_time = jiffies + HZ; |
2302 | do { | 2294 | do { |
2303 | nstatus = igetdword(chip, ICHREG(GLOB_STA)) & | 2295 | nstatus = igetdword(chip, ICHREG(GLOB_STA)) & |
2304 | (ICH_PCR | ICH_SCR | ICH_TCR); | 2296 | chip->codec_isr_bits; |
2305 | if (status == nstatus) | 2297 | if (status == nstatus) |
2306 | break; | 2298 | break; |
2307 | schedule_timeout_uninterruptible(1); | 2299 | schedule_timeout_uninterruptible(1); |
@@ -2359,7 +2351,7 @@ static int snd_intel8x0_ali_chip_init(struct intel8x0 *chip, int probing) | |||
2359 | 2351 | ||
2360 | static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) | 2352 | static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) |
2361 | { | 2353 | { |
2362 | unsigned int i; | 2354 | unsigned int i, timeout; |
2363 | int err; | 2355 | int err; |
2364 | 2356 | ||
2365 | if (chip->device_type != DEVICE_ALI) { | 2357 | if (chip->device_type != DEVICE_ALI) { |
@@ -2377,6 +2369,15 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) | |||
2377 | /* reset channels */ | 2369 | /* reset channels */ |
2378 | for (i = 0; i < chip->bdbars_count; i++) | 2370 | for (i = 0; i < chip->bdbars_count; i++) |
2379 | iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); | 2371 | iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); |
2372 | for (i = 0; i < chip->bdbars_count; i++) { | ||
2373 | timeout = 100000; | ||
2374 | while (--timeout != 0) { | ||
2375 | if ((igetbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset) & ICH_RESETREGS) == 0) | ||
2376 | break; | ||
2377 | } | ||
2378 | if (timeout == 0) | ||
2379 | printk(KERN_ERR "intel8x0: reset of registers failed?\n"); | ||
2380 | } | ||
2380 | /* initialize Buffer Descriptor Lists */ | 2381 | /* initialize Buffer Descriptor Lists */ |
2381 | for (i = 0; i < chip->bdbars_count; i++) | 2382 | for (i = 0; i < chip->bdbars_count; i++) |
2382 | iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, | 2383 | iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, |
@@ -2447,7 +2448,7 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) | |||
2447 | } | 2448 | } |
2448 | } | 2449 | } |
2449 | } | 2450 | } |
2450 | for (i = 0; i < 3; i++) | 2451 | for (i = 0; i < chip->ncodecs; i++) |
2451 | snd_ac97_suspend(chip->ac97[i]); | 2452 | snd_ac97_suspend(chip->ac97[i]); |
2452 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2453 | if (chip->device_type == DEVICE_INTEL_ICH4) |
2453 | chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); | 2454 | chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); |
@@ -2488,7 +2489,7 @@ static int intel8x0_resume(struct pci_dev *pci) | |||
2488 | if (chip->fix_nocache) | 2489 | if (chip->fix_nocache) |
2489 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); | 2490 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); |
2490 | 2491 | ||
2491 | for (i = 0; i < 3; i++) | 2492 | for (i = 0; i < chip->ncodecs; i++) |
2492 | snd_ac97_resume(chip->ac97[i]); | 2493 | snd_ac97_resume(chip->ac97[i]); |
2493 | 2494 | ||
2494 | /* refill nocache */ | 2495 | /* refill nocache */ |
@@ -2619,12 +2620,20 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry, | |||
2619 | snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); | 2620 | snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); |
2620 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2621 | if (chip->device_type == DEVICE_INTEL_ICH4) |
2621 | snd_iprintf(buffer, "SDM : 0x%08x\n", igetdword(chip, ICHREG(SDM))); | 2622 | snd_iprintf(buffer, "SDM : 0x%08x\n", igetdword(chip, ICHREG(SDM))); |
2622 | snd_iprintf(buffer, "AC'97 codecs ready :%s%s%s%s\n", | 2623 | snd_iprintf(buffer, "AC'97 codecs ready :"); |
2623 | tmp & ICH_PCR ? " primary" : "", | 2624 | if (tmp & chip->codec_isr_bits) { |
2624 | tmp & ICH_SCR ? " secondary" : "", | 2625 | int i; |
2625 | tmp & ICH_TCR ? " tertiary" : "", | 2626 | static const char *codecs[3] = { |
2626 | (tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : ""); | 2627 | "primary", "secondary", "tertiary" |
2627 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2628 | }; |
2629 | for (i = 0; i < chip->max_codecs; i++) | ||
2630 | if (tmp & chip->codec_bit[i]) | ||
2631 | snd_iprintf(buffer, " %s", codecs[i]); | ||
2632 | } else | ||
2633 | snd_iprintf(buffer, " none"); | ||
2634 | snd_iprintf(buffer, "\n"); | ||
2635 | if (chip->device_type == DEVICE_INTEL_ICH4 || | ||
2636 | chip->device_type == DEVICE_SIS) | ||
2628 | snd_iprintf(buffer, "AC'97 codecs SDIN : %i %i %i\n", | 2637 | snd_iprintf(buffer, "AC'97 codecs SDIN : %i %i %i\n", |
2629 | chip->ac97_sdin[0], | 2638 | chip->ac97_sdin[0], |
2630 | chip->ac97_sdin[1], | 2639 | chip->ac97_sdin[1], |
@@ -2653,6 +2662,13 @@ struct ich_reg_info { | |||
2653 | unsigned int offset; | 2662 | unsigned int offset; |
2654 | }; | 2663 | }; |
2655 | 2664 | ||
2665 | static unsigned int ich_codec_bits[3] = { | ||
2666 | ICH_PCR, ICH_SCR, ICH_TCR | ||
2667 | }; | ||
2668 | static unsigned int sis_codec_bits[3] = { | ||
2669 | ICH_PCR, ICH_SCR, ICH_SIS_TCR | ||
2670 | }; | ||
2671 | |||
2656 | static int __devinit snd_intel8x0_create(struct snd_card *card, | 2672 | static int __devinit snd_intel8x0_create(struct snd_card *card, |
2657 | struct pci_dev *pci, | 2673 | struct pci_dev *pci, |
2658 | unsigned long device_type, | 2674 | unsigned long device_type, |
@@ -2835,6 +2851,29 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, | |||
2835 | pci_set_master(pci); | 2851 | pci_set_master(pci); |
2836 | synchronize_irq(chip->irq); | 2852 | synchronize_irq(chip->irq); |
2837 | 2853 | ||
2854 | switch(chip->device_type) { | ||
2855 | case DEVICE_INTEL_ICH4: | ||
2856 | /* ICH4 can have three codecs */ | ||
2857 | chip->max_codecs = 3; | ||
2858 | chip->codec_bit = ich_codec_bits; | ||
2859 | chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_TRI; | ||
2860 | break; | ||
2861 | case DEVICE_SIS: | ||
2862 | /* recent SIS7012 can have three codecs */ | ||
2863 | chip->max_codecs = 3; | ||
2864 | chip->codec_bit = sis_codec_bits; | ||
2865 | chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_SIS_TRI; | ||
2866 | break; | ||
2867 | default: | ||
2868 | /* others up to two codecs */ | ||
2869 | chip->max_codecs = 2; | ||
2870 | chip->codec_bit = ich_codec_bits; | ||
2871 | chip->codec_ready_bits = ICH_PRI | ICH_SRI; | ||
2872 | break; | ||
2873 | } | ||
2874 | for (i = 0; i < chip->max_codecs; i++) | ||
2875 | chip->codec_isr_bits |= chip->codec_bit[i]; | ||
2876 | |||
2838 | if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { | 2877 | if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { |
2839 | snd_intel8x0_free(chip); | 2878 | snd_intel8x0_free(chip); |
2840 | return err; | 2879 | return err; |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 4eddb512c12f..4721c096335e 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/mutex.h> | ||
30 | 31 | ||
31 | #include <sound/core.h> | 32 | #include <sound/core.h> |
32 | #include <sound/info.h> | 33 | #include <sound/info.h> |
@@ -325,7 +326,7 @@ struct snd_korg1212 { | |||
325 | int irq; | 326 | int irq; |
326 | 327 | ||
327 | spinlock_t lock; | 328 | spinlock_t lock; |
328 | struct semaphore open_mutex; | 329 | struct mutex open_mutex; |
329 | 330 | ||
330 | struct timer_list timer; /* timer callback for checking ack of stop request */ | 331 | struct timer_list timer; /* timer callback for checking ack of stop request */ |
331 | int stop_pending_cnt; /* counter for stop pending check */ | 332 | int stop_pending_cnt; /* counter for stop pending check */ |
@@ -667,13 +668,13 @@ static int snd_korg1212_OpenCard(struct snd_korg1212 * korg1212) | |||
667 | { | 668 | { |
668 | K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", | 669 | K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", |
669 | stateName[korg1212->cardState], korg1212->opencnt); | 670 | stateName[korg1212->cardState], korg1212->opencnt); |
670 | down(&korg1212->open_mutex); | 671 | mutex_lock(&korg1212->open_mutex); |
671 | if (korg1212->opencnt++ == 0) { | 672 | if (korg1212->opencnt++ == 0) { |
672 | snd_korg1212_TurnOffIdleMonitor(korg1212); | 673 | snd_korg1212_TurnOffIdleMonitor(korg1212); |
673 | snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); | 674 | snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); |
674 | } | 675 | } |
675 | 676 | ||
676 | up(&korg1212->open_mutex); | 677 | mutex_unlock(&korg1212->open_mutex); |
677 | return 1; | 678 | return 1; |
678 | } | 679 | } |
679 | 680 | ||
@@ -682,9 +683,9 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) | |||
682 | K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", | 683 | K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", |
683 | stateName[korg1212->cardState], korg1212->opencnt); | 684 | stateName[korg1212->cardState], korg1212->opencnt); |
684 | 685 | ||
685 | down(&korg1212->open_mutex); | 686 | mutex_lock(&korg1212->open_mutex); |
686 | if (--(korg1212->opencnt)) { | 687 | if (--(korg1212->opencnt)) { |
687 | up(&korg1212->open_mutex); | 688 | mutex_unlock(&korg1212->open_mutex); |
688 | return 0; | 689 | return 0; |
689 | } | 690 | } |
690 | 691 | ||
@@ -695,7 +696,7 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) | |||
695 | K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", | 696 | K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", |
696 | rc, stateName[korg1212->cardState]); | 697 | rc, stateName[korg1212->cardState]); |
697 | if (rc != K1212_CMDRET_Success) { | 698 | if (rc != K1212_CMDRET_Success) { |
698 | up(&korg1212->open_mutex); | 699 | mutex_unlock(&korg1212->open_mutex); |
699 | return 0; | 700 | return 0; |
700 | } | 701 | } |
701 | } else if (korg1212->cardState > K1212_STATE_SETUP) { | 702 | } else if (korg1212->cardState > K1212_STATE_SETUP) { |
@@ -707,7 +708,7 @@ static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) | |||
707 | snd_korg1212_setCardState(korg1212, K1212_STATE_READY); | 708 | snd_korg1212_setCardState(korg1212, K1212_STATE_READY); |
708 | } | 709 | } |
709 | 710 | ||
710 | up(&korg1212->open_mutex); | 711 | mutex_unlock(&korg1212->open_mutex); |
711 | return 0; | 712 | return 0; |
712 | } | 713 | } |
713 | 714 | ||
@@ -2179,7 +2180,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev * | |||
2179 | 2180 | ||
2180 | init_waitqueue_head(&korg1212->wait); | 2181 | init_waitqueue_head(&korg1212->wait); |
2181 | spin_lock_init(&korg1212->lock); | 2182 | spin_lock_init(&korg1212->lock); |
2182 | init_MUTEX(&korg1212->open_mutex); | 2183 | mutex_init(&korg1212->open_mutex); |
2183 | init_timer(&korg1212->timer); | 2184 | init_timer(&korg1212->timer); |
2184 | korg1212->timer.function = snd_korg1212_timer_func; | 2185 | korg1212->timer.function = snd_korg1212_timer_func; |
2185 | korg1212->timer.data = (unsigned long)korg1212; | 2186 | korg1212->timer.data = (unsigned long)korg1212; |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index d3ef0cc6c4f9..8bc084956c28 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/dma-mapping.h> | ||
40 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
41 | #include <linux/vmalloc.h> | 42 | #include <linux/vmalloc.h> |
42 | #include <linux/moduleparam.h> | 43 | #include <linux/moduleparam.h> |
@@ -2657,8 +2658,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
2657 | return -EIO; | 2658 | return -EIO; |
2658 | 2659 | ||
2659 | /* check, if we can restrict PCI DMA transfers to 28 bits */ | 2660 | /* check, if we can restrict PCI DMA transfers to 28 bits */ |
2660 | if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || | 2661 | if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || |
2661 | pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { | 2662 | pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { |
2662 | snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); | 2663 | snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); |
2663 | pci_disable_device(pci); | 2664 | pci_disable_device(pci); |
2664 | return -ENXIO; | 2665 | return -ENXIO; |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index b218e1d20c78..43ee3b2b948f 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -25,7 +25,9 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/dma-mapping.h> | ||
28 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/mutex.h> | ||
29 | #include <sound/core.h> | 31 | #include <sound/core.h> |
30 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
31 | #include <sound/info.h> | 33 | #include <sound/info.h> |
@@ -589,7 +591,7 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, | |||
589 | /* set up format for the stream */ | 591 | /* set up format for the stream */ |
590 | format = params_format(hw); | 592 | format = params_format(hw); |
591 | 593 | ||
592 | down(&mgr->setup_mutex); | 594 | mutex_lock(&mgr->setup_mutex); |
593 | 595 | ||
594 | /* update the stream levels */ | 596 | /* update the stream levels */ |
595 | if( stream->pcm_number <= MIXART_PCM_DIGITAL ) { | 597 | if( stream->pcm_number <= MIXART_PCM_DIGITAL ) { |
@@ -628,7 +630,7 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs, | |||
628 | bufferinfo[i].available_length, | 630 | bufferinfo[i].available_length, |
629 | subs->number); | 631 | subs->number); |
630 | } | 632 | } |
631 | up(&mgr->setup_mutex); | 633 | mutex_unlock(&mgr->setup_mutex); |
632 | 634 | ||
633 | return err; | 635 | return err; |
634 | } | 636 | } |
@@ -700,7 +702,7 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) | |||
700 | int err = 0; | 702 | int err = 0; |
701 | int pcm_number; | 703 | int pcm_number; |
702 | 704 | ||
703 | down(&mgr->setup_mutex); | 705 | mutex_lock(&mgr->setup_mutex); |
704 | 706 | ||
705 | if ( pcm == chip->pcm ) { | 707 | if ( pcm == chip->pcm ) { |
706 | pcm_number = MIXART_PCM_ANALOG; | 708 | pcm_number = MIXART_PCM_ANALOG; |
@@ -758,7 +760,7 @@ static int snd_mixart_playback_open(struct snd_pcm_substream *subs) | |||
758 | } | 760 | } |
759 | 761 | ||
760 | _exit_open: | 762 | _exit_open: |
761 | up(&mgr->setup_mutex); | 763 | mutex_unlock(&mgr->setup_mutex); |
762 | 764 | ||
763 | return err; | 765 | return err; |
764 | } | 766 | } |
@@ -775,7 +777,7 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) | |||
775 | int err = 0; | 777 | int err = 0; |
776 | int pcm_number; | 778 | int pcm_number; |
777 | 779 | ||
778 | down(&mgr->setup_mutex); | 780 | mutex_lock(&mgr->setup_mutex); |
779 | 781 | ||
780 | if ( pcm == chip->pcm ) { | 782 | if ( pcm == chip->pcm ) { |
781 | pcm_number = MIXART_PCM_ANALOG; | 783 | pcm_number = MIXART_PCM_ANALOG; |
@@ -836,7 +838,7 @@ static int snd_mixart_capture_open(struct snd_pcm_substream *subs) | |||
836 | } | 838 | } |
837 | 839 | ||
838 | _exit_open: | 840 | _exit_open: |
839 | up(&mgr->setup_mutex); | 841 | mutex_unlock(&mgr->setup_mutex); |
840 | 842 | ||
841 | return err; | 843 | return err; |
842 | } | 844 | } |
@@ -849,7 +851,7 @@ static int snd_mixart_close(struct snd_pcm_substream *subs) | |||
849 | struct mixart_mgr *mgr = chip->mgr; | 851 | struct mixart_mgr *mgr = chip->mgr; |
850 | struct mixart_stream *stream = subs->runtime->private_data; | 852 | struct mixart_stream *stream = subs->runtime->private_data; |
851 | 853 | ||
852 | down(&mgr->setup_mutex); | 854 | mutex_lock(&mgr->setup_mutex); |
853 | 855 | ||
854 | snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number); | 856 | snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number); |
855 | 857 | ||
@@ -868,7 +870,7 @@ static int snd_mixart_close(struct snd_pcm_substream *subs) | |||
868 | stream->status = MIXART_STREAM_STATUS_FREE; | 870 | stream->status = MIXART_STREAM_STATUS_FREE; |
869 | stream->substream = NULL; | 871 | stream->substream = NULL; |
870 | 872 | ||
871 | up(&mgr->setup_mutex); | 873 | mutex_unlock(&mgr->setup_mutex); |
872 | return 0; | 874 | return 0; |
873 | } | 875 | } |
874 | 876 | ||
@@ -1288,7 +1290,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, | |||
1288 | pci_set_master(pci); | 1290 | pci_set_master(pci); |
1289 | 1291 | ||
1290 | /* check if we can restrict PCI DMA transfers to 32 bits */ | 1292 | /* check if we can restrict PCI DMA transfers to 32 bits */ |
1291 | if (pci_set_dma_mask(pci, 0xffffffff) < 0) { | 1293 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) { |
1292 | snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); | 1294 | snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); |
1293 | pci_disable_device(pci); | 1295 | pci_disable_device(pci); |
1294 | return -ENXIO; | 1296 | return -ENXIO; |
@@ -1335,12 +1337,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, | |||
1335 | mgr->msg_fifo_writeptr = 0; | 1337 | mgr->msg_fifo_writeptr = 0; |
1336 | 1338 | ||
1337 | spin_lock_init(&mgr->msg_lock); | 1339 | spin_lock_init(&mgr->msg_lock); |
1338 | init_MUTEX(&mgr->msg_mutex); | 1340 | mutex_init(&mgr->msg_mutex); |
1339 | init_waitqueue_head(&mgr->msg_sleep); | 1341 | init_waitqueue_head(&mgr->msg_sleep); |
1340 | atomic_set(&mgr->msg_processed, 0); | 1342 | atomic_set(&mgr->msg_processed, 0); |
1341 | 1343 | ||
1342 | /* init setup mutex*/ | 1344 | /* init setup mutex*/ |
1343 | init_MUTEX(&mgr->setup_mutex); | 1345 | mutex_init(&mgr->setup_mutex); |
1344 | 1346 | ||
1345 | /* init message taslket */ | 1347 | /* init message taslket */ |
1346 | tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr); | 1348 | tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr); |
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h index 3e84863ca02c..561634d5c007 100644 --- a/sound/pci/mixart/mixart.h +++ b/sound/pci/mixart/mixart.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #define __SOUND_MIXART_H | 24 | #define __SOUND_MIXART_H |
25 | 25 | ||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/mutex.h> | ||
27 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
28 | 29 | ||
29 | #define MIXART_DRIVER_VERSION 0x000100 /* 0.1.0 */ | 30 | #define MIXART_DRIVER_VERSION 0x000100 /* 0.1.0 */ |
@@ -92,9 +93,9 @@ struct mixart_mgr { | |||
92 | 93 | ||
93 | spinlock_t lock; /* interrupt spinlock */ | 94 | spinlock_t lock; /* interrupt spinlock */ |
94 | spinlock_t msg_lock; /* mailbox spinlock */ | 95 | spinlock_t msg_lock; /* mailbox spinlock */ |
95 | struct semaphore msg_mutex; /* mutex for blocking_requests */ | 96 | struct mutex msg_mutex; /* mutex for blocking_requests */ |
96 | 97 | ||
97 | struct semaphore setup_mutex; /* mutex used in hw_params, open and close */ | 98 | struct mutex setup_mutex; /* mutex used in hw_params, open and close */ |
98 | 99 | ||
99 | /* hardware interface */ | 100 | /* hardware interface */ |
100 | unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ | 101 | unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ |
@@ -107,7 +108,7 @@ struct mixart_mgr { | |||
107 | int sample_rate; | 108 | int sample_rate; |
108 | int ref_count_rate; | 109 | int ref_count_rate; |
109 | 110 | ||
110 | struct semaphore mixer_mutex; /* mutex for mixer */ | 111 | struct mutex mixer_mutex; /* mutex for mixer */ |
111 | 112 | ||
112 | }; | 113 | }; |
113 | 114 | ||
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 07c707d7ebbf..406ac3a9d42a 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c | |||
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #include <sound/driver.h> | 23 | #include <sound/driver.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/mutex.h> | ||
26 | |||
25 | #include <asm/io.h> | 27 | #include <asm/io.h> |
26 | #include <sound/core.h> | 28 | #include <sound/core.h> |
27 | #include "mixart.h" | 29 | #include "mixart.h" |
@@ -239,7 +241,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int | |||
239 | wait_queue_t wait; | 241 | wait_queue_t wait; |
240 | long timeout; | 242 | long timeout; |
241 | 243 | ||
242 | down(&mgr->msg_mutex); | 244 | mutex_lock(&mgr->msg_mutex); |
243 | 245 | ||
244 | init_waitqueue_entry(&wait, current); | 246 | init_waitqueue_entry(&wait, current); |
245 | 247 | ||
@@ -248,7 +250,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int | |||
248 | err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ | 250 | err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ |
249 | if (err) { | 251 | if (err) { |
250 | spin_unlock_irq(&mgr->msg_lock); | 252 | spin_unlock_irq(&mgr->msg_lock); |
251 | up(&mgr->msg_mutex); | 253 | mutex_unlock(&mgr->msg_mutex); |
252 | return err; | 254 | return err; |
253 | } | 255 | } |
254 | 256 | ||
@@ -260,7 +262,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int | |||
260 | 262 | ||
261 | if (! timeout) { | 263 | if (! timeout) { |
262 | /* error - no ack */ | 264 | /* error - no ack */ |
263 | up(&mgr->msg_mutex); | 265 | mutex_unlock(&mgr->msg_mutex); |
264 | snd_printk(KERN_ERR "error: no reponse on msg %x\n", msg_frame); | 266 | snd_printk(KERN_ERR "error: no reponse on msg %x\n", msg_frame); |
265 | return -EIO; | 267 | return -EIO; |
266 | } | 268 | } |
@@ -276,7 +278,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int | |||
276 | if( request->message_id != resp.message_id ) | 278 | if( request->message_id != resp.message_id ) |
277 | snd_printk(KERN_ERR "REPONSE ERROR!\n"); | 279 | snd_printk(KERN_ERR "REPONSE ERROR!\n"); |
278 | 280 | ||
279 | up(&mgr->msg_mutex); | 281 | mutex_unlock(&mgr->msg_mutex); |
280 | return err; | 282 | return err; |
281 | } | 283 | } |
282 | 284 | ||
@@ -292,7 +294,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, | |||
292 | snd_assert((notif_event & MSG_TYPE_MASK) == MSG_TYPE_NOTIFY, return -EINVAL); | 294 | snd_assert((notif_event & MSG_TYPE_MASK) == MSG_TYPE_NOTIFY, return -EINVAL); |
293 | snd_assert((notif_event & MSG_CANCEL_NOTIFY_MASK) == 0, return -EINVAL); | 295 | snd_assert((notif_event & MSG_CANCEL_NOTIFY_MASK) == 0, return -EINVAL); |
294 | 296 | ||
295 | down(&mgr->msg_mutex); | 297 | mutex_lock(&mgr->msg_mutex); |
296 | 298 | ||
297 | init_waitqueue_entry(&wait, current); | 299 | init_waitqueue_entry(&wait, current); |
298 | 300 | ||
@@ -301,7 +303,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, | |||
301 | err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ | 303 | err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ |
302 | if(err) { | 304 | if(err) { |
303 | spin_unlock_irq(&mgr->msg_lock); | 305 | spin_unlock_irq(&mgr->msg_lock); |
304 | up(&mgr->msg_mutex); | 306 | mutex_unlock(&mgr->msg_mutex); |
305 | return err; | 307 | return err; |
306 | } | 308 | } |
307 | 309 | ||
@@ -313,12 +315,12 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, | |||
313 | 315 | ||
314 | if (! timeout) { | 316 | if (! timeout) { |
315 | /* error - no ack */ | 317 | /* error - no ack */ |
316 | up(&mgr->msg_mutex); | 318 | mutex_unlock(&mgr->msg_mutex); |
317 | snd_printk(KERN_ERR "error: notification %x not received\n", notif_event); | 319 | snd_printk(KERN_ERR "error: notification %x not received\n", notif_event); |
318 | return -EIO; | 320 | return -EIO; |
319 | } | 321 | } |
320 | 322 | ||
321 | up(&mgr->msg_mutex); | 323 | mutex_unlock(&mgr->msg_mutex); |
322 | return 0; | 324 | return 0; |
323 | } | 325 | } |
324 | 326 | ||
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index 36a7e9ddfb15..ed47b732c103 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/time.h> | 24 | #include <linux/time.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/mutex.h> | ||
28 | |||
27 | #include <sound/core.h> | 29 | #include <sound/core.h> |
28 | #include "mixart.h" | 30 | #include "mixart.h" |
29 | #include "mixart_core.h" | 31 | #include "mixart_core.h" |
@@ -353,7 +355,7 @@ static int mixart_analog_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
353 | static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 355 | static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
354 | { | 356 | { |
355 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); | 357 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); |
356 | down(&chip->mgr->mixer_mutex); | 358 | mutex_lock(&chip->mgr->mixer_mutex); |
357 | if(kcontrol->private_value == 0) { /* playback */ | 359 | if(kcontrol->private_value == 0) { /* playback */ |
358 | ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; | 360 | ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; |
359 | ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; | 361 | ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; |
@@ -361,7 +363,7 @@ static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
361 | ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; | 363 | ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; |
362 | ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; | 364 | ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; |
363 | } | 365 | } |
364 | up(&chip->mgr->mixer_mutex); | 366 | mutex_unlock(&chip->mgr->mixer_mutex); |
365 | return 0; | 367 | return 0; |
366 | } | 368 | } |
367 | 369 | ||
@@ -371,7 +373,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
371 | int changed = 0; | 373 | int changed = 0; |
372 | int is_capture, i; | 374 | int is_capture, i; |
373 | 375 | ||
374 | down(&chip->mgr->mixer_mutex); | 376 | mutex_lock(&chip->mgr->mixer_mutex); |
375 | is_capture = (kcontrol->private_value != 0); | 377 | is_capture = (kcontrol->private_value != 0); |
376 | for(i=0; i<2; i++) { | 378 | for(i=0; i<2; i++) { |
377 | int new_volume = ucontrol->value.integer.value[i]; | 379 | int new_volume = ucontrol->value.integer.value[i]; |
@@ -382,7 +384,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
382 | } | 384 | } |
383 | } | 385 | } |
384 | if(changed) mixart_update_analog_audio_level(chip, is_capture); | 386 | if(changed) mixart_update_analog_audio_level(chip, is_capture); |
385 | up(&chip->mgr->mixer_mutex); | 387 | mutex_unlock(&chip->mgr->mixer_mutex); |
386 | return changed; | 388 | return changed; |
387 | } | 389 | } |
388 | 390 | ||
@@ -408,10 +410,10 @@ static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
408 | { | 410 | { |
409 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); | 411 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); |
410 | 412 | ||
411 | down(&chip->mgr->mixer_mutex); | 413 | mutex_lock(&chip->mgr->mixer_mutex); |
412 | ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; | 414 | ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; |
413 | ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; | 415 | ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; |
414 | up(&chip->mgr->mixer_mutex); | 416 | mutex_unlock(&chip->mgr->mixer_mutex); |
415 | return 0; | 417 | return 0; |
416 | } | 418 | } |
417 | 419 | ||
@@ -419,7 +421,7 @@ static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
419 | { | 421 | { |
420 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); | 422 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); |
421 | int i, changed = 0; | 423 | int i, changed = 0; |
422 | down(&chip->mgr->mixer_mutex); | 424 | mutex_lock(&chip->mgr->mixer_mutex); |
423 | for(i=0; i<2; i++) { | 425 | for(i=0; i<2; i++) { |
424 | if(chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) { | 426 | if(chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) { |
425 | chip->analog_playback_active[i] = ucontrol->value.integer.value[i]; | 427 | chip->analog_playback_active[i] = ucontrol->value.integer.value[i]; |
@@ -427,7 +429,7 @@ static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
427 | } | 429 | } |
428 | } | 430 | } |
429 | if(changed) mixart_update_analog_audio_level(chip, 0); /* update playback levels */ | 431 | if(changed) mixart_update_analog_audio_level(chip, 0); /* update playback levels */ |
430 | up(&chip->mgr->mixer_mutex); | 432 | mutex_unlock(&chip->mgr->mixer_mutex); |
431 | return changed; | 433 | return changed; |
432 | } | 434 | } |
433 | 435 | ||
@@ -817,7 +819,7 @@ static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
817 | int *stored_volume; | 819 | int *stored_volume; |
818 | int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; | 820 | int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; |
819 | int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; | 821 | int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; |
820 | down(&chip->mgr->mixer_mutex); | 822 | mutex_lock(&chip->mgr->mixer_mutex); |
821 | if(is_capture) { | 823 | if(is_capture) { |
822 | if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ | 824 | if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ |
823 | else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ | 825 | else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ |
@@ -828,7 +830,7 @@ static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
828 | } | 830 | } |
829 | ucontrol->value.integer.value[0] = stored_volume[0]; | 831 | ucontrol->value.integer.value[0] = stored_volume[0]; |
830 | ucontrol->value.integer.value[1] = stored_volume[1]; | 832 | ucontrol->value.integer.value[1] = stored_volume[1]; |
831 | up(&chip->mgr->mixer_mutex); | 833 | mutex_unlock(&chip->mgr->mixer_mutex); |
832 | return 0; | 834 | return 0; |
833 | } | 835 | } |
834 | 836 | ||
@@ -841,7 +843,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
841 | int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; | 843 | int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; |
842 | int* stored_volume; | 844 | int* stored_volume; |
843 | int i; | 845 | int i; |
844 | down(&chip->mgr->mixer_mutex); | 846 | mutex_lock(&chip->mgr->mixer_mutex); |
845 | if(is_capture) { | 847 | if(is_capture) { |
846 | if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ | 848 | if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ |
847 | else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ | 849 | else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ |
@@ -860,7 +862,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
860 | if(is_capture) mixart_update_capture_stream_level(chip, is_aes); | 862 | if(is_capture) mixart_update_capture_stream_level(chip, is_aes); |
861 | else mixart_update_playback_stream_level(chip, is_aes, idx); | 863 | else mixart_update_playback_stream_level(chip, is_aes, idx); |
862 | } | 864 | } |
863 | up(&chip->mgr->mixer_mutex); | 865 | mutex_unlock(&chip->mgr->mixer_mutex); |
864 | return changed; | 866 | return changed; |
865 | } | 867 | } |
866 | 868 | ||
@@ -880,12 +882,12 @@ static int mixart_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
880 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); | 882 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); |
881 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ | 883 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ |
882 | snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); | 884 | snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); |
883 | down(&chip->mgr->mixer_mutex); | 885 | mutex_lock(&chip->mgr->mixer_mutex); |
884 | if(kcontrol->private_value & MIXART_VOL_AES_MASK) /* AES playback */ | 886 | if(kcontrol->private_value & MIXART_VOL_AES_MASK) /* AES playback */ |
885 | idx += MIXART_PLAYBACK_STREAMS; | 887 | idx += MIXART_PLAYBACK_STREAMS; |
886 | ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; | 888 | ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; |
887 | ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; | 889 | ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; |
888 | up(&chip->mgr->mixer_mutex); | 890 | mutex_unlock(&chip->mgr->mixer_mutex); |
889 | return 0; | 891 | return 0; |
890 | } | 892 | } |
891 | 893 | ||
@@ -897,7 +899,7 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
897 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ | 899 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ |
898 | int i, j; | 900 | int i, j; |
899 | snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); | 901 | snd_assert ( idx < MIXART_PLAYBACK_STREAMS ); |
900 | down(&chip->mgr->mixer_mutex); | 902 | mutex_lock(&chip->mgr->mixer_mutex); |
901 | j = idx; | 903 | j = idx; |
902 | if(is_aes) j += MIXART_PLAYBACK_STREAMS; | 904 | if(is_aes) j += MIXART_PLAYBACK_STREAMS; |
903 | for(i=0; i<2; i++) { | 905 | for(i=0; i<2; i++) { |
@@ -907,7 +909,7 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
907 | } | 909 | } |
908 | } | 910 | } |
909 | if(changed) mixart_update_playback_stream_level(chip, is_aes, idx); | 911 | if(changed) mixart_update_playback_stream_level(chip, is_aes, idx); |
910 | up(&chip->mgr->mixer_mutex); | 912 | mutex_unlock(&chip->mgr->mixer_mutex); |
911 | return changed; | 913 | return changed; |
912 | } | 914 | } |
913 | 915 | ||
@@ -956,10 +958,10 @@ static int mixart_update_monitoring(struct snd_mixart* chip, int channel) | |||
956 | static int mixart_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 958 | static int mixart_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
957 | { | 959 | { |
958 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); | 960 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); |
959 | down(&chip->mgr->mixer_mutex); | 961 | mutex_lock(&chip->mgr->mixer_mutex); |
960 | ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; | 962 | ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; |
961 | ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; | 963 | ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; |
962 | up(&chip->mgr->mixer_mutex); | 964 | mutex_unlock(&chip->mgr->mixer_mutex); |
963 | return 0; | 965 | return 0; |
964 | } | 966 | } |
965 | 967 | ||
@@ -968,7 +970,7 @@ static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
968 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); | 970 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); |
969 | int changed = 0; | 971 | int changed = 0; |
970 | int i; | 972 | int i; |
971 | down(&chip->mgr->mixer_mutex); | 973 | mutex_lock(&chip->mgr->mixer_mutex); |
972 | for(i=0; i<2; i++) { | 974 | for(i=0; i<2; i++) { |
973 | if(chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { | 975 | if(chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { |
974 | chip->monitoring_volume[i] = ucontrol->value.integer.value[i]; | 976 | chip->monitoring_volume[i] = ucontrol->value.integer.value[i]; |
@@ -976,7 +978,7 @@ static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
976 | changed = 1; | 978 | changed = 1; |
977 | } | 979 | } |
978 | } | 980 | } |
979 | up(&chip->mgr->mixer_mutex); | 981 | mutex_unlock(&chip->mgr->mixer_mutex); |
980 | return changed; | 982 | return changed; |
981 | } | 983 | } |
982 | 984 | ||
@@ -995,10 +997,10 @@ static struct snd_kcontrol_new mixart_control_monitor_vol = { | |||
995 | static int mixart_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 997 | static int mixart_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
996 | { | 998 | { |
997 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); | 999 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); |
998 | down(&chip->mgr->mixer_mutex); | 1000 | mutex_lock(&chip->mgr->mixer_mutex); |
999 | ucontrol->value.integer.value[0] = chip->monitoring_active[0]; | 1001 | ucontrol->value.integer.value[0] = chip->monitoring_active[0]; |
1000 | ucontrol->value.integer.value[1] = chip->monitoring_active[1]; | 1002 | ucontrol->value.integer.value[1] = chip->monitoring_active[1]; |
1001 | up(&chip->mgr->mixer_mutex); | 1003 | mutex_unlock(&chip->mgr->mixer_mutex); |
1002 | return 0; | 1004 | return 0; |
1003 | } | 1005 | } |
1004 | 1006 | ||
@@ -1007,7 +1009,7 @@ static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1007 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); | 1009 | struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); |
1008 | int changed = 0; | 1010 | int changed = 0; |
1009 | int i; | 1011 | int i; |
1010 | down(&chip->mgr->mixer_mutex); | 1012 | mutex_lock(&chip->mgr->mixer_mutex); |
1011 | for(i=0; i<2; i++) { | 1013 | for(i=0; i<2; i++) { |
1012 | if(chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { | 1014 | if(chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { |
1013 | chip->monitoring_active[i] = ucontrol->value.integer.value[i]; | 1015 | chip->monitoring_active[i] = ucontrol->value.integer.value[i]; |
@@ -1029,7 +1031,7 @@ static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1029 | } | 1031 | } |
1030 | } | 1032 | } |
1031 | 1033 | ||
1032 | up(&chip->mgr->mixer_mutex); | 1034 | mutex_unlock(&chip->mgr->mixer_mutex); |
1033 | return (changed != 0); | 1035 | return (changed != 0); |
1034 | } | 1036 | } |
1035 | 1037 | ||
@@ -1059,7 +1061,7 @@ int snd_mixart_create_mixer(struct mixart_mgr *mgr) | |||
1059 | struct snd_mixart *chip; | 1061 | struct snd_mixart *chip; |
1060 | int err, i; | 1062 | int err, i; |
1061 | 1063 | ||
1062 | init_MUTEX(&mgr->mixer_mutex); /* can be in another place */ | 1064 | mutex_init(&mgr->mixer_mutex); /* can be in another place */ |
1063 | 1065 | ||
1064 | for(i=0; i<mgr->num_cards; i++) { | 1066 | for(i=0; i<mgr->num_cards; i++) { |
1065 | struct snd_kcontrol_new temp; | 1067 | struct snd_kcontrol_new temp; |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 0d0ff54f0fc6..cc297abc9d11 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
35 | #include <linux/mutex.h> | ||
36 | |||
35 | #include <sound/core.h> | 37 | #include <sound/core.h> |
36 | #include <sound/info.h> | 38 | #include <sound/info.h> |
37 | #include <sound/control.h> | 39 | #include <sound/control.h> |
@@ -226,6 +228,7 @@ struct nm256 { | |||
226 | unsigned int use_cache: 1; /* use one big coef. table */ | 228 | unsigned int use_cache: 1; /* use one big coef. table */ |
227 | unsigned int reset_workaround: 1; /* Workaround for some laptops to avoid freeze */ | 229 | unsigned int reset_workaround: 1; /* Workaround for some laptops to avoid freeze */ |
228 | unsigned int reset_workaround_2: 1; /* Extended workaround for some other laptops to avoid freeze */ | 230 | unsigned int reset_workaround_2: 1; /* Extended workaround for some other laptops to avoid freeze */ |
231 | unsigned int in_resume: 1; | ||
229 | 232 | ||
230 | int mixer_base; /* register offset of ac97 mixer */ | 233 | int mixer_base; /* register offset of ac97 mixer */ |
231 | int mixer_status_offset; /* offset of mixer status reg. */ | 234 | int mixer_status_offset; /* offset of mixer status reg. */ |
@@ -235,11 +238,12 @@ struct nm256 { | |||
235 | int irq_acks; | 238 | int irq_acks; |
236 | irqreturn_t (*interrupt)(int, void *, struct pt_regs *); | 239 | irqreturn_t (*interrupt)(int, void *, struct pt_regs *); |
237 | int badintrcount; /* counter to check bogus interrupts */ | 240 | int badintrcount; /* counter to check bogus interrupts */ |
238 | struct semaphore irq_mutex; | 241 | struct mutex irq_mutex; |
239 | 242 | ||
240 | struct nm256_stream streams[2]; | 243 | struct nm256_stream streams[2]; |
241 | 244 | ||
242 | struct snd_ac97 *ac97; | 245 | struct snd_ac97 *ac97; |
246 | unsigned short *ac97_regs; /* register caches, only for valid regs */ | ||
243 | 247 | ||
244 | struct snd_pcm *pcm; | 248 | struct snd_pcm *pcm; |
245 | 249 | ||
@@ -459,32 +463,32 @@ snd_nm256_set_format(struct nm256 *chip, struct nm256_stream *s, | |||
459 | /* acquire interrupt */ | 463 | /* acquire interrupt */ |
460 | static int snd_nm256_acquire_irq(struct nm256 *chip) | 464 | static int snd_nm256_acquire_irq(struct nm256 *chip) |
461 | { | 465 | { |
462 | down(&chip->irq_mutex); | 466 | mutex_lock(&chip->irq_mutex); |
463 | if (chip->irq < 0) { | 467 | if (chip->irq < 0) { |
464 | if (request_irq(chip->pci->irq, chip->interrupt, SA_INTERRUPT|SA_SHIRQ, | 468 | if (request_irq(chip->pci->irq, chip->interrupt, SA_INTERRUPT|SA_SHIRQ, |
465 | chip->card->driver, chip)) { | 469 | chip->card->driver, chip)) { |
466 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); | 470 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); |
467 | up(&chip->irq_mutex); | 471 | mutex_unlock(&chip->irq_mutex); |
468 | return -EBUSY; | 472 | return -EBUSY; |
469 | } | 473 | } |
470 | chip->irq = chip->pci->irq; | 474 | chip->irq = chip->pci->irq; |
471 | } | 475 | } |
472 | chip->irq_acks++; | 476 | chip->irq_acks++; |
473 | up(&chip->irq_mutex); | 477 | mutex_unlock(&chip->irq_mutex); |
474 | return 0; | 478 | return 0; |
475 | } | 479 | } |
476 | 480 | ||
477 | /* release interrupt */ | 481 | /* release interrupt */ |
478 | static void snd_nm256_release_irq(struct nm256 *chip) | 482 | static void snd_nm256_release_irq(struct nm256 *chip) |
479 | { | 483 | { |
480 | down(&chip->irq_mutex); | 484 | mutex_lock(&chip->irq_mutex); |
481 | if (chip->irq_acks > 0) | 485 | if (chip->irq_acks > 0) |
482 | chip->irq_acks--; | 486 | chip->irq_acks--; |
483 | if (chip->irq_acks == 0 && chip->irq >= 0) { | 487 | if (chip->irq_acks == 0 && chip->irq >= 0) { |
484 | free_irq(chip->irq, chip); | 488 | free_irq(chip->irq, chip); |
485 | chip->irq = -1; | 489 | chip->irq = -1; |
486 | } | 490 | } |
487 | up(&chip->irq_mutex); | 491 | mutex_unlock(&chip->irq_mutex); |
488 | } | 492 | } |
489 | 493 | ||
490 | /* | 494 | /* |
@@ -1151,23 +1155,63 @@ snd_nm256_ac97_ready(struct nm256 *chip) | |||
1151 | return 0; | 1155 | return 0; |
1152 | } | 1156 | } |
1153 | 1157 | ||
1158 | /* | ||
1159 | * Initial register values to be written to the AC97 mixer. | ||
1160 | * While most of these are identical to the reset values, we do this | ||
1161 | * so that we have most of the register contents cached--this avoids | ||
1162 | * reading from the mixer directly (which seems to be problematic, | ||
1163 | * probably due to ignorance). | ||
1164 | */ | ||
1165 | |||
1166 | struct initialValues { | ||
1167 | unsigned short reg; | ||
1168 | unsigned short value; | ||
1169 | }; | ||
1170 | |||
1171 | static struct initialValues nm256_ac97_init_val[] = | ||
1172 | { | ||
1173 | { AC97_MASTER, 0x8000 }, | ||
1174 | { AC97_HEADPHONE, 0x8000 }, | ||
1175 | { AC97_MASTER_MONO, 0x8000 }, | ||
1176 | { AC97_PC_BEEP, 0x8000 }, | ||
1177 | { AC97_PHONE, 0x8008 }, | ||
1178 | { AC97_MIC, 0x8000 }, | ||
1179 | { AC97_LINE, 0x8808 }, | ||
1180 | { AC97_CD, 0x8808 }, | ||
1181 | { AC97_VIDEO, 0x8808 }, | ||
1182 | { AC97_AUX, 0x8808 }, | ||
1183 | { AC97_PCM, 0x8808 }, | ||
1184 | { AC97_REC_SEL, 0x0000 }, | ||
1185 | { AC97_REC_GAIN, 0x0B0B }, | ||
1186 | { AC97_GENERAL_PURPOSE, 0x0000 }, | ||
1187 | { AC97_3D_CONTROL, 0x8000 }, | ||
1188 | { AC97_VENDOR_ID1, 0x8384 }, | ||
1189 | { AC97_VENDOR_ID2, 0x7609 }, | ||
1190 | }; | ||
1191 | |||
1192 | static int nm256_ac97_idx(unsigned short reg) | ||
1193 | { | ||
1194 | int i; | ||
1195 | for (i = 0; i < ARRAY_SIZE(nm256_ac97_init_val); i++) | ||
1196 | if (nm256_ac97_init_val[i].reg == reg) | ||
1197 | return i; | ||
1198 | return -1; | ||
1199 | } | ||
1200 | |||
1154 | /* | 1201 | /* |
1202 | * some nm256 easily crash when reading from mixer registers | ||
1203 | * thus we're treating it as a write-only mixer and cache the | ||
1204 | * written values | ||
1155 | */ | 1205 | */ |
1156 | static unsigned short | 1206 | static unsigned short |
1157 | snd_nm256_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 1207 | snd_nm256_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
1158 | { | 1208 | { |
1159 | struct nm256 *chip = ac97->private_data; | 1209 | struct nm256 *chip = ac97->private_data; |
1160 | int res; | 1210 | int idx = nm256_ac97_idx(reg); |
1161 | 1211 | ||
1162 | if (reg >= 128) | 1212 | if (idx < 0) |
1163 | return 0; | 1213 | return 0; |
1164 | 1214 | return chip->ac97_regs[idx]; | |
1165 | if (! snd_nm256_ac97_ready(chip)) | ||
1166 | return 0; | ||
1167 | res = snd_nm256_readw(chip, chip->mixer_base + reg); | ||
1168 | /* Magic delay. Bleah yucky. */ | ||
1169 | msleep(1); | ||
1170 | return res; | ||
1171 | } | 1215 | } |
1172 | 1216 | ||
1173 | /* | 1217 | /* |
@@ -1178,8 +1222,12 @@ snd_nm256_ac97_write(struct snd_ac97 *ac97, | |||
1178 | { | 1222 | { |
1179 | struct nm256 *chip = ac97->private_data; | 1223 | struct nm256 *chip = ac97->private_data; |
1180 | int tries = 2; | 1224 | int tries = 2; |
1225 | int idx = nm256_ac97_idx(reg); | ||
1181 | u32 base; | 1226 | u32 base; |
1182 | 1227 | ||
1228 | if (idx < 0) | ||
1229 | return; | ||
1230 | |||
1183 | base = chip->mixer_base; | 1231 | base = chip->mixer_base; |
1184 | 1232 | ||
1185 | snd_nm256_ac97_ready(chip); | 1233 | snd_nm256_ac97_ready(chip); |
@@ -1188,12 +1236,32 @@ snd_nm256_ac97_write(struct snd_ac97 *ac97, | |||
1188 | while (tries-- > 0) { | 1236 | while (tries-- > 0) { |
1189 | snd_nm256_writew(chip, base + reg, val); | 1237 | snd_nm256_writew(chip, base + reg, val); |
1190 | msleep(1); /* a little delay here seems better.. */ | 1238 | msleep(1); /* a little delay here seems better.. */ |
1191 | if (snd_nm256_ac97_ready(chip)) | 1239 | if (snd_nm256_ac97_ready(chip)) { |
1240 | /* successful write: set cache */ | ||
1241 | chip->ac97_regs[idx] = val; | ||
1192 | return; | 1242 | return; |
1243 | } | ||
1193 | } | 1244 | } |
1194 | snd_printd("nm256: ac97 codec not ready..\n"); | 1245 | snd_printd("nm256: ac97 codec not ready..\n"); |
1195 | } | 1246 | } |
1196 | 1247 | ||
1248 | /* static resolution table */ | ||
1249 | static struct snd_ac97_res_table nm256_res_table[] = { | ||
1250 | { AC97_MASTER, 0x1f1f }, | ||
1251 | { AC97_HEADPHONE, 0x1f1f }, | ||
1252 | { AC97_MASTER_MONO, 0x001f }, | ||
1253 | { AC97_PC_BEEP, 0x001f }, | ||
1254 | { AC97_PHONE, 0x001f }, | ||
1255 | { AC97_MIC, 0x001f }, | ||
1256 | { AC97_LINE, 0x1f1f }, | ||
1257 | { AC97_CD, 0x1f1f }, | ||
1258 | { AC97_VIDEO, 0x1f1f }, | ||
1259 | { AC97_AUX, 0x1f1f }, | ||
1260 | { AC97_PCM, 0x1f1f }, | ||
1261 | { AC97_REC_GAIN, 0x0f0f }, | ||
1262 | { } /* terminator */ | ||
1263 | }; | ||
1264 | |||
1197 | /* initialize the ac97 into a known state */ | 1265 | /* initialize the ac97 into a known state */ |
1198 | static void | 1266 | static void |
1199 | snd_nm256_ac97_reset(struct snd_ac97 *ac97) | 1267 | snd_nm256_ac97_reset(struct snd_ac97 *ac97) |
@@ -1211,6 +1279,16 @@ snd_nm256_ac97_reset(struct snd_ac97 *ac97) | |||
1211 | snd_nm256_writeb(chip, 0x6cc, 0x80); | 1279 | snd_nm256_writeb(chip, 0x6cc, 0x80); |
1212 | snd_nm256_writeb(chip, 0x6cc, 0x0); | 1280 | snd_nm256_writeb(chip, 0x6cc, 0x0); |
1213 | } | 1281 | } |
1282 | if (! chip->in_resume) { | ||
1283 | int i; | ||
1284 | for (i = 0; i < ARRAY_SIZE(nm256_ac97_init_val); i++) { | ||
1285 | /* preload the cache, so as to avoid even a single | ||
1286 | * read of the mixer regs | ||
1287 | */ | ||
1288 | snd_nm256_ac97_write(ac97, nm256_ac97_init_val[i].reg, | ||
1289 | nm256_ac97_init_val[i].value); | ||
1290 | } | ||
1291 | } | ||
1214 | } | 1292 | } |
1215 | 1293 | ||
1216 | /* create an ac97 mixer interface */ | 1294 | /* create an ac97 mixer interface */ |
@@ -1219,32 +1297,25 @@ snd_nm256_mixer(struct nm256 *chip) | |||
1219 | { | 1297 | { |
1220 | struct snd_ac97_bus *pbus; | 1298 | struct snd_ac97_bus *pbus; |
1221 | struct snd_ac97_template ac97; | 1299 | struct snd_ac97_template ac97; |
1222 | int i, err; | 1300 | int err; |
1223 | static struct snd_ac97_bus_ops ops = { | 1301 | static struct snd_ac97_bus_ops ops = { |
1224 | .reset = snd_nm256_ac97_reset, | 1302 | .reset = snd_nm256_ac97_reset, |
1225 | .write = snd_nm256_ac97_write, | 1303 | .write = snd_nm256_ac97_write, |
1226 | .read = snd_nm256_ac97_read, | 1304 | .read = snd_nm256_ac97_read, |
1227 | }; | 1305 | }; |
1228 | /* looks like nm256 hangs up when unexpected registers are touched... */ | 1306 | |
1229 | static int mixer_regs[] = { | 1307 | chip->ac97_regs = kcalloc(sizeof(short), |
1230 | AC97_MASTER, AC97_HEADPHONE, AC97_MASTER_MONO, | 1308 | ARRAY_SIZE(nm256_ac97_init_val), GFP_KERNEL); |
1231 | AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE, AC97_CD, | 1309 | if (! chip->ac97_regs) |
1232 | AC97_VIDEO, AC97_AUX, AC97_PCM, AC97_REC_SEL, | 1310 | return -ENOMEM; |
1233 | AC97_REC_GAIN, AC97_GENERAL_PURPOSE, AC97_3D_CONTROL, | ||
1234 | /*AC97_EXTENDED_ID,*/ | ||
1235 | AC97_VENDOR_ID1, AC97_VENDOR_ID2, | ||
1236 | -1 | ||
1237 | }; | ||
1238 | 1311 | ||
1239 | if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) | 1312 | if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) |
1240 | return err; | 1313 | return err; |
1241 | 1314 | ||
1242 | memset(&ac97, 0, sizeof(ac97)); | 1315 | memset(&ac97, 0, sizeof(ac97)); |
1243 | ac97.scaps = AC97_SCAP_AUDIO; /* we support audio! */ | 1316 | ac97.scaps = AC97_SCAP_AUDIO; /* we support audio! */ |
1244 | ac97.limited_regs = 1; | ||
1245 | for (i = 0; mixer_regs[i] >= 0; i++) | ||
1246 | set_bit(mixer_regs[i], ac97.reg_accessed); | ||
1247 | ac97.private_data = chip; | 1317 | ac97.private_data = chip; |
1318 | ac97.res_table = nm256_res_table; | ||
1248 | pbus->no_vra = 1; | 1319 | pbus->no_vra = 1; |
1249 | err = snd_ac97_mixer(pbus, &ac97, &chip->ac97); | 1320 | err = snd_ac97_mixer(pbus, &ac97, &chip->ac97); |
1250 | if (err < 0) | 1321 | if (err < 0) |
@@ -1329,6 +1400,7 @@ static int nm256_resume(struct pci_dev *pci) | |||
1329 | int i; | 1400 | int i; |
1330 | 1401 | ||
1331 | /* Perform a full reset on the hardware */ | 1402 | /* Perform a full reset on the hardware */ |
1403 | chip->in_resume = 1; | ||
1332 | pci_restore_state(pci); | 1404 | pci_restore_state(pci); |
1333 | pci_enable_device(pci); | 1405 | pci_enable_device(pci); |
1334 | snd_nm256_init_chip(chip); | 1406 | snd_nm256_init_chip(chip); |
@@ -1346,6 +1418,7 @@ static int nm256_resume(struct pci_dev *pci) | |||
1346 | } | 1418 | } |
1347 | 1419 | ||
1348 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1420 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1421 | chip->in_resume = 0; | ||
1349 | return 0; | 1422 | return 0; |
1350 | } | 1423 | } |
1351 | #endif /* CONFIG_PM */ | 1424 | #endif /* CONFIG_PM */ |
@@ -1370,6 +1443,7 @@ static int snd_nm256_free(struct nm256 *chip) | |||
1370 | free_irq(chip->irq, chip); | 1443 | free_irq(chip->irq, chip); |
1371 | 1444 | ||
1372 | pci_disable_device(chip->pci); | 1445 | pci_disable_device(chip->pci); |
1446 | kfree(chip->ac97_regs); | ||
1373 | kfree(chip); | 1447 | kfree(chip); |
1374 | return 0; | 1448 | return 0; |
1375 | } | 1449 | } |
@@ -1407,7 +1481,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, | |||
1407 | chip->use_cache = use_cache; | 1481 | chip->use_cache = use_cache; |
1408 | spin_lock_init(&chip->reg_lock); | 1482 | spin_lock_init(&chip->reg_lock); |
1409 | chip->irq = -1; | 1483 | chip->irq = -1; |
1410 | init_MUTEX(&chip->irq_mutex); | 1484 | mutex_init(&chip->irq_mutex); |
1411 | 1485 | ||
1412 | /* store buffer sizes in bytes */ | 1486 | /* store buffer sizes in bytes */ |
1413 | chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize = playback_bufsize * 1024; | 1487 | chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize = playback_bufsize * 1024; |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index b2cba75b6b16..f679779d96e3 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -26,8 +26,11 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
32 | #include <linux/mutex.h> | ||
33 | |||
31 | #include <sound/core.h> | 34 | #include <sound/core.h> |
32 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
33 | #include <sound/info.h> | 36 | #include <sound/info.h> |
@@ -518,7 +521,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
518 | struct timeval my_tv1, my_tv2; | 521 | struct timeval my_tv1, my_tv2; |
519 | do_gettimeofday(&my_tv1); | 522 | do_gettimeofday(&my_tv1); |
520 | #endif | 523 | #endif |
521 | down(&mgr->setup_mutex); | 524 | mutex_lock(&mgr->setup_mutex); |
522 | 525 | ||
523 | /* check the pipes concerned and build pipe_array */ | 526 | /* check the pipes concerned and build pipe_array */ |
524 | for (i = 0; i < mgr->num_cards; i++) { | 527 | for (i = 0; i < mgr->num_cards; i++) { |
@@ -537,7 +540,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
537 | } | 540 | } |
538 | } | 541 | } |
539 | if (capture_mask == 0 && playback_mask == 0) { | 542 | if (capture_mask == 0 && playback_mask == 0) { |
540 | up(&mgr->setup_mutex); | 543 | mutex_unlock(&mgr->setup_mutex); |
541 | snd_printk(KERN_ERR "pcxhr_trigger_tasklet : no pipes\n"); | 544 | snd_printk(KERN_ERR "pcxhr_trigger_tasklet : no pipes\n"); |
542 | return; | 545 | return; |
543 | } | 546 | } |
@@ -548,7 +551,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
548 | /* synchronous stop of all the pipes concerned */ | 551 | /* synchronous stop of all the pipes concerned */ |
549 | err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); | 552 | err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); |
550 | if (err) { | 553 | if (err) { |
551 | up(&mgr->setup_mutex); | 554 | mutex_unlock(&mgr->setup_mutex); |
552 | snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error stop pipes (P%x C%x)\n", | 555 | snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error stop pipes (P%x C%x)\n", |
553 | playback_mask, capture_mask); | 556 | playback_mask, capture_mask); |
554 | return; | 557 | return; |
@@ -592,7 +595,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
592 | /* synchronous start of all the pipes concerned */ | 595 | /* synchronous start of all the pipes concerned */ |
593 | err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); | 596 | err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); |
594 | if (err) { | 597 | if (err) { |
595 | up(&mgr->setup_mutex); | 598 | mutex_unlock(&mgr->setup_mutex); |
596 | snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error start pipes (P%x C%x)\n", | 599 | snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error start pipes (P%x C%x)\n", |
597 | playback_mask, capture_mask); | 600 | playback_mask, capture_mask); |
598 | return; | 601 | return; |
@@ -619,7 +622,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg) | |||
619 | } | 622 | } |
620 | spin_unlock_irqrestore(&mgr->lock, flags); | 623 | spin_unlock_irqrestore(&mgr->lock, flags); |
621 | 624 | ||
622 | up(&mgr->setup_mutex); | 625 | mutex_unlock(&mgr->setup_mutex); |
623 | 626 | ||
624 | #ifdef CONFIG_SND_DEBUG_DETECT | 627 | #ifdef CONFIG_SND_DEBUG_DETECT |
625 | do_gettimeofday(&my_tv2); | 628 | do_gettimeofday(&my_tv2); |
@@ -728,7 +731,7 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs) | |||
728 | } | 731 | } |
729 | */ | 732 | */ |
730 | 733 | ||
731 | down(&mgr->setup_mutex); | 734 | mutex_lock(&mgr->setup_mutex); |
732 | 735 | ||
733 | do { | 736 | do { |
734 | /* if the stream was stopped before, format and buffer were reset */ | 737 | /* if the stream was stopped before, format and buffer were reset */ |
@@ -755,7 +758,7 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs) | |||
755 | } | 758 | } |
756 | } while(0); /* do only once (so we can use break instead of goto) */ | 759 | } while(0); /* do only once (so we can use break instead of goto) */ |
757 | 760 | ||
758 | up(&mgr->setup_mutex); | 761 | mutex_unlock(&mgr->setup_mutex); |
759 | 762 | ||
760 | return err; | 763 | return err; |
761 | } | 764 | } |
@@ -780,7 +783,7 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs, | |||
780 | /* set up format for the stream */ | 783 | /* set up format for the stream */ |
781 | format = params_format(hw); | 784 | format = params_format(hw); |
782 | 785 | ||
783 | down(&mgr->setup_mutex); | 786 | mutex_lock(&mgr->setup_mutex); |
784 | 787 | ||
785 | stream->channels = channels; | 788 | stream->channels = channels; |
786 | stream->format = format; | 789 | stream->format = format; |
@@ -789,7 +792,7 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs, | |||
789 | /* | 792 | /* |
790 | err = pcxhr_set_format(stream); | 793 | err = pcxhr_set_format(stream); |
791 | if(err) { | 794 | if(err) { |
792 | up(&mgr->setup_mutex); | 795 | mutex_unlock(&mgr->setup_mutex); |
793 | return err; | 796 | return err; |
794 | } | 797 | } |
795 | */ | 798 | */ |
@@ -801,7 +804,7 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs, | |||
801 | err = pcxhr_update_r_buffer(stream); | 804 | err = pcxhr_update_r_buffer(stream); |
802 | } | 805 | } |
803 | */ | 806 | */ |
804 | up(&mgr->setup_mutex); | 807 | mutex_unlock(&mgr->setup_mutex); |
805 | 808 | ||
806 | return err; | 809 | return err; |
807 | } | 810 | } |
@@ -847,7 +850,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) | |||
847 | struct pcxhr_stream *stream; | 850 | struct pcxhr_stream *stream; |
848 | int is_capture; | 851 | int is_capture; |
849 | 852 | ||
850 | down(&mgr->setup_mutex); | 853 | mutex_lock(&mgr->setup_mutex); |
851 | 854 | ||
852 | /* copy the struct snd_pcm_hardware struct */ | 855 | /* copy the struct snd_pcm_hardware struct */ |
853 | runtime->hw = pcxhr_caps; | 856 | runtime->hw = pcxhr_caps; |
@@ -871,7 +874,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) | |||
871 | /* streams in use */ | 874 | /* streams in use */ |
872 | snd_printk(KERN_ERR "pcxhr_open chip%d subs%d in use\n", | 875 | snd_printk(KERN_ERR "pcxhr_open chip%d subs%d in use\n", |
873 | chip->chip_idx, subs->number); | 876 | chip->chip_idx, subs->number); |
874 | up(&mgr->setup_mutex); | 877 | mutex_unlock(&mgr->setup_mutex); |
875 | return -EBUSY; | 878 | return -EBUSY; |
876 | } | 879 | } |
877 | 880 | ||
@@ -887,7 +890,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) | |||
887 | &external_rate) || | 890 | &external_rate) || |
888 | external_rate == 0) { | 891 | external_rate == 0) { |
889 | /* cannot detect the external clock rate */ | 892 | /* cannot detect the external clock rate */ |
890 | up(&mgr->setup_mutex); | 893 | mutex_unlock(&mgr->setup_mutex); |
891 | return -EBUSY; | 894 | return -EBUSY; |
892 | } | 895 | } |
893 | runtime->hw.rate_min = runtime->hw.rate_max = external_rate; | 896 | runtime->hw.rate_min = runtime->hw.rate_max = external_rate; |
@@ -905,7 +908,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs) | |||
905 | 908 | ||
906 | mgr->ref_count_rate++; | 909 | mgr->ref_count_rate++; |
907 | 910 | ||
908 | up(&mgr->setup_mutex); | 911 | mutex_unlock(&mgr->setup_mutex); |
909 | return 0; | 912 | return 0; |
910 | } | 913 | } |
911 | 914 | ||
@@ -916,7 +919,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs) | |||
916 | struct pcxhr_mgr *mgr = chip->mgr; | 919 | struct pcxhr_mgr *mgr = chip->mgr; |
917 | struct pcxhr_stream *stream = subs->runtime->private_data; | 920 | struct pcxhr_stream *stream = subs->runtime->private_data; |
918 | 921 | ||
919 | down(&mgr->setup_mutex); | 922 | mutex_lock(&mgr->setup_mutex); |
920 | 923 | ||
921 | snd_printdd("pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number); | 924 | snd_printdd("pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number); |
922 | 925 | ||
@@ -929,7 +932,7 @@ static int pcxhr_close(struct snd_pcm_substream *subs) | |||
929 | stream->status = PCXHR_STREAM_STATUS_FREE; | 932 | stream->status = PCXHR_STREAM_STATUS_FREE; |
930 | stream->substream = NULL; | 933 | stream->substream = NULL; |
931 | 934 | ||
932 | up(&mgr->setup_mutex); | 935 | mutex_unlock(&mgr->setup_mutex); |
933 | 936 | ||
934 | return 0; | 937 | return 0; |
935 | } | 938 | } |
@@ -1215,7 +1218,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id | |||
1215 | pci_set_master(pci); | 1218 | pci_set_master(pci); |
1216 | 1219 | ||
1217 | /* check if we can restrict PCI DMA transfers to 32 bits */ | 1220 | /* check if we can restrict PCI DMA transfers to 32 bits */ |
1218 | if (pci_set_dma_mask(pci, 0xffffffff) < 0) { | 1221 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) { |
1219 | snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); | 1222 | snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); |
1220 | pci_disable_device(pci); | 1223 | pci_disable_device(pci); |
1221 | return -ENXIO; | 1224 | return -ENXIO; |
@@ -1264,7 +1267,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id | |||
1264 | spin_lock_init(&mgr->msg_lock); | 1267 | spin_lock_init(&mgr->msg_lock); |
1265 | 1268 | ||
1266 | /* init setup mutex*/ | 1269 | /* init setup mutex*/ |
1267 | init_MUTEX(&mgr->setup_mutex); | 1270 | mutex_init(&mgr->setup_mutex); |
1268 | 1271 | ||
1269 | /* init taslket */ | 1272 | /* init taslket */ |
1270 | tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, (unsigned long) mgr); | 1273 | tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, (unsigned long) mgr); |
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index 049f2b3f2867..652064787a55 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #define __SOUND_PCXHR_H | 24 | #define __SOUND_PCXHR_H |
25 | 25 | ||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/mutex.h> | ||
27 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
28 | 29 | ||
29 | #define PCXHR_DRIVER_VERSION 0x000804 /* 0.8.4 */ | 30 | #define PCXHR_DRIVER_VERSION 0x000804 /* 0.8.4 */ |
@@ -76,8 +77,8 @@ struct pcxhr_mgr { | |||
76 | spinlock_t lock; /* interrupt spinlock */ | 77 | spinlock_t lock; /* interrupt spinlock */ |
77 | spinlock_t msg_lock; /* message spinlock */ | 78 | spinlock_t msg_lock; /* message spinlock */ |
78 | 79 | ||
79 | struct semaphore setup_mutex; /* mutex used in hw_params, open and close */ | 80 | struct mutex setup_mutex; /* mutex used in hw_params, open and close */ |
80 | struct semaphore mixer_mutex; /* mutex for mixer */ | 81 | struct mutex mixer_mutex; /* mutex for mixer */ |
81 | 82 | ||
82 | /* hardware interface */ | 83 | /* hardware interface */ |
83 | unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ | 84 | unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ |
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index fa0d27e2c79b..fdc652c6992d 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c | |||
@@ -1176,7 +1176,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1176 | mgr->dsp_time_last = dsp_time_new; | 1176 | mgr->dsp_time_last = dsp_time_new; |
1177 | 1177 | ||
1178 | if (timer_toggle == mgr->timer_toggle) | 1178 | if (timer_toggle == mgr->timer_toggle) |
1179 | snd_printk(KERN_ERR "ERROR TIMER TOGGLE\n"); | 1179 | snd_printdd("ERROR TIMER TOGGLE\n"); |
1180 | mgr->timer_toggle = timer_toggle; | 1180 | mgr->timer_toggle = timer_toggle; |
1181 | 1181 | ||
1182 | reg &= ~PCXHR_IRQ_TIMER; | 1182 | reg &= ~PCXHR_IRQ_TIMER; |
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index 760e733ac25e..94e63a1e90d9 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/time.h> | 25 | #include <linux/time.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/mutex.h> | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include "pcxhr.h" | 30 | #include "pcxhr.h" |
30 | #include "pcxhr_hwdep.h" | 31 | #include "pcxhr_hwdep.h" |
@@ -92,7 +93,7 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol, | |||
92 | struct snd_ctl_elem_value *ucontrol) | 93 | struct snd_ctl_elem_value *ucontrol) |
93 | { | 94 | { |
94 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 95 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
95 | down(&chip->mgr->mixer_mutex); | 96 | mutex_lock(&chip->mgr->mixer_mutex); |
96 | if (kcontrol->private_value == 0) { /* playback */ | 97 | if (kcontrol->private_value == 0) { /* playback */ |
97 | ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; | 98 | ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; |
98 | ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; | 99 | ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; |
@@ -100,7 +101,7 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol, | |||
100 | ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; | 101 | ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; |
101 | ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; | 102 | ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; |
102 | } | 103 | } |
103 | up(&chip->mgr->mixer_mutex); | 104 | mutex_unlock(&chip->mgr->mixer_mutex); |
104 | return 0; | 105 | return 0; |
105 | } | 106 | } |
106 | 107 | ||
@@ -111,7 +112,7 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, | |||
111 | int changed = 0; | 112 | int changed = 0; |
112 | int is_capture, i; | 113 | int is_capture, i; |
113 | 114 | ||
114 | down(&chip->mgr->mixer_mutex); | 115 | mutex_lock(&chip->mgr->mixer_mutex); |
115 | is_capture = (kcontrol->private_value != 0); | 116 | is_capture = (kcontrol->private_value != 0); |
116 | for (i = 0; i < 2; i++) { | 117 | for (i = 0; i < 2; i++) { |
117 | int new_volume = ucontrol->value.integer.value[i]; | 118 | int new_volume = ucontrol->value.integer.value[i]; |
@@ -123,7 +124,7 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, | |||
123 | pcxhr_update_analog_audio_level(chip, is_capture, i); | 124 | pcxhr_update_analog_audio_level(chip, is_capture, i); |
124 | } | 125 | } |
125 | } | 126 | } |
126 | up(&chip->mgr->mixer_mutex); | 127 | mutex_unlock(&chip->mgr->mixer_mutex); |
127 | return changed; | 128 | return changed; |
128 | } | 129 | } |
129 | 130 | ||
@@ -150,10 +151,10 @@ static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, | |||
150 | { | 151 | { |
151 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 152 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
152 | 153 | ||
153 | down(&chip->mgr->mixer_mutex); | 154 | mutex_lock(&chip->mgr->mixer_mutex); |
154 | ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; | 155 | ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; |
155 | ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; | 156 | ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; |
156 | up(&chip->mgr->mixer_mutex); | 157 | mutex_unlock(&chip->mgr->mixer_mutex); |
157 | return 0; | 158 | return 0; |
158 | } | 159 | } |
159 | 160 | ||
@@ -162,7 +163,7 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol, | |||
162 | { | 163 | { |
163 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 164 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
164 | int i, changed = 0; | 165 | int i, changed = 0; |
165 | down(&chip->mgr->mixer_mutex); | 166 | mutex_lock(&chip->mgr->mixer_mutex); |
166 | for(i = 0; i < 2; i++) { | 167 | for(i = 0; i < 2; i++) { |
167 | if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) { | 168 | if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) { |
168 | chip->analog_playback_active[i] = ucontrol->value.integer.value[i]; | 169 | chip->analog_playback_active[i] = ucontrol->value.integer.value[i]; |
@@ -170,7 +171,7 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol, | |||
170 | pcxhr_update_analog_audio_level(chip, 0, i); /* update playback levels */ | 171 | pcxhr_update_analog_audio_level(chip, 0, i); /* update playback levels */ |
171 | } | 172 | } |
172 | } | 173 | } |
173 | up(&chip->mgr->mixer_mutex); | 174 | mutex_unlock(&chip->mgr->mixer_mutex); |
174 | return changed; | 175 | return changed; |
175 | } | 176 | } |
176 | 177 | ||
@@ -299,14 +300,14 @@ static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol, | |||
299 | int *stored_volume; | 300 | int *stored_volume; |
300 | int is_capture = kcontrol->private_value; | 301 | int is_capture = kcontrol->private_value; |
301 | 302 | ||
302 | down(&chip->mgr->mixer_mutex); | 303 | mutex_lock(&chip->mgr->mixer_mutex); |
303 | if (is_capture) | 304 | if (is_capture) |
304 | stored_volume = chip->digital_capture_volume; /* digital capture */ | 305 | stored_volume = chip->digital_capture_volume; /* digital capture */ |
305 | else | 306 | else |
306 | stored_volume = chip->digital_playback_volume[idx]; /* digital playback */ | 307 | stored_volume = chip->digital_playback_volume[idx]; /* digital playback */ |
307 | ucontrol->value.integer.value[0] = stored_volume[0]; | 308 | ucontrol->value.integer.value[0] = stored_volume[0]; |
308 | ucontrol->value.integer.value[1] = stored_volume[1]; | 309 | ucontrol->value.integer.value[1] = stored_volume[1]; |
309 | up(&chip->mgr->mixer_mutex); | 310 | mutex_unlock(&chip->mgr->mixer_mutex); |
310 | return 0; | 311 | return 0; |
311 | } | 312 | } |
312 | 313 | ||
@@ -320,7 +321,7 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
320 | int *stored_volume; | 321 | int *stored_volume; |
321 | int i; | 322 | int i; |
322 | 323 | ||
323 | down(&chip->mgr->mixer_mutex); | 324 | mutex_lock(&chip->mgr->mixer_mutex); |
324 | if (is_capture) | 325 | if (is_capture) |
325 | stored_volume = chip->digital_capture_volume; /* digital capture */ | 326 | stored_volume = chip->digital_capture_volume; /* digital capture */ |
326 | else | 327 | else |
@@ -335,7 +336,7 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
335 | } | 336 | } |
336 | if (! is_capture && changed) | 337 | if (! is_capture && changed) |
337 | pcxhr_update_playback_stream_level(chip, idx); /* update playback volume */ | 338 | pcxhr_update_playback_stream_level(chip, idx); /* update playback volume */ |
338 | up(&chip->mgr->mixer_mutex); | 339 | mutex_unlock(&chip->mgr->mixer_mutex); |
339 | return changed; | 340 | return changed; |
340 | } | 341 | } |
341 | 342 | ||
@@ -356,10 +357,10 @@ static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol, | |||
356 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 357 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
357 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ | 358 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ |
358 | 359 | ||
359 | down(&chip->mgr->mixer_mutex); | 360 | mutex_lock(&chip->mgr->mixer_mutex); |
360 | ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; | 361 | ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; |
361 | ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; | 362 | ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; |
362 | up(&chip->mgr->mixer_mutex); | 363 | mutex_unlock(&chip->mgr->mixer_mutex); |
363 | return 0; | 364 | return 0; |
364 | } | 365 | } |
365 | 366 | ||
@@ -370,7 +371,7 @@ static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
370 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ | 371 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ |
371 | int i, j; | 372 | int i, j; |
372 | 373 | ||
373 | down(&chip->mgr->mixer_mutex); | 374 | mutex_lock(&chip->mgr->mixer_mutex); |
374 | j = idx; | 375 | j = idx; |
375 | for (i = 0; i < 2; i++) { | 376 | for (i = 0; i < 2; i++) { |
376 | if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) { | 377 | if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) { |
@@ -380,7 +381,7 @@ static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
380 | } | 381 | } |
381 | if (changed) | 382 | if (changed) |
382 | pcxhr_update_playback_stream_level(chip, idx); | 383 | pcxhr_update_playback_stream_level(chip, idx); |
383 | up(&chip->mgr->mixer_mutex); | 384 | mutex_unlock(&chip->mgr->mixer_mutex); |
384 | return changed; | 385 | return changed; |
385 | } | 386 | } |
386 | 387 | ||
@@ -402,10 +403,10 @@ static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol, | |||
402 | struct snd_ctl_elem_value *ucontrol) | 403 | struct snd_ctl_elem_value *ucontrol) |
403 | { | 404 | { |
404 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 405 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
405 | down(&chip->mgr->mixer_mutex); | 406 | mutex_lock(&chip->mgr->mixer_mutex); |
406 | ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; | 407 | ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; |
407 | ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; | 408 | ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; |
408 | up(&chip->mgr->mixer_mutex); | 409 | mutex_unlock(&chip->mgr->mixer_mutex); |
409 | return 0; | 410 | return 0; |
410 | } | 411 | } |
411 | 412 | ||
@@ -416,7 +417,7 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, | |||
416 | int changed = 0; | 417 | int changed = 0; |
417 | int i; | 418 | int i; |
418 | 419 | ||
419 | down(&chip->mgr->mixer_mutex); | 420 | mutex_lock(&chip->mgr->mixer_mutex); |
420 | for (i = 0; i < 2; i++) { | 421 | for (i = 0; i < 2; i++) { |
421 | if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { | 422 | if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) { |
422 | chip->monitoring_volume[i] = ucontrol->value.integer.value[i]; | 423 | chip->monitoring_volume[i] = ucontrol->value.integer.value[i]; |
@@ -426,7 +427,7 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, | |||
426 | changed = 1; | 427 | changed = 1; |
427 | } | 428 | } |
428 | } | 429 | } |
429 | up(&chip->mgr->mixer_mutex); | 430 | mutex_unlock(&chip->mgr->mixer_mutex); |
430 | return changed; | 431 | return changed; |
431 | } | 432 | } |
432 | 433 | ||
@@ -446,10 +447,10 @@ static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol, | |||
446 | struct snd_ctl_elem_value *ucontrol) | 447 | struct snd_ctl_elem_value *ucontrol) |
447 | { | 448 | { |
448 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 449 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
449 | down(&chip->mgr->mixer_mutex); | 450 | mutex_lock(&chip->mgr->mixer_mutex); |
450 | ucontrol->value.integer.value[0] = chip->monitoring_active[0]; | 451 | ucontrol->value.integer.value[0] = chip->monitoring_active[0]; |
451 | ucontrol->value.integer.value[1] = chip->monitoring_active[1]; | 452 | ucontrol->value.integer.value[1] = chip->monitoring_active[1]; |
452 | up(&chip->mgr->mixer_mutex); | 453 | mutex_unlock(&chip->mgr->mixer_mutex); |
453 | return 0; | 454 | return 0; |
454 | } | 455 | } |
455 | 456 | ||
@@ -460,7 +461,7 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, | |||
460 | int changed = 0; | 461 | int changed = 0; |
461 | int i; | 462 | int i; |
462 | 463 | ||
463 | down(&chip->mgr->mixer_mutex); | 464 | mutex_lock(&chip->mgr->mixer_mutex); |
464 | for (i = 0; i < 2; i++) { | 465 | for (i = 0; i < 2; i++) { |
465 | if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { | 466 | if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) { |
466 | chip->monitoring_active[i] = ucontrol->value.integer.value[i]; | 467 | chip->monitoring_active[i] = ucontrol->value.integer.value[i]; |
@@ -474,7 +475,7 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, | |||
474 | /* update right monitoring volume and mute */ | 475 | /* update right monitoring volume and mute */ |
475 | pcxhr_update_audio_pipe_level(chip, 0, 1); | 476 | pcxhr_update_audio_pipe_level(chip, 0, 1); |
476 | 477 | ||
477 | up(&chip->mgr->mixer_mutex); | 478 | mutex_unlock(&chip->mgr->mixer_mutex); |
478 | return (changed != 0); | 479 | return (changed != 0); |
479 | } | 480 | } |
480 | 481 | ||
@@ -571,13 +572,13 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol, | |||
571 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 572 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
572 | int ret = 0; | 573 | int ret = 0; |
573 | 574 | ||
574 | down(&chip->mgr->mixer_mutex); | 575 | mutex_lock(&chip->mgr->mixer_mutex); |
575 | if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) { | 576 | if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) { |
576 | chip->audio_capture_source = ucontrol->value.enumerated.item[0]; | 577 | chip->audio_capture_source = ucontrol->value.enumerated.item[0]; |
577 | pcxhr_set_audio_source(chip); | 578 | pcxhr_set_audio_source(chip); |
578 | ret = 1; | 579 | ret = 1; |
579 | } | 580 | } |
580 | up(&chip->mgr->mixer_mutex); | 581 | mutex_unlock(&chip->mgr->mixer_mutex); |
581 | return ret; | 582 | return ret; |
582 | } | 583 | } |
583 | 584 | ||
@@ -636,9 +637,9 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, | |||
636 | struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); | 637 | struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); |
637 | int rate, ret = 0; | 638 | int rate, ret = 0; |
638 | 639 | ||
639 | down(&mgr->mixer_mutex); | 640 | mutex_lock(&mgr->mixer_mutex); |
640 | if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { | 641 | if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { |
641 | down(&mgr->setup_mutex); | 642 | mutex_lock(&mgr->setup_mutex); |
642 | mgr->use_clock_type = ucontrol->value.enumerated.item[0]; | 643 | mgr->use_clock_type = ucontrol->value.enumerated.item[0]; |
643 | if (mgr->use_clock_type) | 644 | if (mgr->use_clock_type) |
644 | pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate); | 645 | pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate); |
@@ -649,10 +650,10 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, | |||
649 | if (mgr->sample_rate) | 650 | if (mgr->sample_rate) |
650 | mgr->sample_rate = rate; | 651 | mgr->sample_rate = rate; |
651 | } | 652 | } |
652 | up(&mgr->setup_mutex); | 653 | mutex_unlock(&mgr->setup_mutex); |
653 | ret = 1; /* return 1 even if the set was not done. ok ? */ | 654 | ret = 1; /* return 1 even if the set was not done. ok ? */ |
654 | } | 655 | } |
655 | up(&mgr->mixer_mutex); | 656 | mutex_unlock(&mgr->mixer_mutex); |
656 | return ret; | 657 | return ret; |
657 | } | 658 | } |
658 | 659 | ||
@@ -685,7 +686,7 @@ static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol, | |||
685 | struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); | 686 | struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); |
686 | int i, err, rate; | 687 | int i, err, rate; |
687 | 688 | ||
688 | down(&mgr->mixer_mutex); | 689 | mutex_lock(&mgr->mixer_mutex); |
689 | for(i = 0; i < 3 + mgr->capture_chips; i++) { | 690 | for(i = 0; i < 3 + mgr->capture_chips; i++) { |
690 | if (i == PCXHR_CLOCK_TYPE_INTERNAL) | 691 | if (i == PCXHR_CLOCK_TYPE_INTERNAL) |
691 | rate = mgr->sample_rate_real; | 692 | rate = mgr->sample_rate_real; |
@@ -696,7 +697,7 @@ static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol, | |||
696 | } | 697 | } |
697 | ucontrol->value.integer.value[i] = rate; | 698 | ucontrol->value.integer.value[i] = rate; |
698 | } | 699 | } |
699 | up(&mgr->mixer_mutex); | 700 | mutex_unlock(&mgr->mixer_mutex); |
700 | return 0; | 701 | return 0; |
701 | } | 702 | } |
702 | 703 | ||
@@ -765,7 +766,7 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
765 | unsigned char aes_bits; | 766 | unsigned char aes_bits; |
766 | int i, err; | 767 | int i, err; |
767 | 768 | ||
768 | down(&chip->mgr->mixer_mutex); | 769 | mutex_lock(&chip->mgr->mixer_mutex); |
769 | for(i = 0; i < 5; i++) { | 770 | for(i = 0; i < 5; i++) { |
770 | if (kcontrol->private_value == 0) /* playback */ | 771 | if (kcontrol->private_value == 0) /* playback */ |
771 | aes_bits = chip->aes_bits[i]; | 772 | aes_bits = chip->aes_bits[i]; |
@@ -776,7 +777,7 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
776 | } | 777 | } |
777 | ucontrol->value.iec958.status[i] = aes_bits; | 778 | ucontrol->value.iec958.status[i] = aes_bits; |
778 | } | 779 | } |
779 | up(&chip->mgr->mixer_mutex); | 780 | mutex_unlock(&chip->mgr->mixer_mutex); |
780 | return 0; | 781 | return 0; |
781 | } | 782 | } |
782 | 783 | ||
@@ -828,14 +829,14 @@ static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol, | |||
828 | int i, changed = 0; | 829 | int i, changed = 0; |
829 | 830 | ||
830 | /* playback */ | 831 | /* playback */ |
831 | down(&chip->mgr->mixer_mutex); | 832 | mutex_lock(&chip->mgr->mixer_mutex); |
832 | for (i = 0; i < 5; i++) { | 833 | for (i = 0; i < 5; i++) { |
833 | if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) { | 834 | if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) { |
834 | pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]); | 835 | pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]); |
835 | changed = 1; | 836 | changed = 1; |
836 | } | 837 | } |
837 | } | 838 | } |
838 | up(&chip->mgr->mixer_mutex); | 839 | mutex_unlock(&chip->mgr->mixer_mutex); |
839 | return changed; | 840 | return changed; |
840 | } | 841 | } |
841 | 842 | ||
@@ -916,7 +917,7 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr) | |||
916 | struct snd_pcxhr *chip; | 917 | struct snd_pcxhr *chip; |
917 | int err, i; | 918 | int err, i; |
918 | 919 | ||
919 | init_MUTEX(&mgr->mixer_mutex); /* can be in another place */ | 920 | mutex_init(&mgr->mixer_mutex); /* can be in another place */ |
920 | 921 | ||
921 | for (i = 0; i < mgr->num_cards; i++) { | 922 | for (i = 0; i < mgr->num_cards; i++) { |
922 | struct snd_kcontrol_new temp; | 923 | struct snd_kcontrol_new temp; |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 103b4d715ff4..980b9cd689dd 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -474,7 +474,7 @@ static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg) | |||
474 | static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan, | 474 | static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan, |
475 | unsigned int in) | 475 | unsigned int in) |
476 | { | 476 | { |
477 | if (chan > HDSPM_MIXER_CHANNELS || in > HDSPM_MIXER_CHANNELS) | 477 | if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS) |
478 | return 0; | 478 | return 0; |
479 | 479 | ||
480 | return hdspm->mixer->ch[chan].in[in]; | 480 | return hdspm->mixer->ch[chan].in[in]; |
@@ -483,7 +483,7 @@ static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan, | |||
483 | static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan, | 483 | static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan, |
484 | unsigned int pb) | 484 | unsigned int pb) |
485 | { | 485 | { |
486 | if (chan > HDSPM_MIXER_CHANNELS || pb > HDSPM_MIXER_CHANNELS) | 486 | if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS) |
487 | return 0; | 487 | return 0; |
488 | return hdspm->mixer->ch[chan].pb[pb]; | 488 | return hdspm->mixer->ch[chan].pb[pb]; |
489 | } | 489 | } |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index cf09ea99755c..46c6982c9e88 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <asm/io.h> | 27 | #include <asm/io.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/time.h> | 29 | #include <linux/time.h> |
30 | #include <linux/mutex.h> | ||
31 | |||
30 | #include <sound/core.h> | 32 | #include <sound/core.h> |
31 | #include <sound/trident.h> | 33 | #include <sound/trident.h> |
32 | 34 | ||
@@ -201,16 +203,16 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, | |||
201 | 203 | ||
202 | 204 | ||
203 | 205 | ||
204 | down(&hdr->block_mutex); | 206 | mutex_lock(&hdr->block_mutex); |
205 | blk = search_empty(hdr, runtime->dma_bytes); | 207 | blk = search_empty(hdr, runtime->dma_bytes); |
206 | if (blk == NULL) { | 208 | if (blk == NULL) { |
207 | up(&hdr->block_mutex); | 209 | mutex_unlock(&hdr->block_mutex); |
208 | return NULL; | 210 | return NULL; |
209 | } | 211 | } |
210 | if (lastpg(blk) - firstpg(blk) >= sgbuf->pages) { | 212 | if (lastpg(blk) - firstpg(blk) >= sgbuf->pages) { |
211 | snd_printk(KERN_ERR "page calculation doesn't match: allocated pages = %d, trident = %d/%d\n", sgbuf->pages, firstpg(blk), lastpg(blk)); | 213 | snd_printk(KERN_ERR "page calculation doesn't match: allocated pages = %d, trident = %d/%d\n", sgbuf->pages, firstpg(blk), lastpg(blk)); |
212 | __snd_util_mem_free(hdr, blk); | 214 | __snd_util_mem_free(hdr, blk); |
213 | up(&hdr->block_mutex); | 215 | mutex_unlock(&hdr->block_mutex); |
214 | return NULL; | 216 | return NULL; |
215 | } | 217 | } |
216 | 218 | ||
@@ -221,12 +223,12 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, | |||
221 | unsigned long ptr = (unsigned long)sgbuf->table[idx].buf; | 223 | unsigned long ptr = (unsigned long)sgbuf->table[idx].buf; |
222 | if (! is_valid_page(addr)) { | 224 | if (! is_valid_page(addr)) { |
223 | __snd_util_mem_free(hdr, blk); | 225 | __snd_util_mem_free(hdr, blk); |
224 | up(&hdr->block_mutex); | 226 | mutex_unlock(&hdr->block_mutex); |
225 | return NULL; | 227 | return NULL; |
226 | } | 228 | } |
227 | set_tlb_bus(trident, page, ptr, addr); | 229 | set_tlb_bus(trident, page, ptr, addr); |
228 | } | 230 | } |
229 | up(&hdr->block_mutex); | 231 | mutex_unlock(&hdr->block_mutex); |
230 | return blk; | 232 | return blk; |
231 | } | 233 | } |
232 | 234 | ||
@@ -248,10 +250,10 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, | |||
248 | hdr = trident->tlb.memhdr; | 250 | hdr = trident->tlb.memhdr; |
249 | snd_assert(hdr != NULL, return NULL); | 251 | snd_assert(hdr != NULL, return NULL); |
250 | 252 | ||
251 | down(&hdr->block_mutex); | 253 | mutex_lock(&hdr->block_mutex); |
252 | blk = search_empty(hdr, runtime->dma_bytes); | 254 | blk = search_empty(hdr, runtime->dma_bytes); |
253 | if (blk == NULL) { | 255 | if (blk == NULL) { |
254 | up(&hdr->block_mutex); | 256 | mutex_unlock(&hdr->block_mutex); |
255 | return NULL; | 257 | return NULL; |
256 | } | 258 | } |
257 | 259 | ||
@@ -262,12 +264,12 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, | |||
262 | ptr += SNDRV_TRIDENT_PAGE_SIZE, addr += SNDRV_TRIDENT_PAGE_SIZE) { | 264 | ptr += SNDRV_TRIDENT_PAGE_SIZE, addr += SNDRV_TRIDENT_PAGE_SIZE) { |
263 | if (! is_valid_page(addr)) { | 265 | if (! is_valid_page(addr)) { |
264 | __snd_util_mem_free(hdr, blk); | 266 | __snd_util_mem_free(hdr, blk); |
265 | up(&hdr->block_mutex); | 267 | mutex_unlock(&hdr->block_mutex); |
266 | return NULL; | 268 | return NULL; |
267 | } | 269 | } |
268 | set_tlb_bus(trident, page, ptr, addr); | 270 | set_tlb_bus(trident, page, ptr, addr); |
269 | } | 271 | } |
270 | up(&hdr->block_mutex); | 272 | mutex_unlock(&hdr->block_mutex); |
271 | return blk; | 273 | return blk; |
272 | } | 274 | } |
273 | 275 | ||
@@ -300,13 +302,13 @@ int snd_trident_free_pages(struct snd_trident *trident, | |||
300 | snd_assert(blk != NULL, return -EINVAL); | 302 | snd_assert(blk != NULL, return -EINVAL); |
301 | 303 | ||
302 | hdr = trident->tlb.memhdr; | 304 | hdr = trident->tlb.memhdr; |
303 | down(&hdr->block_mutex); | 305 | mutex_lock(&hdr->block_mutex); |
304 | /* reset TLB entries */ | 306 | /* reset TLB entries */ |
305 | for (page = firstpg(blk); page <= lastpg(blk); page++) | 307 | for (page = firstpg(blk); page <= lastpg(blk); page++) |
306 | set_silent_tlb(trident, page); | 308 | set_silent_tlb(trident, page); |
307 | /* free memory block */ | 309 | /* free memory block */ |
308 | __snd_util_mem_free(hdr, blk); | 310 | __snd_util_mem_free(hdr, blk); |
309 | up(&hdr->block_mutex); | 311 | mutex_unlock(&hdr->block_mutex); |
310 | return 0; | 312 | return 0; |
311 | } | 313 | } |
312 | 314 | ||
@@ -332,18 +334,18 @@ snd_trident_synth_alloc(struct snd_trident *hw, unsigned int size) | |||
332 | struct snd_util_memblk *blk; | 334 | struct snd_util_memblk *blk; |
333 | struct snd_util_memhdr *hdr = hw->tlb.memhdr; | 335 | struct snd_util_memhdr *hdr = hw->tlb.memhdr; |
334 | 336 | ||
335 | down(&hdr->block_mutex); | 337 | mutex_lock(&hdr->block_mutex); |
336 | blk = __snd_util_mem_alloc(hdr, size); | 338 | blk = __snd_util_mem_alloc(hdr, size); |
337 | if (blk == NULL) { | 339 | if (blk == NULL) { |
338 | up(&hdr->block_mutex); | 340 | mutex_unlock(&hdr->block_mutex); |
339 | return NULL; | 341 | return NULL; |
340 | } | 342 | } |
341 | if (synth_alloc_pages(hw, blk)) { | 343 | if (synth_alloc_pages(hw, blk)) { |
342 | __snd_util_mem_free(hdr, blk); | 344 | __snd_util_mem_free(hdr, blk); |
343 | up(&hdr->block_mutex); | 345 | mutex_unlock(&hdr->block_mutex); |
344 | return NULL; | 346 | return NULL; |
345 | } | 347 | } |
346 | up(&hdr->block_mutex); | 348 | mutex_unlock(&hdr->block_mutex); |
347 | return blk; | 349 | return blk; |
348 | } | 350 | } |
349 | 351 | ||
@@ -356,10 +358,10 @@ snd_trident_synth_free(struct snd_trident *hw, struct snd_util_memblk *blk) | |||
356 | { | 358 | { |
357 | struct snd_util_memhdr *hdr = hw->tlb.memhdr; | 359 | struct snd_util_memhdr *hdr = hw->tlb.memhdr; |
358 | 360 | ||
359 | down(&hdr->block_mutex); | 361 | mutex_lock(&hdr->block_mutex); |
360 | synth_free_pages(hw, blk); | 362 | synth_free_pages(hw, blk); |
361 | __snd_util_mem_free(hdr, blk); | 363 | __snd_util_mem_free(hdr, blk); |
362 | up(&hdr->block_mutex); | 364 | mutex_unlock(&hdr->block_mutex); |
363 | return 0; | 365 | return 0; |
364 | } | 366 | } |
365 | 367 | ||
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 423741371191..1957d29c119e 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -2375,8 +2375,10 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2375 | { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ | 2375 | { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ |
2376 | { .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */ | 2376 | { .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */ |
2377 | { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */ | 2377 | { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */ |
2378 | { .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */ | ||
2378 | { .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */ | 2379 | { .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */ |
2379 | { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ | 2380 | { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ |
2381 | { .subvendor = 0x1849, .subdevice = 0x9739, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ | ||
2380 | { .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ | 2382 | { .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ |
2381 | { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */ | 2383 | { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */ |
2382 | { .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC }, /* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */ | 2384 | { .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC }, /* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */ |
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index c705af409b0f..9b6d345b83a6 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include <linux/firmware.h> | 26 | #include <linux/firmware.h> |
27 | #include <linux/mutex.h> | ||
28 | |||
27 | #include <sound/core.h> | 29 | #include <sound/core.h> |
28 | #include <sound/control.h> | 30 | #include <sound/control.h> |
29 | #include <asm/io.h> | 31 | #include <asm/io.h> |
@@ -861,10 +863,10 @@ static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
861 | { | 863 | { |
862 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 864 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
863 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 865 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; |
864 | down(&_chip->mixer_mutex); | 866 | mutex_lock(&_chip->mixer_mutex); |
865 | ucontrol->value.integer.value[0] = chip->input_level[0]; | 867 | ucontrol->value.integer.value[0] = chip->input_level[0]; |
866 | ucontrol->value.integer.value[1] = chip->input_level[1]; | 868 | ucontrol->value.integer.value[1] = chip->input_level[1]; |
867 | up(&_chip->mixer_mutex); | 869 | mutex_unlock(&_chip->mixer_mutex); |
868 | return 0; | 870 | return 0; |
869 | } | 871 | } |
870 | 872 | ||
@@ -872,16 +874,16 @@ static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
872 | { | 874 | { |
873 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 875 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
874 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 876 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; |
875 | down(&_chip->mixer_mutex); | 877 | mutex_lock(&_chip->mixer_mutex); |
876 | if (chip->input_level[0] != ucontrol->value.integer.value[0] || | 878 | if (chip->input_level[0] != ucontrol->value.integer.value[0] || |
877 | chip->input_level[1] != ucontrol->value.integer.value[1]) { | 879 | chip->input_level[1] != ucontrol->value.integer.value[1]) { |
878 | chip->input_level[0] = ucontrol->value.integer.value[0]; | 880 | chip->input_level[0] = ucontrol->value.integer.value[0]; |
879 | chip->input_level[1] = ucontrol->value.integer.value[1]; | 881 | chip->input_level[1] = ucontrol->value.integer.value[1]; |
880 | vx2_set_input_level(chip); | 882 | vx2_set_input_level(chip); |
881 | up(&_chip->mixer_mutex); | 883 | mutex_unlock(&_chip->mixer_mutex); |
882 | return 1; | 884 | return 1; |
883 | } | 885 | } |
884 | up(&_chip->mixer_mutex); | 886 | mutex_unlock(&_chip->mixer_mutex); |
885 | return 0; | 887 | return 0; |
886 | } | 888 | } |
887 | 889 | ||
@@ -907,14 +909,14 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
907 | { | 909 | { |
908 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 910 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
909 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 911 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; |
910 | down(&_chip->mixer_mutex); | 912 | mutex_lock(&_chip->mixer_mutex); |
911 | if (chip->mic_level != ucontrol->value.integer.value[0]) { | 913 | if (chip->mic_level != ucontrol->value.integer.value[0]) { |
912 | chip->mic_level = ucontrol->value.integer.value[0]; | 914 | chip->mic_level = ucontrol->value.integer.value[0]; |
913 | vx2_set_input_level(chip); | 915 | vx2_set_input_level(chip); |
914 | up(&_chip->mixer_mutex); | 916 | mutex_unlock(&_chip->mixer_mutex); |
915 | return 1; | 917 | return 1; |
916 | } | 918 | } |
917 | up(&_chip->mixer_mutex); | 919 | mutex_unlock(&_chip->mixer_mutex); |
918 | return 0; | 920 | return 0; |
919 | } | 921 | } |
920 | 922 | ||
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index dab9b8310341..db57ce939fa8 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -49,6 +49,7 @@ static long mpu_port[SNDRV_CARDS]; | |||
49 | static long joystick_port[SNDRV_CARDS]; | 49 | static long joystick_port[SNDRV_CARDS]; |
50 | #endif | 50 | #endif |
51 | static int rear_switch[SNDRV_CARDS]; | 51 | static int rear_switch[SNDRV_CARDS]; |
52 | static int rear_swap[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; | ||
52 | 53 | ||
53 | module_param_array(index, int, NULL, 0444); | 54 | module_param_array(index, int, NULL, 0444); |
54 | MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard."); | 55 | MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard."); |
@@ -66,6 +67,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address"); | |||
66 | #endif | 67 | #endif |
67 | module_param_array(rear_switch, bool, NULL, 0444); | 68 | module_param_array(rear_switch, bool, NULL, 0444); |
68 | MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); | 69 | MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); |
70 | module_param_array(rear_swap, bool, NULL, 0444); | ||
71 | MODULE_PARM_DESC(rear_swap, "Swap rear channels (must be enabled for correct IEC958 (S/PDIF)) output"); | ||
69 | 72 | ||
70 | static struct pci_device_id snd_ymfpci_ids[] = { | 73 | static struct pci_device_id snd_ymfpci_ids[] = { |
71 | { 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724 */ | 74 | { 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724 */ |
@@ -295,7 +298,7 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, | |||
295 | snd_card_free(card); | 298 | snd_card_free(card); |
296 | return err; | 299 | return err; |
297 | } | 300 | } |
298 | if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) { | 301 | if ((err = snd_ymfpci_mixer(chip, rear_switch[dev], rear_swap[dev])) < 0) { |
299 | snd_card_free(card); | 302 | snd_card_free(card); |
300 | return err; | 303 | return err; |
301 | } | 304 | } |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index a1aa74b79b3d..8ac5ab50b5c7 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -536,15 +536,30 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int | |||
536 | } | 536 | } |
537 | } | 537 | } |
538 | if (ypcm->output_rear) { | 538 | if (ypcm->output_rear) { |
539 | if (use_left) { | 539 | if (!ypcm->swap_rear) { |
540 | bank->eff2_gain = | 540 | if (use_left) { |
541 | bank->eff2_gain_end = vol_left; | 541 | bank->eff2_gain = |
542 | } | 542 | bank->eff2_gain_end = vol_left; |
543 | if (use_right) { | 543 | } |
544 | bank->eff3_gain = | 544 | if (use_right) { |
545 | bank->eff3_gain_end = vol_right; | 545 | bank->eff3_gain = |
546 | } | 546 | bank->eff3_gain_end = vol_right; |
547 | } | 547 | } |
548 | } else { | ||
549 | /* The SPDIF out channels seem to be swapped, so we have | ||
550 | * to swap them here, too. The rear analog out channels | ||
551 | * will be wrong, but otherwise AC3 would not work. | ||
552 | */ | ||
553 | if (use_left) { | ||
554 | bank->eff3_gain = | ||
555 | bank->eff3_gain_end = vol_left; | ||
556 | } | ||
557 | if (use_right) { | ||
558 | bank->eff2_gain = | ||
559 | bank->eff2_gain_end = vol_right; | ||
560 | } | ||
561 | } | ||
562 | } | ||
548 | } | 563 | } |
549 | } | 564 | } |
550 | 565 | ||
@@ -894,6 +909,7 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) | |||
894 | ypcm = runtime->private_data; | 909 | ypcm = runtime->private_data; |
895 | ypcm->output_front = 1; | 910 | ypcm->output_front = 1; |
896 | ypcm->output_rear = chip->mode_dup4ch ? 1 : 0; | 911 | ypcm->output_rear = chip->mode_dup4ch ? 1 : 0; |
912 | ypcm->swap_rear = chip->rear_swap; | ||
897 | spin_lock_irq(&chip->reg_lock); | 913 | spin_lock_irq(&chip->reg_lock); |
898 | if (ypcm->output_rear) { | 914 | if (ypcm->output_rear) { |
899 | ymfpci_open_extension(chip); | 915 | ymfpci_open_extension(chip); |
@@ -1734,7 +1750,7 @@ static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97) | |||
1734 | chip->ac97 = NULL; | 1750 | chip->ac97 = NULL; |
1735 | } | 1751 | } |
1736 | 1752 | ||
1737 | int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) | 1753 | int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch, int rear_swap) |
1738 | { | 1754 | { |
1739 | struct snd_ac97_template ac97; | 1755 | struct snd_ac97_template ac97; |
1740 | struct snd_kcontrol *kctl; | 1756 | struct snd_kcontrol *kctl; |
@@ -1746,6 +1762,7 @@ int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) | |||
1746 | .read = snd_ymfpci_codec_read, | 1762 | .read = snd_ymfpci_codec_read, |
1747 | }; | 1763 | }; |
1748 | 1764 | ||
1765 | chip->rear_swap = rear_swap; | ||
1749 | if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) | 1766 | if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) |
1750 | return err; | 1767 | return err; |
1751 | chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus; | 1768 | chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus; |
@@ -2293,6 +2310,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, | |||
2293 | return -EIO; | 2310 | return -EIO; |
2294 | } | 2311 | } |
2295 | 2312 | ||
2313 | chip->rear_swap = 1; | ||
2296 | if ((err = snd_ymfpci_ac3_init(chip)) < 0) { | 2314 | if ((err = snd_ymfpci_ac3_init(chip)) < 0) { |
2297 | snd_ymfpci_free(chip); | 2315 | snd_ymfpci_free(chip); |
2298 | return err; | 2316 | return err; |