diff options
Diffstat (limited to 'sound')
54 files changed, 845 insertions, 170 deletions
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index 3fd1a7e24928..552b97afbca5 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c | |||
@@ -1073,10 +1073,10 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) | |||
1073 | sdev->pcmid = -1; | 1073 | sdev->pcmid = -1; |
1074 | list_del(&ldev->list); | 1074 | list_del(&ldev->list); |
1075 | layouts_list_items--; | 1075 | layouts_list_items--; |
1076 | kfree(ldev); | ||
1076 | outnodev: | 1077 | outnodev: |
1077 | of_node_put(sound); | 1078 | of_node_put(sound); |
1078 | layout_device = NULL; | 1079 | layout_device = NULL; |
1079 | kfree(ldev); | ||
1080 | return -ENODEV; | 1080 | return -ENODEV; |
1081 | } | 1081 | } |
1082 | 1082 | ||
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 86d0caf91b35..62e90b862a0d 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1761,6 +1761,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream, | |||
1761 | snd_pcm_uframes_t avail = 0; | 1761 | snd_pcm_uframes_t avail = 0; |
1762 | long wait_time, tout; | 1762 | long wait_time, tout; |
1763 | 1763 | ||
1764 | init_waitqueue_entry(&wait, current); | ||
1765 | set_current_state(TASK_INTERRUPTIBLE); | ||
1766 | add_wait_queue(&runtime->tsleep, &wait); | ||
1767 | |||
1764 | if (runtime->no_period_wakeup) | 1768 | if (runtime->no_period_wakeup) |
1765 | wait_time = MAX_SCHEDULE_TIMEOUT; | 1769 | wait_time = MAX_SCHEDULE_TIMEOUT; |
1766 | else { | 1770 | else { |
@@ -1771,16 +1775,32 @@ static int wait_for_avail(struct snd_pcm_substream *substream, | |||
1771 | } | 1775 | } |
1772 | wait_time = msecs_to_jiffies(wait_time * 1000); | 1776 | wait_time = msecs_to_jiffies(wait_time * 1000); |
1773 | } | 1777 | } |
1774 | init_waitqueue_entry(&wait, current); | 1778 | |
1775 | add_wait_queue(&runtime->tsleep, &wait); | ||
1776 | for (;;) { | 1779 | for (;;) { |
1777 | if (signal_pending(current)) { | 1780 | if (signal_pending(current)) { |
1778 | err = -ERESTARTSYS; | 1781 | err = -ERESTARTSYS; |
1779 | break; | 1782 | break; |
1780 | } | 1783 | } |
1784 | |||
1785 | /* | ||
1786 | * We need to check if space became available already | ||
1787 | * (and thus the wakeup happened already) first to close | ||
1788 | * the race of space already having become available. | ||
1789 | * This check must happen after been added to the waitqueue | ||
1790 | * and having current state be INTERRUPTIBLE. | ||
1791 | */ | ||
1792 | if (is_playback) | ||
1793 | avail = snd_pcm_playback_avail(runtime); | ||
1794 | else | ||
1795 | avail = snd_pcm_capture_avail(runtime); | ||
1796 | if (avail >= runtime->twake) | ||
1797 | break; | ||
1781 | snd_pcm_stream_unlock_irq(substream); | 1798 | snd_pcm_stream_unlock_irq(substream); |
1782 | tout = schedule_timeout_interruptible(wait_time); | 1799 | |
1800 | tout = schedule_timeout(wait_time); | ||
1801 | |||
1783 | snd_pcm_stream_lock_irq(substream); | 1802 | snd_pcm_stream_lock_irq(substream); |
1803 | set_current_state(TASK_INTERRUPTIBLE); | ||
1784 | switch (runtime->status->state) { | 1804 | switch (runtime->status->state) { |
1785 | case SNDRV_PCM_STATE_SUSPENDED: | 1805 | case SNDRV_PCM_STATE_SUSPENDED: |
1786 | err = -ESTRPIPE; | 1806 | err = -ESTRPIPE; |
@@ -1806,14 +1826,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream, | |||
1806 | err = -EIO; | 1826 | err = -EIO; |
1807 | break; | 1827 | break; |
1808 | } | 1828 | } |
1809 | if (is_playback) | ||
1810 | avail = snd_pcm_playback_avail(runtime); | ||
1811 | else | ||
1812 | avail = snd_pcm_capture_avail(runtime); | ||
1813 | if (avail >= runtime->twake) | ||
1814 | break; | ||
1815 | } | 1829 | } |
1816 | _endloop: | 1830 | _endloop: |
1831 | set_current_state(TASK_RUNNING); | ||
1817 | remove_wait_queue(&runtime->tsleep, &wait); | 1832 | remove_wait_queue(&runtime->tsleep, &wait); |
1818 | *availp = avail; | 1833 | *availp = avail; |
1819 | return err; | 1834 | return err; |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 200c9a1d48b7..a872d0a82976 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whitelist[] = { | |||
1909 | 0x103c0944, /* HP nc6220 */ | 1909 | 0x103c0944, /* HP nc6220 */ |
1910 | 0x103c0934, /* HP nc8220 */ | 1910 | 0x103c0934, /* HP nc8220 */ |
1911 | 0x103c006d, /* HP nx9105 */ | 1911 | 0x103c006d, /* HP nx9105 */ |
1912 | 0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */ | ||
1912 | 0x17340088, /* FSC Scenic-W */ | 1913 | 0x17340088, /* FSC Scenic-W */ |
1913 | 0 /* end */ | 1914 | 0 /* end */ |
1914 | }; | 1915 | }; |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index e4d76a270c9f..579fc0dce128 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -2625,16 +2625,19 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2625 | int err; | 2625 | int err; |
2626 | 2626 | ||
2627 | snd_azf3328_dbgcallenter(); | 2627 | snd_azf3328_dbgcallenter(); |
2628 | if (dev >= SNDRV_CARDS) | 2628 | if (dev >= SNDRV_CARDS) { |
2629 | return -ENODEV; | 2629 | err = -ENODEV; |
2630 | goto out; | ||
2631 | } | ||
2630 | if (!enable[dev]) { | 2632 | if (!enable[dev]) { |
2631 | dev++; | 2633 | dev++; |
2632 | return -ENOENT; | 2634 | err = -ENOENT; |
2635 | goto out; | ||
2633 | } | 2636 | } |
2634 | 2637 | ||
2635 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); | 2638 | err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); |
2636 | if (err < 0) | 2639 | if (err < 0) |
2637 | return err; | 2640 | goto out; |
2638 | 2641 | ||
2639 | strcpy(card->driver, "AZF3328"); | 2642 | strcpy(card->driver, "AZF3328"); |
2640 | strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); | 2643 | strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); |
diff --git a/sound/pci/hda/alc268_quirks.c b/sound/pci/hda/alc268_quirks.c index be58bf2f3aec..2e5876ce71fe 100644 --- a/sound/pci/hda/alc268_quirks.c +++ b/sound/pci/hda/alc268_quirks.c | |||
@@ -476,8 +476,8 @@ static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = { | |||
476 | 476 | ||
477 | static const struct alc_config_preset alc268_presets[] = { | 477 | static const struct alc_config_preset alc268_presets[] = { |
478 | [ALC267_QUANTA_IL1] = { | 478 | [ALC267_QUANTA_IL1] = { |
479 | .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer, | 479 | .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer }, |
480 | alc268_capture_nosrc_mixer }, | 480 | .cap_mixer = alc268_capture_nosrc_mixer, |
481 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 481 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
482 | alc267_quanta_il1_verbs }, | 482 | alc267_quanta_il1_verbs }, |
483 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 483 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -492,8 +492,8 @@ static const struct alc_config_preset alc268_presets[] = { | |||
492 | .init_hook = alc_inithook, | 492 | .init_hook = alc_inithook, |
493 | }, | 493 | }, |
494 | [ALC268_3ST] = { | 494 | [ALC268_3ST] = { |
495 | .mixers = { alc268_base_mixer, alc268_capture_alt_mixer, | 495 | .mixers = { alc268_base_mixer, alc268_beep_mixer }, |
496 | alc268_beep_mixer }, | 496 | .cap_mixer = alc268_capture_alt_mixer, |
497 | .init_verbs = { alc268_base_init_verbs }, | 497 | .init_verbs = { alc268_base_init_verbs }, |
498 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 498 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
499 | .dac_nids = alc268_dac_nids, | 499 | .dac_nids = alc268_dac_nids, |
@@ -507,8 +507,8 @@ static const struct alc_config_preset alc268_presets[] = { | |||
507 | .input_mux = &alc268_capture_source, | 507 | .input_mux = &alc268_capture_source, |
508 | }, | 508 | }, |
509 | [ALC268_TOSHIBA] = { | 509 | [ALC268_TOSHIBA] = { |
510 | .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer, | 510 | .mixers = { alc268_toshiba_mixer, alc268_beep_mixer }, |
511 | alc268_beep_mixer }, | 511 | .cap_mixer = alc268_capture_alt_mixer, |
512 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 512 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
513 | alc268_toshiba_verbs }, | 513 | alc268_toshiba_verbs }, |
514 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 514 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -525,8 +525,8 @@ static const struct alc_config_preset alc268_presets[] = { | |||
525 | .init_hook = alc_inithook, | 525 | .init_hook = alc_inithook, |
526 | }, | 526 | }, |
527 | [ALC268_ACER] = { | 527 | [ALC268_ACER] = { |
528 | .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer, | 528 | .mixers = { alc268_acer_mixer, alc268_beep_mixer }, |
529 | alc268_beep_mixer }, | 529 | .cap_mixer = alc268_capture_alt_mixer, |
530 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 530 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
531 | alc268_acer_verbs }, | 531 | alc268_acer_verbs }, |
532 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 532 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -543,8 +543,8 @@ static const struct alc_config_preset alc268_presets[] = { | |||
543 | .init_hook = alc_inithook, | 543 | .init_hook = alc_inithook, |
544 | }, | 544 | }, |
545 | [ALC268_ACER_DMIC] = { | 545 | [ALC268_ACER_DMIC] = { |
546 | .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer, | 546 | .mixers = { alc268_acer_dmic_mixer, alc268_beep_mixer }, |
547 | alc268_beep_mixer }, | 547 | .cap_mixer = alc268_capture_alt_mixer, |
548 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 548 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
549 | alc268_acer_verbs }, | 549 | alc268_acer_verbs }, |
550 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 550 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -561,9 +561,8 @@ static const struct alc_config_preset alc268_presets[] = { | |||
561 | .init_hook = alc_inithook, | 561 | .init_hook = alc_inithook, |
562 | }, | 562 | }, |
563 | [ALC268_ACER_ASPIRE_ONE] = { | 563 | [ALC268_ACER_ASPIRE_ONE] = { |
564 | .mixers = { alc268_acer_aspire_one_mixer, | 564 | .mixers = { alc268_acer_aspire_one_mixer, alc268_beep_mixer}, |
565 | alc268_beep_mixer, | 565 | .cap_mixer = alc268_capture_nosrc_mixer, |
566 | alc268_capture_nosrc_mixer }, | ||
567 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 566 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
568 | alc268_acer_aspire_one_verbs }, | 567 | alc268_acer_aspire_one_verbs }, |
569 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 568 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -579,8 +578,8 @@ static const struct alc_config_preset alc268_presets[] = { | |||
579 | .init_hook = alc_inithook, | 578 | .init_hook = alc_inithook, |
580 | }, | 579 | }, |
581 | [ALC268_DELL] = { | 580 | [ALC268_DELL] = { |
582 | .mixers = { alc268_dell_mixer, alc268_beep_mixer, | 581 | .mixers = { alc268_dell_mixer, alc268_beep_mixer}, |
583 | alc268_capture_nosrc_mixer }, | 582 | .cap_mixer = alc268_capture_nosrc_mixer, |
584 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 583 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
585 | alc268_dell_verbs }, | 584 | alc268_dell_verbs }, |
586 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 585 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -596,8 +595,8 @@ static const struct alc_config_preset alc268_presets[] = { | |||
596 | .init_hook = alc_inithook, | 595 | .init_hook = alc_inithook, |
597 | }, | 596 | }, |
598 | [ALC268_ZEPTO] = { | 597 | [ALC268_ZEPTO] = { |
599 | .mixers = { alc268_base_mixer, alc268_capture_alt_mixer, | 598 | .mixers = { alc268_base_mixer, alc268_beep_mixer }, |
600 | alc268_beep_mixer }, | 599 | .cap_mixer = alc268_capture_alt_mixer, |
601 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 600 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
602 | alc268_toshiba_verbs }, | 601 | alc268_toshiba_verbs }, |
603 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | 602 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), |
@@ -616,7 +615,8 @@ static const struct alc_config_preset alc268_presets[] = { | |||
616 | }, | 615 | }, |
617 | #ifdef CONFIG_SND_DEBUG | 616 | #ifdef CONFIG_SND_DEBUG |
618 | [ALC268_TEST] = { | 617 | [ALC268_TEST] = { |
619 | .mixers = { alc268_test_mixer, alc268_capture_mixer }, | 618 | .mixers = { alc268_test_mixer }, |
619 | .cap_mixer = alc268_capture_mixer, | ||
620 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | 620 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, |
621 | alc268_volume_init_verbs, | 621 | alc268_volume_init_verbs, |
622 | alc268_beep_init_verbs }, | 622 | alc268_beep_init_verbs }, |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 3e7850c238c3..f3aefef37216 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -579,9 +579,13 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, | |||
579 | return -1; | 579 | return -1; |
580 | } | 580 | } |
581 | recursive++; | 581 | recursive++; |
582 | for (i = 0; i < nums; i++) | 582 | for (i = 0; i < nums; i++) { |
583 | unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i])); | ||
584 | if (type == AC_WID_PIN || type == AC_WID_AUD_OUT) | ||
585 | continue; | ||
583 | if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0) | 586 | if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0) |
584 | return i; | 587 | return i; |
588 | } | ||
585 | return -1; | 589 | return -1; |
586 | } | 590 | } |
587 | EXPORT_SYMBOL_HDA(snd_hda_get_conn_index); | 591 | EXPORT_SYMBOL_HDA(snd_hda_get_conn_index); |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 28ce17d09c33..c34f730f4815 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -144,25 +144,17 @@ static int cea_sampling_frequencies[8] = { | |||
144 | SNDRV_PCM_RATE_192000, /* 7: 192000Hz */ | 144 | SNDRV_PCM_RATE_192000, /* 7: 192000Hz */ |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid, | 147 | static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, |
148 | int byte_index) | 148 | int byte_index) |
149 | { | 149 | { |
150 | unsigned int val; | 150 | unsigned int val; |
151 | 151 | ||
152 | val = snd_hda_codec_read(codec, nid, 0, | 152 | val = snd_hda_codec_read(codec, nid, 0, |
153 | AC_VERB_GET_HDMI_ELDD, byte_index); | 153 | AC_VERB_GET_HDMI_ELDD, byte_index); |
154 | |||
155 | #ifdef BE_PARANOID | 154 | #ifdef BE_PARANOID |
156 | printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); | 155 | printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); |
157 | #endif | 156 | #endif |
158 | 157 | return val; | |
159 | if ((val & AC_ELDD_ELD_VALID) == 0) { | ||
160 | snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n", | ||
161 | byte_index); | ||
162 | val = 0; | ||
163 | } | ||
164 | |||
165 | return val & AC_ELDD_ELD_DATA; | ||
166 | } | 158 | } |
167 | 159 | ||
168 | #define GRAB_BITS(buf, byte, lowbit, bits) \ | 160 | #define GRAB_BITS(buf, byte, lowbit, bits) \ |
@@ -344,11 +336,26 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, | |||
344 | if (!buf) | 336 | if (!buf) |
345 | return -ENOMEM; | 337 | return -ENOMEM; |
346 | 338 | ||
347 | for (i = 0; i < size; i++) | 339 | for (i = 0; i < size; i++) { |
348 | buf[i] = hdmi_get_eld_byte(codec, nid, i); | 340 | unsigned int val = hdmi_get_eld_data(codec, nid, i); |
341 | if (!(val & AC_ELDD_ELD_VALID)) { | ||
342 | if (!i) { | ||
343 | snd_printd(KERN_INFO | ||
344 | "HDMI: invalid ELD data\n"); | ||
345 | ret = -EINVAL; | ||
346 | goto error; | ||
347 | } | ||
348 | snd_printd(KERN_INFO | ||
349 | "HDMI: invalid ELD data byte %d\n", i); | ||
350 | val = 0; | ||
351 | } else | ||
352 | val &= AC_ELDD_ELD_DATA; | ||
353 | buf[i] = val; | ||
354 | } | ||
349 | 355 | ||
350 | ret = hdmi_update_eld(eld, buf, size); | 356 | ret = hdmi_update_eld(eld, buf, size); |
351 | 357 | ||
358 | error: | ||
352 | kfree(buf); | 359 | kfree(buf); |
353 | return ret; | 360 | return ret; |
354 | } | 361 | } |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 47d6ffc9b5b5..c45f3e69bcf0 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -375,7 +375,7 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx) | |||
375 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, | 375 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, |
376 | unsigned int *idxp) | 376 | unsigned int *idxp) |
377 | { | 377 | { |
378 | int i; | 378 | int i, idx; |
379 | hda_nid_t nid; | 379 | hda_nid_t nid; |
380 | 380 | ||
381 | nid = codec->start_nid; | 381 | nid = codec->start_nid; |
@@ -384,9 +384,11 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, | |||
384 | type = get_wcaps_type(get_wcaps(codec, nid)); | 384 | type = get_wcaps_type(get_wcaps(codec, nid)); |
385 | if (type != AC_WID_AUD_IN) | 385 | if (type != AC_WID_AUD_IN) |
386 | continue; | 386 | continue; |
387 | *idxp = snd_hda_get_conn_index(codec, nid, pin, false); | 387 | idx = snd_hda_get_conn_index(codec, nid, pin, false); |
388 | if (*idxp >= 0) | 388 | if (idx >= 0) { |
389 | *idxp = idx; | ||
389 | return nid; | 390 | return nid; |
391 | } | ||
390 | } | 392 | } |
391 | return 0; | 393 | return 0; |
392 | } | 394 | } |
@@ -533,7 +535,7 @@ static int add_volume(struct hda_codec *codec, const char *name, | |||
533 | int index, unsigned int pval, int dir, | 535 | int index, unsigned int pval, int dir, |
534 | struct snd_kcontrol **kctlp) | 536 | struct snd_kcontrol **kctlp) |
535 | { | 537 | { |
536 | char tmp[32]; | 538 | char tmp[44]; |
537 | struct snd_kcontrol_new knew = | 539 | struct snd_kcontrol_new knew = |
538 | HDA_CODEC_VOLUME_IDX(tmp, index, 0, 0, HDA_OUTPUT); | 540 | HDA_CODEC_VOLUME_IDX(tmp, index, 0, 0, HDA_OUTPUT); |
539 | knew.private_value = pval; | 541 | knew.private_value = pval; |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 502fc9499453..7696d05b9356 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -3348,6 +3348,8 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin, | |||
3348 | 3348 | ||
3349 | #define MAX_AUTO_DACS 5 | 3349 | #define MAX_AUTO_DACS 5 |
3350 | 3350 | ||
3351 | #define DAC_SLAVE_FLAG 0x8000 /* filled dac is a slave */ | ||
3352 | |||
3351 | /* fill analog DAC list from the widget tree */ | 3353 | /* fill analog DAC list from the widget tree */ |
3352 | static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs) | 3354 | static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs) |
3353 | { | 3355 | { |
@@ -3370,16 +3372,26 @@ static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs) | |||
3370 | /* fill pin_dac_pair list from the pin and dac list */ | 3372 | /* fill pin_dac_pair list from the pin and dac list */ |
3371 | static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins, | 3373 | static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins, |
3372 | int num_pins, hda_nid_t *dacs, int *rest, | 3374 | int num_pins, hda_nid_t *dacs, int *rest, |
3373 | struct pin_dac_pair *filled, int type) | 3375 | struct pin_dac_pair *filled, int nums, |
3376 | int type) | ||
3374 | { | 3377 | { |
3375 | int i, nums; | 3378 | int i, start = nums; |
3376 | 3379 | ||
3377 | nums = 0; | 3380 | for (i = 0; i < num_pins; i++, nums++) { |
3378 | for (i = 0; i < num_pins; i++) { | ||
3379 | filled[nums].pin = pins[i]; | 3381 | filled[nums].pin = pins[i]; |
3380 | filled[nums].type = type; | 3382 | filled[nums].type = type; |
3381 | filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest); | 3383 | filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest); |
3382 | nums++; | 3384 | if (filled[nums].dac) |
3385 | continue; | ||
3386 | if (filled[start].dac && get_connection_index(codec, pins[i], filled[start].dac) >= 0) { | ||
3387 | filled[nums].dac = filled[start].dac | DAC_SLAVE_FLAG; | ||
3388 | continue; | ||
3389 | } | ||
3390 | if (filled[0].dac && get_connection_index(codec, pins[i], filled[0].dac) >= 0) { | ||
3391 | filled[nums].dac = filled[0].dac | DAC_SLAVE_FLAG; | ||
3392 | continue; | ||
3393 | } | ||
3394 | snd_printdd("Failed to find a DAC for pin 0x%x", pins[i]); | ||
3383 | } | 3395 | } |
3384 | return nums; | 3396 | return nums; |
3385 | } | 3397 | } |
@@ -3395,19 +3407,19 @@ static void cx_auto_parse_output(struct hda_codec *codec) | |||
3395 | rest = fill_cx_auto_dacs(codec, dacs); | 3407 | rest = fill_cx_auto_dacs(codec, dacs); |
3396 | /* parse all analog output pins */ | 3408 | /* parse all analog output pins */ |
3397 | nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs, | 3409 | nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs, |
3398 | dacs, &rest, spec->dac_info, | 3410 | dacs, &rest, spec->dac_info, 0, |
3399 | AUTO_PIN_LINE_OUT); | 3411 | AUTO_PIN_LINE_OUT); |
3400 | nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs, | 3412 | nums = fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs, |
3401 | dacs, &rest, spec->dac_info + nums, | 3413 | dacs, &rest, spec->dac_info, nums, |
3402 | AUTO_PIN_HP_OUT); | 3414 | AUTO_PIN_HP_OUT); |
3403 | nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs, | 3415 | nums = fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs, |
3404 | dacs, &rest, spec->dac_info + nums, | 3416 | dacs, &rest, spec->dac_info, nums, |
3405 | AUTO_PIN_SPEAKER_OUT); | 3417 | AUTO_PIN_SPEAKER_OUT); |
3406 | spec->dac_info_filled = nums; | 3418 | spec->dac_info_filled = nums; |
3407 | /* fill multiout struct */ | 3419 | /* fill multiout struct */ |
3408 | for (i = 0; i < nums; i++) { | 3420 | for (i = 0; i < nums; i++) { |
3409 | hda_nid_t dac = spec->dac_info[i].dac; | 3421 | hda_nid_t dac = spec->dac_info[i].dac; |
3410 | if (!dac) | 3422 | if (!dac || (dac & DAC_SLAVE_FLAG)) |
3411 | continue; | 3423 | continue; |
3412 | switch (spec->dac_info[i].type) { | 3424 | switch (spec->dac_info[i].type) { |
3413 | case AUTO_PIN_LINE_OUT: | 3425 | case AUTO_PIN_LINE_OUT: |
@@ -3862,7 +3874,7 @@ static void cx_auto_parse_input(struct hda_codec *codec) | |||
3862 | } | 3874 | } |
3863 | if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items) | 3875 | if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items) |
3864 | cx_auto_check_auto_mic(codec); | 3876 | cx_auto_check_auto_mic(codec); |
3865 | if (imux->num_items > 1 && !spec->auto_mic) { | 3877 | if (imux->num_items > 1) { |
3866 | for (i = 1; i < imux->num_items; i++) { | 3878 | for (i = 1; i < imux->num_items; i++) { |
3867 | if (spec->imux_info[i].adc != spec->imux_info[0].adc) { | 3879 | if (spec->imux_info[i].adc != spec->imux_info[0].adc) { |
3868 | spec->adc_switching = 1; | 3880 | spec->adc_switching = 1; |
@@ -4035,6 +4047,8 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
4035 | nid = spec->dac_info[i].dac; | 4047 | nid = spec->dac_info[i].dac; |
4036 | if (!nid) | 4048 | if (!nid) |
4037 | nid = spec->multiout.dac_nids[0]; | 4049 | nid = spec->multiout.dac_nids[0]; |
4050 | else if (nid & DAC_SLAVE_FLAG) | ||
4051 | nid &= ~DAC_SLAVE_FLAG; | ||
4038 | select_connection(codec, spec->dac_info[i].pin, nid); | 4052 | select_connection(codec, spec->dac_info[i].pin, nid); |
4039 | } | 4053 | } |
4040 | if (spec->auto_mute) { | 4054 | if (spec->auto_mute) { |
@@ -4167,9 +4181,11 @@ static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac, | |||
4167 | hda_nid_t pin, const char *name, int idx) | 4181 | hda_nid_t pin, const char *name, int idx) |
4168 | { | 4182 | { |
4169 | unsigned int caps; | 4183 | unsigned int caps; |
4170 | caps = query_amp_caps(codec, dac, HDA_OUTPUT); | 4184 | if (dac && !(dac & DAC_SLAVE_FLAG)) { |
4171 | if (caps & AC_AMPCAP_NUM_STEPS) | 4185 | caps = query_amp_caps(codec, dac, HDA_OUTPUT); |
4172 | return cx_auto_add_pb_volume(codec, dac, name, idx); | 4186 | if (caps & AC_AMPCAP_NUM_STEPS) |
4187 | return cx_auto_add_pb_volume(codec, dac, name, idx); | ||
4188 | } | ||
4173 | caps = query_amp_caps(codec, pin, HDA_OUTPUT); | 4189 | caps = query_amp_caps(codec, pin, HDA_OUTPUT); |
4174 | if (caps & AC_AMPCAP_NUM_STEPS) | 4190 | if (caps & AC_AMPCAP_NUM_STEPS) |
4175 | return cx_auto_add_pb_volume(codec, pin, name, idx); | 4191 | return cx_auto_add_pb_volume(codec, pin, name, idx); |
@@ -4191,8 +4207,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) | |||
4191 | for (i = 0; i < spec->dac_info_filled; i++) { | 4207 | for (i = 0; i < spec->dac_info_filled; i++) { |
4192 | const char *label; | 4208 | const char *label; |
4193 | int idx, type; | 4209 | int idx, type; |
4194 | if (!spec->dac_info[i].dac) | 4210 | hda_nid_t dac = spec->dac_info[i].dac; |
4195 | continue; | ||
4196 | type = spec->dac_info[i].type; | 4211 | type = spec->dac_info[i].type; |
4197 | if (type == AUTO_PIN_LINE_OUT) | 4212 | if (type == AUTO_PIN_LINE_OUT) |
4198 | type = spec->autocfg.line_out_type; | 4213 | type = spec->autocfg.line_out_type; |
@@ -4211,7 +4226,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) | |||
4211 | idx = num_spk++; | 4226 | idx = num_spk++; |
4212 | break; | 4227 | break; |
4213 | } | 4228 | } |
4214 | err = try_add_pb_volume(codec, spec->dac_info[i].dac, | 4229 | err = try_add_pb_volume(codec, dac, |
4215 | spec->dac_info[i].pin, | 4230 | spec->dac_info[i].pin, |
4216 | label, idx); | 4231 | label, idx); |
4217 | if (err < 0) | 4232 | if (err < 0) |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9a1aa09f47fe..0503c999e7d3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -168,7 +168,7 @@ struct alc_spec { | |||
168 | unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */ | 168 | unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */ |
169 | unsigned int automute:1; /* HP automute enabled */ | 169 | unsigned int automute:1; /* HP automute enabled */ |
170 | unsigned int detect_line:1; /* Line-out detection enabled */ | 170 | unsigned int detect_line:1; /* Line-out detection enabled */ |
171 | unsigned int automute_lines:1; /* automute line-out as well */ | 171 | unsigned int automute_lines:1; /* automute line-out as well; NOP when automute_hp_lo isn't set */ |
172 | unsigned int automute_hp_lo:1; /* both HP and LO available */ | 172 | unsigned int automute_hp_lo:1; /* both HP and LO available */ |
173 | 173 | ||
174 | /* other flags */ | 174 | /* other flags */ |
@@ -551,7 +551,7 @@ static void update_speakers(struct hda_codec *codec) | |||
551 | if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] || | 551 | if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] || |
552 | spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0]) | 552 | spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0]) |
553 | return; | 553 | return; |
554 | if (!spec->automute_lines || !spec->automute) | 554 | if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines)) |
555 | on = 0; | 555 | on = 0; |
556 | else | 556 | else |
557 | on = spec->jack_present; | 557 | on = spec->jack_present; |
@@ -565,11 +565,11 @@ static void alc_hp_automute(struct hda_codec *codec) | |||
565 | { | 565 | { |
566 | struct alc_spec *spec = codec->spec; | 566 | struct alc_spec *spec = codec->spec; |
567 | 567 | ||
568 | if (!spec->automute) | ||
569 | return; | ||
570 | spec->jack_present = | 568 | spec->jack_present = |
571 | detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins), | 569 | detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins), |
572 | spec->autocfg.hp_pins); | 570 | spec->autocfg.hp_pins); |
571 | if (!spec->automute) | ||
572 | return; | ||
573 | update_speakers(codec); | 573 | update_speakers(codec); |
574 | } | 574 | } |
575 | 575 | ||
@@ -578,11 +578,11 @@ static void alc_line_automute(struct hda_codec *codec) | |||
578 | { | 578 | { |
579 | struct alc_spec *spec = codec->spec; | 579 | struct alc_spec *spec = codec->spec; |
580 | 580 | ||
581 | if (!spec->automute || !spec->detect_line) | ||
582 | return; | ||
583 | spec->line_jack_present = | 581 | spec->line_jack_present = |
584 | detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins), | 582 | detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins), |
585 | spec->autocfg.line_out_pins); | 583 | spec->autocfg.line_out_pins); |
584 | if (!spec->automute || !spec->detect_line) | ||
585 | return; | ||
586 | update_speakers(codec); | 586 | update_speakers(codec); |
587 | } | 587 | } |
588 | 588 | ||
@@ -803,7 +803,7 @@ static int alc_automute_mode_get(struct snd_kcontrol *kcontrol, | |||
803 | unsigned int val; | 803 | unsigned int val; |
804 | if (!spec->automute) | 804 | if (!spec->automute) |
805 | val = 0; | 805 | val = 0; |
806 | else if (!spec->automute_lines) | 806 | else if (!spec->automute_hp_lo || !spec->automute_lines) |
807 | val = 1; | 807 | val = 1; |
808 | else | 808 | else |
809 | val = 2; | 809 | val = 2; |
@@ -824,7 +824,8 @@ static int alc_automute_mode_put(struct snd_kcontrol *kcontrol, | |||
824 | spec->automute = 0; | 824 | spec->automute = 0; |
825 | break; | 825 | break; |
826 | case 1: | 826 | case 1: |
827 | if (spec->automute && !spec->automute_lines) | 827 | if (spec->automute && |
828 | (!spec->automute_hp_lo || !spec->automute_lines)) | ||
828 | return 0; | 829 | return 0; |
829 | spec->automute = 1; | 830 | spec->automute = 1; |
830 | spec->automute_lines = 0; | 831 | spec->automute_lines = 0; |
@@ -1784,6 +1785,7 @@ static const char * const alc_slave_vols[] = { | |||
1784 | "Speaker Playback Volume", | 1785 | "Speaker Playback Volume", |
1785 | "Mono Playback Volume", | 1786 | "Mono Playback Volume", |
1786 | "Line-Out Playback Volume", | 1787 | "Line-Out Playback Volume", |
1788 | "PCM Playback Volume", | ||
1787 | NULL, | 1789 | NULL, |
1788 | }; | 1790 | }; |
1789 | 1791 | ||
@@ -1798,6 +1800,7 @@ static const char * const alc_slave_sws[] = { | |||
1798 | "Mono Playback Switch", | 1800 | "Mono Playback Switch", |
1799 | "IEC958 Playback Switch", | 1801 | "IEC958 Playback Switch", |
1800 | "Line-Out Playback Switch", | 1802 | "Line-Out Playback Switch", |
1803 | "PCM Playback Switch", | ||
1801 | NULL, | 1804 | NULL, |
1802 | }; | 1805 | }; |
1803 | 1806 | ||
@@ -3081,16 +3084,22 @@ static void alc_auto_init_multi_out(struct hda_codec *codec) | |||
3081 | static void alc_auto_init_extra_out(struct hda_codec *codec) | 3084 | static void alc_auto_init_extra_out(struct hda_codec *codec) |
3082 | { | 3085 | { |
3083 | struct alc_spec *spec = codec->spec; | 3086 | struct alc_spec *spec = codec->spec; |
3084 | hda_nid_t pin; | 3087 | hda_nid_t pin, dac; |
3085 | 3088 | ||
3086 | pin = spec->autocfg.hp_pins[0]; | 3089 | pin = spec->autocfg.hp_pins[0]; |
3087 | if (pin) | 3090 | if (pin) { |
3088 | alc_auto_set_output_and_unmute(codec, pin, PIN_HP, | 3091 | dac = spec->multiout.hp_nid; |
3089 | spec->multiout.hp_nid); | 3092 | if (!dac) |
3093 | dac = spec->multiout.dac_nids[0]; | ||
3094 | alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); | ||
3095 | } | ||
3090 | pin = spec->autocfg.speaker_pins[0]; | 3096 | pin = spec->autocfg.speaker_pins[0]; |
3091 | if (pin) | 3097 | if (pin) { |
3092 | alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, | 3098 | dac = spec->multiout.extra_out_nid[0]; |
3093 | spec->multiout.extra_out_nid[0]); | 3099 | if (!dac) |
3100 | dac = spec->multiout.dac_nids[0]; | ||
3101 | alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); | ||
3102 | } | ||
3094 | } | 3103 | } |
3095 | 3104 | ||
3096 | /* | 3105 | /* |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index aa376b59c006..1b7c11432aa7 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -673,6 +673,7 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, | |||
673 | return 0; | 673 | return 0; |
674 | } | 674 | } |
675 | 675 | ||
676 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
676 | static int stac_vrefout_set(struct hda_codec *codec, | 677 | static int stac_vrefout_set(struct hda_codec *codec, |
677 | hda_nid_t nid, unsigned int new_vref) | 678 | hda_nid_t nid, unsigned int new_vref) |
678 | { | 679 | { |
@@ -696,6 +697,7 @@ static int stac_vrefout_set(struct hda_codec *codec, | |||
696 | 697 | ||
697 | return 1; | 698 | return 1; |
698 | } | 699 | } |
700 | #endif | ||
699 | 701 | ||
700 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, | 702 | static unsigned int stac92xx_vref_set(struct hda_codec *codec, |
701 | hda_nid_t nid, unsigned int new_vref) | 703 | hda_nid_t nid, unsigned int new_vref) |
@@ -6571,6 +6573,7 @@ static const struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
6571 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, | 6573 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, |
6572 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, | 6574 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, |
6573 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, | 6575 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, |
6576 | { .id = 0x111d76df, .name = "92HD93BXX", .patch = patch_stac92hd83xxx}, | ||
6574 | { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx}, | 6577 | { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx}, |
6575 | { .id = 0x111d76e3, .name = "92HD98BXX", .patch = patch_stac92hd83xxx}, | 6578 | { .id = 0x111d76e3, .name = "92HD98BXX", .patch = patch_stac92hd83xxx}, |
6576 | { .id = 0x111d76e5, .name = "92HD99BXX", .patch = patch_stac92hd83xxx}, | 6579 | { .id = 0x111d76e5, .name = "92HD99BXX", .patch = patch_stac92hd83xxx}, |
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c index d6651c033cb7..5956584ea3a4 100644 --- a/sound/soc/blackfin/bf5xx-ad193x.c +++ b/sound/soc/blackfin/bf5xx-ad193x.c | |||
@@ -56,7 +56,7 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | |||
56 | 56 | ||
57 | switch (params_rate(params)) { | 57 | switch (params_rate(params)) { |
58 | case 48000: | 58 | case 48000: |
59 | clk = 12288000; | 59 | clk = 24576000; |
60 | break; | 60 | break; |
61 | } | 61 | } |
62 | 62 | ||
@@ -103,7 +103,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { | |||
103 | .cpu_dai_name = "bfin-tdm.0", | 103 | .cpu_dai_name = "bfin-tdm.0", |
104 | .codec_dai_name ="ad193x-hifi", | 104 | .codec_dai_name ="ad193x-hifi", |
105 | .platform_name = "bfin-tdm-pcm-audio", | 105 | .platform_name = "bfin-tdm-pcm-audio", |
106 | .codec_name = "ad193x.5", | 106 | .codec_name = "spi0.5", |
107 | .ops = &bf5xx_ad193x_ops, | 107 | .ops = &bf5xx_ad193x_ops, |
108 | }, | 108 | }, |
109 | { | 109 | { |
@@ -112,7 +112,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { | |||
112 | .cpu_dai_name = "bfin-tdm.1", | 112 | .cpu_dai_name = "bfin-tdm.1", |
113 | .codec_dai_name ="ad193x-hifi", | 113 | .codec_dai_name ="ad193x-hifi", |
114 | .platform_name = "bfin-tdm-pcm-audio", | 114 | .platform_name = "bfin-tdm-pcm-audio", |
115 | .codec_name = "ad193x.5", | 115 | .codec_name = "spi0.5", |
116 | .ops = &bf5xx_ad193x_ops, | 116 | .ops = &bf5xx_ad193x_ops, |
117 | }, | 117 | }, |
118 | }; | 118 | }; |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 2374ca5ffe68..eedb6f5e5823 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -27,11 +27,6 @@ struct ad193x_priv { | |||
27 | int sysclk; | 27 | int sysclk; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | /* ad193x register cache & default register settings */ | ||
31 | static const u8 ad193x_reg[AD193X_NUM_REGS] = { | ||
32 | 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, | ||
33 | }; | ||
34 | |||
35 | /* | 30 | /* |
36 | * AD193X volume/mute/de-emphasis etc. controls | 31 | * AD193X volume/mute/de-emphasis etc. controls |
37 | */ | 32 | */ |
@@ -307,7 +302,8 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
307 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg); | 302 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg); |
308 | 303 | ||
309 | reg = snd_soc_read(codec, AD193X_DAC_CTRL2); | 304 | reg = snd_soc_read(codec, AD193X_DAC_CTRL2); |
310 | reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len; | 305 | reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) |
306 | | (word_len << AD193X_DAC_WORD_LEN_SHFT); | ||
311 | snd_soc_write(codec, AD193X_DAC_CTRL2, reg); | 307 | snd_soc_write(codec, AD193X_DAC_CTRL2, reg); |
312 | 308 | ||
313 | reg = snd_soc_read(codec, AD193X_ADC_CTRL1); | 309 | reg = snd_soc_read(codec, AD193X_ADC_CTRL1); |
@@ -389,9 +385,6 @@ static int ad193x_probe(struct snd_soc_codec *codec) | |||
389 | 385 | ||
390 | static struct snd_soc_codec_driver soc_codec_dev_ad193x = { | 386 | static struct snd_soc_codec_driver soc_codec_dev_ad193x = { |
391 | .probe = ad193x_probe, | 387 | .probe = ad193x_probe, |
392 | .reg_cache_default = ad193x_reg, | ||
393 | .reg_cache_size = AD193X_NUM_REGS, | ||
394 | .reg_word_size = sizeof(u16), | ||
395 | }; | 388 | }; |
396 | 389 | ||
397 | #if defined(CONFIG_SPI_MASTER) | 390 | #if defined(CONFIG_SPI_MASTER) |
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 9747b5497877..cccc2e8e5fbd 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h | |||
@@ -34,7 +34,8 @@ | |||
34 | #define AD193X_DAC_LEFT_HIGH (1 << 3) | 34 | #define AD193X_DAC_LEFT_HIGH (1 << 3) |
35 | #define AD193X_DAC_BCLK_INV (1 << 7) | 35 | #define AD193X_DAC_BCLK_INV (1 << 7) |
36 | #define AD193X_DAC_CTRL2 0x804 | 36 | #define AD193X_DAC_CTRL2 0x804 |
37 | #define AD193X_DAC_WORD_LEN_MASK 0xC | 37 | #define AD193X_DAC_WORD_LEN_SHFT 3 |
38 | #define AD193X_DAC_WORD_LEN_MASK 0x18 | ||
38 | #define AD193X_DAC_MASTER_MUTE 1 | 39 | #define AD193X_DAC_MASTER_MUTE 1 |
39 | #define AD193X_DAC_CHNL_MUTE 0x805 | 40 | #define AD193X_DAC_CHNL_MUTE 0x805 |
40 | #define AD193X_DACL1_MUTE 0 | 41 | #define AD193X_DACL1_MUTE 0 |
@@ -63,7 +64,7 @@ | |||
63 | #define AD193X_ADC_CTRL1 0x80f | 64 | #define AD193X_ADC_CTRL1 0x80f |
64 | #define AD193X_ADC_SERFMT_MASK 0x60 | 65 | #define AD193X_ADC_SERFMT_MASK 0x60 |
65 | #define AD193X_ADC_SERFMT_STEREO (0 << 5) | 66 | #define AD193X_ADC_SERFMT_STEREO (0 << 5) |
66 | #define AD193X_ADC_SERFMT_TDM (1 << 2) | 67 | #define AD193X_ADC_SERFMT_TDM (1 << 5) |
67 | #define AD193X_ADC_SERFMT_AUX (2 << 5) | 68 | #define AD193X_ADC_SERFMT_AUX (2 << 5) |
68 | #define AD193X_ADC_WORD_LEN_MASK 0x3 | 69 | #define AD193X_ADC_WORD_LEN_MASK 0x3 |
69 | #define AD193X_ADC_CTRL2 0x810 | 70 | #define AD193X_ADC_CTRL2 0x810 |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 409d89d1f34c..fbd7eb9e61ce 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -857,6 +857,7 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, | |||
857 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); | 857 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); |
858 | if (ret != 0) { | 858 | if (ret != 0) { |
859 | dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); | 859 | dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); |
860 | kfree(sta32x); | ||
860 | return ret; | 861 | return ret; |
861 | } | 862 | } |
862 | 863 | ||
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 38f38fddd190..d0003cc3bcd6 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -778,11 +778,19 @@ static int __devexit wm8750_spi_remove(struct spi_device *spi) | |||
778 | return 0; | 778 | return 0; |
779 | } | 779 | } |
780 | 780 | ||
781 | static const struct spi_device_id wm8750_spi_ids[] = { | ||
782 | { "wm8750", 0 }, | ||
783 | { "wm8987", 0 }, | ||
784 | { }, | ||
785 | }; | ||
786 | MODULE_DEVICE_TABLE(spi, wm8750_spi_ids); | ||
787 | |||
781 | static struct spi_driver wm8750_spi_driver = { | 788 | static struct spi_driver wm8750_spi_driver = { |
782 | .driver = { | 789 | .driver = { |
783 | .name = "wm8750-codec", | 790 | .name = "wm8750-codec", |
784 | .owner = THIS_MODULE, | 791 | .owner = THIS_MODULE, |
785 | }, | 792 | }, |
793 | .id_table = wm8750_spi_ids, | ||
786 | .probe = wm8750_spi_probe, | 794 | .probe = wm8750_spi_probe, |
787 | .remove = __devexit_p(wm8750_spi_remove), | 795 | .remove = __devexit_p(wm8750_spi_remove), |
788 | }; | 796 | }; |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 43e3d760766f..4ad8ebd290e3 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -2046,8 +2046,13 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
2046 | /* power down chip */ | 2046 | /* power down chip */ |
2047 | static int wm8903_remove(struct snd_soc_codec *codec) | 2047 | static int wm8903_remove(struct snd_soc_codec *codec) |
2048 | { | 2048 | { |
2049 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
2050 | |||
2049 | wm8903_free_gpio(codec); | 2051 | wm8903_free_gpio(codec); |
2050 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2052 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2053 | if (wm8903->irq) | ||
2054 | free_irq(wm8903->irq, codec); | ||
2055 | |||
2051 | return 0; | 2056 | return 0; |
2052 | } | 2057 | } |
2053 | 2058 | ||
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 60d740ebeb5b..1725550c293e 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -2221,6 +2221,8 @@ static int sysclk_event(struct snd_soc_dapm_widget *w, | |||
2221 | switch (event) { | 2221 | switch (event) { |
2222 | case SND_SOC_DAPM_PRE_PMU: | 2222 | case SND_SOC_DAPM_PRE_PMU: |
2223 | if (fll) { | 2223 | if (fll) { |
2224 | try_wait_for_completion(&wm8962->fll_lock); | ||
2225 | |||
2224 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, | 2226 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, |
2225 | WM8962_FLL_ENA, WM8962_FLL_ENA); | 2227 | WM8962_FLL_ENA, WM8962_FLL_ENA); |
2226 | if (wm8962->irq) { | 2228 | if (wm8962->irq) { |
@@ -2927,10 +2929,6 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, | |||
2927 | WM8962_BIAS_ENA | 0x180); | 2929 | WM8962_BIAS_ENA | 0x180); |
2928 | 2930 | ||
2929 | msleep(5); | 2931 | msleep(5); |
2930 | |||
2931 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | ||
2932 | WM8962_CLKREG_OVD, | ||
2933 | WM8962_CLKREG_OVD); | ||
2934 | } | 2932 | } |
2935 | 2933 | ||
2936 | /* VMID 2*250k */ | 2934 | /* VMID 2*250k */ |
@@ -3288,6 +3286,8 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
3288 | snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); | 3286 | snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); |
3289 | snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); | 3287 | snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); |
3290 | 3288 | ||
3289 | try_wait_for_completion(&wm8962->fll_lock); | ||
3290 | |||
3291 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, | 3291 | snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, |
3292 | WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | | 3292 | WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | |
3293 | WM8962_FLL_ENA, fll1); | 3293 | WM8962_FLL_ENA, fll1); |
@@ -3868,6 +3868,10 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3868 | */ | 3868 | */ |
3869 | snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0); | 3869 | snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0); |
3870 | 3870 | ||
3871 | /* Ensure we have soft control over all registers */ | ||
3872 | snd_soc_update_bits(codec, WM8962_CLOCKING2, | ||
3873 | WM8962_CLKREG_OVD, WM8962_CLKREG_OVD); | ||
3874 | |||
3871 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); | 3875 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); |
3872 | 3876 | ||
3873 | if (pdata) { | 3877 | if (pdata) { |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 09e680ae88b2..b393f9fac97a 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -2981,6 +2981,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2981 | wm8994->hubs.dcs_readback_mode = 1; | 2981 | wm8994->hubs.dcs_readback_mode = 1; |
2982 | break; | 2982 | break; |
2983 | } | 2983 | } |
2984 | break; | ||
2984 | 2985 | ||
2985 | case WM8958: | 2986 | case WM8958: |
2986 | wm8994->hubs.dcs_readback_mode = 1; | 2987 | wm8994->hubs.dcs_readback_mode = 1; |
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index ab8e9d1aaff0..0cdb9d105671 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -420,7 +420,7 @@ static const char *sidetone_hpf_text[] = { | |||
420 | }; | 420 | }; |
421 | 421 | ||
422 | static const struct soc_enum sidetone_hpf = | 422 | static const struct soc_enum sidetone_hpf = |
423 | SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 6, sidetone_hpf_text); | 423 | SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 7, sidetone_hpf_text); |
424 | 424 | ||
425 | static const char *hpf_mode_text[] = { | 425 | static const char *hpf_mode_text[] = { |
426 | "HiFi", "Custom", "Voice" | 426 | "HiFi", "Custom", "Voice" |
@@ -988,15 +988,10 @@ SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0), | |||
988 | SND_SOC_DAPM_PGA("IN1L PGA", WM8996_POWER_MANAGEMENT_2, 5, 0, NULL, 0), | 988 | SND_SOC_DAPM_PGA("IN1L PGA", WM8996_POWER_MANAGEMENT_2, 5, 0, NULL, 0), |
989 | SND_SOC_DAPM_PGA("IN1R PGA", WM8996_POWER_MANAGEMENT_2, 4, 0, NULL, 0), | 989 | SND_SOC_DAPM_PGA("IN1R PGA", WM8996_POWER_MANAGEMENT_2, 4, 0, NULL, 0), |
990 | 990 | ||
991 | SND_SOC_DAPM_MUX("IN1L Mux", SND_SOC_NOPM, 0, 0, &in1_mux), | 991 | SND_SOC_DAPM_MUX("IN1L Mux", WM8996_POWER_MANAGEMENT_7, 2, 0, &in1_mux), |
992 | SND_SOC_DAPM_MUX("IN1R Mux", SND_SOC_NOPM, 0, 0, &in1_mux), | 992 | SND_SOC_DAPM_MUX("IN1R Mux", WM8996_POWER_MANAGEMENT_7, 3, 0, &in1_mux), |
993 | SND_SOC_DAPM_MUX("IN2L Mux", SND_SOC_NOPM, 0, 0, &in2_mux), | 993 | SND_SOC_DAPM_MUX("IN2L Mux", WM8996_POWER_MANAGEMENT_7, 6, 0, &in2_mux), |
994 | SND_SOC_DAPM_MUX("IN2R Mux", SND_SOC_NOPM, 0, 0, &in2_mux), | 994 | SND_SOC_DAPM_MUX("IN2R Mux", WM8996_POWER_MANAGEMENT_7, 7, 0, &in2_mux), |
995 | |||
996 | SND_SOC_DAPM_PGA("IN1L", WM8996_POWER_MANAGEMENT_7, 2, 0, NULL, 0), | ||
997 | SND_SOC_DAPM_PGA("IN1R", WM8996_POWER_MANAGEMENT_7, 3, 0, NULL, 0), | ||
998 | SND_SOC_DAPM_PGA("IN2L", WM8996_POWER_MANAGEMENT_7, 6, 0, NULL, 0), | ||
999 | SND_SOC_DAPM_PGA("IN2R", WM8996_POWER_MANAGEMENT_7, 7, 0, NULL, 0), | ||
1000 | 995 | ||
1001 | SND_SOC_DAPM_SUPPLY("DMIC2", WM8996_POWER_MANAGEMENT_7, 9, 0, NULL, 0), | 996 | SND_SOC_DAPM_SUPPLY("DMIC2", WM8996_POWER_MANAGEMENT_7, 9, 0, NULL, 0), |
1002 | SND_SOC_DAPM_SUPPLY("DMIC1", WM8996_POWER_MANAGEMENT_7, 8, 0, NULL, 0), | 997 | SND_SOC_DAPM_SUPPLY("DMIC1", WM8996_POWER_MANAGEMENT_7, 8, 0, NULL, 0), |
@@ -1213,6 +1208,16 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1213 | { "AIF2RX0", NULL, "AIFCLK" }, | 1208 | { "AIF2RX0", NULL, "AIFCLK" }, |
1214 | { "AIF2RX1", NULL, "AIFCLK" }, | 1209 | { "AIF2RX1", NULL, "AIFCLK" }, |
1215 | 1210 | ||
1211 | { "AIF1TX0", NULL, "AIFCLK" }, | ||
1212 | { "AIF1TX1", NULL, "AIFCLK" }, | ||
1213 | { "AIF1TX2", NULL, "AIFCLK" }, | ||
1214 | { "AIF1TX3", NULL, "AIFCLK" }, | ||
1215 | { "AIF1TX4", NULL, "AIFCLK" }, | ||
1216 | { "AIF1TX5", NULL, "AIFCLK" }, | ||
1217 | |||
1218 | { "AIF2TX0", NULL, "AIFCLK" }, | ||
1219 | { "AIF2TX1", NULL, "AIFCLK" }, | ||
1220 | |||
1216 | { "DSP1RXL", NULL, "SYSDSPCLK" }, | 1221 | { "DSP1RXL", NULL, "SYSDSPCLK" }, |
1217 | { "DSP1RXR", NULL, "SYSDSPCLK" }, | 1222 | { "DSP1RXR", NULL, "SYSDSPCLK" }, |
1218 | { "DSP2RXL", NULL, "SYSDSPCLK" }, | 1223 | { "DSP2RXL", NULL, "SYSDSPCLK" }, |
@@ -2106,6 +2111,9 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2106 | 2111 | ||
2107 | snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); | 2112 | snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); |
2108 | 2113 | ||
2114 | /* Clear any pending completions (eg, from failed startups) */ | ||
2115 | try_wait_for_completion(&wm8996->fll_lock); | ||
2116 | |||
2109 | snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, | 2117 | snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, |
2110 | WM8996_FLL_ENA, WM8996_FLL_ENA); | 2118 | WM8996_FLL_ENA, WM8996_FLL_ENA); |
2111 | 2119 | ||
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c index 56efa0c1c9a9..099614e16651 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/ep93xx/ep93xx-i2s.c | |||
@@ -385,14 +385,14 @@ static int ep93xx_i2s_probe(struct platform_device *pdev) | |||
385 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 385 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
386 | if (!res) { | 386 | if (!res) { |
387 | err = -ENODEV; | 387 | err = -ENODEV; |
388 | goto fail; | 388 | goto fail_free_info; |
389 | } | 389 | } |
390 | 390 | ||
391 | info->mem = request_mem_region(res->start, resource_size(res), | 391 | info->mem = request_mem_region(res->start, resource_size(res), |
392 | pdev->name); | 392 | pdev->name); |
393 | if (!info->mem) { | 393 | if (!info->mem) { |
394 | err = -EBUSY; | 394 | err = -EBUSY; |
395 | goto fail; | 395 | goto fail_free_info; |
396 | } | 396 | } |
397 | 397 | ||
398 | info->regs = ioremap(info->mem->start, resource_size(info->mem)); | 398 | info->regs = ioremap(info->mem->start, resource_size(info->mem)); |
@@ -435,6 +435,7 @@ fail_unmap_mem: | |||
435 | iounmap(info->regs); | 435 | iounmap(info->regs); |
436 | fail_release_mem: | 436 | fail_release_mem: |
437 | release_mem_region(info->mem->start, resource_size(info->mem)); | 437 | release_mem_region(info->mem->start, resource_size(info->mem)); |
438 | fail_free_info: | ||
438 | kfree(info); | 439 | kfree(info); |
439 | fail: | 440 | fail: |
440 | return err; | 441 | return err; |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 732208c8c0b4..cb50598338e9 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -879,10 +879,12 @@ static struct device_node *find_ssi_node(struct device_node *dma_channel_np) | |||
879 | * assume that device_node pointers are a valid comparison. | 879 | * assume that device_node pointers are a valid comparison. |
880 | */ | 880 | */ |
881 | np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0); | 881 | np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0); |
882 | of_node_put(np); | ||
882 | if (np == dma_channel_np) | 883 | if (np == dma_channel_np) |
883 | return ssi_np; | 884 | return ssi_np; |
884 | 885 | ||
885 | np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0); | 886 | np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0); |
887 | of_node_put(np); | ||
886 | if (np == dma_channel_np) | 888 | if (np == dma_channel_np) |
887 | return ssi_np; | 889 | return ssi_np; |
888 | } | 890 | } |
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index fd0dc46afc34..5c6c2457386e 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -369,7 +369,7 @@ static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { | |||
369 | .pcm_free = &psc_dma_free, | 369 | .pcm_free = &psc_dma_free, |
370 | }; | 370 | }; |
371 | 371 | ||
372 | static int mpc5200_hpcd_probe(struct of_device *op) | 372 | static int mpc5200_hpcd_probe(struct platform_device *op) |
373 | { | 373 | { |
374 | phys_addr_t fifo; | 374 | phys_addr_t fifo; |
375 | struct psc_dma *psc_dma; | 375 | struct psc_dma *psc_dma; |
@@ -487,7 +487,7 @@ out_unmap: | |||
487 | return ret; | 487 | return ret; |
488 | } | 488 | } |
489 | 489 | ||
490 | static int mpc5200_hpcd_remove(struct of_device *op) | 490 | static int mpc5200_hpcd_remove(struct platform_device *op) |
491 | { | 491 | { |
492 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); | 492 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); |
493 | 493 | ||
@@ -519,7 +519,7 @@ MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); | |||
519 | static struct platform_driver mpc5200_hpcd_of_driver = { | 519 | static struct platform_driver mpc5200_hpcd_of_driver = { |
520 | .probe = mpc5200_hpcd_probe, | 520 | .probe = mpc5200_hpcd_probe, |
521 | .remove = mpc5200_hpcd_remove, | 521 | .remove = mpc5200_hpcd_remove, |
522 | .dev = { | 522 | .driver = { |
523 | .owner = THIS_MODULE, | 523 | .owner = THIS_MODULE, |
524 | .name = "mpc5200-pcm-audio", | 524 | .name = "mpc5200-pcm-audio", |
525 | .of_match_table = mpc5200_hpcd_match, | 525 | .of_match_table = mpc5200_hpcd_match, |
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index a19297959587..358f0baaf71b 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -345,8 +345,10 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
345 | } | 345 | } |
346 | 346 | ||
347 | machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); | 347 | machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); |
348 | if (!machine_data) | 348 | if (!machine_data) { |
349 | return -ENOMEM; | 349 | ret = -ENOMEM; |
350 | goto error_alloc; | ||
351 | } | ||
350 | 352 | ||
351 | machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); | 353 | machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); |
352 | machine_data->dai[0].ops = &mpc8610_hpcd_ops; | 354 | machine_data->dai[0].ops = &mpc8610_hpcd_ops; |
@@ -494,7 +496,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
494 | ret = platform_device_add(sound_device); | 496 | ret = platform_device_add(sound_device); |
495 | if (ret) { | 497 | if (ret) { |
496 | dev_err(&pdev->dev, "platform device add failed\n"); | 498 | dev_err(&pdev->dev, "platform device add failed\n"); |
497 | goto error; | 499 | goto error_sound; |
498 | } | 500 | } |
499 | dev_set_drvdata(&pdev->dev, sound_device); | 501 | dev_set_drvdata(&pdev->dev, sound_device); |
500 | 502 | ||
@@ -502,14 +504,12 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
502 | 504 | ||
503 | return 0; | 505 | return 0; |
504 | 506 | ||
507 | error_sound: | ||
508 | platform_device_unregister(sound_device); | ||
505 | error: | 509 | error: |
506 | of_node_put(codec_np); | ||
507 | |||
508 | if (sound_device) | ||
509 | platform_device_unregister(sound_device); | ||
510 | |||
511 | kfree(machine_data); | 510 | kfree(machine_data); |
512 | 511 | error_alloc: | |
512 | of_node_put(codec_np); | ||
513 | return ret; | 513 | return ret; |
514 | } | 514 | } |
515 | 515 | ||
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 8fa4d5f8eda1..fcb862eb0c73 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c | |||
@@ -297,8 +297,10 @@ static int get_dma_channel(struct device_node *ssi_np, | |||
297 | * dai->platform name should already point to an allocated buffer. | 297 | * dai->platform name should already point to an allocated buffer. |
298 | */ | 298 | */ |
299 | ret = of_address_to_resource(dma_channel_np, 0, &res); | 299 | ret = of_address_to_resource(dma_channel_np, 0, &res); |
300 | if (ret) | 300 | if (ret) { |
301 | of_node_put(dma_channel_np); | ||
301 | return ret; | 302 | return ret; |
303 | } | ||
302 | snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", | 304 | snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", |
303 | (unsigned long long) res.start, dma_channel_np->name); | 305 | (unsigned long long) res.start, dma_channel_np->name); |
304 | 306 | ||
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c index 309c59e6fb6c..7945625e0e08 100644 --- a/sound/soc/imx/imx-pcm-fiq.c +++ b/sound/soc/imx/imx-pcm-fiq.c | |||
@@ -240,7 +240,6 @@ static int ssi_irq = 0; | |||
240 | 240 | ||
241 | static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) | 241 | static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) |
242 | { | 242 | { |
243 | struct snd_card *card = rtd->card->snd_card; | ||
244 | struct snd_soc_dai *dai = rtd->cpu_dai; | 243 | struct snd_soc_dai *dai = rtd->cpu_dai; |
245 | struct snd_pcm *pcm = rtd->pcm; | 244 | struct snd_pcm *pcm = rtd->pcm; |
246 | int ret; | 245 | int ret; |
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index a33fc51f363b..d0bcf3fcea01 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c | |||
@@ -424,7 +424,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) | |||
424 | if (!priv->mem) { | 424 | if (!priv->mem) { |
425 | dev_err(&pdev->dev, "request_mem_region failed\n"); | 425 | dev_err(&pdev->dev, "request_mem_region failed\n"); |
426 | err = -EBUSY; | 426 | err = -EBUSY; |
427 | goto error; | 427 | goto err_alloc; |
428 | } | 428 | } |
429 | 429 | ||
430 | priv->io = ioremap(priv->mem->start, SZ_16K); | 430 | priv->io = ioremap(priv->mem->start, SZ_16K); |
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 30fe0d0efe1c..0aa475f92efa 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c | |||
@@ -514,7 +514,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) | |||
514 | } | 514 | } |
515 | 515 | ||
516 | /* Set codec bias level */ | 516 | /* Set codec bias level */ |
517 | ams_delta_set_bias_level(card, SND_SOC_BIAS_STANDBY); | 517 | ams_delta_set_bias_level(card, dapm, SND_SOC_BIAS_STANDBY); |
518 | 518 | ||
519 | /* Add hook switch - can be used to control the codec from userspace | 519 | /* Add hook switch - can be used to control the codec from userspace |
520 | * even if line discipline fails */ | 520 | * even if line discipline fails */ |
@@ -649,7 +649,9 @@ static void __exit ams_delta_module_exit(void) | |||
649 | ams_delta_hook_switch_gpios); | 649 | ams_delta_hook_switch_gpios); |
650 | 650 | ||
651 | /* Keep modem power on */ | 651 | /* Keep modem power on */ |
652 | ams_delta_set_bias_level(&ams_delta_audio_card, SND_SOC_BIAS_STANDBY); | 652 | ams_delta_set_bias_level(&ams_delta_audio_card, |
653 | &ams_delta_audio_card.rtd[0].codec->dapm, | ||
654 | SND_SOC_BIAS_STANDBY); | ||
653 | 655 | ||
654 | platform_device_unregister(cx20442_platform_device); | 656 | platform_device_unregister(cx20442_platform_device); |
655 | platform_device_unregister(ams_delta_audio_platform_device); | 657 | platform_device_unregister(ams_delta_audio_platform_device); |
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 83d213bfd3d1..62e292f49313 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
@@ -402,6 +402,6 @@ static void __exit n810_soc_exit(void) | |||
402 | module_init(n810_soc_init); | 402 | module_init(n810_soc_init); |
403 | module_exit(n810_soc_exit); | 403 | module_exit(n810_soc_exit); |
404 | 404 | ||
405 | MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>"); | 405 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>"); |
406 | MODULE_DESCRIPTION("ALSA SoC Nokia N810"); | 406 | MODULE_DESCRIPTION("ALSA SoC Nokia N810"); |
407 | MODULE_LICENSE("GPL"); | 407 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 07b772357244..ebcc2d4d2b18 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> |
7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> | 7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -780,6 +780,6 @@ static void __exit snd_omap_mcbsp_exit(void) | |||
780 | } | 780 | } |
781 | module_exit(snd_omap_mcbsp_exit); | 781 | module_exit(snd_omap_mcbsp_exit); |
782 | 782 | ||
783 | MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>"); | 783 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>"); |
784 | MODULE_DESCRIPTION("OMAP I2S SoC Interface"); | 784 | MODULE_DESCRIPTION("OMAP I2S SoC Interface"); |
785 | MODULE_LICENSE("GPL"); | 785 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 9a7dedd6f5a9..65cde9d3807b 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> |
7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> | 7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index b2f5751edae3..9b5c88ac35b9 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> |
7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> | 7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -436,6 +436,6 @@ static void __exit snd_omap_pcm_exit(void) | |||
436 | } | 436 | } |
437 | module_exit(snd_omap_pcm_exit); | 437 | module_exit(snd_omap_pcm_exit); |
438 | 438 | ||
439 | MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>"); | 439 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>"); |
440 | MODULE_DESCRIPTION("OMAP PCM DMA module"); | 440 | MODULE_DESCRIPTION("OMAP PCM DMA module"); |
441 | MODULE_LICENSE("GPL"); | 441 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index a0ed1dbb52d6..f95fe3064172 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 Nokia Corporation | 4 | * Copyright (C) 2008 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Jarkko Nikula <jhnikula@gmail.com> | 6 | * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> |
7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> | 7 | * Peter Ujfalusi <peter.ujfalusi@ti.com> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 0aae998b6540..893300a53bab 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * Contact: Peter Ujfalusi <peter.ujfalusi@ti.com> | 6 | * Contact: Peter Ujfalusi <peter.ujfalusi@ti.com> |
7 | * Eduardo Valentin <eduardo.valentin@nokia.com> | 7 | * Eduardo Valentin <eduardo.valentin@nokia.com> |
8 | * Jarkko Nikula <jhnikula@gmail.com> | 8 | * Jarkko Nikula <jarkko.nikula@bitmer.com> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 11 | * modify it under the terms of the GNU General Public License |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index b99091fc34eb..65f980ef2870 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -185,6 +185,7 @@ config SND_SOC_SPEYSIDE | |||
185 | select SND_SAMSUNG_I2S | 185 | select SND_SAMSUNG_I2S |
186 | select SND_SOC_WM8996 | 186 | select SND_SOC_WM8996 |
187 | select SND_SOC_WM9081 | 187 | select SND_SOC_WM9081 |
188 | select SND_SOC_WM1250_EV1 | ||
188 | 189 | ||
189 | config SND_SOC_SPEYSIDE_WM8962 | 190 | config SND_SOC_SPEYSIDE_WM8962 |
190 | tristate "Audio support for Wolfson Speyside with WM8962" | 191 | tristate "Audio support for Wolfson Speyside with WM8962" |
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 9eb3b12eb72f..8509d3c4366e 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | # S3c24XX Platform Support | 1 | # S3c24XX Platform Support |
2 | snd-soc-s3c24xx-objs := dma.o | 2 | snd-soc-s3c24xx-objs := dma.o |
3 | snd-soc-idma-objs := idma.o | ||
3 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 4 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
4 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 5 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
5 | snd-soc-ac97-objs := ac97.o | 6 | snd-soc-ac97-objs := ac97.o |
@@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o | |||
16 | obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o | 17 | obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o |
17 | obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o | 18 | obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o |
18 | obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o | 19 | obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o |
20 | obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o | ||
19 | 21 | ||
20 | # S3C24XX Machine Support | 22 | # S3C24XX Machine Support |
21 | snd-soc-jive-wm8750-objs := jive_wm8750.o | 23 | snd-soc-jive-wm8750-objs := jive_wm8750.o |
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 241f55d00660..c6c65892294e 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/types.h> | ||
16 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
17 | 18 | ||
18 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c new file mode 100644 index 000000000000..ebde0740ab19 --- /dev/null +++ b/sound/soc/samsung/idma.c | |||
@@ -0,0 +1,453 @@ | |||
1 | /* | ||
2 | * sound/soc/samsung/idma.c | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com | ||
6 | * | ||
7 | * I2S0's Internal DMA driver | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | |||
22 | #include "i2s.h" | ||
23 | #include "idma.h" | ||
24 | #include "dma.h" | ||
25 | #include "i2s-regs.h" | ||
26 | |||
27 | #define ST_RUNNING (1<<0) | ||
28 | #define ST_OPENED (1<<1) | ||
29 | |||
30 | static const struct snd_pcm_hardware idma_hardware = { | ||
31 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
32 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
33 | SNDRV_PCM_INFO_MMAP | | ||
34 | SNDRV_PCM_INFO_MMAP_VALID | | ||
35 | SNDRV_PCM_INFO_PAUSE | | ||
36 | SNDRV_PCM_INFO_RESUME, | ||
37 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
38 | SNDRV_PCM_FMTBIT_U16_LE | | ||
39 | SNDRV_PCM_FMTBIT_S24_LE | | ||
40 | SNDRV_PCM_FMTBIT_U24_LE | | ||
41 | SNDRV_PCM_FMTBIT_U8 | | ||
42 | SNDRV_PCM_FMTBIT_S8, | ||
43 | .channels_min = 2, | ||
44 | .channels_max = 2, | ||
45 | .buffer_bytes_max = MAX_IDMA_BUFFER, | ||
46 | .period_bytes_min = 128, | ||
47 | .period_bytes_max = MAX_IDMA_PERIOD, | ||
48 | .periods_min = 1, | ||
49 | .periods_max = 2, | ||
50 | }; | ||
51 | |||
52 | struct idma_ctrl { | ||
53 | spinlock_t lock; | ||
54 | int state; | ||
55 | dma_addr_t start; | ||
56 | dma_addr_t pos; | ||
57 | dma_addr_t end; | ||
58 | dma_addr_t period; | ||
59 | dma_addr_t periodsz; | ||
60 | void *token; | ||
61 | void (*cb)(void *dt, int bytes_xfer); | ||
62 | }; | ||
63 | |||
64 | static struct idma_info { | ||
65 | spinlock_t lock; | ||
66 | void __iomem *regs; | ||
67 | dma_addr_t lp_tx_addr; | ||
68 | } idma; | ||
69 | |||
70 | static void idma_getpos(dma_addr_t *src) | ||
71 | { | ||
72 | *src = idma.lp_tx_addr + | ||
73 | (readl(idma.regs + I2STRNCNT) & 0xffffff) * 4; | ||
74 | } | ||
75 | |||
76 | static int idma_enqueue(struct snd_pcm_substream *substream) | ||
77 | { | ||
78 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
79 | struct idma_ctrl *prtd = substream->runtime->private_data; | ||
80 | u32 val; | ||
81 | |||
82 | spin_lock(&prtd->lock); | ||
83 | prtd->token = (void *) substream; | ||
84 | spin_unlock(&prtd->lock); | ||
85 | |||
86 | /* Internal DMA Level0 Interrupt Address */ | ||
87 | val = idma.lp_tx_addr + prtd->periodsz; | ||
88 | writel(val, idma.regs + I2SLVL0ADDR); | ||
89 | |||
90 | /* Start address0 of I2S internal DMA operation. */ | ||
91 | val = idma.lp_tx_addr; | ||
92 | writel(val, idma.regs + I2SSTR0); | ||
93 | |||
94 | /* | ||
95 | * Transfer block size for I2S internal DMA. | ||
96 | * Should decide transfer size before start dma operation | ||
97 | */ | ||
98 | val = readl(idma.regs + I2SSIZE); | ||
99 | val &= ~(I2SSIZE_TRNMSK << I2SSIZE_SHIFT); | ||
100 | val |= (((runtime->dma_bytes >> 2) & | ||
101 | I2SSIZE_TRNMSK) << I2SSIZE_SHIFT); | ||
102 | writel(val, idma.regs + I2SSIZE); | ||
103 | |||
104 | val = readl(idma.regs + I2SAHB); | ||
105 | val |= AHB_INTENLVL0; | ||
106 | writel(val, idma.regs + I2SAHB); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void idma_setcallbk(struct snd_pcm_substream *substream, | ||
112 | void (*cb)(void *, int)) | ||
113 | { | ||
114 | struct idma_ctrl *prtd = substream->runtime->private_data; | ||
115 | |||
116 | spin_lock(&prtd->lock); | ||
117 | prtd->cb = cb; | ||
118 | spin_unlock(&prtd->lock); | ||
119 | } | ||
120 | |||
121 | static void idma_control(int op) | ||
122 | { | ||
123 | u32 val = readl(idma.regs + I2SAHB); | ||
124 | |||
125 | spin_lock(&idma.lock); | ||
126 | |||
127 | switch (op) { | ||
128 | case LPAM_DMA_START: | ||
129 | val |= (AHB_INTENLVL0 | AHB_DMAEN); | ||
130 | break; | ||
131 | case LPAM_DMA_STOP: | ||
132 | val &= ~(AHB_INTENLVL0 | AHB_DMAEN); | ||
133 | break; | ||
134 | default: | ||
135 | spin_unlock(&idma.lock); | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | writel(val, idma.regs + I2SAHB); | ||
140 | spin_unlock(&idma.lock); | ||
141 | } | ||
142 | |||
143 | static void idma_done(void *id, int bytes_xfer) | ||
144 | { | ||
145 | struct snd_pcm_substream *substream = id; | ||
146 | struct idma_ctrl *prtd = substream->runtime->private_data; | ||
147 | |||
148 | if (prtd && (prtd->state & ST_RUNNING)) | ||
149 | snd_pcm_period_elapsed(substream); | ||
150 | } | ||
151 | |||
152 | static int idma_hw_params(struct snd_pcm_substream *substream, | ||
153 | struct snd_pcm_hw_params *params) | ||
154 | { | ||
155 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
156 | struct idma_ctrl *prtd = substream->runtime->private_data; | ||
157 | u32 mod = readl(idma.regs + I2SMOD); | ||
158 | u32 ahb = readl(idma.regs + I2SAHB); | ||
159 | |||
160 | ahb |= (AHB_DMARLD | AHB_INTMASK); | ||
161 | mod |= MOD_TXS_IDMA; | ||
162 | writel(ahb, idma.regs + I2SAHB); | ||
163 | writel(mod, idma.regs + I2SMOD); | ||
164 | |||
165 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
166 | runtime->dma_bytes = params_buffer_bytes(params); | ||
167 | |||
168 | prtd->start = prtd->pos = runtime->dma_addr; | ||
169 | prtd->period = params_periods(params); | ||
170 | prtd->periodsz = params_period_bytes(params); | ||
171 | prtd->end = runtime->dma_addr + runtime->dma_bytes; | ||
172 | |||
173 | idma_setcallbk(substream, idma_done); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int idma_hw_free(struct snd_pcm_substream *substream) | ||
179 | { | ||
180 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int idma_prepare(struct snd_pcm_substream *substream) | ||
186 | { | ||
187 | struct idma_ctrl *prtd = substream->runtime->private_data; | ||
188 | |||
189 | prtd->pos = prtd->start; | ||
190 | |||
191 | /* flush the DMA channel */ | ||
192 | idma_control(LPAM_DMA_STOP); | ||
193 | idma_enqueue(substream); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int idma_trigger(struct snd_pcm_substream *substream, int cmd) | ||
199 | { | ||
200 | struct idma_ctrl *prtd = substream->runtime->private_data; | ||
201 | int ret = 0; | ||
202 | |||
203 | spin_lock(&prtd->lock); | ||
204 | |||
205 | switch (cmd) { | ||
206 | case SNDRV_PCM_TRIGGER_RESUME: | ||
207 | case SNDRV_PCM_TRIGGER_START: | ||
208 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
209 | prtd->state |= ST_RUNNING; | ||
210 | idma_control(LPAM_DMA_START); | ||
211 | break; | ||
212 | |||
213 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
214 | case SNDRV_PCM_TRIGGER_STOP: | ||
215 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
216 | prtd->state &= ~ST_RUNNING; | ||
217 | idma_control(LPAM_DMA_STOP); | ||
218 | break; | ||
219 | |||
220 | default: | ||
221 | ret = -EINVAL; | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | spin_unlock(&prtd->lock); | ||
226 | |||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | static snd_pcm_uframes_t | ||
231 | idma_pointer(struct snd_pcm_substream *substream) | ||
232 | { | ||
233 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
234 | struct idma_ctrl *prtd = runtime->private_data; | ||
235 | dma_addr_t src; | ||
236 | unsigned long res; | ||
237 | |||
238 | spin_lock(&prtd->lock); | ||
239 | |||
240 | idma_getpos(&src); | ||
241 | res = src - prtd->start; | ||
242 | |||
243 | spin_unlock(&prtd->lock); | ||
244 | |||
245 | return bytes_to_frames(substream->runtime, res); | ||
246 | } | ||
247 | |||
248 | static int idma_mmap(struct snd_pcm_substream *substream, | ||
249 | struct vm_area_struct *vma) | ||
250 | { | ||
251 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
252 | unsigned long size, offset; | ||
253 | int ret; | ||
254 | |||
255 | /* From snd_pcm_lib_mmap_iomem */ | ||
256 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
257 | vma->vm_flags |= VM_IO; | ||
258 | size = vma->vm_end - vma->vm_start; | ||
259 | offset = vma->vm_pgoff << PAGE_SHIFT; | ||
260 | ret = io_remap_pfn_range(vma, vma->vm_start, | ||
261 | (runtime->dma_addr + offset) >> PAGE_SHIFT, | ||
262 | size, vma->vm_page_prot); | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | static irqreturn_t iis_irq(int irqno, void *dev_id) | ||
268 | { | ||
269 | struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id; | ||
270 | u32 iiscon, iisahb, val, addr; | ||
271 | |||
272 | iisahb = readl(idma.regs + I2SAHB); | ||
273 | iiscon = readl(idma.regs + I2SCON); | ||
274 | |||
275 | val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0; | ||
276 | |||
277 | if (val) { | ||
278 | iisahb |= val; | ||
279 | writel(iisahb, idma.regs + I2SAHB); | ||
280 | |||
281 | addr = readl(idma.regs + I2SLVL0ADDR) - idma.lp_tx_addr; | ||
282 | addr += prtd->periodsz; | ||
283 | addr %= (prtd->end - prtd->start); | ||
284 | addr += idma.lp_tx_addr; | ||
285 | |||
286 | writel(addr, idma.regs + I2SLVL0ADDR); | ||
287 | |||
288 | if (prtd->cb) | ||
289 | prtd->cb(prtd->token, prtd->period); | ||
290 | } | ||
291 | |||
292 | return IRQ_HANDLED; | ||
293 | } | ||
294 | |||
295 | static int idma_open(struct snd_pcm_substream *substream) | ||
296 | { | ||
297 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
298 | struct idma_ctrl *prtd; | ||
299 | int ret; | ||
300 | |||
301 | snd_soc_set_runtime_hwparams(substream, &idma_hardware); | ||
302 | |||
303 | prtd = kzalloc(sizeof(struct idma_ctrl), GFP_KERNEL); | ||
304 | if (prtd == NULL) | ||
305 | return -ENOMEM; | ||
306 | |||
307 | ret = request_irq(IRQ_I2S0, iis_irq, 0, "i2s", prtd); | ||
308 | if (ret < 0) { | ||
309 | pr_err("fail to claim i2s irq , ret = %d\n", ret); | ||
310 | kfree(prtd); | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | spin_lock_init(&prtd->lock); | ||
315 | |||
316 | runtime->private_data = prtd; | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int idma_close(struct snd_pcm_substream *substream) | ||
322 | { | ||
323 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
324 | struct idma_ctrl *prtd = runtime->private_data; | ||
325 | |||
326 | free_irq(IRQ_I2S0, prtd); | ||
327 | |||
328 | if (!prtd) | ||
329 | pr_err("idma_close called with prtd == NULL\n"); | ||
330 | |||
331 | kfree(prtd); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static struct snd_pcm_ops idma_ops = { | ||
337 | .open = idma_open, | ||
338 | .close = idma_close, | ||
339 | .ioctl = snd_pcm_lib_ioctl, | ||
340 | .trigger = idma_trigger, | ||
341 | .pointer = idma_pointer, | ||
342 | .mmap = idma_mmap, | ||
343 | .hw_params = idma_hw_params, | ||
344 | .hw_free = idma_hw_free, | ||
345 | .prepare = idma_prepare, | ||
346 | }; | ||
347 | |||
348 | static void idma_free(struct snd_pcm *pcm) | ||
349 | { | ||
350 | struct snd_pcm_substream *substream; | ||
351 | struct snd_dma_buffer *buf; | ||
352 | |||
353 | substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | ||
354 | if (!substream) | ||
355 | return; | ||
356 | |||
357 | buf = &substream->dma_buffer; | ||
358 | if (!buf->area) | ||
359 | return; | ||
360 | |||
361 | iounmap(buf->area); | ||
362 | |||
363 | buf->area = NULL; | ||
364 | buf->addr = 0; | ||
365 | } | ||
366 | |||
367 | static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream) | ||
368 | { | ||
369 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
370 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
371 | |||
372 | buf->dev.dev = pcm->card->dev; | ||
373 | buf->private_data = NULL; | ||
374 | |||
375 | /* Assign PCM buffer pointers */ | ||
376 | buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS; | ||
377 | buf->addr = idma.lp_tx_addr; | ||
378 | buf->bytes = idma_hardware.buffer_bytes_max; | ||
379 | buf->area = (unsigned char *)ioremap(buf->addr, buf->bytes); | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static u64 idma_mask = DMA_BIT_MASK(32); | ||
385 | |||
386 | static int idma_new(struct snd_soc_pcm_runtime *rtd) | ||
387 | { | ||
388 | struct snd_card *card = rtd->card->snd_card; | ||
389 | struct snd_soc_dai *dai = rtd->cpu_dai; | ||
390 | struct snd_pcm *pcm = rtd->pcm; | ||
391 | int ret = 0; | ||
392 | |||
393 | if (!card->dev->dma_mask) | ||
394 | card->dev->dma_mask = &idma_mask; | ||
395 | if (!card->dev->coherent_dma_mask) | ||
396 | card->dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
397 | |||
398 | if (dai->driver->playback.channels_min) | ||
399 | ret = preallocate_idma_buffer(pcm, | ||
400 | SNDRV_PCM_STREAM_PLAYBACK); | ||
401 | |||
402 | return ret; | ||
403 | } | ||
404 | |||
405 | void idma_reg_addr_init(void *regs, dma_addr_t addr) | ||
406 | { | ||
407 | spin_lock_init(&idma.lock); | ||
408 | idma.regs = regs; | ||
409 | idma.lp_tx_addr = addr; | ||
410 | } | ||
411 | |||
412 | struct snd_soc_platform_driver asoc_idma_platform = { | ||
413 | .ops = &idma_ops, | ||
414 | .pcm_new = idma_new, | ||
415 | .pcm_free = idma_free, | ||
416 | }; | ||
417 | |||
418 | static int __devinit asoc_idma_platform_probe(struct platform_device *pdev) | ||
419 | { | ||
420 | return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform); | ||
421 | } | ||
422 | |||
423 | static int __devexit asoc_idma_platform_remove(struct platform_device *pdev) | ||
424 | { | ||
425 | snd_soc_unregister_platform(&pdev->dev); | ||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | static struct platform_driver asoc_idma_driver = { | ||
430 | .driver = { | ||
431 | .name = "samsung-idma", | ||
432 | .owner = THIS_MODULE, | ||
433 | }, | ||
434 | |||
435 | .probe = asoc_idma_platform_probe, | ||
436 | .remove = __devexit_p(asoc_idma_platform_remove), | ||
437 | }; | ||
438 | |||
439 | static int __init asoc_idma_init(void) | ||
440 | { | ||
441 | return platform_driver_register(&asoc_idma_driver); | ||
442 | } | ||
443 | module_init(asoc_idma_init); | ||
444 | |||
445 | static void __exit asoc_idma_exit(void) | ||
446 | { | ||
447 | platform_driver_unregister(&asoc_idma_driver); | ||
448 | } | ||
449 | module_exit(asoc_idma_exit); | ||
450 | |||
451 | MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>"); | ||
452 | MODULE_DESCRIPTION("Samsung ASoC IDMA Driver"); | ||
453 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h new file mode 100644 index 000000000000..48273216166e --- /dev/null +++ b/sound/soc/samsung/idma.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * sound/soc/samsung/idma.h | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd | ||
5 | * http://www.samsung.com | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef __SND_SOC_SAMSUNG_IDMA_H_ | ||
15 | #define __SND_SOC_SAMSUNG_IDMA_H_ | ||
16 | |||
17 | extern void idma_reg_addr_init(void *regs, dma_addr_t addr); | ||
18 | |||
19 | /* dma_state */ | ||
20 | #define LPAM_DMA_STOP 0 | ||
21 | #define LPAM_DMA_START 1 | ||
22 | |||
23 | #define MAX_IDMA_PERIOD (128 * 1024) | ||
24 | #define MAX_IDMA_BUFFER (160 * 1024) | ||
25 | |||
26 | #endif /* __SND_SOC_SAMSUNG_IDMA_H_ */ | ||
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index 3b53ad54bc33..14eb6ea69e7c 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c | |||
@@ -131,7 +131,7 @@ static struct snd_soc_dai_link jive_dai = { | |||
131 | .cpu_dai_name = "s3c2412-i2s", | 131 | .cpu_dai_name = "s3c2412-i2s", |
132 | .codec_dai_name = "wm8750-hifi", | 132 | .codec_dai_name = "wm8750-hifi", |
133 | .platform_name = "samsung-audio", | 133 | .platform_name = "samsung-audio", |
134 | .codec_name = "wm8750-codec.0-0x1a", | 134 | .codec_name = "wm8750-codec.0-001a", |
135 | .init = jive_wm8750_init, | 135 | .init = jive_wm8750_init, |
136 | .ops = &jive_ops, | 136 | .ops = &jive_ops, |
137 | }; | 137 | }; |
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 1e574a5d440d..bc8c1676459f 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/types.h> | ||
20 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
21 | 22 | ||
22 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/speyside_wm8962.c index 8ac42bf82090..72535f2daaf2 100644 --- a/sound/soc/samsung/speyside_wm8962.c +++ b/sound/soc/samsung/speyside_wm8962.c | |||
@@ -23,6 +23,9 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card, | |||
23 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 23 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; |
24 | int ret; | 24 | int ret; |
25 | 25 | ||
26 | if (dapm->dev != codec_dai->dev) | ||
27 | return 0; | ||
28 | |||
26 | switch (level) { | 29 | switch (level) { |
27 | case SND_SOC_BIAS_PREPARE: | 30 | case SND_SOC_BIAS_PREPARE: |
28 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | 31 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { |
@@ -37,7 +40,7 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card, | |||
37 | 44100 * 256, | 40 | 44100 * 256, |
38 | SND_SOC_CLOCK_IN); | 41 | SND_SOC_CLOCK_IN); |
39 | if (ret < 0) { | 42 | if (ret < 0) { |
40 | pr_err("Failed to set SYSCLK: %d\n"); | 43 | pr_err("Failed to set SYSCLK: %d\n", ret); |
41 | return ret; | 44 | return ret; |
42 | } | 45 | } |
43 | } | 46 | } |
@@ -57,6 +60,9 @@ static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card, | |||
57 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 60 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; |
58 | int ret; | 61 | int ret; |
59 | 62 | ||
63 | if (dapm->dev != codec_dai->dev) | ||
64 | return 0; | ||
65 | |||
60 | switch (level) { | 66 | switch (level) { |
61 | case SND_SOC_BIAS_STANDBY: | 67 | case SND_SOC_BIAS_STANDBY: |
62 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK, | 68 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK, |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index d9f8aded51f3..20b7f3b003a3 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -203,14 +203,14 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec) | |||
203 | rbnode = rb_entry(node, struct snd_soc_rbtree_node, node); | 203 | rbnode = rb_entry(node, struct snd_soc_rbtree_node, node); |
204 | for (i = 0; i < rbnode->blklen; ++i) { | 204 | for (i = 0; i < rbnode->blklen; ++i) { |
205 | regtmp = rbnode->base_reg + i; | 205 | regtmp = rbnode->base_reg + i; |
206 | WARN_ON(codec->writable_register && | ||
207 | codec->writable_register(codec, regtmp)); | ||
208 | val = snd_soc_rbtree_get_register(rbnode, i); | 206 | val = snd_soc_rbtree_get_register(rbnode, i); |
209 | def = snd_soc_get_cache_val(codec->reg_def_copy, i, | 207 | def = snd_soc_get_cache_val(codec->reg_def_copy, i, |
210 | rbnode->word_size); | 208 | rbnode->word_size); |
211 | if (val == def) | 209 | if (val == def) |
212 | continue; | 210 | continue; |
213 | 211 | ||
212 | WARN_ON(!snd_soc_codec_writable_register(codec, regtmp)); | ||
213 | |||
214 | codec->cache_bypass = 1; | 214 | codec->cache_bypass = 1; |
215 | ret = snd_soc_write(codec, regtmp, val); | 215 | ret = snd_soc_write(codec, regtmp, val); |
216 | codec->cache_bypass = 0; | 216 | codec->cache_bypass = 0; |
@@ -563,8 +563,7 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec) | |||
563 | 563 | ||
564 | lzo_blocks = codec->reg_cache; | 564 | lzo_blocks = codec->reg_cache; |
565 | for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) { | 565 | for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) { |
566 | WARN_ON(codec->writable_register && | 566 | WARN_ON(!snd_soc_codec_writable_register(codec, i)); |
567 | codec->writable_register(codec, i)); | ||
568 | ret = snd_soc_cache_read(codec, i, &val); | 567 | ret = snd_soc_cache_read(codec, i, &val); |
569 | if (ret) | 568 | if (ret) |
570 | return ret; | 569 | return ret; |
@@ -823,8 +822,6 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) | |||
823 | 822 | ||
824 | codec_drv = codec->driver; | 823 | codec_drv = codec->driver; |
825 | for (i = 0; i < codec_drv->reg_cache_size; ++i) { | 824 | for (i = 0; i < codec_drv->reg_cache_size; ++i) { |
826 | WARN_ON(codec->writable_register && | ||
827 | codec->writable_register(codec, i)); | ||
828 | ret = snd_soc_cache_read(codec, i, &val); | 825 | ret = snd_soc_cache_read(codec, i, &val); |
829 | if (ret) | 826 | if (ret) |
830 | return ret; | 827 | return ret; |
@@ -832,6 +829,9 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) | |||
832 | if (snd_soc_get_cache_val(codec->reg_def_copy, | 829 | if (snd_soc_get_cache_val(codec->reg_def_copy, |
833 | i, codec_drv->reg_word_size) == val) | 830 | i, codec_drv->reg_word_size) == val) |
834 | continue; | 831 | continue; |
832 | |||
833 | WARN_ON(!snd_soc_codec_writable_register(codec, i)); | ||
834 | |||
835 | ret = snd_soc_write(codec, i, val); | 835 | ret = snd_soc_write(codec, i, val); |
836 | if (ret) | 836 | if (ret) |
837 | return ret; | 837 | return ret; |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 83ad8ca27490..d2ef014af215 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1633,7 +1633,7 @@ int snd_soc_codec_readable_register(struct snd_soc_codec *codec, | |||
1633 | if (codec->readable_register) | 1633 | if (codec->readable_register) |
1634 | return codec->readable_register(codec, reg); | 1634 | return codec->readable_register(codec, reg); |
1635 | else | 1635 | else |
1636 | return 0; | 1636 | return 1; |
1637 | } | 1637 | } |
1638 | EXPORT_SYMBOL_GPL(snd_soc_codec_readable_register); | 1638 | EXPORT_SYMBOL_GPL(snd_soc_codec_readable_register); |
1639 | 1639 | ||
@@ -1651,7 +1651,7 @@ int snd_soc_codec_writable_register(struct snd_soc_codec *codec, | |||
1651 | if (codec->writable_register) | 1651 | if (codec->writable_register) |
1652 | return codec->writable_register(codec, reg); | 1652 | return codec->writable_register(codec, reg); |
1653 | else | 1653 | else |
1654 | return 0; | 1654 | return 1; |
1655 | } | 1655 | } |
1656 | EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register); | 1656 | EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register); |
1657 | 1657 | ||
@@ -1913,7 +1913,7 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | |||
1913 | 1913 | ||
1914 | if (prefix) { | 1914 | if (prefix) { |
1915 | name_len = strlen(long_name) + strlen(prefix) + 2; | 1915 | name_len = strlen(long_name) + strlen(prefix) + 2; |
1916 | name = kmalloc(name_len, GFP_ATOMIC); | 1916 | name = kmalloc(name_len, GFP_KERNEL); |
1917 | if (!name) | 1917 | if (!name) |
1918 | return NULL; | 1918 | return NULL; |
1919 | 1919 | ||
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7e15914b3633..d67c637557a7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -2763,7 +2763,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | |||
2763 | 2763 | ||
2764 | /** | 2764 | /** |
2765 | * snd_soc_dapm_free - free dapm resources | 2765 | * snd_soc_dapm_free - free dapm resources |
2766 | * @card: SoC device | 2766 | * @dapm: DAPM context |
2767 | * | 2767 | * |
2768 | * Free all dapm widgets and resources. | 2768 | * Free all dapm widgets and resources. |
2769 | */ | 2769 | */ |
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index cca490c80589..a62f7dd4ba96 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c | |||
@@ -205,6 +205,25 @@ static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec, | |||
205 | #define snd_soc_16_8_read_i2c NULL | 205 | #define snd_soc_16_8_read_i2c NULL |
206 | #endif | 206 | #endif |
207 | 207 | ||
208 | #if defined(CONFIG_SPI_MASTER) | ||
209 | static unsigned int snd_soc_16_8_read_spi(struct snd_soc_codec *codec, | ||
210 | unsigned int r) | ||
211 | { | ||
212 | struct spi_device *spi = codec->control_data; | ||
213 | |||
214 | const u16 reg = cpu_to_be16(r | 0x100); | ||
215 | u8 data; | ||
216 | int ret; | ||
217 | |||
218 | ret = spi_write_then_read(spi, ®, 2, &data, 1); | ||
219 | if (ret < 0) | ||
220 | return 0; | ||
221 | return data; | ||
222 | } | ||
223 | #else | ||
224 | #define snd_soc_16_8_read_spi NULL | ||
225 | #endif | ||
226 | |||
208 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | 227 | static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, |
209 | unsigned int value) | 228 | unsigned int value) |
210 | { | 229 | { |
@@ -295,6 +314,7 @@ static struct { | |||
295 | int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); | 314 | int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); |
296 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | 315 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); |
297 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); | 316 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); |
317 | unsigned int (*spi_read)(struct snd_soc_codec *, unsigned int); | ||
298 | } io_types[] = { | 318 | } io_types[] = { |
299 | { | 319 | { |
300 | .addr_bits = 4, .data_bits = 12, | 320 | .addr_bits = 4, .data_bits = 12, |
@@ -318,6 +338,7 @@ static struct { | |||
318 | .addr_bits = 16, .data_bits = 8, | 338 | .addr_bits = 16, .data_bits = 8, |
319 | .write = snd_soc_16_8_write, | 339 | .write = snd_soc_16_8_write, |
320 | .i2c_read = snd_soc_16_8_read_i2c, | 340 | .i2c_read = snd_soc_16_8_read_i2c, |
341 | .spi_read = snd_soc_16_8_read_spi, | ||
321 | }, | 342 | }, |
322 | { | 343 | { |
323 | .addr_bits = 16, .data_bits = 16, | 344 | .addr_bits = 16, .data_bits = 16, |
@@ -383,6 +404,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
383 | #ifdef CONFIG_SPI_MASTER | 404 | #ifdef CONFIG_SPI_MASTER |
384 | codec->hw_write = do_spi_write; | 405 | codec->hw_write = do_spi_write; |
385 | #endif | 406 | #endif |
407 | if (io_types[i].spi_read) | ||
408 | codec->hw_read = io_types[i].spi_read; | ||
386 | 409 | ||
387 | codec->control_data = container_of(codec->dev, | 410 | codec->control_data = container_of(codec->dev, |
388 | struct spi_device, | 411 | struct spi_device, |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 7c17b98d5846..fa31d9c2abd8 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -105,7 +105,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
105 | 105 | ||
106 | snd_soc_dapm_sync(dapm); | 106 | snd_soc_dapm_sync(dapm); |
107 | 107 | ||
108 | snd_jack_report(jack->jack, status); | 108 | snd_jack_report(jack->jack, jack->status); |
109 | 109 | ||
110 | out: | 110 | out: |
111 | mutex_unlock(&codec->mutex); | 111 | mutex_unlock(&codec->mutex); |
@@ -327,7 +327,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | |||
327 | IRQF_TRIGGER_FALLING, | 327 | IRQF_TRIGGER_FALLING, |
328 | gpios[i].name, | 328 | gpios[i].name, |
329 | &gpios[i]); | 329 | &gpios[i]); |
330 | if (ret) | 330 | if (ret < 0) |
331 | goto err; | 331 | goto err; |
332 | 332 | ||
333 | if (gpios[i].wake) { | 333 | if (gpios[i].wake) { |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b5759397afa3..2879c883eebc 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -290,6 +290,9 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
290 | codec_dai->active--; | 290 | codec_dai->active--; |
291 | codec->active--; | 291 | codec->active--; |
292 | 292 | ||
293 | if (!cpu_dai->active && !codec_dai->active) | ||
294 | rtd->rate = 0; | ||
295 | |||
293 | /* Muting the DAC suppresses artifacts caused during digital | 296 | /* Muting the DAC suppresses artifacts caused during digital |
294 | * shutdown, for example from stopping clocks. | 297 | * shutdown, for example from stopping clocks. |
295 | */ | 298 | */ |
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index ff86e5e3db68..c7cfd96e991e 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c | |||
@@ -309,9 +309,14 @@ static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
309 | 309 | ||
310 | static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) | 310 | static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) |
311 | { | 311 | { |
312 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | 312 | struct snd_pcm_substream *substream; |
313 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 313 | struct snd_dma_buffer *buf; |
314 | |||
315 | substream = pcm->streams[stream].substream; | ||
316 | if (!substream) | ||
317 | return; | ||
314 | 318 | ||
319 | buf = &substream->dma_buffer; | ||
315 | if (!buf->area) | 320 | if (!buf->area) |
316 | return; | 321 | return; |
317 | 322 | ||
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index a42e9ac30f28..be27f1d229af 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #define GPIO_HP_MUTE BIT(1) | 56 | #define GPIO_HP_MUTE BIT(1) |
57 | #define GPIO_INT_MIC_EN BIT(2) | 57 | #define GPIO_INT_MIC_EN BIT(2) |
58 | #define GPIO_EXT_MIC_EN BIT(3) | 58 | #define GPIO_EXT_MIC_EN BIT(3) |
59 | #define GPIO_HP_DET BIT(4) | ||
59 | 60 | ||
60 | struct tegra_wm8903 { | 61 | struct tegra_wm8903 { |
61 | struct tegra_asoc_utils_data util_data; | 62 | struct tegra_asoc_utils_data util_data; |
@@ -304,6 +305,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) | |||
304 | snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, | 305 | snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, |
305 | 1, | 306 | 1, |
306 | &tegra_wm8903_hp_jack_gpio); | 307 | &tegra_wm8903_hp_jack_gpio); |
308 | machine->gpio_requested |= GPIO_HP_DET; | ||
307 | } | 309 | } |
308 | 310 | ||
309 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, | 311 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, |
@@ -317,7 +319,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) | |||
317 | snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); | 319 | snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); |
318 | 320 | ||
319 | /* FIXME: Calculate automatically based on DAPM routes? */ | 321 | /* FIXME: Calculate automatically based on DAPM routes? */ |
320 | if (!machine_is_harmony() && !machine_is_ventana()) | 322 | if (!machine_is_harmony()) |
321 | snd_soc_dapm_nc_pin(dapm, "IN1L"); | 323 | snd_soc_dapm_nc_pin(dapm, "IN1L"); |
322 | if (!machine_is_seaboard() && !machine_is_aebl()) | 324 | if (!machine_is_seaboard() && !machine_is_aebl()) |
323 | snd_soc_dapm_nc_pin(dapm, "IN1R"); | 325 | snd_soc_dapm_nc_pin(dapm, "IN1R"); |
@@ -393,7 +395,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) | |||
393 | platform_set_drvdata(pdev, card); | 395 | platform_set_drvdata(pdev, card); |
394 | snd_soc_card_set_drvdata(card, machine); | 396 | snd_soc_card_set_drvdata(card, machine); |
395 | 397 | ||
396 | if (machine_is_harmony() || machine_is_ventana()) { | 398 | if (machine_is_harmony()) { |
397 | card->dapm_routes = harmony_audio_map; | 399 | card->dapm_routes = harmony_audio_map; |
398 | card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); | 400 | card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); |
399 | } else if (machine_is_seaboard()) { | 401 | } else if (machine_is_seaboard()) { |
@@ -429,10 +431,10 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) | |||
429 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); | 431 | struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); |
430 | struct tegra_wm8903_platform_data *pdata = machine->pdata; | 432 | struct tegra_wm8903_platform_data *pdata = machine->pdata; |
431 | 433 | ||
432 | snd_soc_unregister_card(card); | 434 | if (machine->gpio_requested & GPIO_HP_DET) |
433 | 435 | snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, | |
434 | tegra_asoc_utils_fini(&machine->util_data); | 436 | 1, |
435 | 437 | &tegra_wm8903_hp_jack_gpio); | |
436 | if (machine->gpio_requested & GPIO_EXT_MIC_EN) | 438 | if (machine->gpio_requested & GPIO_EXT_MIC_EN) |
437 | gpio_free(pdata->gpio_ext_mic_en); | 439 | gpio_free(pdata->gpio_ext_mic_en); |
438 | if (machine->gpio_requested & GPIO_INT_MIC_EN) | 440 | if (machine->gpio_requested & GPIO_INT_MIC_EN) |
@@ -441,6 +443,11 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) | |||
441 | gpio_free(pdata->gpio_hp_mute); | 443 | gpio_free(pdata->gpio_hp_mute); |
442 | if (machine->gpio_requested & GPIO_SPKR_EN) | 444 | if (machine->gpio_requested & GPIO_SPKR_EN) |
443 | gpio_free(pdata->gpio_spkr_en); | 445 | gpio_free(pdata->gpio_spkr_en); |
446 | machine->gpio_requested = 0; | ||
447 | |||
448 | snd_soc_unregister_card(card); | ||
449 | |||
450 | tegra_asoc_utils_fini(&machine->util_data); | ||
444 | 451 | ||
445 | kfree(machine); | 452 | kfree(machine); |
446 | 453 | ||
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index d0d493ca28ae..2cf87f5afed4 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c | |||
@@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_caiaqdev *dev) | |||
139 | 139 | ||
140 | for (i = 0; i < N_URBS; i++) { | 140 | for (i = 0; i < N_URBS; i++) { |
141 | usb_kill_urb(dev->data_urbs_in[i]); | 141 | usb_kill_urb(dev->data_urbs_in[i]); |
142 | usb_kill_urb(dev->data_urbs_out[i]); | 142 | |
143 | if (test_bit(i, &dev->outurb_active_mask)) | ||
144 | usb_kill_urb(dev->data_urbs_out[i]); | ||
143 | } | 145 | } |
146 | |||
147 | dev->outurb_active_mask = 0; | ||
144 | } | 148 | } |
145 | 149 | ||
146 | static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) | 150 | static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) |
@@ -612,8 +616,9 @@ static void read_completed(struct urb *urb) | |||
612 | { | 616 | { |
613 | struct snd_usb_caiaq_cb_info *info = urb->context; | 617 | struct snd_usb_caiaq_cb_info *info = urb->context; |
614 | struct snd_usb_caiaqdev *dev; | 618 | struct snd_usb_caiaqdev *dev; |
615 | struct urb *out; | 619 | struct urb *out = NULL; |
616 | int frame, len, send_it = 0, outframe = 0; | 620 | int i, frame, len, send_it = 0, outframe = 0; |
621 | size_t offset = 0; | ||
617 | 622 | ||
618 | if (urb->status || !info) | 623 | if (urb->status || !info) |
619 | return; | 624 | return; |
@@ -623,7 +628,17 @@ static void read_completed(struct urb *urb) | |||
623 | if (!dev->streaming) | 628 | if (!dev->streaming) |
624 | return; | 629 | return; |
625 | 630 | ||
626 | out = dev->data_urbs_out[info->index]; | 631 | /* find an unused output urb that is unused */ |
632 | for (i = 0; i < N_URBS; i++) | ||
633 | if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) { | ||
634 | out = dev->data_urbs_out[i]; | ||
635 | break; | ||
636 | } | ||
637 | |||
638 | if (!out) { | ||
639 | log("Unable to find an output urb to use\n"); | ||
640 | goto requeue; | ||
641 | } | ||
627 | 642 | ||
628 | /* read the recently received packet and send back one which has | 643 | /* read the recently received packet and send back one which has |
629 | * the same layout */ | 644 | * the same layout */ |
@@ -634,7 +649,8 @@ static void read_completed(struct urb *urb) | |||
634 | len = urb->iso_frame_desc[outframe].actual_length; | 649 | len = urb->iso_frame_desc[outframe].actual_length; |
635 | out->iso_frame_desc[outframe].length = len; | 650 | out->iso_frame_desc[outframe].length = len; |
636 | out->iso_frame_desc[outframe].actual_length = 0; | 651 | out->iso_frame_desc[outframe].actual_length = 0; |
637 | out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame; | 652 | out->iso_frame_desc[outframe].offset = offset; |
653 | offset += len; | ||
638 | 654 | ||
639 | if (len > 0) { | 655 | if (len > 0) { |
640 | spin_lock(&dev->spinlock); | 656 | spin_lock(&dev->spinlock); |
@@ -650,11 +666,15 @@ static void read_completed(struct urb *urb) | |||
650 | } | 666 | } |
651 | 667 | ||
652 | if (send_it) { | 668 | if (send_it) { |
653 | out->number_of_packets = FRAMES_PER_URB; | 669 | out->number_of_packets = outframe; |
654 | out->transfer_flags = URB_ISO_ASAP; | 670 | out->transfer_flags = URB_ISO_ASAP; |
655 | usb_submit_urb(out, GFP_ATOMIC); | 671 | usb_submit_urb(out, GFP_ATOMIC); |
672 | } else { | ||
673 | struct snd_usb_caiaq_cb_info *oinfo = out->context; | ||
674 | clear_bit(oinfo->index, &dev->outurb_active_mask); | ||
656 | } | 675 | } |
657 | 676 | ||
677 | requeue: | ||
658 | /* re-submit inbound urb */ | 678 | /* re-submit inbound urb */ |
659 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { | 679 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { |
660 | urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; | 680 | urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; |
@@ -676,6 +696,8 @@ static void write_completed(struct urb *urb) | |||
676 | dev->output_running = 1; | 696 | dev->output_running = 1; |
677 | wake_up(&dev->prepare_wait_queue); | 697 | wake_up(&dev->prepare_wait_queue); |
678 | } | 698 | } |
699 | |||
700 | clear_bit(info->index, &dev->outurb_active_mask); | ||
679 | } | 701 | } |
680 | 702 | ||
681 | static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) | 703 | static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) |
@@ -827,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) | |||
827 | if (!dev->data_cb_info) | 849 | if (!dev->data_cb_info) |
828 | return -ENOMEM; | 850 | return -ENOMEM; |
829 | 851 | ||
852 | dev->outurb_active_mask = 0; | ||
853 | BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8)); | ||
854 | |||
830 | for (i = 0; i < N_URBS; i++) { | 855 | for (i = 0; i < N_URBS; i++) { |
831 | dev->data_cb_info[i].dev = dev; | 856 | dev->data_cb_info[i].dev = dev; |
832 | dev->data_cb_info[i].index = i; | 857 | dev->data_cb_info[i].index = i; |
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h index b2b310194ffa..3f9c6339ae90 100644 --- a/sound/usb/caiaq/device.h +++ b/sound/usb/caiaq/device.h | |||
@@ -96,6 +96,7 @@ struct snd_usb_caiaqdev { | |||
96 | int input_panic, output_panic, warned; | 96 | int input_panic, output_panic, warned; |
97 | char *audio_in_buf, *audio_out_buf; | 97 | char *audio_in_buf, *audio_out_buf; |
98 | unsigned int samplerates, bpp; | 98 | unsigned int samplerates, bpp; |
99 | unsigned long outurb_active_mask; | ||
99 | 100 | ||
100 | struct snd_pcm_substream *sub_playback[MAX_STREAMS]; | 101 | struct snd_pcm_substream *sub_playback[MAX_STREAMS]; |
101 | struct snd_pcm_substream *sub_capture[MAX_STREAMS]; | 102 | struct snd_pcm_substream *sub_capture[MAX_STREAMS]; |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c04d7c71ac88..cdd19d7fe500 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -152,6 +152,7 @@ static inline void check_mapped_dB(const struct usbmix_name_map *p, | |||
152 | if (p && p->dB) { | 152 | if (p && p->dB) { |
153 | cval->dBmin = p->dB->min; | 153 | cval->dBmin = p->dB->min; |
154 | cval->dBmax = p->dB->max; | 154 | cval->dBmax = p->dB->max; |
155 | cval->initialized = 1; | ||
155 | } | 156 | } |
156 | } | 157 | } |
157 | 158 | ||
@@ -1092,7 +1093,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1092 | " Switch" : " Volume"); | 1093 | " Switch" : " Volume"); |
1093 | if (control == UAC_FU_VOLUME) { | 1094 | if (control == UAC_FU_VOLUME) { |
1094 | check_mapped_dB(map, cval); | 1095 | check_mapped_dB(map, cval); |
1095 | if (cval->dBmin < cval->dBmax) { | 1096 | if (cval->dBmin < cval->dBmax || !cval->initialized) { |
1096 | kctl->tlv.c = mixer_vol_tlv; | 1097 | kctl->tlv.c = mixer_vol_tlv; |
1097 | kctl->vd[0].access |= | 1098 | kctl->vd[0].access |= |
1098 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 1099 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 4d4f86552a23..a42e3ef3832d 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -1707,6 +1707,40 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1707 | } | 1707 | } |
1708 | } | 1708 | } |
1709 | }, | 1709 | }, |
1710 | { | ||
1711 | USB_DEVICE(0x0582, 0x0130), | ||
1712 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1713 | /* .vendor_name = "BOSS", */ | ||
1714 | /* .product_name = "MICRO BR-80", */ | ||
1715 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1716 | .type = QUIRK_COMPOSITE, | ||
1717 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1718 | { | ||
1719 | .ifnum = 0, | ||
1720 | .type = QUIRK_IGNORE_INTERFACE | ||
1721 | }, | ||
1722 | { | ||
1723 | .ifnum = 1, | ||
1724 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1725 | }, | ||
1726 | { | ||
1727 | .ifnum = 2, | ||
1728 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1729 | }, | ||
1730 | { | ||
1731 | .ifnum = 3, | ||
1732 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1733 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1734 | .out_cables = 0x0001, | ||
1735 | .in_cables = 0x0001 | ||
1736 | } | ||
1737 | }, | ||
1738 | { | ||
1739 | .ifnum = -1 | ||
1740 | } | ||
1741 | } | ||
1742 | } | ||
1743 | }, | ||
1710 | 1744 | ||
1711 | /* Guillemot devices */ | 1745 | /* Guillemot devices */ |
1712 | { | 1746 | { |