diff options
| -rw-r--r-- | sound/core/pcm_lib.c | 8 | ||||
| -rw-r--r-- | sound/pci/hda/hda_codec.c | 48 | ||||
| -rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
| -rw-r--r-- | sound/pci/hda/hda_hwdep.c | 7 | ||||
| -rw-r--r-- | sound/pci/hda/hda_intel.c | 51 | ||||
| -rw-r--r-- | sound/pci/hda/hda_local.h | 2 | ||||
| -rw-r--r-- | sound/pci/hda/patch_analog.c | 71 | ||||
| -rw-r--r-- | sound/pci/hda/patch_cirrus.c | 12 | ||||
| -rw-r--r-- | sound/pci/hda/patch_cmedia.c | 3 | ||||
| -rw-r--r-- | sound/pci/hda/patch_conexant.c | 382 | ||||
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 73 | ||||
| -rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 113 | ||||
| -rw-r--r-- | sound/pci/hda/patch_via.c | 3 |
13 files changed, 591 insertions, 183 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 0403a7d55f0c..720019560794 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
| @@ -394,6 +394,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 394 | + HZ/100); | 394 | + HZ/100); |
| 395 | /* move new_hw_ptr according jiffies not pos variable */ | 395 | /* move new_hw_ptr according jiffies not pos variable */ |
| 396 | new_hw_ptr = old_hw_ptr; | 396 | new_hw_ptr = old_hw_ptr; |
| 397 | hw_base = delta; | ||
| 397 | /* use loop to avoid checks for delta overflows */ | 398 | /* use loop to avoid checks for delta overflows */ |
| 398 | /* the delta value is small or zero in most cases */ | 399 | /* the delta value is small or zero in most cases */ |
| 399 | while (delta > 0) { | 400 | while (delta > 0) { |
| @@ -403,8 +404,6 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 403 | delta--; | 404 | delta--; |
| 404 | } | 405 | } |
| 405 | /* align hw_base to buffer_size */ | 406 | /* align hw_base to buffer_size */ |
| 406 | hw_base = new_hw_ptr - (new_hw_ptr % runtime->buffer_size); | ||
| 407 | delta = 0; | ||
| 408 | hw_ptr_error(substream, | 407 | hw_ptr_error(substream, |
| 409 | "hw_ptr skipping! %s" | 408 | "hw_ptr skipping! %s" |
| 410 | "(pos=%ld, delta=%ld, period=%ld, " | 409 | "(pos=%ld, delta=%ld, period=%ld, " |
| @@ -412,9 +411,12 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 412 | in_interrupt ? "[Q] " : "", | 411 | in_interrupt ? "[Q] " : "", |
| 413 | (long)pos, (long)hdelta, | 412 | (long)pos, (long)hdelta, |
| 414 | (long)runtime->period_size, jdelta, | 413 | (long)runtime->period_size, jdelta, |
| 415 | ((hdelta * HZ) / runtime->rate), delta, | 414 | ((hdelta * HZ) / runtime->rate), hw_base, |
| 416 | (unsigned long)old_hw_ptr, | 415 | (unsigned long)old_hw_ptr, |
| 417 | (unsigned long)new_hw_ptr); | 416 | (unsigned long)new_hw_ptr); |
| 417 | /* reset values to proper state */ | ||
| 418 | delta = 0; | ||
| 419 | hw_base = new_hw_ptr - (new_hw_ptr % runtime->buffer_size); | ||
| 418 | } | 420 | } |
| 419 | no_jiffies_check: | 421 | no_jiffies_check: |
| 420 | if (delta > runtime->period_size + runtime->period_size / 2) { | 422 | if (delta > runtime->period_size + runtime->period_size / 2) { |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index d2f10b1c3a8a..d02ea8926e7e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
| @@ -824,6 +824,9 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | |||
| 824 | struct hda_pincfg *pin; | 824 | struct hda_pincfg *pin; |
| 825 | unsigned int oldcfg; | 825 | unsigned int oldcfg; |
| 826 | 826 | ||
| 827 | if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) | ||
| 828 | return -EINVAL; | ||
| 829 | |||
| 827 | oldcfg = snd_hda_codec_get_pincfg(codec, nid); | 830 | oldcfg = snd_hda_codec_get_pincfg(codec, nid); |
| 828 | pin = look_up_pincfg(codec, list, nid); | 831 | pin = look_up_pincfg(codec, list, nid); |
| 829 | if (!pin) { | 832 | if (!pin) { |
| @@ -899,6 +902,25 @@ static void restore_pincfgs(struct hda_codec *codec) | |||
| 899 | } | 902 | } |
| 900 | } | 903 | } |
| 901 | 904 | ||
| 905 | /** | ||
| 906 | * snd_hda_shutup_pins - Shut up all pins | ||
| 907 | * @codec: the HDA codec | ||
| 908 | * | ||
| 909 | * Clear all pin controls to shup up before suspend for avoiding click noise. | ||
| 910 | * The controls aren't cached so that they can be resumed properly. | ||
| 911 | */ | ||
| 912 | void snd_hda_shutup_pins(struct hda_codec *codec) | ||
| 913 | { | ||
| 914 | int i; | ||
| 915 | for (i = 0; i < codec->init_pins.used; i++) { | ||
| 916 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
| 917 | /* use read here for syncing after issuing each verb */ | ||
| 918 | snd_hda_codec_read(codec, pin->nid, 0, | ||
| 919 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
| 920 | } | ||
| 921 | } | ||
| 922 | EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); | ||
| 923 | |||
| 902 | static void init_hda_cache(struct hda_cache_rec *cache, | 924 | static void init_hda_cache(struct hda_cache_rec *cache, |
| 903 | unsigned int record_size); | 925 | unsigned int record_size); |
| 904 | static void free_hda_cache(struct hda_cache_rec *cache); | 926 | static void free_hda_cache(struct hda_cache_rec *cache); |
| @@ -3537,32 +3559,6 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | |||
| 3537 | } | 3559 | } |
| 3538 | EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); | 3560 | EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); |
| 3539 | 3561 | ||
| 3540 | /** | ||
| 3541 | * snd_hda_add_nids - assign nids to controls from the array | ||
| 3542 | * @codec: the HDA codec | ||
| 3543 | * @kctl: struct snd_kcontrol | ||
| 3544 | * @index: index to kctl | ||
| 3545 | * @nids: the array of hda_nid_t | ||
| 3546 | * @size: count of hda_nid_t items | ||
| 3547 | * | ||
| 3548 | * This helper function assigns NIDs in the given array to a control element. | ||
| 3549 | * | ||
| 3550 | * Returns 0 if successful, or a negative error code. | ||
| 3551 | */ | ||
| 3552 | int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
| 3553 | unsigned int index, hda_nid_t *nids, unsigned int size) | ||
| 3554 | { | ||
| 3555 | int err; | ||
| 3556 | |||
| 3557 | for ( ; size > 0; size--, nids++) { | ||
| 3558 | err = snd_hda_add_nid(codec, kctl, index, *nids); | ||
| 3559 | if (err < 0) | ||
| 3560 | return err; | ||
| 3561 | } | ||
| 3562 | return 0; | ||
| 3563 | } | ||
| 3564 | EXPORT_SYMBOL_HDA(snd_hda_add_nids); | ||
| 3565 | |||
| 3566 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3562 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 3567 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 3563 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
| 3568 | unsigned int power_state); | 3564 | unsigned int power_state); |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 0d08ad5bd898..11c4aa8ee996 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
| @@ -898,6 +898,7 @@ int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid, | |||
| 898 | unsigned int cfg); | 898 | unsigned int cfg); |
| 899 | int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | 899 | int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, |
| 900 | hda_nid_t nid, unsigned int cfg); /* for hwdep */ | 900 | hda_nid_t nid, unsigned int cfg); /* for hwdep */ |
| 901 | void snd_hda_shutup_pins(struct hda_codec *codec); | ||
| 901 | 902 | ||
| 902 | /* | 903 | /* |
| 903 | * Mixer | 904 | * Mixer |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 40ccb419b6e9..b36919c0d363 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
| @@ -293,8 +293,11 @@ static ssize_t type##_store(struct device *dev, \ | |||
| 293 | { \ | 293 | { \ |
| 294 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ | 294 | struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ |
| 295 | struct hda_codec *codec = hwdep->private_data; \ | 295 | struct hda_codec *codec = hwdep->private_data; \ |
| 296 | char *after; \ | 296 | unsigned long val; \ |
| 297 | codec->type = simple_strtoul(buf, &after, 0); \ | 297 | int err = strict_strtoul(buf, 0, &val); \ |
| 298 | if (err < 0) \ | ||
| 299 | return err; \ | ||
| 300 | codec->type = val; \ | ||
| 298 | return count; \ | 301 | return count; \ |
| 299 | } | 302 | } |
| 300 | 303 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ff8ad46cc50e..1f516e668d88 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -356,6 +356,7 @@ struct azx_dev { | |||
| 356 | */ | 356 | */ |
| 357 | unsigned char stream_tag; /* assigned stream */ | 357 | unsigned char stream_tag; /* assigned stream */ |
| 358 | unsigned char index; /* stream index */ | 358 | unsigned char index; /* stream index */ |
| 359 | int device; /* last device number assigned to */ | ||
| 359 | 360 | ||
| 360 | unsigned int opened :1; | 361 | unsigned int opened :1; |
| 361 | unsigned int running :1; | 362 | unsigned int running :1; |
| @@ -1441,10 +1442,13 @@ static int __devinit azx_codec_configure(struct azx *chip) | |||
| 1441 | */ | 1442 | */ |
| 1442 | 1443 | ||
| 1443 | /* assign a stream for the PCM */ | 1444 | /* assign a stream for the PCM */ |
| 1444 | static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream) | 1445 | static inline struct azx_dev * |
| 1446 | azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) | ||
| 1445 | { | 1447 | { |
| 1446 | int dev, i, nums; | 1448 | int dev, i, nums; |
| 1447 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1449 | struct azx_dev *res = NULL; |
| 1450 | |||
| 1451 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 1448 | dev = chip->playback_index_offset; | 1452 | dev = chip->playback_index_offset; |
| 1449 | nums = chip->playback_streams; | 1453 | nums = chip->playback_streams; |
| 1450 | } else { | 1454 | } else { |
| @@ -1453,10 +1457,15 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream) | |||
| 1453 | } | 1457 | } |
| 1454 | for (i = 0; i < nums; i++, dev++) | 1458 | for (i = 0; i < nums; i++, dev++) |
| 1455 | if (!chip->azx_dev[dev].opened) { | 1459 | if (!chip->azx_dev[dev].opened) { |
| 1456 | chip->azx_dev[dev].opened = 1; | 1460 | res = &chip->azx_dev[dev]; |
| 1457 | return &chip->azx_dev[dev]; | 1461 | if (res->device == substream->pcm->device) |
| 1462 | break; | ||
| 1458 | } | 1463 | } |
| 1459 | return NULL; | 1464 | if (res) { |
| 1465 | res->opened = 1; | ||
| 1466 | res->device = substream->pcm->device; | ||
| 1467 | } | ||
| 1468 | return res; | ||
| 1460 | } | 1469 | } |
| 1461 | 1470 | ||
| 1462 | /* release the assigned stream */ | 1471 | /* release the assigned stream */ |
| @@ -1505,7 +1514,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
| 1505 | int err; | 1514 | int err; |
| 1506 | 1515 | ||
| 1507 | mutex_lock(&chip->open_mutex); | 1516 | mutex_lock(&chip->open_mutex); |
| 1508 | azx_dev = azx_assign_device(chip, substream->stream); | 1517 | azx_dev = azx_assign_device(chip, substream); |
| 1509 | if (azx_dev == NULL) { | 1518 | if (azx_dev == NULL) { |
| 1510 | mutex_unlock(&chip->open_mutex); | 1519 | mutex_unlock(&chip->open_mutex); |
| 1511 | return -EBUSY; | 1520 | return -EBUSY; |
| @@ -2695,32 +2704,10 @@ static struct pci_device_id azx_ids[] = { | |||
| 2695 | /* ULI M5461 */ | 2704 | /* ULI M5461 */ |
| 2696 | { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, | 2705 | { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, |
| 2697 | /* NVIDIA MCP */ | 2706 | /* NVIDIA MCP */ |
| 2698 | { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA }, | 2707 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), |
| 2699 | { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA }, | 2708 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
| 2700 | { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA }, | 2709 | .class_mask = 0xffffff, |
| 2701 | { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA }, | 2710 | .driver_data = AZX_DRIVER_NVIDIA }, |
| 2702 | { PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2703 | { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2704 | { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2705 | { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2706 | { PCI_DEVICE(0x10de, 0x0590), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2707 | { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2708 | { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2709 | { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2710 | { PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2711 | { PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2712 | { PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2713 | { PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2714 | { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2715 | { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2716 | { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2717 | { PCI_DEVICE(0x10de, 0x0be2), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2718 | { PCI_DEVICE(0x10de, 0x0be3), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2719 | { PCI_DEVICE(0x10de, 0x0be4), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2720 | { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2721 | { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2722 | { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2723 | { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA }, | ||
| 2724 | /* Teradici */ | 2711 | /* Teradici */ |
| 2725 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, | 2712 | { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, |
| 2726 | /* Creative X-Fi (CA0110-IBG) */ | 2713 | /* Creative X-Fi (CA0110-IBG) */ |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index d505d052972e..7cee364976ff 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
| @@ -343,8 +343,6 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, | |||
| 343 | const struct snd_pci_quirk *tbl); | 343 | const struct snd_pci_quirk *tbl); |
| 344 | int snd_hda_add_new_ctls(struct hda_codec *codec, | 344 | int snd_hda_add_new_ctls(struct hda_codec *codec, |
| 345 | struct snd_kcontrol_new *knew); | 345 | struct snd_kcontrol_new *knew); |
| 346 | int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl, | ||
| 347 | unsigned int index, hda_nid_t *nids, unsigned int size); | ||
| 348 | 346 | ||
| 349 | /* | 347 | /* |
| 350 | * unsolicited event handler | 348 | * unsolicited event handler |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 92b72d4f3984..cecd3c108990 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
| @@ -244,8 +244,7 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
| 244 | if (!kctl) | 244 | if (!kctl) |
| 245 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | 245 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); |
| 246 | for (i = 0; kctl && i < kctl->count; i++) { | 246 | for (i = 0; kctl && i < kctl->count; i++) { |
| 247 | err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids, | 247 | err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]); |
| 248 | spec->input_mux->num_items); | ||
| 249 | if (err < 0) | 248 | if (err < 0) |
| 250 | return err; | 249 | return err; |
| 251 | } | 250 | } |
| @@ -442,6 +441,11 @@ static int ad198x_build_pcms(struct hda_codec *codec) | |||
| 442 | return 0; | 441 | return 0; |
| 443 | } | 442 | } |
| 444 | 443 | ||
| 444 | static inline void ad198x_shutup(struct hda_codec *codec) | ||
| 445 | { | ||
| 446 | snd_hda_shutup_pins(codec); | ||
| 447 | } | ||
| 448 | |||
| 445 | static void ad198x_free_kctls(struct hda_codec *codec) | 449 | static void ad198x_free_kctls(struct hda_codec *codec) |
| 446 | { | 450 | { |
| 447 | struct ad198x_spec *spec = codec->spec; | 451 | struct ad198x_spec *spec = codec->spec; |
| @@ -455,6 +459,46 @@ static void ad198x_free_kctls(struct hda_codec *codec) | |||
| 455 | snd_array_free(&spec->kctls); | 459 | snd_array_free(&spec->kctls); |
| 456 | } | 460 | } |
| 457 | 461 | ||
| 462 | static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front, | ||
| 463 | hda_nid_t hp) | ||
| 464 | { | ||
| 465 | struct ad198x_spec *spec = codec->spec; | ||
| 466 | snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
| 467 | !spec->inv_eapd ? 0x00 : 0x02); | ||
| 468 | snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
| 469 | !spec->inv_eapd ? 0x00 : 0x02); | ||
| 470 | } | ||
| 471 | |||
| 472 | static void ad198x_power_eapd(struct hda_codec *codec) | ||
| 473 | { | ||
| 474 | /* We currently only handle front, HP */ | ||
| 475 | switch (codec->vendor_id) { | ||
| 476 | case 0x11d41882: | ||
| 477 | case 0x11d4882a: | ||
| 478 | case 0x11d41884: | ||
| 479 | case 0x11d41984: | ||
| 480 | case 0x11d41883: | ||
| 481 | case 0x11d4184a: | ||
| 482 | case 0x11d4194a: | ||
| 483 | case 0x11d4194b: | ||
| 484 | ad198x_power_eapd_write(codec, 0x12, 0x11); | ||
| 485 | break; | ||
| 486 | case 0x11d41981: | ||
| 487 | case 0x11d41983: | ||
| 488 | ad198x_power_eapd_write(codec, 0x05, 0x06); | ||
| 489 | break; | ||
| 490 | case 0x11d41986: | ||
| 491 | ad198x_power_eapd_write(codec, 0x1b, 0x1a); | ||
| 492 | break; | ||
| 493 | case 0x11d41988: | ||
| 494 | case 0x11d4198b: | ||
| 495 | case 0x11d4989a: | ||
| 496 | case 0x11d4989b: | ||
| 497 | ad198x_power_eapd_write(codec, 0x29, 0x22); | ||
| 498 | break; | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 458 | static void ad198x_free(struct hda_codec *codec) | 502 | static void ad198x_free(struct hda_codec *codec) |
| 459 | { | 503 | { |
| 460 | struct ad198x_spec *spec = codec->spec; | 504 | struct ad198x_spec *spec = codec->spec; |
| @@ -462,11 +506,29 @@ static void ad198x_free(struct hda_codec *codec) | |||
| 462 | if (!spec) | 506 | if (!spec) |
| 463 | return; | 507 | return; |
| 464 | 508 | ||
| 509 | ad198x_shutup(codec); | ||
| 465 | ad198x_free_kctls(codec); | 510 | ad198x_free_kctls(codec); |
| 466 | kfree(spec); | 511 | kfree(spec); |
| 467 | snd_hda_detach_beep_device(codec); | 512 | snd_hda_detach_beep_device(codec); |
| 468 | } | 513 | } |
| 469 | 514 | ||
| 515 | #ifdef SND_HDA_NEEDS_RESUME | ||
| 516 | static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) | ||
| 517 | { | ||
| 518 | ad198x_shutup(codec); | ||
| 519 | ad198x_power_eapd(codec); | ||
| 520 | return 0; | ||
| 521 | } | ||
| 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 | ||
| 531 | |||
| 470 | static struct hda_codec_ops ad198x_patch_ops = { | 532 | static struct hda_codec_ops ad198x_patch_ops = { |
| 471 | .build_controls = ad198x_build_controls, | 533 | .build_controls = ad198x_build_controls, |
| 472 | .build_pcms = ad198x_build_pcms, | 534 | .build_pcms = ad198x_build_pcms, |
| @@ -475,6 +537,11 @@ static struct hda_codec_ops ad198x_patch_ops = { | |||
| 475 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 537 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 476 | .check_power_status = ad198x_check_power_status, | 538 | .check_power_status = ad198x_check_power_status, |
| 477 | #endif | 539 | #endif |
| 540 | #ifdef SND_HDA_NEEDS_RESUME | ||
| 541 | .suspend = ad198x_suspend, | ||
| 542 | .resume = ad198x_resume, | ||
| 543 | #endif | ||
| 544 | .reboot_notify = ad198x_shutup, | ||
| 478 | }; | 545 | }; |
| 479 | 546 | ||
| 480 | 547 | ||
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 093cfbb55e9e..7de782a5b8f4 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
| @@ -753,6 +753,7 @@ static int build_input(struct hda_codec *codec) | |||
| 753 | spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); | 753 | spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); |
| 754 | for (i = 0; i < 2; i++) { | 754 | for (i = 0; i < 2; i++) { |
| 755 | struct snd_kcontrol *kctl; | 755 | struct snd_kcontrol *kctl; |
| 756 | int n; | ||
| 756 | if (!spec->capture_bind[i]) | 757 | if (!spec->capture_bind[i]) |
| 757 | return -ENOMEM; | 758 | return -ENOMEM; |
| 758 | kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); | 759 | kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); |
| @@ -762,10 +763,13 @@ static int build_input(struct hda_codec *codec) | |||
| 762 | err = snd_hda_ctl_add(codec, 0, kctl); | 763 | err = snd_hda_ctl_add(codec, 0, kctl); |
| 763 | if (err < 0) | 764 | if (err < 0) |
| 764 | return err; | 765 | return err; |
| 765 | err = snd_hda_add_nids(codec, kctl, 0, spec->adc_nid, | 766 | for (n = 0; n < AUTO_PIN_LAST; n++) { |
| 766 | spec->num_inputs); | 767 | if (!spec->adc_nid[n]) |
| 767 | if (err < 0) | 768 | continue; |
| 768 | return err; | 769 | err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[i]); |
| 770 | if (err < 0) | ||
| 771 | return err; | ||
| 772 | } | ||
| 769 | } | 773 | } |
| 770 | 774 | ||
| 771 | if (spec->num_inputs > 1 && !spec->mic_detect) { | 775 | if (spec->num_inputs > 1 && !spec->mic_detect) { |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index cc1c22370a60..ff60908f4554 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
| @@ -345,8 +345,7 @@ static int cmi9880_build_controls(struct hda_codec *codec) | |||
| 345 | /* assign Capture Source enums to NID */ | 345 | /* assign Capture Source enums to NID */ |
| 346 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); | 346 | kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); |
| 347 | for (i = 0; kctl && i < kctl->count; i++) { | 347 | for (i = 0; kctl && i < kctl->count; i++) { |
| 348 | err = snd_hda_add_nids(codec, kctl, i, spec->adc_nids, | 348 | err = snd_hda_add_nid(codec, kctl, i, spec->adc_nids[i]); |
| 349 | spec->input_mux->num_items); | ||
| 350 | if (err < 0) | 349 | if (err < 0) |
| 351 | return err; | 350 | return err; |
| 352 | } | 351 | } |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 947785f43b28..685015a53292 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
| @@ -111,8 +111,22 @@ struct conexant_spec { | |||
| 111 | 111 | ||
| 112 | unsigned int dell_automute; | 112 | unsigned int dell_automute; |
| 113 | unsigned int port_d_mode; | 113 | unsigned int port_d_mode; |
| 114 | unsigned char ext_mic_bias; | ||
| 115 | unsigned int dell_vostro; | 114 | unsigned int dell_vostro; |
| 115 | |||
| 116 | unsigned int ext_mic_present; | ||
| 117 | unsigned int recording; | ||
| 118 | void (*capture_prepare)(struct hda_codec *codec); | ||
| 119 | void (*capture_cleanup)(struct hda_codec *codec); | ||
| 120 | |||
| 121 | /* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors) | ||
| 122 | * through the microphone jack. | ||
| 123 | * When the user enables this through a mixer switch, both internal and | ||
| 124 | * external microphones are disabled. Gain is fixed at 0dB. In this mode, | ||
| 125 | * we also allow the bias to be configured through a separate mixer | ||
| 126 | * control. */ | ||
| 127 | unsigned int dc_enable; | ||
| 128 | unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */ | ||
| 129 | unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ | ||
| 116 | }; | 130 | }; |
| 117 | 131 | ||
| 118 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, | 132 | static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, |
| @@ -185,6 +199,8 @@ static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
| 185 | struct snd_pcm_substream *substream) | 199 | struct snd_pcm_substream *substream) |
| 186 | { | 200 | { |
| 187 | struct conexant_spec *spec = codec->spec; | 201 | struct conexant_spec *spec = codec->spec; |
| 202 | if (spec->capture_prepare) | ||
| 203 | spec->capture_prepare(codec); | ||
| 188 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | 204 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], |
| 189 | stream_tag, 0, format); | 205 | stream_tag, 0, format); |
| 190 | return 0; | 206 | return 0; |
| @@ -196,6 +212,8 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
| 196 | { | 212 | { |
| 197 | struct conexant_spec *spec = codec->spec; | 213 | struct conexant_spec *spec = codec->spec; |
| 198 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | 214 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); |
| 215 | if (spec->capture_cleanup) | ||
| 216 | spec->capture_cleanup(codec); | ||
| 199 | return 0; | 217 | return 0; |
| 200 | } | 218 | } |
| 201 | 219 | ||
| @@ -1723,6 +1741,22 @@ static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { | |||
| 1723 | {} | 1741 | {} |
| 1724 | }; | 1742 | }; |
| 1725 | 1743 | ||
| 1744 | static struct snd_kcontrol_new cxt5051_f700_mixers[] = { | ||
| 1745 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), | ||
| 1746 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), | ||
| 1747 | HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), | ||
| 1748 | { | ||
| 1749 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 1750 | .name = "Master Playback Switch", | ||
| 1751 | .info = cxt_eapd_info, | ||
| 1752 | .get = cxt_eapd_get, | ||
| 1753 | .put = cxt5051_hp_master_sw_put, | ||
| 1754 | .private_value = 0x1a, | ||
| 1755 | }, | ||
| 1756 | |||
| 1757 | {} | ||
| 1758 | }; | ||
| 1759 | |||
| 1726 | static struct hda_verb cxt5051_init_verbs[] = { | 1760 | static struct hda_verb cxt5051_init_verbs[] = { |
| 1727 | /* Line in, Mic */ | 1761 | /* Line in, Mic */ |
| 1728 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, | 1762 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, |
| @@ -1813,6 +1847,32 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { | |||
| 1813 | { } /* end */ | 1847 | { } /* end */ |
| 1814 | }; | 1848 | }; |
| 1815 | 1849 | ||
| 1850 | static struct hda_verb cxt5051_f700_init_verbs[] = { | ||
| 1851 | /* Line in, Mic */ | ||
| 1852 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x03}, | ||
| 1853 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
| 1854 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
| 1855 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, | ||
| 1856 | /* SPK */ | ||
| 1857 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
| 1858 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
| 1859 | /* HP, Amp */ | ||
| 1860 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
| 1861 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
| 1862 | /* DAC1 */ | ||
| 1863 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
| 1864 | /* Record selector: Int mic */ | ||
| 1865 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | ||
| 1866 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
| 1867 | /* SPDIF route: PCM */ | ||
| 1868 | {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
| 1869 | /* EAPD */ | ||
| 1870 | {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | ||
| 1871 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, | ||
| 1872 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT}, | ||
| 1873 | { } /* end */ | ||
| 1874 | }; | ||
| 1875 | |||
| 1816 | /* initialize jack-sensing, too */ | 1876 | /* initialize jack-sensing, too */ |
| 1817 | static int cxt5051_init(struct hda_codec *codec) | 1877 | static int cxt5051_init(struct hda_codec *codec) |
| 1818 | { | 1878 | { |
| @@ -1832,6 +1892,7 @@ enum { | |||
| 1832 | CXT5051_HP, /* no docking */ | 1892 | CXT5051_HP, /* no docking */ |
| 1833 | CXT5051_HP_DV6736, /* HP without mic switch */ | 1893 | CXT5051_HP_DV6736, /* HP without mic switch */ |
| 1834 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ | 1894 | CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ |
| 1895 | CXT5051_F700, /* HP Compaq Presario F700 */ | ||
| 1835 | CXT5051_MODELS | 1896 | CXT5051_MODELS |
| 1836 | }; | 1897 | }; |
| 1837 | 1898 | ||
| @@ -1840,6 +1901,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = { | |||
| 1840 | [CXT5051_HP] = "hp", | 1901 | [CXT5051_HP] = "hp", |
| 1841 | [CXT5051_HP_DV6736] = "hp-dv6736", | 1902 | [CXT5051_HP_DV6736] = "hp-dv6736", |
| 1842 | [CXT5051_LENOVO_X200] = "lenovo-x200", | 1903 | [CXT5051_LENOVO_X200] = "lenovo-x200", |
| 1904 | [CXT5051_F700] = "hp 700" | ||
| 1843 | }; | 1905 | }; |
| 1844 | 1906 | ||
| 1845 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { | 1907 | static struct snd_pci_quirk cxt5051_cfg_tbl[] = { |
| @@ -1849,6 +1911,7 @@ static struct snd_pci_quirk cxt5051_cfg_tbl[] = { | |||
| 1849 | CXT5051_LAPTOP), | 1911 | CXT5051_LAPTOP), |
| 1850 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), | 1912 | SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), |
| 1851 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), | 1913 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), |
| 1914 | SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700), | ||
| 1852 | {} | 1915 | {} |
| 1853 | }; | 1916 | }; |
| 1854 | 1917 | ||
| @@ -1899,6 +1962,11 @@ static int patch_cxt5051(struct hda_codec *codec) | |||
| 1899 | case CXT5051_LENOVO_X200: | 1962 | case CXT5051_LENOVO_X200: |
| 1900 | spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; | 1963 | spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; |
| 1901 | break; | 1964 | break; |
| 1965 | case CXT5051_F700: | ||
| 1966 | spec->init_verbs[0] = cxt5051_f700_init_verbs; | ||
| 1967 | spec->mixers[0] = cxt5051_f700_mixers; | ||
| 1968 | spec->no_auto_mic = 1; | ||
| 1969 | break; | ||
| 1902 | } | 1970 | } |
| 1903 | 1971 | ||
| 1904 | return 0; | 1972 | return 0; |
| @@ -1966,53 +2034,97 @@ static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
| 1966 | return 1; | 2034 | return 1; |
| 1967 | } | 2035 | } |
| 1968 | 2036 | ||
| 1969 | /* toggle input of built-in and mic jack appropriately */ | 2037 | static const struct hda_input_mux cxt5066_olpc_dc_bias = { |
| 1970 | static void cxt5066_automic(struct hda_codec *codec) | 2038 | .num_items = 3, |
| 2039 | .items = { | ||
| 2040 | { "Off", PIN_IN }, | ||
| 2041 | { "50%", PIN_VREF50 }, | ||
| 2042 | { "80%", PIN_VREF80 }, | ||
| 2043 | }, | ||
| 2044 | }; | ||
| 2045 | |||
| 2046 | static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec) | ||
| 1971 | { | 2047 | { |
| 1972 | struct conexant_spec *spec = codec->spec; | 2048 | struct conexant_spec *spec = codec->spec; |
| 1973 | struct hda_verb ext_mic_present[] = { | 2049 | /* Even though port F is the DC input, the bias is controlled on port B. |
| 1974 | /* enable external mic, port B */ | 2050 | * we also leave that port as an active input (but unselected) in DC mode |
| 1975 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias}, | 2051 | * just in case that is necessary to make the bias setting take effect. */ |
| 2052 | return snd_hda_codec_write_cache(codec, 0x1a, 0, | ||
| 2053 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
| 2054 | cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); | ||
| 2055 | } | ||
| 1976 | 2056 | ||
| 1977 | /* switch to external mic input */ | 2057 | /* OLPC defers mic widget control until when capture is started because the |
| 1978 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | 2058 | * microphone LED comes on as soon as these settings are put in place. if we |
| 2059 | * did this before recording, it would give the false indication that recording | ||
| 2060 | * is happening when it is not. */ | ||
| 2061 | static void cxt5066_olpc_select_mic(struct hda_codec *codec) | ||
| 2062 | { | ||
| 2063 | struct conexant_spec *spec = codec->spec; | ||
| 2064 | if (!spec->recording) | ||
| 2065 | return; | ||
| 1979 | 2066 | ||
| 1980 | /* disable internal mic, port C */ | 2067 | if (spec->dc_enable) { |
| 1981 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2068 | /* in DC mode we ignore presence detection and just use the jack |
| 1982 | {} | 2069 | * through our special DC port */ |
| 1983 | }; | 2070 | const struct hda_verb enable_dc_mode[] = { |
| 1984 | static struct hda_verb ext_mic_absent[] = { | 2071 | /* disble internal mic, port C */ |
| 1985 | /* enable internal mic, port C */ | 2072 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
| 1986 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 2073 | |
| 2074 | /* enable DC capture, port F */ | ||
| 2075 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
| 2076 | {}, | ||
| 2077 | }; | ||
| 2078 | |||
| 2079 | snd_hda_sequence_write(codec, enable_dc_mode); | ||
| 2080 | /* port B input disabled (and bias set) through the following call */ | ||
| 2081 | cxt5066_set_olpc_dc_bias(codec); | ||
| 2082 | return; | ||
| 2083 | } | ||
| 1987 | 2084 | ||
| 1988 | /* switch to internal mic input */ | 2085 | /* disable DC (port F) */ |
| 1989 | {0x17, AC_VERB_SET_CONNECT_SEL, 1}, | 2086 | snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0); |
| 1990 | 2087 | ||
| 1991 | /* disable external mic, port B */ | 2088 | /* external mic, port B */ |
| 1992 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2089 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 1993 | {} | 2090 | spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); |
| 1994 | }; | 2091 | |
| 2092 | /* internal mic, port C */ | ||
| 2093 | snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
| 2094 | spec->ext_mic_present ? 0 : PIN_VREF80); | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | /* toggle input of built-in and mic jack appropriately */ | ||
| 2098 | static void cxt5066_olpc_automic(struct hda_codec *codec) | ||
| 2099 | { | ||
| 2100 | struct conexant_spec *spec = codec->spec; | ||
| 1995 | unsigned int present; | 2101 | unsigned int present; |
| 1996 | 2102 | ||
| 1997 | present = snd_hda_jack_detect(codec, 0x1a); | 2103 | if (spec->dc_enable) /* don't do presence detection in DC mode */ |
| 1998 | if (present) { | 2104 | return; |
| 2105 | |||
| 2106 | present = snd_hda_codec_read(codec, 0x1a, 0, | ||
| 2107 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
| 2108 | if (present) | ||
| 1999 | snd_printdd("CXT5066: external microphone detected\n"); | 2109 | snd_printdd("CXT5066: external microphone detected\n"); |
| 2000 | snd_hda_sequence_write(codec, ext_mic_present); | 2110 | else |
| 2001 | } else { | ||
| 2002 | snd_printdd("CXT5066: external microphone absent\n"); | 2111 | snd_printdd("CXT5066: external microphone absent\n"); |
| 2003 | snd_hda_sequence_write(codec, ext_mic_absent); | 2112 | |
| 2004 | } | 2113 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, |
| 2114 | present ? 0 : 1); | ||
| 2115 | spec->ext_mic_present = !!present; | ||
| 2116 | |||
| 2117 | cxt5066_olpc_select_mic(codec); | ||
| 2005 | } | 2118 | } |
| 2006 | 2119 | ||
| 2007 | /* toggle input of built-in digital mic and mic jack appropriately */ | 2120 | /* toggle input of built-in digital mic and mic jack appropriately */ |
| 2008 | static void cxt5066_vostro_automic(struct hda_codec *codec) | 2121 | static void cxt5066_vostro_automic(struct hda_codec *codec) |
| 2009 | { | 2122 | { |
| 2010 | struct conexant_spec *spec = codec->spec; | ||
| 2011 | unsigned int present; | 2123 | unsigned int present; |
| 2012 | 2124 | ||
| 2013 | struct hda_verb ext_mic_present[] = { | 2125 | struct hda_verb ext_mic_present[] = { |
| 2014 | /* enable external mic, port B */ | 2126 | /* enable external mic, port B */ |
| 2015 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, spec->ext_mic_bias}, | 2127 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
| 2016 | 2128 | ||
| 2017 | /* switch to external mic input */ | 2129 | /* switch to external mic input */ |
| 2018 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, | 2130 | {0x17, AC_VERB_SET_CONNECT_SEL, 0}, |
| @@ -2063,15 +2175,18 @@ static void cxt5066_hp_automute(struct hda_codec *codec) | |||
| 2063 | } | 2175 | } |
| 2064 | 2176 | ||
| 2065 | /* unsolicited event for jack sensing */ | 2177 | /* unsolicited event for jack sensing */ |
| 2066 | static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) | 2178 | static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) |
| 2067 | { | 2179 | { |
| 2180 | struct conexant_spec *spec = codec->spec; | ||
| 2068 | snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); | 2181 | snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); |
| 2069 | switch (res >> 26) { | 2182 | switch (res >> 26) { |
| 2070 | case CONEXANT_HP_EVENT: | 2183 | case CONEXANT_HP_EVENT: |
| 2071 | cxt5066_hp_automute(codec); | 2184 | cxt5066_hp_automute(codec); |
| 2072 | break; | 2185 | break; |
| 2073 | case CONEXANT_MIC_EVENT: | 2186 | case CONEXANT_MIC_EVENT: |
| 2074 | cxt5066_automic(codec); | 2187 | /* ignore mic events in DC mode; we're always using the jack */ |
| 2188 | if (!spec->dc_enable) | ||
| 2189 | cxt5066_olpc_automic(codec); | ||
| 2075 | break; | 2190 | break; |
| 2076 | } | 2191 | } |
| 2077 | } | 2192 | } |
| @@ -2101,6 +2216,15 @@ static const struct hda_input_mux cxt5066_analog_mic_boost = { | |||
| 2101 | }, | 2216 | }, |
| 2102 | }; | 2217 | }; |
| 2103 | 2218 | ||
| 2219 | static int cxt5066_set_mic_boost(struct hda_codec *codec) | ||
| 2220 | { | ||
| 2221 | struct conexant_spec *spec = codec->spec; | ||
| 2222 | return snd_hda_codec_write_cache(codec, 0x17, 0, | ||
| 2223 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
| 2224 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | | ||
| 2225 | cxt5066_analog_mic_boost.items[spec->mic_boost].index); | ||
| 2226 | } | ||
| 2227 | |||
| 2104 | static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, | 2228 | static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, |
| 2105 | struct snd_ctl_elem_info *uinfo) | 2229 | struct snd_ctl_elem_info *uinfo) |
| 2106 | { | 2230 | { |
| @@ -2111,15 +2235,8 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, | |||
| 2111 | struct snd_ctl_elem_value *ucontrol) | 2235 | struct snd_ctl_elem_value *ucontrol) |
| 2112 | { | 2236 | { |
| 2113 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2237 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
| 2114 | int val; | 2238 | struct conexant_spec *spec = codec->spec; |
| 2115 | hda_nid_t nid = kcontrol->private_value & 0xff; | 2239 | ucontrol->value.enumerated.item[0] = spec->mic_boost; |
| 2116 | int inout = (kcontrol->private_value & 0x100) ? | ||
| 2117 | AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT; | ||
| 2118 | |||
| 2119 | val = snd_hda_codec_read(codec, nid, 0, | ||
| 2120 | AC_VERB_GET_AMP_GAIN_MUTE, inout); | ||
| 2121 | |||
| 2122 | ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN; | ||
| 2123 | return 0; | 2240 | return 0; |
| 2124 | } | 2241 | } |
| 2125 | 2242 | ||
| @@ -2127,26 +2244,132 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
| 2127 | struct snd_ctl_elem_value *ucontrol) | 2244 | struct snd_ctl_elem_value *ucontrol) |
| 2128 | { | 2245 | { |
| 2129 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2246 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
| 2247 | struct conexant_spec *spec = codec->spec; | ||
| 2130 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; | 2248 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; |
| 2131 | unsigned int idx; | 2249 | unsigned int idx; |
| 2132 | hda_nid_t nid = kcontrol->private_value & 0xff; | 2250 | idx = ucontrol->value.enumerated.item[0]; |
| 2133 | int inout = (kcontrol->private_value & 0x100) ? | 2251 | if (idx >= imux->num_items) |
| 2134 | AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT; | 2252 | idx = imux->num_items - 1; |
| 2253 | |||
| 2254 | spec->mic_boost = idx; | ||
| 2255 | if (!spec->dc_enable) | ||
| 2256 | cxt5066_set_mic_boost(codec); | ||
| 2257 | return 1; | ||
| 2258 | } | ||
| 2259 | |||
| 2260 | static void cxt5066_enable_dc(struct hda_codec *codec) | ||
| 2261 | { | ||
| 2262 | const struct hda_verb enable_dc_mode[] = { | ||
| 2263 | /* disable gain */ | ||
| 2264 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
| 2265 | |||
| 2266 | /* switch to DC input */ | ||
| 2267 | {0x17, AC_VERB_SET_CONNECT_SEL, 3}, | ||
| 2268 | {} | ||
| 2269 | }; | ||
| 2270 | |||
| 2271 | /* configure as input source */ | ||
| 2272 | snd_hda_sequence_write(codec, enable_dc_mode); | ||
| 2273 | cxt5066_olpc_select_mic(codec); /* also sets configured bias */ | ||
| 2274 | } | ||
| 2275 | |||
| 2276 | static void cxt5066_disable_dc(struct hda_codec *codec) | ||
| 2277 | { | ||
| 2278 | /* reconfigure input source */ | ||
| 2279 | cxt5066_set_mic_boost(codec); | ||
| 2280 | /* automic also selects the right mic if we're recording */ | ||
| 2281 | cxt5066_olpc_automic(codec); | ||
| 2282 | } | ||
| 2283 | |||
| 2284 | static int cxt5066_olpc_dc_get(struct snd_kcontrol *kcontrol, | ||
| 2285 | struct snd_ctl_elem_value *ucontrol) | ||
| 2286 | { | ||
| 2287 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 2288 | struct conexant_spec *spec = codec->spec; | ||
| 2289 | ucontrol->value.integer.value[0] = spec->dc_enable; | ||
| 2290 | return 0; | ||
| 2291 | } | ||
| 2292 | |||
| 2293 | static int cxt5066_olpc_dc_put(struct snd_kcontrol *kcontrol, | ||
| 2294 | struct snd_ctl_elem_value *ucontrol) | ||
| 2295 | { | ||
| 2296 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 2297 | struct conexant_spec *spec = codec->spec; | ||
| 2298 | int dc_enable = !!ucontrol->value.integer.value[0]; | ||
| 2135 | 2299 | ||
| 2136 | if (!imux->num_items) | 2300 | if (dc_enable == spec->dc_enable) |
| 2137 | return 0; | 2301 | return 0; |
| 2302 | |||
| 2303 | spec->dc_enable = dc_enable; | ||
| 2304 | if (dc_enable) | ||
| 2305 | cxt5066_enable_dc(codec); | ||
| 2306 | else | ||
| 2307 | cxt5066_disable_dc(codec); | ||
| 2308 | |||
| 2309 | return 1; | ||
| 2310 | } | ||
| 2311 | |||
| 2312 | static int cxt5066_olpc_dc_bias_enum_info(struct snd_kcontrol *kcontrol, | ||
| 2313 | struct snd_ctl_elem_info *uinfo) | ||
| 2314 | { | ||
| 2315 | return snd_hda_input_mux_info(&cxt5066_olpc_dc_bias, uinfo); | ||
| 2316 | } | ||
| 2317 | |||
| 2318 | static int cxt5066_olpc_dc_bias_enum_get(struct snd_kcontrol *kcontrol, | ||
| 2319 | struct snd_ctl_elem_value *ucontrol) | ||
| 2320 | { | ||
| 2321 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 2322 | struct conexant_spec *spec = codec->spec; | ||
| 2323 | ucontrol->value.enumerated.item[0] = spec->dc_input_bias; | ||
| 2324 | return 0; | ||
| 2325 | } | ||
| 2326 | |||
| 2327 | static int cxt5066_olpc_dc_bias_enum_put(struct snd_kcontrol *kcontrol, | ||
| 2328 | struct snd_ctl_elem_value *ucontrol) | ||
| 2329 | { | ||
| 2330 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 2331 | struct conexant_spec *spec = codec->spec; | ||
| 2332 | const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; | ||
| 2333 | unsigned int idx; | ||
| 2334 | |||
| 2138 | idx = ucontrol->value.enumerated.item[0]; | 2335 | idx = ucontrol->value.enumerated.item[0]; |
| 2139 | if (idx >= imux->num_items) | 2336 | if (idx >= imux->num_items) |
| 2140 | idx = imux->num_items - 1; | 2337 | idx = imux->num_items - 1; |
| 2141 | 2338 | ||
| 2142 | snd_hda_codec_write_cache(codec, nid, 0, | 2339 | spec->dc_input_bias = idx; |
| 2143 | AC_VERB_SET_AMP_GAIN_MUTE, | 2340 | if (spec->dc_enable) |
| 2144 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout | | 2341 | cxt5066_set_olpc_dc_bias(codec); |
| 2145 | imux->items[idx].index); | ||
| 2146 | |||
| 2147 | return 1; | 2342 | return 1; |
| 2148 | } | 2343 | } |
| 2149 | 2344 | ||
| 2345 | static void cxt5066_olpc_capture_prepare(struct hda_codec *codec) | ||
| 2346 | { | ||
| 2347 | struct conexant_spec *spec = codec->spec; | ||
| 2348 | /* mark as recording and configure the microphone widget so that the | ||
| 2349 | * recording LED comes on. */ | ||
| 2350 | spec->recording = 1; | ||
| 2351 | cxt5066_olpc_select_mic(codec); | ||
| 2352 | } | ||
| 2353 | |||
| 2354 | static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec) | ||
| 2355 | { | ||
| 2356 | struct conexant_spec *spec = codec->spec; | ||
| 2357 | const struct hda_verb disable_mics[] = { | ||
| 2358 | /* disable external mic, port B */ | ||
| 2359 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
| 2360 | |||
| 2361 | /* disble internal mic, port C */ | ||
| 2362 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
| 2363 | |||
| 2364 | /* disable DC capture, port F */ | ||
| 2365 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
| 2366 | {}, | ||
| 2367 | }; | ||
| 2368 | |||
| 2369 | snd_hda_sequence_write(codec, disable_mics); | ||
| 2370 | spec->recording = 0; | ||
| 2371 | } | ||
| 2372 | |||
| 2150 | static struct hda_input_mux cxt5066_capture_source = { | 2373 | static struct hda_input_mux cxt5066_capture_source = { |
| 2151 | .num_items = 4, | 2374 | .num_items = 4, |
| 2152 | .items = { | 2375 | .items = { |
| @@ -2199,6 +2422,24 @@ static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { | |||
| 2199 | {} | 2422 | {} |
| 2200 | }; | 2423 | }; |
| 2201 | 2424 | ||
| 2425 | static struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = { | ||
| 2426 | { | ||
| 2427 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 2428 | .name = "DC Mode Enable Switch", | ||
| 2429 | .info = snd_ctl_boolean_mono_info, | ||
| 2430 | .get = cxt5066_olpc_dc_get, | ||
| 2431 | .put = cxt5066_olpc_dc_put, | ||
| 2432 | }, | ||
| 2433 | { | ||
| 2434 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 2435 | .name = "DC Input Bias Enum", | ||
| 2436 | .info = cxt5066_olpc_dc_bias_enum_info, | ||
| 2437 | .get = cxt5066_olpc_dc_bias_enum_get, | ||
| 2438 | .put = cxt5066_olpc_dc_bias_enum_put, | ||
| 2439 | }, | ||
| 2440 | {} | ||
| 2441 | }; | ||
| 2442 | |||
| 2202 | static struct snd_kcontrol_new cxt5066_mixers[] = { | 2443 | static struct snd_kcontrol_new cxt5066_mixers[] = { |
| 2203 | { | 2444 | { |
| 2204 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2445 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| @@ -2211,11 +2452,10 @@ static struct snd_kcontrol_new cxt5066_mixers[] = { | |||
| 2211 | 2452 | ||
| 2212 | { | 2453 | { |
| 2213 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2454 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 2214 | .name = "Ext Mic Boost Capture Enum", | 2455 | .name = "Analog Mic Boost Capture Enum", |
| 2215 | .info = cxt5066_mic_boost_mux_enum_info, | 2456 | .info = cxt5066_mic_boost_mux_enum_info, |
| 2216 | .get = cxt5066_mic_boost_mux_enum_get, | 2457 | .get = cxt5066_mic_boost_mux_enum_get, |
| 2217 | .put = cxt5066_mic_boost_mux_enum_put, | 2458 | .put = cxt5066_mic_boost_mux_enum_put, |
| 2218 | .private_value = 0x17, | ||
| 2219 | }, | 2459 | }, |
| 2220 | 2460 | ||
| 2221 | HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), | 2461 | HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), |
| @@ -2297,10 +2537,10 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = { | |||
| 2297 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ | 2537 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ |
| 2298 | 2538 | ||
| 2299 | /* Port B: external microphone */ | 2539 | /* Port B: external microphone */ |
| 2300 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, CXT5066_OLPC_EXT_MIC_BIAS}, | 2540 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
| 2301 | 2541 | ||
| 2302 | /* Port C: internal microphone */ | 2542 | /* Port C: internal microphone */ |
| 2303 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | 2543 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
| 2304 | 2544 | ||
| 2305 | /* Port D: unused */ | 2545 | /* Port D: unused */ |
| 2306 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2546 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
| @@ -2309,7 +2549,7 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = { | |||
| 2309 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2549 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
| 2310 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 2550 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
| 2311 | 2551 | ||
| 2312 | /* Port F: unused */ | 2552 | /* Port F: external DC input through microphone port */ |
| 2313 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | 2553 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, |
| 2314 | 2554 | ||
| 2315 | /* Port G: internal speakers */ | 2555 | /* Port G: internal speakers */ |
| @@ -2429,8 +2669,22 @@ static int cxt5066_init(struct hda_codec *codec) | |||
| 2429 | cxt5066_hp_automute(codec); | 2669 | cxt5066_hp_automute(codec); |
| 2430 | if (spec->dell_vostro) | 2670 | if (spec->dell_vostro) |
| 2431 | cxt5066_vostro_automic(codec); | 2671 | cxt5066_vostro_automic(codec); |
| 2432 | else | 2672 | } |
| 2433 | cxt5066_automic(codec); | 2673 | cxt5066_set_mic_boost(codec); |
| 2674 | return 0; | ||
| 2675 | } | ||
| 2676 | |||
| 2677 | static int cxt5066_olpc_init(struct hda_codec *codec) | ||
| 2678 | { | ||
| 2679 | struct conexant_spec *spec = codec->spec; | ||
| 2680 | snd_printdd("CXT5066: init\n"); | ||
| 2681 | conexant_init(codec); | ||
| 2682 | cxt5066_hp_automute(codec); | ||
| 2683 | if (!spec->dc_enable) { | ||
| 2684 | cxt5066_set_mic_boost(codec); | ||
| 2685 | cxt5066_olpc_automic(codec); | ||
| 2686 | } else { | ||
| 2687 | cxt5066_enable_dc(codec); | ||
| 2434 | } | 2688 | } |
| 2435 | return 0; | 2689 | return 0; |
| 2436 | } | 2690 | } |
| @@ -2471,7 +2725,7 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
| 2471 | codec->spec = spec; | 2725 | codec->spec = spec; |
| 2472 | 2726 | ||
| 2473 | codec->patch_ops = conexant_patch_ops; | 2727 | codec->patch_ops = conexant_patch_ops; |
| 2474 | codec->patch_ops.init = cxt5066_init; | 2728 | codec->patch_ops.init = conexant_init; |
| 2475 | 2729 | ||
| 2476 | spec->dell_automute = 0; | 2730 | spec->dell_automute = 0; |
| 2477 | spec->multiout.max_channels = 2; | 2731 | spec->multiout.max_channels = 2; |
| @@ -2484,7 +2738,6 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
| 2484 | spec->input_mux = &cxt5066_capture_source; | 2738 | spec->input_mux = &cxt5066_capture_source; |
| 2485 | 2739 | ||
| 2486 | spec->port_d_mode = PIN_HP; | 2740 | spec->port_d_mode = PIN_HP; |
| 2487 | spec->ext_mic_bias = PIN_VREF80; | ||
| 2488 | 2741 | ||
| 2489 | spec->num_init_verbs = 1; | 2742 | spec->num_init_verbs = 1; |
| 2490 | spec->init_verbs[0] = cxt5066_init_verbs; | 2743 | spec->init_verbs[0] = cxt5066_init_verbs; |
| @@ -2511,20 +2764,28 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
| 2511 | spec->dell_automute = 1; | 2764 | spec->dell_automute = 1; |
| 2512 | break; | 2765 | break; |
| 2513 | case CXT5066_OLPC_XO_1_5: | 2766 | case CXT5066_OLPC_XO_1_5: |
| 2514 | codec->patch_ops.unsol_event = cxt5066_unsol_event; | 2767 | codec->patch_ops.init = cxt5066_olpc_init; |
| 2768 | codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; | ||
| 2515 | spec->init_verbs[0] = cxt5066_init_verbs_olpc; | 2769 | spec->init_verbs[0] = cxt5066_init_verbs_olpc; |
| 2516 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; | 2770 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; |
| 2771 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_olpc_dc; | ||
| 2517 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; | 2772 | spec->mixers[spec->num_mixers++] = cxt5066_mixers; |
| 2518 | spec->port_d_mode = 0; | 2773 | spec->port_d_mode = 0; |
| 2519 | spec->ext_mic_bias = CXT5066_OLPC_EXT_MIC_BIAS; | 2774 | spec->mic_boost = 3; /* default 30dB gain */ |
| 2520 | 2775 | ||
| 2521 | /* no S/PDIF out */ | 2776 | /* no S/PDIF out */ |
| 2522 | spec->multiout.dig_out_nid = 0; | 2777 | spec->multiout.dig_out_nid = 0; |
| 2523 | 2778 | ||
| 2524 | /* input source automatically selected */ | 2779 | /* input source automatically selected */ |
| 2525 | spec->input_mux = NULL; | 2780 | spec->input_mux = NULL; |
| 2781 | |||
| 2782 | /* our capture hooks which allow us to turn on the microphone LED | ||
| 2783 | * at the right time */ | ||
| 2784 | spec->capture_prepare = cxt5066_olpc_capture_prepare; | ||
| 2785 | spec->capture_cleanup = cxt5066_olpc_capture_cleanup; | ||
| 2526 | break; | 2786 | break; |
| 2527 | case CXT5066_DELL_VOSTO: | 2787 | case CXT5066_DELL_VOSTO: |
| 2788 | codec->patch_ops.init = cxt5066_init; | ||
| 2528 | codec->patch_ops.unsol_event = cxt5066_vostro_event; | 2789 | codec->patch_ops.unsol_event = cxt5066_vostro_event; |
| 2529 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; | 2790 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; |
| 2530 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; | 2791 | spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; |
| @@ -2532,6 +2793,7 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
| 2532 | spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; | 2793 | spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; |
| 2533 | spec->port_d_mode = 0; | 2794 | spec->port_d_mode = 0; |
| 2534 | spec->dell_vostro = 1; | 2795 | spec->dell_vostro = 1; |
| 2796 | spec->mic_boost = 3; /* default 30dB gain */ | ||
| 2535 | snd_hda_attach_beep_device(codec, 0x13); | 2797 | snd_hda_attach_beep_device(codec, 0x13); |
| 2536 | 2798 | ||
| 2537 | /* no S/PDIF out */ | 2799 | /* no S/PDIF out */ |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index aeb23ef6afe5..141ff446104a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -338,7 +338,7 @@ struct alc_spec { | |||
| 338 | void (*init_hook)(struct hda_codec *codec); | 338 | void (*init_hook)(struct hda_codec *codec); |
| 339 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | 339 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); |
| 340 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 340 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 341 | void (*power_hook)(struct hda_codec *codec, int power); | 341 | void (*power_hook)(struct hda_codec *codec); |
| 342 | #endif | 342 | #endif |
| 343 | 343 | ||
| 344 | /* for pin sensing */ | 344 | /* for pin sensing */ |
| @@ -391,7 +391,7 @@ struct alc_config_preset { | |||
| 391 | void (*init_hook)(struct hda_codec *); | 391 | void (*init_hook)(struct hda_codec *); |
| 392 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 392 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 393 | struct hda_amp_list *loopbacks; | 393 | struct hda_amp_list *loopbacks; |
| 394 | void (*power_hook)(struct hda_codec *codec, int power); | 394 | void (*power_hook)(struct hda_codec *codec); |
| 395 | #endif | 395 | #endif |
| 396 | }; | 396 | }; |
| 397 | 397 | ||
| @@ -1835,16 +1835,6 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec) | |||
| 1835 | spec->autocfg.speaker_pins[2] = 0x1b; | 1835 | spec->autocfg.speaker_pins[2] = 0x1b; |
| 1836 | } | 1836 | } |
| 1837 | 1837 | ||
| 1838 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 1839 | static void alc889_power_eapd(struct hda_codec *codec, int power) | ||
| 1840 | { | ||
| 1841 | snd_hda_codec_write(codec, 0x14, 0, | ||
| 1842 | AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0); | ||
| 1843 | snd_hda_codec_write(codec, 0x15, 0, | ||
| 1844 | AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0); | ||
| 1845 | } | ||
| 1846 | #endif | ||
| 1847 | |||
| 1848 | /* | 1838 | /* |
| 1849 | * ALC880 3-stack model | 1839 | * ALC880 3-stack model |
| 1850 | * | 1840 | * |
| @@ -2548,8 +2538,10 @@ static int alc_build_controls(struct hda_codec *codec) | |||
| 2548 | if (!kctl) | 2538 | if (!kctl) |
| 2549 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | 2539 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); |
| 2550 | for (i = 0; kctl && i < kctl->count; i++) { | 2540 | for (i = 0; kctl && i < kctl->count; i++) { |
| 2551 | err = snd_hda_add_nids(codec, kctl, i, spec->capsrc_nids, | 2541 | hda_nid_t *nids = spec->capsrc_nids; |
| 2552 | spec->input_mux->num_items); | 2542 | if (!nids) |
| 2543 | nids = spec->adc_nids; | ||
| 2544 | err = snd_hda_add_nid(codec, kctl, i, nids[i]); | ||
| 2553 | if (err < 0) | 2545 | if (err < 0) |
| 2554 | return err; | 2546 | return err; |
| 2555 | } | 2547 | } |
| @@ -3691,6 +3683,11 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
| 3691 | return 0; | 3683 | return 0; |
| 3692 | } | 3684 | } |
| 3693 | 3685 | ||
| 3686 | static inline void alc_shutup(struct hda_codec *codec) | ||
| 3687 | { | ||
| 3688 | snd_hda_shutup_pins(codec); | ||
| 3689 | } | ||
| 3690 | |||
| 3694 | static void alc_free_kctls(struct hda_codec *codec) | 3691 | static void alc_free_kctls(struct hda_codec *codec) |
| 3695 | { | 3692 | { |
| 3696 | struct alc_spec *spec = codec->spec; | 3693 | struct alc_spec *spec = codec->spec; |
| @@ -3711,17 +3708,47 @@ static void alc_free(struct hda_codec *codec) | |||
| 3711 | if (!spec) | 3708 | if (!spec) |
| 3712 | return; | 3709 | return; |
| 3713 | 3710 | ||
| 3711 | alc_shutup(codec); | ||
| 3714 | alc_free_kctls(codec); | 3712 | alc_free_kctls(codec); |
| 3715 | kfree(spec); | 3713 | kfree(spec); |
| 3716 | snd_hda_detach_beep_device(codec); | 3714 | snd_hda_detach_beep_device(codec); |
| 3717 | } | 3715 | } |
| 3718 | 3716 | ||
| 3719 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3717 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 3718 | static void alc_power_eapd(struct hda_codec *codec) | ||
| 3719 | { | ||
| 3720 | /* We currently only handle front, HP */ | ||
| 3721 | switch (codec->vendor_id) { | ||
| 3722 | case 0x10ec0260: | ||
| 3723 | snd_hda_codec_write(codec, 0x0f, 0, | ||
| 3724 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); | ||
| 3725 | snd_hda_codec_write(codec, 0x10, 0, | ||
| 3726 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); | ||
| 3727 | break; | ||
| 3728 | case 0x10ec0262: | ||
| 3729 | case 0x10ec0267: | ||
| 3730 | case 0x10ec0268: | ||
| 3731 | case 0x10ec0269: | ||
| 3732 | case 0x10ec0272: | ||
| 3733 | case 0x10ec0660: | ||
| 3734 | case 0x10ec0662: | ||
| 3735 | case 0x10ec0663: | ||
| 3736 | case 0x10ec0862: | ||
| 3737 | case 0x10ec0889: | ||
| 3738 | snd_hda_codec_write(codec, 0x14, 0, | ||
| 3739 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); | ||
| 3740 | snd_hda_codec_write(codec, 0x15, 0, | ||
| 3741 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); | ||
| 3742 | break; | ||
| 3743 | } | ||
| 3744 | } | ||
| 3745 | |||
| 3720 | static int alc_suspend(struct hda_codec *codec, pm_message_t state) | 3746 | static int alc_suspend(struct hda_codec *codec, pm_message_t state) |
| 3721 | { | 3747 | { |
| 3722 | struct alc_spec *spec = codec->spec; | 3748 | struct alc_spec *spec = codec->spec; |
| 3749 | alc_shutup(codec); | ||
| 3723 | if (spec && spec->power_hook) | 3750 | if (spec && spec->power_hook) |
| 3724 | spec->power_hook(codec, 0); | 3751 | spec->power_hook(codec); |
| 3725 | return 0; | 3752 | return 0; |
| 3726 | } | 3753 | } |
| 3727 | #endif | 3754 | #endif |
| @@ -3729,16 +3756,9 @@ static int alc_suspend(struct hda_codec *codec, pm_message_t state) | |||
| 3729 | #ifdef SND_HDA_NEEDS_RESUME | 3756 | #ifdef SND_HDA_NEEDS_RESUME |
| 3730 | static int alc_resume(struct hda_codec *codec) | 3757 | static int alc_resume(struct hda_codec *codec) |
| 3731 | { | 3758 | { |
| 3732 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 3733 | struct alc_spec *spec = codec->spec; | ||
| 3734 | #endif | ||
| 3735 | codec->patch_ops.init(codec); | 3759 | codec->patch_ops.init(codec); |
| 3736 | snd_hda_codec_resume_amp(codec); | 3760 | snd_hda_codec_resume_amp(codec); |
| 3737 | snd_hda_codec_resume_cache(codec); | 3761 | snd_hda_codec_resume_cache(codec); |
| 3738 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 3739 | if (spec && spec->power_hook) | ||
| 3740 | spec->power_hook(codec, 1); | ||
| 3741 | #endif | ||
| 3742 | return 0; | 3762 | return 0; |
| 3743 | } | 3763 | } |
| 3744 | #endif | 3764 | #endif |
| @@ -3758,6 +3778,7 @@ static struct hda_codec_ops alc_patch_ops = { | |||
| 3758 | .suspend = alc_suspend, | 3778 | .suspend = alc_suspend, |
| 3759 | .check_power_status = alc_check_power_status, | 3779 | .check_power_status = alc_check_power_status, |
| 3760 | #endif | 3780 | #endif |
| 3781 | .reboot_notify = alc_shutup, | ||
| 3761 | }; | 3782 | }; |
| 3762 | 3783 | ||
| 3763 | 3784 | ||
| @@ -9538,7 +9559,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
| 9538 | .setup = alc889_acer_aspire_8930g_setup, | 9559 | .setup = alc889_acer_aspire_8930g_setup, |
| 9539 | .init_hook = alc_automute_amp, | 9560 | .init_hook = alc_automute_amp, |
| 9540 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 9561 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 9541 | .power_hook = alc889_power_eapd, | 9562 | .power_hook = alc_power_eapd, |
| 9542 | #endif | 9563 | #endif |
| 9543 | }, | 9564 | }, |
| 9544 | [ALC888_ACER_ASPIRE_7730G] = { | 9565 | [ALC888_ACER_ASPIRE_7730G] = { |
| @@ -14975,9 +14996,13 @@ static int patch_alc861(struct hda_codec *codec) | |||
| 14975 | spec->vmaster_nid = 0x03; | 14996 | spec->vmaster_nid = 0x03; |
| 14976 | 14997 | ||
| 14977 | codec->patch_ops = alc_patch_ops; | 14998 | codec->patch_ops = alc_patch_ops; |
| 14978 | if (board_config == ALC861_AUTO) | 14999 | if (board_config == ALC861_AUTO) { |
| 14979 | spec->init_hook = alc861_auto_init; | 15000 | spec->init_hook = alc861_auto_init; |
| 14980 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 15001 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 15002 | spec->power_hook = alc_power_eapd; | ||
| 15003 | #endif | ||
| 15004 | } | ||
| 15005 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 14981 | if (!spec->loopback.amplist) | 15006 | if (!spec->loopback.amplist) |
| 14982 | spec->loopback.amplist = alc861_loopbacks; | 15007 | spec->loopback.amplist = alc861_loopbacks; |
| 14983 | #endif | 15008 | #endif |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 74d5d333ed6c..e28c810bc00c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
| @@ -4159,34 +4159,52 @@ static void stac92xx_power_down(struct hda_codec *codec) | |||
| 4159 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | 4159 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, |
| 4160 | int enable); | 4160 | int enable); |
| 4161 | 4161 | ||
| 4162 | static inline int get_int_hint(struct hda_codec *codec, const char *key, | ||
| 4163 | int *valp) | ||
| 4164 | { | ||
| 4165 | const char *p; | ||
| 4166 | p = snd_hda_get_hint(codec, key); | ||
| 4167 | if (p) { | ||
| 4168 | unsigned long val; | ||
| 4169 | if (!strict_strtoul(p, 0, &val)) { | ||
| 4170 | *valp = val; | ||
| 4171 | return 1; | ||
| 4172 | } | ||
| 4173 | } | ||
| 4174 | return 0; | ||
| 4175 | } | ||
| 4176 | |||
| 4162 | /* override some hints from the hwdep entry */ | 4177 | /* override some hints from the hwdep entry */ |
| 4163 | static void stac_store_hints(struct hda_codec *codec) | 4178 | static void stac_store_hints(struct hda_codec *codec) |
| 4164 | { | 4179 | { |
| 4165 | struct sigmatel_spec *spec = codec->spec; | 4180 | struct sigmatel_spec *spec = codec->spec; |
| 4166 | const char *p; | ||
| 4167 | int val; | 4181 | int val; |
| 4168 | 4182 | ||
| 4169 | val = snd_hda_get_bool_hint(codec, "hp_detect"); | 4183 | val = snd_hda_get_bool_hint(codec, "hp_detect"); |
| 4170 | if (val >= 0) | 4184 | if (val >= 0) |
| 4171 | spec->hp_detect = val; | 4185 | spec->hp_detect = val; |
| 4172 | p = snd_hda_get_hint(codec, "gpio_mask"); | 4186 | if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) { |
| 4173 | if (p) { | ||
| 4174 | spec->gpio_mask = simple_strtoul(p, NULL, 0); | ||
| 4175 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = | 4187 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = |
| 4176 | spec->gpio_mask; | 4188 | spec->gpio_mask; |
| 4177 | } | 4189 | } |
| 4178 | p = snd_hda_get_hint(codec, "gpio_dir"); | 4190 | if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) |
| 4179 | if (p) | 4191 | spec->gpio_mask &= spec->gpio_mask; |
| 4180 | spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | 4192 | if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) |
| 4181 | p = snd_hda_get_hint(codec, "gpio_data"); | 4193 | spec->gpio_dir &= spec->gpio_mask; |
| 4182 | if (p) | 4194 | if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) |
| 4183 | spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | 4195 | spec->eapd_mask &= spec->gpio_mask; |
| 4184 | p = snd_hda_get_hint(codec, "eapd_mask"); | 4196 | if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) |
| 4185 | if (p) | 4197 | spec->gpio_mute &= spec->gpio_mask; |
| 4186 | spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
| 4187 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); | 4198 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); |
| 4188 | if (val >= 0) | 4199 | if (val >= 0) |
| 4189 | spec->eapd_switch = val; | 4200 | spec->eapd_switch = val; |
| 4201 | get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); | ||
| 4202 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { | ||
| 4203 | spec->gpio_mask |= spec->gpio_led; | ||
| 4204 | spec->gpio_dir |= spec->gpio_led; | ||
| 4205 | if (spec->gpio_led_polarity) | ||
| 4206 | spec->gpio_data |= spec->gpio_led; | ||
| 4207 | } | ||
| 4190 | } | 4208 | } |
| 4191 | 4209 | ||
| 4192 | static int stac92xx_init(struct hda_codec *codec) | 4210 | static int stac92xx_init(struct hda_codec *codec) |
| @@ -4371,18 +4389,8 @@ static void stac92xx_free_kctls(struct hda_codec *codec) | |||
| 4371 | static void stac92xx_shutup(struct hda_codec *codec) | 4389 | static void stac92xx_shutup(struct hda_codec *codec) |
| 4372 | { | 4390 | { |
| 4373 | struct sigmatel_spec *spec = codec->spec; | 4391 | struct sigmatel_spec *spec = codec->spec; |
| 4374 | int i; | ||
| 4375 | hda_nid_t nid; | ||
| 4376 | 4392 | ||
| 4377 | /* reset each pin before powering down DAC/ADC to avoid click noise */ | 4393 | snd_hda_shutup_pins(codec); |
| 4378 | nid = codec->start_nid; | ||
| 4379 | for (i = 0; i < codec->num_nodes; i++, nid++) { | ||
| 4380 | unsigned int wcaps = get_wcaps(codec, nid); | ||
| 4381 | unsigned int wid_type = get_wcaps_type(wcaps); | ||
| 4382 | if (wid_type == AC_WID_PIN) | ||
| 4383 | snd_hda_codec_read(codec, nid, 0, | ||
| 4384 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
| 4385 | } | ||
| 4386 | 4394 | ||
| 4387 | if (spec->eapd_mask) | 4395 | if (spec->eapd_mask) |
| 4388 | stac_gpio_set(codec, spec->gpio_mask, | 4396 | stac_gpio_set(codec, spec->gpio_mask, |
| @@ -5406,6 +5414,54 @@ static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | |||
| 5406 | return 0; | 5414 | return 0; |
| 5407 | } | 5415 | } |
| 5408 | 5416 | ||
| 5417 | /* HP dv7 bass switch - GPIO5 */ | ||
| 5418 | #define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info | ||
| 5419 | static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol, | ||
| 5420 | struct snd_ctl_elem_value *ucontrol) | ||
| 5421 | { | ||
| 5422 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 5423 | struct sigmatel_spec *spec = codec->spec; | ||
| 5424 | ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20); | ||
| 5425 | return 0; | ||
| 5426 | } | ||
| 5427 | |||
| 5428 | static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol, | ||
| 5429 | struct snd_ctl_elem_value *ucontrol) | ||
| 5430 | { | ||
| 5431 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 5432 | struct sigmatel_spec *spec = codec->spec; | ||
| 5433 | unsigned int gpio_data; | ||
| 5434 | |||
| 5435 | gpio_data = (spec->gpio_data & ~0x20) | | ||
| 5436 | (ucontrol->value.integer.value[0] ? 0x20 : 0); | ||
| 5437 | if (gpio_data == spec->gpio_data) | ||
| 5438 | return 0; | ||
| 5439 | spec->gpio_data = gpio_data; | ||
| 5440 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | ||
| 5441 | return 1; | ||
| 5442 | } | ||
| 5443 | |||
| 5444 | static struct snd_kcontrol_new stac_hp_bass_sw_ctrl = { | ||
| 5445 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 5446 | .info = stac_hp_bass_gpio_info, | ||
| 5447 | .get = stac_hp_bass_gpio_get, | ||
| 5448 | .put = stac_hp_bass_gpio_put, | ||
| 5449 | }; | ||
| 5450 | |||
| 5451 | static int stac_add_hp_bass_switch(struct hda_codec *codec) | ||
| 5452 | { | ||
| 5453 | struct sigmatel_spec *spec = codec->spec; | ||
| 5454 | |||
| 5455 | if (!stac_control_new(spec, &stac_hp_bass_sw_ctrl, | ||
| 5456 | "Bass Speaker Playback Switch", 0)) | ||
| 5457 | return -ENOMEM; | ||
| 5458 | |||
| 5459 | spec->gpio_mask |= 0x20; | ||
| 5460 | spec->gpio_dir |= 0x20; | ||
| 5461 | spec->gpio_data |= 0x20; | ||
| 5462 | return 0; | ||
| 5463 | } | ||
| 5464 | |||
| 5409 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 5465 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
| 5410 | { | 5466 | { |
| 5411 | struct sigmatel_spec *spec; | 5467 | struct sigmatel_spec *spec; |
| @@ -5646,6 +5702,15 @@ again: | |||
| 5646 | return err; | 5702 | return err; |
| 5647 | } | 5703 | } |
| 5648 | 5704 | ||
| 5705 | /* enable bass on HP dv7 */ | ||
| 5706 | if (spec->board_config == STAC_HP_DV5) { | ||
| 5707 | unsigned int cap; | ||
| 5708 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); | ||
| 5709 | cap &= AC_GPIO_IO_COUNT; | ||
| 5710 | if (cap >= 6) | ||
| 5711 | stac_add_hp_bass_switch(codec); | ||
| 5712 | } | ||
| 5713 | |||
| 5649 | codec->proc_widget_hook = stac92hd7x_proc_hook; | 5714 | codec->proc_widget_hook = stac92hd7x_proc_hook; |
| 5650 | 5715 | ||
| 5651 | return 0; | 5716 | return 0; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index de4839e46762..9ddc37300f6b 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
| @@ -1907,8 +1907,7 @@ static int via_build_controls(struct hda_codec *codec) | |||
| 1907 | /* assign Capture Source enums to NID */ | 1907 | /* assign Capture Source enums to NID */ |
| 1908 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); | 1908 | kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); |
| 1909 | for (i = 0; kctl && i < kctl->count; i++) { | 1909 | for (i = 0; kctl && i < kctl->count; i++) { |
| 1910 | err = snd_hda_add_nids(codec, kctl, i, spec->mux_nids, | 1910 | err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]); |
| 1911 | spec->input_mux->num_items); | ||
| 1912 | if (err < 0) | 1911 | if (err < 0) |
| 1913 | return err; | 1912 | return err; |
| 1914 | } | 1913 | } |
