diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-05-20 05:59:52 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-05-20 05:59:52 -0400 |
commit | 19008bdacb9f7841166ebafe0aef361ee582ffbf (patch) | |
tree | 8fddf106217c83fae4bf84e90f8b5cdf90d12068 /sound/pci/hda | |
parent | 9ce3db4e7949a394bad0de91883b5e786c17607a (diff) | |
parent | fbc256692eac29e04cf87e45736d7ff149180a52 (diff) |
Merge branch 'topic/hda' into for-linus
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/Kconfig | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 76 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 109 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 21 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 157 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 10 | ||||
-rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 21 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 238 |
9 files changed, 499 insertions, 137 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 567348b05b5a..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 |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0e76ac2b2ace..a3d638c8c1fd 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1209,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache) | |||
1209 | } | 1209 | } |
1210 | 1210 | ||
1211 | /* query the hash. allocate an entry if not found. */ | 1211 | /* query the hash. allocate an entry if not found. */ |
1212 | 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) |
1213 | u32 key) | ||
1214 | { | 1213 | { |
1215 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); | 1214 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
1216 | u16 cur = cache->hash[idx]; | 1215 | u16 cur = cache->hash[idx]; |
@@ -1222,17 +1221,27 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, | |||
1222 | return info; | 1221 | return info; |
1223 | cur = info->next; | 1222 | cur = info->next; |
1224 | } | 1223 | } |
1224 | return NULL; | ||
1225 | } | ||
1225 | 1226 | ||
1226 | /* add a new hash entry */ | 1227 | /* query the hash. allocate an entry if not found. */ |
1227 | info = snd_array_new(&cache->buf); | 1228 | static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, |
1228 | if (!info) | 1229 | u32 key) |
1229 | return NULL; | 1230 | { |
1230 | cur = snd_array_index(&cache->buf, info); | 1231 | struct hda_cache_head *info = get_hash(cache, key); |
1231 | info->key = key; | 1232 | if (!info) { |
1232 | info->val = 0; | 1233 | u16 idx, cur; |
1233 | info->next = cache->hash[idx]; | 1234 | /* add a new hash entry */ |
1234 | cache->hash[idx] = cur; | 1235 | info = snd_array_new(&cache->buf); |
1235 | 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 | } | ||
1236 | return info; | 1245 | return info; |
1237 | } | 1246 | } |
1238 | 1247 | ||
@@ -1461,6 +1470,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
1461 | 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)); |
1462 | if (!info) | 1471 | if (!info) |
1463 | return 0; | 1472 | return 0; |
1473 | if (snd_BUG_ON(mask & ~0xff)) | ||
1474 | mask &= 0xff; | ||
1464 | val &= mask; | 1475 | val &= mask; |
1465 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; | 1476 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; |
1466 | if (info->vol[ch] == val) | 1477 | if (info->vol[ch] == val) |
@@ -1486,6 +1497,9 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | |||
1486 | int direction, int idx, int mask, int val) | 1497 | int direction, int idx, int mask, int val) |
1487 | { | 1498 | { |
1488 | int ch, ret = 0; | 1499 | int ch, ret = 0; |
1500 | |||
1501 | if (snd_BUG_ON(mask & ~0xff)) | ||
1502 | mask &= 0xff; | ||
1489 | for (ch = 0; ch < 2; ch++) | 1503 | for (ch = 0; ch < 2; ch++) |
1490 | ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, | 1504 | ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, |
1491 | idx, mask, val); | 1505 | idx, mask, val); |
@@ -2717,6 +2731,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | |||
2717 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); | 2731 | EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); |
2718 | 2732 | ||
2719 | /** | 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 | /** | ||
2720 | * 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 |
2721 | * @codec: HD-audio codec | 2770 | * @codec: HD-audio codec |
2722 | * | 2771 | * |
@@ -4218,7 +4267,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4218 | break; | 4267 | break; |
4219 | case AC_JACK_MIC_IN: { | 4268 | case AC_JACK_MIC_IN: { |
4220 | int preferred, alt; | 4269 | int preferred, alt; |
4221 | if (loc == AC_JACK_LOC_FRONT) { | 4270 | if (loc == AC_JACK_LOC_FRONT || |
4271 | (loc & 0x30) == AC_JACK_LOC_INTERNAL) { | ||
4222 | preferred = AUTO_PIN_FRONT_MIC; | 4272 | preferred = AUTO_PIN_FRONT_MIC; |
4223 | alt = AUTO_PIN_MIC; | 4273 | alt = AUTO_PIN_MIC; |
4224 | } else { | 4274 | } else { |
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_intel.c b/sound/pci/hda/hda_intel.c index cec68152dcb1..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 |
@@ -340,8 +340,8 @@ struct azx_dev { | |||
340 | unsigned int period_bytes; /* size of the period in bytes */ | 340 | unsigned int period_bytes; /* size of the period in bytes */ |
341 | unsigned int frags; /* number for period in the play buffer */ | 341 | unsigned int frags; /* number for period in the play buffer */ |
342 | unsigned int fifo_size; /* FIFO size */ | 342 | unsigned int fifo_size; /* FIFO size */ |
343 | unsigned long start_jiffies; /* start + minimum jiffies */ | 343 | unsigned long start_wallclk; /* start + minimum wallclk */ |
344 | unsigned long min_jiffies; /* minimum jiffies before position is valid */ | 344 | unsigned long period_wallclk; /* wallclk for period */ |
345 | 345 | ||
346 | void __iomem *sd_addr; /* stream descriptor pointer */ | 346 | void __iomem *sd_addr; /* stream descriptor pointer */ |
347 | 347 | ||
@@ -361,7 +361,6 @@ struct azx_dev { | |||
361 | unsigned int opened :1; | 361 | unsigned int opened :1; |
362 | unsigned int running :1; | 362 | unsigned int running :1; |
363 | unsigned int irq_pending :1; | 363 | unsigned int irq_pending :1; |
364 | unsigned int start_flag: 1; /* stream full start flag */ | ||
365 | /* | 364 | /* |
366 | * For VIA: | 365 | * For VIA: |
367 | * A flag to ensure DMA position is 0 | 366 | * A flag to ensure DMA position is 0 |
@@ -425,7 +424,7 @@ struct azx { | |||
425 | struct snd_dma_buffer posbuf; | 424 | struct snd_dma_buffer posbuf; |
426 | 425 | ||
427 | /* flags */ | 426 | /* flags */ |
428 | int position_fix; | 427 | int position_fix[2]; /* for both playback/capture streams */ |
429 | int poll_count; | 428 | int poll_count; |
430 | unsigned int running :1; | 429 | unsigned int running :1; |
431 | unsigned int initialized :1; | 430 | unsigned int initialized :1; |
@@ -858,10 +857,13 @@ static void azx_power_notify(struct hda_bus *bus); | |||
858 | #endif | 857 | #endif |
859 | 858 | ||
860 | /* reset codec link */ | 859 | /* reset codec link */ |
861 | static int azx_reset(struct azx *chip) | 860 | static int azx_reset(struct azx *chip, int full_reset) |
862 | { | 861 | { |
863 | int count; | 862 | int count; |
864 | 863 | ||
864 | if (!full_reset) | ||
865 | goto __skip; | ||
866 | |||
865 | /* clear STATESTS */ | 867 | /* clear STATESTS */ |
866 | azx_writeb(chip, STATESTS, STATESTS_INT_MASK); | 868 | azx_writeb(chip, STATESTS, STATESTS_INT_MASK); |
867 | 869 | ||
@@ -887,6 +889,7 @@ static int azx_reset(struct azx *chip) | |||
887 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ | 889 | /* Brent Chartrand said to wait >= 540us for codecs to initialize */ |
888 | msleep(1); | 890 | msleep(1); |
889 | 891 | ||
892 | __skip: | ||
890 | /* check to see if controller is ready */ | 893 | /* check to see if controller is ready */ |
891 | if (!azx_readb(chip, GCTL)) { | 894 | if (!azx_readb(chip, GCTL)) { |
892 | snd_printd(SFX "azx_reset: controller not ready!\n"); | 895 | snd_printd(SFX "azx_reset: controller not ready!\n"); |
@@ -998,13 +1001,13 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | |||
998 | /* | 1001 | /* |
999 | * reset and start the controller registers | 1002 | * reset and start the controller registers |
1000 | */ | 1003 | */ |
1001 | static void azx_init_chip(struct azx *chip) | 1004 | static void azx_init_chip(struct azx *chip, int full_reset) |
1002 | { | 1005 | { |
1003 | if (chip->initialized) | 1006 | if (chip->initialized) |
1004 | return; | 1007 | return; |
1005 | 1008 | ||
1006 | /* reset controller */ | 1009 | /* reset controller */ |
1007 | azx_reset(chip); | 1010 | azx_reset(chip, full_reset); |
1008 | 1011 | ||
1009 | /* initialize interrupts */ | 1012 | /* initialize interrupts */ |
1010 | azx_int_clear(chip); | 1013 | azx_int_clear(chip); |
@@ -1302,8 +1305,10 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1302 | 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)); |
1303 | 1306 | ||
1304 | /* enable the position buffer */ | 1307 | /* enable the position buffer */ |
1305 | if (chip->position_fix == POS_FIX_POSBUF || | 1308 | if (chip->position_fix[0] == POS_FIX_POSBUF || |
1306 | 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 || | ||
1307 | chip->via_dmapos_patch) { | 1312 | chip->via_dmapos_patch) { |
1308 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 1313 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
1309 | azx_writel(chip, DPLBASE, | 1314 | azx_writel(chip, DPLBASE, |
@@ -1348,7 +1353,7 @@ static void azx_bus_reset(struct hda_bus *bus) | |||
1348 | 1353 | ||
1349 | bus->in_reset = 1; | 1354 | bus->in_reset = 1; |
1350 | azx_stop_chip(chip); | 1355 | azx_stop_chip(chip); |
1351 | azx_init_chip(chip); | 1356 | azx_init_chip(chip, 1); |
1352 | #ifdef CONFIG_PM | 1357 | #ifdef CONFIG_PM |
1353 | if (chip->initialized) { | 1358 | if (chip->initialized) { |
1354 | int i; | 1359 | int i; |
@@ -1422,7 +1427,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
1422 | * get back to the sanity state. | 1427 | * get back to the sanity state. |
1423 | */ | 1428 | */ |
1424 | azx_stop_chip(chip); | 1429 | azx_stop_chip(chip); |
1425 | azx_init_chip(chip); | 1430 | azx_init_chip(chip, 1); |
1426 | } | 1431 | } |
1427 | } | 1432 | } |
1428 | } | 1433 | } |
@@ -1670,8 +1675,9 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1670 | return err; | 1675 | return err; |
1671 | } | 1676 | } |
1672 | 1677 | ||
1673 | azx_dev->min_jiffies = (runtime->period_size * HZ) / | 1678 | /* wallclk has 24Mhz clock source */ |
1674 | (runtime->rate * 2); | 1679 | azx_dev->period_wallclk = (((runtime->period_size * 24000) / |
1680 | runtime->rate) * 1000); | ||
1675 | azx_setup_controller(chip, azx_dev); | 1681 | azx_setup_controller(chip, azx_dev); |
1676 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1682 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1677 | 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; |
@@ -1725,14 +1731,15 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1725 | if (s->pcm->card != substream->pcm->card) | 1731 | if (s->pcm->card != substream->pcm->card) |
1726 | continue; | 1732 | continue; |
1727 | azx_dev = get_azx_dev(s); | 1733 | azx_dev = get_azx_dev(s); |
1728 | if (rstart) { | 1734 | if (start) { |
1729 | azx_dev->start_flag = 1; | 1735 | azx_dev->start_wallclk = azx_readl(chip, WALLCLK); |
1730 | azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies; | 1736 | if (!rstart) |
1731 | } | 1737 | azx_dev->start_wallclk -= |
1732 | if (start) | 1738 | azx_dev->period_wallclk; |
1733 | azx_stream_start(chip, azx_dev); | 1739 | azx_stream_start(chip, azx_dev); |
1734 | else | 1740 | } else { |
1735 | azx_stream_stop(chip, azx_dev); | 1741 | azx_stream_stop(chip, azx_dev); |
1742 | } | ||
1736 | azx_dev->running = start; | 1743 | azx_dev->running = start; |
1737 | } | 1744 | } |
1738 | spin_unlock(&chip->reg_lock); | 1745 | spin_unlock(&chip->reg_lock); |
@@ -1843,13 +1850,16 @@ static unsigned int azx_get_position(struct azx *chip, | |||
1843 | 1850 | ||
1844 | if (chip->via_dmapos_patch) | 1851 | if (chip->via_dmapos_patch) |
1845 | pos = azx_via_get_position(chip, azx_dev); | 1852 | pos = azx_via_get_position(chip, azx_dev); |
1846 | else if (chip->position_fix == POS_FIX_POSBUF || | 1853 | else { |
1847 | chip->position_fix == POS_FIX_AUTO) { | 1854 | int stream = azx_dev->substream->stream; |
1848 | /* use the position buffer */ | 1855 | if (chip->position_fix[stream] == POS_FIX_POSBUF || |
1849 | pos = le32_to_cpu(*azx_dev->posbuf); | 1856 | chip->position_fix[stream] == POS_FIX_AUTO) { |
1850 | } else { | 1857 | /* use the position buffer */ |
1851 | /* read LPIB */ | 1858 | pos = le32_to_cpu(*azx_dev->posbuf); |
1852 | pos = azx_sd_readl(azx_dev, SD_LPIB); | 1859 | } else { |
1860 | /* read LPIB */ | ||
1861 | pos = azx_sd_readl(azx_dev, SD_LPIB); | ||
1862 | } | ||
1853 | } | 1863 | } |
1854 | if (pos >= azx_dev->bufsize) | 1864 | if (pos >= azx_dev->bufsize) |
1855 | pos = 0; | 1865 | pos = 0; |
@@ -1876,32 +1886,35 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
1876 | */ | 1886 | */ |
1877 | 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) |
1878 | { | 1888 | { |
1889 | u32 wallclk; | ||
1879 | unsigned int pos; | 1890 | unsigned int pos; |
1891 | int stream; | ||
1880 | 1892 | ||
1881 | if (azx_dev->start_flag && | 1893 | wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk; |
1882 | time_before_eq(jiffies, azx_dev->start_jiffies)) | 1894 | if (wallclk < (azx_dev->period_wallclk * 2) / 3) |
1883 | return -1; /* bogus (too early) interrupt */ | 1895 | return -1; /* bogus (too early) interrupt */ |
1884 | azx_dev->start_flag = 0; | ||
1885 | 1896 | ||
1897 | stream = azx_dev->substream->stream; | ||
1886 | pos = azx_get_position(chip, azx_dev); | 1898 | pos = azx_get_position(chip, azx_dev); |
1887 | if (chip->position_fix == POS_FIX_AUTO) { | 1899 | if (chip->position_fix[stream] == POS_FIX_AUTO) { |
1888 | if (!pos) { | 1900 | if (!pos) { |
1889 | printk(KERN_WARNING | 1901 | printk(KERN_WARNING |
1890 | "hda-intel: Invalid position buffer, " | 1902 | "hda-intel: Invalid position buffer, " |
1891 | "using LPIB read method instead.\n"); | 1903 | "using LPIB read method instead.\n"); |
1892 | chip->position_fix = POS_FIX_LPIB; | 1904 | chip->position_fix[stream] = POS_FIX_LPIB; |
1893 | pos = azx_get_position(chip, azx_dev); | 1905 | pos = azx_get_position(chip, azx_dev); |
1894 | } else | 1906 | } else |
1895 | chip->position_fix = POS_FIX_POSBUF; | 1907 | chip->position_fix[stream] = POS_FIX_POSBUF; |
1896 | } | 1908 | } |
1897 | 1909 | ||
1898 | if (!bdl_pos_adj[chip->dev_index]) | ||
1899 | return 1; /* no delayed ack */ | ||
1900 | if (WARN_ONCE(!azx_dev->period_bytes, | 1910 | if (WARN_ONCE(!azx_dev->period_bytes, |
1901 | "hda-intel: zero azx_dev->period_bytes")) | 1911 | "hda-intel: zero azx_dev->period_bytes")) |
1902 | return 0; /* this shouldn't happen! */ | 1912 | return -1; /* this shouldn't happen! */ |
1903 | if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) | 1913 | if (wallclk <= azx_dev->period_wallclk && |
1904 | 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; | ||
1905 | return 1; /* OK, it's fine */ | 1918 | return 1; /* OK, it's fine */ |
1906 | } | 1919 | } |
1907 | 1920 | ||
@@ -1911,7 +1924,7 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) | |||
1911 | static void azx_irq_pending_work(struct work_struct *work) | 1924 | static void azx_irq_pending_work(struct work_struct *work) |
1912 | { | 1925 | { |
1913 | struct azx *chip = container_of(work, struct azx, irq_pending_work); | 1926 | struct azx *chip = container_of(work, struct azx, irq_pending_work); |
1914 | int i, pending; | 1927 | int i, pending, ok; |
1915 | 1928 | ||
1916 | if (!chip->irq_pending_warned) { | 1929 | if (!chip->irq_pending_warned) { |
1917 | printk(KERN_WARNING | 1930 | printk(KERN_WARNING |
@@ -1930,11 +1943,14 @@ static void azx_irq_pending_work(struct work_struct *work) | |||
1930 | !azx_dev->substream || | 1943 | !azx_dev->substream || |
1931 | !azx_dev->running) | 1944 | !azx_dev->running) |
1932 | continue; | 1945 | continue; |
1933 | if (azx_position_ok(chip, azx_dev)) { | 1946 | ok = azx_position_ok(chip, azx_dev); |
1947 | if (ok > 0) { | ||
1934 | azx_dev->irq_pending = 0; | 1948 | azx_dev->irq_pending = 0; |
1935 | spin_unlock(&chip->reg_lock); | 1949 | spin_unlock(&chip->reg_lock); |
1936 | snd_pcm_period_elapsed(azx_dev->substream); | 1950 | snd_pcm_period_elapsed(azx_dev->substream); |
1937 | spin_lock(&chip->reg_lock); | 1951 | spin_lock(&chip->reg_lock); |
1952 | } else if (ok < 0) { | ||
1953 | pending = 0; /* too early */ | ||
1938 | } else | 1954 | } else |
1939 | pending++; | 1955 | pending++; |
1940 | } | 1956 | } |
@@ -2112,7 +2128,7 @@ static void azx_power_notify(struct hda_bus *bus) | |||
2112 | } | 2128 | } |
2113 | } | 2129 | } |
2114 | if (power_on) | 2130 | if (power_on) |
2115 | azx_init_chip(chip); | 2131 | azx_init_chip(chip, 1); |
2116 | else if (chip->running && power_save_controller && | 2132 | else if (chip->running && power_save_controller && |
2117 | !bus->power_keep_link_on) | 2133 | !bus->power_keep_link_on) |
2118 | azx_stop_chip(chip); | 2134 | azx_stop_chip(chip); |
@@ -2182,7 +2198,7 @@ static int azx_resume(struct pci_dev *pci) | |||
2182 | azx_init_pci(chip); | 2198 | azx_init_pci(chip); |
2183 | 2199 | ||
2184 | if (snd_hda_codecs_inuse(chip->bus)) | 2200 | if (snd_hda_codecs_inuse(chip->bus)) |
2185 | azx_init_chip(chip); | 2201 | azx_init_chip(chip, 1); |
2186 | 2202 | ||
2187 | snd_hda_resume(chip->bus); | 2203 | snd_hda_resume(chip->bus); |
2188 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2204 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
@@ -2431,7 +2447,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2431 | chip->dev_index = dev; | 2447 | chip->dev_index = dev; |
2432 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); | 2448 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); |
2433 | 2449 | ||
2434 | 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]); | ||
2435 | check_probe_mask(chip, dev); | 2452 | check_probe_mask(chip, dev); |
2436 | 2453 | ||
2437 | chip->single_cmd = single_cmd; | 2454 | chip->single_cmd = single_cmd; |
@@ -2577,7 +2594,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
2577 | 2594 | ||
2578 | /* initialize chip */ | 2595 | /* initialize chip */ |
2579 | azx_init_pci(chip); | 2596 | azx_init_pci(chip); |
2580 | azx_init_chip(chip); | 2597 | azx_init_chip(chip, (probe_only[dev] & 2) == 0); |
2581 | 2598 | ||
2582 | /* codec detection */ | 2599 | /* codec detection */ |
2583 | if (!chip->codec_mask) { | 2600 | if (!chip->codec_mask) { |
@@ -2666,7 +2683,7 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
2666 | goto out_free; | 2683 | goto out_free; |
2667 | } | 2684 | } |
2668 | #endif | 2685 | #endif |
2669 | if (!probe_only[dev]) { | 2686 | if ((probe_only[dev] & 1) == 0) { |
2670 | err = azx_codec_configure(chip); | 2687 | err = azx_codec_configure(chip); |
2671 | if (err < 0) | 2688 | if (err < 0) |
2672 | goto out_free; | 2689 | goto out_free; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e9fdfc4b1c57..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) |
@@ -3481,6 +3489,8 @@ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { | |||
3481 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | 3489 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), |
3482 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), | 3490 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), |
3483 | 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), | ||
3484 | HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), | 3494 | HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), |
3485 | HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3495 | HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
3486 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3496 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), |
@@ -3522,6 +3532,8 @@ static struct hda_verb ad1984_thinkpad_init_verbs[] = { | |||
3522 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 3532 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
3523 | /* docking mic boost */ | 3533 | /* docking mic boost */ |
3524 | {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}, | ||
3525 | /* Analog mixer - docking mic; mute as default */ | 3537 | /* Analog mixer - docking mic; mute as default */ |
3526 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 3538 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3527 | /* enable EAPD bit */ | 3539 | /* enable EAPD bit */ |
@@ -3654,6 +3666,7 @@ static int patch_ad1984(struct hda_codec *codec) | |||
3654 | spec->input_mux = &ad1984_thinkpad_capture_source; | 3666 | spec->input_mux = &ad1984_thinkpad_capture_source; |
3655 | spec->mixers[0] = ad1984_thinkpad_mixers; | 3667 | spec->mixers[0] = ad1984_thinkpad_mixers; |
3656 | 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; | ||
3657 | break; | 3670 | break; |
3658 | case AD1984_DELL_DESKTOP: | 3671 | case AD1984_DELL_DESKTOP: |
3659 | spec->multiout.dig_out_nid = 0; | 3672 | spec->multiout.dig_out_nid = 0; |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index feabb44c7ca4..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; |
@@ -1784,6 +1785,7 @@ static struct hda_verb cxt5051_init_verbs[] = { | |||
1784 | {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}, |
1785 | {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}, |
1786 | /* SPDIF route: PCM */ | 1787 | /* SPDIF route: PCM */ |
1788 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1787 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | 1789 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, |
1788 | /* EAPD */ | 1790 | /* EAPD */ |
1789 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 1791 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
@@ -1840,6 +1842,7 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { | |||
1840 | {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}, |
1841 | {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}, |
1842 | /* SPDIF route: PCM */ | 1844 | /* SPDIF route: PCM */ |
1845 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* needed for W500 Advanced Mini Dock 250410 */ | ||
1843 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | 1846 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, |
1844 | /* EAPD */ | 1847 | /* EAPD */ |
1845 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 1848 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
@@ -1911,7 +1914,7 @@ enum { | |||
1911 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ | 1914 | CXT5051_LAPTOP, /* Laptops w/ EAPD support */ |
1912 | CXT5051_HP, /* no docking */ | 1915 | CXT5051_HP, /* no docking */ |
1913 | CXT5051_HP_DV6736, /* HP without mic switch */ | 1916 | CXT5051_HP_DV6736, /* HP without mic switch */ |
1914 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ | 1917 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */ |
1915 | CXT5051_F700, /* HP Compaq Presario F700 */ | 1918 | CXT5051_F700, /* HP Compaq Presario F700 */ |
1916 | CXT5051_TOSHIBA, /* Toshiba M300 & co */ | 1919 | CXT5051_TOSHIBA, /* Toshiba M300 & co */ |
1917 | CXT5051_MODELS | 1920 | CXT5051_MODELS |
@@ -2033,6 +2036,9 @@ static void cxt5066_update_speaker(struct hda_codec *codec) | |||
2033 | /* Port D (HP/LO) */ | 2036 | /* Port D (HP/LO) */ |
2034 | pinctl = ((spec->hp_present & 2) && spec->cur_eapd) | 2037 | pinctl = ((spec->hp_present & 2) && spec->cur_eapd) |
2035 | ? 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; | ||
2036 | 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, |
2037 | pinctl); | 2043 | pinctl); |
2038 | 2044 | ||
@@ -2213,6 +2219,50 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec) | |||
2213 | } | 2219 | } |
2214 | } | 2220 | } |
2215 | 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 | |||
2216 | /* mute internal speaker if HP is plugged */ | 2266 | /* mute internal speaker if HP is plugged */ |
2217 | static void cxt5066_hp_automute(struct hda_codec *codec) | 2267 | static void cxt5066_hp_automute(struct hda_codec *codec) |
2218 | { | 2268 | { |
@@ -2225,7 +2275,8 @@ static void cxt5066_hp_automute(struct hda_codec *codec) | |||
2225 | /* Port D */ | 2275 | /* Port D */ |
2226 | portD = snd_hda_jack_detect(codec, 0x1c); | 2276 | portD = snd_hda_jack_detect(codec, 0x1c); |
2227 | 2277 | ||
2228 | spec->hp_present = !!(portA | portD); | 2278 | spec->hp_present = !!(portA); |
2279 | spec->hp_present |= portD ? 2 : 0; | ||
2229 | 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", |
2230 | portA, portD, spec->hp_present); | 2281 | portA, portD, spec->hp_present); |
2231 | cxt5066_update_speaker(codec); | 2282 | cxt5066_update_speaker(codec); |
@@ -2276,6 +2327,20 @@ static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res) | |||
2276 | } | 2327 | } |
2277 | } | 2328 | } |
2278 | 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 | |||
2279 | static const struct hda_input_mux cxt5066_analog_mic_boost = { | 2344 | static const struct hda_input_mux cxt5066_analog_mic_boost = { |
2280 | .num_items = 5, | 2345 | .num_items = 5, |
2281 | .items = { | 2346 | .items = { |
@@ -2294,7 +2359,7 @@ static void cxt5066_set_mic_boost(struct hda_codec *codec) | |||
2294 | AC_VERB_SET_AMP_GAIN_MUTE, | 2359 | AC_VERB_SET_AMP_GAIN_MUTE, |
2295 | 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 | |
2296 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); | 2361 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); |
2297 | if (spec->ideapad) { | 2362 | if (spec->ideapad || spec->thinkpad) { |
2298 | /* adjust the internal mic as well...it is not through 0x17 */ | 2363 | /* adjust the internal mic as well...it is not through 0x17 */ |
2299 | snd_hda_codec_write_cache(codec, 0x23, 0, | 2364 | snd_hda_codec_write_cache(codec, 0x23, 0, |
2300 | AC_VERB_SET_AMP_GAIN_MUTE, | 2365 | AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -2782,6 +2847,64 @@ static struct hda_verb cxt5066_init_verbs_ideapad[] = { | |||
2782 | { } /* end */ | 2847 | { } /* end */ |
2783 | }; | 2848 | }; |
2784 | 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 | |||
2785 | static struct hda_verb cxt5066_init_verbs_portd_lo[] = { | 2908 | static struct hda_verb cxt5066_init_verbs_portd_lo[] = { |
2786 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 2909 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
2787 | { } /* end */ | 2910 | { } /* end */ |
@@ -2800,6 +2923,8 @@ static int cxt5066_init(struct hda_codec *codec) | |||
2800 | cxt5066_vostro_automic(codec); | 2923 | cxt5066_vostro_automic(codec); |
2801 | else if (spec->ideapad) | 2924 | else if (spec->ideapad) |
2802 | cxt5066_ideapad_automic(codec); | 2925 | cxt5066_ideapad_automic(codec); |
2926 | else if (spec->thinkpad) | ||
2927 | cxt5066_thinkpad_automic(codec); | ||
2803 | } | 2928 | } |
2804 | cxt5066_set_mic_boost(codec); | 2929 | cxt5066_set_mic_boost(codec); |
2805 | return 0; | 2930 | return 0; |
@@ -2821,20 +2946,22 @@ static int cxt5066_olpc_init(struct hda_codec *codec) | |||
2821 | } | 2946 | } |
2822 | 2947 | ||
2823 | enum { | 2948 | enum { |
2824 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ | 2949 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ |
2825 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ | 2950 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ |
2826 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ | 2951 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ |
2827 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ | 2952 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ |
2828 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | 2953 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ |
2954 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ | ||
2829 | CXT5066_MODELS | 2955 | CXT5066_MODELS |
2830 | }; | 2956 | }; |
2831 | 2957 | ||
2832 | static const char *cxt5066_models[CXT5066_MODELS] = { | 2958 | static const char *cxt5066_models[CXT5066_MODELS] = { |
2833 | [CXT5066_LAPTOP] = "laptop", | 2959 | [CXT5066_LAPTOP] = "laptop", |
2834 | [CXT5066_DELL_LAPTOP] = "dell-laptop", | 2960 | [CXT5066_DELL_LAPTOP] = "dell-laptop", |
2835 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", | 2961 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", |
2836 | [CXT5066_DELL_VOSTO] = "dell-vostro", | 2962 | [CXT5066_DELL_VOSTO] = "dell-vostro", |
2837 | [CXT5066_IDEAPAD] = "ideapad", | 2963 | [CXT5066_IDEAPAD] = "ideapad", |
2964 | [CXT5066_THINKPAD] = "thinkpad", | ||
2838 | }; | 2965 | }; |
2839 | 2966 | ||
2840 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | 2967 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { |
@@ -2849,6 +2976,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
2849 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), | 2976 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), |
2850 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), | 2977 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), |
2851 | 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), | ||
2852 | {} | 2980 | {} |
2853 | }; | 2981 | }; |
2854 | 2982 | ||
@@ -2956,6 +3084,22 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
2956 | /* input source automatically selected */ | 3084 | /* input source automatically selected */ |
2957 | spec->input_mux = NULL; | 3085 | spec->input_mux = NULL; |
2958 | 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; | ||
2959 | } | 3103 | } |
2960 | 3104 | ||
2961 | return 0; | 3105 | return 0; |
@@ -2975,6 +3119,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = { | |||
2975 | .patch = patch_cxt5066 }, | 3119 | .patch = patch_cxt5066 }, |
2976 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", | 3120 | { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", |
2977 | .patch = patch_cxt5066 }, | 3121 | .patch = patch_cxt5066 }, |
3122 | { .id = 0x14f15069, .name = "CX20585", | ||
3123 | .patch = patch_cxt5066 }, | ||
2978 | {} /* terminator */ | 3124 | {} /* terminator */ |
2979 | }; | 3125 | }; |
2980 | 3126 | ||
@@ -2983,6 +3129,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15047"); | |||
2983 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); | 3129 | MODULE_ALIAS("snd-hda-codec-id:14f15051"); |
2984 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); | 3130 | MODULE_ALIAS("snd-hda-codec-id:14f15066"); |
2985 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); | 3131 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); |
3132 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); | ||
2986 | 3133 | ||
2987 | MODULE_LICENSE("GPL"); | 3134 | MODULE_LICENSE("GPL"); |
2988 | 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 index 2c2bafbf0258..86067ee78632 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -766,7 +766,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | |||
766 | if (spec->num_pins >= MAX_HDMI_PINS) { | 766 | if (spec->num_pins >= MAX_HDMI_PINS) { |
767 | snd_printk(KERN_WARNING | 767 | snd_printk(KERN_WARNING |
768 | "HDMI: no space for pin %d\n", pin_nid); | 768 | "HDMI: no space for pin %d\n", pin_nid); |
769 | return -EINVAL; | 769 | return -E2BIG; |
770 | } | 770 | } |
771 | 771 | ||
772 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); | 772 | hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); |
@@ -788,7 +788,7 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) | |||
788 | if (spec->num_cvts >= MAX_HDMI_CVTS) { | 788 | if (spec->num_cvts >= MAX_HDMI_CVTS) { |
789 | snd_printk(KERN_WARNING | 789 | snd_printk(KERN_WARNING |
790 | "HDMI: no space for converter %d\n", nid); | 790 | "HDMI: no space for converter %d\n", nid); |
791 | return -EINVAL; | 791 | return -E2BIG; |
792 | } | 792 | } |
793 | 793 | ||
794 | spec->cvt[spec->num_cvts] = nid; | 794 | spec->cvt[spec->num_cvts] = nid; |
@@ -820,15 +820,13 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
820 | 820 | ||
821 | switch (type) { | 821 | switch (type) { |
822 | case AC_WID_AUD_OUT: | 822 | case AC_WID_AUD_OUT: |
823 | if (hdmi_add_cvt(codec, nid) < 0) | 823 | hdmi_add_cvt(codec, nid); |
824 | return -EINVAL; | ||
825 | break; | 824 | break; |
826 | case AC_WID_PIN: | 825 | case AC_WID_PIN: |
827 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 826 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); |
828 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | 827 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) |
829 | continue; | 828 | continue; |
830 | if (hdmi_add_pin(codec, nid) < 0) | 829 | hdmi_add_pin(codec, nid); |
831 | return -EINVAL; | ||
832 | break; | 830 | break; |
833 | } | 831 | } |
834 | } | 832 | } |
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 88d035104cc5..b81d23e42ace 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c | |||
@@ -40,7 +40,7 @@ | |||
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 MAX_HDMI_CVTS 2 | 43 | #define MAX_HDMI_CVTS 3 |
44 | #define MAX_HDMI_PINS 3 | 44 | #define MAX_HDMI_PINS 3 |
45 | 45 | ||
46 | #include "patch_hdmi.c" | 46 | #include "patch_hdmi.c" |
@@ -48,6 +48,7 @@ | |||
48 | static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { | 48 | static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { |
49 | "INTEL HDMI 0", | 49 | "INTEL HDMI 0", |
50 | "INTEL HDMI 1", | 50 | "INTEL HDMI 1", |
51 | "INTEL HDMI 2", | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | /* | 54 | /* |
@@ -185,14 +186,15 @@ static int patch_intel_hdmi(struct hda_codec *codec) | |||
185 | } | 186 | } |
186 | 187 | ||
187 | static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { | 188 | static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { |
188 | { .id = 0x808629fb, .name = "G45 DEVCL", .patch = patch_intel_hdmi }, | 189 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_intel_hdmi }, |
189 | { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi }, | 190 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_intel_hdmi }, |
190 | { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi }, | 191 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_intel_hdmi }, |
191 | { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi }, | 192 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_intel_hdmi }, |
192 | { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi }, | 193 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi }, |
193 | { .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi }, | 194 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi }, |
194 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, | 195 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_intel_hdmi }, |
195 | {} /* terminator */ | 196 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, |
197 | {} /* terminator */ | ||
196 | }; | 198 | }; |
197 | 199 | ||
198 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | 200 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
@@ -200,6 +202,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862801"); | |||
200 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | 202 | MODULE_ALIAS("snd-hda-codec-id:80862802"); |
201 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | 203 | MODULE_ALIAS("snd-hda-codec-id:80862803"); |
202 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | 204 | MODULE_ALIAS("snd-hda-codec-id:80862804"); |
205 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | ||
203 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | 206 | MODULE_ALIAS("snd-hda-codec-id:80860054"); |
204 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | 207 | MODULE_ALIAS("snd-hda-codec-id:10951392"); |
205 | 208 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 886d8e46bb37..53538b0f9991 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -276,6 +276,18 @@ struct alc_mic_route { | |||
276 | 276 | ||
277 | #define MUX_IDX_UNDEF ((unsigned char)-1) | 277 | #define MUX_IDX_UNDEF ((unsigned char)-1) |
278 | 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 | |||
279 | struct alc_spec { | 291 | struct alc_spec { |
280 | /* codec parameterization */ | 292 | /* codec parameterization */ |
281 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ | 293 | struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ |
@@ -333,6 +345,7 @@ struct alc_spec { | |||
333 | 345 | ||
334 | /* dynamic controls, init_verbs and input_mux */ | 346 | /* dynamic controls, init_verbs and input_mux */ |
335 | struct auto_pin_cfg autocfg; | 347 | struct auto_pin_cfg autocfg; |
348 | struct alc_customize_define cdefine; | ||
336 | struct snd_array kctls; | 349 | struct snd_array kctls; |
337 | struct hda_input_mux private_imux[3]; | 350 | struct hda_input_mux private_imux[3]; |
338 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 351 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
@@ -1248,6 +1261,62 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
1248 | spec->unsol_event = alc_sku_unsol_event; | 1261 | spec->unsol_event = alc_sku_unsol_event; |
1249 | } | 1262 | } |
1250 | 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 | |||
1251 | /* check subsystem ID and set up device-specific initialization; | 1320 | /* check subsystem ID and set up device-specific initialization; |
1252 | * return 1 if initialized, 0 if invalid SSID | 1321 | * return 1 if initialized, 0 if invalid SSID |
1253 | */ | 1322 | */ |
@@ -3415,6 +3484,10 @@ static int alc_init(struct hda_codec *codec) | |||
3415 | if (spec->init_hook) | 3484 | if (spec->init_hook) |
3416 | spec->init_hook(codec); | 3485 | spec->init_hook(codec); |
3417 | 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 | ||
3418 | return 0; | 3491 | return 0; |
3419 | } | 3492 | } |
3420 | 3493 | ||
@@ -3775,6 +3848,10 @@ static int alc_resume(struct hda_codec *codec) | |||
3775 | codec->patch_ops.init(codec); | 3848 | codec->patch_ops.init(codec); |
3776 | snd_hda_codec_resume_amp(codec); | 3849 | snd_hda_codec_resume_amp(codec); |
3777 | 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 | ||
3778 | return 0; | 3855 | return 0; |
3779 | } | 3856 | } |
3780 | #endif | 3857 | #endif |
@@ -3797,6 +3874,17 @@ static struct hda_codec_ops alc_patch_ops = { | |||
3797 | .reboot_notify = alc_shutup, | 3874 | .reboot_notify = alc_shutup, |
3798 | }; | 3875 | }; |
3799 | 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 | } | ||
3800 | 3888 | ||
3801 | /* | 3889 | /* |
3802 | * Test configuration for debugging | 3890 | * Test configuration for debugging |
@@ -10189,21 +10277,20 @@ static int alc882_auto_create_input_ctls(struct hda_codec *codec, | |||
10189 | 10277 | ||
10190 | 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, |
10191 | hda_nid_t nid, int pin_type, | 10279 | hda_nid_t nid, int pin_type, |
10192 | int dac_idx) | 10280 | hda_nid_t dac) |
10193 | { | 10281 | { |
10194 | /* set as output */ | ||
10195 | struct alc_spec *spec = codec->spec; | ||
10196 | int idx; | 10282 | int idx; |
10197 | 10283 | ||
10284 | /* set as output */ | ||
10198 | alc_set_pin_output(codec, nid, pin_type); | 10285 | alc_set_pin_output(codec, nid, pin_type); |
10199 | if (dac_idx >= spec->multiout.num_dacs) | 10286 | |
10200 | return; | 10287 | if (dac == 0x25) |
10201 | if (spec->multiout.dac_nids[dac_idx] == 0x25) | ||
10202 | idx = 4; | 10288 | idx = 4; |
10289 | else if (dac >= 0x02 && dac <= 0x05) | ||
10290 | idx = dac - 2; | ||
10203 | else | 10291 | else |
10204 | idx = spec->multiout.dac_nids[dac_idx] - 2; | 10292 | return; |
10205 | 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); |
10206 | |||
10207 | } | 10294 | } |
10208 | 10295 | ||
10209 | static void alc882_auto_init_multi_out(struct hda_codec *codec) | 10296 | static void alc882_auto_init_multi_out(struct hda_codec *codec) |
@@ -10216,22 +10303,29 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec) | |||
10216 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | 10303 | int pin_type = get_pin_type(spec->autocfg.line_out_type); |
10217 | if (nid) | 10304 | if (nid) |
10218 | alc882_auto_set_output_and_unmute(codec, nid, pin_type, | 10305 | alc882_auto_set_output_and_unmute(codec, nid, pin_type, |
10219 | i); | 10306 | spec->multiout.dac_nids[i]); |
10220 | } | 10307 | } |
10221 | } | 10308 | } |
10222 | 10309 | ||
10223 | static void alc882_auto_init_hp_out(struct hda_codec *codec) | 10310 | static void alc882_auto_init_hp_out(struct hda_codec *codec) |
10224 | { | 10311 | { |
10225 | struct alc_spec *spec = codec->spec; | 10312 | struct alc_spec *spec = codec->spec; |
10226 | hda_nid_t pin; | 10313 | hda_nid_t pin, dac; |
10227 | 10314 | ||
10228 | pin = spec->autocfg.hp_pins[0]; | 10315 | pin = spec->autocfg.hp_pins[0]; |
10229 | if (pin) /* connect to front */ | 10316 | if (pin) { |
10230 | /* use dac 0 */ | 10317 | dac = spec->multiout.hp_nid; |
10231 | 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 | } | ||
10232 | pin = spec->autocfg.speaker_pins[0]; | 10322 | pin = spec->autocfg.speaker_pins[0]; |
10233 | if (pin) | 10323 | if (pin) { |
10234 | 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 | } | ||
10235 | } | 10329 | } |
10236 | 10330 | ||
10237 | static void alc882_auto_init_analog_input(struct hda_codec *codec) | 10331 | static void alc882_auto_init_analog_input(struct hda_codec *codec) |
@@ -10347,15 +10441,15 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
10347 | err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); | 10441 | err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); |
10348 | if (err < 0) | 10442 | if (err < 0) |
10349 | 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; | ||
10350 | err = alc880_auto_create_extra_out(spec, | 10448 | err = alc880_auto_create_extra_out(spec, |
10351 | spec->autocfg.speaker_pins[0], | 10449 | spec->autocfg.speaker_pins[0], |
10352 | "Speaker"); | 10450 | "Speaker"); |
10353 | if (err < 0) | 10451 | if (err < 0) |
10354 | return err; | 10452 | return err; |
10355 | err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], | ||
10356 | "Headphone"); | ||
10357 | if (err < 0) | ||
10358 | return err; | ||
10359 | err = alc882_auto_create_input_ctls(codec, &spec->autocfg); | 10453 | err = alc882_auto_create_input_ctls(codec, &spec->autocfg); |
10360 | if (err < 0) | 10454 | if (err < 0) |
10361 | return err; | 10455 | return err; |
@@ -10425,6 +10519,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
10425 | 10519 | ||
10426 | codec->spec = spec; | 10520 | codec->spec = spec; |
10427 | 10521 | ||
10522 | alc_auto_parse_customize_define(codec); | ||
10523 | |||
10428 | switch (codec->vendor_id) { | 10524 | switch (codec->vendor_id) { |
10429 | case 0x10ec0882: | 10525 | case 0x10ec0882: |
10430 | case 0x10ec0885: | 10526 | case 0x10ec0885: |
@@ -10484,9 +10580,6 @@ static int patch_alc882(struct hda_codec *codec) | |||
10484 | spec->stream_digital_playback = &alc882_pcm_digital_playback; | 10580 | spec->stream_digital_playback = &alc882_pcm_digital_playback; |
10485 | spec->stream_digital_capture = &alc882_pcm_digital_capture; | 10581 | spec->stream_digital_capture = &alc882_pcm_digital_capture; |
10486 | 10582 | ||
10487 | if (codec->vendor_id == 0x10ec0888) | ||
10488 | spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */ | ||
10489 | |||
10490 | if (!spec->adc_nids && spec->input_mux) { | 10583 | if (!spec->adc_nids && spec->input_mux) { |
10491 | int i, j; | 10584 | int i, j; |
10492 | spec->num_adc_nids = 0; | 10585 | spec->num_adc_nids = 0; |
@@ -10521,7 +10614,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
10521 | } | 10614 | } |
10522 | 10615 | ||
10523 | set_capture_mixer(codec); | 10616 | set_capture_mixer(codec); |
10524 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 10617 | |
10618 | if (spec->cdefine.enable_pcbeep) | ||
10619 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | ||
10525 | 10620 | ||
10526 | if (board_config == ALC882_AUTO) | 10621 | if (board_config == ALC882_AUTO) |
10527 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0); | 10622 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0); |
@@ -12308,6 +12403,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
12308 | 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); |
12309 | } | 12404 | } |
12310 | #endif | 12405 | #endif |
12406 | alc_auto_parse_customize_define(codec); | ||
12311 | 12407 | ||
12312 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); | 12408 | alc_fix_pll_init(codec, 0x20, 0x0a, 10); |
12313 | 12409 | ||
@@ -12386,7 +12482,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
12386 | } | 12482 | } |
12387 | if (!spec->cap_mixer && !spec->no_analog) | 12483 | if (!spec->cap_mixer && !spec->no_analog) |
12388 | set_capture_mixer(codec); | 12484 | set_capture_mixer(codec); |
12389 | if (!spec->no_analog) | 12485 | if (!spec->no_analog && spec->cdefine.enable_pcbeep) |
12390 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 12486 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
12391 | 12487 | ||
12392 | spec->vmaster_nid = 0x0c; | 12488 | spec->vmaster_nid = 0x0c; |
@@ -14005,6 +14101,35 @@ static struct hda_pcm_stream alc269_44k_pcm_analog_capture = { | |||
14005 | /* NID is set in alc_build_pcms */ | 14101 | /* NID is set in alc_build_pcms */ |
14006 | }; | 14102 | }; |
14007 | 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 | |||
14008 | /* | 14133 | /* |
14009 | * BIOS auto configuration | 14134 | * BIOS auto configuration |
14010 | */ | 14135 | */ |
@@ -14082,7 +14207,7 @@ enum { | |||
14082 | ALC269_FIXUP_SONY_VAIO, | 14207 | ALC269_FIXUP_SONY_VAIO, |
14083 | }; | 14208 | }; |
14084 | 14209 | ||
14085 | const static struct hda_verb alc269_sony_vaio_fixup_verbs[] = { | 14210 | static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { |
14086 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | 14211 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, |
14087 | {} | 14212 | {} |
14088 | }; | 14213 | }; |
@@ -14290,17 +14415,17 @@ static int patch_alc269(struct hda_codec *codec) | |||
14290 | 14415 | ||
14291 | codec->spec = spec; | 14416 | codec->spec = spec; |
14292 | 14417 | ||
14293 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 14418 | alc_auto_parse_customize_define(codec); |
14294 | 14419 | ||
14295 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ | 14420 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ |
14296 | kfree(codec->chip_name); | 14421 | if (codec->bus->pci->subsystem_vendor == 0x1025 && |
14297 | codec->chip_name = kstrdup("ALC259", GFP_KERNEL); | 14422 | spec->cdefine.platform_type == 1) |
14298 | if (!codec->chip_name) { | 14423 | alc_codec_rename(codec, "ALC271X"); |
14299 | alc_free(codec); | 14424 | else |
14300 | return -ENOMEM; | 14425 | alc_codec_rename(codec, "ALC259"); |
14301 | } | ||
14302 | is_alc269vb = 1; | 14426 | is_alc269vb = 1; |
14303 | } | 14427 | } else |
14428 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | ||
14304 | 14429 | ||
14305 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, | 14430 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, |
14306 | alc269_models, | 14431 | alc269_models, |
@@ -14365,7 +14490,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
14365 | 14490 | ||
14366 | if (!spec->cap_mixer) | 14491 | if (!spec->cap_mixer) |
14367 | set_capture_mixer(codec); | 14492 | set_capture_mixer(codec); |
14368 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 14493 | if (spec->cdefine.enable_pcbeep) |
14494 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | ||
14369 | 14495 | ||
14370 | if (board_config == ALC269_AUTO) | 14496 | if (board_config == ALC269_AUTO) |
14371 | alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0); | 14497 | alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0); |
@@ -14378,6 +14504,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
14378 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 14504 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
14379 | if (!spec->loopback.amplist) | 14505 | if (!spec->loopback.amplist) |
14380 | 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; | ||
14381 | #endif | 14509 | #endif |
14382 | 14510 | ||
14383 | return 0; | 14511 | return 0; |
@@ -18525,16 +18653,16 @@ static int patch_alc662(struct hda_codec *codec) | |||
18525 | 18653 | ||
18526 | codec->spec = spec; | 18654 | codec->spec = spec; |
18527 | 18655 | ||
18656 | alc_auto_parse_customize_define(codec); | ||
18657 | |||
18528 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 18658 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
18529 | 18659 | ||
18530 | if (alc_read_coef_idx(codec, 0)==0x8020){ | 18660 | if (alc_read_coef_idx(codec, 0) == 0x8020) |
18531 | kfree(codec->chip_name); | 18661 | alc_codec_rename(codec, "ALC661"); |
18532 | codec->chip_name = kstrdup("ALC661", GFP_KERNEL); | 18662 | else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) && |
18533 | if (!codec->chip_name) { | 18663 | codec->bus->pci->subsystem_vendor == 0x1025 && |
18534 | alc_free(codec); | 18664 | spec->cdefine.platform_type == 1) |
18535 | return -ENOMEM; | 18665 | alc_codec_rename(codec, "ALC272X"); |
18536 | } | ||
18537 | } | ||
18538 | 18666 | ||
18539 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, | 18667 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, |
18540 | alc662_models, | 18668 | alc662_models, |
@@ -18584,18 +18712,20 @@ static int patch_alc662(struct hda_codec *codec) | |||
18584 | if (!spec->cap_mixer) | 18712 | if (!spec->cap_mixer) |
18585 | set_capture_mixer(codec); | 18713 | set_capture_mixer(codec); |
18586 | 18714 | ||
18587 | switch (codec->vendor_id) { | 18715 | if (spec->cdefine.enable_pcbeep) { |
18588 | case 0x10ec0662: | 18716 | switch (codec->vendor_id) { |
18589 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 18717 | case 0x10ec0662: |
18590 | break; | 18718 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
18591 | case 0x10ec0272: | 18719 | break; |
18592 | case 0x10ec0663: | 18720 | case 0x10ec0272: |
18593 | case 0x10ec0665: | 18721 | case 0x10ec0663: |
18594 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 18722 | case 0x10ec0665: |
18595 | break; | 18723 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
18596 | case 0x10ec0273: | 18724 | break; |
18597 | set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); | 18725 | case 0x10ec0273: |
18598 | break; | 18726 | set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); |
18727 | break; | ||
18728 | } | ||
18599 | } | 18729 | } |
18600 | spec->vmaster_nid = 0x02; | 18730 | spec->vmaster_nid = 0x02; |
18601 | 18731 | ||