aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-04-22 13:17:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-04-22 13:17:18 -0400
commitd4b05288271040217c46440a1dc246357ac301d2 (patch)
treef4f6ec02301255a492b72be36a5e767eb7125ff4
parent5f44abd041c5f3be76d57579ab254d78e601315b (diff)
parent3194ed497939c6448005542e3ca4fa2386968fa0 (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.h2
-rw-r--r--sound/hda/hdac_device.c10
-rw-r--r--sound/hda/hdac_regmap.c40
-rw-r--r--sound/pci/hda/hda_generic.c6
-rw-r--r--sound/pci/hda/hda_intel.c3
-rw-r--r--sound/pci/hda/patch_cirrus.c14
-rw-r--r--sound/pci/hda/patch_hdmi.c2
-rw-r--r--sound/pci/hda/patch_realtek.c1
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c1
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);
18int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, 18int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg,
19 unsigned int *val); 19 unsigned int *val);
20int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec,
21 unsigned int reg, unsigned int *val);
20int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg, 22int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
21 unsigned int val); 23 unsigned int val);
22int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg, 24int 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);
299int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, 299int 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}
311EXPORT_SYMBOL_GPL(snd_hdac_read_parm_uncached); 309EXPORT_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,
453EXPORT_SYMBOL_GPL(snd_hdac_regmap_write_raw); 453EXPORT_SYMBOL_GPL(snd_hdac_regmap_write_raw);
454 454
455static int reg_raw_read(struct hdac_device *codec, unsigned int reg, 455static 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
464static 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,
472int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg, 488int 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}
486EXPORT_SYMBOL_GPL(snd_hdac_regmap_read_raw); 493EXPORT_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 */
498int 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}