diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/Kconfig | 3 | ||||
-rw-r--r-- | sound/pci/hda/Makefile | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_beep.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 149 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_eld.c | 7 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 132 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 38 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 184 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 847 | ||||
-rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 840 | ||||
-rw-r--r-- | sound/pci/hda/patch_nvhdmi.c | 278 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 591 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 27 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 41 |
17 files changed, 2015 insertions, 1134 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 556cff937be7..9194c3c1d04a 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -145,6 +145,7 @@ config SND_HDA_CODEC_NVHDMI | |||
145 | 145 | ||
146 | config SND_HDA_CODEC_INTELHDMI | 146 | config SND_HDA_CODEC_INTELHDMI |
147 | bool "Build INTEL HDMI HD-audio codec support" | 147 | bool "Build INTEL HDMI HD-audio codec support" |
148 | select SND_DYNAMIC_MINORS | ||
148 | default y | 149 | default y |
149 | help | 150 | help |
150 | Say Y here to include INTEL HDMI HD-audio codec support in | 151 | Say Y here to include INTEL HDMI HD-audio codec support in |
@@ -157,7 +158,7 @@ config SND_HDA_CODEC_INTELHDMI | |||
157 | 158 | ||
158 | config SND_HDA_ELD | 159 | config SND_HDA_ELD |
159 | def_bool y | 160 | def_bool y |
160 | depends on SND_HDA_CODEC_INTELHDMI | 161 | depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI |
161 | 162 | ||
162 | config SND_HDA_CODEC_CIRRUS | 163 | config SND_HDA_CODEC_CIRRUS |
163 | bool "Build Cirrus Logic codec support" | 164 | bool "Build Cirrus Logic codec support" |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 315a1c4f8998..24bc195b02da 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -3,7 +3,7 @@ snd-hda-intel-objs := hda_intel.o | |||
3 | snd-hda-codec-y := hda_codec.o | 3 | snd-hda-codec-y := hda_codec.o |
4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | 4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o |
6 | # snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o | 6 | snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o |
7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | 8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o |
9 | 9 | ||
@@ -18,7 +18,7 @@ snd-hda-codec-ca0110-objs := patch_ca0110.o | |||
18 | snd-hda-codec-conexant-objs := patch_conexant.o | 18 | snd-hda-codec-conexant-objs := patch_conexant.o |
19 | snd-hda-codec-via-objs := patch_via.o | 19 | snd-hda-codec-via-objs := patch_via.o |
20 | snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o | 20 | snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o |
21 | snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o | 21 | snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o |
22 | 22 | ||
23 | # common driver | 23 | # common driver |
24 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o | 24 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o |
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index e4581a42ace5..29714c818b53 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/input.h> | 22 | #include <linux/input.h> |
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include "hda_beep.h" | 27 | #include "hda_beep.h" |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 76d3c4c049db..a3d638c8c1fd 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -978,8 +978,9 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
978 | * | 978 | * |
979 | * Returns 0 if successful, or a negative error code. | 979 | * Returns 0 if successful, or a negative error code. |
980 | */ | 980 | */ |
981 | int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | 981 | int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, |
982 | struct hda_codec **codecp) | 982 | unsigned int codec_addr, |
983 | struct hda_codec **codecp) | ||
983 | { | 984 | { |
984 | struct hda_codec *codec; | 985 | struct hda_codec *codec; |
985 | char component[31]; | 986 | char component[31]; |
@@ -1186,7 +1187,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | |||
1186 | */ | 1187 | */ |
1187 | 1188 | ||
1188 | /* FIXME: more better hash key? */ | 1189 | /* FIXME: more better hash key? */ |
1189 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) | 1190 | #define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) |
1190 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) | 1191 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) |
1191 | #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) | 1192 | #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) |
1192 | #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) | 1193 | #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) |
@@ -1208,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache) | |||
1208 | } | 1209 | } |
1209 | 1210 | ||
1210 | /* query the hash. allocate an entry if not found. */ | 1211 | /* query the hash. allocate an entry if not found. */ |
1211 | static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | 1212 | static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key) |
1212 | u32 key) | ||
1213 | { | 1213 | { |
1214 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); | 1214 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
1215 | u16 cur = cache->hash[idx]; | 1215 | u16 cur = cache->hash[idx]; |
@@ -1221,17 +1221,27 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
1221 | return info; | 1221 | return info; |
1222 | cur = info->next; | 1222 | cur = info->next; |
1223 | } | 1223 | } |
1224 | return NULL; | ||
1225 | } | ||
1224 | 1226 | ||
1225 | /* add a new hash entry */ | 1227 | /* query the hash. allocate an entry if not found. */ |
1226 | info = snd_array_new(&cache->buf); | 1228 | static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, |
1227 | if (!info) | 1229 | u32 key) |
1228 | return NULL; | 1230 | { |
1229 | cur = snd_array_index(&cache->buf, info); | 1231 | struct hda_cache_head *info = get_hash(cache, key); |
1230 | info->key = key; | 1232 | if (!info) { |
1231 | info->val = 0; | 1233 | u16 idx, cur; |
1232 | info->next = cache->hash[idx]; | 1234 | /* add a new hash entry */ |
1233 | cache->hash[idx] = cur; | 1235 | info = snd_array_new(&cache->buf); |
1234 | 1236 | if (!info) | |
1237 | return NULL; | ||
1238 | cur = snd_array_index(&cache->buf, info); | ||
1239 | info->key = key; | ||
1240 | info->val = 0; | ||
1241 | idx = key % (u16)ARRAY_SIZE(cache->hash); | ||
1242 | info->next = cache->hash[idx]; | ||
1243 | cache->hash[idx] = cur; | ||
1244 | } | ||
1235 | return info; | 1245 | return info; |
1236 | } | 1246 | } |
1237 | 1247 | ||
@@ -1356,7 +1366,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) | |||
1356 | if (!codec->no_trigger_sense) { | 1366 | if (!codec->no_trigger_sense) { |
1357 | pincap = snd_hda_query_pin_caps(codec, nid); | 1367 | pincap = snd_hda_query_pin_caps(codec, nid); |
1358 | if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ | 1368 | if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ |
1359 | snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); | 1369 | snd_hda_codec_read(codec, nid, 0, |
1370 | AC_VERB_SET_PIN_SENSE, 0); | ||
1360 | } | 1371 | } |
1361 | return snd_hda_codec_read(codec, nid, 0, | 1372 | return snd_hda_codec_read(codec, nid, 0, |
1362 | AC_VERB_GET_PIN_SENSE, 0); | 1373 | AC_VERB_GET_PIN_SENSE, 0); |
@@ -1372,8 +1383,8 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense); | |||
1372 | */ | 1383 | */ |
1373 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) | 1384 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) |
1374 | { | 1385 | { |
1375 | u32 sense = snd_hda_pin_sense(codec, nid); | 1386 | u32 sense = snd_hda_pin_sense(codec, nid); |
1376 | return !!(sense & AC_PINSENSE_PRESENCE); | 1387 | return !!(sense & AC_PINSENSE_PRESENCE); |
1377 | } | 1388 | } |
1378 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect); | 1389 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect); |
1379 | 1390 | ||
@@ -1459,6 +1470,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
1459 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); | 1470 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); |
1460 | if (!info) | 1471 | if (!info) |
1461 | return 0; | 1472 | return 0; |
1473 | if (snd_BUG_ON(mask & ~0xff)) | ||
1474 | mask &= 0xff; | ||
1462 | val &= mask; | 1475 | val &= mask; |
1463 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; | 1476 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; |
1464 | if (info->vol[ch] == val) | 1477 | if (info->vol[ch] == val) |
@@ -1484,6 +1497,9 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
1484 | int direction, int idx, int mask, int val) | 1497 | int direction, int idx, int mask, int val) |
1485 | { | 1498 | { |
1486 | int ch, ret = 0; | 1499 | int ch, ret = 0; |
1500 | |||
1501 | if (snd_BUG_ON(mask & ~0xff)) | ||
1502 | mask &= 0xff; | ||
1487 | for (ch = 0; ch < 2; ch++) | 1503 | for (ch = 0; ch < 2; ch++) |
1488 | ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, | 1504 | ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, |
1489 | idx, mask, val); | 1505 | idx, mask, val); |
@@ -1804,6 +1820,8 @@ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, | |||
1804 | item->nid = nid; | 1820 | item->nid = nid; |
1805 | return 0; | 1821 | return 0; |
1806 | } | 1822 | } |
1823 | printk(KERN_ERR "hda-codec: no NID for mapping control %s:%d:%d\n", | ||
1824 | kctl->id.name, kctl->id.index, index); | ||
1807 | return -EINVAL; | 1825 | return -EINVAL; |
1808 | } | 1826 | } |
1809 | EXPORT_SYMBOL_HDA(snd_hda_add_nid); | 1827 | EXPORT_SYMBOL_HDA(snd_hda_add_nid); |
@@ -1952,7 +1970,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
1952 | err = snd_hda_ctl_add(codec, 0, kctl); | 1970 | err = snd_hda_ctl_add(codec, 0, kctl); |
1953 | if (err < 0) | 1971 | if (err < 0) |
1954 | return err; | 1972 | return err; |
1955 | 1973 | ||
1956 | for (s = slaves; *s; s++) { | 1974 | for (s = slaves; *s; s++) { |
1957 | struct snd_kcontrol *sctl; | 1975 | struct snd_kcontrol *sctl; |
1958 | int i = 0; | 1976 | int i = 0; |
@@ -2439,27 +2457,27 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
2439 | { | 2457 | { |
2440 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2458 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2441 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2459 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2442 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), | 2460 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), |
2443 | .info = snd_hda_spdif_mask_info, | 2461 | .info = snd_hda_spdif_mask_info, |
2444 | .get = snd_hda_spdif_cmask_get, | 2462 | .get = snd_hda_spdif_cmask_get, |
2445 | }, | 2463 | }, |
2446 | { | 2464 | { |
2447 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2465 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2448 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2466 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2449 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), | 2467 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), |
2450 | .info = snd_hda_spdif_mask_info, | 2468 | .info = snd_hda_spdif_mask_info, |
2451 | .get = snd_hda_spdif_pmask_get, | 2469 | .get = snd_hda_spdif_pmask_get, |
2452 | }, | 2470 | }, |
2453 | { | 2471 | { |
2454 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2472 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2455 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 2473 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), |
2456 | .info = snd_hda_spdif_mask_info, | 2474 | .info = snd_hda_spdif_mask_info, |
2457 | .get = snd_hda_spdif_default_get, | 2475 | .get = snd_hda_spdif_default_get, |
2458 | .put = snd_hda_spdif_default_put, | 2476 | .put = snd_hda_spdif_default_put, |
2459 | }, | 2477 | }, |
2460 | { | 2478 | { |
2461 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2479 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2462 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), | 2480 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), |
2463 | .info = snd_hda_spdif_out_switch_info, | 2481 | .info = snd_hda_spdif_out_switch_info, |
2464 | .get = snd_hda_spdif_out_switch_get, | 2482 | .get = snd_hda_spdif_out_switch_get, |
2465 | .put = snd_hda_spdif_out_switch_put, | 2483 | .put = snd_hda_spdif_out_switch_put, |
@@ -2610,7 +2628,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, | |||
2610 | static struct snd_kcontrol_new dig_in_ctls[] = { | 2628 | static struct snd_kcontrol_new dig_in_ctls[] = { |
2611 | { | 2629 | { |
2612 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2630 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2613 | .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), | 2631 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), |
2614 | .info = snd_hda_spdif_in_switch_info, | 2632 | .info = snd_hda_spdif_in_switch_info, |
2615 | .get = snd_hda_spdif_in_switch_get, | 2633 | .get = snd_hda_spdif_in_switch_get, |
2616 | .put = snd_hda_spdif_in_switch_put, | 2634 | .put = snd_hda_spdif_in_switch_put, |
@@ -2618,7 +2636,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = { | |||
2618 | { | 2636 | { |
2619 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 2637 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
2620 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2638 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2621 | .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), | 2639 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), |
2622 | .info = snd_hda_spdif_mask_info, | 2640 | .info = snd_hda_spdif_mask_info, |
2623 | .get = snd_hda_spdif_in_status_get, | 2641 | .get = snd_hda_spdif_in_status_get, |
2624 | }, | 2642 | }, |
@@ -2713,6 +2731,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
2713 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); | 2731 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); |
2714 | 2732 | ||
2715 | /** | 2733 | /** |
2734 | * snd_hda_codec_update_cache - check cache and write the cmd only when needed | ||
2735 | * @codec: the HDA codec | ||
2736 | * @nid: NID to send the command | ||
2737 | * @direct: direct flag | ||
2738 | * @verb: the verb to send | ||
2739 | * @parm: the parameter for the verb | ||
2740 | * | ||
2741 | * This function works like snd_hda_codec_write_cache(), but it doesn't send | ||
2742 | * command if the parameter is already identical with the cached value. | ||
2743 | * If not, it sends the command and refreshes the cache. | ||
2744 | * | ||
2745 | * Returns 0 if successful, or a negative error code. | ||
2746 | */ | ||
2747 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | ||
2748 | int direct, unsigned int verb, unsigned int parm) | ||
2749 | { | ||
2750 | struct hda_cache_head *c; | ||
2751 | u32 key; | ||
2752 | |||
2753 | /* parm may contain the verb stuff for get/set amp */ | ||
2754 | verb = verb | (parm >> 8); | ||
2755 | parm &= 0xff; | ||
2756 | key = build_cmd_cache_key(nid, verb); | ||
2757 | mutex_lock(&codec->bus->cmd_mutex); | ||
2758 | c = get_hash(&codec->cmd_cache, key); | ||
2759 | if (c && c->val == parm) { | ||
2760 | mutex_unlock(&codec->bus->cmd_mutex); | ||
2761 | return 0; | ||
2762 | } | ||
2763 | mutex_unlock(&codec->bus->cmd_mutex); | ||
2764 | return snd_hda_codec_write_cache(codec, nid, direct, verb, parm); | ||
2765 | } | ||
2766 | EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache); | ||
2767 | |||
2768 | /** | ||
2716 | * snd_hda_codec_resume_cache - Resume the all commands from the cache | 2769 | * snd_hda_codec_resume_cache - Resume the all commands from the cache |
2717 | * @codec: HD-audio codec | 2770 | * @codec: HD-audio codec |
2718 | * | 2771 | * |
@@ -2882,8 +2935,8 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) | |||
2882 | list_for_each_entry(codec, &bus->codec_list, list) { | 2935 | list_for_each_entry(codec, &bus->codec_list, list) { |
2883 | int err = snd_hda_codec_build_controls(codec); | 2936 | int err = snd_hda_codec_build_controls(codec); |
2884 | if (err < 0) { | 2937 | if (err < 0) { |
2885 | printk(KERN_ERR "hda_codec: cannot build controls" | 2938 | printk(KERN_ERR "hda_codec: cannot build controls " |
2886 | "for #%d (error %d)\n", codec->addr, err); | 2939 | "for #%d (error %d)\n", codec->addr, err); |
2887 | err = snd_hda_codec_reset(codec); | 2940 | err = snd_hda_codec_reset(codec); |
2888 | if (err < 0) { | 2941 | if (err < 0) { |
2889 | printk(KERN_ERR | 2942 | printk(KERN_ERR |
@@ -2979,8 +3032,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
2979 | val |= channels - 1; | 3032 | val |= channels - 1; |
2980 | 3033 | ||
2981 | switch (snd_pcm_format_width(format)) { | 3034 | switch (snd_pcm_format_width(format)) { |
2982 | case 8: val |= 0x00; break; | 3035 | case 8: |
2983 | case 16: val |= 0x10; break; | 3036 | val |= 0x00; |
3037 | break; | ||
3038 | case 16: | ||
3039 | val |= 0x10; | ||
3040 | break; | ||
2984 | case 20: | 3041 | case 20: |
2985 | case 24: | 3042 | case 24: |
2986 | case 32: | 3043 | case 32: |
@@ -3298,7 +3355,8 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) | |||
3298 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) | 3355 | if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) |
3299 | return audio_idx[type][i]; | 3356 | return audio_idx[type][i]; |
3300 | 3357 | ||
3301 | snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]); | 3358 | snd_printk(KERN_WARNING "Too many %s devices\n", |
3359 | snd_hda_pcm_type_name[type]); | ||
3302 | return -EAGAIN; | 3360 | return -EAGAIN; |
3303 | } | 3361 | } |
3304 | 3362 | ||
@@ -3336,7 +3394,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) | |||
3336 | err = codec->patch_ops.build_pcms(codec); | 3394 | err = codec->patch_ops.build_pcms(codec); |
3337 | if (err < 0) { | 3395 | if (err < 0) { |
3338 | printk(KERN_ERR "hda_codec: cannot build PCMs" | 3396 | printk(KERN_ERR "hda_codec: cannot build PCMs" |
3339 | "for #%d (error %d)\n", codec->addr, err); | 3397 | "for #%d (error %d)\n", codec->addr, err); |
3340 | err = snd_hda_codec_reset(codec); | 3398 | err = snd_hda_codec_reset(codec); |
3341 | if (err < 0) { | 3399 | if (err < 0) { |
3342 | printk(KERN_ERR | 3400 | printk(KERN_ERR |
@@ -3466,8 +3524,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config); | |||
3466 | 3524 | ||
3467 | /** | 3525 | /** |
3468 | * snd_hda_check_board_codec_sid_config - compare the current codec | 3526 | * snd_hda_check_board_codec_sid_config - compare the current codec |
3469 | subsystem ID with the | 3527 | subsystem ID with the |
3470 | config table | 3528 | config table |
3471 | 3529 | ||
3472 | This is important for Gateway notebooks with SB450 HDA Audio | 3530 | This is important for Gateway notebooks with SB450 HDA Audio |
3473 | where the vendor ID of the PCI device is: | 3531 | where the vendor ID of the PCI device is: |
@@ -3607,7 +3665,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec) | |||
3607 | * | 3665 | * |
3608 | * Increment the power-up counter and power up the hardware really when | 3666 | * Increment the power-up counter and power up the hardware really when |
3609 | * not turned on yet. | 3667 | * not turned on yet. |
3610 | */ | 3668 | */ |
3611 | void snd_hda_power_up(struct hda_codec *codec) | 3669 | void snd_hda_power_up(struct hda_codec *codec) |
3612 | { | 3670 | { |
3613 | struct hda_bus *bus = codec->bus; | 3671 | struct hda_bus *bus = codec->bus; |
@@ -3636,7 +3694,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up); | |||
3636 | * | 3694 | * |
3637 | * Decrement the power-up counter and schedules the power-off work if | 3695 | * Decrement the power-up counter and schedules the power-off work if |
3638 | * the counter rearches to zero. | 3696 | * the counter rearches to zero. |
3639 | */ | 3697 | */ |
3640 | void snd_hda_power_down(struct hda_codec *codec) | 3698 | void snd_hda_power_down(struct hda_codec *codec) |
3641 | { | 3699 | { |
3642 | --codec->power_count; | 3700 | --codec->power_count; |
@@ -3662,7 +3720,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_down); | |||
3662 | * | 3720 | * |
3663 | * This function is supposed to be set or called from the check_power_status | 3721 | * This function is supposed to be set or called from the check_power_status |
3664 | * patch ops. | 3722 | * patch ops. |
3665 | */ | 3723 | */ |
3666 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | 3724 | int snd_hda_check_amp_list_power(struct hda_codec *codec, |
3667 | struct hda_loopback_check *check, | 3725 | struct hda_loopback_check *check, |
3668 | hda_nid_t nid) | 3726 | hda_nid_t nid) |
@@ -3830,7 +3888,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, | |||
3830 | { | 3888 | { |
3831 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 3889 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
3832 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 3890 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) |
3833 | set_dig_out_convert(codec, nid, | 3891 | set_dig_out_convert(codec, nid, |
3834 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, | 3892 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, |
3835 | -1); | 3893 | -1); |
3836 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | 3894 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); |
@@ -4089,13 +4147,13 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
4089 | /* | 4147 | /* |
4090 | * Sort an associated group of pins according to their sequence numbers. | 4148 | * Sort an associated group of pins according to their sequence numbers. |
4091 | */ | 4149 | */ |
4092 | static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | 4150 | static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, |
4093 | int num_pins) | 4151 | int num_pins) |
4094 | { | 4152 | { |
4095 | int i, j; | 4153 | int i, j; |
4096 | short seq; | 4154 | short seq; |
4097 | hda_nid_t nid; | 4155 | hda_nid_t nid; |
4098 | 4156 | ||
4099 | for (i = 0; i < num_pins; i++) { | 4157 | for (i = 0; i < num_pins; i++) { |
4100 | for (j = i + 1; j < num_pins; j++) { | 4158 | for (j = i + 1; j < num_pins; j++) { |
4101 | if (sequences[i] > sequences[j]) { | 4159 | if (sequences[i] > sequences[j]) { |
@@ -4123,7 +4181,7 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | |||
4123 | * is detected, one of speaker of HP pins is assigned as the primary | 4181 | * is detected, one of speaker of HP pins is assigned as the primary |
4124 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 4182 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
4125 | * if any analog output exists. | 4183 | * if any analog output exists. |
4126 | * | 4184 | * |
4127 | * The analog input pins are assigned to input_pins array. | 4185 | * The analog input pins are assigned to input_pins array. |
4128 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 4186 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
4129 | * respectively. | 4187 | * respectively. |
@@ -4186,9 +4244,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4186 | case AC_JACK_SPEAKER: | 4244 | case AC_JACK_SPEAKER: |
4187 | seq = get_defcfg_sequence(def_conf); | 4245 | seq = get_defcfg_sequence(def_conf); |
4188 | assoc = get_defcfg_association(def_conf); | 4246 | assoc = get_defcfg_association(def_conf); |
4189 | if (! assoc) | 4247 | if (!assoc) |
4190 | continue; | 4248 | continue; |
4191 | if (! assoc_speaker) | 4249 | if (!assoc_speaker) |
4192 | assoc_speaker = assoc; | 4250 | assoc_speaker = assoc; |
4193 | else if (assoc_speaker != assoc) | 4251 | else if (assoc_speaker != assoc) |
4194 | continue; | 4252 | continue; |
@@ -4209,7 +4267,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4209 | break; | 4267 | break; |
4210 | case AC_JACK_MIC_IN: { | 4268 | case AC_JACK_MIC_IN: { |
4211 | int preferred, alt; | 4269 | int preferred, alt; |
4212 | if (loc == AC_JACK_LOC_FRONT) { | 4270 | if (loc == AC_JACK_LOC_FRONT || |
4271 | (loc & 0x30) == AC_JACK_LOC_INTERNAL) { | ||
4213 | preferred = AUTO_PIN_FRONT_MIC; | 4272 | preferred = AUTO_PIN_FRONT_MIC; |
4214 | alt = AUTO_PIN_MIC; | 4273 | alt = AUTO_PIN_MIC; |
4215 | } else { | 4274 | } else { |
@@ -4286,7 +4345,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4286 | cfg->speaker_outs); | 4345 | cfg->speaker_outs); |
4287 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, | 4346 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, |
4288 | cfg->hp_outs); | 4347 | cfg->hp_outs); |
4289 | 4348 | ||
4290 | /* if we have only one mic, make it AUTO_PIN_MIC */ | 4349 | /* if we have only one mic, make it AUTO_PIN_MIC */ |
4291 | if (!cfg->input_pins[AUTO_PIN_MIC] && | 4350 | if (!cfg->input_pins[AUTO_PIN_MIC] && |
4292 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { | 4351 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { |
@@ -4436,7 +4495,7 @@ EXPORT_SYMBOL_HDA(snd_hda_resume); | |||
4436 | /** | 4495 | /** |
4437 | * snd_array_new - get a new element from the given array | 4496 | * snd_array_new - get a new element from the given array |
4438 | * @array: the array object | 4497 | * @array: the array object |
4439 | * | 4498 | * |
4440 | * Get a new element from the given array. If it exceeds the | 4499 | * Get a new element from the given array. If it exceeds the |
4441 | * pre-allocated array size, re-allocate the array. | 4500 | * pre-allocated array size, re-allocate the array. |
4442 | * | 4501 | * |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index b75da47571e6..49e939e7e5cd 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -885,9 +885,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
885 | int direct, unsigned int verb, unsigned int parm); | 885 | int direct, unsigned int verb, unsigned int parm); |
886 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | 886 | void snd_hda_sequence_write_cache(struct hda_codec *codec, |
887 | const struct hda_verb *seq); | 887 | const struct hda_verb *seq); |
888 | int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, | ||
889 | int direct, unsigned int verb, unsigned int parm); | ||
888 | void snd_hda_codec_resume_cache(struct hda_codec *codec); | 890 | void snd_hda_codec_resume_cache(struct hda_codec *codec); |
889 | #else | 891 | #else |
890 | #define snd_hda_codec_write_cache snd_hda_codec_write | 892 | #define snd_hda_codec_write_cache snd_hda_codec_write |
893 | #define snd_hda_codec_update_cache snd_hda_codec_write | ||
891 | #define snd_hda_sequence_write_cache snd_hda_sequence_write | 894 | #define snd_hda_sequence_write_cache snd_hda_sequence_write |
892 | #endif | 895 | #endif |
893 | 896 | ||
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 4228f2fe5956..d8da18a9e98b 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/slab.h> | ||
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
27 | #include "hda_codec.h" | 28 | #include "hda_codec.h" |
@@ -331,6 +332,7 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) | |||
331 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, | 332 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, |
332 | AC_DIPSIZE_ELD_BUF); | 333 | AC_DIPSIZE_ELD_BUF); |
333 | } | 334 | } |
335 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size); | ||
334 | 336 | ||
335 | int snd_hdmi_get_eld(struct hdmi_eld *eld, | 337 | int snd_hdmi_get_eld(struct hdmi_eld *eld, |
336 | struct hda_codec *codec, hda_nid_t nid) | 338 | struct hda_codec *codec, hda_nid_t nid) |
@@ -366,6 +368,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, | |||
366 | kfree(buf); | 368 | kfree(buf); |
367 | return ret; | 369 | return ret; |
368 | } | 370 | } |
371 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld); | ||
369 | 372 | ||
370 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | 373 | static void hdmi_show_short_audio_desc(struct cea_sad *a) |
371 | { | 374 | { |
@@ -404,6 +407,7 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | |||
404 | } | 407 | } |
405 | buf[j] = '\0'; /* necessary when j == 0 */ | 408 | buf[j] = '\0'; /* necessary when j == 0 */ |
406 | } | 409 | } |
410 | EXPORT_SYMBOL_HDA(snd_print_channel_allocation); | ||
407 | 411 | ||
408 | void snd_hdmi_show_eld(struct hdmi_eld *e) | 412 | void snd_hdmi_show_eld(struct hdmi_eld *e) |
409 | { | 413 | { |
@@ -422,6 +426,7 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) | |||
422 | for (i = 0; i < e->sad_count; i++) | 426 | for (i = 0; i < e->sad_count; i++) |
423 | hdmi_show_short_audio_desc(e->sad + i); | 427 | hdmi_show_short_audio_desc(e->sad + i); |
424 | } | 428 | } |
429 | EXPORT_SYMBOL_HDA(snd_hdmi_show_eld); | ||
425 | 430 | ||
426 | #ifdef CONFIG_PROC_FS | 431 | #ifdef CONFIG_PROC_FS |
427 | 432 | ||
@@ -580,6 +585,7 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, | |||
580 | 585 | ||
581 | return 0; | 586 | return 0; |
582 | } | 587 | } |
588 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new); | ||
583 | 589 | ||
584 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | 590 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) |
585 | { | 591 | { |
@@ -588,5 +594,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | |||
588 | eld->proc_entry = NULL; | 594 | eld->proc_entry = NULL; |
589 | } | 595 | } |
590 | } | 596 | } |
597 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); | ||
591 | 598 | ||
592 | #endif /* CONFIG_PROC_FS */ | 599 | #endif /* CONFIG_PROC_FS */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d5c93ad852ee..170610e1d7da 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -84,7 +84,7 @@ module_param_array(bdl_pos_adj, int, NULL, 0644); | |||
84 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); | 84 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); |
85 | module_param_array(probe_mask, int, NULL, 0444); | 85 | module_param_array(probe_mask, int, NULL, 0444); |
86 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); | 86 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); |
87 | module_param_array(probe_only, bool, NULL, 0444); | 87 | module_param_array(probe_only, int, NULL, 0444); |
88 | MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); | 88 | MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); |
89 | module_param(single_cmd, bool, 0444); | 89 | module_param(single_cmd, bool, 0444); |
90 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " | 90 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " |
@@ -174,7 +174,7 @@ MODULE_DESCRIPTION("Intel HDA driver"); | |||
174 | #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ | 174 | #define ICH6_GSTS_FSTS (1 << 1) /* flush status */ |
175 | #define ICH6_REG_INTCTL 0x20 | 175 | #define ICH6_REG_INTCTL 0x20 |
176 | #define ICH6_REG_INTSTS 0x24 | 176 | #define ICH6_REG_INTSTS 0x24 |
177 | #define ICH6_REG_WALCLK 0x30 | 177 | #define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ |
178 | #define ICH6_REG_SYNC 0x34 | 178 | #define ICH6_REG_SYNC 0x34 |
179 | #define ICH6_REG_CORBLBASE 0x40 | 179 | #define ICH6_REG_CORBLBASE 0x40 |
180 | #define ICH6_REG_CORBUBASE 0x44 | 180 | #define ICH6_REG_CORBUBASE 0x44 |
@@ -267,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
267 | #define RIRB_INT_MASK 0x05 | 267 | #define RIRB_INT_MASK 0x05 |
268 | 268 | ||
269 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ | 269 | /* STATESTS int mask: S3,SD2,SD1,SD0 */ |
270 | #define AZX_MAX_CODECS 4 | 270 | #define AZX_MAX_CODECS 8 |
271 | #define AZX_DEFAULT_CODECS 4 | ||
271 | #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) | 272 | #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) |
272 | 273 | ||
273 | /* SD_CTL bits */ | 274 | /* SD_CTL bits */ |
@@ -339,8 +340,8 @@ struct azx_dev { | |||
339 | unsigned int period_bytes; /* size of the period in bytes */ | 340 | unsigned int period_bytes; /* size of the period in bytes */ |
340 | unsigned int frags; /* number for period in the play buffer */ | 341 | unsigned int frags; /* number for period in the play buffer */ |
341 | unsigned int fifo_size; /* FIFO size */ | 342 | unsigned int fifo_size; /* FIFO size */ |
342 | unsigned long start_jiffies; /* start + minimum jiffies */ | 343 | unsigned long start_wallclk; /* start + minimum wallclk */ |
343 | unsigned long min_jiffies; /* minimum jiffies before position is valid */ | 344 | unsigned long period_wallclk; /* wallclk for period */ |
344 | 345 | ||
345 | void __iomem *sd_addr; /* stream descriptor pointer */ | 346 | void __iomem *sd_addr; /* stream descriptor pointer */ |
346 | 347 | ||
@@ -360,7 +361,6 @@ struct azx_dev { | |||
360 | unsigned int opened :1; | 361 | unsigned int opened :1; |
361 | unsigned int running :1; | 362 | unsigned int running :1; |
362 | unsigned int irq_pending :1; | 363 | unsigned int irq_pending :1; |
363 | unsigned int start_flag: 1; /* stream full start flag */ | ||
364 | /* | 364 | /* |
365 | * For VIA: | 365 | * For VIA: |
366 | * A flag to ensure DMA position is 0 | 366 | * A flag to ensure DMA position is 0 |
@@ -424,7 +424,7 @@ struct azx { | |||
424 | struct snd_dma_buffer posbuf; | 424 | struct snd_dma_buffer posbuf; |
425 | 425 | ||
426 | /* flags */ | 426 | /* flags */ |
427 | int position_fix; | 427 | int position_fix[2]; /* for both playback/capture streams */ |
428 | int poll_count; | 428 | int poll_count; |
429 | unsigned int running :1; | 429 | unsigned int running :1; |
430 | unsigned int initialized :1; | 430 | unsigned int initialized :1; |
@@ -857,10 +857,13 @@ static void azx_power_notify(struct hda_bus *bus); | |||
857 | #endif | 857 | #endif |
858 | 858 | ||
859 | /* reset codec link */ | 859 | /* reset codec link */ |
860 | static int azx_reset(struct azx *chip) | 860 | static int azx_reset(struct azx *chip, int full_reset) |
861 | { | 861 | { |
862 | int count; | 862 | int count; |
863 | 863 | ||
864 | if (!full_reset) | ||
865 | goto __skip; | ||
866 | |||
864 | /* clear STATESTS */ | 867 | /* clear STATESTS */ |
865 | azx_writeb(chip, STATESTS, STATESTS_INT_MASK); | 868 | azx_writeb(chip, STATESTS, STATESTS_INT_MASK); |
866 | 869 | ||
@@ -886,6 +889,7 @@ static int azx_reset(struct azx *chip) | |||
886 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ | 889 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ |
887 | msleep(1); | 890 | msleep(1); |
888 | 891 | ||
892 | __skip: | ||
889 | /* check to see if controller is ready */ | 893 | /* check to see if controller is ready */ |
890 | if (!azx_readb(chip, GCTL)) { | 894 | if (!azx_readb(chip, GCTL)) { |
891 | snd_printd(SFX "azx_reset: controller not ready!\n"); | 895 | snd_printd(SFX "azx_reset: controller not ready!\n"); |
@@ -997,13 +1001,13 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | |||
997 | /* | 1001 | /* |
998 | * reset and start the controller registers | 1002 | * reset and start the controller registers |
999 | */ | 1003 | */ |
1000 | static void azx_init_chip(struct azx *chip) | 1004 | static void azx_init_chip(struct azx *chip, int full_reset) |
1001 | { | 1005 | { |
1002 | if (chip->initialized) | 1006 | if (chip->initialized) |
1003 | return; | 1007 | return; |
1004 | 1008 | ||
1005 | /* reset controller */ | 1009 | /* reset controller */ |
1006 | azx_reset(chip); | 1010 | azx_reset(chip, full_reset); |
1007 | 1011 | ||
1008 | /* initialize interrupts */ | 1012 | /* initialize interrupts */ |
1009 | azx_int_clear(chip); | 1013 | azx_int_clear(chip); |
@@ -1301,8 +1305,10 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1301 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); | 1305 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); |
1302 | 1306 | ||
1303 | /* enable the position buffer */ | 1307 | /* enable the position buffer */ |
1304 | if (chip->position_fix == POS_FIX_POSBUF || | 1308 | if (chip->position_fix[0] == POS_FIX_POSBUF || |
1305 | chip->position_fix == POS_FIX_AUTO || | 1309 | chip->position_fix[0] == POS_FIX_AUTO || |
1310 | chip->position_fix[1] == POS_FIX_POSBUF || | ||
1311 | chip->position_fix[1] == POS_FIX_AUTO || | ||
1306 | chip->via_dmapos_patch) { | 1312 | chip->via_dmapos_patch) { |
1307 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 1313 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
1308 | azx_writel(chip, DPLBASE, | 1314 | azx_writel(chip, DPLBASE, |
@@ -1347,7 +1353,7 @@ static void azx_bus_reset(struct hda_bus *bus) | |||
1347 | 1353 | ||
1348 | bus->in_reset = 1; | 1354 | bus->in_reset = 1; |
1349 | azx_stop_chip(chip); | 1355 | azx_stop_chip(chip); |
1350 | azx_init_chip(chip); | 1356 | azx_init_chip(chip, 1); |
1351 | #ifdef CONFIG_PM | 1357 | #ifdef CONFIG_PM |
1352 | if (chip->initialized) { | 1358 | if (chip->initialized) { |
1353 | int i; | 1359 | int i; |
@@ -1367,6 +1373,7 @@ static void azx_bus_reset(struct hda_bus *bus) | |||
1367 | 1373 | ||
1368 | /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ | 1374 | /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ |
1369 | static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { | 1375 | static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { |
1376 | [AZX_DRIVER_NVIDIA] = 8, | ||
1370 | [AZX_DRIVER_TERA] = 1, | 1377 | [AZX_DRIVER_TERA] = 1, |
1371 | }; | 1378 | }; |
1372 | 1379 | ||
@@ -1399,7 +1406,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
1399 | codecs = 0; | 1406 | codecs = 0; |
1400 | max_slots = azx_max_codecs[chip->driver_type]; | 1407 | max_slots = azx_max_codecs[chip->driver_type]; |
1401 | if (!max_slots) | 1408 | if (!max_slots) |
1402 | max_slots = AZX_MAX_CODECS; | 1409 | max_slots = AZX_DEFAULT_CODECS; |
1403 | 1410 | ||
1404 | /* First try to probe all given codec slots */ | 1411 | /* First try to probe all given codec slots */ |
1405 | for (c = 0; c < max_slots; c++) { | 1412 | for (c = 0; c < max_slots; c++) { |
@@ -1420,7 +1427,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
1420 | * get back to the sanity state. | 1427 | * get back to the sanity state. |
1421 | */ | 1428 | */ |
1422 | azx_stop_chip(chip); | 1429 | azx_stop_chip(chip); |
1423 | azx_init_chip(chip); | 1430 | azx_init_chip(chip, 1); |
1424 | } | 1431 | } |
1425 | } | 1432 | } |
1426 | } | 1433 | } |
@@ -1668,8 +1675,9 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1668 | return err; | 1675 | return err; |
1669 | } | 1676 | } |
1670 | 1677 | ||
1671 | azx_dev->min_jiffies = (runtime->period_size * HZ) / | 1678 | /* wallclk has 24Mhz clock source */ |
1672 | (runtime->rate * 2); | 1679 | azx_dev->period_wallclk = (((runtime->period_size * 24000) / |
1680 | runtime->rate) * 1000); | ||
1673 | azx_setup_controller(chip, azx_dev); | 1681 | azx_setup_controller(chip, azx_dev); |
1674 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1682 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1675 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; | 1683 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; |
@@ -1723,14 +1731,15 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1723 | if (s->pcm->card != substream->pcm->card) | 1731 | if (s->pcm->card != substream->pcm->card) |
1724 | continue; | 1732 | continue; |
1725 | azx_dev = get_azx_dev(s); | 1733 | azx_dev = get_azx_dev(s); |
1726 | if (rstart) { | 1734 | if (start) { |
1727 | azx_dev->start_flag = 1; | 1735 | azx_dev->start_wallclk = azx_readl(chip, WALLCLK); |
1728 | azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies; | 1736 | if (!rstart) |
1729 | } | 1737 | azx_dev->start_wallclk -= |
1730 | if (start) | 1738 | azx_dev->period_wallclk; |
1731 | azx_stream_start(chip, azx_dev); | 1739 | azx_stream_start(chip, azx_dev); |
1732 | else | 1740 | } else { |
1733 | azx_stream_stop(chip, azx_dev); | 1741 | azx_stream_stop(chip, azx_dev); |
1742 | } | ||
1734 | azx_dev->running = start; | 1743 | azx_dev->running = start; |
1735 | } | 1744 | } |
1736 | spin_unlock(&chip->reg_lock); | 1745 | spin_unlock(&chip->reg_lock); |
@@ -1841,13 +1850,16 @@ static unsigned int azx_get_position(struct azx *chip, | |||
1841 | 1850 | ||
1842 | if (chip->via_dmapos_patch) | 1851 | if (chip->via_dmapos_patch) |
1843 | pos = azx_via_get_position(chip, azx_dev); | 1852 | pos = azx_via_get_position(chip, azx_dev); |
1844 | else if (chip->position_fix == POS_FIX_POSBUF || | 1853 | else { |
1845 | chip->position_fix == POS_FIX_AUTO) { | 1854 | int stream = azx_dev->substream->stream; |
1846 | /* use the position buffer */ | 1855 | if (chip->position_fix[stream] == POS_FIX_POSBUF || |
1847 | pos = le32_to_cpu(*azx_dev->posbuf); | 1856 | chip->position_fix[stream] == POS_FIX_AUTO) { |
1848 | } else { | 1857 | /* use the position buffer */ |
1849 | /* read LPIB */ | 1858 | pos = le32_to_cpu(*azx_dev->posbuf); |
1850 | pos = azx_sd_readl(azx_dev, SD_LPIB); | 1859 | } else { |
1860 | /* read LPIB */ | ||
1861 | pos = azx_sd_readl(azx_dev, SD_LPIB); | ||
1862 | } | ||
1851 | } | 1863 | } |
1852 | if (pos >= azx_dev->bufsize) | 1864 | if (pos >= azx_dev->bufsize) |
1853 | pos = 0; | 1865 | pos = 0; |
@@ -1874,32 +1886,35 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
1874 | */ | 1886 | */ |
1875 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | 1887 | static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) |
1876 | { | 1888 | { |
1889 | u32 wallclk; | ||
1877 | unsigned int pos; | 1890 | unsigned int pos; |
1891 | int stream; | ||
1878 | 1892 | ||
1879 | if (azx_dev->start_flag && | 1893 | wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk; |
1880 | time_before_eq(jiffies, azx_dev->start_jiffies)) | 1894 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) |
1881 | return -1; /* bogus (too early) interrupt */ | 1895 | return -1; /* bogus (too early) interrupt */ |
1882 | azx_dev->start_flag = 0; | ||
1883 | 1896 | ||
1897 | stream = azx_dev->substream->stream; | ||
1884 | pos = azx_get_position(chip, azx_dev); | 1898 | pos = azx_get_position(chip, azx_dev); |
1885 | if (chip->position_fix == POS_FIX_AUTO) { | 1899 | if (chip->position_fix[stream] == POS_FIX_AUTO) { |
1886 | if (!pos) { | 1900 | if (!pos) { |
1887 | printk(KERN_WARNING | 1901 | printk(KERN_WARNING |
1888 | "hda-intel: Invalid position buffer, " | 1902 | "hda-intel: Invalid position buffer, " |
1889 | "using LPIB read method instead.\n"); | 1903 | "using LPIB read method instead.\n"); |
1890 | chip->position_fix = POS_FIX_LPIB; | 1904 | chip->position_fix[stream] = POS_FIX_LPIB; |
1891 | pos = azx_get_position(chip, azx_dev); | 1905 | pos = azx_get_position(chip, azx_dev); |
1892 | } else | 1906 | } else |
1893 | chip->position_fix = POS_FIX_POSBUF; | 1907 | chip->position_fix[stream] = POS_FIX_POSBUF; |
1894 | } | 1908 | } |
1895 | 1909 | ||
1896 | if (!bdl_pos_adj[chip->dev_index]) | ||
1897 | return 1; /* no delayed ack */ | ||
1898 | if (WARN_ONCE(!azx_dev->period_bytes, | 1910 | if (WARN_ONCE(!azx_dev->period_bytes, |
1899 | "hda-intel: zero azx_dev->period_bytes")) | 1911 | "hda-intel: zero azx_dev->period_bytes")) |
1900 | return 0; /* this shouldn't happen! */ | 1912 | return -1; /* this shouldn't happen! */ |
1901 | if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) | 1913 | if (wallclk <= azx_dev->period_wallclk && |
1902 | return 0; /* NG - it's below the period boundary */ | 1914 | pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) |
1915 | /* NG - it's below the first next period boundary */ | ||
1916 | return bdl_pos_adj[chip->dev_index] ? 0 : -1; | ||
1917 | azx_dev->start_wallclk = wallclk; | ||
1903 | return 1; /* OK, it's fine */ | 1918 | return 1; /* OK, it's fine */ |
1904 | } | 1919 | } |
1905 | 1920 | ||
@@ -1909,7 +1924,7 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
1909 | static void azx_irq_pending_work(struct work_struct *work) | 1924 | static void azx_irq_pending_work(struct work_struct *work) |
1910 | { | 1925 | { |
1911 | struct azx *chip = container_of(work, struct azx, irq_pending_work); | 1926 | struct azx *chip = container_of(work, struct azx, irq_pending_work); |
1912 | int i, pending; | 1927 | int i, pending, ok; |
1913 | 1928 | ||
1914 | if (!chip->irq_pending_warned) { | 1929 | if (!chip->irq_pending_warned) { |
1915 | printk(KERN_WARNING | 1930 | printk(KERN_WARNING |
@@ -1928,11 +1943,14 @@ static void azx_irq_pending_work(struct work_struct *work) | |||
1928 | !azx_dev->substream || | 1943 | !azx_dev->substream || |
1929 | !azx_dev->running) | 1944 | !azx_dev->running) |
1930 | continue; | 1945 | continue; |
1931 | if (azx_position_ok(chip, azx_dev)) { | 1946 | ok = azx_position_ok(chip, azx_dev); |
1947 | if (ok > 0) { | ||
1932 | azx_dev->irq_pending = 0; | 1948 | azx_dev->irq_pending = 0; |
1933 | spin_unlock(&chip->reg_lock); | 1949 | spin_unlock(&chip->reg_lock); |
1934 | snd_pcm_period_elapsed(azx_dev->substream); | 1950 | snd_pcm_period_elapsed(azx_dev->substream); |
1935 | spin_lock(&chip->reg_lock); | 1951 | spin_lock(&chip->reg_lock); |
1952 | } else if (ok < 0) { | ||
1953 | pending = 0; /* too early */ | ||
1936 | } else | 1954 | } else |
1937 | pending++; | 1955 | pending++; |
1938 | } | 1956 | } |
@@ -2110,7 +2128,7 @@ static void azx_power_notify(struct hda_bus *bus) | |||
2110 | } | 2128 | } |
2111 | } | 2129 | } |
2112 | if (power_on) | 2130 | if (power_on) |
2113 | azx_init_chip(chip); | 2131 | azx_init_chip(chip, 1); |
2114 | else if (chip->running && power_save_controller && | 2132 | else if (chip->running && power_save_controller && |
2115 | !bus->power_keep_link_on) | 2133 | !bus->power_keep_link_on) |
2116 | azx_stop_chip(chip); | 2134 | azx_stop_chip(chip); |
@@ -2180,7 +2198,7 @@ static int azx_resume(struct pci_dev *pci) | |||
2180 | azx_init_pci(chip); | 2198 | azx_init_pci(chip); |
2181 | 2199 | ||
2182 | if (snd_hda_codecs_inuse(chip->bus)) | 2200 | if (snd_hda_codecs_inuse(chip->bus)) |
2183 | azx_init_chip(chip); | 2201 | azx_init_chip(chip, 1); |
2184 | 2202 | ||
2185 | snd_hda_resume(chip->bus); | 2203 | snd_hda_resume(chip->bus); |
2186 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2204 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
@@ -2263,10 +2281,16 @@ static int azx_dev_free(struct snd_device *device) | |||
2263 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { | 2281 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { |
2264 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), | 2282 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), |
2265 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), | 2283 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), |
2284 | SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), | ||
2266 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), | 2285 | SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), |
2267 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), | 2286 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), |
2268 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), | 2287 | SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), |
2288 | SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), | ||
2269 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), | 2289 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), |
2290 | SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), | ||
2291 | SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB), | ||
2292 | SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB), | ||
2293 | SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB), | ||
2270 | {} | 2294 | {} |
2271 | }; | 2295 | }; |
2272 | 2296 | ||
@@ -2354,6 +2378,9 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) | |||
2354 | static struct snd_pci_quirk msi_black_list[] __devinitdata = { | 2378 | static struct snd_pci_quirk msi_black_list[] __devinitdata = { |
2355 | SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ | 2379 | SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ |
2356 | SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ | 2380 | SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ |
2381 | SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */ | ||
2382 | SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */ | ||
2383 | SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */ | ||
2357 | {} | 2384 | {} |
2358 | }; | 2385 | }; |
2359 | 2386 | ||
@@ -2372,6 +2399,13 @@ static void __devinit check_msi(struct azx *chip) | |||
2372 | "hda_intel: msi for device %04x:%04x set to %d\n", | 2399 | "hda_intel: msi for device %04x:%04x set to %d\n", |
2373 | q->subvendor, q->subdevice, q->value); | 2400 | q->subvendor, q->subdevice, q->value); |
2374 | chip->msi = q->value; | 2401 | chip->msi = q->value; |
2402 | return; | ||
2403 | } | ||
2404 | |||
2405 | /* NVidia chipsets seem to cause troubles with MSI */ | ||
2406 | if (chip->driver_type == AZX_DRIVER_NVIDIA) { | ||
2407 | printk(KERN_INFO "hda_intel: Disable MSI for Nvidia chipset\n"); | ||
2408 | chip->msi = 0; | ||
2375 | } | 2409 | } |
2376 | } | 2410 | } |
2377 | 2411 | ||
@@ -2413,7 +2447,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2413 | chip->dev_index = dev; | 2447 | chip->dev_index = dev; |
2414 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); | 2448 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); |
2415 | 2449 | ||
2416 | chip->position_fix = check_position_fix(chip, position_fix[dev]); | 2450 | chip->position_fix[0] = chip->position_fix[1] = |
2451 | check_position_fix(chip, position_fix[dev]); | ||
2417 | check_probe_mask(chip, dev); | 2452 | check_probe_mask(chip, dev); |
2418 | 2453 | ||
2419 | chip->single_cmd = single_cmd; | 2454 | chip->single_cmd = single_cmd; |
@@ -2559,7 +2594,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2559 | 2594 | ||
2560 | /* initialize chip */ | 2595 | /* initialize chip */ |
2561 | azx_init_pci(chip); | 2596 | azx_init_pci(chip); |
2562 | azx_init_chip(chip); | 2597 | azx_init_chip(chip, (probe_only[dev] & 2) == 0); |
2563 | 2598 | ||
2564 | /* codec detection */ | 2599 | /* codec detection */ |
2565 | if (!chip->codec_mask) { | 2600 | if (!chip->codec_mask) { |
@@ -2648,7 +2683,7 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2648 | goto out_free; | 2683 | goto out_free; |
2649 | } | 2684 | } |
2650 | #endif | 2685 | #endif |
2651 | if (!probe_only[dev]) { | 2686 | if ((probe_only[dev] & 1) == 0) { |
2652 | err = azx_codec_configure(chip); | 2687 | err = azx_codec_configure(chip); |
2653 | if (err < 0) | 2688 | if (err < 0) |
2654 | goto out_free; | 2689 | goto out_free; |
@@ -2700,6 +2735,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
2700 | { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, | 2735 | { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, |
2701 | /* PCH */ | 2736 | /* PCH */ |
2702 | { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, | 2737 | { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, |
2738 | { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH }, | ||
2703 | /* CPT */ | 2739 | /* CPT */ |
2704 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, | 2740 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, |
2705 | /* SCH */ | 2741 | /* SCH */ |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7cee364976ff..7a97f126f6f7 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -361,7 +361,7 @@ struct hda_bus_unsolicited { | |||
361 | }; | 361 | }; |
362 | 362 | ||
363 | /* | 363 | /* |
364 | * Helper for automatic ping configuration | 364 | * Helper for automatic pin configuration |
365 | */ | 365 | */ |
366 | 366 | ||
367 | enum { | 367 | enum { |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e6d1bdff1b6e..afbe314a5bf3 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -71,9 +71,10 @@ struct ad198x_spec { | |||
71 | struct hda_input_mux private_imux; | 71 | struct hda_input_mux private_imux; |
72 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 72 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
73 | 73 | ||
74 | unsigned int jack_present :1; | 74 | unsigned int jack_present: 1; |
75 | unsigned int inv_jack_detect:1; /* inverted jack-detection */ | 75 | unsigned int inv_jack_detect: 1;/* inverted jack-detection */ |
76 | unsigned int inv_eapd:1; /* inverted EAPD implementation */ | 76 | unsigned int inv_eapd: 1; /* inverted EAPD implementation */ |
77 | unsigned int analog_beep: 1; /* analog beep input present */ | ||
77 | 78 | ||
78 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 79 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
79 | struct hda_loopback_check loopback; | 80 | struct hda_loopback_check loopback; |
@@ -165,6 +166,12 @@ static struct snd_kcontrol_new ad_beep_mixer[] = { | |||
165 | { } /* end */ | 166 | { } /* end */ |
166 | }; | 167 | }; |
167 | 168 | ||
169 | static struct snd_kcontrol_new ad_beep2_mixer[] = { | ||
170 | HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT), | ||
171 | HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT), | ||
172 | { } /* end */ | ||
173 | }; | ||
174 | |||
168 | #define set_beep_amp(spec, nid, idx, dir) \ | 175 | #define set_beep_amp(spec, nid, idx, dir) \ |
169 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ | 176 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ |
170 | #else | 177 | #else |
@@ -203,7 +210,8 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
203 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 210 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
204 | if (spec->beep_amp) { | 211 | if (spec->beep_amp) { |
205 | struct snd_kcontrol_new *knew; | 212 | struct snd_kcontrol_new *knew; |
206 | for (knew = ad_beep_mixer; knew->name; knew++) { | 213 | knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer; |
214 | for ( ; knew->name; knew++) { | ||
207 | struct snd_kcontrol *kctl; | 215 | struct snd_kcontrol *kctl; |
208 | kctl = snd_ctl_new1(knew, codec); | 216 | kctl = snd_ctl_new1(knew, codec); |
209 | if (!kctl) | 217 | if (!kctl) |
@@ -519,14 +527,6 @@ static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) | |||
519 | ad198x_power_eapd(codec); | 527 | ad198x_power_eapd(codec); |
520 | return 0; | 528 | return 0; |
521 | } | 529 | } |
522 | |||
523 | static int ad198x_resume(struct hda_codec *codec) | ||
524 | { | ||
525 | ad198x_init(codec); | ||
526 | snd_hda_codec_resume_amp(codec); | ||
527 | snd_hda_codec_resume_cache(codec); | ||
528 | return 0; | ||
529 | } | ||
530 | #endif | 530 | #endif |
531 | 531 | ||
532 | static struct hda_codec_ops ad198x_patch_ops = { | 532 | static struct hda_codec_ops ad198x_patch_ops = { |
@@ -539,7 +539,6 @@ static struct hda_codec_ops ad198x_patch_ops = { | |||
539 | #endif | 539 | #endif |
540 | #ifdef SND_HDA_NEEDS_RESUME | 540 | #ifdef SND_HDA_NEEDS_RESUME |
541 | .suspend = ad198x_suspend, | 541 | .suspend = ad198x_suspend, |
542 | .resume = ad198x_resume, | ||
543 | #endif | 542 | #endif |
544 | .reboot_notify = ad198x_shutup, | 543 | .reboot_notify = ad198x_shutup, |
545 | }; | 544 | }; |
@@ -1896,6 +1895,14 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1896 | case AD1981_THINKPAD: | 1895 | case AD1981_THINKPAD: |
1897 | spec->mixers[0] = ad1981_thinkpad_mixers; | 1896 | spec->mixers[0] = ad1981_thinkpad_mixers; |
1898 | spec->input_mux = &ad1981_thinkpad_capture_source; | 1897 | spec->input_mux = &ad1981_thinkpad_capture_source; |
1898 | /* set the upper-limit for mixer amp to 0dB for avoiding the | ||
1899 | * possible damage by overloading | ||
1900 | */ | ||
1901 | snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, | ||
1902 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
1903 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
1904 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
1905 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
1899 | break; | 1906 | break; |
1900 | case AD1981_TOSHIBA: | 1907 | case AD1981_TOSHIBA: |
1901 | spec->mixers[0] = ad1981_hp_mixers; | 1908 | spec->mixers[0] = ad1981_hp_mixers; |
@@ -3482,6 +3489,8 @@ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { | |||
3482 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | 3489 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), |
3483 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), | 3490 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), |
3484 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | 3491 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), |
3492 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
3493 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
3485 | HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), | 3494 | HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), |
3486 | HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3495 | HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
3487 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3496 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), |
@@ -3523,6 +3532,8 @@ static struct hda_verb ad1984_thinkpad_init_verbs[] = { | |||
3523 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3532 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
3524 | /* docking mic boost */ | 3533 | /* docking mic boost */ |
3525 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 3534 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
3535 | /* Analog PC Beeper - allow firmware/ACPI beeps */ | ||
3536 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a}, | ||
3526 | /* Analog mixer - docking mic; mute as default */ | 3537 | /* Analog mixer - docking mic; mute as default */ |
3527 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 3538 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3528 | /* enable EAPD bit */ | 3539 | /* enable EAPD bit */ |
@@ -3655,6 +3666,7 @@ static int patch_ad1984(struct hda_codec *codec) | |||
3655 | spec->input_mux = &ad1984_thinkpad_capture_source; | 3666 | spec->input_mux = &ad1984_thinkpad_capture_source; |
3656 | spec->mixers[0] = ad1984_thinkpad_mixers; | 3667 | spec->mixers[0] = ad1984_thinkpad_mixers; |
3657 | spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; | 3668 | spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; |
3669 | spec->analog_beep = 1; | ||
3658 | break; | 3670 | break; |
3659 | case AD1984_DELL_DESKTOP: | 3671 | case AD1984_DELL_DESKTOP: |
3660 | spec->multiout.dig_out_nid = 0; | 3672 | spec->multiout.dig_out_nid = 0; |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 7de782a5b8f4..350ee8ac4153 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -766,7 +766,7 @@ static int build_input(struct hda_codec *codec) | |||
766 | for (n = 0; n < AUTO_PIN_LAST; n++) { | 766 | for (n = 0; n < AUTO_PIN_LAST; n++) { |
767 | if (!spec->adc_nid[n]) | 767 | if (!spec->adc_nid[n]) |
768 | continue; | 768 | continue; |
769 | err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[i]); | 769 | err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]); |
770 | if (err < 0) | 770 | if (err < 0) |
771 | return err; | 771 | return err; |
772 | } | 772 | } |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 194a28c54992..e863649d31f5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -115,6 +115,7 @@ struct conexant_spec { | |||
115 | unsigned int port_d_mode; | 115 | unsigned int port_d_mode; |
116 | unsigned int dell_vostro:1; | 116 | unsigned int dell_vostro:1; |
117 | unsigned int ideapad:1; | 117 | unsigned int ideapad:1; |
118 | unsigned int thinkpad:1; | ||
118 | 119 | ||
119 | unsigned int ext_mic_present; | 120 | unsigned int ext_mic_present; |
120 | unsigned int recording; | 121 | unsigned int recording; |
@@ -1195,10 +1196,12 @@ static int patch_cxt5045(struct hda_codec *codec) | |||
1195 | 1196 | ||
1196 | switch (codec->subsystem_id >> 16) { | 1197 | switch (codec->subsystem_id >> 16) { |
1197 | case 0x103c: | 1198 | case 0x103c: |
1199 | case 0x1631: | ||
1198 | case 0x1734: | 1200 | case 0x1734: |
1199 | /* HP & Fujitsu-Siemens laptops have really bad sound over 0dB | 1201 | case 0x17aa: |
1200 | * on NID 0x17. Fix max PCM level to 0 dB | 1202 | /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have |
1201 | * (originally it has 0x2b steps with 0dB offset 0x14) | 1203 | * really bad sound over 0dB on NID 0x17. Fix max PCM level to |
1204 | * 0 dB (originally it has 0x2b steps with 0dB offset 0x14) | ||
1202 | */ | 1205 | */ |
1203 | snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, | 1206 | snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, |
1204 | (0x14 << AC_AMPCAP_OFFSET_SHIFT) | | 1207 | (0x14 << AC_AMPCAP_OFFSET_SHIFT) | |
@@ -1591,6 +1594,21 @@ static int patch_cxt5047(struct hda_codec *codec) | |||
1591 | #endif | 1594 | #endif |
1592 | } | 1595 | } |
1593 | spec->vmaster_nid = 0x13; | 1596 | spec->vmaster_nid = 0x13; |
1597 | |||
1598 | switch (codec->subsystem_id >> 16) { | ||
1599 | case 0x103c: | ||
1600 | /* HP laptops have really bad sound over 0 dB on NID 0x10. | ||
1601 | * Fix max PCM level to 0 dB (originally it has 0x1e steps | ||
1602 | * with 0 dB offset 0x17) | ||
1603 | */ | ||
1604 | snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT, | ||
1605 | (0x17 << AC_AMPCAP_OFFSET_SHIFT) | | ||
1606 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
1607 | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
1608 | (1 << AC_AMPCAP_MUTE_SHIFT)); | ||
1609 | break; | ||
1610 | } | ||
1611 | |||
1594 | return 0; | 1612 | return 0; |
1595 | } | 1613 | } |
1596 | 1614 | ||
@@ -1767,6 +1785,7 @@ static struct hda_verb cxt5051_init_verbs[] = { | |||
1767 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | 1785 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, |
1768 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | 1786 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, |
1769 | /* SPDIF route: PCM */ | 1787 | /* SPDIF route: PCM */ |
1788 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1770 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | 1789 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, |
1771 | /* EAPD */ | 1790 | /* EAPD */ |
1772 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 1791 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
@@ -1823,6 +1842,7 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { | |||
1823 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | 1842 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, |
1824 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | 1843 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, |
1825 | /* SPDIF route: PCM */ | 1844 | /* SPDIF route: PCM */ |
1845 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* needed for W500 Advanced Mini Dock 250410 */ | ||
1826 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | 1846 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, |
1827 | /* EAPD */ | 1847 | /* EAPD */ |
1828 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 1848 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
@@ -1894,7 +1914,7 @@ enum { | |||
1894 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ | 1914 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ |
1895 | CXT5051_HP, /* no docking */ | 1915 | CXT5051_HP, /* no docking */ |
1896 | CXT5051_HP_DV6736, /* HP without mic switch */ | 1916 | CXT5051_HP_DV6736, /* HP without mic switch */ |
1897 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ | 1917 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */ |
1898 | CXT5051_F700, /* HP Compaq Presario F700 */ | 1918 | CXT5051_F700, /* HP Compaq Presario F700 */ |
1899 | CXT5051_TOSHIBA, /* Toshiba M300 & co */ | 1919 | CXT5051_TOSHIBA, /* Toshiba M300 & co */ |
1900 | CXT5051_MODELS | 1920 | CXT5051_MODELS |
@@ -2016,6 +2036,9 @@ static void cxt5066_update_speaker(struct hda_codec *codec) | |||
2016 | /* Port D (HP/LO) */ | 2036 | /* Port D (HP/LO) */ |
2017 | pinctl = ((spec->hp_present & 2) && spec->cur_eapd) | 2037 | pinctl = ((spec->hp_present & 2) && spec->cur_eapd) |
2018 | ? spec->port_d_mode : 0; | 2038 | ? spec->port_d_mode : 0; |
2039 | /* Mute if Port A is connected on Thinkpad */ | ||
2040 | if (spec->thinkpad && (spec->hp_present & 1)) | ||
2041 | pinctl = 0; | ||
2019 | snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2042 | snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
2020 | pinctl); | 2043 | pinctl); |
2021 | 2044 | ||
@@ -2196,6 +2219,50 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec) | |||
2196 | } | 2219 | } |
2197 | } | 2220 | } |
2198 | 2221 | ||
2222 | /* toggle input of built-in digital mic and mic jack appropriately | ||
2223 | order is: external mic -> dock mic -> interal mic */ | ||
2224 | static void cxt5066_thinkpad_automic(struct hda_codec *codec) | ||
2225 | { | ||
2226 | unsigned int ext_present, dock_present; | ||
2227 | |||
2228 | static struct hda_verb ext_mic_present[] = { | ||
2229 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2230 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, | ||
2231 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2232 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2233 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2234 | {} | ||
2235 | }; | ||
2236 | static struct hda_verb dock_mic_present[] = { | ||
2237 | {0x14, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2238 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | ||
2239 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2240 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2241 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2242 | {} | ||
2243 | }; | ||
2244 | static struct hda_verb ext_mic_absent[] = { | ||
2245 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, | ||
2246 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2247 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2248 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2249 | {} | ||
2250 | }; | ||
2251 | |||
2252 | ext_present = snd_hda_jack_detect(codec, 0x1b); | ||
2253 | dock_present = snd_hda_jack_detect(codec, 0x1a); | ||
2254 | if (ext_present) { | ||
2255 | snd_printdd("CXT5066: external microphone detected\n"); | ||
2256 | snd_hda_sequence_write(codec, ext_mic_present); | ||
2257 | } else if (dock_present) { | ||
2258 | snd_printdd("CXT5066: dock microphone detected\n"); | ||
2259 | snd_hda_sequence_write(codec, dock_mic_present); | ||
2260 | } else { | ||
2261 | snd_printdd("CXT5066: external microphone absent\n"); | ||
2262 | snd_hda_sequence_write(codec, ext_mic_absent); | ||
2263 | } | ||
2264 | } | ||
2265 | |||
2199 | /* mute internal speaker if HP is plugged */ | 2266 | /* mute internal speaker if HP is plugged */ |
2200 | static void cxt5066_hp_automute(struct hda_codec *codec) | 2267 | static void cxt5066_hp_automute(struct hda_codec *codec) |
2201 | { | 2268 | { |
@@ -2208,7 +2275,8 @@ static void cxt5066_hp_automute(struct hda_codec *codec) | |||
2208 | /* Port D */ | 2275 | /* Port D */ |
2209 | portD = snd_hda_jack_detect(codec, 0x1c); | 2276 | portD = snd_hda_jack_detect(codec, 0x1c); |
2210 | 2277 | ||
2211 | spec->hp_present = !!(portA | portD); | 2278 | spec->hp_present = !!(portA); |
2279 | spec->hp_present |= portD ? 2 : 0; | ||
2212 | snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", | 2280 | snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", |
2213 | portA, portD, spec->hp_present); | 2281 | portA, portD, spec->hp_present); |
2214 | cxt5066_update_speaker(codec); | 2282 | cxt5066_update_speaker(codec); |
@@ -2259,6 +2327,20 @@ static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res) | |||
2259 | } | 2327 | } |
2260 | } | 2328 | } |
2261 | 2329 | ||
2330 | /* unsolicited event for jack sensing */ | ||
2331 | static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res) | ||
2332 | { | ||
2333 | snd_printdd("CXT5066_thinkpad: unsol event %x (%x)\n", res, res >> 26); | ||
2334 | switch (res >> 26) { | ||
2335 | case CONEXANT_HP_EVENT: | ||
2336 | cxt5066_hp_automute(codec); | ||
2337 | break; | ||
2338 | case CONEXANT_MIC_EVENT: | ||
2339 | cxt5066_thinkpad_automic(codec); | ||
2340 | break; | ||
2341 | } | ||
2342 | } | ||
2343 | |||
2262 | static const struct hda_input_mux cxt5066_analog_mic_boost = { | 2344 | static const struct hda_input_mux cxt5066_analog_mic_boost = { |
2263 | .num_items = 5, | 2345 | .num_items = 5, |
2264 | .items = { | 2346 | .items = { |
@@ -2277,7 +2359,7 @@ static void cxt5066_set_mic_boost(struct hda_codec *codec) | |||
2277 | AC_VERB_SET_AMP_GAIN_MUTE, | 2359 | AC_VERB_SET_AMP_GAIN_MUTE, |
2278 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | | 2360 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | |
2279 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); | 2361 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); |
2280 | if (spec->ideapad) { | 2362 | if (spec->ideapad || spec->thinkpad) { |
2281 | /* adjust the internal mic as well...it is not through 0x17 */ | 2363 | /* adjust the internal mic as well...it is not through 0x17 */ |
2282 | snd_hda_codec_write_cache(codec, 0x23, 0, | 2364 | snd_hda_codec_write_cache(codec, 0x23, 0, |
2283 | AC_VERB_SET_AMP_GAIN_MUTE, | 2365 | AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -2765,6 +2847,64 @@ static struct hda_verb cxt5066_init_verbs_ideapad[] = { | |||
2765 | { } /* end */ | 2847 | { } /* end */ |
2766 | }; | 2848 | }; |
2767 | 2849 | ||
2850 | static struct hda_verb cxt5066_init_verbs_thinkpad[] = { | ||
2851 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ | ||
2852 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ | ||
2853 | |||
2854 | /* Port G: internal speakers */ | ||
2855 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2856 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2857 | |||
2858 | /* Port A: HP, Amp */ | ||
2859 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2860 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2861 | |||
2862 | /* Port B: Mic Dock */ | ||
2863 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2864 | |||
2865 | /* Port C: Mic */ | ||
2866 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2867 | |||
2868 | /* Port D: HP Dock, Amp */ | ||
2869 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
2870 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | ||
2871 | |||
2872 | /* DAC1 */ | ||
2873 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2874 | |||
2875 | /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ | ||
2876 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, | ||
2877 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2878 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, | ||
2879 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2880 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
2881 | {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ | ||
2882 | |||
2883 | /* Audio input selector */ | ||
2884 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, | ||
2885 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ | ||
2886 | |||
2887 | /* SPDIF route: PCM */ | ||
2888 | {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2889 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2890 | |||
2891 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2892 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2893 | |||
2894 | /* internal microphone */ | ||
2895 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable int mic */ | ||
2896 | |||
2897 | /* EAPD */ | ||
2898 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
2899 | |||
2900 | /* enable unsolicited events for Port A, B, C and D */ | ||
2901 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2902 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, | ||
2903 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2904 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, | ||
2905 | { } /* end */ | ||
2906 | }; | ||
2907 | |||
2768 | static struct hda_verb cxt5066_init_verbs_portd_lo[] = { | 2908 | static struct hda_verb cxt5066_init_verbs_portd_lo[] = { |
2769 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 2909 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
2770 | { } /* end */ | 2910 | { } /* end */ |
@@ -2783,6 +2923,8 @@ static int cxt5066_init(struct hda_codec *codec) | |||
2783 | cxt5066_vostro_automic(codec); | 2923 | cxt5066_vostro_automic(codec); |
2784 | else if (spec->ideapad) | 2924 | else if (spec->ideapad) |
2785 | cxt5066_ideapad_automic(codec); | 2925 | cxt5066_ideapad_automic(codec); |
2926 | else if (spec->thinkpad) | ||
2927 | cxt5066_thinkpad_automic(codec); | ||
2786 | } | 2928 | } |
2787 | cxt5066_set_mic_boost(codec); | 2929 | cxt5066_set_mic_boost(codec); |
2788 | return 0; | 2930 | return 0; |
@@ -2804,20 +2946,22 @@ static int cxt5066_olpc_init(struct hda_codec *codec) | |||
2804 | } | 2946 | } |
2805 | 2947 | ||
2806 | enum { | 2948 | enum { |
2807 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ | 2949 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ |
2808 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ | 2950 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ |
2809 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ | 2951 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ |
2810 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ | 2952 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ |
2811 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | 2953 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ |
2954 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ | ||
2812 | CXT5066_MODELS | 2955 | CXT5066_MODELS |
2813 | }; | 2956 | }; |
2814 | 2957 | ||
2815 | static const char *cxt5066_models[CXT5066_MODELS] = { | 2958 | static const char *cxt5066_models[CXT5066_MODELS] = { |
2816 | [CXT5066_LAPTOP] = "laptop", | 2959 | [CXT5066_LAPTOP] = "laptop", |
2817 | [CXT5066_DELL_LAPTOP] = "dell-laptop", | 2960 | [CXT5066_DELL_LAPTOP] = "dell-laptop", |
2818 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", | 2961 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", |
2819 | [CXT5066_DELL_VOSTO] = "dell-vostro", | 2962 | [CXT5066_DELL_VOSTO] = "dell-vostro", |
2820 | [CXT5066_IDEAPAD] = "ideapad", | 2963 | [CXT5066_IDEAPAD] = "ideapad", |
2964 | [CXT5066_THINKPAD] = "thinkpad", | ||
2821 | }; | 2965 | }; |
2822 | 2966 | ||
2823 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | 2967 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { |
@@ -2827,7 +2971,12 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
2827 | CXT5066_DELL_LAPTOP), | 2971 | CXT5066_DELL_LAPTOP), |
2828 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), | 2972 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), |
2829 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), | 2973 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), |
2974 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), | ||
2975 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), | ||
2976 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), | ||
2977 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), | ||
2830 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), | 2978 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), |
2979 | SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), | ||
2831 | {} | 2980 | {} |
2832 | }; | 2981 | }; |
2833 | 2982 | ||
@@ -2935,6 +3084,22 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
2935 | /* input source automatically selected */ | 3084 | /* input source automatically selected */ |
2936 | spec->input_mux = NULL; | 3085 | spec->input_mux = NULL; |
2937 | break; | 3086 | break; |
3087 | case CXT5066_THINKPAD: | ||
3088 | codec->patch_ops.init = cxt5066_init; | ||
3089 | codec->patch_ops.unsol_event = cxt5066_thinkpad_event; | ||
3090 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; | ||
3091 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | ||
3092 | spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; | ||
3093 | spec->thinkpad = 1; | ||
3094 | spec->port_d_mode = PIN_OUT; | ||
3095 | spec->mic_boost = 2; /* default 20dB gain */ | ||
3096 | |||
3097 | /* no S/PDIF out */ | ||
3098 | spec->multiout.dig_out_nid = 0; | ||
3099 | |||
3100 | /* input source automatically selected */ | ||
3101 | spec->input_mux = NULL; | ||
3102 | break; | ||
2938 | } | 3103 | } |
2939 | 3104 | ||
2940 | return 0; | 3105 | return 0; |
@@ -2954,6 +3119,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = { | |||
2954 | .patch = patch_cxt5066 }, | 3119 | .patch = patch_cxt5066 }, |
2955 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", | 3120 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", |
2956 | .patch = patch_cxt5066 }, | 3121 | .patch = patch_cxt5066 }, |
3122 | { .id = 0x14f15069, .name = "CX20585", | ||
3123 | .patch = patch_cxt5066 }, | ||
2957 | {} /* terminator */ | 3124 | {} /* terminator */ |
2958 | }; | 3125 | }; |
2959 | 3126 | ||
@@ -2962,6 +3129,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15047"); | |||
2962 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); | 3129 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); |
2963 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); | 3130 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); |
2964 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); | 3131 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); |
3132 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); | ||
2965 | 3133 | ||
2966 | MODULE_LICENSE("GPL"); | 3134 | MODULE_LICENSE("GPL"); |
2967 | MODULE_DESCRIPTION("Conexant HD-audio codec"); | 3135 | MODULE_DESCRIPTION("Conexant HD-audio codec"); |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c new file mode 100644 index 000000000000..86067ee78632 --- /dev/null +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -0,0 +1,847 @@ | |||
1 | /* | ||
2 | * | ||
3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs | ||
4 | * | ||
5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * Authors: | ||
8 | * Wu Fengguang <wfg@linux.intel.com> | ||
9 | * | ||
10 | * Maintained by: | ||
11 | * Wu Fengguang <wfg@linux.intel.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the Free | ||
15 | * Software Foundation; either version 2 of the License, or (at your option) | ||
16 | * any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, but | ||
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
20 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
21 | * for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software Foundation, | ||
25 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
26 | */ | ||
27 | |||
28 | |||
29 | struct hdmi_spec { | ||
30 | int num_cvts; | ||
31 | int num_pins; | ||
32 | hda_nid_t cvt[MAX_HDMI_CVTS+1]; /* audio sources */ | ||
33 | hda_nid_t pin[MAX_HDMI_PINS+1]; /* audio sinks */ | ||
34 | |||
35 | /* | ||
36 | * source connection for each pin | ||
37 | */ | ||
38 | hda_nid_t pin_cvt[MAX_HDMI_PINS+1]; | ||
39 | |||
40 | /* | ||
41 | * HDMI sink attached to each pin | ||
42 | */ | ||
43 | struct hdmi_eld sink_eld[MAX_HDMI_PINS]; | ||
44 | |||
45 | /* | ||
46 | * export one pcm per pipe | ||
47 | */ | ||
48 | struct hda_pcm pcm_rec[MAX_HDMI_CVTS]; | ||
49 | |||
50 | /* | ||
51 | * nvhdmi specific | ||
52 | */ | ||
53 | struct hda_multi_out multiout; | ||
54 | unsigned int codec_type; | ||
55 | }; | ||
56 | |||
57 | |||
58 | struct hdmi_audio_infoframe { | ||
59 | u8 type; /* 0x84 */ | ||
60 | u8 ver; /* 0x01 */ | ||
61 | u8 len; /* 0x0a */ | ||
62 | |||
63 | u8 checksum; /* PB0 */ | ||
64 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | ||
65 | u8 SS01_SF24; | ||
66 | u8 CXT04; | ||
67 | u8 CA; | ||
68 | u8 LFEPBL01_LSV36_DM_INH7; | ||
69 | u8 reserved[5]; /* PB6 - PB10 */ | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * CEA speaker placement: | ||
74 | * | ||
75 | * FLH FCH FRH | ||
76 | * FLW FL FLC FC FRC FR FRW | ||
77 | * | ||
78 | * LFE | ||
79 | * TC | ||
80 | * | ||
81 | * RL RLC RC RRC RR | ||
82 | * | ||
83 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | ||
84 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | ||
85 | */ | ||
86 | enum cea_speaker_placement { | ||
87 | FL = (1 << 0), /* Front Left */ | ||
88 | FC = (1 << 1), /* Front Center */ | ||
89 | FR = (1 << 2), /* Front Right */ | ||
90 | FLC = (1 << 3), /* Front Left Center */ | ||
91 | FRC = (1 << 4), /* Front Right Center */ | ||
92 | RL = (1 << 5), /* Rear Left */ | ||
93 | RC = (1 << 6), /* Rear Center */ | ||
94 | RR = (1 << 7), /* Rear Right */ | ||
95 | RLC = (1 << 8), /* Rear Left Center */ | ||
96 | RRC = (1 << 9), /* Rear Right Center */ | ||
97 | LFE = (1 << 10), /* Low Frequency Effect */ | ||
98 | FLW = (1 << 11), /* Front Left Wide */ | ||
99 | FRW = (1 << 12), /* Front Right Wide */ | ||
100 | FLH = (1 << 13), /* Front Left High */ | ||
101 | FCH = (1 << 14), /* Front Center High */ | ||
102 | FRH = (1 << 15), /* Front Right High */ | ||
103 | TC = (1 << 16), /* Top Center */ | ||
104 | }; | ||
105 | |||
106 | /* | ||
107 | * ELD SA bits in the CEA Speaker Allocation data block | ||
108 | */ | ||
109 | static int eld_speaker_allocation_bits[] = { | ||
110 | [0] = FL | FR, | ||
111 | [1] = LFE, | ||
112 | [2] = FC, | ||
113 | [3] = RL | RR, | ||
114 | [4] = RC, | ||
115 | [5] = FLC | FRC, | ||
116 | [6] = RLC | RRC, | ||
117 | /* the following are not defined in ELD yet */ | ||
118 | [7] = FLW | FRW, | ||
119 | [8] = FLH | FRH, | ||
120 | [9] = TC, | ||
121 | [10] = FCH, | ||
122 | }; | ||
123 | |||
124 | struct cea_channel_speaker_allocation { | ||
125 | int ca_index; | ||
126 | int speakers[8]; | ||
127 | |||
128 | /* derived values, just for convenience */ | ||
129 | int channels; | ||
130 | int spk_mask; | ||
131 | }; | ||
132 | |||
133 | /* | ||
134 | * ALSA sequence is: | ||
135 | * | ||
136 | * surround40 surround41 surround50 surround51 surround71 | ||
137 | * ch0 front left = = = = | ||
138 | * ch1 front right = = = = | ||
139 | * ch2 rear left = = = = | ||
140 | * ch3 rear right = = = = | ||
141 | * ch4 LFE center center center | ||
142 | * ch5 LFE LFE | ||
143 | * ch6 side left | ||
144 | * ch7 side right | ||
145 | * | ||
146 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | ||
147 | */ | ||
148 | static int hdmi_channel_mapping[0x32][8] = { | ||
149 | /* stereo */ | ||
150 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
151 | /* 2.1 */ | ||
152 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
153 | /* Dolby Surround */ | ||
154 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
155 | /* surround40 */ | ||
156 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | ||
157 | /* 4ch */ | ||
158 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | ||
159 | /* surround41 */ | ||
160 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
161 | /* surround50 */ | ||
162 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
163 | /* surround51 */ | ||
164 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | ||
165 | /* 7.1 */ | ||
166 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, | ||
167 | }; | ||
168 | |||
169 | /* | ||
170 | * This is an ordered list! | ||
171 | * | ||
172 | * The preceding ones have better chances to be selected by | ||
173 | * hdmi_setup_channel_allocation(). | ||
174 | */ | ||
175 | static struct cea_channel_speaker_allocation channel_allocations[] = { | ||
176 | /* channel: 7 6 5 4 3 2 1 0 */ | ||
177 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | ||
178 | /* 2.1 */ | ||
179 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | ||
180 | /* Dolby Surround */ | ||
181 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | ||
182 | /* surround40 */ | ||
183 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
184 | /* surround41 */ | ||
185 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
186 | /* surround50 */ | ||
187 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
188 | /* surround51 */ | ||
189 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
190 | /* 6.1 */ | ||
191 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
192 | /* surround71 */ | ||
193 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
194 | |||
195 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | ||
196 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | ||
197 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | ||
198 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | ||
199 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | ||
200 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | ||
201 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | ||
202 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | ||
203 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | ||
204 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | ||
205 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | ||
206 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | ||
207 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | ||
208 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | ||
209 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | ||
210 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | ||
211 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | ||
212 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | ||
213 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | ||
214 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | ||
215 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | ||
216 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | ||
217 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | ||
218 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | ||
219 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
220 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | ||
221 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | ||
222 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | ||
223 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | ||
224 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | ||
225 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | ||
226 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | ||
227 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | ||
228 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | ||
229 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | ||
230 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | ||
231 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
232 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | ||
233 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | ||
234 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | ||
235 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | ||
236 | }; | ||
237 | |||
238 | |||
239 | /* | ||
240 | * HDMI routines | ||
241 | */ | ||
242 | |||
243 | static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) | ||
244 | { | ||
245 | int i; | ||
246 | |||
247 | for (i = 0; nids[i]; i++) | ||
248 | if (nids[i] == nid) | ||
249 | return i; | ||
250 | |||
251 | snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, | ||
256 | struct hdmi_eld *eld) | ||
257 | { | ||
258 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) | ||
259 | snd_hdmi_show_eld(eld); | ||
260 | } | ||
261 | |||
262 | #ifdef BE_PARANOID | ||
263 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
264 | int *packet_index, int *byte_index) | ||
265 | { | ||
266 | int val; | ||
267 | |||
268 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
269 | AC_VERB_GET_HDMI_DIP_INDEX, 0); | ||
270 | |||
271 | *packet_index = val >> 5; | ||
272 | *byte_index = val & 0x1f; | ||
273 | } | ||
274 | #endif | ||
275 | |||
276 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
277 | int packet_index, int byte_index) | ||
278 | { | ||
279 | int val; | ||
280 | |||
281 | val = (packet_index << 5) | (byte_index & 0x1f); | ||
282 | |||
283 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | ||
284 | } | ||
285 | |||
286 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, | ||
287 | unsigned char val) | ||
288 | { | ||
289 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | ||
290 | } | ||
291 | |||
292 | static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) | ||
293 | { | ||
294 | /* Unmute */ | ||
295 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) | ||
296 | snd_hda_codec_write(codec, pin_nid, 0, | ||
297 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
298 | /* Enable pin out */ | ||
299 | snd_hda_codec_write(codec, pin_nid, 0, | ||
300 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
301 | } | ||
302 | |||
303 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) | ||
304 | { | ||
305 | return 1 + snd_hda_codec_read(codec, nid, 0, | ||
306 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | ||
307 | } | ||
308 | |||
309 | static void hdmi_set_channel_count(struct hda_codec *codec, | ||
310 | hda_nid_t nid, int chs) | ||
311 | { | ||
312 | if (chs != hdmi_get_channel_count(codec, nid)) | ||
313 | snd_hda_codec_write(codec, nid, 0, | ||
314 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | ||
315 | } | ||
316 | |||
317 | |||
318 | /* | ||
319 | * Channel mapping routines | ||
320 | */ | ||
321 | |||
322 | /* | ||
323 | * Compute derived values in channel_allocations[]. | ||
324 | */ | ||
325 | static void init_channel_allocations(void) | ||
326 | { | ||
327 | int i, j; | ||
328 | struct cea_channel_speaker_allocation *p; | ||
329 | |||
330 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
331 | p = channel_allocations + i; | ||
332 | p->channels = 0; | ||
333 | p->spk_mask = 0; | ||
334 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | ||
335 | if (p->speakers[j]) { | ||
336 | p->channels++; | ||
337 | p->spk_mask |= p->speakers[j]; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * The transformation takes two steps: | ||
344 | * | ||
345 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | ||
346 | * spk_mask => (channel_allocations[]) => ai->CA | ||
347 | * | ||
348 | * TODO: it could select the wrong CA from multiple candidates. | ||
349 | */ | ||
350 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | ||
351 | struct hdmi_audio_infoframe *ai) | ||
352 | { | ||
353 | struct hdmi_spec *spec = codec->spec; | ||
354 | struct hdmi_eld *eld; | ||
355 | int i; | ||
356 | int spk_mask = 0; | ||
357 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
358 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
359 | |||
360 | /* | ||
361 | * CA defaults to 0 for basic stereo audio | ||
362 | */ | ||
363 | if (channels <= 2) | ||
364 | return 0; | ||
365 | |||
366 | i = hda_node_index(spec->pin_cvt, nid); | ||
367 | if (i < 0) | ||
368 | return 0; | ||
369 | eld = &spec->sink_eld[i]; | ||
370 | |||
371 | /* | ||
372 | * HDMI sink's ELD info cannot always be retrieved for now, e.g. | ||
373 | * in console or for audio devices. Assume the highest speakers | ||
374 | * configuration, to _not_ prohibit multi-channel audio playback. | ||
375 | */ | ||
376 | if (!eld->spk_alloc) | ||
377 | eld->spk_alloc = 0xffff; | ||
378 | |||
379 | /* | ||
380 | * expand ELD's speaker allocation mask | ||
381 | * | ||
382 | * ELD tells the speaker mask in a compact(paired) form, | ||
383 | * expand ELD's notions to match the ones used by Audio InfoFrame. | ||
384 | */ | ||
385 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | ||
386 | if (eld->spk_alloc & (1 << i)) | ||
387 | spk_mask |= eld_speaker_allocation_bits[i]; | ||
388 | } | ||
389 | |||
390 | /* search for the first working match in the CA table */ | ||
391 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
392 | if (channels == channel_allocations[i].channels && | ||
393 | (spk_mask & channel_allocations[i].spk_mask) == | ||
394 | channel_allocations[i].spk_mask) { | ||
395 | ai->CA = channel_allocations[i].ca_index; | ||
396 | break; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | ||
401 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | ||
402 | ai->CA, channels, buf); | ||
403 | |||
404 | return ai->CA; | ||
405 | } | ||
406 | |||
407 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | ||
408 | hda_nid_t pin_nid) | ||
409 | { | ||
410 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
411 | int i; | ||
412 | int slot; | ||
413 | |||
414 | for (i = 0; i < 8; i++) { | ||
415 | slot = snd_hda_codec_read(codec, pin_nid, 0, | ||
416 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | ||
417 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", | ||
418 | slot >> 4, slot & 0xf); | ||
419 | } | ||
420 | #endif | ||
421 | } | ||
422 | |||
423 | |||
424 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | ||
425 | hda_nid_t pin_nid, | ||
426 | struct hdmi_audio_infoframe *ai) | ||
427 | { | ||
428 | int i; | ||
429 | int ca = ai->CA; | ||
430 | int err; | ||
431 | |||
432 | if (hdmi_channel_mapping[ca][1] == 0) { | ||
433 | for (i = 0; i < channel_allocations[ca].channels; i++) | ||
434 | hdmi_channel_mapping[ca][i] = i | (i << 4); | ||
435 | for (; i < 8; i++) | ||
436 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); | ||
437 | } | ||
438 | |||
439 | for (i = 0; i < 8; i++) { | ||
440 | err = snd_hda_codec_write(codec, pin_nid, 0, | ||
441 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
442 | hdmi_channel_mapping[ca][i]); | ||
443 | if (err) { | ||
444 | snd_printdd(KERN_NOTICE | ||
445 | "HDMI: channel mapping failed\n"); | ||
446 | break; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | hdmi_debug_channel_mapping(codec, pin_nid); | ||
451 | } | ||
452 | |||
453 | |||
454 | /* | ||
455 | * Audio InfoFrame routines | ||
456 | */ | ||
457 | |||
458 | /* | ||
459 | * Enable Audio InfoFrame Transmission | ||
460 | */ | ||
461 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, | ||
462 | hda_nid_t pin_nid) | ||
463 | { | ||
464 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
465 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
466 | AC_DIPXMIT_BEST); | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * Disable Audio InfoFrame Transmission | ||
471 | */ | ||
472 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, | ||
473 | hda_nid_t pin_nid) | ||
474 | { | ||
475 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
476 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
477 | AC_DIPXMIT_DISABLE); | ||
478 | } | ||
479 | |||
480 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) | ||
481 | { | ||
482 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
483 | int i; | ||
484 | int size; | ||
485 | |||
486 | size = snd_hdmi_get_eld_size(codec, pin_nid); | ||
487 | printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); | ||
488 | |||
489 | for (i = 0; i < 8; i++) { | ||
490 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
491 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
492 | printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); | ||
493 | } | ||
494 | #endif | ||
495 | } | ||
496 | |||
497 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | ||
498 | { | ||
499 | #ifdef BE_PARANOID | ||
500 | int i, j; | ||
501 | int size; | ||
502 | int pi, bi; | ||
503 | for (i = 0; i < 8; i++) { | ||
504 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
505 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
506 | if (size == 0) | ||
507 | continue; | ||
508 | |||
509 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); | ||
510 | for (j = 1; j < 1000; j++) { | ||
511 | hdmi_write_dip_byte(codec, pin_nid, 0x0); | ||
512 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); | ||
513 | if (pi != i) | ||
514 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", | ||
515 | bi, pi, i); | ||
516 | if (bi == 0) /* byte index wrapped around */ | ||
517 | break; | ||
518 | } | ||
519 | snd_printd(KERN_INFO | ||
520 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", | ||
521 | i, size, j); | ||
522 | } | ||
523 | #endif | ||
524 | } | ||
525 | |||
526 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | ||
527 | { | ||
528 | u8 *bytes = (u8 *)ai; | ||
529 | u8 sum = 0; | ||
530 | int i; | ||
531 | |||
532 | ai->checksum = 0; | ||
533 | |||
534 | for (i = 0; i < sizeof(*ai); i++) | ||
535 | sum += bytes[i]; | ||
536 | |||
537 | ai->checksum = -sum; | ||
538 | } | ||
539 | |||
540 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | ||
541 | hda_nid_t pin_nid, | ||
542 | struct hdmi_audio_infoframe *ai) | ||
543 | { | ||
544 | u8 *bytes = (u8 *)ai; | ||
545 | int i; | ||
546 | |||
547 | hdmi_debug_dip_size(codec, pin_nid); | ||
548 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | ||
549 | |||
550 | hdmi_checksum_audio_infoframe(ai); | ||
551 | |||
552 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
553 | for (i = 0; i < sizeof(*ai); i++) | ||
554 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | ||
555 | } | ||
556 | |||
557 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | ||
558 | struct hdmi_audio_infoframe *ai) | ||
559 | { | ||
560 | u8 *bytes = (u8 *)ai; | ||
561 | u8 val; | ||
562 | int i; | ||
563 | |||
564 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) | ||
565 | != AC_DIPXMIT_BEST) | ||
566 | return false; | ||
567 | |||
568 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
569 | for (i = 0; i < sizeof(*ai); i++) { | ||
570 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
571 | AC_VERB_GET_HDMI_DIP_DATA, 0); | ||
572 | if (val != bytes[i]) | ||
573 | return false; | ||
574 | } | ||
575 | |||
576 | return true; | ||
577 | } | ||
578 | |||
579 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | ||
580 | struct snd_pcm_substream *substream) | ||
581 | { | ||
582 | struct hdmi_spec *spec = codec->spec; | ||
583 | hda_nid_t pin_nid; | ||
584 | int i; | ||
585 | struct hdmi_audio_infoframe ai = { | ||
586 | .type = 0x84, | ||
587 | .ver = 0x01, | ||
588 | .len = 0x0a, | ||
589 | .CC02_CT47 = substream->runtime->channels - 1, | ||
590 | }; | ||
591 | |||
592 | hdmi_setup_channel_allocation(codec, nid, &ai); | ||
593 | |||
594 | for (i = 0; i < spec->num_pins; i++) { | ||
595 | if (spec->pin_cvt[i] != nid) | ||
596 | continue; | ||
597 | if (!spec->sink_eld[i].monitor_present) | ||
598 | continue; | ||
599 | |||
600 | pin_nid = spec->pin[i]; | ||
601 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | ||
602 | snd_printdd("hdmi_setup_audio_infoframe: " | ||
603 | "cvt=%d pin=%d channels=%d\n", | ||
604 | nid, pin_nid, | ||
605 | substream->runtime->channels); | ||
606 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | ||
607 | hdmi_stop_infoframe_trans(codec, pin_nid); | ||
608 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | ||
609 | hdmi_start_infoframe_trans(codec, pin_nid); | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | |||
615 | /* | ||
616 | * Unsolicited events | ||
617 | */ | ||
618 | |||
619 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
620 | { | ||
621 | struct hdmi_spec *spec = codec->spec; | ||
622 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
623 | int pind = !!(res & AC_UNSOL_RES_PD); | ||
624 | int eldv = !!(res & AC_UNSOL_RES_ELDV); | ||
625 | int index; | ||
626 | |||
627 | printk(KERN_INFO | ||
628 | "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | ||
629 | tag, pind, eldv); | ||
630 | |||
631 | index = hda_node_index(spec->pin, tag); | ||
632 | if (index < 0) | ||
633 | return; | ||
634 | |||
635 | spec->sink_eld[index].monitor_present = pind; | ||
636 | spec->sink_eld[index].eld_valid = eldv; | ||
637 | |||
638 | if (pind && eldv) { | ||
639 | hdmi_get_show_eld(codec, spec->pin[index], | ||
640 | &spec->sink_eld[index]); | ||
641 | /* TODO: do real things about ELD */ | ||
642 | } | ||
643 | } | ||
644 | |||
645 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
646 | { | ||
647 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
648 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
649 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | ||
650 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | ||
651 | |||
652 | printk(KERN_INFO | ||
653 | "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | ||
654 | tag, | ||
655 | subtag, | ||
656 | cp_state, | ||
657 | cp_ready); | ||
658 | |||
659 | /* TODO */ | ||
660 | if (cp_state) | ||
661 | ; | ||
662 | if (cp_ready) | ||
663 | ; | ||
664 | } | ||
665 | |||
666 | |||
667 | static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | ||
668 | { | ||
669 | struct hdmi_spec *spec = codec->spec; | ||
670 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
671 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
672 | |||
673 | if (hda_node_index(spec->pin, tag) < 0) { | ||
674 | snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); | ||
675 | return; | ||
676 | } | ||
677 | |||
678 | if (subtag == 0) | ||
679 | hdmi_intrinsic_event(codec, res); | ||
680 | else | ||
681 | hdmi_non_intrinsic_event(codec, res); | ||
682 | } | ||
683 | |||
684 | /* | ||
685 | * Callbacks | ||
686 | */ | ||
687 | |||
688 | static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | ||
689 | u32 stream_tag, int format) | ||
690 | { | ||
691 | int tag; | ||
692 | int fmt; | ||
693 | |||
694 | tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; | ||
695 | fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); | ||
696 | |||
697 | snd_printdd("hdmi_setup_stream: " | ||
698 | "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", | ||
699 | nid, | ||
700 | tag == stream_tag ? "" : "new-", | ||
701 | stream_tag, | ||
702 | fmt == format ? "" : "new-", | ||
703 | format); | ||
704 | |||
705 | if (tag != stream_tag) | ||
706 | snd_hda_codec_write(codec, nid, 0, | ||
707 | AC_VERB_SET_CHANNEL_STREAMID, | ||
708 | stream_tag << 4); | ||
709 | if (fmt != format) | ||
710 | snd_hda_codec_write(codec, nid, 0, | ||
711 | AC_VERB_SET_STREAM_FORMAT, format); | ||
712 | } | ||
713 | |||
714 | /* | ||
715 | * HDA/HDMI auto parsing | ||
716 | */ | ||
717 | |||
718 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | ||
719 | { | ||
720 | struct hdmi_spec *spec = codec->spec; | ||
721 | hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; | ||
722 | int conn_len, curr; | ||
723 | int index; | ||
724 | |||
725 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { | ||
726 | snd_printk(KERN_WARNING | ||
727 | "HDMI: pin %d wcaps %#x " | ||
728 | "does not support connection list\n", | ||
729 | pin_nid, get_wcaps(codec, pin_nid)); | ||
730 | return -EINVAL; | ||
731 | } | ||
732 | |||
733 | conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, | ||
734 | HDA_MAX_CONNECTIONS); | ||
735 | if (conn_len > 1) | ||
736 | curr = snd_hda_codec_read(codec, pin_nid, 0, | ||
737 | AC_VERB_GET_CONNECT_SEL, 0); | ||
738 | else | ||
739 | curr = 0; | ||
740 | |||
741 | index = hda_node_index(spec->pin, pin_nid); | ||
742 | if (index < 0) | ||
743 | return -EINVAL; | ||
744 | |||
745 | spec->pin_cvt[index] = conn_list[curr]; | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | ||
751 | struct hdmi_eld *eld) | ||
752 | { | ||
753 | int present = snd_hda_pin_sense(codec, pin_nid); | ||
754 | |||
755 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | ||
756 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | ||
757 | |||
758 | if (present & AC_PINSENSE_ELDV) | ||
759 | hdmi_get_show_eld(codec, pin_nid, eld); | ||
760 | } | ||
761 | |||
762 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | ||
763 | { | ||
764 | struct hdmi_spec *spec = codec->spec; | ||
765 | |||
766 | if (spec->num_pins >= MAX_HDMI_PINS) { | ||
767 | snd_printk(KERN_WARNING | ||
768 | "HDMI: no space for pin %d\n", pin_nid); | ||
769 | return -E2BIG; | ||
770 | } | ||
771 | |||
772 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); | ||
773 | |||
774 | spec->pin[spec->num_pins] = pin_nid; | ||
775 | spec->num_pins++; | ||
776 | |||
777 | /* | ||
778 | * It is assumed that converter nodes come first in the node list and | ||
779 | * hence have been registered and usable now. | ||
780 | */ | ||
781 | return hdmi_read_pin_conn(codec, pin_nid); | ||
782 | } | ||
783 | |||
784 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) | ||
785 | { | ||
786 | struct hdmi_spec *spec = codec->spec; | ||
787 | |||
788 | if (spec->num_cvts >= MAX_HDMI_CVTS) { | ||
789 | snd_printk(KERN_WARNING | ||
790 | "HDMI: no space for converter %d\n", nid); | ||
791 | return -E2BIG; | ||
792 | } | ||
793 | |||
794 | spec->cvt[spec->num_cvts] = nid; | ||
795 | spec->num_cvts++; | ||
796 | |||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static int hdmi_parse_codec(struct hda_codec *codec) | ||
801 | { | ||
802 | hda_nid_t nid; | ||
803 | int i, nodes; | ||
804 | |||
805 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | ||
806 | if (!nid || nodes < 0) { | ||
807 | snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); | ||
808 | return -EINVAL; | ||
809 | } | ||
810 | |||
811 | for (i = 0; i < nodes; i++, nid++) { | ||
812 | unsigned int caps; | ||
813 | unsigned int type; | ||
814 | |||
815 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); | ||
816 | type = get_wcaps_type(caps); | ||
817 | |||
818 | if (!(caps & AC_WCAP_DIGITAL)) | ||
819 | continue; | ||
820 | |||
821 | switch (type) { | ||
822 | case AC_WID_AUD_OUT: | ||
823 | hdmi_add_cvt(codec, nid); | ||
824 | break; | ||
825 | case AC_WID_PIN: | ||
826 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
827 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | ||
828 | continue; | ||
829 | hdmi_add_pin(codec, nid); | ||
830 | break; | ||
831 | } | ||
832 | } | ||
833 | |||
834 | /* | ||
835 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | ||
836 | * can be lost and presence sense verb will become inaccurate if the | ||
837 | * HDA link is powered off at hot plug or hw initialization time. | ||
838 | */ | ||
839 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
840 | if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | ||
841 | AC_PWRST_EPSS)) | ||
842 | codec->bus->power_keep_link_on = 1; | ||
843 | #endif | ||
844 | |||
845 | return 0; | ||
846 | } | ||
847 | |||
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 918f40378d52..b81d23e42ace 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c | |||
@@ -40,815 +40,21 @@ | |||
40 | * | 40 | * |
41 | * The HDA correspondence of pipes/ports are converter/pin nodes. | 41 | * The HDA correspondence of pipes/ports are converter/pin nodes. |
42 | */ | 42 | */ |
43 | #define INTEL_HDMI_CVTS 2 | 43 | #define MAX_HDMI_CVTS 3 |
44 | #define INTEL_HDMI_PINS 3 | 44 | #define MAX_HDMI_PINS 3 |
45 | 45 | ||
46 | static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = { | 46 | #include "patch_hdmi.c" |
47 | |||
48 | static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
47 | "INTEL HDMI 0", | 49 | "INTEL HDMI 0", |
48 | "INTEL HDMI 1", | 50 | "INTEL HDMI 1", |
51 | "INTEL HDMI 2", | ||
49 | }; | 52 | }; |
50 | 53 | ||
51 | struct intel_hdmi_spec { | ||
52 | int num_cvts; | ||
53 | int num_pins; | ||
54 | hda_nid_t cvt[INTEL_HDMI_CVTS+1]; /* audio sources */ | ||
55 | hda_nid_t pin[INTEL_HDMI_PINS+1]; /* audio sinks */ | ||
56 | |||
57 | /* | ||
58 | * source connection for each pin | ||
59 | */ | ||
60 | hda_nid_t pin_cvt[INTEL_HDMI_PINS+1]; | ||
61 | |||
62 | /* | ||
63 | * HDMI sink attached to each pin | ||
64 | */ | ||
65 | struct hdmi_eld sink_eld[INTEL_HDMI_PINS]; | ||
66 | |||
67 | /* | ||
68 | * export one pcm per pipe | ||
69 | */ | ||
70 | struct hda_pcm pcm_rec[INTEL_HDMI_CVTS]; | ||
71 | }; | ||
72 | |||
73 | struct hdmi_audio_infoframe { | ||
74 | u8 type; /* 0x84 */ | ||
75 | u8 ver; /* 0x01 */ | ||
76 | u8 len; /* 0x0a */ | ||
77 | |||
78 | u8 checksum; /* PB0 */ | ||
79 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | ||
80 | u8 SS01_SF24; | ||
81 | u8 CXT04; | ||
82 | u8 CA; | ||
83 | u8 LFEPBL01_LSV36_DM_INH7; | ||
84 | u8 reserved[5]; /* PB6 - PB10 */ | ||
85 | }; | ||
86 | |||
87 | /* | ||
88 | * CEA speaker placement: | ||
89 | * | ||
90 | * FLH FCH FRH | ||
91 | * FLW FL FLC FC FRC FR FRW | ||
92 | * | ||
93 | * LFE | ||
94 | * TC | ||
95 | * | ||
96 | * RL RLC RC RRC RR | ||
97 | * | ||
98 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | ||
99 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | ||
100 | */ | ||
101 | enum cea_speaker_placement { | ||
102 | FL = (1 << 0), /* Front Left */ | ||
103 | FC = (1 << 1), /* Front Center */ | ||
104 | FR = (1 << 2), /* Front Right */ | ||
105 | FLC = (1 << 3), /* Front Left Center */ | ||
106 | FRC = (1 << 4), /* Front Right Center */ | ||
107 | RL = (1 << 5), /* Rear Left */ | ||
108 | RC = (1 << 6), /* Rear Center */ | ||
109 | RR = (1 << 7), /* Rear Right */ | ||
110 | RLC = (1 << 8), /* Rear Left Center */ | ||
111 | RRC = (1 << 9), /* Rear Right Center */ | ||
112 | LFE = (1 << 10), /* Low Frequency Effect */ | ||
113 | FLW = (1 << 11), /* Front Left Wide */ | ||
114 | FRW = (1 << 12), /* Front Right Wide */ | ||
115 | FLH = (1 << 13), /* Front Left High */ | ||
116 | FCH = (1 << 14), /* Front Center High */ | ||
117 | FRH = (1 << 15), /* Front Right High */ | ||
118 | TC = (1 << 16), /* Top Center */ | ||
119 | }; | ||
120 | |||
121 | /* | ||
122 | * ELD SA bits in the CEA Speaker Allocation data block | ||
123 | */ | ||
124 | static int eld_speaker_allocation_bits[] = { | ||
125 | [0] = FL | FR, | ||
126 | [1] = LFE, | ||
127 | [2] = FC, | ||
128 | [3] = RL | RR, | ||
129 | [4] = RC, | ||
130 | [5] = FLC | FRC, | ||
131 | [6] = RLC | RRC, | ||
132 | /* the following are not defined in ELD yet */ | ||
133 | [7] = FLW | FRW, | ||
134 | [8] = FLH | FRH, | ||
135 | [9] = TC, | ||
136 | [10] = FCH, | ||
137 | }; | ||
138 | |||
139 | struct cea_channel_speaker_allocation { | ||
140 | int ca_index; | ||
141 | int speakers[8]; | ||
142 | |||
143 | /* derived values, just for convenience */ | ||
144 | int channels; | ||
145 | int spk_mask; | ||
146 | }; | ||
147 | |||
148 | /* | ||
149 | * ALSA sequence is: | ||
150 | * | ||
151 | * surround40 surround41 surround50 surround51 surround71 | ||
152 | * ch0 front left = = = = | ||
153 | * ch1 front right = = = = | ||
154 | * ch2 rear left = = = = | ||
155 | * ch3 rear right = = = = | ||
156 | * ch4 LFE center center center | ||
157 | * ch5 LFE LFE | ||
158 | * ch6 side left | ||
159 | * ch7 side right | ||
160 | * | ||
161 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | ||
162 | */ | ||
163 | static int hdmi_channel_mapping[0x32][8] = { | ||
164 | /* stereo */ | ||
165 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
166 | /* 2.1 */ | ||
167 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
168 | /* Dolby Surround */ | ||
169 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | ||
170 | /* surround40 */ | ||
171 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | ||
172 | /* 4ch */ | ||
173 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | ||
174 | /* surround41 */ | ||
175 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
176 | /* surround50 */ | ||
177 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | ||
178 | /* surround51 */ | ||
179 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | ||
180 | /* 7.1 */ | ||
181 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, | ||
182 | }; | ||
183 | |||
184 | /* | ||
185 | * This is an ordered list! | ||
186 | * | ||
187 | * The preceding ones have better chances to be selected by | ||
188 | * hdmi_setup_channel_allocation(). | ||
189 | */ | ||
190 | static struct cea_channel_speaker_allocation channel_allocations[] = { | ||
191 | /* channel: 7 6 5 4 3 2 1 0 */ | ||
192 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | ||
193 | /* 2.1 */ | ||
194 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | ||
195 | /* Dolby Surround */ | ||
196 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | ||
197 | /* surround40 */ | ||
198 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | ||
199 | /* surround41 */ | ||
200 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | ||
201 | /* surround50 */ | ||
202 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | ||
203 | /* surround51 */ | ||
204 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | ||
205 | /* 6.1 */ | ||
206 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | ||
207 | /* surround71 */ | ||
208 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | ||
209 | |||
210 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | ||
211 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | ||
212 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | ||
213 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | ||
214 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | ||
215 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | ||
216 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | ||
217 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | ||
218 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | ||
219 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | ||
220 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | ||
221 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | ||
222 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | ||
223 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | ||
224 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | ||
225 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | ||
226 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | ||
227 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | ||
228 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | ||
229 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | ||
230 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | ||
231 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | ||
232 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | ||
233 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | ||
234 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
235 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | ||
236 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | ||
237 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | ||
238 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | ||
239 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | ||
240 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | ||
241 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | ||
242 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | ||
243 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | ||
244 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | ||
245 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | ||
246 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | ||
247 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | ||
248 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | ||
249 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | ||
250 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | ||
251 | }; | ||
252 | |||
253 | /* | ||
254 | * HDA/HDMI auto parsing | ||
255 | */ | ||
256 | |||
257 | static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) | ||
258 | { | ||
259 | int i; | ||
260 | |||
261 | for (i = 0; nids[i]; i++) | ||
262 | if (nids[i] == nid) | ||
263 | return i; | ||
264 | |||
265 | snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | ||
270 | { | ||
271 | struct intel_hdmi_spec *spec = codec->spec; | ||
272 | hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; | ||
273 | int conn_len, curr; | ||
274 | int index; | ||
275 | |||
276 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { | ||
277 | snd_printk(KERN_WARNING | ||
278 | "HDMI: pin %d wcaps %#x " | ||
279 | "does not support connection list\n", | ||
280 | pin_nid, get_wcaps(codec, pin_nid)); | ||
281 | return -EINVAL; | ||
282 | } | ||
283 | |||
284 | conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, | ||
285 | HDA_MAX_CONNECTIONS); | ||
286 | if (conn_len > 1) | ||
287 | curr = snd_hda_codec_read(codec, pin_nid, 0, | ||
288 | AC_VERB_GET_CONNECT_SEL, 0); | ||
289 | else | ||
290 | curr = 0; | ||
291 | |||
292 | index = hda_node_index(spec->pin, pin_nid); | ||
293 | if (index < 0) | ||
294 | return -EINVAL; | ||
295 | |||
296 | spec->pin_cvt[index] = conn_list[curr]; | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, | ||
302 | struct hdmi_eld *eld) | ||
303 | { | ||
304 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) | ||
305 | snd_hdmi_show_eld(eld); | ||
306 | } | ||
307 | |||
308 | static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, | ||
309 | struct hdmi_eld *eld) | ||
310 | { | ||
311 | int present = snd_hda_pin_sense(codec, pin_nid); | ||
312 | |||
313 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | ||
314 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | ||
315 | |||
316 | if (present & AC_PINSENSE_ELDV) | ||
317 | hdmi_get_show_eld(codec, pin_nid, eld); | ||
318 | } | ||
319 | |||
320 | static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | ||
321 | { | ||
322 | struct intel_hdmi_spec *spec = codec->spec; | ||
323 | |||
324 | if (spec->num_pins >= INTEL_HDMI_PINS) { | ||
325 | snd_printk(KERN_WARNING | ||
326 | "HDMI: no space for pin %d \n", pin_nid); | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | |||
330 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); | ||
331 | |||
332 | spec->pin[spec->num_pins] = pin_nid; | ||
333 | spec->num_pins++; | ||
334 | |||
335 | /* | ||
336 | * It is assumed that converter nodes come first in the node list and | ||
337 | * hence have been registered and usable now. | ||
338 | */ | ||
339 | return intel_hdmi_read_pin_conn(codec, pin_nid); | ||
340 | } | ||
341 | |||
342 | static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) | ||
343 | { | ||
344 | struct intel_hdmi_spec *spec = codec->spec; | ||
345 | |||
346 | if (spec->num_cvts >= INTEL_HDMI_CVTS) { | ||
347 | snd_printk(KERN_WARNING | ||
348 | "HDMI: no space for converter %d \n", nid); | ||
349 | return -EINVAL; | ||
350 | } | ||
351 | |||
352 | spec->cvt[spec->num_cvts] = nid; | ||
353 | spec->num_cvts++; | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static int intel_hdmi_parse_codec(struct hda_codec *codec) | ||
359 | { | ||
360 | hda_nid_t nid; | ||
361 | int i, nodes; | ||
362 | |||
363 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | ||
364 | if (!nid || nodes < 0) { | ||
365 | snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); | ||
366 | return -EINVAL; | ||
367 | } | ||
368 | |||
369 | for (i = 0; i < nodes; i++, nid++) { | ||
370 | unsigned int caps; | ||
371 | unsigned int type; | ||
372 | |||
373 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); | ||
374 | type = get_wcaps_type(caps); | ||
375 | |||
376 | if (!(caps & AC_WCAP_DIGITAL)) | ||
377 | continue; | ||
378 | |||
379 | switch (type) { | ||
380 | case AC_WID_AUD_OUT: | ||
381 | if (intel_hdmi_add_cvt(codec, nid) < 0) | ||
382 | return -EINVAL; | ||
383 | break; | ||
384 | case AC_WID_PIN: | ||
385 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
386 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | ||
387 | continue; | ||
388 | if (intel_hdmi_add_pin(codec, nid) < 0) | ||
389 | return -EINVAL; | ||
390 | break; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | /* | ||
395 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | ||
396 | * can be lost and presence sense verb will become inaccurate if the | ||
397 | * HDA link is powered off at hot plug or hw initialization time. | ||
398 | */ | ||
399 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
400 | if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | ||
401 | AC_PWRST_EPSS)) | ||
402 | codec->bus->power_keep_link_on = 1; | ||
403 | #endif | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | /* | ||
409 | * HDMI routines | ||
410 | */ | ||
411 | |||
412 | #ifdef BE_PARANOID | ||
413 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
414 | int *packet_index, int *byte_index) | ||
415 | { | ||
416 | int val; | ||
417 | |||
418 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
419 | AC_VERB_GET_HDMI_DIP_INDEX, 0); | ||
420 | |||
421 | *packet_index = val >> 5; | ||
422 | *byte_index = val & 0x1f; | ||
423 | } | ||
424 | #endif | ||
425 | |||
426 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | ||
427 | int packet_index, int byte_index) | ||
428 | { | ||
429 | int val; | ||
430 | |||
431 | val = (packet_index << 5) | (byte_index & 0x1f); | ||
432 | |||
433 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | ||
434 | } | ||
435 | |||
436 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, | ||
437 | unsigned char val) | ||
438 | { | ||
439 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | ||
440 | } | ||
441 | |||
442 | static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) | ||
443 | { | ||
444 | /* Unmute */ | ||
445 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) | ||
446 | snd_hda_codec_write(codec, pin_nid, 0, | ||
447 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
448 | /* Enable pin out */ | ||
449 | snd_hda_codec_write(codec, pin_nid, 0, | ||
450 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
451 | } | ||
452 | |||
453 | /* | ||
454 | * Enable Audio InfoFrame Transmission | ||
455 | */ | ||
456 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, | ||
457 | hda_nid_t pin_nid) | ||
458 | { | ||
459 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
460 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
461 | AC_DIPXMIT_BEST); | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * Disable Audio InfoFrame Transmission | ||
466 | */ | ||
467 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, | ||
468 | hda_nid_t pin_nid) | ||
469 | { | ||
470 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
471 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | ||
472 | AC_DIPXMIT_DISABLE); | ||
473 | } | ||
474 | |||
475 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) | ||
476 | { | ||
477 | return 1 + snd_hda_codec_read(codec, nid, 0, | ||
478 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | ||
479 | } | ||
480 | |||
481 | static void hdmi_set_channel_count(struct hda_codec *codec, | ||
482 | hda_nid_t nid, int chs) | ||
483 | { | ||
484 | if (chs != hdmi_get_channel_count(codec, nid)) | ||
485 | snd_hda_codec_write(codec, nid, 0, | ||
486 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | ||
487 | } | ||
488 | |||
489 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | ||
490 | hda_nid_t pin_nid) | ||
491 | { | ||
492 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
493 | int i; | ||
494 | int slot; | ||
495 | |||
496 | for (i = 0; i < 8; i++) { | ||
497 | slot = snd_hda_codec_read(codec, pin_nid, 0, | ||
498 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | ||
499 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", | ||
500 | slot >> 4, slot & 0xf); | ||
501 | } | ||
502 | #endif | ||
503 | } | ||
504 | |||
505 | |||
506 | /* | ||
507 | * Audio InfoFrame routines | ||
508 | */ | ||
509 | |||
510 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) | ||
511 | { | ||
512 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
513 | int i; | ||
514 | int size; | ||
515 | |||
516 | size = snd_hdmi_get_eld_size(codec, pin_nid); | ||
517 | printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); | ||
518 | |||
519 | for (i = 0; i < 8; i++) { | ||
520 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
521 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
522 | printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); | ||
523 | } | ||
524 | #endif | ||
525 | } | ||
526 | |||
527 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | ||
528 | { | ||
529 | #ifdef BE_PARANOID | ||
530 | int i, j; | ||
531 | int size; | ||
532 | int pi, bi; | ||
533 | for (i = 0; i < 8; i++) { | ||
534 | size = snd_hda_codec_read(codec, pin_nid, 0, | ||
535 | AC_VERB_GET_HDMI_DIP_SIZE, i); | ||
536 | if (size == 0) | ||
537 | continue; | ||
538 | |||
539 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); | ||
540 | for (j = 1; j < 1000; j++) { | ||
541 | hdmi_write_dip_byte(codec, pin_nid, 0x0); | ||
542 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); | ||
543 | if (pi != i) | ||
544 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", | ||
545 | bi, pi, i); | ||
546 | if (bi == 0) /* byte index wrapped around */ | ||
547 | break; | ||
548 | } | ||
549 | snd_printd(KERN_INFO | ||
550 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", | ||
551 | i, size, j); | ||
552 | } | ||
553 | #endif | ||
554 | } | ||
555 | |||
556 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | ||
557 | { | ||
558 | u8 *bytes = (u8 *)ai; | ||
559 | u8 sum = 0; | ||
560 | int i; | ||
561 | |||
562 | ai->checksum = 0; | ||
563 | |||
564 | for (i = 0; i < sizeof(*ai); i++) | ||
565 | sum += bytes[i]; | ||
566 | |||
567 | ai->checksum = - sum; | ||
568 | } | ||
569 | |||
570 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | ||
571 | hda_nid_t pin_nid, | ||
572 | struct hdmi_audio_infoframe *ai) | ||
573 | { | ||
574 | u8 *bytes = (u8 *)ai; | ||
575 | int i; | ||
576 | |||
577 | hdmi_debug_dip_size(codec, pin_nid); | ||
578 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | ||
579 | |||
580 | hdmi_checksum_audio_infoframe(ai); | ||
581 | |||
582 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
583 | for (i = 0; i < sizeof(*ai); i++) | ||
584 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * Compute derived values in channel_allocations[]. | ||
589 | */ | ||
590 | static void init_channel_allocations(void) | ||
591 | { | ||
592 | int i, j; | ||
593 | struct cea_channel_speaker_allocation *p; | ||
594 | |||
595 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
596 | p = channel_allocations + i; | ||
597 | p->channels = 0; | ||
598 | p->spk_mask = 0; | ||
599 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | ||
600 | if (p->speakers[j]) { | ||
601 | p->channels++; | ||
602 | p->spk_mask |= p->speakers[j]; | ||
603 | } | ||
604 | } | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * The transformation takes two steps: | ||
609 | * | ||
610 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | ||
611 | * spk_mask => (channel_allocations[]) => ai->CA | ||
612 | * | ||
613 | * TODO: it could select the wrong CA from multiple candidates. | ||
614 | */ | ||
615 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | ||
616 | struct hdmi_audio_infoframe *ai) | ||
617 | { | ||
618 | struct intel_hdmi_spec *spec = codec->spec; | ||
619 | struct hdmi_eld *eld; | ||
620 | int i; | ||
621 | int spk_mask = 0; | ||
622 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
623 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | ||
624 | |||
625 | /* | ||
626 | * CA defaults to 0 for basic stereo audio | ||
627 | */ | ||
628 | if (channels <= 2) | ||
629 | return 0; | ||
630 | |||
631 | i = hda_node_index(spec->pin_cvt, nid); | ||
632 | if (i < 0) | ||
633 | return 0; | ||
634 | eld = &spec->sink_eld[i]; | ||
635 | |||
636 | /* | ||
637 | * HDMI sink's ELD info cannot always be retrieved for now, e.g. | ||
638 | * in console or for audio devices. Assume the highest speakers | ||
639 | * configuration, to _not_ prohibit multi-channel audio playback. | ||
640 | */ | ||
641 | if (!eld->spk_alloc) | ||
642 | eld->spk_alloc = 0xffff; | ||
643 | |||
644 | /* | ||
645 | * expand ELD's speaker allocation mask | ||
646 | * | ||
647 | * ELD tells the speaker mask in a compact(paired) form, | ||
648 | * expand ELD's notions to match the ones used by Audio InfoFrame. | ||
649 | */ | ||
650 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | ||
651 | if (eld->spk_alloc & (1 << i)) | ||
652 | spk_mask |= eld_speaker_allocation_bits[i]; | ||
653 | } | ||
654 | |||
655 | /* search for the first working match in the CA table */ | ||
656 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
657 | if (channels == channel_allocations[i].channels && | ||
658 | (spk_mask & channel_allocations[i].spk_mask) == | ||
659 | channel_allocations[i].spk_mask) { | ||
660 | ai->CA = channel_allocations[i].ca_index; | ||
661 | break; | ||
662 | } | ||
663 | } | ||
664 | |||
665 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | ||
666 | snd_printdd(KERN_INFO | ||
667 | "HDMI: select CA 0x%x for %d-channel allocation: %s\n", | ||
668 | ai->CA, channels, buf); | ||
669 | |||
670 | return ai->CA; | ||
671 | } | ||
672 | |||
673 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | ||
674 | hda_nid_t pin_nid, | ||
675 | struct hdmi_audio_infoframe *ai) | ||
676 | { | ||
677 | int i; | ||
678 | int ca = ai->CA; | ||
679 | int err; | ||
680 | |||
681 | if (hdmi_channel_mapping[ca][1] == 0) { | ||
682 | for (i = 0; i < channel_allocations[ca].channels; i++) | ||
683 | hdmi_channel_mapping[ca][i] = i | (i << 4); | ||
684 | for (; i < 8; i++) | ||
685 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); | ||
686 | } | ||
687 | |||
688 | for (i = 0; i < 8; i++) { | ||
689 | err = snd_hda_codec_write(codec, pin_nid, 0, | ||
690 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
691 | hdmi_channel_mapping[ca][i]); | ||
692 | if (err) { | ||
693 | snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); | ||
694 | break; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | hdmi_debug_channel_mapping(codec, pin_nid); | ||
699 | } | ||
700 | |||
701 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | ||
702 | struct hdmi_audio_infoframe *ai) | ||
703 | { | ||
704 | u8 *bytes = (u8 *)ai; | ||
705 | u8 val; | ||
706 | int i; | ||
707 | |||
708 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) | ||
709 | != AC_DIPXMIT_BEST) | ||
710 | return false; | ||
711 | |||
712 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | ||
713 | for (i = 0; i < sizeof(*ai); i++) { | ||
714 | val = snd_hda_codec_read(codec, pin_nid, 0, | ||
715 | AC_VERB_GET_HDMI_DIP_DATA, 0); | ||
716 | if (val != bytes[i]) | ||
717 | return false; | ||
718 | } | ||
719 | |||
720 | return true; | ||
721 | } | ||
722 | |||
723 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | ||
724 | struct snd_pcm_substream *substream) | ||
725 | { | ||
726 | struct intel_hdmi_spec *spec = codec->spec; | ||
727 | hda_nid_t pin_nid; | ||
728 | int i; | ||
729 | struct hdmi_audio_infoframe ai = { | ||
730 | .type = 0x84, | ||
731 | .ver = 0x01, | ||
732 | .len = 0x0a, | ||
733 | .CC02_CT47 = substream->runtime->channels - 1, | ||
734 | }; | ||
735 | |||
736 | hdmi_setup_channel_allocation(codec, nid, &ai); | ||
737 | |||
738 | for (i = 0; i < spec->num_pins; i++) { | ||
739 | if (spec->pin_cvt[i] != nid) | ||
740 | continue; | ||
741 | if (!spec->sink_eld[i].monitor_present) | ||
742 | continue; | ||
743 | |||
744 | pin_nid = spec->pin[i]; | ||
745 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | ||
746 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | ||
747 | hdmi_stop_infoframe_trans(codec, pin_nid); | ||
748 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | ||
749 | hdmi_start_infoframe_trans(codec, pin_nid); | ||
750 | } | ||
751 | } | ||
752 | } | ||
753 | |||
754 | |||
755 | /* | 54 | /* |
756 | * Unsolicited events | 55 | * HDMI callbacks |
757 | */ | 56 | */ |
758 | 57 | ||
759 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
760 | { | ||
761 | struct intel_hdmi_spec *spec = codec->spec; | ||
762 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
763 | int pind = !!(res & AC_UNSOL_RES_PD); | ||
764 | int eldv = !!(res & AC_UNSOL_RES_ELDV); | ||
765 | int index; | ||
766 | |||
767 | printk(KERN_INFO | ||
768 | "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | ||
769 | tag, pind, eldv); | ||
770 | |||
771 | index = hda_node_index(spec->pin, tag); | ||
772 | if (index < 0) | ||
773 | return; | ||
774 | |||
775 | spec->sink_eld[index].monitor_present = pind; | ||
776 | spec->sink_eld[index].eld_valid = eldv; | ||
777 | |||
778 | if (pind && eldv) { | ||
779 | hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]); | ||
780 | /* TODO: do real things about ELD */ | ||
781 | } | ||
782 | } | ||
783 | |||
784 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | ||
785 | { | ||
786 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
787 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
788 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | ||
789 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | ||
790 | |||
791 | printk(KERN_INFO | ||
792 | "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | ||
793 | tag, | ||
794 | subtag, | ||
795 | cp_state, | ||
796 | cp_ready); | ||
797 | |||
798 | /* TODO */ | ||
799 | if (cp_state) | ||
800 | ; | ||
801 | if (cp_ready) | ||
802 | ; | ||
803 | } | ||
804 | |||
805 | |||
806 | static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | ||
807 | { | ||
808 | struct intel_hdmi_spec *spec = codec->spec; | ||
809 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | ||
810 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | ||
811 | |||
812 | if (hda_node_index(spec->pin, tag) < 0) { | ||
813 | snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); | ||
814 | return; | ||
815 | } | ||
816 | |||
817 | if (subtag == 0) | ||
818 | hdmi_intrinsic_event(codec, res); | ||
819 | else | ||
820 | hdmi_non_intrinsic_event(codec, res); | ||
821 | } | ||
822 | |||
823 | /* | ||
824 | * Callbacks | ||
825 | */ | ||
826 | |||
827 | static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | ||
828 | u32 stream_tag, int format) | ||
829 | { | ||
830 | int tag; | ||
831 | int fmt; | ||
832 | |||
833 | tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; | ||
834 | fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); | ||
835 | |||
836 | snd_printdd("hdmi_setup_stream: " | ||
837 | "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", | ||
838 | nid, | ||
839 | tag == stream_tag ? "" : "new-", | ||
840 | stream_tag, | ||
841 | fmt == format ? "" : "new-", | ||
842 | format); | ||
843 | |||
844 | if (tag != stream_tag) | ||
845 | snd_hda_codec_write(codec, nid, 0, | ||
846 | AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4); | ||
847 | if (fmt != format) | ||
848 | snd_hda_codec_write(codec, nid, 0, | ||
849 | AC_VERB_SET_STREAM_FORMAT, format); | ||
850 | } | ||
851 | |||
852 | static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 58 | static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
853 | struct hda_codec *codec, | 59 | struct hda_codec *codec, |
854 | unsigned int stream_tag, | 60 | unsigned int stream_tag, |
@@ -882,7 +88,7 @@ static struct hda_pcm_stream intel_hdmi_pcm_playback = { | |||
882 | 88 | ||
883 | static int intel_hdmi_build_pcms(struct hda_codec *codec) | 89 | static int intel_hdmi_build_pcms(struct hda_codec *codec) |
884 | { | 90 | { |
885 | struct intel_hdmi_spec *spec = codec->spec; | 91 | struct hdmi_spec *spec = codec->spec; |
886 | struct hda_pcm *info = spec->pcm_rec; | 92 | struct hda_pcm *info = spec->pcm_rec; |
887 | int i; | 93 | int i; |
888 | 94 | ||
@@ -908,7 +114,7 @@ static int intel_hdmi_build_pcms(struct hda_codec *codec) | |||
908 | 114 | ||
909 | static int intel_hdmi_build_controls(struct hda_codec *codec) | 115 | static int intel_hdmi_build_controls(struct hda_codec *codec) |
910 | { | 116 | { |
911 | struct intel_hdmi_spec *spec = codec->spec; | 117 | struct hdmi_spec *spec = codec->spec; |
912 | int err; | 118 | int err; |
913 | int i; | 119 | int i; |
914 | 120 | ||
@@ -923,7 +129,7 @@ static int intel_hdmi_build_controls(struct hda_codec *codec) | |||
923 | 129 | ||
924 | static int intel_hdmi_init(struct hda_codec *codec) | 130 | static int intel_hdmi_init(struct hda_codec *codec) |
925 | { | 131 | { |
926 | struct intel_hdmi_spec *spec = codec->spec; | 132 | struct hdmi_spec *spec = codec->spec; |
927 | int i; | 133 | int i; |
928 | 134 | ||
929 | for (i = 0; spec->pin[i]; i++) { | 135 | for (i = 0; spec->pin[i]; i++) { |
@@ -937,7 +143,7 @@ static int intel_hdmi_init(struct hda_codec *codec) | |||
937 | 143 | ||
938 | static void intel_hdmi_free(struct hda_codec *codec) | 144 | static void intel_hdmi_free(struct hda_codec *codec) |
939 | { | 145 | { |
940 | struct intel_hdmi_spec *spec = codec->spec; | 146 | struct hdmi_spec *spec = codec->spec; |
941 | int i; | 147 | int i; |
942 | 148 | ||
943 | for (i = 0; i < spec->num_pins; i++) | 149 | for (i = 0; i < spec->num_pins; i++) |
@@ -951,12 +157,12 @@ static struct hda_codec_ops intel_hdmi_patch_ops = { | |||
951 | .free = intel_hdmi_free, | 157 | .free = intel_hdmi_free, |
952 | .build_pcms = intel_hdmi_build_pcms, | 158 | .build_pcms = intel_hdmi_build_pcms, |
953 | .build_controls = intel_hdmi_build_controls, | 159 | .build_controls = intel_hdmi_build_controls, |
954 | .unsol_event = intel_hdmi_unsol_event, | 160 | .unsol_event = hdmi_unsol_event, |
955 | }; | 161 | }; |
956 | 162 | ||
957 | static int patch_intel_hdmi(struct hda_codec *codec) | 163 | static int patch_intel_hdmi(struct hda_codec *codec) |
958 | { | 164 | { |
959 | struct intel_hdmi_spec *spec; | 165 | struct hdmi_spec *spec; |
960 | int i; | 166 | int i; |
961 | 167 | ||
962 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 168 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
@@ -964,7 +170,7 @@ static int patch_intel_hdmi(struct hda_codec *codec) | |||
964 | return -ENOMEM; | 170 | return -ENOMEM; |
965 | 171 | ||
966 | codec->spec = spec; | 172 | codec->spec = spec; |
967 | if (intel_hdmi_parse_codec(codec) < 0) { | 173 | if (hdmi_parse_codec(codec) < 0) { |
968 | codec->spec = NULL; | 174 | codec->spec = NULL; |
969 | kfree(spec); | 175 | kfree(spec); |
970 | return -EINVAL; | 176 | return -EINVAL; |
@@ -980,14 +186,15 @@ static int patch_intel_hdmi(struct hda_codec *codec) | |||
980 | } | 186 | } |
981 | 187 | ||
982 | static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { | 188 | static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { |
983 | { .id = 0x808629fb, .name = "G45 DEVCL", .patch = patch_intel_hdmi }, | 189 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_intel_hdmi }, |
984 | { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi }, | 190 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_intel_hdmi }, |
985 | { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi }, | 191 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_intel_hdmi }, |
986 | { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi }, | 192 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_intel_hdmi }, |
987 | { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi }, | 193 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi }, |
988 | { .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi }, | 194 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi }, |
989 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, | 195 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_intel_hdmi }, |
990 | {} /* terminator */ | 196 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, |
197 | {} /* terminator */ | ||
991 | }; | 198 | }; |
992 | 199 | ||
993 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | 200 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
@@ -995,6 +202,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862801"); | |||
995 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | 202 | MODULE_ALIAS("snd-hda-codec-id:80862802"); |
996 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | 203 | MODULE_ALIAS("snd-hda-codec-id:80862803"); |
997 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | 204 | MODULE_ALIAS("snd-hda-codec-id:80862804"); |
205 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | ||
998 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | 206 | MODULE_ALIAS("snd-hda-codec-id:80860054"); |
999 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | 207 | MODULE_ALIAS("snd-hda-codec-id:10951392"); |
1000 | 208 | ||
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 6afdab09bab7..3c10c0b149f4 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c | |||
@@ -29,13 +29,23 @@ | |||
29 | #include "hda_codec.h" | 29 | #include "hda_codec.h" |
30 | #include "hda_local.h" | 30 | #include "hda_local.h" |
31 | 31 | ||
32 | #define MAX_HDMI_CVTS 1 | ||
33 | #define MAX_HDMI_PINS 1 | ||
34 | |||
35 | #include "patch_hdmi.c" | ||
36 | |||
37 | static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
38 | "NVIDIA HDMI", | ||
39 | }; | ||
40 | |||
32 | /* define below to restrict the supported rates and formats */ | 41 | /* define below to restrict the supported rates and formats */ |
33 | /* #define LIMITED_RATE_FMT_SUPPORT */ | 42 | /* #define LIMITED_RATE_FMT_SUPPORT */ |
34 | 43 | ||
35 | struct nvhdmi_spec { | 44 | enum HDACodec { |
36 | struct hda_multi_out multiout; | 45 | HDA_CODEC_NVIDIA_MCP7X, |
37 | 46 | HDA_CODEC_NVIDIA_MCP89, | |
38 | struct hda_pcm pcm_rec; | 47 | HDA_CODEC_NVIDIA_GT21X, |
48 | HDA_CODEC_INVALID | ||
39 | }; | 49 | }; |
40 | 50 | ||
41 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | 51 | #define Nv_VERB_SET_Channel_Allocation 0xF79 |
@@ -43,15 +53,18 @@ struct nvhdmi_spec { | |||
43 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | 53 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 |
44 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | 54 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 |
45 | 55 | ||
46 | #define Nv_Master_Convert_nid 0x04 | 56 | #define nvhdmi_master_con_nid_7x 0x04 |
47 | #define Nv_Master_Pin_nid 0x05 | 57 | #define nvhdmi_master_pin_nid_7x 0x05 |
48 | 58 | ||
49 | static hda_nid_t nvhdmi_convert_nids[4] = { | 59 | #define nvhdmi_master_con_nid_89 0x04 |
60 | #define nvhdmi_master_pin_nid_89 0x05 | ||
61 | |||
62 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
50 | /*front, rear, clfe, rear_surr */ | 63 | /*front, rear, clfe, rear_surr */ |
51 | 0x6, 0x8, 0xa, 0xc, | 64 | 0x6, 0x8, 0xa, 0xc, |
52 | }; | 65 | }; |
53 | 66 | ||
54 | static struct hda_verb nvhdmi_basic_init[] = { | 67 | static struct hda_verb nvhdmi_basic_init_7x[] = { |
55 | /* set audio protect on */ | 68 | /* set audio protect on */ |
56 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 69 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
57 | /* enable digital output on pin widget */ | 70 | /* enable digital output on pin widget */ |
@@ -84,22 +97,60 @@ static struct hda_verb nvhdmi_basic_init[] = { | |||
84 | */ | 97 | */ |
85 | static int nvhdmi_build_controls(struct hda_codec *codec) | 98 | static int nvhdmi_build_controls(struct hda_codec *codec) |
86 | { | 99 | { |
87 | struct nvhdmi_spec *spec = codec->spec; | 100 | struct hdmi_spec *spec = codec->spec; |
88 | int err; | 101 | int err; |
102 | int i; | ||
89 | 103 | ||
90 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 104 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) |
91 | if (err < 0) | 105 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { |
92 | return err; | 106 | for (i = 0; i < codec->num_pcms; i++) { |
107 | err = snd_hda_create_spdif_out_ctls(codec, | ||
108 | spec->cvt[i]); | ||
109 | if (err < 0) | ||
110 | return err; | ||
111 | } | ||
112 | } else { | ||
113 | err = snd_hda_create_spdif_out_ctls(codec, | ||
114 | spec->multiout.dig_out_nid); | ||
115 | if (err < 0) | ||
116 | return err; | ||
117 | } | ||
93 | 118 | ||
94 | return 0; | 119 | return 0; |
95 | } | 120 | } |
96 | 121 | ||
97 | static int nvhdmi_init(struct hda_codec *codec) | 122 | static int nvhdmi_init(struct hda_codec *codec) |
98 | { | 123 | { |
99 | snd_hda_sequence_write(codec, nvhdmi_basic_init); | 124 | struct hdmi_spec *spec = codec->spec; |
125 | int i; | ||
126 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
127 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
128 | for (i = 0; spec->pin[i]; i++) { | ||
129 | hdmi_enable_output(codec, spec->pin[i]); | ||
130 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
131 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
132 | AC_USRSP_EN | spec->pin[i]); | ||
133 | } | ||
134 | } else { | ||
135 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
136 | } | ||
100 | return 0; | 137 | return 0; |
101 | } | 138 | } |
102 | 139 | ||
140 | static void nvhdmi_free(struct hda_codec *codec) | ||
141 | { | ||
142 | struct hdmi_spec *spec = codec->spec; | ||
143 | int i; | ||
144 | |||
145 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
146 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
147 | for (i = 0; i < spec->num_pins; i++) | ||
148 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
149 | } | ||
150 | |||
151 | kfree(spec); | ||
152 | } | ||
153 | |||
103 | /* | 154 | /* |
104 | * Digital out | 155 | * Digital out |
105 | */ | 156 | */ |
@@ -107,25 +158,25 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | |||
107 | struct hda_codec *codec, | 158 | struct hda_codec *codec, |
108 | struct snd_pcm_substream *substream) | 159 | struct snd_pcm_substream *substream) |
109 | { | 160 | { |
110 | struct nvhdmi_spec *spec = codec->spec; | 161 | struct hdmi_spec *spec = codec->spec; |
111 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 162 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); |
112 | } | 163 | } |
113 | 164 | ||
114 | static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo, | 165 | static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, |
115 | struct hda_codec *codec, | 166 | struct hda_codec *codec, |
116 | struct snd_pcm_substream *substream) | 167 | struct snd_pcm_substream *substream) |
117 | { | 168 | { |
118 | struct nvhdmi_spec *spec = codec->spec; | 169 | struct hdmi_spec *spec = codec->spec; |
119 | int i; | 170 | int i; |
120 | 171 | ||
121 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, | 172 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, |
122 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | 173 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); |
123 | for (i = 0; i < 4; i++) { | 174 | for (i = 0; i < 4; i++) { |
124 | /* set the stream id */ | 175 | /* set the stream id */ |
125 | snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, | 176 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
126 | AC_VERB_SET_CHANNEL_STREAMID, 0); | 177 | AC_VERB_SET_CHANNEL_STREAMID, 0); |
127 | /* set the stream format */ | 178 | /* set the stream format */ |
128 | snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, | 179 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
129 | AC_VERB_SET_STREAM_FORMAT, 0); | 180 | AC_VERB_SET_STREAM_FORMAT, 0); |
130 | } | 181 | } |
131 | 182 | ||
@@ -136,10 +187,25 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, | |||
136 | struct hda_codec *codec, | 187 | struct hda_codec *codec, |
137 | struct snd_pcm_substream *substream) | 188 | struct snd_pcm_substream *substream) |
138 | { | 189 | { |
139 | struct nvhdmi_spec *spec = codec->spec; | 190 | struct hdmi_spec *spec = codec->spec; |
140 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 191 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
141 | } | 192 | } |
142 | 193 | ||
194 | static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, | ||
195 | struct hda_codec *codec, | ||
196 | unsigned int stream_tag, | ||
197 | unsigned int format, | ||
198 | struct snd_pcm_substream *substream) | ||
199 | { | ||
200 | hdmi_set_channel_count(codec, hinfo->nid, | ||
201 | substream->runtime->channels); | ||
202 | |||
203 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
204 | |||
205 | hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
143 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | 209 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, |
144 | struct hda_codec *codec, | 210 | struct hda_codec *codec, |
145 | unsigned int stream_tag, | 211 | unsigned int stream_tag, |
@@ -181,29 +247,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
181 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 247 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
182 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 248 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) |
183 | snd_hda_codec_write(codec, | 249 | snd_hda_codec_write(codec, |
184 | Nv_Master_Convert_nid, | 250 | nvhdmi_master_con_nid_7x, |
185 | 0, | 251 | 0, |
186 | AC_VERB_SET_DIGI_CONVERT_1, | 252 | AC_VERB_SET_DIGI_CONVERT_1, |
187 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | 253 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); |
188 | 254 | ||
189 | /* set the stream id */ | 255 | /* set the stream id */ |
190 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, | 256 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
191 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | 257 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); |
192 | 258 | ||
193 | /* set the stream format */ | 259 | /* set the stream format */ |
194 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, | 260 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
195 | AC_VERB_SET_STREAM_FORMAT, format); | 261 | AC_VERB_SET_STREAM_FORMAT, format); |
196 | 262 | ||
197 | /* turn on again (if needed) */ | 263 | /* turn on again (if needed) */ |
198 | /* enable and set the channel status audio/data flag */ | 264 | /* enable and set the channel status audio/data flag */ |
199 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | 265 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { |
200 | snd_hda_codec_write(codec, | 266 | snd_hda_codec_write(codec, |
201 | Nv_Master_Convert_nid, | 267 | nvhdmi_master_con_nid_7x, |
202 | 0, | 268 | 0, |
203 | AC_VERB_SET_DIGI_CONVERT_1, | 269 | AC_VERB_SET_DIGI_CONVERT_1, |
204 | codec->spdif_ctls & 0xff); | 270 | codec->spdif_ctls & 0xff); |
205 | snd_hda_codec_write(codec, | 271 | snd_hda_codec_write(codec, |
206 | Nv_Master_Convert_nid, | 272 | nvhdmi_master_con_nid_7x, |
207 | 0, | 273 | 0, |
208 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 274 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
209 | } | 275 | } |
@@ -220,19 +286,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
220 | if (codec->spdif_status_reset && | 286 | if (codec->spdif_status_reset && |
221 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | 287 | (codec->spdif_ctls & AC_DIG1_ENABLE)) |
222 | snd_hda_codec_write(codec, | 288 | snd_hda_codec_write(codec, |
223 | nvhdmi_convert_nids[i], | 289 | nvhdmi_con_nids_7x[i], |
224 | 0, | 290 | 0, |
225 | AC_VERB_SET_DIGI_CONVERT_1, | 291 | AC_VERB_SET_DIGI_CONVERT_1, |
226 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | 292 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); |
227 | /* set the stream id */ | 293 | /* set the stream id */ |
228 | snd_hda_codec_write(codec, | 294 | snd_hda_codec_write(codec, |
229 | nvhdmi_convert_nids[i], | 295 | nvhdmi_con_nids_7x[i], |
230 | 0, | 296 | 0, |
231 | AC_VERB_SET_CHANNEL_STREAMID, | 297 | AC_VERB_SET_CHANNEL_STREAMID, |
232 | (stream_tag << 4) | channel_id); | 298 | (stream_tag << 4) | channel_id); |
233 | /* set the stream format */ | 299 | /* set the stream format */ |
234 | snd_hda_codec_write(codec, | 300 | snd_hda_codec_write(codec, |
235 | nvhdmi_convert_nids[i], | 301 | nvhdmi_con_nids_7x[i], |
236 | 0, | 302 | 0, |
237 | AC_VERB_SET_STREAM_FORMAT, | 303 | AC_VERB_SET_STREAM_FORMAT, |
238 | format); | 304 | format); |
@@ -241,12 +307,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
241 | if (codec->spdif_status_reset && | 307 | if (codec->spdif_status_reset && |
242 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | 308 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { |
243 | snd_hda_codec_write(codec, | 309 | snd_hda_codec_write(codec, |
244 | nvhdmi_convert_nids[i], | 310 | nvhdmi_con_nids_7x[i], |
245 | 0, | 311 | 0, |
246 | AC_VERB_SET_DIGI_CONVERT_1, | 312 | AC_VERB_SET_DIGI_CONVERT_1, |
247 | codec->spdif_ctls & 0xff); | 313 | codec->spdif_ctls & 0xff); |
248 | snd_hda_codec_write(codec, | 314 | snd_hda_codec_write(codec, |
249 | nvhdmi_convert_nids[i], | 315 | nvhdmi_con_nids_7x[i], |
250 | 0, | 316 | 0, |
251 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 317 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
252 | } | 318 | } |
@@ -261,28 +327,47 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
261 | return 0; | 327 | return 0; |
262 | } | 328 | } |
263 | 329 | ||
330 | static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
331 | struct hda_codec *codec, | ||
332 | struct snd_pcm_substream *substream) | ||
333 | { | ||
334 | return 0; | ||
335 | } | ||
336 | |||
264 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, | 337 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, |
265 | struct hda_codec *codec, | 338 | struct hda_codec *codec, |
266 | unsigned int stream_tag, | 339 | unsigned int stream_tag, |
267 | unsigned int format, | 340 | unsigned int format, |
268 | struct snd_pcm_substream *substream) | 341 | struct snd_pcm_substream *substream) |
269 | { | 342 | { |
270 | struct nvhdmi_spec *spec = codec->spec; | 343 | struct hdmi_spec *spec = codec->spec; |
271 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | 344 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, |
272 | format, substream); | 345 | format, substream); |
273 | } | 346 | } |
274 | 347 | ||
275 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = { | 348 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { |
349 | .substreams = 1, | ||
350 | .channels_min = 2, | ||
351 | .rates = SUPPORTED_RATES, | ||
352 | .maxbps = SUPPORTED_MAXBPS, | ||
353 | .formats = SUPPORTED_FORMATS, | ||
354 | .ops = { | ||
355 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, | ||
356 | .cleanup = nvhdmi_playback_pcm_cleanup, | ||
357 | }, | ||
358 | }; | ||
359 | |||
360 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { | ||
276 | .substreams = 1, | 361 | .substreams = 1, |
277 | .channels_min = 2, | 362 | .channels_min = 2, |
278 | .channels_max = 8, | 363 | .channels_max = 8, |
279 | .nid = Nv_Master_Convert_nid, | 364 | .nid = nvhdmi_master_con_nid_7x, |
280 | .rates = SUPPORTED_RATES, | 365 | .rates = SUPPORTED_RATES, |
281 | .maxbps = SUPPORTED_MAXBPS, | 366 | .maxbps = SUPPORTED_MAXBPS, |
282 | .formats = SUPPORTED_FORMATS, | 367 | .formats = SUPPORTED_FORMATS, |
283 | .ops = { | 368 | .ops = { |
284 | .open = nvhdmi_dig_playback_pcm_open, | 369 | .open = nvhdmi_dig_playback_pcm_open, |
285 | .close = nvhdmi_dig_playback_pcm_close_8ch, | 370 | .close = nvhdmi_dig_playback_pcm_close_8ch_7x, |
286 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch | 371 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch |
287 | }, | 372 | }, |
288 | }; | 373 | }; |
@@ -291,7 +376,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | |||
291 | .substreams = 1, | 376 | .substreams = 1, |
292 | .channels_min = 2, | 377 | .channels_min = 2, |
293 | .channels_max = 2, | 378 | .channels_max = 2, |
294 | .nid = Nv_Master_Convert_nid, | 379 | .nid = nvhdmi_master_con_nid_7x, |
295 | .rates = SUPPORTED_RATES, | 380 | .rates = SUPPORTED_RATES, |
296 | .maxbps = SUPPORTED_MAXBPS, | 381 | .maxbps = SUPPORTED_MAXBPS, |
297 | .formats = SUPPORTED_FORMATS, | 382 | .formats = SUPPORTED_FORMATS, |
@@ -302,10 +387,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | |||
302 | }, | 387 | }, |
303 | }; | 388 | }; |
304 | 389 | ||
305 | static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | 390 | static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) |
391 | { | ||
392 | struct hdmi_spec *spec = codec->spec; | ||
393 | struct hda_pcm *info = spec->pcm_rec; | ||
394 | int i; | ||
395 | |||
396 | codec->num_pcms = spec->num_cvts; | ||
397 | codec->pcm_info = info; | ||
398 | |||
399 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
400 | unsigned int chans; | ||
401 | |||
402 | chans = get_wcaps(codec, spec->cvt[i]); | ||
403 | chans = get_wcaps_channels(chans); | ||
404 | |||
405 | info->name = nvhdmi_pcm_names[i]; | ||
406 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
407 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
408 | = nvhdmi_pcm_digital_playback_8ch_89; | ||
409 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; | ||
410 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
411 | } | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) | ||
306 | { | 417 | { |
307 | struct nvhdmi_spec *spec = codec->spec; | 418 | struct hdmi_spec *spec = codec->spec; |
308 | struct hda_pcm *info = &spec->pcm_rec; | 419 | struct hda_pcm *info = spec->pcm_rec; |
309 | 420 | ||
310 | codec->num_pcms = 1; | 421 | codec->num_pcms = 1; |
311 | codec->pcm_info = info; | 422 | codec->pcm_info = info; |
@@ -313,15 +424,15 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | |||
313 | info->name = "NVIDIA HDMI"; | 424 | info->name = "NVIDIA HDMI"; |
314 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 425 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
315 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | 426 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] |
316 | = nvhdmi_pcm_digital_playback_8ch; | 427 | = nvhdmi_pcm_digital_playback_8ch_7x; |
317 | 428 | ||
318 | return 0; | 429 | return 0; |
319 | } | 430 | } |
320 | 431 | ||
321 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | 432 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) |
322 | { | 433 | { |
323 | struct nvhdmi_spec *spec = codec->spec; | 434 | struct hdmi_spec *spec = codec->spec; |
324 | struct hda_pcm *info = &spec->pcm_rec; | 435 | struct hda_pcm *info = spec->pcm_rec; |
325 | 436 | ||
326 | codec->num_pcms = 1; | 437 | codec->num_pcms = 1; |
327 | codec->pcm_info = info; | 438 | codec->pcm_info = info; |
@@ -334,14 +445,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | |||
334 | return 0; | 445 | return 0; |
335 | } | 446 | } |
336 | 447 | ||
337 | static void nvhdmi_free(struct hda_codec *codec) | 448 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { |
338 | { | 449 | .build_controls = nvhdmi_build_controls, |
339 | kfree(codec->spec); | 450 | .build_pcms = nvhdmi_build_pcms_8ch_89, |
340 | } | 451 | .init = nvhdmi_init, |
452 | .free = nvhdmi_free, | ||
453 | .unsol_event = hdmi_unsol_event, | ||
454 | }; | ||
341 | 455 | ||
342 | static struct hda_codec_ops nvhdmi_patch_ops_8ch = { | 456 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { |
343 | .build_controls = nvhdmi_build_controls, | 457 | .build_controls = nvhdmi_build_controls, |
344 | .build_pcms = nvhdmi_build_pcms_8ch, | 458 | .build_pcms = nvhdmi_build_pcms_8ch_7x, |
345 | .init = nvhdmi_init, | 459 | .init = nvhdmi_init, |
346 | .free = nvhdmi_free, | 460 | .free = nvhdmi_free, |
347 | }; | 461 | }; |
@@ -353,9 +467,36 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | |||
353 | .free = nvhdmi_free, | 467 | .free = nvhdmi_free, |
354 | }; | 468 | }; |
355 | 469 | ||
356 | static int patch_nvhdmi_8ch(struct hda_codec *codec) | 470 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) |
471 | { | ||
472 | struct hdmi_spec *spec; | ||
473 | int i; | ||
474 | |||
475 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
476 | if (spec == NULL) | ||
477 | return -ENOMEM; | ||
478 | |||
479 | codec->spec = spec; | ||
480 | spec->codec_type = HDA_CODEC_NVIDIA_MCP89; | ||
481 | |||
482 | if (hdmi_parse_codec(codec) < 0) { | ||
483 | codec->spec = NULL; | ||
484 | kfree(spec); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | codec->patch_ops = nvhdmi_patch_ops_8ch_89; | ||
488 | |||
489 | for (i = 0; i < spec->num_pins; i++) | ||
490 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
491 | |||
492 | init_channel_allocations(); | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
357 | { | 498 | { |
358 | struct nvhdmi_spec *spec; | 499 | struct hdmi_spec *spec; |
359 | 500 | ||
360 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 501 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
361 | if (spec == NULL) | 502 | if (spec == NULL) |
@@ -365,16 +506,17 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec) | |||
365 | 506 | ||
366 | spec->multiout.num_dacs = 0; /* no analog */ | 507 | spec->multiout.num_dacs = 0; /* no analog */ |
367 | spec->multiout.max_channels = 8; | 508 | spec->multiout.max_channels = 8; |
368 | spec->multiout.dig_out_nid = Nv_Master_Convert_nid; | 509 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
510 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
369 | 511 | ||
370 | codec->patch_ops = nvhdmi_patch_ops_8ch; | 512 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; |
371 | 513 | ||
372 | return 0; | 514 | return 0; |
373 | } | 515 | } |
374 | 516 | ||
375 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | 517 | static int patch_nvhdmi_2ch(struct hda_codec *codec) |
376 | { | 518 | { |
377 | struct nvhdmi_spec *spec; | 519 | struct hdmi_spec *spec; |
378 | 520 | ||
379 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 521 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
380 | if (spec == NULL) | 522 | if (spec == NULL) |
@@ -384,7 +526,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
384 | 526 | ||
385 | spec->multiout.num_dacs = 0; /* no analog */ | 527 | spec->multiout.num_dacs = 0; /* no analog */ |
386 | spec->multiout.max_channels = 2; | 528 | spec->multiout.max_channels = 2; |
387 | spec->multiout.dig_out_nid = Nv_Master_Convert_nid; | 529 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
530 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
388 | 531 | ||
389 | codec->patch_ops = nvhdmi_patch_ops_2ch; | 532 | codec->patch_ops = nvhdmi_patch_ops_2ch; |
390 | 533 | ||
@@ -395,11 +538,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
395 | * patch entries | 538 | * patch entries |
396 | */ | 539 | */ |
397 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { | 540 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { |
398 | { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | 541 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", |
399 | { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | 542 | .patch = patch_nvhdmi_8ch_7x }, |
400 | { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | 543 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", |
401 | { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | 544 | .patch = patch_nvhdmi_8ch_7x }, |
402 | { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch }, | 545 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", |
546 | .patch = patch_nvhdmi_8ch_7x }, | ||
547 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", | ||
548 | .patch = patch_nvhdmi_8ch_7x }, | ||
549 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", | ||
550 | .patch = patch_nvhdmi_8ch_7x }, | ||
551 | { .id = 0x10de000a, .name = "GT220 HDMI", | ||
552 | .patch = patch_nvhdmi_8ch_89 }, | ||
553 | { .id = 0x10de000b, .name = "GT21x HDMI", | ||
554 | .patch = patch_nvhdmi_8ch_89 }, | ||
555 | { .id = 0x10de000c, .name = "MCP89 HDMI", | ||
556 | .patch = patch_nvhdmi_8ch_89 }, | ||
557 | { .id = 0x10de000d, .name = "GT240 HDMI", | ||
558 | .patch = patch_nvhdmi_8ch_89 }, | ||
403 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 559 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
404 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 560 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
405 | {} /* terminator */ | 561 | {} /* terminator */ |
@@ -410,11 +566,15 @@ MODULE_ALIAS("snd-hda-codec-id:10de0003"); | |||
410 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | 566 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); |
411 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | 567 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); |
412 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | 568 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); |
569 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | ||
570 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
571 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
572 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
413 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 573 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
414 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 574 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
415 | 575 | ||
416 | MODULE_LICENSE("GPL"); | 576 | MODULE_LICENSE("GPL"); |
417 | MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec"); | 577 | MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); |
418 | 578 | ||
419 | static struct hda_codec_preset_list nvhdmi_list = { | 579 | static struct hda_codec_preset_list nvhdmi_list = { |
420 | .preset = snd_hda_preset_nvhdmi, | 580 | .preset = snd_hda_preset_nvhdmi, |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e8cbe216e912..53538b0f9991 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -230,6 +230,7 @@ enum { | |||
230 | ALC888_ACER_ASPIRE_7730G, | 230 | ALC888_ACER_ASPIRE_7730G, |
231 | ALC883_MEDION, | 231 | ALC883_MEDION, |
232 | ALC883_MEDION_MD2, | 232 | ALC883_MEDION_MD2, |
233 | ALC883_MEDION_WIM2160, | ||
233 | ALC883_LAPTOP_EAPD, | 234 | ALC883_LAPTOP_EAPD, |
234 | ALC883_LENOVO_101E_2ch, | 235 | ALC883_LENOVO_101E_2ch, |
235 | ALC883_LENOVO_NB0763, | 236 | ALC883_LENOVO_NB0763, |
@@ -275,6 +276,18 @@ struct alc_mic_route { | |||
275 | 276 | ||
276 | #define MUX_IDX_UNDEF ((unsigned char)-1) | 277 | #define MUX_IDX_UNDEF ((unsigned char)-1) |
277 | 278 | ||
279 | struct alc_customize_define { | ||
280 | unsigned int sku_cfg; | ||
281 | unsigned char port_connectivity; | ||
282 | unsigned char check_sum; | ||
283 | unsigned char customization; | ||
284 | unsigned char external_amp; | ||
285 | unsigned int enable_pcbeep:1; | ||
286 | unsigned int platform_type:1; | ||
287 | unsigned int swap:1; | ||
288 | unsigned int override:1; | ||
289 | }; | ||
290 | |||
278 | struct alc_spec { | 291 | struct alc_spec { |
279 | /* codec parameterization */ | 292 | /* codec parameterization */ |
280 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ | 293 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ |
@@ -332,6 +345,7 @@ struct alc_spec { | |||
332 | 345 | ||
333 | /* dynamic controls, init_verbs and input_mux */ | 346 | /* dynamic controls, init_verbs and input_mux */ |
334 | struct auto_pin_cfg autocfg; | 347 | struct auto_pin_cfg autocfg; |
348 | struct alc_customize_define cdefine; | ||
335 | struct snd_array kctls; | 349 | struct snd_array kctls; |
336 | struct hda_input_mux private_imux[3]; | 350 | struct hda_input_mux private_imux[3]; |
337 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 351 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
@@ -411,6 +425,8 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, | |||
411 | unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); | 425 | unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); |
412 | if (mux_idx >= spec->num_mux_defs) | 426 | if (mux_idx >= spec->num_mux_defs) |
413 | mux_idx = 0; | 427 | mux_idx = 0; |
428 | if (!spec->input_mux[mux_idx].num_items && mux_idx > 0) | ||
429 | mux_idx = 0; | ||
414 | return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); | 430 | return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); |
415 | } | 431 | } |
416 | 432 | ||
@@ -439,6 +455,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
439 | 455 | ||
440 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; | 456 | mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; |
441 | imux = &spec->input_mux[mux_idx]; | 457 | imux = &spec->input_mux[mux_idx]; |
458 | if (!imux->num_items && mux_idx > 0) | ||
459 | imux = &spec->input_mux[0]; | ||
442 | 460 | ||
443 | type = get_wcaps_type(get_wcaps(codec, nid)); | 461 | type = get_wcaps_type(get_wcaps(codec, nid)); |
444 | if (type == AC_WID_AUD_MIX) { | 462 | if (type == AC_WID_AUD_MIX) { |
@@ -1243,6 +1261,62 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
1243 | spec->unsol_event = alc_sku_unsol_event; | 1261 | spec->unsol_event = alc_sku_unsol_event; |
1244 | } | 1262 | } |
1245 | 1263 | ||
1264 | static int alc_auto_parse_customize_define(struct hda_codec *codec) | ||
1265 | { | ||
1266 | unsigned int ass, tmp, i; | ||
1267 | unsigned nid = 0; | ||
1268 | struct alc_spec *spec = codec->spec; | ||
1269 | |||
1270 | ass = codec->subsystem_id & 0xffff; | ||
1271 | if (ass != codec->bus->pci->subsystem_device && (ass & 1)) | ||
1272 | goto do_sku; | ||
1273 | |||
1274 | nid = 0x1d; | ||
1275 | if (codec->vendor_id == 0x10ec0260) | ||
1276 | nid = 0x17; | ||
1277 | ass = snd_hda_codec_get_pincfg(codec, nid); | ||
1278 | |||
1279 | if (!(ass & 1)) { | ||
1280 | printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n", | ||
1281 | codec->chip_name, ass); | ||
1282 | return -1; | ||
1283 | } | ||
1284 | |||
1285 | /* check sum */ | ||
1286 | tmp = 0; | ||
1287 | for (i = 1; i < 16; i++) { | ||
1288 | if ((ass >> i) & 1) | ||
1289 | tmp++; | ||
1290 | } | ||
1291 | if (((ass >> 16) & 0xf) != tmp) | ||
1292 | return -1; | ||
1293 | |||
1294 | spec->cdefine.port_connectivity = ass >> 30; | ||
1295 | spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20; | ||
1296 | spec->cdefine.check_sum = (ass >> 16) & 0xf; | ||
1297 | spec->cdefine.customization = ass >> 8; | ||
1298 | do_sku: | ||
1299 | spec->cdefine.sku_cfg = ass; | ||
1300 | spec->cdefine.external_amp = (ass & 0x38) >> 3; | ||
1301 | spec->cdefine.platform_type = (ass & 0x4) >> 2; | ||
1302 | spec->cdefine.swap = (ass & 0x2) >> 1; | ||
1303 | spec->cdefine.override = ass & 0x1; | ||
1304 | |||
1305 | snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n", | ||
1306 | nid, spec->cdefine.sku_cfg); | ||
1307 | snd_printd("SKU: port_connectivity=0x%x\n", | ||
1308 | spec->cdefine.port_connectivity); | ||
1309 | snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep); | ||
1310 | snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum); | ||
1311 | snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization); | ||
1312 | snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp); | ||
1313 | snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type); | ||
1314 | snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap); | ||
1315 | snd_printd("SKU: override=0x%x\n", spec->cdefine.override); | ||
1316 | |||
1317 | return 0; | ||
1318 | } | ||
1319 | |||
1246 | /* check subsystem ID and set up device-specific initialization; | 1320 | /* check subsystem ID and set up device-specific initialization; |
1247 | * return 1 if initialized, 0 if invalid SSID | 1321 | * return 1 if initialized, 0 if invalid SSID |
1248 | */ | 1322 | */ |
@@ -1385,22 +1459,31 @@ struct alc_fixup { | |||
1385 | 1459 | ||
1386 | static void alc_pick_fixup(struct hda_codec *codec, | 1460 | static void alc_pick_fixup(struct hda_codec *codec, |
1387 | const struct snd_pci_quirk *quirk, | 1461 | const struct snd_pci_quirk *quirk, |
1388 | const struct alc_fixup *fix) | 1462 | const struct alc_fixup *fix, |
1463 | int pre_init) | ||
1389 | { | 1464 | { |
1390 | const struct alc_pincfg *cfg; | 1465 | const struct alc_pincfg *cfg; |
1391 | 1466 | ||
1392 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); | 1467 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); |
1393 | if (!quirk) | 1468 | if (!quirk) |
1394 | return; | 1469 | return; |
1395 | |||
1396 | fix += quirk->value; | 1470 | fix += quirk->value; |
1397 | cfg = fix->pins; | 1471 | cfg = fix->pins; |
1398 | if (cfg) { | 1472 | if (pre_init && cfg) { |
1473 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
1474 | snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", | ||
1475 | codec->chip_name, quirk->name); | ||
1476 | #endif | ||
1399 | for (; cfg->nid; cfg++) | 1477 | for (; cfg->nid; cfg++) |
1400 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); | 1478 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); |
1401 | } | 1479 | } |
1402 | if (fix->verbs) | 1480 | if (!pre_init && fix->verbs) { |
1481 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
1482 | snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-verbs for %s\n", | ||
1483 | codec->chip_name, quirk->name); | ||
1484 | #endif | ||
1403 | add_verb(codec->spec, fix->verbs); | 1485 | add_verb(codec->spec, fix->verbs); |
1486 | } | ||
1404 | } | 1487 | } |
1405 | 1488 | ||
1406 | static int alc_read_coef_idx(struct hda_codec *codec, | 1489 | static int alc_read_coef_idx(struct hda_codec *codec, |
@@ -1617,6 +1700,11 @@ static struct hda_verb alc888_acer_aspire_4930g_verbs[] = { | |||
1617 | */ | 1700 | */ |
1618 | 1701 | ||
1619 | static struct hda_verb alc888_acer_aspire_6530g_verbs[] = { | 1702 | static struct hda_verb alc888_acer_aspire_6530g_verbs[] = { |
1703 | /* Route to built-in subwoofer as well as speakers */ | ||
1704 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1705 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1706 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1707 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1620 | /* Bias voltage on for external mic port */ | 1708 | /* Bias voltage on for external mic port */ |
1621 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80}, | 1709 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80}, |
1622 | /* Front Mic: set to PIN_IN (empty by default) */ | 1710 | /* Front Mic: set to PIN_IN (empty by default) */ |
@@ -1628,10 +1716,12 @@ static struct hda_verb alc888_acer_aspire_6530g_verbs[] = { | |||
1628 | /* Enable speaker output */ | 1716 | /* Enable speaker output */ |
1629 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 1717 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1630 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1718 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1719 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
1631 | /* Enable headphone output */ | 1720 | /* Enable headphone output */ |
1632 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP}, | 1721 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP}, |
1633 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1722 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1634 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | 1723 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1724 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
1635 | { } | 1725 | { } |
1636 | }; | 1726 | }; |
1637 | 1727 | ||
@@ -2528,8 +2618,6 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2528 | return err; | 2618 | return err; |
2529 | } | 2619 | } |
2530 | 2620 | ||
2531 | alc_free_kctls(codec); /* no longer needed */ | ||
2532 | |||
2533 | /* assign Capture Source enums to NID */ | 2621 | /* assign Capture Source enums to NID */ |
2534 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | 2622 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); |
2535 | if (!kctl) | 2623 | if (!kctl) |
@@ -2598,6 +2686,9 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2598 | } | 2686 | } |
2599 | } | 2687 | } |
2600 | } | 2688 | } |
2689 | |||
2690 | alc_free_kctls(codec); /* no longer needed */ | ||
2691 | |||
2601 | return 0; | 2692 | return 0; |
2602 | } | 2693 | } |
2603 | 2694 | ||
@@ -3393,6 +3484,10 @@ static int alc_init(struct hda_codec *codec) | |||
3393 | if (spec->init_hook) | 3484 | if (spec->init_hook) |
3394 | spec->init_hook(codec); | 3485 | spec->init_hook(codec); |
3395 | 3486 | ||
3487 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3488 | if (codec->patch_ops.check_power_status) | ||
3489 | codec->patch_ops.check_power_status(codec, 0x01); | ||
3490 | #endif | ||
3396 | return 0; | 3491 | return 0; |
3397 | } | 3492 | } |
3398 | 3493 | ||
@@ -3753,6 +3848,10 @@ static int alc_resume(struct hda_codec *codec) | |||
3753 | codec->patch_ops.init(codec); | 3848 | codec->patch_ops.init(codec); |
3754 | snd_hda_codec_resume_amp(codec); | 3849 | snd_hda_codec_resume_amp(codec); |
3755 | snd_hda_codec_resume_cache(codec); | 3850 | snd_hda_codec_resume_cache(codec); |
3851 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3852 | if (codec->patch_ops.check_power_status) | ||
3853 | codec->patch_ops.check_power_status(codec, 0x01); | ||
3854 | #endif | ||
3756 | return 0; | 3855 | return 0; |
3757 | } | 3856 | } |
3758 | #endif | 3857 | #endif |
@@ -3775,6 +3874,17 @@ static struct hda_codec_ops alc_patch_ops = { | |||
3775 | .reboot_notify = alc_shutup, | 3874 | .reboot_notify = alc_shutup, |
3776 | }; | 3875 | }; |
3777 | 3876 | ||
3877 | /* replace the codec chip_name with the given string */ | ||
3878 | static int alc_codec_rename(struct hda_codec *codec, const char *name) | ||
3879 | { | ||
3880 | kfree(codec->chip_name); | ||
3881 | codec->chip_name = kstrdup(name, GFP_KERNEL); | ||
3882 | if (!codec->chip_name) { | ||
3883 | alc_free(codec); | ||
3884 | return -ENOMEM; | ||
3885 | } | ||
3886 | return 0; | ||
3887 | } | ||
3778 | 3888 | ||
3779 | /* | 3889 | /* |
3780 | * Test configuration for debugging | 3890 | * Test configuration for debugging |
@@ -4121,7 +4231,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { | |||
4121 | SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), | 4231 | SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), |
4122 | SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), | 4232 | SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), |
4123 | SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), | 4233 | SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), |
4124 | SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL), | 4234 | SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734), |
4125 | SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), | 4235 | SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), |
4126 | SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), | 4236 | SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), |
4127 | SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), | 4237 | SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), |
@@ -4796,6 +4906,25 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) | |||
4796 | } | 4906 | } |
4797 | } | 4907 | } |
4798 | 4908 | ||
4909 | static void alc880_auto_init_input_src(struct hda_codec *codec) | ||
4910 | { | ||
4911 | struct alc_spec *spec = codec->spec; | ||
4912 | int c; | ||
4913 | |||
4914 | for (c = 0; c < spec->num_adc_nids; c++) { | ||
4915 | unsigned int mux_idx; | ||
4916 | const struct hda_input_mux *imux; | ||
4917 | mux_idx = c >= spec->num_mux_defs ? 0 : c; | ||
4918 | imux = &spec->input_mux[mux_idx]; | ||
4919 | if (!imux->num_items && mux_idx > 0) | ||
4920 | imux = &spec->input_mux[0]; | ||
4921 | if (imux) | ||
4922 | snd_hda_codec_write(codec, spec->adc_nids[c], 0, | ||
4923 | AC_VERB_SET_CONNECT_SEL, | ||
4924 | imux->items[0].index); | ||
4925 | } | ||
4926 | } | ||
4927 | |||
4799 | /* parse the BIOS configuration and set up the alc_spec */ | 4928 | /* parse the BIOS configuration and set up the alc_spec */ |
4800 | /* return 1 if successful, 0 if the proper config is not found, | 4929 | /* return 1 if successful, 0 if the proper config is not found, |
4801 | * or a negative error code | 4930 | * or a negative error code |
@@ -4874,6 +5003,7 @@ static void alc880_auto_init(struct hda_codec *codec) | |||
4874 | alc880_auto_init_multi_out(codec); | 5003 | alc880_auto_init_multi_out(codec); |
4875 | alc880_auto_init_extra_out(codec); | 5004 | alc880_auto_init_extra_out(codec); |
4876 | alc880_auto_init_analog_input(codec); | 5005 | alc880_auto_init_analog_input(codec); |
5006 | alc880_auto_init_input_src(codec); | ||
4877 | if (spec->unsol_event) | 5007 | if (spec->unsol_event) |
4878 | alc_inithook(codec); | 5008 | alc_inithook(codec); |
4879 | } | 5009 | } |
@@ -4915,7 +5045,7 @@ static void fixup_automic_adc(struct hda_codec *codec) | |||
4915 | static void fixup_single_adc(struct hda_codec *codec) | 5045 | static void fixup_single_adc(struct hda_codec *codec) |
4916 | { | 5046 | { |
4917 | struct alc_spec *spec = codec->spec; | 5047 | struct alc_spec *spec = codec->spec; |
4918 | hda_nid_t pin; | 5048 | hda_nid_t pin = 0; |
4919 | int i; | 5049 | int i; |
4920 | 5050 | ||
4921 | /* search for the input pin; there must be only one */ | 5051 | /* search for the input pin; there must be only one */ |
@@ -4979,6 +5109,70 @@ static void set_capture_mixer(struct hda_codec *codec) | |||
4979 | } | 5109 | } |
4980 | } | 5110 | } |
4981 | 5111 | ||
5112 | /* fill adc_nids (and capsrc_nids) containing all active input pins */ | ||
5113 | static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | ||
5114 | int num_nids) | ||
5115 | { | ||
5116 | struct alc_spec *spec = codec->spec; | ||
5117 | int n; | ||
5118 | hda_nid_t fallback_adc = 0, fallback_cap = 0; | ||
5119 | |||
5120 | for (n = 0; n < num_nids; n++) { | ||
5121 | hda_nid_t adc, cap; | ||
5122 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | ||
5123 | int nconns, i, j; | ||
5124 | |||
5125 | adc = nids[n]; | ||
5126 | if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN) | ||
5127 | continue; | ||
5128 | cap = adc; | ||
5129 | nconns = snd_hda_get_connections(codec, cap, conn, | ||
5130 | ARRAY_SIZE(conn)); | ||
5131 | if (nconns == 1) { | ||
5132 | cap = conn[0]; | ||
5133 | nconns = snd_hda_get_connections(codec, cap, conn, | ||
5134 | ARRAY_SIZE(conn)); | ||
5135 | } | ||
5136 | if (nconns <= 0) | ||
5137 | continue; | ||
5138 | if (!fallback_adc) { | ||
5139 | fallback_adc = adc; | ||
5140 | fallback_cap = cap; | ||
5141 | } | ||
5142 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
5143 | hda_nid_t nid = spec->autocfg.input_pins[i]; | ||
5144 | if (!nid) | ||
5145 | continue; | ||
5146 | for (j = 0; j < nconns; j++) { | ||
5147 | if (conn[j] == nid) | ||
5148 | break; | ||
5149 | } | ||
5150 | if (j >= nconns) | ||
5151 | break; | ||
5152 | } | ||
5153 | if (i >= AUTO_PIN_LAST) { | ||
5154 | int num_adcs = spec->num_adc_nids; | ||
5155 | spec->private_adc_nids[num_adcs] = adc; | ||
5156 | spec->private_capsrc_nids[num_adcs] = cap; | ||
5157 | spec->num_adc_nids++; | ||
5158 | spec->adc_nids = spec->private_adc_nids; | ||
5159 | if (adc != cap) | ||
5160 | spec->capsrc_nids = spec->private_capsrc_nids; | ||
5161 | } | ||
5162 | } | ||
5163 | if (!spec->num_adc_nids) { | ||
5164 | printk(KERN_WARNING "hda_codec: %s: no valid ADC found;" | ||
5165 | " using fallback 0x%x\n", | ||
5166 | codec->chip_name, fallback_adc); | ||
5167 | spec->private_adc_nids[0] = fallback_adc; | ||
5168 | spec->adc_nids = spec->private_adc_nids; | ||
5169 | if (fallback_adc != fallback_cap) { | ||
5170 | spec->private_capsrc_nids[0] = fallback_cap; | ||
5171 | spec->capsrc_nids = spec->private_adc_nids; | ||
5172 | } | ||
5173 | } | ||
5174 | } | ||
5175 | |||
4982 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 5176 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
4983 | #define set_beep_amp(spec, nid, idx, dir) \ | 5177 | #define set_beep_amp(spec, nid, idx, dir) \ |
4984 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) | 5178 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) |
@@ -6321,6 +6515,8 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec) | |||
6321 | } | 6515 | } |
6322 | } | 6516 | } |
6323 | 6517 | ||
6518 | #define alc260_auto_init_input_src alc880_auto_init_input_src | ||
6519 | |||
6324 | /* | 6520 | /* |
6325 | * generic initialization of ADC, input mixers and output mixers | 6521 | * generic initialization of ADC, input mixers and output mixers |
6326 | */ | 6522 | */ |
@@ -6407,6 +6603,7 @@ static void alc260_auto_init(struct hda_codec *codec) | |||
6407 | struct alc_spec *spec = codec->spec; | 6603 | struct alc_spec *spec = codec->spec; |
6408 | alc260_auto_init_multi_out(codec); | 6604 | alc260_auto_init_multi_out(codec); |
6409 | alc260_auto_init_analog_input(codec); | 6605 | alc260_auto_init_analog_input(codec); |
6606 | alc260_auto_init_input_src(codec); | ||
6410 | if (spec->unsol_event) | 6607 | if (spec->unsol_event) |
6411 | alc_inithook(codec); | 6608 | alc_inithook(codec); |
6412 | } | 6609 | } |
@@ -6473,7 +6670,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
6473 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 6670 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
6474 | .dac_nids = alc260_dac_nids, | 6671 | .dac_nids = alc260_dac_nids, |
6475 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), | 6672 | .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), |
6476 | .adc_nids = alc260_adc_nids, | 6673 | .adc_nids = alc260_dual_adc_nids, |
6477 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 6674 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
6478 | .channel_mode = alc260_modes, | 6675 | .channel_mode = alc260_modes, |
6479 | .input_mux = &alc260_capture_source, | 6676 | .input_mux = &alc260_capture_source, |
@@ -8379,6 +8576,42 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { | |||
8379 | { } /* end */ | 8576 | { } /* end */ |
8380 | }; | 8577 | }; |
8381 | 8578 | ||
8579 | static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = { | ||
8580 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
8581 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
8582 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
8583 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), | ||
8584 | HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT), | ||
8585 | HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT), | ||
8586 | { } /* end */ | ||
8587 | }; | ||
8588 | |||
8589 | static struct hda_verb alc883_medion_wim2160_verbs[] = { | ||
8590 | /* Unmute front mixer */ | ||
8591 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8592 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8593 | |||
8594 | /* Set speaker pin to front mixer */ | ||
8595 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
8596 | |||
8597 | /* Init headphone pin */ | ||
8598 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
8599 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
8600 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
8601 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
8602 | |||
8603 | { } /* end */ | ||
8604 | }; | ||
8605 | |||
8606 | /* toggle speaker-output according to the hp-jack state */ | ||
8607 | static void alc883_medion_wim2160_setup(struct hda_codec *codec) | ||
8608 | { | ||
8609 | struct alc_spec *spec = codec->spec; | ||
8610 | |||
8611 | spec->autocfg.hp_pins[0] = 0x1a; | ||
8612 | spec->autocfg.speaker_pins[0] = 0x15; | ||
8613 | } | ||
8614 | |||
8382 | static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { | 8615 | static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { |
8383 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 8616 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
8384 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | 8617 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
@@ -8393,9 +8626,7 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { | |||
8393 | 8626 | ||
8394 | static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = { | 8627 | static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = { |
8395 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 8628 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
8396 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
8397 | HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | 8629 | HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT), |
8398 | HDA_BIND_MUTE("LFE Playback Switch", 0x0f, 2, HDA_INPUT), | ||
8399 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 8630 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
8400 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8631 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
8401 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 8632 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
@@ -9090,6 +9321,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { | |||
9090 | [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g", | 9321 | [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g", |
9091 | [ALC883_MEDION] = "medion", | 9322 | [ALC883_MEDION] = "medion", |
9092 | [ALC883_MEDION_MD2] = "medion-md2", | 9323 | [ALC883_MEDION_MD2] = "medion-md2", |
9324 | [ALC883_MEDION_WIM2160] = "medion-wim2160", | ||
9093 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", | 9325 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", |
9094 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", | 9326 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", |
9095 | [ALC883_LENOVO_NB0763] = "lenovo-nb0763", | 9327 | [ALC883_LENOVO_NB0763] = "lenovo-nb0763", |
@@ -9191,6 +9423,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { | |||
9191 | SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), | 9423 | SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), |
9192 | SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), | 9424 | SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), |
9193 | SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), | 9425 | SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), |
9426 | SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG), | ||
9194 | SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG), | 9427 | SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG), |
9195 | SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), | 9428 | SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), |
9196 | SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), | 9429 | SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), |
@@ -9200,10 +9433,12 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { | |||
9200 | SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), | 9433 | SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), |
9201 | SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), | 9434 | SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), |
9202 | SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG), | 9435 | SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG), |
9436 | SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG), | ||
9203 | SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), | 9437 | SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), |
9204 | SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG), | 9438 | SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG), |
9205 | 9439 | ||
9206 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), | 9440 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), |
9441 | SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG), | ||
9207 | SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), | 9442 | SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), |
9208 | SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), | 9443 | SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), |
9209 | SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R), | 9444 | SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R), |
@@ -9231,7 +9466,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { | |||
9231 | SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL), | 9466 | SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL), |
9232 | SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL), | 9467 | SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL), |
9233 | SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL), | 9468 | SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL), |
9234 | SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), | 9469 | SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG), |
9235 | 9470 | ||
9236 | {} | 9471 | {} |
9237 | }; | 9472 | }; |
@@ -9742,6 +9977,21 @@ static struct alc_config_preset alc882_presets[] = { | |||
9742 | .setup = alc883_medion_md2_setup, | 9977 | .setup = alc883_medion_md2_setup, |
9743 | .init_hook = alc_automute_amp, | 9978 | .init_hook = alc_automute_amp, |
9744 | }, | 9979 | }, |
9980 | [ALC883_MEDION_WIM2160] = { | ||
9981 | .mixers = { alc883_medion_wim2160_mixer }, | ||
9982 | .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs }, | ||
9983 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
9984 | .dac_nids = alc883_dac_nids, | ||
9985 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
9986 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
9987 | .adc_nids = alc883_adc_nids, | ||
9988 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
9989 | .channel_mode = alc883_3ST_2ch_modes, | ||
9990 | .input_mux = &alc883_capture_source, | ||
9991 | .unsol_event = alc_automute_amp_unsol_event, | ||
9992 | .setup = alc883_medion_wim2160_setup, | ||
9993 | .init_hook = alc_automute_amp, | ||
9994 | }, | ||
9745 | [ALC883_LAPTOP_EAPD] = { | 9995 | [ALC883_LAPTOP_EAPD] = { |
9746 | .mixers = { alc883_base_mixer }, | 9996 | .mixers = { alc883_base_mixer }, |
9747 | .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, | 9997 | .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, |
@@ -10027,19 +10277,20 @@ static int alc882_auto_create_input_ctls(struct hda_codec *codec, | |||
10027 | 10277 | ||
10028 | static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, | 10278 | static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, |
10029 | hda_nid_t nid, int pin_type, | 10279 | hda_nid_t nid, int pin_type, |
10030 | int dac_idx) | 10280 | hda_nid_t dac) |
10031 | { | 10281 | { |
10032 | /* set as output */ | ||
10033 | struct alc_spec *spec = codec->spec; | ||
10034 | int idx; | 10282 | int idx; |
10035 | 10283 | ||
10284 | /* set as output */ | ||
10036 | alc_set_pin_output(codec, nid, pin_type); | 10285 | alc_set_pin_output(codec, nid, pin_type); |
10037 | if (spec->multiout.dac_nids[dac_idx] == 0x25) | 10286 | |
10287 | if (dac == 0x25) | ||
10038 | idx = 4; | 10288 | idx = 4; |
10289 | else if (dac >= 0x02 && dac <= 0x05) | ||
10290 | idx = dac - 2; | ||
10039 | else | 10291 | else |
10040 | idx = spec->multiout.dac_nids[dac_idx] - 2; | 10292 | return; |
10041 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); | 10293 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); |
10042 | |||
10043 | } | 10294 | } |
10044 | 10295 | ||
10045 | static void alc882_auto_init_multi_out(struct hda_codec *codec) | 10296 | static void alc882_auto_init_multi_out(struct hda_codec *codec) |
@@ -10052,22 +10303,29 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec) | |||
10052 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | 10303 | int pin_type = get_pin_type(spec->autocfg.line_out_type); |
10053 | if (nid) | 10304 | if (nid) |
10054 | alc882_auto_set_output_and_unmute(codec, nid, pin_type, | 10305 | alc882_auto_set_output_and_unmute(codec, nid, pin_type, |
10055 | i); | 10306 | spec->multiout.dac_nids[i]); |
10056 | } | 10307 | } |
10057 | } | 10308 | } |
10058 | 10309 | ||
10059 | static void alc882_auto_init_hp_out(struct hda_codec *codec) | 10310 | static void alc882_auto_init_hp_out(struct hda_codec *codec) |
10060 | { | 10311 | { |
10061 | struct alc_spec *spec = codec->spec; | 10312 | struct alc_spec *spec = codec->spec; |
10062 | hda_nid_t pin; | 10313 | hda_nid_t pin, dac; |
10063 | 10314 | ||
10064 | pin = spec->autocfg.hp_pins[0]; | 10315 | pin = spec->autocfg.hp_pins[0]; |
10065 | if (pin) /* connect to front */ | 10316 | if (pin) { |
10066 | /* use dac 0 */ | 10317 | dac = spec->multiout.hp_nid; |
10067 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 10318 | if (!dac) |
10319 | dac = spec->multiout.dac_nids[0]; /* to front */ | ||
10320 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); | ||
10321 | } | ||
10068 | pin = spec->autocfg.speaker_pins[0]; | 10322 | pin = spec->autocfg.speaker_pins[0]; |
10069 | if (pin) | 10323 | if (pin) { |
10070 | alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 10324 | dac = spec->multiout.extra_out_nid[0]; |
10325 | if (!dac) | ||
10326 | dac = spec->multiout.dac_nids[0]; /* to front */ | ||
10327 | alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); | ||
10328 | } | ||
10071 | } | 10329 | } |
10072 | 10330 | ||
10073 | static void alc882_auto_init_analog_input(struct hda_codec *codec) | 10331 | static void alc882_auto_init_analog_input(struct hda_codec *codec) |
@@ -10105,6 +10363,8 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) | |||
10105 | continue; | 10363 | continue; |
10106 | mux_idx = c >= spec->num_mux_defs ? 0 : c; | 10364 | mux_idx = c >= spec->num_mux_defs ? 0 : c; |
10107 | imux = &spec->input_mux[mux_idx]; | 10365 | imux = &spec->input_mux[mux_idx]; |
10366 | if (!imux->num_items && mux_idx > 0) | ||
10367 | imux = &spec->input_mux[0]; | ||
10108 | for (idx = 0; idx < conns; idx++) { | 10368 | for (idx = 0; idx < conns; idx++) { |
10109 | /* if the current connection is the selected one, | 10369 | /* if the current connection is the selected one, |
10110 | * unmute it as default - otherwise mute it | 10370 | * unmute it as default - otherwise mute it |
@@ -10181,15 +10441,15 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
10181 | err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); | 10441 | err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); |
10182 | if (err < 0) | 10442 | if (err < 0) |
10183 | return err; | 10443 | return err; |
10444 | err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], | ||
10445 | "Headphone"); | ||
10446 | if (err < 0) | ||
10447 | return err; | ||
10184 | err = alc880_auto_create_extra_out(spec, | 10448 | err = alc880_auto_create_extra_out(spec, |
10185 | spec->autocfg.speaker_pins[0], | 10449 | spec->autocfg.speaker_pins[0], |
10186 | "Speaker"); | 10450 | "Speaker"); |
10187 | if (err < 0) | 10451 | if (err < 0) |
10188 | return err; | 10452 | return err; |
10189 | err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], | ||
10190 | "Headphone"); | ||
10191 | if (err < 0) | ||
10192 | return err; | ||
10193 | err = alc882_auto_create_input_ctls(codec, &spec->autocfg); | 10453 | err = alc882_auto_create_input_ctls(codec, &spec->autocfg); |
10194 | if (err < 0) | 10454 | if (err < 0) |
10195 | return err; | 10455 | return err; |
@@ -10259,6 +10519,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
10259 | 10519 | ||
10260 | codec->spec = spec; | 10520 | codec->spec = spec; |
10261 | 10521 | ||
10522 | alc_auto_parse_customize_define(codec); | ||
10523 | |||
10262 | switch (codec->vendor_id) { | 10524 | switch (codec->vendor_id) { |
10263 | case 0x10ec0882: | 10525 | case 0x10ec0882: |
10264 | case 0x10ec0885: | 10526 | case 0x10ec0885: |
@@ -10283,7 +10545,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
10283 | board_config = ALC882_AUTO; | 10545 | board_config = ALC882_AUTO; |
10284 | } | 10546 | } |
10285 | 10547 | ||
10286 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups); | 10548 | if (board_config == ALC882_AUTO) |
10549 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1); | ||
10287 | 10550 | ||
10288 | if (board_config == ALC882_AUTO) { | 10551 | if (board_config == ALC882_AUTO) { |
10289 | /* automatic parse from the BIOS config */ | 10552 | /* automatic parse from the BIOS config */ |
@@ -10317,9 +10580,6 @@ static int patch_alc882(struct hda_codec *codec) | |||
10317 | spec->stream_digital_playback = &alc882_pcm_digital_playback; | 10580 | spec->stream_digital_playback = &alc882_pcm_digital_playback; |
10318 | spec->stream_digital_capture = &alc882_pcm_digital_capture; | 10581 | spec->stream_digital_capture = &alc882_pcm_digital_capture; |
10319 | 10582 | ||
10320 | if (codec->vendor_id == 0x10ec0888) | ||
10321 | spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */ | ||
10322 | |||
10323 | if (!spec->adc_nids && spec->input_mux) { | 10583 | if (!spec->adc_nids && spec->input_mux) { |
10324 | int i, j; | 10584 | int i, j; |
10325 | spec->num_adc_nids = 0; | 10585 | spec->num_adc_nids = 0; |
@@ -10354,7 +10614,12 @@ static int patch_alc882(struct hda_codec *codec) | |||
10354 | } | 10614 | } |
10355 | 10615 | ||
10356 | set_capture_mixer(codec); | 10616 | set_capture_mixer(codec); |
10357 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 10617 | |
10618 | if (spec->cdefine.enable_pcbeep) | ||
10619 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
10620 | |||
10621 | if (board_config == ALC882_AUTO) | ||
10622 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0); | ||
10358 | 10623 | ||
10359 | spec->vmaster_nid = 0x0c; | 10624 | spec->vmaster_nid = 0x0c; |
10360 | 10625 | ||
@@ -12138,6 +12403,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
12138 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); | 12403 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); |
12139 | } | 12404 | } |
12140 | #endif | 12405 | #endif |
12406 | alc_auto_parse_customize_define(codec); | ||
12141 | 12407 | ||
12142 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); | 12408 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); |
12143 | 12409 | ||
@@ -12216,7 +12482,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
12216 | } | 12482 | } |
12217 | if (!spec->cap_mixer && !spec->no_analog) | 12483 | if (!spec->cap_mixer && !spec->no_analog) |
12218 | set_capture_mixer(codec); | 12484 | set_capture_mixer(codec); |
12219 | if (!spec->no_analog) | 12485 | if (!spec->no_analog && spec->cdefine.enable_pcbeep) |
12220 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 12486 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
12221 | 12487 | ||
12222 | spec->vmaster_nid = 0x0c; | 12488 | spec->vmaster_nid = 0x0c; |
@@ -12447,11 +12713,11 @@ static void alc268_aspire_one_speaker_automute(struct hda_codec *codec) | |||
12447 | unsigned char bits; | 12713 | unsigned char bits; |
12448 | 12714 | ||
12449 | present = snd_hda_jack_detect(codec, 0x15); | 12715 | present = snd_hda_jack_detect(codec, 0x15); |
12450 | bits = present ? AMP_IN_MUTE(0) : 0; | 12716 | bits = present ? HDA_AMP_MUTE : 0; |
12451 | snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0, | 12717 | snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0, |
12452 | AMP_IN_MUTE(0), bits); | 12718 | HDA_AMP_MUTE, bits); |
12453 | snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1, | 12719 | snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1, |
12454 | AMP_IN_MUTE(0), bits); | 12720 | HDA_AMP_MUTE, bits); |
12455 | } | 12721 | } |
12456 | 12722 | ||
12457 | static void alc268_acer_lc_unsol_event(struct hda_codec *codec, | 12723 | static void alc268_acer_lc_unsol_event(struct hda_codec *codec, |
@@ -12736,6 +13002,7 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | |||
12736 | dac = 0x02; | 13002 | dac = 0x02; |
12737 | break; | 13003 | break; |
12738 | case 0x15: | 13004 | case 0x15: |
13005 | case 0x21: /* ALC269vb has this pin, too */ | ||
12739 | dac = 0x03; | 13006 | dac = 0x03; |
12740 | break; | 13007 | break; |
12741 | default: | 13008 | default: |
@@ -13201,7 +13468,7 @@ static int patch_alc268(struct hda_codec *codec) | |||
13201 | 13468 | ||
13202 | if (board_config < 0 || board_config >= ALC268_MODEL_LAST) | 13469 | if (board_config < 0 || board_config >= ALC268_MODEL_LAST) |
13203 | board_config = snd_hda_check_board_codec_sid_config(codec, | 13470 | board_config = snd_hda_check_board_codec_sid_config(codec, |
13204 | ALC882_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl); | 13471 | ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl); |
13205 | 13472 | ||
13206 | if (board_config < 0 || board_config >= ALC268_MODEL_LAST) { | 13473 | if (board_config < 0 || board_config >= ALC268_MODEL_LAST) { |
13207 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | 13474 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", |
@@ -13321,9 +13588,9 @@ static hda_nid_t alc269vb_capsrc_nids[1] = { | |||
13321 | 0x22, | 13588 | 0x22, |
13322 | }; | 13589 | }; |
13323 | 13590 | ||
13324 | /* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24), | 13591 | static hda_nid_t alc269_adc_candidates[] = { |
13325 | * not a mux! | 13592 | 0x08, 0x09, 0x07, |
13326 | */ | 13593 | }; |
13327 | 13594 | ||
13328 | #define alc269_modes alc260_modes | 13595 | #define alc269_modes alc260_modes |
13329 | #define alc269_capture_source alc880_lg_lw_capture_source | 13596 | #define alc269_capture_source alc880_lg_lw_capture_source |
@@ -13470,11 +13737,11 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec) | |||
13470 | unsigned char bits; | 13737 | unsigned char bits; |
13471 | 13738 | ||
13472 | present = snd_hda_jack_detect(codec, 0x15); | 13739 | present = snd_hda_jack_detect(codec, 0x15); |
13473 | bits = present ? AMP_IN_MUTE(0) : 0; | 13740 | bits = present ? HDA_AMP_MUTE : 0; |
13474 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | 13741 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, |
13475 | AMP_IN_MUTE(0), bits); | 13742 | HDA_AMP_MUTE, bits); |
13476 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 13743 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
13477 | AMP_IN_MUTE(0), bits); | 13744 | HDA_AMP_MUTE, bits); |
13478 | 13745 | ||
13479 | snd_hda_codec_write(codec, 0x20, 0, | 13746 | snd_hda_codec_write(codec, 0x20, 0, |
13480 | AC_VERB_SET_COEF_INDEX, 0x0c); | 13747 | AC_VERB_SET_COEF_INDEX, 0x0c); |
@@ -13499,11 +13766,11 @@ static void alc269_lifebook_speaker_automute(struct hda_codec *codec) | |||
13499 | /* Check port replicator headphone socket */ | 13766 | /* Check port replicator headphone socket */ |
13500 | present |= snd_hda_jack_detect(codec, 0x1a); | 13767 | present |= snd_hda_jack_detect(codec, 0x1a); |
13501 | 13768 | ||
13502 | bits = present ? AMP_IN_MUTE(0) : 0; | 13769 | bits = present ? HDA_AMP_MUTE : 0; |
13503 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | 13770 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, |
13504 | AMP_IN_MUTE(0), bits); | 13771 | HDA_AMP_MUTE, bits); |
13505 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 13772 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
13506 | AMP_IN_MUTE(0), bits); | 13773 | HDA_AMP_MUTE, bits); |
13507 | 13774 | ||
13508 | snd_hda_codec_write(codec, 0x20, 0, | 13775 | snd_hda_codec_write(codec, 0x20, 0, |
13509 | AC_VERB_SET_COEF_INDEX, 0x0c); | 13776 | AC_VERB_SET_COEF_INDEX, 0x0c); |
@@ -13561,6 +13828,8 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec, | |||
13561 | static void alc269_quanta_fl1_setup(struct hda_codec *codec) | 13828 | static void alc269_quanta_fl1_setup(struct hda_codec *codec) |
13562 | { | 13829 | { |
13563 | struct alc_spec *spec = codec->spec; | 13830 | struct alc_spec *spec = codec->spec; |
13831 | spec->autocfg.hp_pins[0] = 0x15; | ||
13832 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13564 | spec->ext_mic.pin = 0x18; | 13833 | spec->ext_mic.pin = 0x18; |
13565 | spec->ext_mic.mux_idx = 0; | 13834 | spec->ext_mic.mux_idx = 0; |
13566 | spec->int_mic.pin = 0x19; | 13835 | spec->int_mic.pin = 0x19; |
@@ -13632,11 +13901,11 @@ static void alc269_speaker_automute(struct hda_codec *codec) | |||
13632 | unsigned char bits; | 13901 | unsigned char bits; |
13633 | 13902 | ||
13634 | present = snd_hda_jack_detect(codec, nid); | 13903 | present = snd_hda_jack_detect(codec, nid); |
13635 | bits = present ? AMP_IN_MUTE(0) : 0; | 13904 | bits = present ? HDA_AMP_MUTE : 0; |
13636 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | 13905 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, |
13637 | AMP_IN_MUTE(0), bits); | 13906 | HDA_AMP_MUTE, bits); |
13638 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 13907 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
13639 | AMP_IN_MUTE(0), bits); | 13908 | HDA_AMP_MUTE, bits); |
13640 | } | 13909 | } |
13641 | 13910 | ||
13642 | /* unsolicited event for HP jack sensing */ | 13911 | /* unsolicited event for HP jack sensing */ |
@@ -13653,29 +13922,35 @@ static void alc269_laptop_unsol_event(struct hda_codec *codec, | |||
13653 | } | 13922 | } |
13654 | } | 13923 | } |
13655 | 13924 | ||
13656 | static void alc269_laptop_dmic_setup(struct hda_codec *codec) | 13925 | static void alc269_laptop_amic_setup(struct hda_codec *codec) |
13657 | { | 13926 | { |
13658 | struct alc_spec *spec = codec->spec; | 13927 | struct alc_spec *spec = codec->spec; |
13928 | spec->autocfg.hp_pins[0] = 0x15; | ||
13929 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13659 | spec->ext_mic.pin = 0x18; | 13930 | spec->ext_mic.pin = 0x18; |
13660 | spec->ext_mic.mux_idx = 0; | 13931 | spec->ext_mic.mux_idx = 0; |
13661 | spec->int_mic.pin = 0x12; | 13932 | spec->int_mic.pin = 0x19; |
13662 | spec->int_mic.mux_idx = 5; | 13933 | spec->int_mic.mux_idx = 1; |
13663 | spec->auto_mic = 1; | 13934 | spec->auto_mic = 1; |
13664 | } | 13935 | } |
13665 | 13936 | ||
13666 | static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) | 13937 | static void alc269_laptop_dmic_setup(struct hda_codec *codec) |
13667 | { | 13938 | { |
13668 | struct alc_spec *spec = codec->spec; | 13939 | struct alc_spec *spec = codec->spec; |
13940 | spec->autocfg.hp_pins[0] = 0x15; | ||
13941 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13669 | spec->ext_mic.pin = 0x18; | 13942 | spec->ext_mic.pin = 0x18; |
13670 | spec->ext_mic.mux_idx = 0; | 13943 | spec->ext_mic.mux_idx = 0; |
13671 | spec->int_mic.pin = 0x12; | 13944 | spec->int_mic.pin = 0x12; |
13672 | spec->int_mic.mux_idx = 6; | 13945 | spec->int_mic.mux_idx = 5; |
13673 | spec->auto_mic = 1; | 13946 | spec->auto_mic = 1; |
13674 | } | 13947 | } |
13675 | 13948 | ||
13676 | static void alc269_laptop_amic_setup(struct hda_codec *codec) | 13949 | static void alc269vb_laptop_amic_setup(struct hda_codec *codec) |
13677 | { | 13950 | { |
13678 | struct alc_spec *spec = codec->spec; | 13951 | struct alc_spec *spec = codec->spec; |
13952 | spec->autocfg.hp_pins[0] = 0x21; | ||
13953 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13679 | spec->ext_mic.pin = 0x18; | 13954 | spec->ext_mic.pin = 0x18; |
13680 | spec->ext_mic.mux_idx = 0; | 13955 | spec->ext_mic.mux_idx = 0; |
13681 | spec->int_mic.pin = 0x19; | 13956 | spec->int_mic.pin = 0x19; |
@@ -13683,6 +13958,18 @@ static void alc269_laptop_amic_setup(struct hda_codec *codec) | |||
13683 | spec->auto_mic = 1; | 13958 | spec->auto_mic = 1; |
13684 | } | 13959 | } |
13685 | 13960 | ||
13961 | static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) | ||
13962 | { | ||
13963 | struct alc_spec *spec = codec->spec; | ||
13964 | spec->autocfg.hp_pins[0] = 0x21; | ||
13965 | spec->autocfg.speaker_pins[0] = 0x14; | ||
13966 | spec->ext_mic.pin = 0x18; | ||
13967 | spec->ext_mic.mux_idx = 0; | ||
13968 | spec->int_mic.pin = 0x12; | ||
13969 | spec->int_mic.mux_idx = 6; | ||
13970 | spec->auto_mic = 1; | ||
13971 | } | ||
13972 | |||
13686 | static void alc269_laptop_inithook(struct hda_codec *codec) | 13973 | static void alc269_laptop_inithook(struct hda_codec *codec) |
13687 | { | 13974 | { |
13688 | alc269_speaker_automute(codec); | 13975 | alc269_speaker_automute(codec); |
@@ -13814,6 +14101,35 @@ static struct hda_pcm_stream alc269_44k_pcm_analog_capture = { | |||
13814 | /* NID is set in alc_build_pcms */ | 14101 | /* NID is set in alc_build_pcms */ |
13815 | }; | 14102 | }; |
13816 | 14103 | ||
14104 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
14105 | static int alc269_mic2_for_mute_led(struct hda_codec *codec) | ||
14106 | { | ||
14107 | switch (codec->subsystem_id) { | ||
14108 | case 0x103c1586: | ||
14109 | return 1; | ||
14110 | } | ||
14111 | return 0; | ||
14112 | } | ||
14113 | |||
14114 | static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid) | ||
14115 | { | ||
14116 | /* update mute-LED according to the speaker mute state */ | ||
14117 | if (nid == 0x01 || nid == 0x14) { | ||
14118 | int pinval; | ||
14119 | if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) & | ||
14120 | HDA_AMP_MUTE) | ||
14121 | pinval = 0x24; | ||
14122 | else | ||
14123 | pinval = 0x20; | ||
14124 | /* mic2 vref pin is used for mute LED control */ | ||
14125 | snd_hda_codec_update_cache(codec, 0x19, 0, | ||
14126 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
14127 | pinval); | ||
14128 | } | ||
14129 | return alc_check_power_status(codec, nid); | ||
14130 | } | ||
14131 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
14132 | |||
13817 | /* | 14133 | /* |
13818 | * BIOS auto configuration | 14134 | * BIOS auto configuration |
13819 | */ | 14135 | */ |
@@ -13822,7 +14138,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
13822 | struct alc_spec *spec = codec->spec; | 14138 | struct alc_spec *spec = codec->spec; |
13823 | int err; | 14139 | int err; |
13824 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; | 14140 | static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; |
13825 | hda_nid_t real_capsrc_nids; | ||
13826 | 14141 | ||
13827 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 14142 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
13828 | alc269_ignore); | 14143 | alc269_ignore); |
@@ -13846,18 +14161,19 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
13846 | 14161 | ||
13847 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { | 14162 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { |
13848 | add_verb(spec, alc269vb_init_verbs); | 14163 | add_verb(spec, alc269vb_init_verbs); |
13849 | real_capsrc_nids = alc269vb_capsrc_nids[0]; | ||
13850 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); | 14164 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); |
13851 | } else { | 14165 | } else { |
13852 | add_verb(spec, alc269_init_verbs); | 14166 | add_verb(spec, alc269_init_verbs); |
13853 | real_capsrc_nids = alc269_capsrc_nids[0]; | ||
13854 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); | 14167 | alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); |
13855 | } | 14168 | } |
13856 | 14169 | ||
13857 | spec->num_mux_defs = 1; | 14170 | spec->num_mux_defs = 1; |
13858 | spec->input_mux = &spec->private_imux[0]; | 14171 | spec->input_mux = &spec->private_imux[0]; |
14172 | fillup_priv_adc_nids(codec, alc269_adc_candidates, | ||
14173 | sizeof(alc269_adc_candidates)); | ||
14174 | |||
13859 | /* set default input source */ | 14175 | /* set default input source */ |
13860 | snd_hda_codec_write_cache(codec, real_capsrc_nids, | 14176 | snd_hda_codec_write_cache(codec, spec->capsrc_nids[0], |
13861 | 0, AC_VERB_SET_CONNECT_SEL, | 14177 | 0, AC_VERB_SET_CONNECT_SEL, |
13862 | spec->input_mux->items[0].index); | 14178 | spec->input_mux->items[0].index); |
13863 | 14179 | ||
@@ -13887,6 +14203,27 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
13887 | alc_inithook(codec); | 14203 | alc_inithook(codec); |
13888 | } | 14204 | } |
13889 | 14205 | ||
14206 | enum { | ||
14207 | ALC269_FIXUP_SONY_VAIO, | ||
14208 | }; | ||
14209 | |||
14210 | static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { | ||
14211 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
14212 | {} | ||
14213 | }; | ||
14214 | |||
14215 | static const struct alc_fixup alc269_fixups[] = { | ||
14216 | [ALC269_FIXUP_SONY_VAIO] = { | ||
14217 | .verbs = alc269_sony_vaio_fixup_verbs | ||
14218 | }, | ||
14219 | }; | ||
14220 | |||
14221 | static struct snd_pci_quirk alc269_fixup_tbl[] = { | ||
14222 | SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | ||
14223 | {} | ||
14224 | }; | ||
14225 | |||
14226 | |||
13890 | /* | 14227 | /* |
13891 | * configuration and preset | 14228 | * configuration and preset |
13892 | */ | 14229 | */ |
@@ -13946,7 +14283,7 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = { | |||
13946 | ALC269_DMIC), | 14283 | ALC269_DMIC), |
13947 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC), | 14284 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC), |
13948 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC), | 14285 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC), |
13949 | SND_PCI_QUIRK(0x104d, 0x9071, "SONY XTB", ALC269_DMIC), | 14286 | SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO), |
13950 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), | 14287 | SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), |
13951 | SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC), | 14288 | SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC), |
13952 | SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), | 14289 | SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), |
@@ -14020,7 +14357,7 @@ static struct alc_config_preset alc269_presets[] = { | |||
14020 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | 14357 | .num_channel_mode = ARRAY_SIZE(alc269_modes), |
14021 | .channel_mode = alc269_modes, | 14358 | .channel_mode = alc269_modes, |
14022 | .unsol_event = alc269_laptop_unsol_event, | 14359 | .unsol_event = alc269_laptop_unsol_event, |
14023 | .setup = alc269_laptop_amic_setup, | 14360 | .setup = alc269vb_laptop_amic_setup, |
14024 | .init_hook = alc269_laptop_inithook, | 14361 | .init_hook = alc269_laptop_inithook, |
14025 | }, | 14362 | }, |
14026 | [ALC269VB_DMIC] = { | 14363 | [ALC269VB_DMIC] = { |
@@ -14078,17 +14415,17 @@ static int patch_alc269(struct hda_codec *codec) | |||
14078 | 14415 | ||
14079 | codec->spec = spec; | 14416 | codec->spec = spec; |
14080 | 14417 | ||
14081 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 14418 | alc_auto_parse_customize_define(codec); |
14082 | 14419 | ||
14083 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ | 14420 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ |
14084 | kfree(codec->chip_name); | 14421 | if (codec->bus->pci->subsystem_vendor == 0x1025 && |
14085 | codec->chip_name = kstrdup("ALC259", GFP_KERNEL); | 14422 | spec->cdefine.platform_type == 1) |
14086 | if (!codec->chip_name) { | 14423 | alc_codec_rename(codec, "ALC271X"); |
14087 | alc_free(codec); | 14424 | else |
14088 | return -ENOMEM; | 14425 | alc_codec_rename(codec, "ALC259"); |
14089 | } | ||
14090 | is_alc269vb = 1; | 14426 | is_alc269vb = 1; |
14091 | } | 14427 | } else |
14428 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | ||
14092 | 14429 | ||
14093 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, | 14430 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, |
14094 | alc269_models, | 14431 | alc269_models, |
@@ -14100,6 +14437,9 @@ static int patch_alc269(struct hda_codec *codec) | |||
14100 | board_config = ALC269_AUTO; | 14437 | board_config = ALC269_AUTO; |
14101 | } | 14438 | } |
14102 | 14439 | ||
14440 | if (board_config == ALC269_AUTO) | ||
14441 | alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 1); | ||
14442 | |||
14103 | if (board_config == ALC269_AUTO) { | 14443 | if (board_config == ALC269_AUTO) { |
14104 | /* automatic parse from the BIOS config */ | 14444 | /* automatic parse from the BIOS config */ |
14105 | err = alc269_parse_auto_config(codec); | 14445 | err = alc269_parse_auto_config(codec); |
@@ -14136,19 +14476,25 @@ static int patch_alc269(struct hda_codec *codec) | |||
14136 | spec->stream_digital_playback = &alc269_pcm_digital_playback; | 14476 | spec->stream_digital_playback = &alc269_pcm_digital_playback; |
14137 | spec->stream_digital_capture = &alc269_pcm_digital_capture; | 14477 | spec->stream_digital_capture = &alc269_pcm_digital_capture; |
14138 | 14478 | ||
14139 | if (!is_alc269vb) { | 14479 | if (!spec->adc_nids) { /* wasn't filled automatically? use default */ |
14140 | spec->adc_nids = alc269_adc_nids; | 14480 | if (!is_alc269vb) { |
14141 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 14481 | spec->adc_nids = alc269_adc_nids; |
14142 | spec->capsrc_nids = alc269_capsrc_nids; | 14482 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
14143 | } else { | 14483 | spec->capsrc_nids = alc269_capsrc_nids; |
14144 | spec->adc_nids = alc269vb_adc_nids; | 14484 | } else { |
14145 | spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids); | 14485 | spec->adc_nids = alc269vb_adc_nids; |
14146 | spec->capsrc_nids = alc269vb_capsrc_nids; | 14486 | spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids); |
14487 | spec->capsrc_nids = alc269vb_capsrc_nids; | ||
14488 | } | ||
14147 | } | 14489 | } |
14148 | 14490 | ||
14149 | if (!spec->cap_mixer) | 14491 | if (!spec->cap_mixer) |
14150 | set_capture_mixer(codec); | 14492 | set_capture_mixer(codec); |
14151 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 14493 | if (spec->cdefine.enable_pcbeep) |
14494 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | ||
14495 | |||
14496 | if (board_config == ALC269_AUTO) | ||
14497 | alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0); | ||
14152 | 14498 | ||
14153 | spec->vmaster_nid = 0x02; | 14499 | spec->vmaster_nid = 0x02; |
14154 | 14500 | ||
@@ -14158,6 +14504,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
14158 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 14504 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
14159 | if (!spec->loopback.amplist) | 14505 | if (!spec->loopback.amplist) |
14160 | spec->loopback.amplist = alc269_loopbacks; | 14506 | spec->loopback.amplist = alc269_loopbacks; |
14507 | if (alc269_mic2_for_mute_led(codec)) | ||
14508 | codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps; | ||
14161 | #endif | 14509 | #endif |
14162 | 14510 | ||
14163 | return 0; | 14511 | return 0; |
@@ -15238,7 +15586,8 @@ static int patch_alc861(struct hda_codec *codec) | |||
15238 | board_config = ALC861_AUTO; | 15586 | board_config = ALC861_AUTO; |
15239 | } | 15587 | } |
15240 | 15588 | ||
15241 | alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups); | 15589 | if (board_config == ALC861_AUTO) |
15590 | alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 1); | ||
15242 | 15591 | ||
15243 | if (board_config == ALC861_AUTO) { | 15592 | if (board_config == ALC861_AUTO) { |
15244 | /* automatic parse from the BIOS config */ | 15593 | /* automatic parse from the BIOS config */ |
@@ -15275,6 +15624,9 @@ static int patch_alc861(struct hda_codec *codec) | |||
15275 | 15624 | ||
15276 | spec->vmaster_nid = 0x03; | 15625 | spec->vmaster_nid = 0x03; |
15277 | 15626 | ||
15627 | if (board_config == ALC861_AUTO) | ||
15628 | alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 0); | ||
15629 | |||
15278 | codec->patch_ops = alc_patch_ops; | 15630 | codec->patch_ops = alc_patch_ops; |
15279 | if (board_config == ALC861_AUTO) { | 15631 | if (board_config == ALC861_AUTO) { |
15280 | spec->init_hook = alc861_auto_init; | 15632 | spec->init_hook = alc861_auto_init; |
@@ -16209,7 +16561,8 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
16209 | board_config = ALC861VD_AUTO; | 16561 | board_config = ALC861VD_AUTO; |
16210 | } | 16562 | } |
16211 | 16563 | ||
16212 | alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups); | 16564 | if (board_config == ALC861VD_AUTO) |
16565 | alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 1); | ||
16213 | 16566 | ||
16214 | if (board_config == ALC861VD_AUTO) { | 16567 | if (board_config == ALC861VD_AUTO) { |
16215 | /* automatic parse from the BIOS config */ | 16568 | /* automatic parse from the BIOS config */ |
@@ -16257,6 +16610,9 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
16257 | 16610 | ||
16258 | spec->vmaster_nid = 0x02; | 16611 | spec->vmaster_nid = 0x02; |
16259 | 16612 | ||
16613 | if (board_config == ALC861VD_AUTO) | ||
16614 | alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 0); | ||
16615 | |||
16260 | codec->patch_ops = alc_patch_ops; | 16616 | codec->patch_ops = alc_patch_ops; |
16261 | 16617 | ||
16262 | if (board_config == ALC861VD_AUTO) | 16618 | if (board_config == ALC861VD_AUTO) |
@@ -17095,9 +17451,9 @@ static void alc663_m51va_speaker_automute(struct hda_codec *codec) | |||
17095 | present = snd_hda_jack_detect(codec, 0x21); | 17451 | present = snd_hda_jack_detect(codec, 0x21); |
17096 | bits = present ? HDA_AMP_MUTE : 0; | 17452 | bits = present ? HDA_AMP_MUTE : 0; |
17097 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | 17453 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, |
17098 | AMP_IN_MUTE(0), bits); | 17454 | HDA_AMP_MUTE, bits); |
17099 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 17455 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
17100 | AMP_IN_MUTE(0), bits); | 17456 | HDA_AMP_MUTE, bits); |
17101 | } | 17457 | } |
17102 | 17458 | ||
17103 | static void alc663_21jd_two_speaker_automute(struct hda_codec *codec) | 17459 | static void alc663_21jd_two_speaker_automute(struct hda_codec *codec) |
@@ -17108,13 +17464,13 @@ static void alc663_21jd_two_speaker_automute(struct hda_codec *codec) | |||
17108 | present = snd_hda_jack_detect(codec, 0x21); | 17464 | present = snd_hda_jack_detect(codec, 0x21); |
17109 | bits = present ? HDA_AMP_MUTE : 0; | 17465 | bits = present ? HDA_AMP_MUTE : 0; |
17110 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | 17466 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, |
17111 | AMP_IN_MUTE(0), bits); | 17467 | HDA_AMP_MUTE, bits); |
17112 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 17468 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
17113 | AMP_IN_MUTE(0), bits); | 17469 | HDA_AMP_MUTE, bits); |
17114 | snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0, | 17470 | snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0, |
17115 | AMP_IN_MUTE(0), bits); | 17471 | HDA_AMP_MUTE, bits); |
17116 | snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1, | 17472 | snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1, |
17117 | AMP_IN_MUTE(0), bits); | 17473 | HDA_AMP_MUTE, bits); |
17118 | } | 17474 | } |
17119 | 17475 | ||
17120 | static void alc663_15jd_two_speaker_automute(struct hda_codec *codec) | 17476 | static void alc663_15jd_two_speaker_automute(struct hda_codec *codec) |
@@ -17125,13 +17481,13 @@ static void alc663_15jd_two_speaker_automute(struct hda_codec *codec) | |||
17125 | present = snd_hda_jack_detect(codec, 0x15); | 17481 | present = snd_hda_jack_detect(codec, 0x15); |
17126 | bits = present ? HDA_AMP_MUTE : 0; | 17482 | bits = present ? HDA_AMP_MUTE : 0; |
17127 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | 17483 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, |
17128 | AMP_IN_MUTE(0), bits); | 17484 | HDA_AMP_MUTE, bits); |
17129 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 17485 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
17130 | AMP_IN_MUTE(0), bits); | 17486 | HDA_AMP_MUTE, bits); |
17131 | snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0, | 17487 | snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0, |
17132 | AMP_IN_MUTE(0), bits); | 17488 | HDA_AMP_MUTE, bits); |
17133 | snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1, | 17489 | snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1, |
17134 | AMP_IN_MUTE(0), bits); | 17490 | HDA_AMP_MUTE, bits); |
17135 | } | 17491 | } |
17136 | 17492 | ||
17137 | static void alc662_f5z_speaker_automute(struct hda_codec *codec) | 17493 | static void alc662_f5z_speaker_automute(struct hda_codec *codec) |
@@ -17170,14 +17526,14 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec) | |||
17170 | 17526 | ||
17171 | if (present1 || present2) { | 17527 | if (present1 || present2) { |
17172 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | 17528 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, |
17173 | AMP_IN_MUTE(0), AMP_IN_MUTE(0)); | 17529 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
17174 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 17530 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
17175 | AMP_IN_MUTE(0), AMP_IN_MUTE(0)); | 17531 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
17176 | } else { | 17532 | } else { |
17177 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | 17533 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, |
17178 | AMP_IN_MUTE(0), 0); | 17534 | HDA_AMP_MUTE, 0); |
17179 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 17535 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
17180 | AMP_IN_MUTE(0), 0); | 17536 | HDA_AMP_MUTE, 0); |
17181 | } | 17537 | } |
17182 | } | 17538 | } |
17183 | 17539 | ||
@@ -17643,7 +17999,6 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { | |||
17643 | ALC662_3ST_6ch_DIG), | 17999 | ALC662_3ST_6ch_DIG), |
17644 | SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x", | 18000 | SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x", |
17645 | ALC663_ASUS_H13), | 18001 | ALC663_ASUS_H13), |
17646 | SND_PCI_QUIRK(0x8086, 0xd604, "Intel mobo", ALC662_3ST_2ch_DIG), | ||
17647 | {} | 18002 | {} |
17648 | }; | 18003 | }; |
17649 | 18004 | ||
@@ -18298,16 +18653,16 @@ static int patch_alc662(struct hda_codec *codec) | |||
18298 | 18653 | ||
18299 | codec->spec = spec; | 18654 | codec->spec = spec; |
18300 | 18655 | ||
18656 | alc_auto_parse_customize_define(codec); | ||
18657 | |||
18301 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 18658 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
18302 | 18659 | ||
18303 | if (alc_read_coef_idx(codec, 0)==0x8020){ | 18660 | if (alc_read_coef_idx(codec, 0) == 0x8020) |
18304 | kfree(codec->chip_name); | 18661 | alc_codec_rename(codec, "ALC661"); |
18305 | codec->chip_name = kstrdup("ALC661", GFP_KERNEL); | 18662 | else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) && |
18306 | if (!codec->chip_name) { | 18663 | codec->bus->pci->subsystem_vendor == 0x1025 && |
18307 | alc_free(codec); | 18664 | spec->cdefine.platform_type == 1) |
18308 | return -ENOMEM; | 18665 | alc_codec_rename(codec, "ALC272X"); |
18309 | } | ||
18310 | } | ||
18311 | 18666 | ||
18312 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, | 18667 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, |
18313 | alc662_models, | 18668 | alc662_models, |
@@ -18357,18 +18712,20 @@ static int patch_alc662(struct hda_codec *codec) | |||
18357 | if (!spec->cap_mixer) | 18712 | if (!spec->cap_mixer) |
18358 | set_capture_mixer(codec); | 18713 | set_capture_mixer(codec); |
18359 | 18714 | ||
18360 | switch (codec->vendor_id) { | 18715 | if (spec->cdefine.enable_pcbeep) { |
18361 | case 0x10ec0662: | 18716 | switch (codec->vendor_id) { |
18362 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 18717 | case 0x10ec0662: |
18363 | break; | 18718 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
18364 | case 0x10ec0272: | 18719 | break; |
18365 | case 0x10ec0663: | 18720 | case 0x10ec0272: |
18366 | case 0x10ec0665: | 18721 | case 0x10ec0663: |
18367 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 18722 | case 0x10ec0665: |
18368 | break; | 18723 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
18369 | case 0x10ec0273: | 18724 | break; |
18370 | set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); | 18725 | case 0x10ec0273: |
18371 | break; | 18726 | set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); |
18727 | break; | ||
18728 | } | ||
18372 | } | 18729 | } |
18373 | spec->vmaster_nid = 0x02; | 18730 | spec->vmaster_nid = 0x02; |
18374 | 18731 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 8c416bb18a57..a0e06d82da1f 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -104,6 +104,7 @@ enum { | |||
104 | STAC_DELL_M4_2, | 104 | STAC_DELL_M4_2, |
105 | STAC_DELL_M4_3, | 105 | STAC_DELL_M4_3, |
106 | STAC_HP_M4, | 106 | STAC_HP_M4, |
107 | STAC_HP_DV4, | ||
107 | STAC_HP_DV5, | 108 | STAC_HP_DV5, |
108 | STAC_HP_HDX, | 109 | STAC_HP_HDX, |
109 | STAC_HP_DV4_1222NR, | 110 | STAC_HP_DV4_1222NR, |
@@ -1544,11 +1545,9 @@ static unsigned int alienware_m17x_pin_configs[13] = { | |||
1544 | 0x904601b0, | 1545 | 0x904601b0, |
1545 | }; | 1546 | }; |
1546 | 1547 | ||
1547 | static unsigned int intel_dg45id_pin_configs[14] = { | 1548 | static unsigned int intel_dg45id_pin_configs[13] = { |
1548 | 0x02214230, 0x02A19240, 0x01013214, 0x01014210, | 1549 | 0x02214230, 0x02A19240, 0x01013214, 0x01014210, |
1549 | 0x01A19250, 0x01011212, 0x01016211, 0x40f000f0, | 1550 | 0x01A19250, 0x01011212, 0x01016211 |
1550 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0, | ||
1551 | 0x074510B0, 0x40f000f0 | ||
1552 | }; | 1551 | }; |
1553 | 1552 | ||
1554 | static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | 1553 | static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { |
@@ -1607,6 +1606,10 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | |||
1607 | "Dell Studio 1555", STAC_DELL_M6_DMIC), | 1606 | "Dell Studio 1555", STAC_DELL_M6_DMIC), |
1608 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd, | 1607 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd, |
1609 | "Dell Studio 1557", STAC_DELL_M6_DMIC), | 1608 | "Dell Studio 1557", STAC_DELL_M6_DMIC), |
1609 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe, | ||
1610 | "Dell Studio XPS 1645", STAC_DELL_M6_BOTH), | ||
1611 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413, | ||
1612 | "Dell Studio 1558", STAC_DELL_M6_BOTH), | ||
1610 | {} /* terminator */ | 1613 | {} /* terminator */ |
1611 | }; | 1614 | }; |
1612 | 1615 | ||
@@ -1689,6 +1692,7 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { | |||
1689 | [STAC_DELL_M4_2] = dell_m4_2_pin_configs, | 1692 | [STAC_DELL_M4_2] = dell_m4_2_pin_configs, |
1690 | [STAC_DELL_M4_3] = dell_m4_3_pin_configs, | 1693 | [STAC_DELL_M4_3] = dell_m4_3_pin_configs, |
1691 | [STAC_HP_M4] = NULL, | 1694 | [STAC_HP_M4] = NULL, |
1695 | [STAC_HP_DV4] = NULL, | ||
1692 | [STAC_HP_DV5] = NULL, | 1696 | [STAC_HP_DV5] = NULL, |
1693 | [STAC_HP_HDX] = NULL, | 1697 | [STAC_HP_HDX] = NULL, |
1694 | [STAC_HP_DV4_1222NR] = NULL, | 1698 | [STAC_HP_DV4_1222NR] = NULL, |
@@ -1701,6 +1705,7 @@ static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { | |||
1701 | [STAC_DELL_M4_2] = "dell-m4-2", | 1705 | [STAC_DELL_M4_2] = "dell-m4-2", |
1702 | [STAC_DELL_M4_3] = "dell-m4-3", | 1706 | [STAC_DELL_M4_3] = "dell-m4-3", |
1703 | [STAC_HP_M4] = "hp-m4", | 1707 | [STAC_HP_M4] = "hp-m4", |
1708 | [STAC_HP_DV4] = "hp-dv4", | ||
1704 | [STAC_HP_DV5] = "hp-dv5", | 1709 | [STAC_HP_DV5] = "hp-dv5", |
1705 | [STAC_HP_HDX] = "hp-hdx", | 1710 | [STAC_HP_HDX] = "hp-hdx", |
1706 | [STAC_HP_DV4_1222NR] = "hp-dv4-1222nr", | 1711 | [STAC_HP_DV4_1222NR] = "hp-dv4-1222nr", |
@@ -1719,7 +1724,7 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { | |||
1719 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, | 1724 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, |
1720 | "HP", STAC_HP_DV5), | 1725 | "HP", STAC_HP_DV5), |
1721 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, | 1726 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, |
1722 | "HP dv4-7", STAC_HP_DV5), | 1727 | "HP dv4-7", STAC_HP_DV4), |
1723 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, | 1728 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, |
1724 | "HP dv4-7", STAC_HP_DV5), | 1729 | "HP dv4-7", STAC_HP_DV5), |
1725 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, | 1730 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, |
@@ -1730,6 +1735,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { | |||
1730 | "HP HDX", STAC_HP_HDX), /* HDX16 */ | 1735 | "HP HDX", STAC_HP_HDX), /* HDX16 */ |
1731 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620, | 1736 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620, |
1732 | "HP dv6", STAC_HP_DV5), | 1737 | "HP dv6", STAC_HP_DV5), |
1738 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061, | ||
1739 | "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */ | ||
1733 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, | 1740 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, |
1734 | "HP", STAC_HP_DV5), | 1741 | "HP", STAC_HP_DV5), |
1735 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, | 1742 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, |
@@ -4762,6 +4769,9 @@ static void set_hp_led_gpio(struct hda_codec *codec) | |||
4762 | struct sigmatel_spec *spec = codec->spec; | 4769 | struct sigmatel_spec *spec = codec->spec; |
4763 | unsigned int gpio; | 4770 | unsigned int gpio; |
4764 | 4771 | ||
4772 | if (spec->gpio_led) | ||
4773 | return; | ||
4774 | |||
4765 | gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); | 4775 | gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); |
4766 | gpio &= AC_GPIO_IO_COUNT; | 4776 | gpio &= AC_GPIO_IO_COUNT; |
4767 | if (gpio > 3) | 4777 | if (gpio > 3) |
@@ -5671,6 +5681,9 @@ again: | |||
5671 | spec->num_smuxes = 1; | 5681 | spec->num_smuxes = 1; |
5672 | spec->num_dmuxes = 1; | 5682 | spec->num_dmuxes = 1; |
5673 | /* fallthrough */ | 5683 | /* fallthrough */ |
5684 | case STAC_HP_DV4: | ||
5685 | spec->gpio_led = 0x01; | ||
5686 | /* fallthrough */ | ||
5674 | case STAC_HP_DV5: | 5687 | case STAC_HP_DV5: |
5675 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); | 5688 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); |
5676 | stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); | 5689 | stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); |
@@ -5684,6 +5697,7 @@ again: | |||
5684 | spec->num_dmics = 1; | 5697 | spec->num_dmics = 1; |
5685 | spec->num_dmuxes = 1; | 5698 | spec->num_dmuxes = 1; |
5686 | spec->num_smuxes = 1; | 5699 | spec->num_smuxes = 1; |
5700 | spec->gpio_led = 0x08; | ||
5687 | break; | 5701 | break; |
5688 | } | 5702 | } |
5689 | 5703 | ||
@@ -5740,7 +5754,8 @@ again: | |||
5740 | } | 5754 | } |
5741 | 5755 | ||
5742 | /* enable bass on HP dv7 */ | 5756 | /* enable bass on HP dv7 */ |
5743 | if (spec->board_config == STAC_HP_DV5) { | 5757 | if (spec->board_config == STAC_HP_DV4 || |
5758 | spec->board_config == STAC_HP_DV5) { | ||
5744 | unsigned int cap; | 5759 | unsigned int cap; |
5745 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); | 5760 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); |
5746 | cap &= AC_GPIO_IO_COUNT; | 5761 | cap &= AC_GPIO_IO_COUNT; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 9ddc37300f6b..73453814e098 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -476,7 +476,7 @@ static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, | |||
476 | knew->name = kstrdup(tmpl->name, GFP_KERNEL); | 476 | knew->name = kstrdup(tmpl->name, GFP_KERNEL); |
477 | if (!knew->name) | 477 | if (!knew->name) |
478 | return NULL; | 478 | return NULL; |
479 | return 0; | 479 | return knew; |
480 | } | 480 | } |
481 | 481 | ||
482 | static void via_free_kctls(struct hda_codec *codec) | 482 | static void via_free_kctls(struct hda_codec *codec) |
@@ -1215,14 +1215,13 @@ static struct snd_kcontrol_new via_hp_mixer[2] = { | |||
1215 | }, | 1215 | }, |
1216 | }; | 1216 | }; |
1217 | 1217 | ||
1218 | static int via_hp_build(struct via_spec *spec) | 1218 | static int via_hp_build(struct hda_codec *codec) |
1219 | { | 1219 | { |
1220 | struct via_spec *spec = codec->spec; | ||
1220 | struct snd_kcontrol_new *knew; | 1221 | struct snd_kcontrol_new *knew; |
1221 | hda_nid_t nid; | 1222 | hda_nid_t nid; |
1222 | 1223 | int nums; | |
1223 | knew = via_clone_control(spec, &via_hp_mixer[0]); | 1224 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; |
1224 | if (knew == NULL) | ||
1225 | return -ENOMEM; | ||
1226 | 1225 | ||
1227 | switch (spec->codec_type) { | 1226 | switch (spec->codec_type) { |
1228 | case VT1718S: | 1227 | case VT1718S: |
@@ -1239,6 +1238,14 @@ static int via_hp_build(struct via_spec *spec) | |||
1239 | break; | 1238 | break; |
1240 | } | 1239 | } |
1241 | 1240 | ||
1241 | nums = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS); | ||
1242 | if (nums <= 1) | ||
1243 | return 0; | ||
1244 | |||
1245 | knew = via_clone_control(spec, &via_hp_mixer[0]); | ||
1246 | if (knew == NULL) | ||
1247 | return -ENOMEM; | ||
1248 | |||
1242 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; | 1249 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; |
1243 | knew->private_value = nid; | 1250 | knew->private_value = nid; |
1244 | 1251 | ||
@@ -2561,7 +2568,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
2561 | spec->input_mux = &spec->private_imux[0]; | 2568 | spec->input_mux = &spec->private_imux[0]; |
2562 | 2569 | ||
2563 | if (spec->hp_mux) | 2570 | if (spec->hp_mux) |
2564 | via_hp_build(spec); | 2571 | via_hp_build(codec); |
2565 | 2572 | ||
2566 | via_smart51_build(spec); | 2573 | via_smart51_build(spec); |
2567 | return 1; | 2574 | return 1; |
@@ -3087,7 +3094,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
3087 | spec->input_mux = &spec->private_imux[0]; | 3094 | spec->input_mux = &spec->private_imux[0]; |
3088 | 3095 | ||
3089 | if (spec->hp_mux) | 3096 | if (spec->hp_mux) |
3090 | via_hp_build(spec); | 3097 | via_hp_build(codec); |
3091 | 3098 | ||
3092 | via_smart51_build(spec); | 3099 | via_smart51_build(spec); |
3093 | return 1; | 3100 | return 1; |
@@ -3654,7 +3661,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
3654 | spec->input_mux = &spec->private_imux[0]; | 3661 | spec->input_mux = &spec->private_imux[0]; |
3655 | 3662 | ||
3656 | if (spec->hp_mux) | 3663 | if (spec->hp_mux) |
3657 | via_hp_build(spec); | 3664 | via_hp_build(codec); |
3658 | 3665 | ||
3659 | via_smart51_build(spec); | 3666 | via_smart51_build(spec); |
3660 | return 1; | 3667 | return 1; |
@@ -4140,7 +4147,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
4140 | spec->input_mux = &spec->private_imux[0]; | 4147 | spec->input_mux = &spec->private_imux[0]; |
4141 | 4148 | ||
4142 | if (spec->hp_mux) | 4149 | if (spec->hp_mux) |
4143 | via_hp_build(spec); | 4150 | via_hp_build(codec); |
4144 | 4151 | ||
4145 | via_smart51_build(spec); | 4152 | via_smart51_build(spec); |
4146 | return 1; | 4153 | return 1; |
@@ -4510,7 +4517,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
4510 | spec->input_mux = &spec->private_imux[0]; | 4517 | spec->input_mux = &spec->private_imux[0]; |
4511 | 4518 | ||
4512 | if (spec->hp_mux) | 4519 | if (spec->hp_mux) |
4513 | via_hp_build(spec); | 4520 | via_hp_build(codec); |
4514 | 4521 | ||
4515 | return 1; | 4522 | return 1; |
4516 | } | 4523 | } |
@@ -4930,7 +4937,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec) | |||
4930 | spec->input_mux = &spec->private_imux[0]; | 4937 | spec->input_mux = &spec->private_imux[0]; |
4931 | 4938 | ||
4932 | if (spec->hp_mux) | 4939 | if (spec->hp_mux) |
4933 | via_hp_build(spec); | 4940 | via_hp_build(codec); |
4934 | 4941 | ||
4935 | via_smart51_build(spec); | 4942 | via_smart51_build(spec); |
4936 | 4943 | ||
@@ -5425,7 +5432,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec) | |||
5425 | spec->input_mux = &spec->private_imux[0]; | 5432 | spec->input_mux = &spec->private_imux[0]; |
5426 | 5433 | ||
5427 | if (spec->hp_mux) | 5434 | if (spec->hp_mux) |
5428 | via_hp_build(spec); | 5435 | via_hp_build(codec); |
5429 | 5436 | ||
5430 | via_smart51_build(spec); | 5437 | via_smart51_build(spec); |
5431 | 5438 | ||
@@ -5781,7 +5788,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec) | |||
5781 | spec->input_mux = &spec->private_imux[0]; | 5788 | spec->input_mux = &spec->private_imux[0]; |
5782 | 5789 | ||
5783 | if (spec->hp_mux) | 5790 | if (spec->hp_mux) |
5784 | via_hp_build(spec); | 5791 | via_hp_build(codec); |
5785 | 5792 | ||
5786 | return 1; | 5793 | return 1; |
5787 | } | 5794 | } |
@@ -6000,12 +6007,12 @@ static int vt1812_auto_create_multi_out_ctls(struct via_spec *spec, | |||
6000 | 6007 | ||
6001 | /* Line-Out: PortE */ | 6008 | /* Line-Out: PortE */ |
6002 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | 6009 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, |
6003 | "Master Front Playback Volume", | 6010 | "Front Playback Volume", |
6004 | HDA_COMPOSE_AMP_VAL(0x8, 3, 0, HDA_OUTPUT)); | 6011 | HDA_COMPOSE_AMP_VAL(0x8, 3, 0, HDA_OUTPUT)); |
6005 | if (err < 0) | 6012 | if (err < 0) |
6006 | return err; | 6013 | return err; |
6007 | err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE, | 6014 | err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE, |
6008 | "Master Front Playback Switch", | 6015 | "Front Playback Switch", |
6009 | HDA_COMPOSE_AMP_VAL(0x28, 3, 0, HDA_OUTPUT)); | 6016 | HDA_COMPOSE_AMP_VAL(0x28, 3, 0, HDA_OUTPUT)); |
6010 | if (err < 0) | 6017 | if (err < 0) |
6011 | return err; | 6018 | return err; |
@@ -6130,7 +6137,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec) | |||
6130 | spec->input_mux = &spec->private_imux[0]; | 6137 | spec->input_mux = &spec->private_imux[0]; |
6131 | 6138 | ||
6132 | if (spec->hp_mux) | 6139 | if (spec->hp_mux) |
6133 | via_hp_build(spec); | 6140 | via_hp_build(codec); |
6134 | 6141 | ||
6135 | return 1; | 6142 | return 1; |
6136 | } | 6143 | } |