diff options
26 files changed, 635 insertions, 3720 deletions
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 467836057ee5..a80d5ea87ccd 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c | |||
@@ -47,15 +47,11 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, | |||
47 | /* We use the PCI APIs for now until the generic one gets fixed | 47 | /* We use the PCI APIs for now until the generic one gets fixed |
48 | * enough or until we get some macio-specific versions | 48 | * enough or until we get some macio-specific versions |
49 | */ | 49 | */ |
50 | r->space = dma_alloc_coherent( | 50 | r->space = dma_zalloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev, |
51 | &macio_get_pci_dev(i2sdev->macio)->dev, | 51 | r->size, &r->bus_addr, GFP_KERNEL); |
52 | r->size, | 52 | if (!r->space) |
53 | &r->bus_addr, | 53 | return -ENOMEM; |
54 | GFP_KERNEL); | ||
55 | 54 | ||
56 | if (!r->space) return -ENOMEM; | ||
57 | |||
58 | memset(r->space, 0, r->size); | ||
59 | r->cmds = (void*)DBDMA_ALIGN(r->space); | 55 | r->cmds = (void*)DBDMA_ALIGN(r->space); |
60 | r->bus_cmd_start = r->bus_addr + | 56 | r->bus_cmd_start = r->bus_addr + |
61 | (dma_addr_t)((char*)r->cmds - (char*)r->space); | 57 | (dma_addr_t)((char*)r->cmds - (char*)r->space); |
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 1e206de0c2dd..ba8e4a64e13e 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -101,9 +101,9 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, | |||
101 | len -= size; | 101 | len -= size; |
102 | } | 102 | } |
103 | return 0; | 103 | return 0; |
104 | } if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) { | ||
105 | return func(private_data, event->data.ext.ptr, len); | ||
106 | } | 104 | } |
105 | if (!(event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) | ||
106 | return func(private_data, event->data.ext.ptr, len); | ||
107 | 107 | ||
108 | cell = (struct snd_seq_event_cell *)event->data.ext.ptr; | 108 | cell = (struct snd_seq_event_cell *)event->data.ext.ptr; |
109 | for (; len > 0 && cell; cell = cell->next) { | 109 | for (; len > 0 && cell; cell = cell->next) { |
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c index 3bbc3ec5be82..862735005b43 100644 --- a/sound/oss/mpu401.c +++ b/sound/oss/mpu401.c | |||
@@ -316,6 +316,7 @@ static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic) | |||
316 | case 0xf6: | 316 | case 0xf6: |
317 | /* printk( "tune_request\n"); */ | 317 | /* printk( "tune_request\n"); */ |
318 | devc->m_state = ST_INIT; | 318 | devc->m_state = ST_INIT; |
319 | break; | ||
319 | 320 | ||
320 | /* | 321 | /* |
321 | * Real time messages | 322 | * Real time messages |
@@ -972,7 +973,6 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner) | |||
972 | devc->m_busy = 0; | 973 | devc->m_busy = 0; |
973 | devc->m_state = ST_INIT; | 974 | devc->m_state = ST_INIT; |
974 | devc->shared_irq = hw_config->always_detect; | 975 | devc->shared_irq = hw_config->always_detect; |
975 | devc->irq = hw_config->irq; | ||
976 | spin_lock_init(&devc->lock); | 976 | spin_lock_init(&devc->lock); |
977 | 977 | ||
978 | if (devc->irq < 0) | 978 | if (devc->irq < 0) |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 9f10c9e0df5e..631aaa4046ad 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -1754,9 +1754,6 @@ static struct snd_kcontrol_new snd_echo_vumeters_switch = { | |||
1754 | static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, | 1754 | static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, |
1755 | struct snd_ctl_elem_info *uinfo) | 1755 | struct snd_ctl_elem_info *uinfo) |
1756 | { | 1756 | { |
1757 | struct echoaudio *chip; | ||
1758 | |||
1759 | chip = snd_kcontrol_chip(kcontrol); | ||
1760 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1757 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1761 | uinfo->count = 96; | 1758 | uinfo->count = 96; |
1762 | uinfo->value.integer.min = ECHOGAIN_MINOUT; | 1759 | uinfo->value.integer.min = ECHOGAIN_MINOUT; |
@@ -1798,9 +1795,6 @@ static struct snd_kcontrol_new snd_echo_vumeters = { | |||
1798 | static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, | 1795 | static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, |
1799 | struct snd_ctl_elem_info *uinfo) | 1796 | struct snd_ctl_elem_info *uinfo) |
1800 | { | 1797 | { |
1801 | struct echoaudio *chip; | ||
1802 | |||
1803 | chip = snd_kcontrol_chip(kcontrol); | ||
1804 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1798 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1805 | uinfo->count = 6; | 1799 | uinfo->count = 6; |
1806 | uinfo->value.integer.min = 0; | 1800 | uinfo->value.integer.min = 0; |
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index dabe41975a9d..a9790198aa17 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include "hda_local.h" | 17 | #include "hda_local.h" |
18 | #include "hda_auto_parser.h" | 18 | #include "hda_auto_parser.h" |
19 | 19 | ||
20 | #define SFX "hda_codec: " | ||
21 | |||
22 | /* | 20 | /* |
23 | * Helper for automatic pin configuration | 21 | * Helper for automatic pin configuration |
24 | */ | 22 | */ |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4c20277a6835..47a617786fca 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2727,7 +2727,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2727 | return 0; | 2727 | return 0; |
2728 | } | 2728 | } |
2729 | 2729 | ||
2730 | typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); | 2730 | typedef int (*map_slave_func_t)(struct hda_codec *, void *, struct snd_kcontrol *); |
2731 | 2731 | ||
2732 | /* apply the function to all matching slave ctls in the mixer list */ | 2732 | /* apply the function to all matching slave ctls in the mixer list */ |
2733 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, | 2733 | static int map_slaves(struct hda_codec *codec, const char * const *slaves, |
@@ -2751,7 +2751,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, | |||
2751 | name = tmpname; | 2751 | name = tmpname; |
2752 | } | 2752 | } |
2753 | if (!strcmp(sctl->id.name, name)) { | 2753 | if (!strcmp(sctl->id.name, name)) { |
2754 | err = func(data, sctl); | 2754 | err = func(codec, data, sctl); |
2755 | if (err) | 2755 | if (err) |
2756 | return err; | 2756 | return err; |
2757 | break; | 2757 | break; |
@@ -2761,13 +2761,15 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves, | |||
2761 | return 0; | 2761 | return 0; |
2762 | } | 2762 | } |
2763 | 2763 | ||
2764 | static int check_slave_present(void *data, struct snd_kcontrol *sctl) | 2764 | static int check_slave_present(struct hda_codec *codec, |
2765 | void *data, struct snd_kcontrol *sctl) | ||
2765 | { | 2766 | { |
2766 | return 1; | 2767 | return 1; |
2767 | } | 2768 | } |
2768 | 2769 | ||
2769 | /* guess the value corresponding to 0dB */ | 2770 | /* guess the value corresponding to 0dB */ |
2770 | static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check) | 2771 | static int get_kctl_0dB_offset(struct hda_codec *codec, |
2772 | struct snd_kcontrol *kctl, int *step_to_check) | ||
2771 | { | 2773 | { |
2772 | int _tlv[4]; | 2774 | int _tlv[4]; |
2773 | const int *tlv = NULL; | 2775 | const int *tlv = NULL; |
@@ -2788,7 +2790,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check) | |||
2788 | if (!step) | 2790 | if (!step) |
2789 | return -1; | 2791 | return -1; |
2790 | if (*step_to_check && *step_to_check != step) { | 2792 | if (*step_to_check && *step_to_check != step) { |
2791 | snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n", | 2793 | codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n", |
2792 | - *step_to_check, step); | 2794 | - *step_to_check, step); |
2793 | return -1; | 2795 | return -1; |
2794 | } | 2796 | } |
@@ -2813,20 +2815,28 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) | |||
2813 | } | 2815 | } |
2814 | 2816 | ||
2815 | /* initialize the slave volume with 0dB */ | 2817 | /* initialize the slave volume with 0dB */ |
2816 | static int init_slave_0dB(void *data, struct snd_kcontrol *slave) | 2818 | static int init_slave_0dB(struct hda_codec *codec, |
2819 | void *data, struct snd_kcontrol *slave) | ||
2817 | { | 2820 | { |
2818 | int offset = get_kctl_0dB_offset(slave, data); | 2821 | int offset = get_kctl_0dB_offset(codec, slave, data); |
2819 | if (offset > 0) | 2822 | if (offset > 0) |
2820 | put_kctl_with_value(slave, offset); | 2823 | put_kctl_with_value(slave, offset); |
2821 | return 0; | 2824 | return 0; |
2822 | } | 2825 | } |
2823 | 2826 | ||
2824 | /* unmute the slave */ | 2827 | /* unmute the slave */ |
2825 | static int init_slave_unmute(void *data, struct snd_kcontrol *slave) | 2828 | static int init_slave_unmute(struct hda_codec *codec, |
2829 | void *data, struct snd_kcontrol *slave) | ||
2826 | { | 2830 | { |
2827 | return put_kctl_with_value(slave, 1); | 2831 | return put_kctl_with_value(slave, 1); |
2828 | } | 2832 | } |
2829 | 2833 | ||
2834 | static int add_slave(struct hda_codec *codec, | ||
2835 | void *data, struct snd_kcontrol *slave) | ||
2836 | { | ||
2837 | return snd_ctl_add_slave(data, slave); | ||
2838 | } | ||
2839 | |||
2830 | /** | 2840 | /** |
2831 | * snd_hda_add_vmaster - create a virtual master control and add slaves | 2841 | * snd_hda_add_vmaster - create a virtual master control and add slaves |
2832 | * @codec: HD-audio codec | 2842 | * @codec: HD-audio codec |
@@ -2869,8 +2879,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
2869 | if (err < 0) | 2879 | if (err < 0) |
2870 | return err; | 2880 | return err; |
2871 | 2881 | ||
2872 | err = map_slaves(codec, slaves, suffix, | 2882 | err = map_slaves(codec, slaves, suffix, add_slave, kctl); |
2873 | (map_slave_func_t)snd_ctl_add_slave, kctl); | ||
2874 | if (err < 0) | 2883 | if (err < 0) |
2875 | return err; | 2884 | return err; |
2876 | 2885 | ||
@@ -4280,6 +4289,7 @@ static struct hda_rate_tbl rate_bits[] = { | |||
4280 | 4289 | ||
4281 | /** | 4290 | /** |
4282 | * snd_hda_calc_stream_format - calculate format bitset | 4291 | * snd_hda_calc_stream_format - calculate format bitset |
4292 | * @codec: HD-audio codec | ||
4283 | * @rate: the sample rate | 4293 | * @rate: the sample rate |
4284 | * @channels: the number of channels | 4294 | * @channels: the number of channels |
4285 | * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) | 4295 | * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) |
@@ -4289,7 +4299,8 @@ static struct hda_rate_tbl rate_bits[] = { | |||
4289 | * | 4299 | * |
4290 | * Return zero if invalid. | 4300 | * Return zero if invalid. |
4291 | */ | 4301 | */ |
4292 | unsigned int snd_hda_calc_stream_format(unsigned int rate, | 4302 | unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, |
4303 | unsigned int rate, | ||
4293 | unsigned int channels, | 4304 | unsigned int channels, |
4294 | unsigned int format, | 4305 | unsigned int format, |
4295 | unsigned int maxbps, | 4306 | unsigned int maxbps, |
@@ -4304,12 +4315,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
4304 | break; | 4315 | break; |
4305 | } | 4316 | } |
4306 | if (!rate_bits[i].hz) { | 4317 | if (!rate_bits[i].hz) { |
4307 | snd_printdd("invalid rate %d\n", rate); | 4318 | codec_dbg(codec, "invalid rate %d\n", rate); |
4308 | return 0; | 4319 | return 0; |
4309 | } | 4320 | } |
4310 | 4321 | ||
4311 | if (channels == 0 || channels > 8) { | 4322 | if (channels == 0 || channels > 8) { |
4312 | snd_printdd("invalid channels %d\n", channels); | 4323 | codec_dbg(codec, "invalid channels %d\n", channels); |
4313 | return 0; | 4324 | return 0; |
4314 | } | 4325 | } |
4315 | val |= channels - 1; | 4326 | val |= channels - 1; |
@@ -4332,7 +4343,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
4332 | val |= AC_FMT_BITS_20; | 4343 | val |= AC_FMT_BITS_20; |
4333 | break; | 4344 | break; |
4334 | default: | 4345 | default: |
4335 | snd_printdd("invalid format width %d\n", | 4346 | codec_dbg(codec, "invalid format width %d\n", |
4336 | snd_pcm_format_width(format)); | 4347 | snd_pcm_format_width(format)); |
4337 | return 0; | 4348 | return 0; |
4338 | } | 4349 | } |
@@ -5670,12 +5681,13 @@ EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl); | |||
5670 | * suffix is appended to the label. This label index number is stored | 5681 | * suffix is appended to the label. This label index number is stored |
5671 | * to type_idx when non-NULL pointer is given. | 5682 | * to type_idx when non-NULL pointer is given. |
5672 | */ | 5683 | */ |
5673 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | 5684 | int snd_hda_add_imux_item(struct hda_codec *codec, |
5685 | struct hda_input_mux *imux, const char *label, | ||
5674 | int index, int *type_idx) | 5686 | int index, int *type_idx) |
5675 | { | 5687 | { |
5676 | int i, label_idx = 0; | 5688 | int i, label_idx = 0; |
5677 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { | 5689 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { |
5678 | snd_printd(KERN_ERR "hda_codec: Too many imux items!\n"); | 5690 | codec_err(codec, "hda_codec: Too many imux items!\n"); |
5679 | return -EINVAL; | 5691 | return -EINVAL; |
5680 | } | 5692 | } |
5681 | for (i = 0; i < imux->num_items; i++) { | 5693 | for (i = 0; i < imux->num_items; i++) { |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 5825aa17d8e3..f84a40ef42af 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -538,7 +538,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
538 | int do_now); | 538 | int do_now); |
539 | #define snd_hda_codec_cleanup_stream(codec, nid) \ | 539 | #define snd_hda_codec_cleanup_stream(codec, nid) \ |
540 | __snd_hda_codec_cleanup_stream(codec, nid, 0) | 540 | __snd_hda_codec_cleanup_stream(codec, nid, 0) |
541 | unsigned int snd_hda_calc_stream_format(unsigned int rate, | 541 | unsigned int snd_hda_calc_stream_format(struct hda_codec *codec, |
542 | unsigned int rate, | ||
542 | unsigned int channels, | 543 | unsigned int channels, |
543 | unsigned int format, | 544 | unsigned int format, |
544 | unsigned int maxbps, | 545 | unsigned int maxbps, |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 480bbddbd801..06f39c126ba4 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/reboot.h> | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
32 | #include "hda_priv.h" | 33 | #include "hda_priv.h" |
@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
152 | upper_32_bits(azx_dev->bdl.addr)); | 153 | upper_32_bits(azx_dev->bdl.addr)); |
153 | 154 | ||
154 | /* enable the position buffer */ | 155 | /* enable the position buffer */ |
155 | if (chip->position_fix[0] != POS_FIX_LPIB || | 156 | if (chip->get_position[0] != azx_get_pos_lpib || |
156 | chip->position_fix[1] != POS_FIX_LPIB) { | 157 | chip->get_position[1] != azx_get_pos_lpib) { |
157 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 158 | if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE)) |
158 | azx_writel(chip, DPLBASE, | 159 | azx_writel(chip, DPLBASE, |
159 | (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 160 | (u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE); |
160 | } | 161 | } |
161 | 162 | ||
162 | /* set the interrupt enable bits in the descriptor control register */ | 163 | /* set the interrupt enable bits in the descriptor control register */ |
@@ -481,7 +482,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
481 | } | 482 | } |
482 | 483 | ||
483 | azx_stream_reset(chip, azx_dev); | 484 | azx_stream_reset(chip, azx_dev); |
484 | format_val = snd_hda_calc_stream_format(runtime->rate, | 485 | format_val = snd_hda_calc_stream_format(apcm->codec, |
486 | runtime->rate, | ||
485 | runtime->channels, | 487 | runtime->channels, |
486 | runtime->format, | 488 | runtime->format, |
487 | hinfo->maxbps, | 489 | hinfo->maxbps, |
@@ -672,125 +674,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
672 | return 0; | 674 | return 0; |
673 | } | 675 | } |
674 | 676 | ||
675 | /* get the current DMA position with correction on VIA chips */ | 677 | unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev) |
676 | static unsigned int azx_via_get_position(struct azx *chip, | ||
677 | struct azx_dev *azx_dev) | ||
678 | { | 678 | { |
679 | unsigned int link_pos, mini_pos, bound_pos; | 679 | return azx_sd_readl(chip, azx_dev, SD_LPIB); |
680 | unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; | 680 | } |
681 | unsigned int fifo_size; | 681 | EXPORT_SYMBOL_GPL(azx_get_pos_lpib); |
682 | |||
683 | link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
684 | if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
685 | /* Playback, no problem using link position */ | ||
686 | return link_pos; | ||
687 | } | ||
688 | |||
689 | /* Capture */ | ||
690 | /* For new chipset, | ||
691 | * use mod to get the DMA position just like old chipset | ||
692 | */ | ||
693 | mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); | ||
694 | mod_dma_pos %= azx_dev->period_bytes; | ||
695 | |||
696 | /* azx_dev->fifo_size can't get FIFO size of in stream. | ||
697 | * Get from base address + offset. | ||
698 | */ | ||
699 | fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); | ||
700 | |||
701 | if (azx_dev->insufficient) { | ||
702 | /* Link position never gather than FIFO size */ | ||
703 | if (link_pos <= fifo_size) | ||
704 | return 0; | ||
705 | |||
706 | azx_dev->insufficient = 0; | ||
707 | } | ||
708 | |||
709 | if (link_pos <= fifo_size) | ||
710 | mini_pos = azx_dev->bufsize + link_pos - fifo_size; | ||
711 | else | ||
712 | mini_pos = link_pos - fifo_size; | ||
713 | |||
714 | /* Find nearest previous boudary */ | ||
715 | mod_mini_pos = mini_pos % azx_dev->period_bytes; | ||
716 | mod_link_pos = link_pos % azx_dev->period_bytes; | ||
717 | if (mod_link_pos >= fifo_size) | ||
718 | bound_pos = link_pos - mod_link_pos; | ||
719 | else if (mod_dma_pos >= mod_mini_pos) | ||
720 | bound_pos = mini_pos - mod_mini_pos; | ||
721 | else { | ||
722 | bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; | ||
723 | if (bound_pos >= azx_dev->bufsize) | ||
724 | bound_pos = 0; | ||
725 | } | ||
726 | 682 | ||
727 | /* Calculate real DMA position we want */ | 683 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev) |
728 | return bound_pos + mod_dma_pos; | 684 | { |
685 | return le32_to_cpu(*azx_dev->posbuf); | ||
729 | } | 686 | } |
687 | EXPORT_SYMBOL_GPL(azx_get_pos_posbuf); | ||
730 | 688 | ||
731 | unsigned int azx_get_position(struct azx *chip, | 689 | unsigned int azx_get_position(struct azx *chip, |
732 | struct azx_dev *azx_dev, | 690 | struct azx_dev *azx_dev) |
733 | bool with_check) | ||
734 | { | 691 | { |
735 | struct snd_pcm_substream *substream = azx_dev->substream; | 692 | struct snd_pcm_substream *substream = azx_dev->substream; |
736 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
737 | unsigned int pos; | 693 | unsigned int pos; |
738 | int stream = substream->stream; | 694 | int stream = substream->stream; |
739 | struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; | ||
740 | int delay = 0; | 695 | int delay = 0; |
741 | 696 | ||
742 | switch (chip->position_fix[stream]) { | 697 | if (chip->get_position[stream]) |
743 | case POS_FIX_LPIB: | 698 | pos = chip->get_position[stream](chip, azx_dev); |
744 | /* read LPIB */ | 699 | else /* use the position buffer as default */ |
745 | pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | 700 | pos = azx_get_pos_posbuf(chip, azx_dev); |
746 | break; | ||
747 | case POS_FIX_VIACOMBO: | ||
748 | pos = azx_via_get_position(chip, azx_dev); | ||
749 | break; | ||
750 | default: | ||
751 | /* use the position buffer */ | ||
752 | pos = le32_to_cpu(*azx_dev->posbuf); | ||
753 | if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) { | ||
754 | if (!pos || pos == (u32)-1) { | ||
755 | dev_info(chip->card->dev, | ||
756 | "Invalid position buffer, using LPIB read method instead.\n"); | ||
757 | chip->position_fix[stream] = POS_FIX_LPIB; | ||
758 | pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
759 | } else | ||
760 | chip->position_fix[stream] = POS_FIX_POSBUF; | ||
761 | } | ||
762 | break; | ||
763 | } | ||
764 | 701 | ||
765 | if (pos >= azx_dev->bufsize) | 702 | if (pos >= azx_dev->bufsize) |
766 | pos = 0; | 703 | pos = 0; |
767 | 704 | ||
768 | /* calculate runtime delay from LPIB */ | ||
769 | if (substream->runtime && | ||
770 | chip->position_fix[stream] == POS_FIX_POSBUF && | ||
771 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { | ||
772 | unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
773 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
774 | delay = pos - lpib_pos; | ||
775 | else | ||
776 | delay = lpib_pos - pos; | ||
777 | if (delay < 0) { | ||
778 | if (delay >= azx_dev->delay_negative_threshold) | ||
779 | delay = 0; | ||
780 | else | ||
781 | delay += azx_dev->bufsize; | ||
782 | } | ||
783 | if (delay >= azx_dev->period_bytes) { | ||
784 | dev_info(chip->card->dev, | ||
785 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", | ||
786 | delay, azx_dev->period_bytes); | ||
787 | delay = 0; | ||
788 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | ||
789 | } | ||
790 | delay = bytes_to_frames(substream->runtime, delay); | ||
791 | } | ||
792 | |||
793 | if (substream->runtime) { | 705 | if (substream->runtime) { |
706 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
707 | struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; | ||
708 | |||
709 | if (chip->get_delay[stream]) | ||
710 | delay += chip->get_delay[stream](chip, azx_dev, pos); | ||
794 | if (hinfo->ops.get_delay) | 711 | if (hinfo->ops.get_delay) |
795 | delay += hinfo->ops.get_delay(hinfo, apcm->codec, | 712 | delay += hinfo->ops.get_delay(hinfo, apcm->codec, |
796 | substream); | 713 | substream); |
@@ -808,7 +725,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
808 | struct azx *chip = apcm->chip; | 725 | struct azx *chip = apcm->chip; |
809 | struct azx_dev *azx_dev = get_azx_dev(substream); | 726 | struct azx_dev *azx_dev = get_azx_dev(substream); |
810 | return bytes_to_frames(substream->runtime, | 727 | return bytes_to_frames(substream->runtime, |
811 | azx_get_position(chip, azx_dev, false)); | 728 | azx_get_position(chip, azx_dev)); |
812 | } | 729 | } |
813 | 730 | ||
814 | static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, | 731 | static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, |
@@ -1058,10 +975,10 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1058 | azx_writew(chip, CORBWP, 0); | 975 | azx_writew(chip, CORBWP, 0); |
1059 | 976 | ||
1060 | /* reset the corb hw read pointer */ | 977 | /* reset the corb hw read pointer */ |
1061 | azx_writew(chip, CORBRP, ICH6_CORBRP_RST); | 978 | azx_writew(chip, CORBRP, AZX_CORBRP_RST); |
1062 | if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) { | 979 | if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) { |
1063 | for (timeout = 1000; timeout > 0; timeout--) { | 980 | for (timeout = 1000; timeout > 0; timeout--) { |
1064 | if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST) | 981 | if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST) |
1065 | break; | 982 | break; |
1066 | udelay(1); | 983 | udelay(1); |
1067 | } | 984 | } |
@@ -1081,7 +998,7 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1081 | } | 998 | } |
1082 | 999 | ||
1083 | /* enable corb dma */ | 1000 | /* enable corb dma */ |
1084 | azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN); | 1001 | azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN); |
1085 | 1002 | ||
1086 | /* RIRB set up */ | 1003 | /* RIRB set up */ |
1087 | chip->rirb.addr = chip->rb.addr + 2048; | 1004 | chip->rirb.addr = chip->rb.addr + 2048; |
@@ -1094,14 +1011,14 @@ static void azx_init_cmd_io(struct azx *chip) | |||
1094 | /* set the rirb size to 256 entries (ULI requires explicitly) */ | 1011 | /* set the rirb size to 256 entries (ULI requires explicitly) */ |
1095 | azx_writeb(chip, RIRBSIZE, 0x02); | 1012 | azx_writeb(chip, RIRBSIZE, 0x02); |
1096 | /* reset the rirb hw write pointer */ | 1013 | /* reset the rirb hw write pointer */ |
1097 | azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); | 1014 | azx_writew(chip, RIRBWP, AZX_RIRBWP_RST); |
1098 | /* set N=1, get RIRB response interrupt for new entry */ | 1015 | /* set N=1, get RIRB response interrupt for new entry */ |
1099 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) | 1016 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) |
1100 | azx_writew(chip, RINTCNT, 0xc0); | 1017 | azx_writew(chip, RINTCNT, 0xc0); |
1101 | else | 1018 | else |
1102 | azx_writew(chip, RINTCNT, 1); | 1019 | azx_writew(chip, RINTCNT, 1); |
1103 | /* enable rirb dma and response irq */ | 1020 | /* enable rirb dma and response irq */ |
1104 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); | 1021 | azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); |
1105 | spin_unlock_irq(&chip->reg_lock); | 1022 | spin_unlock_irq(&chip->reg_lock); |
1106 | } | 1023 | } |
1107 | EXPORT_SYMBOL_GPL(azx_init_cmd_io); | 1024 | EXPORT_SYMBOL_GPL(azx_init_cmd_io); |
@@ -1145,7 +1062,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) | |||
1145 | return -EIO; | 1062 | return -EIO; |
1146 | } | 1063 | } |
1147 | wp++; | 1064 | wp++; |
1148 | wp %= ICH6_MAX_CORB_ENTRIES; | 1065 | wp %= AZX_MAX_CORB_ENTRIES; |
1149 | 1066 | ||
1150 | rp = azx_readw(chip, CORBRP); | 1067 | rp = azx_readw(chip, CORBRP); |
1151 | if (wp == rp) { | 1068 | if (wp == rp) { |
@@ -1163,7 +1080,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) | |||
1163 | return 0; | 1080 | return 0; |
1164 | } | 1081 | } |
1165 | 1082 | ||
1166 | #define ICH6_RIRB_EX_UNSOL_EV (1<<4) | 1083 | #define AZX_RIRB_EX_UNSOL_EV (1<<4) |
1167 | 1084 | ||
1168 | /* retrieve RIRB entry - called from interrupt handler */ | 1085 | /* retrieve RIRB entry - called from interrupt handler */ |
1169 | static void azx_update_rirb(struct azx *chip) | 1086 | static void azx_update_rirb(struct azx *chip) |
@@ -1184,7 +1101,7 @@ static void azx_update_rirb(struct azx *chip) | |||
1184 | 1101 | ||
1185 | while (chip->rirb.rp != wp) { | 1102 | while (chip->rirb.rp != wp) { |
1186 | chip->rirb.rp++; | 1103 | chip->rirb.rp++; |
1187 | chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; | 1104 | chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES; |
1188 | 1105 | ||
1189 | rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ | 1106 | rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ |
1190 | res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); | 1107 | res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); |
@@ -1195,8 +1112,7 @@ static void azx_update_rirb(struct azx *chip) | |||
1195 | res, res_ex, | 1112 | res, res_ex, |
1196 | chip->rirb.rp, wp); | 1113 | chip->rirb.rp, wp); |
1197 | snd_BUG(); | 1114 | snd_BUG(); |
1198 | } | 1115 | } else if (res_ex & AZX_RIRB_EX_UNSOL_EV) |
1199 | else if (res_ex & ICH6_RIRB_EX_UNSOL_EV) | ||
1200 | snd_hda_queue_unsol_event(chip->bus, res, res_ex); | 1116 | snd_hda_queue_unsol_event(chip->bus, res, res_ex); |
1201 | else if (chip->rirb.cmds[addr]) { | 1117 | else if (chip->rirb.cmds[addr]) { |
1202 | chip->rirb.res[addr] = res; | 1118 | chip->rirb.res[addr] = res; |
@@ -1304,7 +1220,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, | |||
1304 | /* release CORB/RIRB */ | 1220 | /* release CORB/RIRB */ |
1305 | azx_free_cmd_io(chip); | 1221 | azx_free_cmd_io(chip); |
1306 | /* disable unsolicited responses */ | 1222 | /* disable unsolicited responses */ |
1307 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL); | 1223 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL); |
1308 | return -1; | 1224 | return -1; |
1309 | } | 1225 | } |
1310 | 1226 | ||
@@ -1325,7 +1241,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) | |||
1325 | 1241 | ||
1326 | while (timeout--) { | 1242 | while (timeout--) { |
1327 | /* check IRV busy bit */ | 1243 | /* check IRV busy bit */ |
1328 | if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { | 1244 | if (azx_readw(chip, IRS) & AZX_IRS_VALID) { |
1329 | /* reuse rirb.res as the response return value */ | 1245 | /* reuse rirb.res as the response return value */ |
1330 | chip->rirb.res[addr] = azx_readl(chip, IR); | 1246 | chip->rirb.res[addr] = azx_readl(chip, IR); |
1331 | return 0; | 1247 | return 0; |
@@ -1349,13 +1265,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) | |||
1349 | bus->rirb_error = 0; | 1265 | bus->rirb_error = 0; |
1350 | while (timeout--) { | 1266 | while (timeout--) { |
1351 | /* check ICB busy bit */ | 1267 | /* check ICB busy bit */ |
1352 | if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { | 1268 | if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) { |
1353 | /* Clear IRV valid bit */ | 1269 | /* Clear IRV valid bit */ |
1354 | azx_writew(chip, IRS, azx_readw(chip, IRS) | | 1270 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
1355 | ICH6_IRS_VALID); | 1271 | AZX_IRS_VALID); |
1356 | azx_writel(chip, IC, val); | 1272 | azx_writel(chip, IC, val); |
1357 | azx_writew(chip, IRS, azx_readw(chip, IRS) | | 1273 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
1358 | ICH6_IRS_BUSY); | 1274 | AZX_IRS_BUSY); |
1359 | return azx_single_wait_for_response(chip, addr); | 1275 | return azx_single_wait_for_response(chip, addr); |
1360 | } | 1276 | } |
1361 | udelay(1); | 1277 | udelay(1); |
@@ -1584,10 +1500,10 @@ void azx_enter_link_reset(struct azx *chip) | |||
1584 | unsigned long timeout; | 1500 | unsigned long timeout; |
1585 | 1501 | ||
1586 | /* reset controller */ | 1502 | /* reset controller */ |
1587 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); | 1503 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET); |
1588 | 1504 | ||
1589 | timeout = jiffies + msecs_to_jiffies(100); | 1505 | timeout = jiffies + msecs_to_jiffies(100); |
1590 | while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) && | 1506 | while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) && |
1591 | time_before(jiffies, timeout)) | 1507 | time_before(jiffies, timeout)) |
1592 | usleep_range(500, 1000); | 1508 | usleep_range(500, 1000); |
1593 | } | 1509 | } |
@@ -1598,7 +1514,7 @@ static void azx_exit_link_reset(struct azx *chip) | |||
1598 | { | 1514 | { |
1599 | unsigned long timeout; | 1515 | unsigned long timeout; |
1600 | 1516 | ||
1601 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); | 1517 | azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET); |
1602 | 1518 | ||
1603 | timeout = jiffies + msecs_to_jiffies(100); | 1519 | timeout = jiffies + msecs_to_jiffies(100); |
1604 | while (!azx_readb(chip, GCTL) && | 1520 | while (!azx_readb(chip, GCTL) && |
@@ -1639,7 +1555,7 @@ static int azx_reset(struct azx *chip, bool full_reset) | |||
1639 | /* Accept unsolicited responses */ | 1555 | /* Accept unsolicited responses */ |
1640 | if (!chip->single_cmd) | 1556 | if (!chip->single_cmd) |
1641 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | | 1557 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | |
1642 | ICH6_GCTL_UNSOL); | 1558 | AZX_GCTL_UNSOL); |
1643 | 1559 | ||
1644 | /* detect codecs */ | 1560 | /* detect codecs */ |
1645 | if (!chip->codec_mask) { | 1561 | if (!chip->codec_mask) { |
@@ -1656,7 +1572,7 @@ static void azx_int_enable(struct azx *chip) | |||
1656 | { | 1572 | { |
1657 | /* enable controller CIE and GIE */ | 1573 | /* enable controller CIE and GIE */ |
1658 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | | 1574 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | |
1659 | ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN); | 1575 | AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN); |
1660 | } | 1576 | } |
1661 | 1577 | ||
1662 | /* disable interrupts */ | 1578 | /* disable interrupts */ |
@@ -1677,7 +1593,7 @@ static void azx_int_disable(struct azx *chip) | |||
1677 | 1593 | ||
1678 | /* disable controller CIE and GIE */ | 1594 | /* disable controller CIE and GIE */ |
1679 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & | 1595 | azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & |
1680 | ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN)); | 1596 | ~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN)); |
1681 | } | 1597 | } |
1682 | 1598 | ||
1683 | /* clear interrupts */ | 1599 | /* clear interrupts */ |
@@ -1698,7 +1614,7 @@ static void azx_int_clear(struct azx *chip) | |||
1698 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 1614 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
1699 | 1615 | ||
1700 | /* clear int status */ | 1616 | /* clear int status */ |
1701 | azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM); | 1617 | azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM); |
1702 | } | 1618 | } |
1703 | 1619 | ||
1704 | /* | 1620 | /* |
@@ -2030,5 +1946,30 @@ int azx_init_stream(struct azx *chip) | |||
2030 | } | 1946 | } |
2031 | EXPORT_SYMBOL_GPL(azx_init_stream); | 1947 | EXPORT_SYMBOL_GPL(azx_init_stream); |
2032 | 1948 | ||
1949 | /* | ||
1950 | * reboot notifier for hang-up problem at power-down | ||
1951 | */ | ||
1952 | static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) | ||
1953 | { | ||
1954 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
1955 | snd_hda_bus_reboot_notify(chip->bus); | ||
1956 | azx_stop_chip(chip); | ||
1957 | return NOTIFY_OK; | ||
1958 | } | ||
1959 | |||
1960 | void azx_notifier_register(struct azx *chip) | ||
1961 | { | ||
1962 | chip->reboot_notifier.notifier_call = azx_halt; | ||
1963 | register_reboot_notifier(&chip->reboot_notifier); | ||
1964 | } | ||
1965 | EXPORT_SYMBOL_GPL(azx_notifier_register); | ||
1966 | |||
1967 | void azx_notifier_unregister(struct azx *chip) | ||
1968 | { | ||
1969 | if (chip->reboot_notifier.notifier_call) | ||
1970 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
1971 | } | ||
1972 | EXPORT_SYMBOL_GPL(azx_notifier_unregister); | ||
1973 | |||
2033 | MODULE_LICENSE("GPL"); | 1974 | MODULE_LICENSE("GPL"); |
2034 | MODULE_DESCRIPTION("Common HDA driver funcitons"); | 1975 | MODULE_DESCRIPTION("Common HDA driver funcitons"); |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index baf0e77330af..c90d10fd4d8f 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream) | |||
25 | { | 25 | { |
26 | return substream->runtime->private_data; | 26 | return substream->runtime->private_data; |
27 | } | 27 | } |
28 | unsigned int azx_get_position(struct azx *chip, | 28 | unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev); |
29 | struct azx_dev *azx_dev, | 29 | unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev); |
30 | bool with_check); | 30 | unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev); |
31 | 31 | ||
32 | /* Stream control. */ | 32 | /* Stream control. */ |
33 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); | 33 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); |
@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip); | |||
50 | int azx_mixer_create(struct azx *chip); | 50 | int azx_mixer_create(struct azx *chip); |
51 | int azx_init_stream(struct azx *chip); | 51 | int azx_init_stream(struct azx *chip); |
52 | 52 | ||
53 | void azx_notifier_register(struct azx *chip); | ||
54 | void azx_notifier_unregister(struct azx *chip); | ||
55 | |||
53 | #endif /* __SOUND_HDA_CONTROLLER_H */ | 56 | #endif /* __SOUND_HDA_CONTROLLER_H */ |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 46690a7f48f6..e1cd34d9011d 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -167,7 +167,8 @@ static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, | |||
167 | (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \ | 167 | (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \ |
168 | }) | 168 | }) |
169 | 169 | ||
170 | static void hdmi_update_short_audio_desc(struct cea_sad *a, | 170 | static void hdmi_update_short_audio_desc(struct hda_codec *codec, |
171 | struct cea_sad *a, | ||
171 | const unsigned char *buf) | 172 | const unsigned char *buf) |
172 | { | 173 | { |
173 | int i; | 174 | int i; |
@@ -188,8 +189,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
188 | a->format = GRAB_BITS(buf, 0, 3, 4); | 189 | a->format = GRAB_BITS(buf, 0, 3, 4); |
189 | switch (a->format) { | 190 | switch (a->format) { |
190 | case AUDIO_CODING_TYPE_REF_STREAM_HEADER: | 191 | case AUDIO_CODING_TYPE_REF_STREAM_HEADER: |
191 | snd_printd(KERN_INFO | 192 | codec_info(codec, "HDMI: audio coding type 0 not expected\n"); |
192 | "HDMI: audio coding type 0 not expected\n"); | ||
193 | break; | 193 | break; |
194 | 194 | ||
195 | case AUDIO_CODING_TYPE_LPCM: | 195 | case AUDIO_CODING_TYPE_LPCM: |
@@ -233,9 +233,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
233 | a->format = GRAB_BITS(buf, 2, 3, 5); | 233 | a->format = GRAB_BITS(buf, 2, 3, 5); |
234 | if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || | 234 | if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || |
235 | a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { | 235 | a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { |
236 | snd_printd(KERN_INFO | 236 | codec_info(codec, |
237 | "HDMI: audio coding xtype %d not expected\n", | 237 | "HDMI: audio coding xtype %d not expected\n", |
238 | a->format); | 238 | a->format); |
239 | a->format = 0; | 239 | a->format = 0; |
240 | } else | 240 | } else |
241 | a->format += AUDIO_CODING_TYPE_HE_AAC - | 241 | a->format += AUDIO_CODING_TYPE_HE_AAC - |
@@ -247,7 +247,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, | |||
247 | /* | 247 | /* |
248 | * Be careful, ELD buf could be totally rubbish! | 248 | * Be careful, ELD buf could be totally rubbish! |
249 | */ | 249 | */ |
250 | int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | 250 | int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e, |
251 | const unsigned char *buf, int size) | 251 | const unsigned char *buf, int size) |
252 | { | 252 | { |
253 | int mnl; | 253 | int mnl; |
@@ -256,8 +256,7 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | |||
256 | e->eld_ver = GRAB_BITS(buf, 0, 3, 5); | 256 | e->eld_ver = GRAB_BITS(buf, 0, 3, 5); |
257 | if (e->eld_ver != ELD_VER_CEA_861D && | 257 | if (e->eld_ver != ELD_VER_CEA_861D && |
258 | e->eld_ver != ELD_VER_PARTIAL) { | 258 | e->eld_ver != ELD_VER_PARTIAL) { |
259 | snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n", | 259 | codec_info(codec, "HDMI: Unknown ELD version %d\n", e->eld_ver); |
260 | e->eld_ver); | ||
261 | goto out_fail; | 260 | goto out_fail; |
262 | } | 261 | } |
263 | 262 | ||
@@ -280,20 +279,20 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | |||
280 | e->product_id = get_unaligned_le16(buf + 18); | 279 | e->product_id = get_unaligned_le16(buf + 18); |
281 | 280 | ||
282 | if (mnl > ELD_MAX_MNL) { | 281 | if (mnl > ELD_MAX_MNL) { |
283 | snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl); | 282 | codec_info(codec, "HDMI: MNL is reserved value %d\n", mnl); |
284 | goto out_fail; | 283 | goto out_fail; |
285 | } else if (ELD_FIXED_BYTES + mnl > size) { | 284 | } else if (ELD_FIXED_BYTES + mnl > size) { |
286 | snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl); | 285 | codec_info(codec, "HDMI: out of range MNL %d\n", mnl); |
287 | goto out_fail; | 286 | goto out_fail; |
288 | } else | 287 | } else |
289 | strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); | 288 | strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); |
290 | 289 | ||
291 | for (i = 0; i < e->sad_count; i++) { | 290 | for (i = 0; i < e->sad_count; i++) { |
292 | if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { | 291 | if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { |
293 | snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i); | 292 | codec_info(codec, "HDMI: out of range SAD %d\n", i); |
294 | goto out_fail; | 293 | goto out_fail; |
295 | } | 294 | } |
296 | hdmi_update_short_audio_desc(e->sad + i, | 295 | hdmi_update_short_audio_desc(codec, e->sad + i, |
297 | buf + ELD_FIXED_BYTES + mnl + 3 * i); | 296 | buf + ELD_FIXED_BYTES + mnl + 3 * i); |
298 | } | 297 | } |
299 | 298 | ||
@@ -394,7 +393,8 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) | |||
394 | 393 | ||
395 | #define SND_PRINT_RATES_ADVISED_BUFSIZE 80 | 394 | #define SND_PRINT_RATES_ADVISED_BUFSIZE 80 |
396 | 395 | ||
397 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | 396 | static void hdmi_show_short_audio_desc(struct hda_codec *codec, |
397 | struct cea_sad *a) | ||
398 | { | 398 | { |
399 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; | 399 | char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; |
400 | char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits ="; | 400 | char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits ="; |
@@ -412,12 +412,10 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a) | |||
412 | else | 412 | else |
413 | buf2[0] = '\0'; | 413 | buf2[0] = '\0'; |
414 | 414 | ||
415 | _snd_printd(SND_PR_VERBOSE, "HDMI: supports coding type %s:" | 415 | codec_dbg(codec, |
416 | " channels = %d, rates =%s%s\n", | 416 | "HDMI: supports coding type %s: channels = %d, rates =%s%s\n", |
417 | cea_audio_coding_type_names[a->format], | 417 | cea_audio_coding_type_names[a->format], |
418 | a->channels, | 418 | a->channels, buf, buf2); |
419 | buf, | ||
420 | buf2); | ||
421 | } | 419 | } |
422 | 420 | ||
423 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | 421 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) |
@@ -432,22 +430,22 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | |||
432 | buf[j] = '\0'; /* necessary when j == 0 */ | 430 | buf[j] = '\0'; /* necessary when j == 0 */ |
433 | } | 431 | } |
434 | 432 | ||
435 | void snd_hdmi_show_eld(struct parsed_hdmi_eld *e) | 433 | void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e) |
436 | { | 434 | { |
437 | int i; | 435 | int i; |
438 | 436 | ||
439 | _snd_printd(SND_PR_VERBOSE, "HDMI: detected monitor %s at connection type %s\n", | 437 | codec_dbg(codec, "HDMI: detected monitor %s at connection type %s\n", |
440 | e->monitor_name, | 438 | e->monitor_name, |
441 | eld_connection_type_names[e->conn_type]); | 439 | eld_connection_type_names[e->conn_type]); |
442 | 440 | ||
443 | if (e->spk_alloc) { | 441 | if (e->spk_alloc) { |
444 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 442 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
445 | snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); | 443 | snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); |
446 | _snd_printd(SND_PR_VERBOSE, "HDMI: available speakers:%s\n", buf); | 444 | codec_dbg(codec, "HDMI: available speakers:%s\n", buf); |
447 | } | 445 | } |
448 | 446 | ||
449 | for (i = 0; i < e->sad_count; i++) | 447 | for (i = 0; i < e->sad_count; i++) |
450 | hdmi_show_short_audio_desc(e->sad + i); | 448 | hdmi_show_short_audio_desc(codec, e->sad + i); |
451 | } | 449 | } |
452 | 450 | ||
453 | #ifdef CONFIG_PROC_FS | 451 | #ifdef CONFIG_PROC_FS |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 589e47c5aeb3..a24c7b28b000 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -3054,7 +3054,7 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin, | |||
3054 | if (spec->hp_mic_pin == pin) | 3054 | if (spec->hp_mic_pin == pin) |
3055 | spec->hp_mic_mux_idx = imux->num_items; | 3055 | spec->hp_mic_mux_idx = imux->num_items; |
3056 | spec->imux_pins[imux->num_items] = pin; | 3056 | spec->imux_pins[imux->num_items] = pin; |
3057 | snd_hda_add_imux_item(imux, label, cfg_idx, NULL); | 3057 | snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL); |
3058 | imux_added = true; | 3058 | imux_added = true; |
3059 | if (spec->dyn_adc_switch) | 3059 | if (spec->dyn_adc_switch) |
3060 | spec->dyn_adc_idx[imux_idx] = c; | 3060 | spec->dyn_adc_idx[imux_idx] = c; |
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c index 8b4940ba33d6..d4d0375ac181 100644 --- a/sound/pci/hda/hda_i915.c +++ b/sound/pci/hda/hda_i915.c | |||
@@ -28,8 +28,8 @@ | |||
28 | * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N | 28 | * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N |
29 | * The values will be lost when the display power well is disabled. | 29 | * The values will be lost when the display power well is disabled. |
30 | */ | 30 | */ |
31 | #define ICH6_REG_EM4 0x100c | 31 | #define AZX_REG_EM4 0x100c |
32 | #define ICH6_REG_EM5 0x1010 | 32 | #define AZX_REG_EM5 0x1010 |
33 | 33 | ||
34 | static int (*get_power)(void); | 34 | static int (*get_power)(void); |
35 | static int (*put_power)(void); | 35 | static int (*put_power)(void); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b6b4e71a0b0b..75b52c4cd70d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/pci.h> | 45 | #include <linux/pci.h> |
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <linux/reboot.h> | ||
48 | #include <linux/io.h> | 47 | #include <linux/io.h> |
49 | #include <linux/pm_runtime.h> | 48 | #include <linux/pm_runtime.h> |
50 | #include <linux/clocksource.h> | 49 | #include <linux/clocksource.h> |
@@ -66,6 +65,52 @@ | |||
66 | #include "hda_priv.h" | 65 | #include "hda_priv.h" |
67 | #include "hda_i915.h" | 66 | #include "hda_i915.h" |
68 | 67 | ||
68 | /* position fix mode */ | ||
69 | enum { | ||
70 | POS_FIX_AUTO, | ||
71 | POS_FIX_LPIB, | ||
72 | POS_FIX_POSBUF, | ||
73 | POS_FIX_VIACOMBO, | ||
74 | POS_FIX_COMBO, | ||
75 | }; | ||
76 | |||
77 | /* Defines for ATI HD Audio support in SB450 south bridge */ | ||
78 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | ||
79 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | ||
80 | |||
81 | /* Defines for Nvidia HDA support */ | ||
82 | #define NVIDIA_HDA_TRANSREG_ADDR 0x4e | ||
83 | #define NVIDIA_HDA_ENABLE_COHBITS 0x0f | ||
84 | #define NVIDIA_HDA_ISTRM_COH 0x4d | ||
85 | #define NVIDIA_HDA_OSTRM_COH 0x4c | ||
86 | #define NVIDIA_HDA_ENABLE_COHBIT 0x01 | ||
87 | |||
88 | /* Defines for Intel SCH HDA snoop control */ | ||
89 | #define INTEL_SCH_HDA_DEVC 0x78 | ||
90 | #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) | ||
91 | |||
92 | /* Define IN stream 0 FIFO size offset in VIA controller */ | ||
93 | #define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 | ||
94 | /* Define VIA HD Audio Device ID*/ | ||
95 | #define VIA_HDAC_DEVICE_ID 0x3288 | ||
96 | |||
97 | /* max number of SDs */ | ||
98 | /* ICH, ATI and VIA have 4 playback and 4 capture */ | ||
99 | #define ICH6_NUM_CAPTURE 4 | ||
100 | #define ICH6_NUM_PLAYBACK 4 | ||
101 | |||
102 | /* ULI has 6 playback and 5 capture */ | ||
103 | #define ULI_NUM_CAPTURE 5 | ||
104 | #define ULI_NUM_PLAYBACK 6 | ||
105 | |||
106 | /* ATI HDMI may have up to 8 playbacks and 0 capture */ | ||
107 | #define ATIHDMI_NUM_CAPTURE 0 | ||
108 | #define ATIHDMI_NUM_PLAYBACK 8 | ||
109 | |||
110 | /* TERA has 4 playback and 3 capture */ | ||
111 | #define TERA_NUM_CAPTURE 3 | ||
112 | #define TERA_NUM_PLAYBACK 4 | ||
113 | |||
69 | 114 | ||
70 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 115 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
71 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 116 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
@@ -290,8 +335,28 @@ static char *driver_short_names[] = { | |||
290 | 335 | ||
291 | struct hda_intel { | 336 | struct hda_intel { |
292 | struct azx chip; | 337 | struct azx chip; |
293 | }; | ||
294 | 338 | ||
339 | /* for pending irqs */ | ||
340 | struct work_struct irq_pending_work; | ||
341 | |||
342 | /* sync probing */ | ||
343 | struct completion probe_wait; | ||
344 | struct work_struct probe_work; | ||
345 | |||
346 | /* card list (for power_save trigger) */ | ||
347 | struct list_head list; | ||
348 | |||
349 | /* extra flags */ | ||
350 | unsigned int irq_pending_warned:1; | ||
351 | |||
352 | /* VGA-switcheroo setup */ | ||
353 | unsigned int use_vga_switcheroo:1; | ||
354 | unsigned int vga_switcheroo_registered:1; | ||
355 | unsigned int init_failed:1; /* delayed init failed */ | ||
356 | |||
357 | /* secondary power domain for hdmi audio under vga device */ | ||
358 | struct dev_pm_domain hdmi_pm_domain; | ||
359 | }; | ||
295 | 360 | ||
296 | #ifdef CONFIG_X86 | 361 | #ifdef CONFIG_X86 |
297 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) | 362 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) |
@@ -373,7 +438,7 @@ static void azx_init_pci(struct azx *chip) | |||
373 | */ | 438 | */ |
374 | if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { | 439 | if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { |
375 | dev_dbg(chip->card->dev, "Clearing TCSEL\n"); | 440 | dev_dbg(chip->card->dev, "Clearing TCSEL\n"); |
376 | update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); | 441 | update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0); |
377 | } | 442 | } |
378 | 443 | ||
379 | /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, | 444 | /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, |
@@ -421,11 +486,44 @@ static void azx_init_pci(struct azx *chip) | |||
421 | } | 486 | } |
422 | } | 487 | } |
423 | 488 | ||
489 | /* calculate runtime delay from LPIB */ | ||
490 | static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev, | ||
491 | unsigned int pos) | ||
492 | { | ||
493 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
494 | int stream = substream->stream; | ||
495 | unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev); | ||
496 | int delay; | ||
497 | |||
498 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
499 | delay = pos - lpib_pos; | ||
500 | else | ||
501 | delay = lpib_pos - pos; | ||
502 | if (delay < 0) { | ||
503 | if (delay >= azx_dev->delay_negative_threshold) | ||
504 | delay = 0; | ||
505 | else | ||
506 | delay += azx_dev->bufsize; | ||
507 | } | ||
508 | |||
509 | if (delay >= azx_dev->period_bytes) { | ||
510 | dev_info(chip->card->dev, | ||
511 | "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n", | ||
512 | delay, azx_dev->period_bytes); | ||
513 | delay = 0; | ||
514 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | ||
515 | chip->get_delay[stream] = NULL; | ||
516 | } | ||
517 | |||
518 | return bytes_to_frames(substream->runtime, delay); | ||
519 | } | ||
520 | |||
424 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); | 521 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); |
425 | 522 | ||
426 | /* called from IRQ */ | 523 | /* called from IRQ */ |
427 | static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | 524 | static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) |
428 | { | 525 | { |
526 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
429 | int ok; | 527 | int ok; |
430 | 528 | ||
431 | ok = azx_position_ok(chip, azx_dev); | 529 | ok = azx_position_ok(chip, azx_dev); |
@@ -435,7 +533,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
435 | } else if (ok == 0 && chip->bus && chip->bus->workq) { | 533 | } else if (ok == 0 && chip->bus && chip->bus->workq) { |
436 | /* bogus IRQ, process it later */ | 534 | /* bogus IRQ, process it later */ |
437 | azx_dev->irq_pending = 1; | 535 | azx_dev->irq_pending = 1; |
438 | queue_work(chip->bus->workq, &chip->irq_pending_work); | 536 | queue_work(chip->bus->workq, &hda->irq_pending_work); |
439 | } | 537 | } |
440 | return 0; | 538 | return 0; |
441 | } | 539 | } |
@@ -451,6 +549,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
451 | */ | 549 | */ |
452 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | 550 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) |
453 | { | 551 | { |
552 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
553 | int stream = substream->stream; | ||
454 | u32 wallclk; | 554 | u32 wallclk; |
455 | unsigned int pos; | 555 | unsigned int pos; |
456 | 556 | ||
@@ -458,7 +558,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
458 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) | 558 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) |
459 | return -1; /* bogus (too early) interrupt */ | 559 | return -1; /* bogus (too early) interrupt */ |
460 | 560 | ||
461 | pos = azx_get_position(chip, azx_dev, true); | 561 | if (chip->get_position[stream]) |
562 | pos = chip->get_position[stream](chip, azx_dev); | ||
563 | else { /* use the position buffer as default */ | ||
564 | pos = azx_get_pos_posbuf(chip, azx_dev); | ||
565 | if (!pos || pos == (u32)-1) { | ||
566 | dev_info(chip->card->dev, | ||
567 | "Invalid position buffer, using LPIB read method instead.\n"); | ||
568 | chip->get_position[stream] = azx_get_pos_lpib; | ||
569 | pos = azx_get_pos_lpib(chip, azx_dev); | ||
570 | chip->get_delay[stream] = NULL; | ||
571 | } else { | ||
572 | chip->get_position[stream] = azx_get_pos_posbuf; | ||
573 | if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY) | ||
574 | chip->get_delay[stream] = azx_get_delay_from_lpib; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | if (pos >= azx_dev->bufsize) | ||
579 | pos = 0; | ||
462 | 580 | ||
463 | if (WARN_ONCE(!azx_dev->period_bytes, | 581 | if (WARN_ONCE(!azx_dev->period_bytes, |
464 | "hda-intel: zero azx_dev->period_bytes")) | 582 | "hda-intel: zero azx_dev->period_bytes")) |
@@ -476,14 +594,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
476 | */ | 594 | */ |
477 | static void azx_irq_pending_work(struct work_struct *work) | 595 | static void azx_irq_pending_work(struct work_struct *work) |
478 | { | 596 | { |
479 | struct azx *chip = container_of(work, struct azx, irq_pending_work); | 597 | struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work); |
598 | struct azx *chip = &hda->chip; | ||
480 | int i, pending, ok; | 599 | int i, pending, ok; |
481 | 600 | ||
482 | if (!chip->irq_pending_warned) { | 601 | if (!hda->irq_pending_warned) { |
483 | dev_info(chip->card->dev, | 602 | dev_info(chip->card->dev, |
484 | "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n", | 603 | "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n", |
485 | chip->card->number); | 604 | chip->card->number); |
486 | chip->irq_pending_warned = 1; | 605 | hda->irq_pending_warned = 1; |
487 | } | 606 | } |
488 | 607 | ||
489 | for (;;) { | 608 | for (;;) { |
@@ -541,27 +660,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) | |||
541 | return 0; | 660 | return 0; |
542 | } | 661 | } |
543 | 662 | ||
663 | /* get the current DMA position with correction on VIA chips */ | ||
664 | static unsigned int azx_via_get_position(struct azx *chip, | ||
665 | struct azx_dev *azx_dev) | ||
666 | { | ||
667 | unsigned int link_pos, mini_pos, bound_pos; | ||
668 | unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; | ||
669 | unsigned int fifo_size; | ||
670 | |||
671 | link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB); | ||
672 | if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
673 | /* Playback, no problem using link position */ | ||
674 | return link_pos; | ||
675 | } | ||
676 | |||
677 | /* Capture */ | ||
678 | /* For new chipset, | ||
679 | * use mod to get the DMA position just like old chipset | ||
680 | */ | ||
681 | mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); | ||
682 | mod_dma_pos %= azx_dev->period_bytes; | ||
683 | |||
684 | /* azx_dev->fifo_size can't get FIFO size of in stream. | ||
685 | * Get from base address + offset. | ||
686 | */ | ||
687 | fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); | ||
688 | |||
689 | if (azx_dev->insufficient) { | ||
690 | /* Link position never gather than FIFO size */ | ||
691 | if (link_pos <= fifo_size) | ||
692 | return 0; | ||
693 | |||
694 | azx_dev->insufficient = 0; | ||
695 | } | ||
696 | |||
697 | if (link_pos <= fifo_size) | ||
698 | mini_pos = azx_dev->bufsize + link_pos - fifo_size; | ||
699 | else | ||
700 | mini_pos = link_pos - fifo_size; | ||
701 | |||
702 | /* Find nearest previous boudary */ | ||
703 | mod_mini_pos = mini_pos % azx_dev->period_bytes; | ||
704 | mod_link_pos = link_pos % azx_dev->period_bytes; | ||
705 | if (mod_link_pos >= fifo_size) | ||
706 | bound_pos = link_pos - mod_link_pos; | ||
707 | else if (mod_dma_pos >= mod_mini_pos) | ||
708 | bound_pos = mini_pos - mod_mini_pos; | ||
709 | else { | ||
710 | bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; | ||
711 | if (bound_pos >= azx_dev->bufsize) | ||
712 | bound_pos = 0; | ||
713 | } | ||
714 | |||
715 | /* Calculate real DMA position we want */ | ||
716 | return bound_pos + mod_dma_pos; | ||
717 | } | ||
718 | |||
544 | #ifdef CONFIG_PM | 719 | #ifdef CONFIG_PM |
545 | static DEFINE_MUTEX(card_list_lock); | 720 | static DEFINE_MUTEX(card_list_lock); |
546 | static LIST_HEAD(card_list); | 721 | static LIST_HEAD(card_list); |
547 | 722 | ||
548 | static void azx_add_card_list(struct azx *chip) | 723 | static void azx_add_card_list(struct azx *chip) |
549 | { | 724 | { |
725 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
550 | mutex_lock(&card_list_lock); | 726 | mutex_lock(&card_list_lock); |
551 | list_add(&chip->list, &card_list); | 727 | list_add(&hda->list, &card_list); |
552 | mutex_unlock(&card_list_lock); | 728 | mutex_unlock(&card_list_lock); |
553 | } | 729 | } |
554 | 730 | ||
555 | static void azx_del_card_list(struct azx *chip) | 731 | static void azx_del_card_list(struct azx *chip) |
556 | { | 732 | { |
733 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
557 | mutex_lock(&card_list_lock); | 734 | mutex_lock(&card_list_lock); |
558 | list_del_init(&chip->list); | 735 | list_del_init(&hda->list); |
559 | mutex_unlock(&card_list_lock); | 736 | mutex_unlock(&card_list_lock); |
560 | } | 737 | } |
561 | 738 | ||
562 | /* trigger power-save check at writing parameter */ | 739 | /* trigger power-save check at writing parameter */ |
563 | static int param_set_xint(const char *val, const struct kernel_param *kp) | 740 | static int param_set_xint(const char *val, const struct kernel_param *kp) |
564 | { | 741 | { |
742 | struct hda_intel *hda; | ||
565 | struct azx *chip; | 743 | struct azx *chip; |
566 | struct hda_codec *c; | 744 | struct hda_codec *c; |
567 | int prev = power_save; | 745 | int prev = power_save; |
@@ -571,7 +749,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) | |||
571 | return ret; | 749 | return ret; |
572 | 750 | ||
573 | mutex_lock(&card_list_lock); | 751 | mutex_lock(&card_list_lock); |
574 | list_for_each_entry(chip, &card_list, list) { | 752 | list_for_each_entry(hda, &card_list, list) { |
753 | chip = &hda->chip; | ||
575 | if (!chip->bus || chip->disabled) | 754 | if (!chip->bus || chip->disabled) |
576 | continue; | 755 | continue; |
577 | list_for_each_entry(c, &chip->bus->codec_list, list) | 756 | list_for_each_entry(c, &chip->bus->codec_list, list) |
@@ -753,29 +932,6 @@ static const struct dev_pm_ops azx_pm = { | |||
753 | #endif /* CONFIG_PM */ | 932 | #endif /* CONFIG_PM */ |
754 | 933 | ||
755 | 934 | ||
756 | /* | ||
757 | * reboot notifier for hang-up problem at power-down | ||
758 | */ | ||
759 | static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) | ||
760 | { | ||
761 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
762 | snd_hda_bus_reboot_notify(chip->bus); | ||
763 | azx_stop_chip(chip); | ||
764 | return NOTIFY_OK; | ||
765 | } | ||
766 | |||
767 | static void azx_notifier_register(struct azx *chip) | ||
768 | { | ||
769 | chip->reboot_notifier.notifier_call = azx_halt; | ||
770 | register_reboot_notifier(&chip->reboot_notifier); | ||
771 | } | ||
772 | |||
773 | static void azx_notifier_unregister(struct azx *chip) | ||
774 | { | ||
775 | if (chip->reboot_notifier.notifier_call) | ||
776 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
777 | } | ||
778 | |||
779 | static int azx_probe_continue(struct azx *chip); | 935 | static int azx_probe_continue(struct azx *chip); |
780 | 936 | ||
781 | #ifdef SUPPORT_VGA_SWITCHEROO | 937 | #ifdef SUPPORT_VGA_SWITCHEROO |
@@ -786,10 +942,11 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
786 | { | 942 | { |
787 | struct snd_card *card = pci_get_drvdata(pci); | 943 | struct snd_card *card = pci_get_drvdata(pci); |
788 | struct azx *chip = card->private_data; | 944 | struct azx *chip = card->private_data; |
945 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
789 | bool disabled; | 946 | bool disabled; |
790 | 947 | ||
791 | wait_for_completion(&chip->probe_wait); | 948 | wait_for_completion(&hda->probe_wait); |
792 | if (chip->init_failed) | 949 | if (hda->init_failed) |
793 | return; | 950 | return; |
794 | 951 | ||
795 | disabled = (state == VGA_SWITCHEROO_OFF); | 952 | disabled = (state == VGA_SWITCHEROO_OFF); |
@@ -803,7 +960,7 @@ static void azx_vs_set_state(struct pci_dev *pci, | |||
803 | "Start delayed initialization\n"); | 960 | "Start delayed initialization\n"); |
804 | if (azx_probe_continue(chip) < 0) { | 961 | if (azx_probe_continue(chip) < 0) { |
805 | dev_err(chip->card->dev, "initialization error\n"); | 962 | dev_err(chip->card->dev, "initialization error\n"); |
806 | chip->init_failed = true; | 963 | hda->init_failed = true; |
807 | } | 964 | } |
808 | } | 965 | } |
809 | } else { | 966 | } else { |
@@ -833,9 +990,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci) | |||
833 | { | 990 | { |
834 | struct snd_card *card = pci_get_drvdata(pci); | 991 | struct snd_card *card = pci_get_drvdata(pci); |
835 | struct azx *chip = card->private_data; | 992 | struct azx *chip = card->private_data; |
993 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
836 | 994 | ||
837 | wait_for_completion(&chip->probe_wait); | 995 | wait_for_completion(&hda->probe_wait); |
838 | if (chip->init_failed) | 996 | if (hda->init_failed) |
839 | return false; | 997 | return false; |
840 | if (chip->disabled || !chip->bus) | 998 | if (chip->disabled || !chip->bus) |
841 | return true; | 999 | return true; |
@@ -847,11 +1005,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci) | |||
847 | 1005 | ||
848 | static void init_vga_switcheroo(struct azx *chip) | 1006 | static void init_vga_switcheroo(struct azx *chip) |
849 | { | 1007 | { |
1008 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
850 | struct pci_dev *p = get_bound_vga(chip->pci); | 1009 | struct pci_dev *p = get_bound_vga(chip->pci); |
851 | if (p) { | 1010 | if (p) { |
852 | dev_info(chip->card->dev, | 1011 | dev_info(chip->card->dev, |
853 | "Handle VGA-switcheroo audio client\n"); | 1012 | "Handle VGA-switcheroo audio client\n"); |
854 | chip->use_vga_switcheroo = 1; | 1013 | hda->use_vga_switcheroo = 1; |
855 | pci_dev_put(p); | 1014 | pci_dev_put(p); |
856 | } | 1015 | } |
857 | } | 1016 | } |
@@ -863,9 +1022,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { | |||
863 | 1022 | ||
864 | static int register_vga_switcheroo(struct azx *chip) | 1023 | static int register_vga_switcheroo(struct azx *chip) |
865 | { | 1024 | { |
1025 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
866 | int err; | 1026 | int err; |
867 | 1027 | ||
868 | if (!chip->use_vga_switcheroo) | 1028 | if (!hda->use_vga_switcheroo) |
869 | return 0; | 1029 | return 0; |
870 | /* FIXME: currently only handling DIS controller | 1030 | /* FIXME: currently only handling DIS controller |
871 | * is there any machine with two switchable HDMI audio controllers? | 1031 | * is there any machine with two switchable HDMI audio controllers? |
@@ -875,11 +1035,11 @@ static int register_vga_switcheroo(struct azx *chip) | |||
875 | chip->bus != NULL); | 1035 | chip->bus != NULL); |
876 | if (err < 0) | 1036 | if (err < 0) |
877 | return err; | 1037 | return err; |
878 | chip->vga_switcheroo_registered = 1; | 1038 | hda->vga_switcheroo_registered = 1; |
879 | 1039 | ||
880 | /* register as an optimus hdmi audio power domain */ | 1040 | /* register as an optimus hdmi audio power domain */ |
881 | vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev, | 1041 | vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev, |
882 | &chip->hdmi_pm_domain); | 1042 | &hda->hdmi_pm_domain); |
883 | return 0; | 1043 | return 0; |
884 | } | 1044 | } |
885 | #else | 1045 | #else |
@@ -895,7 +1055,6 @@ static int azx_free(struct azx *chip) | |||
895 | { | 1055 | { |
896 | struct pci_dev *pci = chip->pci; | 1056 | struct pci_dev *pci = chip->pci; |
897 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | 1057 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); |
898 | |||
899 | int i; | 1058 | int i; |
900 | 1059 | ||
901 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) | 1060 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) |
@@ -906,13 +1065,13 @@ static int azx_free(struct azx *chip) | |||
906 | 1065 | ||
907 | azx_notifier_unregister(chip); | 1066 | azx_notifier_unregister(chip); |
908 | 1067 | ||
909 | chip->init_failed = 1; /* to be sure */ | 1068 | hda->init_failed = 1; /* to be sure */ |
910 | complete_all(&chip->probe_wait); | 1069 | complete_all(&hda->probe_wait); |
911 | 1070 | ||
912 | if (use_vga_switcheroo(chip)) { | 1071 | if (use_vga_switcheroo(hda)) { |
913 | if (chip->disabled && chip->bus) | 1072 | if (chip->disabled && chip->bus) |
914 | snd_hda_unlock_devices(chip->bus); | 1073 | snd_hda_unlock_devices(chip->bus); |
915 | if (chip->vga_switcheroo_registered) | 1074 | if (hda->vga_switcheroo_registered) |
916 | vga_switcheroo_unregister_client(chip->pci); | 1075 | vga_switcheroo_unregister_client(chip->pci); |
917 | } | 1076 | } |
918 | 1077 | ||
@@ -1048,6 +1207,30 @@ static int check_position_fix(struct azx *chip, int fix) | |||
1048 | return POS_FIX_AUTO; | 1207 | return POS_FIX_AUTO; |
1049 | } | 1208 | } |
1050 | 1209 | ||
1210 | static void assign_position_fix(struct azx *chip, int fix) | ||
1211 | { | ||
1212 | static azx_get_pos_callback_t callbacks[] = { | ||
1213 | [POS_FIX_AUTO] = NULL, | ||
1214 | [POS_FIX_LPIB] = azx_get_pos_lpib, | ||
1215 | [POS_FIX_POSBUF] = azx_get_pos_posbuf, | ||
1216 | [POS_FIX_VIACOMBO] = azx_via_get_position, | ||
1217 | [POS_FIX_COMBO] = azx_get_pos_lpib, | ||
1218 | }; | ||
1219 | |||
1220 | chip->get_position[0] = chip->get_position[1] = callbacks[fix]; | ||
1221 | |||
1222 | /* combo mode uses LPIB only for playback */ | ||
1223 | if (fix == POS_FIX_COMBO) | ||
1224 | chip->get_position[1] = NULL; | ||
1225 | |||
1226 | if (fix == POS_FIX_POSBUF && | ||
1227 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { | ||
1228 | chip->get_delay[0] = chip->get_delay[1] = | ||
1229 | azx_get_delay_from_lpib; | ||
1230 | } | ||
1231 | |||
1232 | } | ||
1233 | |||
1051 | /* | 1234 | /* |
1052 | * black-lists for probe_mask | 1235 | * black-lists for probe_mask |
1053 | */ | 1236 | */ |
@@ -1173,7 +1356,8 @@ static void azx_check_snoop_available(struct azx *chip) | |||
1173 | 1356 | ||
1174 | static void azx_probe_work(struct work_struct *work) | 1357 | static void azx_probe_work(struct work_struct *work) |
1175 | { | 1358 | { |
1176 | azx_probe_continue(container_of(work, struct azx, probe_work)); | 1359 | struct hda_intel *hda = container_of(work, struct hda_intel, probe_work); |
1360 | azx_probe_continue(&hda->chip); | ||
1177 | } | 1361 | } |
1178 | 1362 | ||
1179 | /* | 1363 | /* |
@@ -1216,19 +1400,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1216 | check_msi(chip); | 1400 | check_msi(chip); |
1217 | chip->dev_index = dev; | 1401 | chip->dev_index = dev; |
1218 | chip->jackpoll_ms = jackpoll_ms; | 1402 | chip->jackpoll_ms = jackpoll_ms; |
1219 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); | ||
1220 | INIT_LIST_HEAD(&chip->pcm_list); | 1403 | INIT_LIST_HEAD(&chip->pcm_list); |
1221 | INIT_LIST_HEAD(&chip->list); | 1404 | INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work); |
1405 | INIT_LIST_HEAD(&hda->list); | ||
1222 | init_vga_switcheroo(chip); | 1406 | init_vga_switcheroo(chip); |
1223 | init_completion(&chip->probe_wait); | 1407 | init_completion(&hda->probe_wait); |
1224 | 1408 | ||
1225 | chip->position_fix[0] = chip->position_fix[1] = | 1409 | assign_position_fix(chip, check_position_fix(chip, position_fix[dev])); |
1226 | check_position_fix(chip, position_fix[dev]); | ||
1227 | /* combo mode uses LPIB for playback */ | ||
1228 | if (chip->position_fix[0] == POS_FIX_COMBO) { | ||
1229 | chip->position_fix[0] = POS_FIX_LPIB; | ||
1230 | chip->position_fix[1] = POS_FIX_AUTO; | ||
1231 | } | ||
1232 | 1410 | ||
1233 | check_probe_mask(chip, dev); | 1411 | check_probe_mask(chip, dev); |
1234 | 1412 | ||
@@ -1257,7 +1435,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1257 | } | 1435 | } |
1258 | 1436 | ||
1259 | /* continue probing in work context as may trigger request module */ | 1437 | /* continue probing in work context as may trigger request module */ |
1260 | INIT_WORK(&chip->probe_work, azx_probe_work); | 1438 | INIT_WORK(&hda->probe_work, azx_probe_work); |
1261 | 1439 | ||
1262 | *rchip = chip; | 1440 | *rchip = chip; |
1263 | 1441 | ||
@@ -1315,7 +1493,7 @@ static int azx_first_init(struct azx *chip) | |||
1315 | NULL); | 1493 | NULL); |
1316 | if (p_smbus) { | 1494 | if (p_smbus) { |
1317 | if (p_smbus->revision < 0x30) | 1495 | if (p_smbus->revision < 0x30) |
1318 | gcap &= ~ICH6_GCAP_64OK; | 1496 | gcap &= ~AZX_GCAP_64OK; |
1319 | pci_dev_put(p_smbus); | 1497 | pci_dev_put(p_smbus); |
1320 | } | 1498 | } |
1321 | } | 1499 | } |
@@ -1323,7 +1501,7 @@ static int azx_first_init(struct azx *chip) | |||
1323 | /* disable 64bit DMA address on some devices */ | 1501 | /* disable 64bit DMA address on some devices */ |
1324 | if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { | 1502 | if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { |
1325 | dev_dbg(card->dev, "Disabling 64bit DMA\n"); | 1503 | dev_dbg(card->dev, "Disabling 64bit DMA\n"); |
1326 | gcap &= ~ICH6_GCAP_64OK; | 1504 | gcap &= ~AZX_GCAP_64OK; |
1327 | } | 1505 | } |
1328 | 1506 | ||
1329 | /* disable buffer size rounding to 128-byte multiples if supported */ | 1507 | /* disable buffer size rounding to 128-byte multiples if supported */ |
@@ -1339,7 +1517,7 @@ static int azx_first_init(struct azx *chip) | |||
1339 | } | 1517 | } |
1340 | 1518 | ||
1341 | /* allow 64bit DMA address if supported by H/W */ | 1519 | /* allow 64bit DMA address if supported by H/W */ |
1342 | if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) | 1520 | if ((gcap & AZX_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) |
1343 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); | 1521 | pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); |
1344 | else { | 1522 | else { |
1345 | pci_set_dma_mask(pci, DMA_BIT_MASK(32)); | 1523 | pci_set_dma_mask(pci, DMA_BIT_MASK(32)); |
@@ -1583,6 +1761,7 @@ static int azx_probe(struct pci_dev *pci, | |||
1583 | { | 1761 | { |
1584 | static int dev; | 1762 | static int dev; |
1585 | struct snd_card *card; | 1763 | struct snd_card *card; |
1764 | struct hda_intel *hda; | ||
1586 | struct azx *chip; | 1765 | struct azx *chip; |
1587 | bool schedule_probe; | 1766 | bool schedule_probe; |
1588 | int err; | 1767 | int err; |
@@ -1606,6 +1785,7 @@ static int azx_probe(struct pci_dev *pci, | |||
1606 | if (err < 0) | 1785 | if (err < 0) |
1607 | goto out_free; | 1786 | goto out_free; |
1608 | card->private_data = chip; | 1787 | card->private_data = chip; |
1788 | hda = container_of(chip, struct hda_intel, chip); | ||
1609 | 1789 | ||
1610 | pci_set_drvdata(pci, card); | 1790 | pci_set_drvdata(pci, card); |
1611 | 1791 | ||
@@ -1642,11 +1822,11 @@ static int azx_probe(struct pci_dev *pci, | |||
1642 | #endif | 1822 | #endif |
1643 | 1823 | ||
1644 | if (schedule_probe) | 1824 | if (schedule_probe) |
1645 | schedule_work(&chip->probe_work); | 1825 | schedule_work(&hda->probe_work); |
1646 | 1826 | ||
1647 | dev++; | 1827 | dev++; |
1648 | if (chip->disabled) | 1828 | if (chip->disabled) |
1649 | complete_all(&chip->probe_wait); | 1829 | complete_all(&hda->probe_wait); |
1650 | return 0; | 1830 | return 0; |
1651 | 1831 | ||
1652 | out_free: | 1832 | out_free: |
@@ -1662,6 +1842,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { | |||
1662 | 1842 | ||
1663 | static int azx_probe_continue(struct azx *chip) | 1843 | static int azx_probe_continue(struct azx *chip) |
1664 | { | 1844 | { |
1845 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
1665 | struct pci_dev *pci = chip->pci; | 1846 | struct pci_dev *pci = chip->pci; |
1666 | int dev = chip->dev_index; | 1847 | int dev = chip->dev_index; |
1667 | int err; | 1848 | int err; |
@@ -1735,13 +1916,13 @@ static int azx_probe_continue(struct azx *chip) | |||
1735 | power_down_all_codecs(chip); | 1916 | power_down_all_codecs(chip); |
1736 | azx_notifier_register(chip); | 1917 | azx_notifier_register(chip); |
1737 | azx_add_card_list(chip); | 1918 | azx_add_card_list(chip); |
1738 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo) | 1919 | if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || hda->use_vga_switcheroo) |
1739 | pm_runtime_put_noidle(&pci->dev); | 1920 | pm_runtime_put_noidle(&pci->dev); |
1740 | 1921 | ||
1741 | out_free: | 1922 | out_free: |
1742 | if (err < 0) | 1923 | if (err < 0) |
1743 | chip->init_failed = 1; | 1924 | hda->init_failed = 1; |
1744 | complete_all(&chip->probe_wait); | 1925 | complete_all(&hda->probe_wait); |
1745 | return err; | 1926 | return err; |
1746 | } | 1927 | } |
1747 | 1928 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 4e2d4863daa1..aa374ad4b5d0 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -268,7 +268,8 @@ int snd_hda_input_mux_put(struct hda_codec *codec, | |||
268 | const struct hda_input_mux *imux, | 268 | const struct hda_input_mux *imux, |
269 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, | 269 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, |
270 | unsigned int *cur_val); | 270 | unsigned int *cur_val); |
271 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | 271 | int snd_hda_add_imux_item(struct hda_codec *codec, |
272 | struct hda_input_mux *imux, const char *label, | ||
272 | int index, int *type_index_ret); | 273 | int index, int *type_index_ret); |
273 | 274 | ||
274 | /* | 275 | /* |
@@ -773,9 +774,9 @@ struct hdmi_eld { | |||
773 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); | 774 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); |
774 | int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, | 775 | int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid, |
775 | unsigned char *buf, int *eld_size); | 776 | unsigned char *buf, int *eld_size); |
776 | int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e, | 777 | int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e, |
777 | const unsigned char *buf, int size); | 778 | const unsigned char *buf, int size); |
778 | void snd_hdmi_show_eld(struct parsed_hdmi_eld *e); | 779 | void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e); |
779 | void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e, | 780 | void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e, |
780 | struct hda_pcm_stream *hinfo); | 781 | struct hda_pcm_stream *hinfo); |
781 | 782 | ||
diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h index 4a7cb01fa912..33eb5d027d38 100644 --- a/sound/pci/hda/hda_priv.h +++ b/sound/pci/hda/hda_priv.h | |||
@@ -22,107 +22,87 @@ | |||
22 | /* | 22 | /* |
23 | * registers | 23 | * registers |
24 | */ | 24 | */ |
25 | #define ICH6_REG_GCAP 0x00 | 25 | #define AZX_REG_GCAP 0x00 |
26 | #define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */ | 26 | #define AZX_GCAP_64OK (1 << 0) /* 64bit address support */ |
27 | #define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */ | 27 | #define AZX_GCAP_NSDO (3 << 1) /* # of serial data out signals */ |
28 | #define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */ | 28 | #define AZX_GCAP_BSS (31 << 3) /* # of bidirectional streams */ |
29 | #define ICH6_GCAP_ISS (15 << 8) /* # of input streams */ | 29 | #define AZX_GCAP_ISS (15 << 8) /* # of input streams */ |
30 | #define ICH6_GCAP_OSS (15 << 12) /* # of output streams */ | 30 | #define AZX_GCAP_OSS (15 << 12) /* # of output streams */ |
31 | #define ICH6_REG_VMIN 0x02 | 31 | #define AZX_REG_VMIN 0x02 |
32 | #define ICH6_REG_VMAJ 0x03 | 32 | #define AZX_REG_VMAJ 0x03 |
33 | #define ICH6_REG_OUTPAY 0x04 | 33 | #define AZX_REG_OUTPAY 0x04 |
34 | #define ICH6_REG_INPAY 0x06 | 34 | #define AZX_REG_INPAY 0x06 |
35 | #define ICH6_REG_GCTL 0x08 | 35 | #define AZX_REG_GCTL 0x08 |
36 | #define ICH6_GCTL_RESET (1 << 0) /* controller reset */ | 36 | #define AZX_GCTL_RESET (1 << 0) /* controller reset */ |
37 | #define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */ | 37 | #define AZX_GCTL_FCNTRL (1 << 1) /* flush control */ |
38 | #define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ | 38 | #define AZX_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ |
39 | #define ICH6_REG_WAKEEN 0x0c | 39 | #define AZX_REG_WAKEEN 0x0c |
40 | #define ICH6_REG_STATESTS 0x0e | 40 | #define AZX_REG_STATESTS 0x0e |
41 | #define ICH6_REG_GSTS 0x10 | 41 | #define AZX_REG_GSTS 0x10 |
42 | #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ | 42 | #define AZX_GSTS_FSTS (1 << 1) /* flush status */ |
43 | #define ICH6_REG_INTCTL 0x20 | 43 | #define AZX_REG_INTCTL 0x20 |
44 | #define ICH6_REG_INTSTS 0x24 | 44 | #define AZX_REG_INTSTS 0x24 |
45 | #define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ | 45 | #define AZX_REG_WALLCLK 0x30 /* 24Mhz source */ |
46 | #define ICH6_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ | 46 | #define AZX_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ |
47 | #define ICH6_REG_SSYNC 0x38 | 47 | #define AZX_REG_SSYNC 0x38 |
48 | #define ICH6_REG_CORBLBASE 0x40 | 48 | #define AZX_REG_CORBLBASE 0x40 |
49 | #define ICH6_REG_CORBUBASE 0x44 | 49 | #define AZX_REG_CORBUBASE 0x44 |
50 | #define ICH6_REG_CORBWP 0x48 | 50 | #define AZX_REG_CORBWP 0x48 |
51 | #define ICH6_REG_CORBRP 0x4a | 51 | #define AZX_REG_CORBRP 0x4a |
52 | #define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */ | 52 | #define AZX_CORBRP_RST (1 << 15) /* read pointer reset */ |
53 | #define ICH6_REG_CORBCTL 0x4c | 53 | #define AZX_REG_CORBCTL 0x4c |
54 | #define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */ | 54 | #define AZX_CORBCTL_RUN (1 << 1) /* enable DMA */ |
55 | #define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ | 55 | #define AZX_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ |
56 | #define ICH6_REG_CORBSTS 0x4d | 56 | #define AZX_REG_CORBSTS 0x4d |
57 | #define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */ | 57 | #define AZX_CORBSTS_CMEI (1 << 0) /* memory error indication */ |
58 | #define ICH6_REG_CORBSIZE 0x4e | 58 | #define AZX_REG_CORBSIZE 0x4e |
59 | 59 | ||
60 | #define ICH6_REG_RIRBLBASE 0x50 | 60 | #define AZX_REG_RIRBLBASE 0x50 |
61 | #define ICH6_REG_RIRBUBASE 0x54 | 61 | #define AZX_REG_RIRBUBASE 0x54 |
62 | #define ICH6_REG_RIRBWP 0x58 | 62 | #define AZX_REG_RIRBWP 0x58 |
63 | #define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */ | 63 | #define AZX_RIRBWP_RST (1 << 15) /* write pointer reset */ |
64 | #define ICH6_REG_RINTCNT 0x5a | 64 | #define AZX_REG_RINTCNT 0x5a |
65 | #define ICH6_REG_RIRBCTL 0x5c | 65 | #define AZX_REG_RIRBCTL 0x5c |
66 | #define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ | 66 | #define AZX_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ |
67 | #define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */ | 67 | #define AZX_RBCTL_DMA_EN (1 << 1) /* enable DMA */ |
68 | #define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ | 68 | #define AZX_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ |
69 | #define ICH6_REG_RIRBSTS 0x5d | 69 | #define AZX_REG_RIRBSTS 0x5d |
70 | #define ICH6_RBSTS_IRQ (1 << 0) /* response irq */ | 70 | #define AZX_RBSTS_IRQ (1 << 0) /* response irq */ |
71 | #define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */ | 71 | #define AZX_RBSTS_OVERRUN (1 << 2) /* overrun irq */ |
72 | #define ICH6_REG_RIRBSIZE 0x5e | 72 | #define AZX_REG_RIRBSIZE 0x5e |
73 | 73 | ||
74 | #define ICH6_REG_IC 0x60 | 74 | #define AZX_REG_IC 0x60 |
75 | #define ICH6_REG_IR 0x64 | 75 | #define AZX_REG_IR 0x64 |
76 | #define ICH6_REG_IRS 0x68 | 76 | #define AZX_REG_IRS 0x68 |
77 | #define ICH6_IRS_VALID (1<<1) | 77 | #define AZX_IRS_VALID (1<<1) |
78 | #define ICH6_IRS_BUSY (1<<0) | 78 | #define AZX_IRS_BUSY (1<<0) |
79 | 79 | ||
80 | #define ICH6_REG_DPLBASE 0x70 | 80 | #define AZX_REG_DPLBASE 0x70 |
81 | #define ICH6_REG_DPUBASE 0x74 | 81 | #define AZX_REG_DPUBASE 0x74 |
82 | #define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */ | 82 | #define AZX_DPLBASE_ENABLE 0x1 /* Enable position buffer */ |
83 | 83 | ||
84 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 84 | /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
85 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | 85 | enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; |
86 | 86 | ||
87 | /* stream register offsets from stream base */ | 87 | /* stream register offsets from stream base */ |
88 | #define ICH6_REG_SD_CTL 0x00 | 88 | #define AZX_REG_SD_CTL 0x00 |
89 | #define ICH6_REG_SD_STS 0x03 | 89 | #define AZX_REG_SD_STS 0x03 |
90 | #define ICH6_REG_SD_LPIB 0x04 | 90 | #define AZX_REG_SD_LPIB 0x04 |
91 | #define ICH6_REG_SD_CBL 0x08 | 91 | #define AZX_REG_SD_CBL 0x08 |
92 | #define ICH6_REG_SD_LVI 0x0c | 92 | #define AZX_REG_SD_LVI 0x0c |
93 | #define ICH6_REG_SD_FIFOW 0x0e | 93 | #define AZX_REG_SD_FIFOW 0x0e |
94 | #define ICH6_REG_SD_FIFOSIZE 0x10 | 94 | #define AZX_REG_SD_FIFOSIZE 0x10 |
95 | #define ICH6_REG_SD_FORMAT 0x12 | 95 | #define AZX_REG_SD_FORMAT 0x12 |
96 | #define ICH6_REG_SD_BDLPL 0x18 | 96 | #define AZX_REG_SD_BDLPL 0x18 |
97 | #define ICH6_REG_SD_BDLPU 0x1c | 97 | #define AZX_REG_SD_BDLPU 0x1c |
98 | 98 | ||
99 | /* PCI space */ | 99 | /* PCI space */ |
100 | #define ICH6_PCIREG_TCSEL 0x44 | 100 | #define AZX_PCIREG_TCSEL 0x44 |
101 | 101 | ||
102 | /* | 102 | /* |
103 | * other constants | 103 | * other constants |
104 | */ | 104 | */ |
105 | 105 | ||
106 | /* max number of SDs */ | ||
107 | /* ICH, ATI and VIA have 4 playback and 4 capture */ | ||
108 | #define ICH6_NUM_CAPTURE 4 | ||
109 | #define ICH6_NUM_PLAYBACK 4 | ||
110 | |||
111 | /* ULI has 6 playback and 5 capture */ | ||
112 | #define ULI_NUM_CAPTURE 5 | ||
113 | #define ULI_NUM_PLAYBACK 6 | ||
114 | |||
115 | /* ATI HDMI may have up to 8 playbacks and 0 capture */ | ||
116 | #define ATIHDMI_NUM_CAPTURE 0 | ||
117 | #define ATIHDMI_NUM_PLAYBACK 8 | ||
118 | |||
119 | /* TERA has 4 playback and 3 capture */ | ||
120 | #define TERA_NUM_CAPTURE 3 | ||
121 | #define TERA_NUM_PLAYBACK 4 | ||
122 | |||
123 | /* this number is statically defined for simplicity */ | ||
124 | #define MAX_AZX_DEV 16 | ||
125 | |||
126 | /* max number of fragments - we may use more if allocating more pages for BDL */ | 106 | /* max number of fragments - we may use more if allocating more pages for BDL */ |
127 | #define BDL_SIZE 4096 | 107 | #define BDL_SIZE 4096 |
128 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) | 108 | #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) |
@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
160 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ | 140 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ |
161 | 141 | ||
162 | /* INTCTL and INTSTS */ | 142 | /* INTCTL and INTSTS */ |
163 | #define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ | 143 | #define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */ |
164 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | 144 | #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ |
165 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | 145 | #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ |
166 | 146 | ||
167 | /* below are so far hardcoded - should read registers in future */ | 147 | /* below are so far hardcoded - should read registers in future */ |
168 | #define ICH6_MAX_CORB_ENTRIES 256 | 148 | #define AZX_MAX_CORB_ENTRIES 256 |
169 | #define ICH6_MAX_RIRB_ENTRIES 256 | 149 | #define AZX_MAX_RIRB_ENTRIES 256 |
170 | 150 | ||
171 | /* driver quirks (capabilities) */ | 151 | /* driver quirks (capabilities) */ |
172 | /* bits 0-7 are used for indicating driver type */ | 152 | /* bits 0-7 are used for indicating driver type */ |
@@ -191,35 +171,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
191 | #define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ | 171 | #define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ |
192 | #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ | 172 | #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ |
193 | 173 | ||
194 | /* position fix mode */ | ||
195 | enum { | ||
196 | POS_FIX_AUTO, | ||
197 | POS_FIX_LPIB, | ||
198 | POS_FIX_POSBUF, | ||
199 | POS_FIX_VIACOMBO, | ||
200 | POS_FIX_COMBO, | ||
201 | }; | ||
202 | |||
203 | /* Defines for ATI HD Audio support in SB450 south bridge */ | ||
204 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | ||
205 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | ||
206 | |||
207 | /* Defines for Nvidia HDA support */ | ||
208 | #define NVIDIA_HDA_TRANSREG_ADDR 0x4e | ||
209 | #define NVIDIA_HDA_ENABLE_COHBITS 0x0f | ||
210 | #define NVIDIA_HDA_ISTRM_COH 0x4d | ||
211 | #define NVIDIA_HDA_OSTRM_COH 0x4c | ||
212 | #define NVIDIA_HDA_ENABLE_COHBIT 0x01 | ||
213 | |||
214 | /* Defines for Intel SCH HDA snoop control */ | ||
215 | #define INTEL_SCH_HDA_DEVC 0x78 | ||
216 | #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) | ||
217 | |||
218 | /* Define IN stream 0 FIFO size offset in VIA controller */ | ||
219 | #define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 | ||
220 | /* Define VIA HD Audio Device ID*/ | ||
221 | #define VIA_HDAC_DEVICE_ID 0x3288 | ||
222 | |||
223 | /* HD Audio class code */ | 174 | /* HD Audio class code */ |
224 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 | 175 | #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 |
225 | 176 | ||
@@ -324,6 +275,9 @@ struct azx_pcm { | |||
324 | struct list_head list; | 275 | struct list_head list; |
325 | }; | 276 | }; |
326 | 277 | ||
278 | typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *); | ||
279 | typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos); | ||
280 | |||
327 | struct azx { | 281 | struct azx { |
328 | struct snd_card *card; | 282 | struct snd_card *card; |
329 | struct pci_dev *pci; | 283 | struct pci_dev *pci; |
@@ -342,6 +296,10 @@ struct azx { | |||
342 | /* Register interaction. */ | 296 | /* Register interaction. */ |
343 | const struct hda_controller_ops *ops; | 297 | const struct hda_controller_ops *ops; |
344 | 298 | ||
299 | /* position adjustment callbacks */ | ||
300 | azx_get_pos_callback_t get_position[2]; | ||
301 | azx_get_delay_callback_t get_delay[2]; | ||
302 | |||
345 | /* pci resources */ | 303 | /* pci resources */ |
346 | unsigned long addr; | 304 | unsigned long addr; |
347 | void __iomem *remap_addr; | 305 | void __iomem *remap_addr; |
@@ -350,7 +308,6 @@ struct azx { | |||
350 | /* locks */ | 308 | /* locks */ |
351 | spinlock_t reg_lock; | 309 | spinlock_t reg_lock; |
352 | struct mutex open_mutex; /* Prevents concurrent open/close operations */ | 310 | struct mutex open_mutex; /* Prevents concurrent open/close operations */ |
353 | struct completion probe_wait; | ||
354 | 311 | ||
355 | /* streams (x num_streams) */ | 312 | /* streams (x num_streams) */ |
356 | struct azx_dev *azx_dev; | 313 | struct azx_dev *azx_dev; |
@@ -377,7 +334,6 @@ struct azx { | |||
377 | #endif | 334 | #endif |
378 | 335 | ||
379 | /* flags */ | 336 | /* flags */ |
380 | int position_fix[2]; /* for both playback/capture streams */ | ||
381 | const int *bdl_pos_adj; | 337 | const int *bdl_pos_adj; |
382 | int poll_count; | 338 | int poll_count; |
383 | unsigned int running:1; | 339 | unsigned int running:1; |
@@ -385,46 +341,23 @@ struct azx { | |||
385 | unsigned int single_cmd:1; | 341 | unsigned int single_cmd:1; |
386 | unsigned int polling_mode:1; | 342 | unsigned int polling_mode:1; |
387 | unsigned int msi:1; | 343 | unsigned int msi:1; |
388 | unsigned int irq_pending_warned:1; | ||
389 | unsigned int probing:1; /* codec probing phase */ | 344 | unsigned int probing:1; /* codec probing phase */ |
390 | unsigned int snoop:1; | 345 | unsigned int snoop:1; |
391 | unsigned int align_buffer_size:1; | 346 | unsigned int align_buffer_size:1; |
392 | unsigned int region_requested:1; | 347 | unsigned int region_requested:1; |
393 | |||
394 | /* VGA-switcheroo setup */ | ||
395 | unsigned int use_vga_switcheroo:1; | ||
396 | unsigned int vga_switcheroo_registered:1; | ||
397 | unsigned int init_failed:1; /* delayed init failed */ | ||
398 | unsigned int disabled:1; /* disabled by VGA-switcher */ | 348 | unsigned int disabled:1; /* disabled by VGA-switcher */ |
399 | 349 | ||
400 | /* for debugging */ | 350 | /* for debugging */ |
401 | unsigned int last_cmd[AZX_MAX_CODECS]; | 351 | unsigned int last_cmd[AZX_MAX_CODECS]; |
402 | 352 | ||
403 | /* for pending irqs */ | ||
404 | struct work_struct irq_pending_work; | ||
405 | |||
406 | struct work_struct probe_work; | ||
407 | |||
408 | /* reboot notifier (for mysterious hangup problem at power-down) */ | 353 | /* reboot notifier (for mysterious hangup problem at power-down) */ |
409 | struct notifier_block reboot_notifier; | 354 | struct notifier_block reboot_notifier; |
410 | 355 | ||
411 | /* card list (for power_save trigger) */ | ||
412 | struct list_head list; | ||
413 | |||
414 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 356 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
415 | struct azx_dev saved_azx_dev; | 357 | struct azx_dev saved_azx_dev; |
416 | #endif | 358 | #endif |
417 | |||
418 | /* secondary power domain for hdmi audio under vga device */ | ||
419 | struct dev_pm_domain hdmi_pm_domain; | ||
420 | }; | 359 | }; |
421 | 360 | ||
422 | #ifdef CONFIG_SND_VERBOSE_PRINTK | ||
423 | #define SFX /* nop */ | ||
424 | #else | ||
425 | #define SFX "hda-intel " | ||
426 | #endif | ||
427 | |||
428 | #ifdef CONFIG_X86 | 361 | #ifdef CONFIG_X86 |
429 | #define azx_snoop(chip) ((chip)->snoop) | 362 | #define azx_snoop(chip) ((chip)->snoop) |
430 | #else | 363 | #else |
@@ -436,29 +369,29 @@ struct azx { | |||
436 | */ | 369 | */ |
437 | 370 | ||
438 | #define azx_writel(chip, reg, value) \ | 371 | #define azx_writel(chip, reg, value) \ |
439 | ((chip)->ops->reg_writel(value, (chip)->remap_addr + ICH6_REG_##reg)) | 372 | ((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg)) |
440 | #define azx_readl(chip, reg) \ | 373 | #define azx_readl(chip, reg) \ |
441 | ((chip)->ops->reg_readl((chip)->remap_addr + ICH6_REG_##reg)) | 374 | ((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg)) |
442 | #define azx_writew(chip, reg, value) \ | 375 | #define azx_writew(chip, reg, value) \ |
443 | ((chip)->ops->reg_writew(value, (chip)->remap_addr + ICH6_REG_##reg)) | 376 | ((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg)) |
444 | #define azx_readw(chip, reg) \ | 377 | #define azx_readw(chip, reg) \ |
445 | ((chip)->ops->reg_readw((chip)->remap_addr + ICH6_REG_##reg)) | 378 | ((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg)) |
446 | #define azx_writeb(chip, reg, value) \ | 379 | #define azx_writeb(chip, reg, value) \ |
447 | ((chip)->ops->reg_writeb(value, (chip)->remap_addr + ICH6_REG_##reg)) | 380 | ((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg)) |
448 | #define azx_readb(chip, reg) \ | 381 | #define azx_readb(chip, reg) \ |
449 | ((chip)->ops->reg_readb((chip)->remap_addr + ICH6_REG_##reg)) | 382 | ((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg)) |
450 | 383 | ||
451 | #define azx_sd_writel(chip, dev, reg, value) \ | 384 | #define azx_sd_writel(chip, dev, reg, value) \ |
452 | ((chip)->ops->reg_writel(value, (dev)->sd_addr + ICH6_REG_##reg)) | 385 | ((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg)) |
453 | #define azx_sd_readl(chip, dev, reg) \ | 386 | #define azx_sd_readl(chip, dev, reg) \ |
454 | ((chip)->ops->reg_readl((dev)->sd_addr + ICH6_REG_##reg)) | 387 | ((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg)) |
455 | #define azx_sd_writew(chip, dev, reg, value) \ | 388 | #define azx_sd_writew(chip, dev, reg, value) \ |
456 | ((chip)->ops->reg_writew(value, (dev)->sd_addr + ICH6_REG_##reg)) | 389 | ((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg)) |
457 | #define azx_sd_readw(chip, dev, reg) \ | 390 | #define azx_sd_readw(chip, dev, reg) \ |
458 | ((chip)->ops->reg_readw((dev)->sd_addr + ICH6_REG_##reg)) | 391 | ((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg)) |
459 | #define azx_sd_writeb(chip, dev, reg, value) \ | 392 | #define azx_sd_writeb(chip, dev, reg, value) \ |
460 | ((chip)->ops->reg_writeb(value, (dev)->sd_addr + ICH6_REG_##reg)) | 393 | ((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg)) |
461 | #define azx_sd_readb(chip, dev, reg) \ | 394 | #define azx_sd_readb(chip, dev, reg) \ |
462 | ((chip)->ops->reg_readb((dev)->sd_addr + ICH6_REG_##reg)) | 395 | ((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg)) |
463 | 396 | ||
464 | #endif /* __SOUND_HDA_PRIV_H */ | 397 | #endif /* __SOUND_HDA_PRIV_H */ |
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index a366ba9293a8..dc4bb21ed17b 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
32 | #include <linux/reboot.h> | ||
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | #include <linux/time.h> | 33 | #include <linux/time.h> |
35 | 34 | ||
@@ -272,13 +271,9 @@ static int hda_tegra_resume(struct device *dev) | |||
272 | struct snd_card *card = dev_get_drvdata(dev); | 271 | struct snd_card *card = dev_get_drvdata(dev); |
273 | struct azx *chip = card->private_data; | 272 | struct azx *chip = card->private_data; |
274 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); | 273 | struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); |
275 | int status; | ||
276 | 274 | ||
277 | hda_tegra_enable_clocks(hda); | 275 | hda_tegra_enable_clocks(hda); |
278 | 276 | ||
279 | /* Read STATESTS before controller reset */ | ||
280 | status = azx_readw(chip, STATESTS); | ||
281 | |||
282 | hda_tegra_init(hda); | 277 | hda_tegra_init(hda); |
283 | 278 | ||
284 | azx_init_chip(chip, 1); | 279 | azx_init_chip(chip, 1); |
@@ -295,30 +290,6 @@ static const struct dev_pm_ops hda_tegra_pm = { | |||
295 | }; | 290 | }; |
296 | 291 | ||
297 | /* | 292 | /* |
298 | * reboot notifier for hang-up problem at power-down | ||
299 | */ | ||
300 | static int hda_tegra_halt(struct notifier_block *nb, unsigned long event, | ||
301 | void *buf) | ||
302 | { | ||
303 | struct azx *chip = container_of(nb, struct azx, reboot_notifier); | ||
304 | snd_hda_bus_reboot_notify(chip->bus); | ||
305 | azx_stop_chip(chip); | ||
306 | return NOTIFY_OK; | ||
307 | } | ||
308 | |||
309 | static void hda_tegra_notifier_register(struct azx *chip) | ||
310 | { | ||
311 | chip->reboot_notifier.notifier_call = hda_tegra_halt; | ||
312 | register_reboot_notifier(&chip->reboot_notifier); | ||
313 | } | ||
314 | |||
315 | static void hda_tegra_notifier_unregister(struct azx *chip) | ||
316 | { | ||
317 | if (chip->reboot_notifier.notifier_call) | ||
318 | unregister_reboot_notifier(&chip->reboot_notifier); | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * destructor | 293 | * destructor |
323 | */ | 294 | */ |
324 | static int hda_tegra_dev_free(struct snd_device *device) | 295 | static int hda_tegra_dev_free(struct snd_device *device) |
@@ -326,7 +297,7 @@ static int hda_tegra_dev_free(struct snd_device *device) | |||
326 | int i; | 297 | int i; |
327 | struct azx *chip = device->device_data; | 298 | struct azx *chip = device->device_data; |
328 | 299 | ||
329 | hda_tegra_notifier_unregister(chip); | 300 | azx_notifier_unregister(chip); |
330 | 301 | ||
331 | if (chip->initialized) { | 302 | if (chip->initialized) { |
332 | for (i = 0; i < chip->num_streams; i++) | 303 | for (i = 0; i < chip->num_streams; i++) |
@@ -478,10 +449,7 @@ static int hda_tegra_create(struct snd_card *card, | |||
478 | chip->driver_type = driver_caps & 0xff; | 449 | chip->driver_type = driver_caps & 0xff; |
479 | chip->dev_index = 0; | 450 | chip->dev_index = 0; |
480 | INIT_LIST_HEAD(&chip->pcm_list); | 451 | INIT_LIST_HEAD(&chip->pcm_list); |
481 | INIT_LIST_HEAD(&chip->list); | ||
482 | 452 | ||
483 | chip->position_fix[0] = POS_FIX_AUTO; | ||
484 | chip->position_fix[1] = POS_FIX_AUTO; | ||
485 | chip->codec_probe_mask = -1; | 453 | chip->codec_probe_mask = -1; |
486 | 454 | ||
487 | chip->single_cmd = false; | 455 | chip->single_cmd = false; |
@@ -559,7 +527,7 @@ static int hda_tegra_probe(struct platform_device *pdev) | |||
559 | 527 | ||
560 | chip->running = 1; | 528 | chip->running = 1; |
561 | power_down_all_codecs(chip); | 529 | power_down_all_codecs(chip); |
562 | hda_tegra_notifier_register(chip); | 530 | azx_notifier_register(chip); |
563 | 531 | ||
564 | return 0; | 532 | return 0; |
565 | 533 | ||
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 092f2bd030bd..4f3aba78f720 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -2046,14 +2046,14 @@ enum dma_state { | |||
2046 | DMA_STATE_RUN = 1 | 2046 | DMA_STATE_RUN = 1 |
2047 | }; | 2047 | }; |
2048 | 2048 | ||
2049 | static int dma_convert_to_hda_format( | 2049 | static int dma_convert_to_hda_format(struct hda_codec *codec, |
2050 | unsigned int sample_rate, | 2050 | unsigned int sample_rate, |
2051 | unsigned short channels, | 2051 | unsigned short channels, |
2052 | unsigned short *hda_format) | 2052 | unsigned short *hda_format) |
2053 | { | 2053 | { |
2054 | unsigned int format_val; | 2054 | unsigned int format_val; |
2055 | 2055 | ||
2056 | format_val = snd_hda_calc_stream_format( | 2056 | format_val = snd_hda_calc_stream_format(codec, |
2057 | sample_rate, | 2057 | sample_rate, |
2058 | channels, | 2058 | channels, |
2059 | SNDRV_PCM_FORMAT_S32_LE, | 2059 | SNDRV_PCM_FORMAT_S32_LE, |
@@ -2452,7 +2452,7 @@ static int dspxfr_image(struct hda_codec *codec, | |||
2452 | } | 2452 | } |
2453 | 2453 | ||
2454 | dma_engine->codec = codec; | 2454 | dma_engine->codec = codec; |
2455 | dma_convert_to_hda_format(sample_rate, channels, &hda_format); | 2455 | dma_convert_to_hda_format(codec, sample_rate, channels, &hda_format); |
2456 | dma_engine->m_converter_format = hda_format; | 2456 | dma_engine->m_converter_format = hda_format; |
2457 | dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY : | 2457 | dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY : |
2458 | DSP_DMA_WRITE_BUFLEN_INIT) * 2; | 2458 | DSP_DMA_WRITE_BUFLEN_INIT) * 2; |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 061ea5965dd5..ed3d133ffbb6 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -31,550 +31,11 @@ | |||
31 | #include "hda_jack.h" | 31 | #include "hda_jack.h" |
32 | #include "hda_generic.h" | 32 | #include "hda_generic.h" |
33 | 33 | ||
34 | #undef ENABLE_CMI_STATIC_QUIRKS | ||
35 | |||
36 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
37 | #define NUM_PINS 11 | ||
38 | |||
39 | |||
40 | /* board config type */ | ||
41 | enum { | ||
42 | CMI_MINIMAL, /* back 3-jack */ | ||
43 | CMI_MIN_FP, /* back 3-jack + front-panel 2-jack */ | ||
44 | CMI_FULL, /* back 6-jack + front-panel 2-jack */ | ||
45 | CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */ | ||
46 | CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */ | ||
47 | CMI_AUTO, /* let driver guess it */ | ||
48 | CMI_MODELS | ||
49 | }; | ||
50 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
51 | |||
52 | struct cmi_spec { | 34 | struct cmi_spec { |
53 | struct hda_gen_spec gen; | 35 | struct hda_gen_spec gen; |
54 | |||
55 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
56 | /* below are only for static models */ | ||
57 | |||
58 | int board_config; | ||
59 | unsigned int no_line_in: 1; /* no line-in (5-jack) */ | ||
60 | unsigned int front_panel: 1; /* has front-panel 2-jack */ | ||
61 | |||
62 | /* playback */ | ||
63 | struct hda_multi_out multiout; | ||
64 | hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS]; /* NID for each DAC */ | ||
65 | int num_dacs; | ||
66 | |||
67 | /* capture */ | ||
68 | const hda_nid_t *adc_nids; | ||
69 | hda_nid_t dig_in_nid; | ||
70 | |||
71 | /* capture source */ | ||
72 | const struct hda_input_mux *input_mux; | ||
73 | unsigned int cur_mux[2]; | ||
74 | |||
75 | /* channel mode */ | ||
76 | int num_channel_modes; | ||
77 | const struct hda_channel_mode *channel_modes; | ||
78 | |||
79 | struct hda_pcm pcm_rec[2]; /* PCM information */ | ||
80 | |||
81 | /* pin default configuration */ | ||
82 | hda_nid_t pin_nid[NUM_PINS]; | ||
83 | unsigned int def_conf[NUM_PINS]; | ||
84 | unsigned int pin_def_confs; | ||
85 | |||
86 | /* multichannel pins */ | ||
87 | struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ | ||
88 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
89 | }; | ||
90 | |||
91 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
92 | /* | ||
93 | * input MUX | ||
94 | */ | ||
95 | static int cmi_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
96 | { | ||
97 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
98 | struct cmi_spec *spec = codec->spec; | ||
99 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
100 | } | ||
101 | |||
102 | static int cmi_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
103 | { | ||
104 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
105 | struct cmi_spec *spec = codec->spec; | ||
106 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
107 | |||
108 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
113 | { | ||
114 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
115 | struct cmi_spec *spec = codec->spec; | ||
116 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
117 | |||
118 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
119 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * shared line-in, mic for surrounds | ||
124 | */ | ||
125 | |||
126 | /* 3-stack / 2 channel */ | ||
127 | static const struct hda_verb cmi9880_ch2_init[] = { | ||
128 | /* set line-in PIN for input */ | ||
129 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
130 | /* set mic PIN for input, also enable vref */ | ||
131 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
132 | /* route front PCM (DAC1) to HP */ | ||
133 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
134 | {} | ||
135 | }; | ||
136 | |||
137 | /* 3-stack / 6 channel */ | ||
138 | static const struct hda_verb cmi9880_ch6_init[] = { | ||
139 | /* set line-in PIN for output */ | ||
140 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
141 | /* set mic PIN for output */ | ||
142 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
143 | /* route front PCM (DAC1) to HP */ | ||
144 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
145 | {} | ||
146 | }; | ||
147 | |||
148 | /* 3-stack+front / 8 channel */ | ||
149 | static const struct hda_verb cmi9880_ch8_init[] = { | ||
150 | /* set line-in PIN for output */ | ||
151 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
152 | /* set mic PIN for output */ | ||
153 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
154 | /* route rear-surround PCM (DAC4) to HP */ | ||
155 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, | ||
156 | {} | ||
157 | }; | ||
158 | |||
159 | static const struct hda_channel_mode cmi9880_channel_modes[3] = { | ||
160 | { 2, cmi9880_ch2_init }, | ||
161 | { 6, cmi9880_ch6_init }, | ||
162 | { 8, cmi9880_ch8_init }, | ||
163 | }; | ||
164 | |||
165 | static int cmi_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
166 | { | ||
167 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
168 | struct cmi_spec *spec = codec->spec; | ||
169 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes, | ||
170 | spec->num_channel_modes); | ||
171 | } | ||
172 | |||
173 | static int cmi_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
174 | { | ||
175 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
176 | struct cmi_spec *spec = codec->spec; | ||
177 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes, | ||
178 | spec->num_channel_modes, spec->multiout.max_channels); | ||
179 | } | ||
180 | |||
181 | static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
182 | { | ||
183 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
184 | struct cmi_spec *spec = codec->spec; | ||
185 | return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes, | ||
186 | spec->num_channel_modes, &spec->multiout.max_channels); | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | */ | ||
191 | static const struct snd_kcontrol_new cmi9880_basic_mixer[] = { | ||
192 | /* CMI9880 has no playback volumes! */ | ||
193 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */ | ||
194 | HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT), | ||
195 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), | ||
196 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), | ||
197 | HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT), | ||
198 | { | ||
199 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
200 | /* The multiple "Capture Source" controls confuse alsamixer | ||
201 | * So call somewhat different.. | ||
202 | */ | ||
203 | /* .name = "Capture Source", */ | ||
204 | .name = "Input Source", | ||
205 | .count = 2, | ||
206 | .info = cmi_mux_enum_info, | ||
207 | .get = cmi_mux_enum_get, | ||
208 | .put = cmi_mux_enum_put, | ||
209 | }, | ||
210 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT), | ||
211 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT), | ||
212 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT), | ||
213 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT), | ||
214 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x23, 0, HDA_OUTPUT), | ||
215 | HDA_CODEC_MUTE("Beep Playback Switch", 0x23, 0, HDA_OUTPUT), | ||
216 | { } /* end */ | ||
217 | }; | 36 | }; |
218 | 37 | ||
219 | /* | 38 | /* |
220 | * shared I/O pins | ||
221 | */ | ||
222 | static const struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = { | ||
223 | { | ||
224 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
225 | .name = "Channel Mode", | ||
226 | .info = cmi_ch_mode_info, | ||
227 | .get = cmi_ch_mode_get, | ||
228 | .put = cmi_ch_mode_put, | ||
229 | }, | ||
230 | { } /* end */ | ||
231 | }; | ||
232 | |||
233 | /* AUD-in selections: | ||
234 | * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20 | ||
235 | */ | ||
236 | static const struct hda_input_mux cmi9880_basic_mux = { | ||
237 | .num_items = 4, | ||
238 | .items = { | ||
239 | { "Front Mic", 0x5 }, | ||
240 | { "Rear Mic", 0x2 }, | ||
241 | { "Line", 0x1 }, | ||
242 | { "CD", 0x7 }, | ||
243 | } | ||
244 | }; | ||
245 | |||
246 | static const struct hda_input_mux cmi9880_no_line_mux = { | ||
247 | .num_items = 3, | ||
248 | .items = { | ||
249 | { "Front Mic", 0x5 }, | ||
250 | { "Rear Mic", 0x2 }, | ||
251 | { "CD", 0x7 }, | ||
252 | } | ||
253 | }; | ||
254 | |||
255 | /* front, rear, clfe, rear_surr */ | ||
256 | static const hda_nid_t cmi9880_dac_nids[4] = { | ||
257 | 0x03, 0x04, 0x05, 0x06 | ||
258 | }; | ||
259 | /* ADC0, ADC1 */ | ||
260 | static const hda_nid_t cmi9880_adc_nids[2] = { | ||
261 | 0x08, 0x09 | ||
262 | }; | ||
263 | |||
264 | #define CMI_DIG_OUT_NID 0x07 | ||
265 | #define CMI_DIG_IN_NID 0x0a | ||
266 | |||
267 | /* | ||
268 | */ | ||
269 | static const struct hda_verb cmi9880_basic_init[] = { | ||
270 | /* port-D for line out (rear panel) */ | ||
271 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
272 | /* port-E for HP out (front panel) */ | ||
273 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
274 | /* route front PCM to HP */ | ||
275 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
276 | /* port-A for surround (rear panel) */ | ||
277 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
278 | /* port-G for CLFE (rear panel) */ | ||
279 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
280 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
281 | /* port-H for side (rear panel) */ | ||
282 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
283 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
284 | /* port-C for line-in (rear panel) */ | ||
285 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
286 | /* port-B for mic-in (rear panel) with vref */ | ||
287 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
288 | /* port-F for mic-in (front panel) with vref */ | ||
289 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
290 | /* CD-in */ | ||
291 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
292 | /* route front mic to ADC1/2 */ | ||
293 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
294 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
295 | {} /* terminator */ | ||
296 | }; | ||
297 | |||
298 | static const struct hda_verb cmi9880_allout_init[] = { | ||
299 | /* port-D for line out (rear panel) */ | ||
300 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
301 | /* port-E for HP out (front panel) */ | ||
302 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
303 | /* route front PCM to HP */ | ||
304 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
305 | /* port-A for side (rear panel) */ | ||
306 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
307 | /* port-G for CLFE (rear panel) */ | ||
308 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
309 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
310 | /* port-H for side (rear panel) */ | ||
311 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
312 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
313 | /* port-C for surround (rear panel) */ | ||
314 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
315 | /* port-B for mic-in (rear panel) with vref */ | ||
316 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
317 | /* port-F for mic-in (front panel) with vref */ | ||
318 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
319 | /* CD-in */ | ||
320 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
321 | /* route front mic to ADC1/2 */ | ||
322 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
323 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, | ||
324 | {} /* terminator */ | ||
325 | }; | ||
326 | |||
327 | /* | ||
328 | */ | ||
329 | static int cmi9880_build_controls(struct hda_codec *codec) | ||
330 | { | ||
331 | struct cmi_spec *spec = codec->spec; | ||
332 | struct snd_kcontrol *kctl; | ||
333 | int i, err; | ||
334 | |||
335 | err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer); | ||
336 | if (err < 0) | ||
337 | return err; | ||
338 | if (spec->channel_modes) { | ||
339 | err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer); | ||
340 | if (err < 0) | ||
341 | return err; | ||
342 | } | ||
343 | if (spec->multiout.dig_out_nid) { | ||
344 | err = snd_hda_create_spdif_out_ctls(codec, | ||
345 | spec->multiout.dig_out_nid, | ||
346 | spec->multiout.dig_out_nid); | ||
347 | if (err < 0) | ||
348 | return err; | ||
349 | err = snd_hda_create_spdif_share_sw(codec, | ||
350 | &spec->multiout); | ||
351 | if (err < 0) | ||
352 | return err; | ||
353 | spec->multiout.share_spdif = 1; | ||
354 | } | ||
355 | if (spec->dig_in_nid) { | ||
356 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | ||
357 | if (err < 0) | ||
358 | return err; | ||
359 | } | ||
360 | |||
361 | /* assign Capture Source enums to NID */ | ||
362 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | ||
363 | for (i = 0; kctl && i < kctl->count; i++) { | ||
364 | err = snd_hda_add_nid(codec, kctl, i, spec->adc_nids[i]); | ||
365 | if (err < 0) | ||
366 | return err; | ||
367 | } | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int cmi9880_init(struct hda_codec *codec) | ||
372 | { | ||
373 | struct cmi_spec *spec = codec->spec; | ||
374 | if (spec->board_config == CMI_ALLOUT) | ||
375 | snd_hda_sequence_write(codec, cmi9880_allout_init); | ||
376 | else | ||
377 | snd_hda_sequence_write(codec, cmi9880_basic_init); | ||
378 | if (spec->board_config == CMI_AUTO) | ||
379 | snd_hda_sequence_write(codec, spec->multi_init); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * Analog playback callbacks | ||
385 | */ | ||
386 | static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
387 | struct hda_codec *codec, | ||
388 | struct snd_pcm_substream *substream) | ||
389 | { | ||
390 | struct cmi_spec *spec = codec->spec; | ||
391 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | ||
392 | hinfo); | ||
393 | } | ||
394 | |||
395 | static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
396 | struct hda_codec *codec, | ||
397 | unsigned int stream_tag, | ||
398 | unsigned int format, | ||
399 | struct snd_pcm_substream *substream) | ||
400 | { | ||
401 | struct cmi_spec *spec = codec->spec; | ||
402 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
403 | format, substream); | ||
404 | } | ||
405 | |||
406 | static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
407 | struct hda_codec *codec, | ||
408 | struct snd_pcm_substream *substream) | ||
409 | { | ||
410 | struct cmi_spec *spec = codec->spec; | ||
411 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Digital out | ||
416 | */ | ||
417 | static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
418 | struct hda_codec *codec, | ||
419 | struct snd_pcm_substream *substream) | ||
420 | { | ||
421 | struct cmi_spec *spec = codec->spec; | ||
422 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
423 | } | ||
424 | |||
425 | static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
426 | struct hda_codec *codec, | ||
427 | struct snd_pcm_substream *substream) | ||
428 | { | ||
429 | struct cmi_spec *spec = codec->spec; | ||
430 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
431 | } | ||
432 | |||
433 | static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
434 | struct hda_codec *codec, | ||
435 | unsigned int stream_tag, | ||
436 | unsigned int format, | ||
437 | struct snd_pcm_substream *substream) | ||
438 | { | ||
439 | struct cmi_spec *spec = codec->spec; | ||
440 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
441 | format, substream); | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | * Analog capture | ||
446 | */ | ||
447 | static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
448 | struct hda_codec *codec, | ||
449 | unsigned int stream_tag, | ||
450 | unsigned int format, | ||
451 | struct snd_pcm_substream *substream) | ||
452 | { | ||
453 | struct cmi_spec *spec = codec->spec; | ||
454 | |||
455 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | ||
456 | stream_tag, 0, format); | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
461 | struct hda_codec *codec, | ||
462 | struct snd_pcm_substream *substream) | ||
463 | { | ||
464 | struct cmi_spec *spec = codec->spec; | ||
465 | |||
466 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | |||
471 | /* | ||
472 | */ | ||
473 | static const struct hda_pcm_stream cmi9880_pcm_analog_playback = { | ||
474 | .substreams = 1, | ||
475 | .channels_min = 2, | ||
476 | .channels_max = 8, | ||
477 | .nid = 0x03, /* NID to query formats and rates */ | ||
478 | .ops = { | ||
479 | .open = cmi9880_playback_pcm_open, | ||
480 | .prepare = cmi9880_playback_pcm_prepare, | ||
481 | .cleanup = cmi9880_playback_pcm_cleanup | ||
482 | }, | ||
483 | }; | ||
484 | |||
485 | static const struct hda_pcm_stream cmi9880_pcm_analog_capture = { | ||
486 | .substreams = 2, | ||
487 | .channels_min = 2, | ||
488 | .channels_max = 2, | ||
489 | .nid = 0x08, /* NID to query formats and rates */ | ||
490 | .ops = { | ||
491 | .prepare = cmi9880_capture_pcm_prepare, | ||
492 | .cleanup = cmi9880_capture_pcm_cleanup | ||
493 | }, | ||
494 | }; | ||
495 | |||
496 | static const struct hda_pcm_stream cmi9880_pcm_digital_playback = { | ||
497 | .substreams = 1, | ||
498 | .channels_min = 2, | ||
499 | .channels_max = 2, | ||
500 | /* NID is set in cmi9880_build_pcms */ | ||
501 | .ops = { | ||
502 | .open = cmi9880_dig_playback_pcm_open, | ||
503 | .close = cmi9880_dig_playback_pcm_close, | ||
504 | .prepare = cmi9880_dig_playback_pcm_prepare | ||
505 | }, | ||
506 | }; | ||
507 | |||
508 | static const struct hda_pcm_stream cmi9880_pcm_digital_capture = { | ||
509 | .substreams = 1, | ||
510 | .channels_min = 2, | ||
511 | .channels_max = 2, | ||
512 | /* NID is set in cmi9880_build_pcms */ | ||
513 | }; | ||
514 | |||
515 | static int cmi9880_build_pcms(struct hda_codec *codec) | ||
516 | { | ||
517 | struct cmi_spec *spec = codec->spec; | ||
518 | struct hda_pcm *info = spec->pcm_rec; | ||
519 | |||
520 | codec->num_pcms = 1; | ||
521 | codec->pcm_info = info; | ||
522 | |||
523 | info->name = "CMI9880"; | ||
524 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback; | ||
525 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture; | ||
526 | |||
527 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | ||
528 | codec->num_pcms++; | ||
529 | info++; | ||
530 | info->name = "CMI9880 Digital"; | ||
531 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
532 | if (spec->multiout.dig_out_nid) { | ||
533 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback; | ||
534 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | ||
535 | } | ||
536 | if (spec->dig_in_nid) { | ||
537 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture; | ||
538 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static void cmi9880_free(struct hda_codec *codec) | ||
546 | { | ||
547 | kfree(codec->spec); | ||
548 | } | ||
549 | |||
550 | /* | ||
551 | */ | ||
552 | |||
553 | static const char * const cmi9880_models[CMI_MODELS] = { | ||
554 | [CMI_MINIMAL] = "minimal", | ||
555 | [CMI_MIN_FP] = "min_fp", | ||
556 | [CMI_FULL] = "full", | ||
557 | [CMI_FULL_DIG] = "full_dig", | ||
558 | [CMI_ALLOUT] = "allout", | ||
559 | [CMI_AUTO] = "auto", | ||
560 | }; | ||
561 | |||
562 | static const struct snd_pci_quirk cmi9880_cfg_tbl[] = { | ||
563 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG), | ||
564 | SND_PCI_QUIRK(0x1854, 0x002b, "LG LS75", CMI_MINIMAL), | ||
565 | SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG), | ||
566 | {} /* terminator */ | ||
567 | }; | ||
568 | |||
569 | static const struct hda_codec_ops cmi9880_patch_ops = { | ||
570 | .build_controls = cmi9880_build_controls, | ||
571 | .build_pcms = cmi9880_build_pcms, | ||
572 | .init = cmi9880_init, | ||
573 | .free = cmi9880_free, | ||
574 | }; | ||
575 | #endif /* ENABLE_CMI_STATIC_QUIRKS */ | ||
576 | |||
577 | /* | ||
578 | * stuff for auto-parser | 39 | * stuff for auto-parser |
579 | */ | 40 | */ |
580 | static const struct hda_codec_ops cmi_auto_patch_ops = { | 41 | static const struct hda_codec_ops cmi_auto_patch_ops = { |
@@ -585,12 +46,18 @@ static const struct hda_codec_ops cmi_auto_patch_ops = { | |||
585 | .unsol_event = snd_hda_jack_unsol_event, | 46 | .unsol_event = snd_hda_jack_unsol_event, |
586 | }; | 47 | }; |
587 | 48 | ||
588 | static int cmi_parse_auto_config(struct hda_codec *codec) | 49 | static int patch_cmi9880(struct hda_codec *codec) |
589 | { | 50 | { |
590 | struct cmi_spec *spec = codec->spec; | 51 | struct cmi_spec *spec; |
591 | struct auto_pin_cfg *cfg = &spec->gen.autocfg; | 52 | struct auto_pin_cfg *cfg; |
592 | int err; | 53 | int err; |
593 | 54 | ||
55 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
56 | if (spec == NULL) | ||
57 | return -ENOMEM; | ||
58 | |||
59 | codec->spec = spec; | ||
60 | cfg = &spec->gen.autocfg; | ||
594 | snd_hda_gen_spec_init(&spec->gen); | 61 | snd_hda_gen_spec_init(&spec->gen); |
595 | 62 | ||
596 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); | 63 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); |
@@ -608,79 +75,6 @@ static int cmi_parse_auto_config(struct hda_codec *codec) | |||
608 | return err; | 75 | return err; |
609 | } | 76 | } |
610 | 77 | ||
611 | |||
612 | static int patch_cmi9880(struct hda_codec *codec) | ||
613 | { | ||
614 | struct cmi_spec *spec; | ||
615 | |||
616 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
617 | if (spec == NULL) | ||
618 | return -ENOMEM; | ||
619 | |||
620 | codec->spec = spec; | ||
621 | #ifdef ENABLE_CMI_STATIC_QUIRKS | ||
622 | spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS, | ||
623 | cmi9880_models, | ||
624 | cmi9880_cfg_tbl); | ||
625 | if (spec->board_config < 0) { | ||
626 | codec_dbg(codec, "%s: BIOS auto-probing.\n", | ||
627 | codec->chip_name); | ||
628 | spec->board_config = CMI_AUTO; /* try everything */ | ||
629 | } | ||
630 | |||
631 | if (spec->board_config == CMI_AUTO) | ||
632 | return cmi_parse_auto_config(codec); | ||
633 | |||
634 | /* copy default DAC NIDs */ | ||
635 | memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); | ||
636 | spec->num_dacs = 4; | ||
637 | |||
638 | switch (spec->board_config) { | ||
639 | case CMI_MINIMAL: | ||
640 | case CMI_MIN_FP: | ||
641 | spec->channel_modes = cmi9880_channel_modes; | ||
642 | if (spec->board_config == CMI_MINIMAL) | ||
643 | spec->num_channel_modes = 2; | ||
644 | else { | ||
645 | spec->front_panel = 1; | ||
646 | spec->num_channel_modes = 3; | ||
647 | } | ||
648 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; | ||
649 | spec->input_mux = &cmi9880_basic_mux; | ||
650 | break; | ||
651 | case CMI_FULL: | ||
652 | case CMI_FULL_DIG: | ||
653 | spec->front_panel = 1; | ||
654 | spec->multiout.max_channels = 8; | ||
655 | spec->input_mux = &cmi9880_basic_mux; | ||
656 | if (spec->board_config == CMI_FULL_DIG) { | ||
657 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | ||
658 | spec->dig_in_nid = CMI_DIG_IN_NID; | ||
659 | } | ||
660 | break; | ||
661 | case CMI_ALLOUT: | ||
662 | default: | ||
663 | spec->front_panel = 1; | ||
664 | spec->multiout.max_channels = 8; | ||
665 | spec->no_line_in = 1; | ||
666 | spec->input_mux = &cmi9880_no_line_mux; | ||
667 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | ||
668 | break; | ||
669 | } | ||
670 | |||
671 | spec->multiout.num_dacs = spec->num_dacs; | ||
672 | spec->multiout.dac_nids = spec->dac_nids; | ||
673 | |||
674 | spec->adc_nids = cmi9880_adc_nids; | ||
675 | |||
676 | codec->patch_ops = cmi9880_patch_ops; | ||
677 | |||
678 | return 0; | ||
679 | #else | ||
680 | return cmi_parse_auto_config(codec); | ||
681 | #endif | ||
682 | } | ||
683 | |||
684 | /* | 78 | /* |
685 | * patch entries | 79 | * patch entries |
686 | */ | 80 | */ |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 1dc7e974f3b1..7627a69ca6d7 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -34,27 +34,6 @@ | |||
34 | #include "hda_jack.h" | 34 | #include "hda_jack.h" |
35 | #include "hda_generic.h" | 35 | #include "hda_generic.h" |
36 | 36 | ||
37 | #undef ENABLE_CXT_STATIC_QUIRKS | ||
38 | |||
39 | #define CXT_PIN_DIR_IN 0x00 | ||
40 | #define CXT_PIN_DIR_OUT 0x01 | ||
41 | #define CXT_PIN_DIR_INOUT 0x02 | ||
42 | #define CXT_PIN_DIR_IN_NOMICBIAS 0x03 | ||
43 | #define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04 | ||
44 | |||
45 | #define CONEXANT_HP_EVENT 0x37 | ||
46 | #define CONEXANT_MIC_EVENT 0x38 | ||
47 | #define CONEXANT_LINE_EVENT 0x39 | ||
48 | |||
49 | /* Conexant 5051 specific */ | ||
50 | |||
51 | #define CXT5051_SPDIF_OUT 0x12 | ||
52 | #define CXT5051_PORTB_EVENT 0x38 | ||
53 | #define CXT5051_PORTC_EVENT 0x39 | ||
54 | |||
55 | #define AUTO_MIC_PORTB (1 << 1) | ||
56 | #define AUTO_MIC_PORTC (1 << 2) | ||
57 | |||
58 | struct conexant_spec { | 37 | struct conexant_spec { |
59 | struct hda_gen_spec gen; | 38 | struct hda_gen_spec gen; |
60 | 39 | ||
@@ -72,64 +51,6 @@ struct conexant_spec { | |||
72 | bool dc_enable; | 51 | bool dc_enable; |
73 | unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */ | 52 | unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */ |
74 | struct nid_path *dc_mode_path; | 53 | struct nid_path *dc_mode_path; |
75 | |||
76 | #ifdef ENABLE_CXT_STATIC_QUIRKS | ||
77 | const struct snd_kcontrol_new *mixers[5]; | ||
78 | int num_mixers; | ||
79 | hda_nid_t vmaster_nid; | ||
80 | |||
81 | const struct hda_verb *init_verbs[5]; /* initialization verbs | ||
82 | * don't forget NULL | ||
83 | * termination! | ||
84 | */ | ||
85 | unsigned int num_init_verbs; | ||
86 | |||
87 | /* playback */ | ||
88 | struct hda_multi_out multiout; /* playback set-up | ||
89 | * max_channels, dacs must be set | ||
90 | * dig_out_nid and hp_nid are optional | ||
91 | */ | ||
92 | unsigned int cur_eapd; | ||
93 | unsigned int hp_present; | ||
94 | unsigned int line_present; | ||
95 | unsigned int auto_mic; | ||
96 | |||
97 | /* capture */ | ||
98 | unsigned int num_adc_nids; | ||
99 | const hda_nid_t *adc_nids; | ||
100 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | ||
101 | |||
102 | unsigned int cur_adc_idx; | ||
103 | hda_nid_t cur_adc; | ||
104 | unsigned int cur_adc_stream_tag; | ||
105 | unsigned int cur_adc_format; | ||
106 | |||
107 | const struct hda_pcm_stream *capture_stream; | ||
108 | |||
109 | /* capture source */ | ||
110 | const struct hda_input_mux *input_mux; | ||
111 | const hda_nid_t *capsrc_nids; | ||
112 | unsigned int cur_mux[3]; | ||
113 | |||
114 | /* channel model */ | ||
115 | const struct hda_channel_mode *channel_mode; | ||
116 | int num_channel_mode; | ||
117 | |||
118 | /* PCM information */ | ||
119 | struct hda_pcm pcm_rec[2]; /* used in build_pcms() */ | ||
120 | |||
121 | unsigned int spdif_route; | ||
122 | |||
123 | unsigned int port_d_mode; | ||
124 | unsigned int dell_automute:1; | ||
125 | unsigned int dell_vostro:1; | ||
126 | unsigned int ideapad:1; | ||
127 | unsigned int thinkpad:1; | ||
128 | unsigned int hp_laptop:1; | ||
129 | unsigned int asus:1; | ||
130 | |||
131 | unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ | ||
132 | #endif /* ENABLE_CXT_STATIC_QUIRKS */ | ||
133 | }; | 54 | }; |
134 | 55 | ||
135 | 56 | ||
@@ -173,2533 +94,6 @@ static int add_beep_ctls(struct hda_codec *codec) | |||
173 | #define add_beep_ctls(codec) 0 | 94 | #define add_beep_ctls(codec) 0 |
174 | #endif | 95 | #endif |
175 | 96 | ||
176 | |||
177 | #ifdef ENABLE_CXT_STATIC_QUIRKS | ||
178 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
179 | struct hda_codec *codec, | ||
180 | struct snd_pcm_substream *substream) | ||
181 | { | ||
182 | struct conexant_spec *spec = codec->spec; | ||
183 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | ||
184 | hinfo); | ||
185 | } | ||
186 | |||
187 | static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
188 | struct hda_codec *codec, | ||
189 | unsigned int stream_tag, | ||
190 | unsigned int format, | ||
191 | struct snd_pcm_substream *substream) | ||
192 | { | ||
193 | struct conexant_spec *spec = codec->spec; | ||
194 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, | ||
195 | stream_tag, | ||
196 | format, substream); | ||
197 | } | ||
198 | |||
199 | static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
200 | struct hda_codec *codec, | ||
201 | struct snd_pcm_substream *substream) | ||
202 | { | ||
203 | struct conexant_spec *spec = codec->spec; | ||
204 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Digital out | ||
209 | */ | ||
210 | static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
211 | struct hda_codec *codec, | ||
212 | struct snd_pcm_substream *substream) | ||
213 | { | ||
214 | struct conexant_spec *spec = codec->spec; | ||
215 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
216 | } | ||
217 | |||
218 | static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
219 | struct hda_codec *codec, | ||
220 | struct snd_pcm_substream *substream) | ||
221 | { | ||
222 | struct conexant_spec *spec = codec->spec; | ||
223 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
224 | } | ||
225 | |||
226 | static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
227 | struct hda_codec *codec, | ||
228 | unsigned int stream_tag, | ||
229 | unsigned int format, | ||
230 | struct snd_pcm_substream *substream) | ||
231 | { | ||
232 | struct conexant_spec *spec = codec->spec; | ||
233 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
234 | stream_tag, | ||
235 | format, substream); | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * Analog capture | ||
240 | */ | ||
241 | static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
242 | struct hda_codec *codec, | ||
243 | unsigned int stream_tag, | ||
244 | unsigned int format, | ||
245 | struct snd_pcm_substream *substream) | ||
246 | { | ||
247 | struct conexant_spec *spec = codec->spec; | ||
248 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | ||
249 | stream_tag, 0, format); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
254 | struct hda_codec *codec, | ||
255 | struct snd_pcm_substream *substream) | ||
256 | { | ||
257 | struct conexant_spec *spec = codec->spec; | ||
258 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | |||
263 | |||
264 | static const struct hda_pcm_stream conexant_pcm_analog_playback = { | ||
265 | .substreams = 1, | ||
266 | .channels_min = 2, | ||
267 | .channels_max = 2, | ||
268 | .nid = 0, /* fill later */ | ||
269 | .ops = { | ||
270 | .open = conexant_playback_pcm_open, | ||
271 | .prepare = conexant_playback_pcm_prepare, | ||
272 | .cleanup = conexant_playback_pcm_cleanup | ||
273 | }, | ||
274 | }; | ||
275 | |||
276 | static const struct hda_pcm_stream conexant_pcm_analog_capture = { | ||
277 | .substreams = 1, | ||
278 | .channels_min = 2, | ||
279 | .channels_max = 2, | ||
280 | .nid = 0, /* fill later */ | ||
281 | .ops = { | ||
282 | .prepare = conexant_capture_pcm_prepare, | ||
283 | .cleanup = conexant_capture_pcm_cleanup | ||
284 | }, | ||
285 | }; | ||
286 | |||
287 | |||
288 | static const struct hda_pcm_stream conexant_pcm_digital_playback = { | ||
289 | .substreams = 1, | ||
290 | .channels_min = 2, | ||
291 | .channels_max = 2, | ||
292 | .nid = 0, /* fill later */ | ||
293 | .ops = { | ||
294 | .open = conexant_dig_playback_pcm_open, | ||
295 | .close = conexant_dig_playback_pcm_close, | ||
296 | .prepare = conexant_dig_playback_pcm_prepare | ||
297 | }, | ||
298 | }; | ||
299 | |||
300 | static const struct hda_pcm_stream conexant_pcm_digital_capture = { | ||
301 | .substreams = 1, | ||
302 | .channels_min = 2, | ||
303 | .channels_max = 2, | ||
304 | /* NID is set in alc_build_pcms */ | ||
305 | }; | ||
306 | |||
307 | static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
308 | struct hda_codec *codec, | ||
309 | unsigned int stream_tag, | ||
310 | unsigned int format, | ||
311 | struct snd_pcm_substream *substream) | ||
312 | { | ||
313 | struct conexant_spec *spec = codec->spec; | ||
314 | spec->cur_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
315 | spec->cur_adc_stream_tag = stream_tag; | ||
316 | spec->cur_adc_format = format; | ||
317 | snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
322 | struct hda_codec *codec, | ||
323 | struct snd_pcm_substream *substream) | ||
324 | { | ||
325 | struct conexant_spec *spec = codec->spec; | ||
326 | snd_hda_codec_cleanup_stream(codec, spec->cur_adc); | ||
327 | spec->cur_adc = 0; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static const struct hda_pcm_stream cx5051_pcm_analog_capture = { | ||
332 | .substreams = 1, | ||
333 | .channels_min = 2, | ||
334 | .channels_max = 2, | ||
335 | .nid = 0, /* fill later */ | ||
336 | .ops = { | ||
337 | .prepare = cx5051_capture_pcm_prepare, | ||
338 | .cleanup = cx5051_capture_pcm_cleanup | ||
339 | }, | ||
340 | }; | ||
341 | |||
342 | static int conexant_build_pcms(struct hda_codec *codec) | ||
343 | { | ||
344 | struct conexant_spec *spec = codec->spec; | ||
345 | struct hda_pcm *info = spec->pcm_rec; | ||
346 | |||
347 | codec->num_pcms = 1; | ||
348 | codec->pcm_info = info; | ||
349 | |||
350 | info->name = "CONEXANT Analog"; | ||
351 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback; | ||
352 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | ||
353 | spec->multiout.max_channels; | ||
354 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = | ||
355 | spec->multiout.dac_nids[0]; | ||
356 | if (spec->capture_stream) | ||
357 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream; | ||
358 | else { | ||
359 | if (codec->vendor_id == 0x14f15051) | ||
360 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
361 | cx5051_pcm_analog_capture; | ||
362 | else { | ||
363 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
364 | conexant_pcm_analog_capture; | ||
365 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = | ||
366 | spec->num_adc_nids; | ||
367 | } | ||
368 | } | ||
369 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | ||
370 | |||
371 | if (spec->multiout.dig_out_nid) { | ||
372 | info++; | ||
373 | codec->num_pcms++; | ||
374 | info->name = "Conexant Digital"; | ||
375 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
376 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
377 | conexant_pcm_digital_playback; | ||
378 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = | ||
379 | spec->multiout.dig_out_nid; | ||
380 | if (spec->dig_in_nid) { | ||
381 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
382 | conexant_pcm_digital_capture; | ||
383 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = | ||
384 | spec->dig_in_nid; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
392 | struct snd_ctl_elem_info *uinfo) | ||
393 | { | ||
394 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
395 | struct conexant_spec *spec = codec->spec; | ||
396 | |||
397 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
398 | } | ||
399 | |||
400 | static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
401 | struct snd_ctl_elem_value *ucontrol) | ||
402 | { | ||
403 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
404 | struct conexant_spec *spec = codec->spec; | ||
405 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
406 | |||
407 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
412 | struct snd_ctl_elem_value *ucontrol) | ||
413 | { | ||
414 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
415 | struct conexant_spec *spec = codec->spec; | ||
416 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
417 | |||
418 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
419 | spec->capsrc_nids[adc_idx], | ||
420 | &spec->cur_mux[adc_idx]); | ||
421 | } | ||
422 | |||
423 | static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg, | ||
424 | unsigned int power_state) | ||
425 | { | ||
426 | if (power_state == AC_PWRST_D3) | ||
427 | msleep(100); | ||
428 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
429 | power_state); | ||
430 | /* partial workaround for "azx_get_response timeout" */ | ||
431 | if (power_state == AC_PWRST_D0) | ||
432 | msleep(10); | ||
433 | snd_hda_codec_set_power_to_all(codec, fg, power_state); | ||
434 | } | ||
435 | |||
436 | static int conexant_init(struct hda_codec *codec) | ||
437 | { | ||
438 | struct conexant_spec *spec = codec->spec; | ||
439 | int i; | ||
440 | |||
441 | for (i = 0; i < spec->num_init_verbs; i++) | ||
442 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | ||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static void conexant_free(struct hda_codec *codec) | ||
447 | { | ||
448 | kfree(codec->spec); | ||
449 | } | ||
450 | |||
451 | static const struct snd_kcontrol_new cxt_capture_mixers[] = { | ||
452 | { | ||
453 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
454 | .name = "Capture Source", | ||
455 | .info = conexant_mux_enum_info, | ||
456 | .get = conexant_mux_enum_get, | ||
457 | .put = conexant_mux_enum_put | ||
458 | }, | ||
459 | {} | ||
460 | }; | ||
461 | |||
462 | static const char * const slave_pfxs[] = { | ||
463 | "Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE", | ||
464 | NULL | ||
465 | }; | ||
466 | |||
467 | static int conexant_build_controls(struct hda_codec *codec) | ||
468 | { | ||
469 | struct conexant_spec *spec = codec->spec; | ||
470 | unsigned int i; | ||
471 | int err; | ||
472 | |||
473 | for (i = 0; i < spec->num_mixers; i++) { | ||
474 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | ||
475 | if (err < 0) | ||
476 | return err; | ||
477 | } | ||
478 | if (spec->multiout.dig_out_nid) { | ||
479 | err = snd_hda_create_spdif_out_ctls(codec, | ||
480 | spec->multiout.dig_out_nid, | ||
481 | spec->multiout.dig_out_nid); | ||
482 | if (err < 0) | ||
483 | return err; | ||
484 | err = snd_hda_create_spdif_share_sw(codec, | ||
485 | &spec->multiout); | ||
486 | if (err < 0) | ||
487 | return err; | ||
488 | spec->multiout.share_spdif = 1; | ||
489 | } | ||
490 | if (spec->dig_in_nid) { | ||
491 | err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid); | ||
492 | if (err < 0) | ||
493 | return err; | ||
494 | } | ||
495 | |||
496 | /* if we have no master control, let's create it */ | ||
497 | if (spec->vmaster_nid && | ||
498 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
499 | unsigned int vmaster_tlv[4]; | ||
500 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | ||
501 | HDA_OUTPUT, vmaster_tlv); | ||
502 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
503 | vmaster_tlv, slave_pfxs, | ||
504 | "Playback Volume"); | ||
505 | if (err < 0) | ||
506 | return err; | ||
507 | } | ||
508 | if (spec->vmaster_nid && | ||
509 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
510 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
511 | NULL, slave_pfxs, | ||
512 | "Playback Switch"); | ||
513 | if (err < 0) | ||
514 | return err; | ||
515 | } | ||
516 | |||
517 | if (spec->input_mux) { | ||
518 | err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); | ||
519 | if (err < 0) | ||
520 | return err; | ||
521 | } | ||
522 | |||
523 | err = add_beep_ctls(codec); | ||
524 | if (err < 0) | ||
525 | return err; | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static const struct hda_codec_ops conexant_patch_ops = { | ||
531 | .build_controls = conexant_build_controls, | ||
532 | .build_pcms = conexant_build_pcms, | ||
533 | .init = conexant_init, | ||
534 | .free = conexant_free, | ||
535 | .set_power_state = conexant_set_power, | ||
536 | }; | ||
537 | |||
538 | static int patch_conexant_auto(struct hda_codec *codec); | ||
539 | /* | ||
540 | * EAPD control | ||
541 | * the private value = nid | (invert << 8) | ||
542 | */ | ||
543 | |||
544 | #define cxt_eapd_info snd_ctl_boolean_mono_info | ||
545 | |||
546 | static int cxt_eapd_get(struct snd_kcontrol *kcontrol, | ||
547 | struct snd_ctl_elem_value *ucontrol) | ||
548 | { | ||
549 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
550 | struct conexant_spec *spec = codec->spec; | ||
551 | int invert = (kcontrol->private_value >> 8) & 1; | ||
552 | if (invert) | ||
553 | ucontrol->value.integer.value[0] = !spec->cur_eapd; | ||
554 | else | ||
555 | ucontrol->value.integer.value[0] = spec->cur_eapd; | ||
556 | return 0; | ||
557 | |||
558 | } | ||
559 | |||
560 | static int cxt_eapd_put(struct snd_kcontrol *kcontrol, | ||
561 | struct snd_ctl_elem_value *ucontrol) | ||
562 | { | ||
563 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
564 | struct conexant_spec *spec = codec->spec; | ||
565 | int invert = (kcontrol->private_value >> 8) & 1; | ||
566 | hda_nid_t nid = kcontrol->private_value & 0xff; | ||
567 | unsigned int eapd; | ||
568 | |||
569 | eapd = !!ucontrol->value.integer.value[0]; | ||
570 | if (invert) | ||
571 | eapd = !eapd; | ||
572 | if (eapd == spec->cur_eapd) | ||
573 | return 0; | ||
574 | |||
575 | spec->cur_eapd = eapd; | ||
576 | snd_hda_codec_write_cache(codec, nid, | ||
577 | 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
578 | eapd ? 0x02 : 0x00); | ||
579 | return 1; | ||
580 | } | ||
581 | |||
582 | /* controls for test mode */ | ||
583 | #ifdef CONFIG_SND_DEBUG | ||
584 | |||
585 | #define CXT_EAPD_SWITCH(xname, nid, mask) \ | ||
586 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
587 | .info = cxt_eapd_info, \ | ||
588 | .get = cxt_eapd_get, \ | ||
589 | .put = cxt_eapd_put, \ | ||
590 | .private_value = nid | (mask<<16) } | ||
591 | |||
592 | |||
593 | |||
594 | static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol, | ||
595 | struct snd_ctl_elem_info *uinfo) | ||
596 | { | ||
597 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
598 | struct conexant_spec *spec = codec->spec; | ||
599 | return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, | ||
600 | spec->num_channel_mode); | ||
601 | } | ||
602 | |||
603 | static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol, | ||
604 | struct snd_ctl_elem_value *ucontrol) | ||
605 | { | ||
606 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
607 | struct conexant_spec *spec = codec->spec; | ||
608 | return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, | ||
609 | spec->num_channel_mode, | ||
610 | spec->multiout.max_channels); | ||
611 | } | ||
612 | |||
613 | static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, | ||
614 | struct snd_ctl_elem_value *ucontrol) | ||
615 | { | ||
616 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
617 | struct conexant_spec *spec = codec->spec; | ||
618 | int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, | ||
619 | spec->num_channel_mode, | ||
620 | &spec->multiout.max_channels); | ||
621 | return err; | ||
622 | } | ||
623 | |||
624 | #define CXT_PIN_MODE(xname, nid, dir) \ | ||
625 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
626 | .info = conexant_ch_mode_info, \ | ||
627 | .get = conexant_ch_mode_get, \ | ||
628 | .put = conexant_ch_mode_put, \ | ||
629 | .private_value = nid | (dir<<16) } | ||
630 | |||
631 | #endif /* CONFIG_SND_DEBUG */ | ||
632 | |||
633 | /* Conexant 5045 specific */ | ||
634 | |||
635 | static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 }; | ||
636 | static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a }; | ||
637 | static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a }; | ||
638 | #define CXT5045_SPDIF_OUT 0x18 | ||
639 | |||
640 | static const struct hda_channel_mode cxt5045_modes[1] = { | ||
641 | { 2, NULL }, | ||
642 | }; | ||
643 | |||
644 | static const struct hda_input_mux cxt5045_capture_source = { | ||
645 | .num_items = 2, | ||
646 | .items = { | ||
647 | { "Internal Mic", 0x1 }, | ||
648 | { "Mic", 0x2 }, | ||
649 | } | ||
650 | }; | ||
651 | |||
652 | static const struct hda_input_mux cxt5045_capture_source_benq = { | ||
653 | .num_items = 4, | ||
654 | .items = { | ||
655 | { "Internal Mic", 0x1 }, | ||
656 | { "Mic", 0x2 }, | ||
657 | { "Line", 0x3 }, | ||
658 | { "Mixer", 0x0 }, | ||
659 | } | ||
660 | }; | ||
661 | |||
662 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
663 | static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
664 | struct snd_ctl_elem_value *ucontrol) | ||
665 | { | ||
666 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
667 | struct conexant_spec *spec = codec->spec; | ||
668 | unsigned int bits; | ||
669 | |||
670 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
671 | return 0; | ||
672 | |||
673 | /* toggle internal speakers mute depending of presence of | ||
674 | * the headphone jack | ||
675 | */ | ||
676 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | ||
677 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, | ||
678 | HDA_AMP_MUTE, bits); | ||
679 | |||
680 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | ||
681 | snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0, | ||
682 | HDA_AMP_MUTE, bits); | ||
683 | return 1; | ||
684 | } | ||
685 | |||
686 | /* bind volumes of both NID 0x10 and 0x11 */ | ||
687 | static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = { | ||
688 | .ops = &snd_hda_bind_vol, | ||
689 | .values = { | ||
690 | HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), | ||
691 | HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT), | ||
692 | 0 | ||
693 | }, | ||
694 | }; | ||
695 | |||
696 | /* toggle input of built-in and mic jack appropriately */ | ||
697 | static void cxt5045_hp_automic(struct hda_codec *codec) | ||
698 | { | ||
699 | static const struct hda_verb mic_jack_on[] = { | ||
700 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
701 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
702 | {} | ||
703 | }; | ||
704 | static const struct hda_verb mic_jack_off[] = { | ||
705 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
706 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
707 | {} | ||
708 | }; | ||
709 | unsigned int present; | ||
710 | |||
711 | present = snd_hda_jack_detect(codec, 0x12); | ||
712 | if (present) | ||
713 | snd_hda_sequence_write(codec, mic_jack_on); | ||
714 | else | ||
715 | snd_hda_sequence_write(codec, mic_jack_off); | ||
716 | } | ||
717 | |||
718 | |||
719 | /* mute internal speaker if HP is plugged */ | ||
720 | static void cxt5045_hp_automute(struct hda_codec *codec) | ||
721 | { | ||
722 | struct conexant_spec *spec = codec->spec; | ||
723 | unsigned int bits; | ||
724 | |||
725 | spec->hp_present = snd_hda_jack_detect(codec, 0x11); | ||
726 | |||
727 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | ||
728 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, | ||
729 | HDA_AMP_MUTE, bits); | ||
730 | } | ||
731 | |||
732 | /* unsolicited event for HP jack sensing */ | ||
733 | static void cxt5045_hp_unsol_event(struct hda_codec *codec, | ||
734 | unsigned int res) | ||
735 | { | ||
736 | res >>= 26; | ||
737 | switch (res) { | ||
738 | case CONEXANT_HP_EVENT: | ||
739 | cxt5045_hp_automute(codec); | ||
740 | break; | ||
741 | case CONEXANT_MIC_EVENT: | ||
742 | cxt5045_hp_automic(codec); | ||
743 | break; | ||
744 | |||
745 | } | ||
746 | } | ||
747 | |||
748 | static const struct snd_kcontrol_new cxt5045_mixers[] = { | ||
749 | HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), | ||
750 | HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
751 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), | ||
752 | HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), | ||
753 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT), | ||
754 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT), | ||
755 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT), | ||
756 | HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT), | ||
757 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), | ||
758 | { | ||
759 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
760 | .name = "Master Playback Switch", | ||
761 | .info = cxt_eapd_info, | ||
762 | .get = cxt_eapd_get, | ||
763 | .put = cxt5045_hp_master_sw_put, | ||
764 | .private_value = 0x10, | ||
765 | }, | ||
766 | |||
767 | {} | ||
768 | }; | ||
769 | |||
770 | static const struct snd_kcontrol_new cxt5045_benq_mixers[] = { | ||
771 | HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x3, HDA_INPUT), | ||
772 | HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x3, HDA_INPUT), | ||
773 | |||
774 | {} | ||
775 | }; | ||
776 | |||
777 | static const struct hda_verb cxt5045_init_verbs[] = { | ||
778 | /* Line in, Mic */ | ||
779 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
780 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
781 | /* HP, Amp */ | ||
782 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
783 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
784 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
785 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
786 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
787 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
788 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
789 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
790 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
791 | /* Record selector: Internal mic */ | ||
792 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, | ||
793 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | ||
794 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
795 | /* SPDIF route: PCM */ | ||
796 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
797 | { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
798 | /* EAPD */ | ||
799 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ | ||
800 | { } /* end */ | ||
801 | }; | ||
802 | |||
803 | static const struct hda_verb cxt5045_benq_init_verbs[] = { | ||
804 | /* Internal Mic, Mic */ | ||
805 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
806 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | ||
807 | /* Line In,HP, Amp */ | ||
808 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
809 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
810 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
811 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
812 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
813 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
814 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
815 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
816 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
817 | /* Record selector: Internal mic */ | ||
818 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
819 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | ||
820 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
821 | /* SPDIF route: PCM */ | ||
822 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
823 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
824 | /* EAPD */ | ||
825 | {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
826 | { } /* end */ | ||
827 | }; | ||
828 | |||
829 | static const struct hda_verb cxt5045_hp_sense_init_verbs[] = { | ||
830 | /* pin sensing on HP jack */ | ||
831 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
832 | { } /* end */ | ||
833 | }; | ||
834 | |||
835 | static const struct hda_verb cxt5045_mic_sense_init_verbs[] = { | ||
836 | /* pin sensing on HP jack */ | ||
837 | {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
838 | { } /* end */ | ||
839 | }; | ||
840 | |||
841 | #ifdef CONFIG_SND_DEBUG | ||
842 | /* Test configuration for debugging, modelled after the ALC260 test | ||
843 | * configuration. | ||
844 | */ | ||
845 | static const struct hda_input_mux cxt5045_test_capture_source = { | ||
846 | .num_items = 5, | ||
847 | .items = { | ||
848 | { "MIXER", 0x0 }, | ||
849 | { "MIC1 pin", 0x1 }, | ||
850 | { "LINE1 pin", 0x2 }, | ||
851 | { "HP-OUT pin", 0x3 }, | ||
852 | { "CD pin", 0x4 }, | ||
853 | }, | ||
854 | }; | ||
855 | |||
856 | static const struct snd_kcontrol_new cxt5045_test_mixer[] = { | ||
857 | |||
858 | /* Output controls */ | ||
859 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
860 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
861 | HDA_CODEC_VOLUME("HP-OUT Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
862 | HDA_CODEC_MUTE("HP-OUT Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
863 | HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
864 | HDA_CODEC_MUTE("LINE1 Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
865 | |||
866 | /* Modes for retasking pin widgets */ | ||
867 | CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), | ||
868 | CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT), | ||
869 | |||
870 | /* EAPD Switch Control */ | ||
871 | CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), | ||
872 | |||
873 | /* Loopback mixer controls */ | ||
874 | |||
875 | HDA_CODEC_VOLUME("PCM Volume", 0x17, 0x0, HDA_INPUT), | ||
876 | HDA_CODEC_MUTE("PCM Switch", 0x17, 0x0, HDA_INPUT), | ||
877 | HDA_CODEC_VOLUME("MIC1 pin Volume", 0x17, 0x1, HDA_INPUT), | ||
878 | HDA_CODEC_MUTE("MIC1 pin Switch", 0x17, 0x1, HDA_INPUT), | ||
879 | HDA_CODEC_VOLUME("LINE1 pin Volume", 0x17, 0x2, HDA_INPUT), | ||
880 | HDA_CODEC_MUTE("LINE1 pin Switch", 0x17, 0x2, HDA_INPUT), | ||
881 | HDA_CODEC_VOLUME("HP-OUT pin Volume", 0x17, 0x3, HDA_INPUT), | ||
882 | HDA_CODEC_MUTE("HP-OUT pin Switch", 0x17, 0x3, HDA_INPUT), | ||
883 | HDA_CODEC_VOLUME("CD pin Volume", 0x17, 0x4, HDA_INPUT), | ||
884 | HDA_CODEC_MUTE("CD pin Switch", 0x17, 0x4, HDA_INPUT), | ||
885 | { | ||
886 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
887 | .name = "Input Source", | ||
888 | .info = conexant_mux_enum_info, | ||
889 | .get = conexant_mux_enum_get, | ||
890 | .put = conexant_mux_enum_put, | ||
891 | }, | ||
892 | /* Audio input controls */ | ||
893 | HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), | ||
894 | HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), | ||
895 | { } /* end */ | ||
896 | }; | ||
897 | |||
898 | static const struct hda_verb cxt5045_test_init_verbs[] = { | ||
899 | /* Set connections */ | ||
900 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
901 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
902 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
903 | /* Enable retasking pins as output, initially without power amp */ | ||
904 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
905 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
906 | |||
907 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
908 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
909 | * payload also sets the generation to 0, output to be in "consumer" | ||
910 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
911 | * control. | ||
912 | */ | ||
913 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
914 | {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
915 | |||
916 | /* Unmute retasking pin widget output buffers since the default | ||
917 | * state appears to be output. As the pin mode is changed by the | ||
918 | * user the pin mode control will take care of enabling the pin's | ||
919 | * input/output buffers as needed. | ||
920 | */ | ||
921 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
922 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
923 | |||
924 | /* Mute capture amp left and right */ | ||
925 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
926 | |||
927 | /* Set ADC connection select to match default mixer setting (mic1 | ||
928 | * pin) | ||
929 | */ | ||
930 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
931 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
932 | |||
933 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
934 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer */ | ||
935 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */ | ||
936 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */ | ||
937 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */ | ||
938 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
939 | |||
940 | { } | ||
941 | }; | ||
942 | #endif | ||
943 | |||
944 | |||
945 | /* initialize jack-sensing, too */ | ||
946 | static int cxt5045_init(struct hda_codec *codec) | ||
947 | { | ||
948 | conexant_init(codec); | ||
949 | cxt5045_hp_automute(codec); | ||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | |||
954 | enum { | ||
955 | CXT5045_LAPTOP_HPSENSE, | ||
956 | CXT5045_LAPTOP_MICSENSE, | ||
957 | CXT5045_LAPTOP_HPMICSENSE, | ||
958 | CXT5045_BENQ, | ||
959 | #ifdef CONFIG_SND_DEBUG | ||
960 | CXT5045_TEST, | ||
961 | #endif | ||
962 | CXT5045_AUTO, | ||
963 | CXT5045_MODELS | ||
964 | }; | ||
965 | |||
966 | static const char * const cxt5045_models[CXT5045_MODELS] = { | ||
967 | [CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense", | ||
968 | [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense", | ||
969 | [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense", | ||
970 | [CXT5045_BENQ] = "benq", | ||
971 | #ifdef CONFIG_SND_DEBUG | ||
972 | [CXT5045_TEST] = "test", | ||
973 | #endif | ||
974 | [CXT5045_AUTO] = "auto", | ||
975 | }; | ||
976 | |||
977 | static const struct snd_pci_quirk cxt5045_cfg_tbl[] = { | ||
978 | SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), | ||
979 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), | ||
980 | SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE), | ||
981 | SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", | ||
982 | CXT5045_LAPTOP_HPMICSENSE), | ||
983 | SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
984 | SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
985 | SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), | ||
986 | SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", | ||
987 | CXT5045_LAPTOP_HPMICSENSE), | ||
988 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), | ||
989 | {} | ||
990 | }; | ||
991 | |||
992 | static int patch_cxt5045(struct hda_codec *codec) | ||
993 | { | ||
994 | struct conexant_spec *spec; | ||
995 | int board_config; | ||
996 | |||
997 | board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, | ||
998 | cxt5045_models, | ||
999 | cxt5045_cfg_tbl); | ||
1000 | if (board_config < 0) | ||
1001 | board_config = CXT5045_AUTO; /* model=auto as default */ | ||
1002 | if (board_config == CXT5045_AUTO) | ||
1003 | return patch_conexant_auto(codec); | ||
1004 | |||
1005 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1006 | if (!spec) | ||
1007 | return -ENOMEM; | ||
1008 | codec->spec = spec; | ||
1009 | codec->single_adc_amp = 1; | ||
1010 | |||
1011 | spec->multiout.max_channels = 2; | ||
1012 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); | ||
1013 | spec->multiout.dac_nids = cxt5045_dac_nids; | ||
1014 | spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT; | ||
1015 | spec->num_adc_nids = 1; | ||
1016 | spec->adc_nids = cxt5045_adc_nids; | ||
1017 | spec->capsrc_nids = cxt5045_capsrc_nids; | ||
1018 | spec->input_mux = &cxt5045_capture_source; | ||
1019 | spec->num_mixers = 1; | ||
1020 | spec->mixers[0] = cxt5045_mixers; | ||
1021 | spec->num_init_verbs = 1; | ||
1022 | spec->init_verbs[0] = cxt5045_init_verbs; | ||
1023 | spec->spdif_route = 0; | ||
1024 | spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes); | ||
1025 | spec->channel_mode = cxt5045_modes; | ||
1026 | |||
1027 | set_beep_amp(spec, 0x16, 0, 1); | ||
1028 | |||
1029 | codec->patch_ops = conexant_patch_ops; | ||
1030 | |||
1031 | switch (board_config) { | ||
1032 | case CXT5045_LAPTOP_HPSENSE: | ||
1033 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1034 | spec->input_mux = &cxt5045_capture_source; | ||
1035 | spec->num_init_verbs = 2; | ||
1036 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
1037 | spec->mixers[0] = cxt5045_mixers; | ||
1038 | codec->patch_ops.init = cxt5045_init; | ||
1039 | break; | ||
1040 | case CXT5045_LAPTOP_MICSENSE: | ||
1041 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1042 | spec->input_mux = &cxt5045_capture_source; | ||
1043 | spec->num_init_verbs = 2; | ||
1044 | spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; | ||
1045 | spec->mixers[0] = cxt5045_mixers; | ||
1046 | codec->patch_ops.init = cxt5045_init; | ||
1047 | break; | ||
1048 | default: | ||
1049 | case CXT5045_LAPTOP_HPMICSENSE: | ||
1050 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1051 | spec->input_mux = &cxt5045_capture_source; | ||
1052 | spec->num_init_verbs = 3; | ||
1053 | spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; | ||
1054 | spec->init_verbs[2] = cxt5045_mic_sense_init_verbs; | ||
1055 | spec->mixers[0] = cxt5045_mixers; | ||
1056 | codec->patch_ops.init = cxt5045_init; | ||
1057 | break; | ||
1058 | case CXT5045_BENQ: | ||
1059 | codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; | ||
1060 | spec->input_mux = &cxt5045_capture_source_benq; | ||
1061 | spec->num_init_verbs = 1; | ||
1062 | spec->init_verbs[0] = cxt5045_benq_init_verbs; | ||
1063 | spec->mixers[0] = cxt5045_mixers; | ||
1064 | spec->mixers[1] = cxt5045_benq_mixers; | ||
1065 | spec->num_mixers = 2; | ||
1066 | codec->patch_ops.init = cxt5045_init; | ||
1067 | break; | ||
1068 | #ifdef CONFIG_SND_DEBUG | ||
1069 | case CXT5045_TEST: | ||
1070 | spec->input_mux = &cxt5045_test_capture_source; | ||
1071 | spec->mixers[0] = cxt5045_test_mixer; | ||
1072 | spec->init_verbs[0] = cxt5045_test_init_verbs; | ||
1073 | break; | ||
1074 | |||
1075 | #endif | ||
1076 | } | ||
1077 | |||
1078 | switch (codec->subsystem_id >> 16) { | ||
1079 | case 0x103c: | ||
1080 | case 0x1631: | ||
1081 | case 0x1734: | ||
1082 | case 0x17aa: | ||
1083 | /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have | ||
1084 | * really bad sound over 0dB on NID 0x17. Fix max PCM level to | ||
1085 | * 0 dB (originally it has 0x2b steps with 0dB offset 0x14) | ||
1086 | */ | ||
1087 | snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, | ||
1088 | (0x14 << AC_AMPCAP_OFFSET_SHIFT) | | ||
1089 | (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
1090 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
1091 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
1092 | break; | ||
1093 | } | ||
1094 | |||
1095 | if (spec->beep_amp) | ||
1096 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | |||
1102 | /* Conexant 5047 specific */ | ||
1103 | #define CXT5047_SPDIF_OUT 0x11 | ||
1104 | |||
1105 | static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ | ||
1106 | static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; | ||
1107 | static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; | ||
1108 | |||
1109 | static const struct hda_channel_mode cxt5047_modes[1] = { | ||
1110 | { 2, NULL }, | ||
1111 | }; | ||
1112 | |||
1113 | static const struct hda_input_mux cxt5047_toshiba_capture_source = { | ||
1114 | .num_items = 2, | ||
1115 | .items = { | ||
1116 | { "ExtMic", 0x2 }, | ||
1117 | { "Line-In", 0x1 }, | ||
1118 | } | ||
1119 | }; | ||
1120 | |||
1121 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1122 | static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1123 | struct snd_ctl_elem_value *ucontrol) | ||
1124 | { | ||
1125 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1126 | struct conexant_spec *spec = codec->spec; | ||
1127 | unsigned int bits; | ||
1128 | |||
1129 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1130 | return 0; | ||
1131 | |||
1132 | /* toggle internal speakers mute depending of presence of | ||
1133 | * the headphone jack | ||
1134 | */ | ||
1135 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; | ||
1136 | /* NOTE: Conexat codec needs the index for *OUTPUT* amp of | ||
1137 | * pin widgets unlike other codecs. In this case, we need to | ||
1138 | * set index 0x01 for the volume from the mixer amp 0x19. | ||
1139 | */ | ||
1140 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1141 | HDA_AMP_MUTE, bits); | ||
1142 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; | ||
1143 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, | ||
1144 | HDA_AMP_MUTE, bits); | ||
1145 | return 1; | ||
1146 | } | ||
1147 | |||
1148 | /* mute internal speaker if HP is plugged */ | ||
1149 | static void cxt5047_hp_automute(struct hda_codec *codec) | ||
1150 | { | ||
1151 | struct conexant_spec *spec = codec->spec; | ||
1152 | unsigned int bits; | ||
1153 | |||
1154 | spec->hp_present = snd_hda_jack_detect(codec, 0x13); | ||
1155 | |||
1156 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; | ||
1157 | /* See the note in cxt5047_hp_master_sw_put */ | ||
1158 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, | ||
1159 | HDA_AMP_MUTE, bits); | ||
1160 | } | ||
1161 | |||
1162 | /* toggle input of built-in and mic jack appropriately */ | ||
1163 | static void cxt5047_hp_automic(struct hda_codec *codec) | ||
1164 | { | ||
1165 | static const struct hda_verb mic_jack_on[] = { | ||
1166 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1167 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1168 | {} | ||
1169 | }; | ||
1170 | static const struct hda_verb mic_jack_off[] = { | ||
1171 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1172 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1173 | {} | ||
1174 | }; | ||
1175 | unsigned int present; | ||
1176 | |||
1177 | present = snd_hda_jack_detect(codec, 0x15); | ||
1178 | if (present) | ||
1179 | snd_hda_sequence_write(codec, mic_jack_on); | ||
1180 | else | ||
1181 | snd_hda_sequence_write(codec, mic_jack_off); | ||
1182 | } | ||
1183 | |||
1184 | /* unsolicited event for HP jack sensing */ | ||
1185 | static void cxt5047_hp_unsol_event(struct hda_codec *codec, | ||
1186 | unsigned int res) | ||
1187 | { | ||
1188 | switch (res >> 26) { | ||
1189 | case CONEXANT_HP_EVENT: | ||
1190 | cxt5047_hp_automute(codec); | ||
1191 | break; | ||
1192 | case CONEXANT_MIC_EVENT: | ||
1193 | cxt5047_hp_automic(codec); | ||
1194 | break; | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | static const struct snd_kcontrol_new cxt5047_base_mixers[] = { | ||
1199 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), | ||
1200 | HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), | ||
1201 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1202 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | ||
1203 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | ||
1204 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1205 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | ||
1206 | { | ||
1207 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1208 | .name = "Master Playback Switch", | ||
1209 | .info = cxt_eapd_info, | ||
1210 | .get = cxt_eapd_get, | ||
1211 | .put = cxt5047_hp_master_sw_put, | ||
1212 | .private_value = 0x13, | ||
1213 | }, | ||
1214 | |||
1215 | {} | ||
1216 | }; | ||
1217 | |||
1218 | static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { | ||
1219 | /* See the note in cxt5047_hp_master_sw_put */ | ||
1220 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), | ||
1221 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1222 | {} | ||
1223 | }; | ||
1224 | |||
1225 | static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { | ||
1226 | HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), | ||
1227 | { } /* end */ | ||
1228 | }; | ||
1229 | |||
1230 | static const struct hda_verb cxt5047_init_verbs[] = { | ||
1231 | /* Line in, Mic, Built-in Mic */ | ||
1232 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
1233 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | ||
1234 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, | ||
1235 | /* HP, Speaker */ | ||
1236 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
1237 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ | ||
1238 | {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ | ||
1239 | /* Record selector: Mic */ | ||
1240 | {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, | ||
1241 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1242 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | ||
1243 | {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, | ||
1244 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1245 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, | ||
1246 | {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1247 | AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, | ||
1248 | /* SPDIF route: PCM */ | ||
1249 | { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, | ||
1250 | /* Enable unsolicited events */ | ||
1251 | {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
1252 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
1253 | { } /* end */ | ||
1254 | }; | ||
1255 | |||
1256 | /* configuration for Toshiba Laptops */ | ||
1257 | static const struct hda_verb cxt5047_toshiba_init_verbs[] = { | ||
1258 | {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ | ||
1259 | {} | ||
1260 | }; | ||
1261 | |||
1262 | /* Test configuration for debugging, modelled after the ALC260 test | ||
1263 | * configuration. | ||
1264 | */ | ||
1265 | #ifdef CONFIG_SND_DEBUG | ||
1266 | static const struct hda_input_mux cxt5047_test_capture_source = { | ||
1267 | .num_items = 4, | ||
1268 | .items = { | ||
1269 | { "LINE1 pin", 0x0 }, | ||
1270 | { "MIC1 pin", 0x1 }, | ||
1271 | { "MIC2 pin", 0x2 }, | ||
1272 | { "CD pin", 0x3 }, | ||
1273 | }, | ||
1274 | }; | ||
1275 | |||
1276 | static const struct snd_kcontrol_new cxt5047_test_mixer[] = { | ||
1277 | |||
1278 | /* Output only controls */ | ||
1279 | HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT), | ||
1280 | HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT), | ||
1281 | HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT), | ||
1282 | HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT), | ||
1283 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | ||
1284 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
1285 | HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
1286 | HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
1287 | HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT), | ||
1288 | HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
1289 | HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT), | ||
1290 | HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
1291 | |||
1292 | /* Modes for retasking pin widgets */ | ||
1293 | CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT), | ||
1294 | CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT), | ||
1295 | |||
1296 | /* EAPD Switch Control */ | ||
1297 | CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0), | ||
1298 | |||
1299 | /* Loopback mixer controls */ | ||
1300 | HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT), | ||
1301 | HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT), | ||
1302 | HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT), | ||
1303 | HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT), | ||
1304 | HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT), | ||
1305 | HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT), | ||
1306 | HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT), | ||
1307 | HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT), | ||
1308 | |||
1309 | HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT), | ||
1310 | HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT), | ||
1311 | HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT), | ||
1312 | HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT), | ||
1313 | HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT), | ||
1314 | HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT), | ||
1315 | HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT), | ||
1316 | HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT), | ||
1317 | { | ||
1318 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1319 | .name = "Input Source", | ||
1320 | .info = conexant_mux_enum_info, | ||
1321 | .get = conexant_mux_enum_get, | ||
1322 | .put = conexant_mux_enum_put, | ||
1323 | }, | ||
1324 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
1325 | |||
1326 | { } /* end */ | ||
1327 | }; | ||
1328 | |||
1329 | static const struct hda_verb cxt5047_test_init_verbs[] = { | ||
1330 | /* Enable retasking pins as output, initially without power amp */ | ||
1331 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1332 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1333 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1334 | |||
1335 | /* Disable digital (SPDIF) pins initially, but users can enable | ||
1336 | * them via a mixer switch. In the case of SPDIF-out, this initverb | ||
1337 | * payload also sets the generation to 0, output to be in "consumer" | ||
1338 | * PCM format, copyright asserted, no pre-emphasis and no validity | ||
1339 | * control. | ||
1340 | */ | ||
1341 | {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, | ||
1342 | |||
1343 | /* Ensure mic1, mic2, line1 pin widgets take input from the | ||
1344 | * OUT1 sum bus when acting as an output. | ||
1345 | */ | ||
1346 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1347 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1348 | |||
1349 | /* Start with output sum widgets muted and their output gains at min */ | ||
1350 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1351 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1352 | |||
1353 | /* Unmute retasking pin widget output buffers since the default | ||
1354 | * state appears to be output. As the pin mode is changed by the | ||
1355 | * user the pin mode control will take care of enabling the pin's | ||
1356 | * input/output buffers as needed. | ||
1357 | */ | ||
1358 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1359 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1360 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1361 | |||
1362 | /* Mute capture amp left and right */ | ||
1363 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1364 | |||
1365 | /* Set ADC connection select to match default mixer setting (mic1 | ||
1366 | * pin) | ||
1367 | */ | ||
1368 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1369 | |||
1370 | /* Mute all inputs to mixer widget (even unconnected ones) */ | ||
1371 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | ||
1372 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ | ||
1373 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ | ||
1374 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ | ||
1375 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ | ||
1376 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ | ||
1377 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ | ||
1378 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ | ||
1379 | |||
1380 | { } | ||
1381 | }; | ||
1382 | #endif | ||
1383 | |||
1384 | |||
1385 | /* initialize jack-sensing, too */ | ||
1386 | static int cxt5047_hp_init(struct hda_codec *codec) | ||
1387 | { | ||
1388 | conexant_init(codec); | ||
1389 | cxt5047_hp_automute(codec); | ||
1390 | return 0; | ||
1391 | } | ||
1392 | |||
1393 | |||
1394 | enum { | ||
1395 | CXT5047_LAPTOP, /* Laptops w/o EAPD support */ | ||
1396 | CXT5047_LAPTOP_HP, /* Some HP laptops */ | ||
1397 | CXT5047_LAPTOP_EAPD, /* Laptops with EAPD support */ | ||
1398 | #ifdef CONFIG_SND_DEBUG | ||
1399 | CXT5047_TEST, | ||
1400 | #endif | ||
1401 | CXT5047_AUTO, | ||
1402 | CXT5047_MODELS | ||
1403 | }; | ||
1404 | |||
1405 | static const char * const cxt5047_models[CXT5047_MODELS] = { | ||
1406 | [CXT5047_LAPTOP] = "laptop", | ||
1407 | [CXT5047_LAPTOP_HP] = "laptop-hp", | ||
1408 | [CXT5047_LAPTOP_EAPD] = "laptop-eapd", | ||
1409 | #ifdef CONFIG_SND_DEBUG | ||
1410 | [CXT5047_TEST] = "test", | ||
1411 | #endif | ||
1412 | [CXT5047_AUTO] = "auto", | ||
1413 | }; | ||
1414 | |||
1415 | static const struct snd_pci_quirk cxt5047_cfg_tbl[] = { | ||
1416 | SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), | ||
1417 | SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", | ||
1418 | CXT5047_LAPTOP), | ||
1419 | SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), | ||
1420 | {} | ||
1421 | }; | ||
1422 | |||
1423 | static int patch_cxt5047(struct hda_codec *codec) | ||
1424 | { | ||
1425 | struct conexant_spec *spec; | ||
1426 | int board_config; | ||
1427 | |||
1428 | board_config = snd_hda_check_board_config(codec, CXT5047_MODELS, | ||
1429 | cxt5047_models, | ||
1430 | cxt5047_cfg_tbl); | ||
1431 | if (board_config < 0) | ||
1432 | board_config = CXT5047_AUTO; /* model=auto as default */ | ||
1433 | if (board_config == CXT5047_AUTO) | ||
1434 | return patch_conexant_auto(codec); | ||
1435 | |||
1436 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1437 | if (!spec) | ||
1438 | return -ENOMEM; | ||
1439 | codec->spec = spec; | ||
1440 | codec->pin_amp_workaround = 1; | ||
1441 | |||
1442 | spec->multiout.max_channels = 2; | ||
1443 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); | ||
1444 | spec->multiout.dac_nids = cxt5047_dac_nids; | ||
1445 | spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT; | ||
1446 | spec->num_adc_nids = 1; | ||
1447 | spec->adc_nids = cxt5047_adc_nids; | ||
1448 | spec->capsrc_nids = cxt5047_capsrc_nids; | ||
1449 | spec->num_mixers = 1; | ||
1450 | spec->mixers[0] = cxt5047_base_mixers; | ||
1451 | spec->num_init_verbs = 1; | ||
1452 | spec->init_verbs[0] = cxt5047_init_verbs; | ||
1453 | spec->spdif_route = 0; | ||
1454 | spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes), | ||
1455 | spec->channel_mode = cxt5047_modes, | ||
1456 | |||
1457 | codec->patch_ops = conexant_patch_ops; | ||
1458 | |||
1459 | switch (board_config) { | ||
1460 | case CXT5047_LAPTOP: | ||
1461 | spec->num_mixers = 2; | ||
1462 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1463 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1464 | break; | ||
1465 | case CXT5047_LAPTOP_HP: | ||
1466 | spec->num_mixers = 2; | ||
1467 | spec->mixers[1] = cxt5047_hp_only_mixers; | ||
1468 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1469 | codec->patch_ops.init = cxt5047_hp_init; | ||
1470 | break; | ||
1471 | case CXT5047_LAPTOP_EAPD: | ||
1472 | spec->input_mux = &cxt5047_toshiba_capture_source; | ||
1473 | spec->num_mixers = 2; | ||
1474 | spec->mixers[1] = cxt5047_hp_spk_mixers; | ||
1475 | spec->num_init_verbs = 2; | ||
1476 | spec->init_verbs[1] = cxt5047_toshiba_init_verbs; | ||
1477 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1478 | break; | ||
1479 | #ifdef CONFIG_SND_DEBUG | ||
1480 | case CXT5047_TEST: | ||
1481 | spec->input_mux = &cxt5047_test_capture_source; | ||
1482 | spec->mixers[0] = cxt5047_test_mixer; | ||
1483 | spec->init_verbs[0] = cxt5047_test_init_verbs; | ||
1484 | codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; | ||
1485 | #endif | ||
1486 | } | ||
1487 | spec->vmaster_nid = 0x13; | ||
1488 | |||
1489 | switch (codec->subsystem_id >> 16) { | ||
1490 | case 0x103c: | ||
1491 | /* HP laptops have really bad sound over 0 dB on NID 0x10. | ||
1492 | * Fix max PCM level to 0 dB (originally it has 0x1e steps | ||
1493 | * with 0 dB offset 0x17) | ||
1494 | */ | ||
1495 | snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT, | ||
1496 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
1497 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
1498 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
1499 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
1500 | break; | ||
1501 | } | ||
1502 | |||
1503 | return 0; | ||
1504 | } | ||
1505 | |||
1506 | /* Conexant 5051 specific */ | ||
1507 | static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; | ||
1508 | static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; | ||
1509 | |||
1510 | static const struct hda_channel_mode cxt5051_modes[1] = { | ||
1511 | { 2, NULL }, | ||
1512 | }; | ||
1513 | |||
1514 | static void cxt5051_update_speaker(struct hda_codec *codec) | ||
1515 | { | ||
1516 | struct conexant_spec *spec = codec->spec; | ||
1517 | unsigned int pinctl; | ||
1518 | /* headphone pin */ | ||
1519 | pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; | ||
1520 | snd_hda_set_pin_ctl(codec, 0x16, pinctl); | ||
1521 | /* speaker pin */ | ||
1522 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | ||
1523 | snd_hda_set_pin_ctl(codec, 0x1a, pinctl); | ||
1524 | /* on ideapad there is an additional speaker (subwoofer) to mute */ | ||
1525 | if (spec->ideapad) | ||
1526 | snd_hda_set_pin_ctl(codec, 0x1b, pinctl); | ||
1527 | } | ||
1528 | |||
1529 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1530 | static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1531 | struct snd_ctl_elem_value *ucontrol) | ||
1532 | { | ||
1533 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1534 | |||
1535 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1536 | return 0; | ||
1537 | cxt5051_update_speaker(codec); | ||
1538 | return 1; | ||
1539 | } | ||
1540 | |||
1541 | /* toggle input of built-in and mic jack appropriately */ | ||
1542 | static void cxt5051_portb_automic(struct hda_codec *codec) | ||
1543 | { | ||
1544 | struct conexant_spec *spec = codec->spec; | ||
1545 | unsigned int present; | ||
1546 | |||
1547 | if (!(spec->auto_mic & AUTO_MIC_PORTB)) | ||
1548 | return; | ||
1549 | present = snd_hda_jack_detect(codec, 0x17); | ||
1550 | snd_hda_codec_write(codec, 0x14, 0, | ||
1551 | AC_VERB_SET_CONNECT_SEL, | ||
1552 | present ? 0x01 : 0x00); | ||
1553 | } | ||
1554 | |||
1555 | /* switch the current ADC according to the jack state */ | ||
1556 | static void cxt5051_portc_automic(struct hda_codec *codec) | ||
1557 | { | ||
1558 | struct conexant_spec *spec = codec->spec; | ||
1559 | unsigned int present; | ||
1560 | hda_nid_t new_adc; | ||
1561 | |||
1562 | if (!(spec->auto_mic & AUTO_MIC_PORTC)) | ||
1563 | return; | ||
1564 | present = snd_hda_jack_detect(codec, 0x18); | ||
1565 | if (present) | ||
1566 | spec->cur_adc_idx = 1; | ||
1567 | else | ||
1568 | spec->cur_adc_idx = 0; | ||
1569 | new_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
1570 | if (spec->cur_adc && spec->cur_adc != new_adc) { | ||
1571 | /* stream is running, let's swap the current ADC */ | ||
1572 | __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); | ||
1573 | spec->cur_adc = new_adc; | ||
1574 | snd_hda_codec_setup_stream(codec, new_adc, | ||
1575 | spec->cur_adc_stream_tag, 0, | ||
1576 | spec->cur_adc_format); | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1580 | /* mute internal speaker if HP is plugged */ | ||
1581 | static void cxt5051_hp_automute(struct hda_codec *codec) | ||
1582 | { | ||
1583 | struct conexant_spec *spec = codec->spec; | ||
1584 | |||
1585 | spec->hp_present = snd_hda_jack_detect(codec, 0x16); | ||
1586 | cxt5051_update_speaker(codec); | ||
1587 | } | ||
1588 | |||
1589 | /* unsolicited event for HP jack sensing */ | ||
1590 | static void cxt5051_hp_unsol_event(struct hda_codec *codec, | ||
1591 | unsigned int res) | ||
1592 | { | ||
1593 | switch (res >> 26) { | ||
1594 | case CONEXANT_HP_EVENT: | ||
1595 | cxt5051_hp_automute(codec); | ||
1596 | break; | ||
1597 | case CXT5051_PORTB_EVENT: | ||
1598 | cxt5051_portb_automic(codec); | ||
1599 | break; | ||
1600 | case CXT5051_PORTC_EVENT: | ||
1601 | cxt5051_portc_automic(codec); | ||
1602 | break; | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1606 | static const struct snd_kcontrol_new cxt5051_playback_mixers[] = { | ||
1607 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
1608 | { | ||
1609 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1610 | .name = "Master Playback Switch", | ||
1611 | .info = cxt_eapd_info, | ||
1612 | .get = cxt_eapd_get, | ||
1613 | .put = cxt5051_hp_master_sw_put, | ||
1614 | .private_value = 0x1a, | ||
1615 | }, | ||
1616 | {} | ||
1617 | }; | ||
1618 | |||
1619 | static const struct snd_kcontrol_new cxt5051_capture_mixers[] = { | ||
1620 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1621 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1622 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1623 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1624 | HDA_CODEC_VOLUME("Dock Mic Volume", 0x15, 0x00, HDA_INPUT), | ||
1625 | HDA_CODEC_MUTE("Dock Mic Switch", 0x15, 0x00, HDA_INPUT), | ||
1626 | {} | ||
1627 | }; | ||
1628 | |||
1629 | static const struct snd_kcontrol_new cxt5051_hp_mixers[] = { | ||
1630 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1631 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1632 | HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT), | ||
1633 | HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT), | ||
1634 | {} | ||
1635 | }; | ||
1636 | |||
1637 | static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { | ||
1638 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT), | ||
1639 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT), | ||
1640 | {} | ||
1641 | }; | ||
1642 | |||
1643 | static const struct snd_kcontrol_new cxt5051_f700_mixers[] = { | ||
1644 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT), | ||
1645 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT), | ||
1646 | {} | ||
1647 | }; | ||
1648 | |||
1649 | static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { | ||
1650 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | ||
1651 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | ||
1652 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
1653 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
1654 | {} | ||
1655 | }; | ||
1656 | |||
1657 | static const struct hda_verb cxt5051_init_verbs[] = { | ||
1658 | /* Line in, Mic */ | ||
1659 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1660 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1661 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1662 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1663 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1664 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1665 | /* SPK */ | ||
1666 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1667 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1668 | /* HP, Amp */ | ||
1669 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1670 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1671 | /* DAC1 */ | ||
1672 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1673 | /* Record selector: Internal mic */ | ||
1674 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1675 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1676 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | ||
1677 | /* SPDIF route: PCM */ | ||
1678 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1679 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1680 | /* EAPD */ | ||
1681 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1682 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1683 | { } /* end */ | ||
1684 | }; | ||
1685 | |||
1686 | static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { | ||
1687 | /* Line in, Mic */ | ||
1688 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1689 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1690 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1691 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1692 | /* SPK */ | ||
1693 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1694 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1695 | /* HP, Amp */ | ||
1696 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1697 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1698 | /* DAC1 */ | ||
1699 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1700 | /* Record selector: Internal mic */ | ||
1701 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1702 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1703 | /* SPDIF route: PCM */ | ||
1704 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1705 | /* EAPD */ | ||
1706 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1707 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1708 | { } /* end */ | ||
1709 | }; | ||
1710 | |||
1711 | static const struct hda_verb cxt5051_f700_init_verbs[] = { | ||
1712 | /* Line in, Mic */ | ||
1713 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | ||
1714 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1715 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1716 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
1717 | /* SPK */ | ||
1718 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1719 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1720 | /* HP, Amp */ | ||
1721 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1722 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1723 | /* DAC1 */ | ||
1724 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1725 | /* Record selector: Internal mic */ | ||
1726 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
1727 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
1728 | /* SPDIF route: PCM */ | ||
1729 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
1730 | /* EAPD */ | ||
1731 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
1732 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
1733 | { } /* end */ | ||
1734 | }; | ||
1735 | |||
1736 | static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, | ||
1737 | unsigned int event) | ||
1738 | { | ||
1739 | snd_hda_codec_write(codec, nid, 0, | ||
1740 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1741 | AC_USRSP_EN | event); | ||
1742 | } | ||
1743 | |||
1744 | static const struct hda_verb cxt5051_ideapad_init_verbs[] = { | ||
1745 | /* Subwoofer */ | ||
1746 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1747 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1748 | { } /* end */ | ||
1749 | }; | ||
1750 | |||
1751 | /* initialize jack-sensing, too */ | ||
1752 | static int cxt5051_init(struct hda_codec *codec) | ||
1753 | { | ||
1754 | struct conexant_spec *spec = codec->spec; | ||
1755 | |||
1756 | conexant_init(codec); | ||
1757 | |||
1758 | if (spec->auto_mic & AUTO_MIC_PORTB) | ||
1759 | cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT); | ||
1760 | if (spec->auto_mic & AUTO_MIC_PORTC) | ||
1761 | cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT); | ||
1762 | |||
1763 | if (codec->patch_ops.unsol_event) { | ||
1764 | cxt5051_hp_automute(codec); | ||
1765 | cxt5051_portb_automic(codec); | ||
1766 | cxt5051_portc_automic(codec); | ||
1767 | } | ||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | |||
1772 | enum { | ||
1773 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ | ||
1774 | CXT5051_HP, /* no docking */ | ||
1775 | CXT5051_HP_DV6736, /* HP without mic switch */ | ||
1776 | CXT5051_F700, /* HP Compaq Presario F700 */ | ||
1777 | CXT5051_TOSHIBA, /* Toshiba M300 & co */ | ||
1778 | CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */ | ||
1779 | CXT5051_AUTO, /* auto-parser */ | ||
1780 | CXT5051_MODELS | ||
1781 | }; | ||
1782 | |||
1783 | static const char *const cxt5051_models[CXT5051_MODELS] = { | ||
1784 | [CXT5051_LAPTOP] = "laptop", | ||
1785 | [CXT5051_HP] = "hp", | ||
1786 | [CXT5051_HP_DV6736] = "hp-dv6736", | ||
1787 | [CXT5051_F700] = "hp-700", | ||
1788 | [CXT5051_TOSHIBA] = "toshiba", | ||
1789 | [CXT5051_IDEAPAD] = "ideapad", | ||
1790 | [CXT5051_AUTO] = "auto", | ||
1791 | }; | ||
1792 | |||
1793 | static const struct snd_pci_quirk cxt5051_cfg_tbl[] = { | ||
1794 | SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), | ||
1795 | SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), | ||
1796 | SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700), | ||
1797 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA), | ||
1798 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | ||
1799 | CXT5051_LAPTOP), | ||
1800 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), | ||
1801 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD), | ||
1802 | {} | ||
1803 | }; | ||
1804 | |||
1805 | static int patch_cxt5051(struct hda_codec *codec) | ||
1806 | { | ||
1807 | struct conexant_spec *spec; | ||
1808 | int board_config; | ||
1809 | |||
1810 | board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, | ||
1811 | cxt5051_models, | ||
1812 | cxt5051_cfg_tbl); | ||
1813 | if (board_config < 0) | ||
1814 | board_config = CXT5051_AUTO; /* model=auto as default */ | ||
1815 | if (board_config == CXT5051_AUTO) | ||
1816 | return patch_conexant_auto(codec); | ||
1817 | |||
1818 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1819 | if (!spec) | ||
1820 | return -ENOMEM; | ||
1821 | codec->spec = spec; | ||
1822 | codec->pin_amp_workaround = 1; | ||
1823 | |||
1824 | codec->patch_ops = conexant_patch_ops; | ||
1825 | codec->patch_ops.init = cxt5051_init; | ||
1826 | |||
1827 | spec->multiout.max_channels = 2; | ||
1828 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids); | ||
1829 | spec->multiout.dac_nids = cxt5051_dac_nids; | ||
1830 | spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT; | ||
1831 | spec->num_adc_nids = 1; /* not 2; via auto-mic switch */ | ||
1832 | spec->adc_nids = cxt5051_adc_nids; | ||
1833 | spec->num_mixers = 2; | ||
1834 | spec->mixers[0] = cxt5051_capture_mixers; | ||
1835 | spec->mixers[1] = cxt5051_playback_mixers; | ||
1836 | spec->num_init_verbs = 1; | ||
1837 | spec->init_verbs[0] = cxt5051_init_verbs; | ||
1838 | spec->spdif_route = 0; | ||
1839 | spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes); | ||
1840 | spec->channel_mode = cxt5051_modes; | ||
1841 | spec->cur_adc = 0; | ||
1842 | spec->cur_adc_idx = 0; | ||
1843 | |||
1844 | set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); | ||
1845 | |||
1846 | codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; | ||
1847 | |||
1848 | spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC; | ||
1849 | switch (board_config) { | ||
1850 | case CXT5051_HP: | ||
1851 | spec->mixers[0] = cxt5051_hp_mixers; | ||
1852 | break; | ||
1853 | case CXT5051_HP_DV6736: | ||
1854 | spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; | ||
1855 | spec->mixers[0] = cxt5051_hp_dv6736_mixers; | ||
1856 | spec->auto_mic = 0; | ||
1857 | break; | ||
1858 | case CXT5051_F700: | ||
1859 | spec->init_verbs[0] = cxt5051_f700_init_verbs; | ||
1860 | spec->mixers[0] = cxt5051_f700_mixers; | ||
1861 | spec->auto_mic = 0; | ||
1862 | break; | ||
1863 | case CXT5051_TOSHIBA: | ||
1864 | spec->mixers[0] = cxt5051_toshiba_mixers; | ||
1865 | spec->auto_mic = AUTO_MIC_PORTB; | ||
1866 | break; | ||
1867 | case CXT5051_IDEAPAD: | ||
1868 | spec->init_verbs[spec->num_init_verbs++] = | ||
1869 | cxt5051_ideapad_init_verbs; | ||
1870 | spec->ideapad = 1; | ||
1871 | break; | ||
1872 | } | ||
1873 | |||
1874 | if (spec->beep_amp) | ||
1875 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
1876 | |||
1877 | return 0; | ||
1878 | } | ||
1879 | |||
1880 | /* Conexant 5066 specific */ | ||
1881 | |||
1882 | static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 }; | ||
1883 | static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; | ||
1884 | static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; | ||
1885 | static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 }; | ||
1886 | |||
1887 | static const struct hda_channel_mode cxt5066_modes[1] = { | ||
1888 | { 2, NULL }, | ||
1889 | }; | ||
1890 | |||
1891 | #define HP_PRESENT_PORT_A (1 << 0) | ||
1892 | #define HP_PRESENT_PORT_D (1 << 1) | ||
1893 | #define hp_port_a_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_A) | ||
1894 | #define hp_port_d_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_D) | ||
1895 | |||
1896 | static void cxt5066_update_speaker(struct hda_codec *codec) | ||
1897 | { | ||
1898 | struct conexant_spec *spec = codec->spec; | ||
1899 | unsigned int pinctl; | ||
1900 | |||
1901 | codec_dbg(codec, | ||
1902 | "CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n", | ||
1903 | spec->hp_present, spec->cur_eapd); | ||
1904 | |||
1905 | /* Port A (HP) */ | ||
1906 | pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; | ||
1907 | snd_hda_set_pin_ctl(codec, 0x19, pinctl); | ||
1908 | |||
1909 | /* Port D (HP/LO) */ | ||
1910 | pinctl = spec->cur_eapd ? spec->port_d_mode : 0; | ||
1911 | if (spec->dell_automute || spec->thinkpad) { | ||
1912 | /* Mute if Port A is connected */ | ||
1913 | if (hp_port_a_present(spec)) | ||
1914 | pinctl = 0; | ||
1915 | } else { | ||
1916 | /* Thinkpad/Dell doesn't give pin-D status */ | ||
1917 | if (!hp_port_d_present(spec)) | ||
1918 | pinctl = 0; | ||
1919 | } | ||
1920 | snd_hda_set_pin_ctl(codec, 0x1c, pinctl); | ||
1921 | |||
1922 | /* CLASS_D AMP */ | ||
1923 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | ||
1924 | snd_hda_set_pin_ctl(codec, 0x1f, pinctl); | ||
1925 | } | ||
1926 | |||
1927 | /* turn on/off EAPD (+ mute HP) as a master switch */ | ||
1928 | static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
1929 | struct snd_ctl_elem_value *ucontrol) | ||
1930 | { | ||
1931 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1932 | |||
1933 | if (!cxt_eapd_put(kcontrol, ucontrol)) | ||
1934 | return 0; | ||
1935 | |||
1936 | cxt5066_update_speaker(codec); | ||
1937 | return 1; | ||
1938 | } | ||
1939 | |||
1940 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
1941 | static void cxt5066_vostro_automic(struct hda_codec *codec) | ||
1942 | { | ||
1943 | unsigned int present; | ||
1944 | |||
1945 | struct hda_verb ext_mic_present[] = { | ||
1946 | /* enable external mic, port B */ | ||
1947 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1948 | |||
1949 | /* switch to external mic input */ | ||
1950 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1951 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1952 | |||
1953 | /* disable internal digital mic */ | ||
1954 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1955 | {} | ||
1956 | }; | ||
1957 | static const struct hda_verb ext_mic_absent[] = { | ||
1958 | /* enable internal mic, port C */ | ||
1959 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1960 | |||
1961 | /* switch to internal mic input */ | ||
1962 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
1963 | |||
1964 | /* disable external mic, port B */ | ||
1965 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1966 | {} | ||
1967 | }; | ||
1968 | |||
1969 | present = snd_hda_jack_detect(codec, 0x1a); | ||
1970 | if (present) { | ||
1971 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
1972 | snd_hda_sequence_write(codec, ext_mic_present); | ||
1973 | } else { | ||
1974 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
1975 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
1976 | } | ||
1977 | } | ||
1978 | |||
1979 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
1980 | static void cxt5066_ideapad_automic(struct hda_codec *codec) | ||
1981 | { | ||
1982 | unsigned int present; | ||
1983 | |||
1984 | struct hda_verb ext_mic_present[] = { | ||
1985 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
1986 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1987 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1988 | {} | ||
1989 | }; | ||
1990 | static const struct hda_verb ext_mic_absent[] = { | ||
1991 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
1992 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1993 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
1994 | {} | ||
1995 | }; | ||
1996 | |||
1997 | present = snd_hda_jack_detect(codec, 0x1b); | ||
1998 | if (present) { | ||
1999 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
2000 | snd_hda_sequence_write(codec, ext_mic_present); | ||
2001 | } else { | ||
2002 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
2003 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
2004 | } | ||
2005 | } | ||
2006 | |||
2007 | |||
2008 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
2009 | static void cxt5066_asus_automic(struct hda_codec *codec) | ||
2010 | { | ||
2011 | unsigned int present; | ||
2012 | |||
2013 | present = snd_hda_jack_detect(codec, 0x1b); | ||
2014 | codec_dbg(codec, "CXT5066: external microphone present=%d\n", present); | ||
2015 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, | ||
2016 | present ? 1 : 0); | ||
2017 | } | ||
2018 | |||
2019 | |||
2020 | /* toggle input of built-in digital mic and mic jack appropriately */ | ||
2021 | static void cxt5066_hp_laptop_automic(struct hda_codec *codec) | ||
2022 | { | ||
2023 | unsigned int present; | ||
2024 | |||
2025 | present = snd_hda_jack_detect(codec, 0x1b); | ||
2026 | codec_dbg(codec, "CXT5066: external microphone present=%d\n", present); | ||
2027 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, | ||
2028 | present ? 1 : 3); | ||
2029 | } | ||
2030 | |||
2031 | |||
2032 | /* toggle input of built-in digital mic and mic jack appropriately | ||
2033 | order is: external mic -> dock mic -> interal mic */ | ||
2034 | static void cxt5066_thinkpad_automic(struct hda_codec *codec) | ||
2035 | { | ||
2036 | unsigned int ext_present, dock_present; | ||
2037 | |||
2038 | static const struct hda_verb ext_mic_present[] = { | ||
2039 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2040 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, | ||
2041 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2042 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2043 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2044 | {} | ||
2045 | }; | ||
2046 | static const struct hda_verb dock_mic_present[] = { | ||
2047 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2048 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2049 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2050 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2051 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2052 | {} | ||
2053 | }; | ||
2054 | static const struct hda_verb ext_mic_absent[] = { | ||
2055 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
2056 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2057 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2058 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2059 | {} | ||
2060 | }; | ||
2061 | |||
2062 | ext_present = snd_hda_jack_detect(codec, 0x1b); | ||
2063 | dock_present = snd_hda_jack_detect(codec, 0x1a); | ||
2064 | if (ext_present) { | ||
2065 | codec_dbg(codec, "CXT5066: external microphone detected\n"); | ||
2066 | snd_hda_sequence_write(codec, ext_mic_present); | ||
2067 | } else if (dock_present) { | ||
2068 | codec_dbg(codec, "CXT5066: dock microphone detected\n"); | ||
2069 | snd_hda_sequence_write(codec, dock_mic_present); | ||
2070 | } else { | ||
2071 | codec_dbg(codec, "CXT5066: external microphone absent\n"); | ||
2072 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
2073 | } | ||
2074 | } | ||
2075 | |||
2076 | /* mute internal speaker if HP is plugged */ | ||
2077 | static void cxt5066_hp_automute(struct hda_codec *codec) | ||
2078 | { | ||
2079 | struct conexant_spec *spec = codec->spec; | ||
2080 | unsigned int portA, portD; | ||
2081 | |||
2082 | /* Port A */ | ||
2083 | portA = snd_hda_jack_detect(codec, 0x19); | ||
2084 | |||
2085 | /* Port D */ | ||
2086 | portD = snd_hda_jack_detect(codec, 0x1c); | ||
2087 | |||
2088 | spec->hp_present = portA ? HP_PRESENT_PORT_A : 0; | ||
2089 | spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0; | ||
2090 | codec_dbg(codec, "CXT5066: hp automute portA=%x portD=%x present=%d\n", | ||
2091 | portA, portD, spec->hp_present); | ||
2092 | cxt5066_update_speaker(codec); | ||
2093 | } | ||
2094 | |||
2095 | /* Dispatch the right mic autoswitch function */ | ||
2096 | static void cxt5066_automic(struct hda_codec *codec) | ||
2097 | { | ||
2098 | struct conexant_spec *spec = codec->spec; | ||
2099 | |||
2100 | if (spec->dell_vostro) | ||
2101 | cxt5066_vostro_automic(codec); | ||
2102 | else if (spec->ideapad) | ||
2103 | cxt5066_ideapad_automic(codec); | ||
2104 | else if (spec->thinkpad) | ||
2105 | cxt5066_thinkpad_automic(codec); | ||
2106 | else if (spec->hp_laptop) | ||
2107 | cxt5066_hp_laptop_automic(codec); | ||
2108 | else if (spec->asus) | ||
2109 | cxt5066_asus_automic(codec); | ||
2110 | } | ||
2111 | |||
2112 | /* unsolicited event for jack sensing */ | ||
2113 | static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) | ||
2114 | { | ||
2115 | codec_dbg(codec, "CXT5066: unsol event %x (%x)\n", res, res >> 26); | ||
2116 | switch (res >> 26) { | ||
2117 | case CONEXANT_HP_EVENT: | ||
2118 | cxt5066_hp_automute(codec); | ||
2119 | break; | ||
2120 | case CONEXANT_MIC_EVENT: | ||
2121 | cxt5066_automic(codec); | ||
2122 | break; | ||
2123 | } | ||
2124 | } | ||
2125 | |||
2126 | |||
2127 | static const struct hda_input_mux cxt5066_analog_mic_boost = { | ||
2128 | .num_items = 5, | ||
2129 | .items = { | ||
2130 | { "0dB", 0 }, | ||
2131 | { "10dB", 1 }, | ||
2132 | { "20dB", 2 }, | ||
2133 | { "30dB", 3 }, | ||
2134 | { "40dB", 4 }, | ||
2135 | }, | ||
2136 | }; | ||
2137 | |||
2138 | static void cxt5066_set_mic_boost(struct hda_codec *codec) | ||
2139 | { | ||
2140 | struct conexant_spec *spec = codec->spec; | ||
2141 | snd_hda_codec_write_cache(codec, 0x17, 0, | ||
2142 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
2143 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | | ||
2144 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); | ||
2145 | if (spec->ideapad || spec->thinkpad) { | ||
2146 | /* adjust the internal mic as well...it is not through 0x17 */ | ||
2147 | snd_hda_codec_write_cache(codec, 0x23, 0, | ||
2148 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
2149 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT | | ||
2150 | cxt5066_analog_mic_boost. | ||
2151 | items[spec->mic_boost].index); | ||
2152 | } | ||
2153 | } | ||
2154 | |||
2155 | static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
2156 | struct snd_ctl_elem_info *uinfo) | ||
2157 | { | ||
2158 | return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo); | ||
2159 | } | ||
2160 | |||
2161 | static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
2162 | struct snd_ctl_elem_value *ucontrol) | ||
2163 | { | ||
2164 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2165 | struct conexant_spec *spec = codec->spec; | ||
2166 | ucontrol->value.enumerated.item[0] = spec->mic_boost; | ||
2167 | return 0; | ||
2168 | } | ||
2169 | |||
2170 | static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
2171 | struct snd_ctl_elem_value *ucontrol) | ||
2172 | { | ||
2173 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2174 | struct conexant_spec *spec = codec->spec; | ||
2175 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; | ||
2176 | unsigned int idx; | ||
2177 | idx = ucontrol->value.enumerated.item[0]; | ||
2178 | if (idx >= imux->num_items) | ||
2179 | idx = imux->num_items - 1; | ||
2180 | |||
2181 | spec->mic_boost = idx; | ||
2182 | cxt5066_set_mic_boost(codec); | ||
2183 | return 1; | ||
2184 | } | ||
2185 | |||
2186 | static void conexant_check_dig_outs(struct hda_codec *codec, | ||
2187 | const hda_nid_t *dig_pins, | ||
2188 | int num_pins) | ||
2189 | { | ||
2190 | struct conexant_spec *spec = codec->spec; | ||
2191 | hda_nid_t *nid_loc = &spec->multiout.dig_out_nid; | ||
2192 | int i; | ||
2193 | |||
2194 | for (i = 0; i < num_pins; i++, dig_pins++) { | ||
2195 | unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins); | ||
2196 | if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE) | ||
2197 | continue; | ||
2198 | if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1) | ||
2199 | continue; | ||
2200 | } | ||
2201 | } | ||
2202 | |||
2203 | static const struct hda_input_mux cxt5066_capture_source = { | ||
2204 | .num_items = 4, | ||
2205 | .items = { | ||
2206 | { "Mic B", 0 }, | ||
2207 | { "Mic C", 1 }, | ||
2208 | { "Mic E", 2 }, | ||
2209 | { "Mic F", 3 }, | ||
2210 | }, | ||
2211 | }; | ||
2212 | |||
2213 | static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = { | ||
2214 | .ops = &snd_hda_bind_vol, | ||
2215 | .values = { | ||
2216 | HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), | ||
2217 | HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), | ||
2218 | 0 | ||
2219 | }, | ||
2220 | }; | ||
2221 | |||
2222 | static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = { | ||
2223 | .ops = &snd_hda_bind_sw, | ||
2224 | .values = { | ||
2225 | HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), | ||
2226 | HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), | ||
2227 | 0 | ||
2228 | }, | ||
2229 | }; | ||
2230 | |||
2231 | static const struct snd_kcontrol_new cxt5066_mixer_master[] = { | ||
2232 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
2233 | {} | ||
2234 | }; | ||
2235 | |||
2236 | static const struct snd_kcontrol_new cxt5066_mixers[] = { | ||
2237 | { | ||
2238 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2239 | .name = "Master Playback Switch", | ||
2240 | .info = cxt_eapd_info, | ||
2241 | .get = cxt_eapd_get, | ||
2242 | .put = cxt5066_hp_master_sw_put, | ||
2243 | .private_value = 0x1d, | ||
2244 | }, | ||
2245 | |||
2246 | { | ||
2247 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2248 | .name = "Analog Mic Boost Capture Enum", | ||
2249 | .info = cxt5066_mic_boost_mux_enum_info, | ||
2250 | .get = cxt5066_mic_boost_mux_enum_get, | ||
2251 | .put = cxt5066_mic_boost_mux_enum_put, | ||
2252 | }, | ||
2253 | |||
2254 | HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), | ||
2255 | HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others), | ||
2256 | {} | ||
2257 | }; | ||
2258 | |||
2259 | static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = { | ||
2260 | { | ||
2261 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2262 | .name = "Internal Mic Boost Capture Enum", | ||
2263 | .info = cxt5066_mic_boost_mux_enum_info, | ||
2264 | .get = cxt5066_mic_boost_mux_enum_get, | ||
2265 | .put = cxt5066_mic_boost_mux_enum_put, | ||
2266 | .private_value = 0x23 | 0x100, | ||
2267 | }, | ||
2268 | {} | ||
2269 | }; | ||
2270 | |||
2271 | static const struct hda_verb cxt5066_init_verbs[] = { | ||
2272 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ | ||
2273 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ | ||
2274 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2275 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2276 | |||
2277 | /* Speakers */ | ||
2278 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2279 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2280 | |||
2281 | /* HP, Amp */ | ||
2282 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2283 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2284 | |||
2285 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2286 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2287 | |||
2288 | /* DAC1 */ | ||
2289 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2290 | |||
2291 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2292 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2293 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2294 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2295 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2296 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2297 | |||
2298 | /* no digital microphone support yet */ | ||
2299 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2300 | |||
2301 | /* Audio input selector */ | ||
2302 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, | ||
2303 | |||
2304 | /* SPDIF route: PCM */ | ||
2305 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2306 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2307 | |||
2308 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2309 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2310 | |||
2311 | /* EAPD */ | ||
2312 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2313 | |||
2314 | /* not handling these yet */ | ||
2315 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2316 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2317 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2318 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2319 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2320 | {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2321 | {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2322 | {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, | ||
2323 | { } /* end */ | ||
2324 | }; | ||
2325 | |||
2326 | static const struct hda_verb cxt5066_init_verbs_vostro[] = { | ||
2327 | /* Port A: headphones */ | ||
2328 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2329 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2330 | |||
2331 | /* Port B: external microphone */ | ||
2332 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2333 | |||
2334 | /* Port C: unused */ | ||
2335 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2336 | |||
2337 | /* Port D: unused */ | ||
2338 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2339 | |||
2340 | /* Port E: unused, but has primary EAPD */ | ||
2341 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2342 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2343 | |||
2344 | /* Port F: unused */ | ||
2345 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2346 | |||
2347 | /* Port G: internal speakers */ | ||
2348 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2349 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2350 | |||
2351 | /* DAC1 */ | ||
2352 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2353 | |||
2354 | /* DAC2: unused */ | ||
2355 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2356 | |||
2357 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2358 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2359 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2360 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2361 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2362 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2363 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2364 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2365 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2366 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2367 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2368 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2369 | |||
2370 | /* Digital microphone port */ | ||
2371 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2372 | |||
2373 | /* Audio input selectors */ | ||
2374 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, | ||
2375 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
2376 | |||
2377 | /* Disable SPDIF */ | ||
2378 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2379 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2380 | |||
2381 | /* enable unsolicited events for Port A and B */ | ||
2382 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2383 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2384 | { } /* end */ | ||
2385 | }; | ||
2386 | |||
2387 | static const struct hda_verb cxt5066_init_verbs_ideapad[] = { | ||
2388 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ | ||
2389 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ | ||
2390 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2391 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2392 | |||
2393 | /* Speakers */ | ||
2394 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2395 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2396 | |||
2397 | /* HP, Amp */ | ||
2398 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2399 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2400 | |||
2401 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2402 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2403 | |||
2404 | /* DAC1 */ | ||
2405 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2406 | |||
2407 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2408 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2409 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2410 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2411 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2412 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2413 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ | ||
2414 | |||
2415 | /* Audio input selector */ | ||
2416 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, | ||
2417 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ | ||
2418 | |||
2419 | /* SPDIF route: PCM */ | ||
2420 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2421 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2422 | |||
2423 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2424 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2425 | |||
2426 | /* internal microphone */ | ||
2427 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ | ||
2428 | |||
2429 | /* EAPD */ | ||
2430 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2431 | |||
2432 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2433 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2434 | { } /* end */ | ||
2435 | }; | ||
2436 | |||
2437 | static const struct hda_verb cxt5066_init_verbs_thinkpad[] = { | ||
2438 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2439 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2440 | |||
2441 | /* Port G: internal speakers */ | ||
2442 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2443 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2444 | |||
2445 | /* Port A: HP, Amp */ | ||
2446 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2447 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2448 | |||
2449 | /* Port B: Mic Dock */ | ||
2450 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2451 | |||
2452 | /* Port C: Mic */ | ||
2453 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2454 | |||
2455 | /* Port D: HP Dock, Amp */ | ||
2456 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2457 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2458 | |||
2459 | /* DAC1 */ | ||
2460 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2461 | |||
2462 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2463 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2464 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2465 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2466 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2467 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2468 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ | ||
2469 | |||
2470 | /* Audio input selector */ | ||
2471 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, | ||
2472 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ | ||
2473 | |||
2474 | /* SPDIF route: PCM */ | ||
2475 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2476 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2477 | |||
2478 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2479 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2480 | |||
2481 | /* internal microphone */ | ||
2482 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ | ||
2483 | |||
2484 | /* EAPD */ | ||
2485 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2486 | |||
2487 | /* enable unsolicited events for Port A, B, C and D */ | ||
2488 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2489 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2490 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2491 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2492 | { } /* end */ | ||
2493 | }; | ||
2494 | |||
2495 | static const struct hda_verb cxt5066_init_verbs_portd_lo[] = { | ||
2496 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2497 | { } /* end */ | ||
2498 | }; | ||
2499 | |||
2500 | |||
2501 | static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = { | ||
2502 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2503 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2504 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2505 | { } /* end */ | ||
2506 | }; | ||
2507 | |||
2508 | /* initialize jack-sensing, too */ | ||
2509 | static int cxt5066_init(struct hda_codec *codec) | ||
2510 | { | ||
2511 | codec_dbg(codec, "CXT5066: init\n"); | ||
2512 | conexant_init(codec); | ||
2513 | if (codec->patch_ops.unsol_event) { | ||
2514 | cxt5066_hp_automute(codec); | ||
2515 | cxt5066_automic(codec); | ||
2516 | } | ||
2517 | cxt5066_set_mic_boost(codec); | ||
2518 | return 0; | ||
2519 | } | ||
2520 | |||
2521 | enum { | ||
2522 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ | ||
2523 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ | ||
2524 | CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ | ||
2525 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | ||
2526 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ | ||
2527 | CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */ | ||
2528 | CXT5066_HP_LAPTOP, /* HP Laptop */ | ||
2529 | CXT5066_AUTO, /* BIOS auto-parser */ | ||
2530 | CXT5066_MODELS | ||
2531 | }; | ||
2532 | |||
2533 | static const char * const cxt5066_models[CXT5066_MODELS] = { | ||
2534 | [CXT5066_LAPTOP] = "laptop", | ||
2535 | [CXT5066_DELL_LAPTOP] = "dell-laptop", | ||
2536 | [CXT5066_DELL_VOSTRO] = "dell-vostro", | ||
2537 | [CXT5066_IDEAPAD] = "ideapad", | ||
2538 | [CXT5066_THINKPAD] = "thinkpad", | ||
2539 | [CXT5066_ASUS] = "asus", | ||
2540 | [CXT5066_HP_LAPTOP] = "hp-laptop", | ||
2541 | [CXT5066_AUTO] = "auto", | ||
2542 | }; | ||
2543 | |||
2544 | static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { | ||
2545 | SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), | ||
2546 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), | ||
2547 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), | ||
2548 | SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), | ||
2549 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), | ||
2550 | SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), | ||
2551 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), | ||
2552 | SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS), | ||
2553 | SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS), | ||
2554 | SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), | ||
2555 | SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), | ||
2556 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | ||
2557 | CXT5066_LAPTOP), | ||
2558 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | ||
2559 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), | ||
2560 | SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), | ||
2561 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), | ||
2562 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), | ||
2563 | {} | ||
2564 | }; | ||
2565 | |||
2566 | static int patch_cxt5066(struct hda_codec *codec) | ||
2567 | { | ||
2568 | struct conexant_spec *spec; | ||
2569 | int board_config; | ||
2570 | |||
2571 | board_config = snd_hda_check_board_config(codec, CXT5066_MODELS, | ||
2572 | cxt5066_models, cxt5066_cfg_tbl); | ||
2573 | if (board_config < 0) | ||
2574 | board_config = CXT5066_AUTO; /* model=auto as default */ | ||
2575 | if (board_config == CXT5066_AUTO) | ||
2576 | return patch_conexant_auto(codec); | ||
2577 | |||
2578 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
2579 | if (!spec) | ||
2580 | return -ENOMEM; | ||
2581 | codec->spec = spec; | ||
2582 | |||
2583 | codec->patch_ops = conexant_patch_ops; | ||
2584 | codec->patch_ops.init = conexant_init; | ||
2585 | |||
2586 | spec->dell_automute = 0; | ||
2587 | spec->multiout.max_channels = 2; | ||
2588 | spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids); | ||
2589 | spec->multiout.dac_nids = cxt5066_dac_nids; | ||
2590 | conexant_check_dig_outs(codec, cxt5066_digout_pin_nids, | ||
2591 | ARRAY_SIZE(cxt5066_digout_pin_nids)); | ||
2592 | spec->num_adc_nids = 1; | ||
2593 | spec->adc_nids = cxt5066_adc_nids; | ||
2594 | spec->capsrc_nids = cxt5066_capsrc_nids; | ||
2595 | spec->input_mux = &cxt5066_capture_source; | ||
2596 | |||
2597 | spec->port_d_mode = PIN_HP; | ||
2598 | |||
2599 | spec->num_init_verbs = 1; | ||
2600 | spec->init_verbs[0] = cxt5066_init_verbs; | ||
2601 | spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes); | ||
2602 | spec->channel_mode = cxt5066_modes; | ||
2603 | spec->cur_adc = 0; | ||
2604 | spec->cur_adc_idx = 0; | ||
2605 | |||
2606 | set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); | ||
2607 | |||
2608 | switch (board_config) { | ||
2609 | default: | ||
2610 | case CXT5066_LAPTOP: | ||
2611 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2612 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2613 | break; | ||
2614 | case CXT5066_DELL_LAPTOP: | ||
2615 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2616 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2617 | |||
2618 | spec->port_d_mode = PIN_OUT; | ||
2619 | spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo; | ||
2620 | spec->num_init_verbs++; | ||
2621 | spec->dell_automute = 1; | ||
2622 | break; | ||
2623 | case CXT5066_ASUS: | ||
2624 | case CXT5066_HP_LAPTOP: | ||
2625 | codec->patch_ops.init = cxt5066_init; | ||
2626 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2627 | spec->init_verbs[spec->num_init_verbs] = | ||
2628 | cxt5066_init_verbs_hp_laptop; | ||
2629 | spec->num_init_verbs++; | ||
2630 | spec->hp_laptop = board_config == CXT5066_HP_LAPTOP; | ||
2631 | spec->asus = board_config == CXT5066_ASUS; | ||
2632 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2633 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2634 | /* no S/PDIF out */ | ||
2635 | if (board_config == CXT5066_HP_LAPTOP) | ||
2636 | spec->multiout.dig_out_nid = 0; | ||
2637 | /* input source automatically selected */ | ||
2638 | spec->input_mux = NULL; | ||
2639 | spec->port_d_mode = 0; | ||
2640 | spec->mic_boost = 3; /* default 30dB gain */ | ||
2641 | break; | ||
2642 | |||
2643 | case CXT5066_DELL_VOSTRO: | ||
2644 | codec->patch_ops.init = cxt5066_init; | ||
2645 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2646 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; | ||
2647 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2648 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2649 | spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; | ||
2650 | spec->port_d_mode = 0; | ||
2651 | spec->dell_vostro = 1; | ||
2652 | spec->mic_boost = 3; /* default 30dB gain */ | ||
2653 | |||
2654 | /* no S/PDIF out */ | ||
2655 | spec->multiout.dig_out_nid = 0; | ||
2656 | |||
2657 | /* input source automatically selected */ | ||
2658 | spec->input_mux = NULL; | ||
2659 | break; | ||
2660 | case CXT5066_IDEAPAD: | ||
2661 | codec->patch_ops.init = cxt5066_init; | ||
2662 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2663 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2664 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2665 | spec->init_verbs[0] = cxt5066_init_verbs_ideapad; | ||
2666 | spec->port_d_mode = 0; | ||
2667 | spec->ideapad = 1; | ||
2668 | spec->mic_boost = 2; /* default 20dB gain */ | ||
2669 | |||
2670 | /* no S/PDIF out */ | ||
2671 | spec->multiout.dig_out_nid = 0; | ||
2672 | |||
2673 | /* input source automatically selected */ | ||
2674 | spec->input_mux = NULL; | ||
2675 | break; | ||
2676 | case CXT5066_THINKPAD: | ||
2677 | codec->patch_ops.init = cxt5066_init; | ||
2678 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | ||
2679 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
2680 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
2681 | spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; | ||
2682 | spec->thinkpad = 1; | ||
2683 | spec->port_d_mode = PIN_OUT; | ||
2684 | spec->mic_boost = 2; /* default 20dB gain */ | ||
2685 | |||
2686 | /* no S/PDIF out */ | ||
2687 | spec->multiout.dig_out_nid = 0; | ||
2688 | |||
2689 | /* input source automatically selected */ | ||
2690 | spec->input_mux = NULL; | ||
2691 | break; | ||
2692 | } | ||
2693 | |||
2694 | if (spec->beep_amp) | ||
2695 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
2696 | |||
2697 | return 0; | ||
2698 | } | ||
2699 | |||
2700 | #endif /* ENABLE_CXT_STATIC_QUIRKS */ | ||
2701 | |||
2702 | |||
2703 | /* | 97 | /* |
2704 | * Automatic parser for CX20641 & co | 98 | * Automatic parser for CX20641 & co |
2705 | */ | 99 | */ |
@@ -3487,35 +881,28 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
3487 | return err; | 881 | return err; |
3488 | } | 882 | } |
3489 | 883 | ||
3490 | #ifndef ENABLE_CXT_STATIC_QUIRKS | ||
3491 | #define patch_cxt5045 patch_conexant_auto | ||
3492 | #define patch_cxt5047 patch_conexant_auto | ||
3493 | #define patch_cxt5051 patch_conexant_auto | ||
3494 | #define patch_cxt5066 patch_conexant_auto | ||
3495 | #endif | ||
3496 | |||
3497 | /* | 884 | /* |
3498 | */ | 885 | */ |
3499 | 886 | ||
3500 | static const struct hda_codec_preset snd_hda_preset_conexant[] = { | 887 | static const struct hda_codec_preset snd_hda_preset_conexant[] = { |
3501 | { .id = 0x14f15045, .name = "CX20549 (Venice)", | 888 | { .id = 0x14f15045, .name = "CX20549 (Venice)", |
3502 | .patch = patch_cxt5045 }, | 889 | .patch = patch_conexant_auto }, |
3503 | { .id = 0x14f15047, .name = "CX20551 (Waikiki)", | 890 | { .id = 0x14f15047, .name = "CX20551 (Waikiki)", |
3504 | .patch = patch_cxt5047 }, | 891 | .patch = patch_conexant_auto }, |
3505 | { .id = 0x14f15051, .name = "CX20561 (Hermosa)", | 892 | { .id = 0x14f15051, .name = "CX20561 (Hermosa)", |
3506 | .patch = patch_cxt5051 }, | 893 | .patch = patch_conexant_auto }, |
3507 | { .id = 0x14f15066, .name = "CX20582 (Pebble)", | 894 | { .id = 0x14f15066, .name = "CX20582 (Pebble)", |
3508 | .patch = patch_cxt5066 }, | 895 | .patch = patch_conexant_auto }, |
3509 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", | 896 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", |
3510 | .patch = patch_cxt5066 }, | 897 | .patch = patch_conexant_auto }, |
3511 | { .id = 0x14f15068, .name = "CX20584", | 898 | { .id = 0x14f15068, .name = "CX20584", |
3512 | .patch = patch_cxt5066 }, | 899 | .patch = patch_conexant_auto }, |
3513 | { .id = 0x14f15069, .name = "CX20585", | 900 | { .id = 0x14f15069, .name = "CX20585", |
3514 | .patch = patch_cxt5066 }, | 901 | .patch = patch_conexant_auto }, |
3515 | { .id = 0x14f1506c, .name = "CX20588", | 902 | { .id = 0x14f1506c, .name = "CX20588", |
3516 | .patch = patch_cxt5066 }, | 903 | .patch = patch_conexant_auto }, |
3517 | { .id = 0x14f1506e, .name = "CX20590", | 904 | { .id = 0x14f1506e, .name = "CX20590", |
3518 | .patch = patch_cxt5066 }, | 905 | .patch = patch_conexant_auto }, |
3519 | { .id = 0x14f15097, .name = "CX20631", | 906 | { .id = 0x14f15097, .name = "CX20631", |
3520 | .patch = patch_conexant_auto }, | 907 | .patch = patch_conexant_auto }, |
3521 | { .id = 0x14f15098, .name = "CX20632", | 908 | { .id = 0x14f15098, .name = "CX20632", |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 4fe876b65fda..10b69c8175d2 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -648,7 +648,8 @@ static int get_channel_allocation_order(int ca) | |||
648 | * | 648 | * |
649 | * TODO: it could select the wrong CA from multiple candidates. | 649 | * TODO: it could select the wrong CA from multiple candidates. |
650 | */ | 650 | */ |
651 | static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) | 651 | static int hdmi_channel_allocation(struct hda_codec *codec, |
652 | struct hdmi_eld *eld, int channels) | ||
652 | { | 653 | { |
653 | int i; | 654 | int i; |
654 | int ca = 0; | 655 | int ca = 0; |
@@ -694,7 +695,7 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) | |||
694 | } | 695 | } |
695 | 696 | ||
696 | snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); | 697 | snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); |
697 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 698 | codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
698 | ca, channels, buf); | 699 | ca, channels, buf); |
699 | 700 | ||
700 | return ca; | 701 | return ca; |
@@ -1131,7 +1132,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | |||
1131 | if (!non_pcm && per_pin->chmap_set) | 1132 | if (!non_pcm && per_pin->chmap_set) |
1132 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); | 1133 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); |
1133 | else | 1134 | else |
1134 | ca = hdmi_channel_allocation(eld, channels); | 1135 | ca = hdmi_channel_allocation(codec, eld, channels); |
1135 | if (ca < 0) | 1136 | if (ca < 0) |
1136 | ca = 0; | 1137 | ca = 0; |
1137 | 1138 | ||
@@ -1557,13 +1558,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | |||
1557 | eld->eld_valid = false; | 1558 | eld->eld_valid = false; |
1558 | else { | 1559 | else { |
1559 | memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld)); | 1560 | memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld)); |
1560 | if (snd_hdmi_parse_eld(&eld->info, eld->eld_buffer, | 1561 | if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, |
1561 | eld->eld_size) < 0) | 1562 | eld->eld_size) < 0) |
1562 | eld->eld_valid = false; | 1563 | eld->eld_valid = false; |
1563 | } | 1564 | } |
1564 | 1565 | ||
1565 | if (eld->eld_valid) { | 1566 | if (eld->eld_valid) { |
1566 | snd_hdmi_show_eld(&eld->info); | 1567 | snd_hdmi_show_eld(codec, &eld->info); |
1567 | update_eld = true; | 1568 | update_eld = true; |
1568 | } | 1569 | } |
1569 | else if (repoll) { | 1570 | else if (repoll) { |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b60824e90408..832c2255a620 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -101,6 +101,7 @@ struct alc_spec { | |||
101 | /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ | 101 | /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ |
102 | int mute_led_polarity; | 102 | int mute_led_polarity; |
103 | hda_nid_t mute_led_nid; | 103 | hda_nid_t mute_led_nid; |
104 | hda_nid_t cap_mute_led_nid; | ||
104 | 105 | ||
105 | unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ | 106 | unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ |
106 | 107 | ||
@@ -3520,6 +3521,67 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, | |||
3520 | } | 3521 | } |
3521 | } | 3522 | } |
3522 | 3523 | ||
3524 | /* turn on/off mic-mute LED per capture hook */ | ||
3525 | static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec, | ||
3526 | struct snd_kcontrol *kcontrol, | ||
3527 | struct snd_ctl_elem_value *ucontrol) | ||
3528 | { | ||
3529 | struct alc_spec *spec = codec->spec; | ||
3530 | unsigned int pinval, enable, disable; | ||
3531 | |||
3532 | pinval = snd_hda_codec_get_pin_target(codec, spec->mute_led_nid); | ||
3533 | pinval &= ~AC_PINCTL_VREFEN; | ||
3534 | enable = pinval | AC_PINCTL_VREF_80; | ||
3535 | disable = pinval | AC_PINCTL_VREF_HIZ; | ||
3536 | |||
3537 | if (!ucontrol) | ||
3538 | return; | ||
3539 | |||
3540 | if (ucontrol->value.integer.value[0] || | ||
3541 | ucontrol->value.integer.value[1]) | ||
3542 | pinval = disable; | ||
3543 | else | ||
3544 | pinval = enable; | ||
3545 | |||
3546 | if (spec->cap_mute_led_nid) | ||
3547 | snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval); | ||
3548 | } | ||
3549 | |||
3550 | static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, | ||
3551 | const struct hda_fixup *fix, int action) | ||
3552 | { | ||
3553 | struct alc_spec *spec = codec->spec; | ||
3554 | static const struct hda_verb gpio_init[] = { | ||
3555 | { 0x01, AC_VERB_SET_GPIO_MASK, 0x08 }, | ||
3556 | { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 }, | ||
3557 | {} | ||
3558 | }; | ||
3559 | |||
3560 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3561 | spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook; | ||
3562 | spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; | ||
3563 | spec->gpio_led = 0; | ||
3564 | spec->cap_mute_led_nid = 0x18; | ||
3565 | snd_hda_add_verbs(codec, gpio_init); | ||
3566 | } | ||
3567 | } | ||
3568 | |||
3569 | static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, | ||
3570 | const struct hda_fixup *fix, int action) | ||
3571 | { | ||
3572 | struct alc_spec *spec = codec->spec; | ||
3573 | |||
3574 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3575 | spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook; | ||
3576 | spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook; | ||
3577 | spec->mute_led_polarity = 0; | ||
3578 | spec->mute_led_nid = 0x1a; | ||
3579 | spec->cap_mute_led_nid = 0x18; | ||
3580 | spec->gen.vmaster_mute_enum = 1; | ||
3581 | codec->power_filter = led_power_filter; | ||
3582 | } | ||
3583 | } | ||
3584 | |||
3523 | static void alc_headset_mode_unplugged(struct hda_codec *codec) | 3585 | static void alc_headset_mode_unplugged(struct hda_codec *codec) |
3524 | { | 3586 | { |
3525 | int val; | 3587 | int val; |
@@ -4255,6 +4317,8 @@ enum { | |||
4255 | ALC269_FIXUP_HP_MUTE_LED_MIC1, | 4317 | ALC269_FIXUP_HP_MUTE_LED_MIC1, |
4256 | ALC269_FIXUP_HP_MUTE_LED_MIC2, | 4318 | ALC269_FIXUP_HP_MUTE_LED_MIC2, |
4257 | ALC269_FIXUP_HP_GPIO_LED, | 4319 | ALC269_FIXUP_HP_GPIO_LED, |
4320 | ALC269_FIXUP_HP_GPIO_MIC1_LED, | ||
4321 | ALC269_FIXUP_HP_LINE1_MIC1_LED, | ||
4258 | ALC269_FIXUP_INV_DMIC, | 4322 | ALC269_FIXUP_INV_DMIC, |
4259 | ALC269_FIXUP_LENOVO_DOCK, | 4323 | ALC269_FIXUP_LENOVO_DOCK, |
4260 | ALC269_FIXUP_NO_SHUTUP, | 4324 | ALC269_FIXUP_NO_SHUTUP, |
@@ -4447,6 +4511,14 @@ static const struct hda_fixup alc269_fixups[] = { | |||
4447 | .type = HDA_FIXUP_FUNC, | 4511 | .type = HDA_FIXUP_FUNC, |
4448 | .v.func = alc269_fixup_hp_gpio_led, | 4512 | .v.func = alc269_fixup_hp_gpio_led, |
4449 | }, | 4513 | }, |
4514 | [ALC269_FIXUP_HP_GPIO_MIC1_LED] = { | ||
4515 | .type = HDA_FIXUP_FUNC, | ||
4516 | .v.func = alc269_fixup_hp_gpio_mic1_led, | ||
4517 | }, | ||
4518 | [ALC269_FIXUP_HP_LINE1_MIC1_LED] = { | ||
4519 | .type = HDA_FIXUP_FUNC, | ||
4520 | .v.func = alc269_fixup_hp_line1_mic1_led, | ||
4521 | }, | ||
4450 | [ALC269_FIXUP_INV_DMIC] = { | 4522 | [ALC269_FIXUP_INV_DMIC] = { |
4451 | .type = HDA_FIXUP_FUNC, | 4523 | .type = HDA_FIXUP_FUNC, |
4452 | .v.func = alc_fixup_inv_dmic_0x12, | 4524 | .v.func = alc_fixup_inv_dmic_0x12, |
@@ -4790,6 +4862,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4790 | SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4862 | SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4791 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4863 | SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4792 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4864 | SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4865 | SND_PCI_QUIRK(0x103c, 0x2234, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4866 | SND_PCI_QUIRK(0x103c, 0x2235, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4867 | SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4868 | SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4869 | SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4870 | SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4871 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4872 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4873 | SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4874 | SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4875 | SND_PCI_QUIRK(0x103c, 0x224a, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4876 | SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4877 | SND_PCI_QUIRK(0x103c, 0x224c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4878 | SND_PCI_QUIRK(0x103c, 0x224d, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED), | ||
4793 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4879 | SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4794 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4880 | SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4795 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4881 | SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
@@ -4814,13 +4900,41 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
4814 | SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4900 | SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4815 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4901 | SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4816 | SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4902 | SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4903 | SND_PCI_QUIRK(0x103c, 0x22da, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4904 | SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4905 | SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4906 | SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4907 | SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4817 | /* ALC290 */ | 4908 | /* ALC290 */ |
4909 | SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4910 | SND_PCI_QUIRK(0x103c, 0x2220, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4911 | SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4912 | SND_PCI_QUIRK(0x103c, 0x2222, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4913 | SND_PCI_QUIRK(0x103c, 0x2223, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4914 | SND_PCI_QUIRK(0x103c, 0x2224, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4915 | SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4916 | SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4917 | SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4918 | SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4919 | SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4920 | SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4921 | SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4922 | SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4923 | SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4924 | SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4925 | SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4926 | SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4927 | SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4818 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4928 | SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4819 | SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4929 | SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4820 | SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4930 | SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4821 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4931 | SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4822 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4932 | SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4823 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4933 | SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4934 | SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4935 | SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4936 | SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4937 | SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED), | ||
4824 | SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4938 | SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4825 | SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4939 | SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
4826 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 4940 | SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3744ea4e843d..52bdbdc7786e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -1017,7 +1017,7 @@ static int stac_create_spdif_mux_ctls(struct hda_codec *codec) | |||
1017 | for (i = 0; i < num_cons; i++) { | 1017 | for (i = 0; i < num_cons; i++) { |
1018 | if (snd_BUG_ON(!labels[i])) | 1018 | if (snd_BUG_ON(!labels[i])) |
1019 | return -EINVAL; | 1019 | return -EINVAL; |
1020 | snd_hda_add_imux_item(&spec->spdif_mux, labels[i], i, NULL); | 1020 | snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL); |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer); | 1023 | kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer); |
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 71f4bdcc4055..84f67450924e 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c | |||
@@ -151,13 +151,11 @@ static int send_msg( struct mixart_mgr *mgr, | |||
151 | { | 151 | { |
152 | u32 headptr, tailptr; | 152 | u32 headptr, tailptr; |
153 | u32 msg_frame_address; | 153 | u32 msg_frame_address; |
154 | int err, i; | 154 | int i; |
155 | 155 | ||
156 | if (snd_BUG_ON(msg->size % 4)) | 156 | if (snd_BUG_ON(msg->size % 4)) |
157 | return -EINVAL; | 157 | return -EINVAL; |
158 | 158 | ||
159 | err = 0; | ||
160 | |||
161 | /* get message frame address */ | 159 | /* get message frame address */ |
162 | tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); | 160 | tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); |
163 | headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); | 161 | headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 1272c18a2544..da875dced2ef 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -3880,14 +3880,12 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi | |||
3880 | { | 3880 | { |
3881 | unsigned long flags; | 3881 | unsigned long flags; |
3882 | void (*private_free)(struct snd_trident_voice *); | 3882 | void (*private_free)(struct snd_trident_voice *); |
3883 | void *private_data; | ||
3884 | 3883 | ||
3885 | if (voice == NULL || !voice->use) | 3884 | if (voice == NULL || !voice->use) |
3886 | return; | 3885 | return; |
3887 | snd_trident_clear_voices(trident, voice->number, voice->number); | 3886 | snd_trident_clear_voices(trident, voice->number, voice->number); |
3888 | spin_lock_irqsave(&trident->voice_alloc, flags); | 3887 | spin_lock_irqsave(&trident->voice_alloc, flags); |
3889 | private_free = voice->private_free; | 3888 | private_free = voice->private_free; |
3890 | private_data = voice->private_data; | ||
3891 | voice->private_free = NULL; | 3889 | voice->private_free = NULL; |
3892 | voice->private_data = NULL; | 3890 | voice->private_data = NULL; |
3893 | if (voice->pcm) | 3891 | if (voice->pcm) |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 3102a579660b..04c474658e3c 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -139,12 +139,11 @@ static inline void *offset_ptr(struct snd_trident *trident, int offset) | |||
139 | static struct snd_util_memblk * | 139 | static struct snd_util_memblk * |
140 | search_empty(struct snd_util_memhdr *hdr, int size) | 140 | search_empty(struct snd_util_memhdr *hdr, int size) |
141 | { | 141 | { |
142 | struct snd_util_memblk *blk, *prev; | 142 | struct snd_util_memblk *blk; |
143 | int page, psize; | 143 | int page, psize; |
144 | struct list_head *p; | 144 | struct list_head *p; |
145 | 145 | ||
146 | psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1); | 146 | psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1); |
147 | prev = NULL; | ||
148 | page = 0; | 147 | page = 0; |
149 | list_for_each(p, &hdr->block) { | 148 | list_for_each(p, &hdr->block) { |
150 | blk = list_entry(p, struct snd_util_memblk, list); | 149 | blk = list_entry(p, struct snd_util_memblk, list); |
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index be1b1aa96b7e..b2c3d0d5dca3 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -2534,12 +2534,10 @@ static int snd_dbri_create(struct snd_card *card, | |||
2534 | dbri->op = op; | 2534 | dbri->op = op; |
2535 | dbri->irq = irq; | 2535 | dbri->irq = irq; |
2536 | 2536 | ||
2537 | dbri->dma = dma_alloc_coherent(&op->dev, | 2537 | dbri->dma = dma_zalloc_coherent(&op->dev, sizeof(struct dbri_dma), |
2538 | sizeof(struct dbri_dma), | 2538 | &dbri->dma_dvma, GFP_ATOMIC); |
2539 | &dbri->dma_dvma, GFP_ATOMIC); | ||
2540 | if (!dbri->dma) | 2539 | if (!dbri->dma) |
2541 | return -ENOMEM; | 2540 | return -ENOMEM; |
2542 | memset((void *)dbri->dma, 0, sizeof(struct dbri_dma)); | ||
2543 | 2541 | ||
2544 | dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", | 2542 | dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", |
2545 | dbri->dma, dbri->dma_dvma); | 2543 | dbri->dma, dbri->dma_dvma); |