diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-22 13:17:18 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-22 13:17:18 -0400 |
| commit | d4b05288271040217c46440a1dc246357ac301d2 (patch) | |
| tree | f4f6ec02301255a492b72be36a5e767eb7125ff4 | |
| parent | 5f44abd041c5f3be76d57579ab254d78e601315b (diff) | |
| parent | 3194ed497939c6448005542e3ca4fa2386968fa0 (diff) | |
Merge tag 'sound-4.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"Again a relatively calm week without surprise: most of fixes are about
HD-audio, including fixes for Cirrus codec regression and a race over
regmap access. Although both change are slightly unintuitive, the
risk of further breakage is quite low, I hope.
Other than that, all the rest are trivial"
* tag 'sound-4.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: hda - Fix possible race on regmap bypass flip
ALSA: pcxhr: Fix missing mutex unlock
ALSA: hda - add PCI ID for Intel Broxton-T
ALSA: hda - Keep powering up ADCs on Cirrus codecs
ALSA: hda/realtek - Add ALC3234 headset mode for Optiplex 9020m
ALSA - hda: hdmi check NULL pointer in hdmi_set_chmap
ALSA: hda - Don't trust the reported actual power state
| -rw-r--r-- | include/sound/hda_regmap.h | 2 | ||||
| -rw-r--r-- | sound/hda/hdac_device.c | 10 | ||||
| -rw-r--r-- | sound/hda/hdac_regmap.c | 40 | ||||
| -rw-r--r-- | sound/pci/hda/hda_generic.c | 6 | ||||
| -rw-r--r-- | sound/pci/hda/hda_intel.c | 3 | ||||
| -rw-r--r-- | sound/pci/hda/patch_cirrus.c | 14 | ||||
| -rw-r--r-- | sound/pci/hda/patch_hdmi.c | 2 | ||||
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 1 | ||||
| -rw-r--r-- | sound/pci/pcxhr/pcxhr_core.c | 1 |
9 files changed, 59 insertions, 20 deletions
diff --git a/include/sound/hda_regmap.h b/include/sound/hda_regmap.h index 2767c55a641e..ca64f0f50b45 100644 --- a/include/sound/hda_regmap.h +++ b/include/sound/hda_regmap.h | |||
| @@ -17,6 +17,8 @@ int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec, | |||
| 17 | unsigned int verb); | 17 | unsigned int verb); |
| 18 | int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, | 18 | int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, |
| 19 | unsigned int *val); | 19 | unsigned int *val); |
| 20 | int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec, | ||
| 21 | unsigned int reg, unsigned int *val); | ||
| 20 | int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg, | 22 | int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg, |
| 21 | unsigned int val); | 23 | unsigned int val); |
| 22 | int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg, | 24 | int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg, |
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index d1a4d6973330..03c9872c31cf 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c | |||
| @@ -299,13 +299,11 @@ EXPORT_SYMBOL_GPL(_snd_hdac_read_parm); | |||
| 299 | int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, | 299 | int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, |
| 300 | int parm) | 300 | int parm) |
| 301 | { | 301 | { |
| 302 | int val; | 302 | unsigned int cmd, val; |
| 303 | 303 | ||
| 304 | if (codec->regmap) | 304 | cmd = snd_hdac_regmap_encode_verb(nid, AC_VERB_PARAMETERS) | parm; |
| 305 | regcache_cache_bypass(codec->regmap, true); | 305 | if (snd_hdac_regmap_read_raw_uncached(codec, cmd, &val) < 0) |
| 306 | val = snd_hdac_read_parm(codec, nid, parm); | 306 | return -1; |
| 307 | if (codec->regmap) | ||
| 308 | regcache_cache_bypass(codec->regmap, false); | ||
| 309 | return val; | 307 | return val; |
| 310 | } | 308 | } |
| 311 | EXPORT_SYMBOL_GPL(snd_hdac_read_parm_uncached); | 309 | EXPORT_SYMBOL_GPL(snd_hdac_read_parm_uncached); |
diff --git a/sound/hda/hdac_regmap.c b/sound/hda/hdac_regmap.c index bdbcd6b75ff6..87041ddd29cb 100644 --- a/sound/hda/hdac_regmap.c +++ b/sound/hda/hdac_regmap.c | |||
| @@ -453,14 +453,30 @@ int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg, | |||
| 453 | EXPORT_SYMBOL_GPL(snd_hdac_regmap_write_raw); | 453 | EXPORT_SYMBOL_GPL(snd_hdac_regmap_write_raw); |
| 454 | 454 | ||
| 455 | static int reg_raw_read(struct hdac_device *codec, unsigned int reg, | 455 | static int reg_raw_read(struct hdac_device *codec, unsigned int reg, |
| 456 | unsigned int *val) | 456 | unsigned int *val, bool uncached) |
| 457 | { | 457 | { |
| 458 | if (!codec->regmap) | 458 | if (uncached || !codec->regmap) |
| 459 | return hda_reg_read(codec, reg, val); | 459 | return hda_reg_read(codec, reg, val); |
| 460 | else | 460 | else |
| 461 | return regmap_read(codec->regmap, reg, val); | 461 | return regmap_read(codec->regmap, reg, val); |
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | static int __snd_hdac_regmap_read_raw(struct hdac_device *codec, | ||
| 465 | unsigned int reg, unsigned int *val, | ||
| 466 | bool uncached) | ||
| 467 | { | ||
| 468 | int err; | ||
| 469 | |||
| 470 | err = reg_raw_read(codec, reg, val, uncached); | ||
| 471 | if (err == -EAGAIN) { | ||
| 472 | err = snd_hdac_power_up_pm(codec); | ||
| 473 | if (!err) | ||
| 474 | err = reg_raw_read(codec, reg, val, uncached); | ||
| 475 | snd_hdac_power_down_pm(codec); | ||
| 476 | } | ||
| 477 | return err; | ||
| 478 | } | ||
| 479 | |||
| 464 | /** | 480 | /** |
| 465 | * snd_hdac_regmap_read_raw - read a pseudo register with power mgmt | 481 | * snd_hdac_regmap_read_raw - read a pseudo register with power mgmt |
| 466 | * @codec: the codec object | 482 | * @codec: the codec object |
| @@ -472,19 +488,19 @@ static int reg_raw_read(struct hdac_device *codec, unsigned int reg, | |||
| 472 | int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, | 488 | int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, |
| 473 | unsigned int *val) | 489 | unsigned int *val) |
| 474 | { | 490 | { |
| 475 | int err; | 491 | return __snd_hdac_regmap_read_raw(codec, reg, val, false); |
| 476 | |||
| 477 | err = reg_raw_read(codec, reg, val); | ||
| 478 | if (err == -EAGAIN) { | ||
| 479 | err = snd_hdac_power_up_pm(codec); | ||
| 480 | if (!err) | ||
| 481 | err = reg_raw_read(codec, reg, val); | ||
| 482 | snd_hdac_power_down_pm(codec); | ||
| 483 | } | ||
| 484 | return err; | ||
| 485 | } | 492 | } |
| 486 | EXPORT_SYMBOL_GPL(snd_hdac_regmap_read_raw); | 493 | EXPORT_SYMBOL_GPL(snd_hdac_regmap_read_raw); |
| 487 | 494 | ||
| 495 | /* Works like snd_hdac_regmap_read_raw(), but this doesn't read from the | ||
| 496 | * cache but always via hda verbs. | ||
| 497 | */ | ||
| 498 | int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec, | ||
| 499 | unsigned int reg, unsigned int *val) | ||
| 500 | { | ||
| 501 | return __snd_hdac_regmap_read_raw(codec, reg, val, true); | ||
| 502 | } | ||
| 503 | |||
| 488 | /** | 504 | /** |
| 489 | * snd_hdac_regmap_update_raw - update a pseudo register with power mgmt | 505 | * snd_hdac_regmap_update_raw - update a pseudo register with power mgmt |
| 490 | * @codec: the codec object | 506 | * @codec: the codec object |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 7ca5b89f088a..dfaf1a93fb8a 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
| @@ -826,7 +826,7 @@ static hda_nid_t path_power_update(struct hda_codec *codec, | |||
| 826 | bool allow_powerdown) | 826 | bool allow_powerdown) |
| 827 | { | 827 | { |
| 828 | hda_nid_t nid, changed = 0; | 828 | hda_nid_t nid, changed = 0; |
| 829 | int i, state; | 829 | int i, state, power; |
| 830 | 830 | ||
| 831 | for (i = 0; i < path->depth; i++) { | 831 | for (i = 0; i < path->depth; i++) { |
| 832 | nid = path->path[i]; | 832 | nid = path->path[i]; |
| @@ -838,7 +838,9 @@ static hda_nid_t path_power_update(struct hda_codec *codec, | |||
| 838 | state = AC_PWRST_D0; | 838 | state = AC_PWRST_D0; |
| 839 | else | 839 | else |
| 840 | state = AC_PWRST_D3; | 840 | state = AC_PWRST_D3; |
| 841 | if (!snd_hda_check_power_state(codec, nid, state)) { | 841 | power = snd_hda_codec_read(codec, nid, 0, |
| 842 | AC_VERB_GET_POWER_STATE, 0); | ||
| 843 | if (power != (state | (state << 4))) { | ||
| 842 | snd_hda_codec_write(codec, nid, 0, | 844 | snd_hda_codec_write(codec, nid, 0, |
| 843 | AC_VERB_SET_POWER_STATE, state); | 845 | AC_VERB_SET_POWER_STATE, state); |
| 844 | changed = nid; | 846 | changed = nid; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b680be0e937d..637b8a0e2a91 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -2232,6 +2232,9 @@ static const struct pci_device_id azx_ids[] = { | |||
| 2232 | /* Broxton-P(Apollolake) */ | 2232 | /* Broxton-P(Apollolake) */ |
| 2233 | { PCI_DEVICE(0x8086, 0x5a98), | 2233 | { PCI_DEVICE(0x8086, 0x5a98), |
| 2234 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, | 2234 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, |
| 2235 | /* Broxton-T */ | ||
| 2236 | { PCI_DEVICE(0x8086, 0x1a98), | ||
| 2237 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, | ||
| 2235 | /* Haswell */ | 2238 | /* Haswell */ |
| 2236 | { PCI_DEVICE(0x8086, 0x0a0c), | 2239 | { PCI_DEVICE(0x8086, 0x0a0c), |
| 2237 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, | 2240 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index a47e8ae0eb30..80bbadc83721 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
| @@ -361,6 +361,7 @@ static int cs_parse_auto_config(struct hda_codec *codec) | |||
| 361 | { | 361 | { |
| 362 | struct cs_spec *spec = codec->spec; | 362 | struct cs_spec *spec = codec->spec; |
| 363 | int err; | 363 | int err; |
| 364 | int i; | ||
| 364 | 365 | ||
| 365 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); | 366 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); |
| 366 | if (err < 0) | 367 | if (err < 0) |
| @@ -370,6 +371,19 @@ static int cs_parse_auto_config(struct hda_codec *codec) | |||
| 370 | if (err < 0) | 371 | if (err < 0) |
| 371 | return err; | 372 | return err; |
| 372 | 373 | ||
| 374 | /* keep the ADCs powered up when it's dynamically switchable */ | ||
| 375 | if (spec->gen.dyn_adc_switch) { | ||
| 376 | unsigned int done = 0; | ||
| 377 | for (i = 0; i < spec->gen.input_mux.num_items; i++) { | ||
| 378 | int idx = spec->gen.dyn_adc_idx[i]; | ||
| 379 | if (done & (1 << idx)) | ||
| 380 | continue; | ||
| 381 | snd_hda_gen_fix_pin_power(codec, | ||
| 382 | spec->gen.adc_nids[idx]); | ||
| 383 | done |= 1 << idx; | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 373 | return 0; | 387 | return 0; |
| 374 | } | 388 | } |
| 375 | 389 | ||
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c83c1a8d9742..40933aa33afe 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
| @@ -1858,6 +1858,8 @@ static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, | |||
| 1858 | struct hdmi_spec *spec = codec->spec; | 1858 | struct hdmi_spec *spec = codec->spec; |
| 1859 | struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); | 1859 | struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); |
| 1860 | 1860 | ||
| 1861 | if (!per_pin) | ||
| 1862 | return; | ||
| 1861 | mutex_lock(&per_pin->lock); | 1863 | mutex_lock(&per_pin->lock); |
| 1862 | per_pin->chmap_set = true; | 1864 | per_pin->chmap_set = true; |
| 1863 | memcpy(per_pin->chmap, chmap, ARRAY_SIZE(per_pin->chmap)); | 1865 | memcpy(per_pin->chmap, chmap, ARRAY_SIZE(per_pin->chmap)); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1402ba954b3d..810bceee4fd2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -5449,6 +5449,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
| 5449 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 5449 | SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
| 5450 | SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 5450 | SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
| 5451 | SND_PCI_QUIRK(0x1028, 0x0665, "Dell XPS 13", ALC288_FIXUP_DELL_XPS_13), | 5451 | SND_PCI_QUIRK(0x1028, 0x0665, "Dell XPS 13", ALC288_FIXUP_DELL_XPS_13), |
| 5452 | SND_PCI_QUIRK(0x1028, 0x0669, "Dell Optiplex 9020m", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
| 5452 | SND_PCI_QUIRK(0x1028, 0x069a, "Dell Vostro 5480", ALC290_FIXUP_SUBWOOFER_HSJACK), | 5453 | SND_PCI_QUIRK(0x1028, 0x069a, "Dell Vostro 5480", ALC290_FIXUP_SUBWOOFER_HSJACK), |
| 5453 | SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), | 5454 | SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), |
| 5454 | SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), | 5455 | SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c index c5194f5b150a..d7e71f309299 100644 --- a/sound/pci/pcxhr/pcxhr_core.c +++ b/sound/pci/pcxhr/pcxhr_core.c | |||
| @@ -1341,5 +1341,6 @@ irqreturn_t pcxhr_threaded_irq(int irq, void *dev_id) | |||
| 1341 | } | 1341 | } |
| 1342 | 1342 | ||
| 1343 | pcxhr_msg_thread(mgr); | 1343 | pcxhr_msg_thread(mgr); |
| 1344 | mutex_unlock(&mgr->lock); | ||
| 1344 | return IRQ_HANDLED; | 1345 | return IRQ_HANDLED; |
| 1345 | } | 1346 | } |
