Skip to content

Commit 3cf2890

Browse files
committed
Merge tag 'sound-fix-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull more sound updates from Takashi Iwai: "A few last-minute updates, most of them are the regression fixes: - AMD HD-audio HDMI runtime PM improvements - Fixes for HD-audio HDMI regressions wrt DP-MST - A regression fix for the previous aloop enhancement - A fix for a long-time problem in PCM OSS layer that was spotted by fuzzer now - A few HD-audio quirks" * tag 'sound-fix-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: pcm: oss: Avoid potential buffer overflows ALSA: hda: hdmi - Keep old slot assignment behavior for Intel platforms ALSA: hda: Modify stream stripe mask only when needed ALSA: hda - fixup for the bass speaker on Lenovo Carbon X1 7th gen ALSA: hda: hdmi - preserve non-MST PCM routing for Intel platforms ALSA: hda: hdmi - fix kernel oops caused by invalid PCM idx ALSA: hda/realtek - Fix inverted bass GPIO pin on Acer 8951G ALSA: hda/realtek - Dell headphone has noise on unmute for ALC236 ALSA: hda: hdmi - fix regression in connect list handling ALSA: aloop: Avoid pointer dereference before null-check ALSA: hda/hdmi - enable automatic runtime pm for AMD HDMI codecs by default ALSA: hda/hdmi - enable runtime pm for newer AMD display audio ALSA: hda/hdmi - Add new pci ids for AMD GPU display audio ALSA: hda/hdmi - fix vgaswitcheroo detection for AMD
2 parents ec05759 + 4cc8d65 commit 3cf2890

File tree

9 files changed

+154
-69
lines changed

9 files changed

+154
-69
lines changed

include/sound/hdaudio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ struct hdac_stream {
493493
bool prepared:1;
494494
bool no_period_wakeup:1;
495495
bool locked:1;
496+
bool stripe:1; /* apply stripe control */
496497

497498
/* timestamp */
498499
unsigned long start_wallclk; /* start + minimum wallclk */

sound/core/oss/linear.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
107107
}
108108
}
109109
#endif
110+
if (frames > dst_channels[0].frames)
111+
frames = dst_channels[0].frames;
110112
convert(plugin, src_channels, dst_channels, frames);
111113
return frames;
112114
}

sound/core/oss/mulaw.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
269269
}
270270
}
271271
#endif
272+
if (frames > dst_channels[0].frames)
273+
frames = dst_channels[0].frames;
272274
data = (struct mulaw_priv *)plugin->extra_data;
273275
data->func(plugin, src_channels, dst_channels, frames);
274276
return frames;

sound/core/oss/route.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
5757
return -ENXIO;
5858
if (frames == 0)
5959
return 0;
60+
if (frames > dst_channels[0].frames)
61+
frames = dst_channels[0].frames;
6062

6163
nsrcs = plugin->src_format.channels;
6264
ndsts = plugin->dst_format.channels;

sound/drivers/aloop.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -727,10 +727,6 @@ static void loopback_snd_timer_period_elapsed(struct loopback_cable *cable,
727727

728728
dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
729729
dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE];
730-
substream_play = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
731-
dpcm_play->substream : NULL;
732-
substream_capt = (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) ?
733-
dpcm_capt->substream : NULL;
734730

735731
if (event == SNDRV_TIMER_EVENT_MSTOP) {
736732
if (!dpcm_play ||
@@ -741,6 +737,10 @@ static void loopback_snd_timer_period_elapsed(struct loopback_cable *cable,
741737
}
742738
}
743739

740+
substream_play = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
741+
dpcm_play->substream : NULL;
742+
substream_capt = (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) ?
743+
dpcm_capt->substream : NULL;
744744
valid_runtime = (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
745745
dpcm_play->substream->runtime :
746746
dpcm_capt->substream->runtime;

sound/hda/hdac_stream.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,14 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
9696
1 << azx_dev->index,
9797
1 << azx_dev->index);
9898
/* set stripe control */
99-
if (azx_dev->substream)
100-
stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
101-
else
102-
stripe_ctl = 0;
103-
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
104-
stripe_ctl);
99+
if (azx_dev->stripe) {
100+
if (azx_dev->substream)
101+
stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
102+
else
103+
stripe_ctl = 0;
104+
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
105+
stripe_ctl);
106+
}
105107
/* set DMA start and interrupt mask */
106108
snd_hdac_stream_updateb(azx_dev, SD_CTL,
107109
0, SD_CTL_DMA_START | SD_INT_MASK);
@@ -118,7 +120,10 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
118120
snd_hdac_stream_updateb(azx_dev, SD_CTL,
119121
SD_CTL_DMA_START | SD_INT_MASK, 0);
120122
snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
121-
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
123+
if (azx_dev->stripe) {
124+
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
125+
azx_dev->stripe = 0;
126+
}
122127
azx_dev->running = false;
123128
}
124129
EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);

sound/pci/hda/hda_intel.c

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <linux/clocksource.h>
3636
#include <linux/time.h>
3737
#include <linux/completion.h>
38+
#include <linux/acpi.h>
3839

3940
#ifdef CONFIG_X86
4041
/* for snoop control */
@@ -1401,6 +1402,34 @@ static int azx_dev_free(struct snd_device *device)
14011402
}
14021403

14031404
#ifdef SUPPORT_VGA_SWITCHEROO
1405+
#ifdef CONFIG_ACPI
1406+
/* ATPX is in the integrated GPU's namespace */
1407+
static bool atpx_present(void)
1408+
{
1409+
struct pci_dev *pdev = NULL;
1410+
acpi_handle dhandle, atpx_handle;
1411+
acpi_status status;
1412+
1413+
while ((pdev = pci_get_class(PCI_BASE_CLASS_DISPLAY << 16, pdev)) != NULL) {
1414+
dhandle = ACPI_HANDLE(&pdev->dev);
1415+
if (dhandle) {
1416+
status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
1417+
if (!ACPI_FAILURE(status)) {
1418+
pci_dev_put(pdev);
1419+
return true;
1420+
}
1421+
}
1422+
pci_dev_put(pdev);
1423+
}
1424+
return false;
1425+
}
1426+
#else
1427+
static bool atpx_present(void)
1428+
{
1429+
return false;
1430+
}
1431+
#endif
1432+
14041433
/*
14051434
* Check of disabled HDMI controller by vga_switcheroo
14061435
*/
@@ -1412,6 +1441,22 @@ static struct pci_dev *get_bound_vga(struct pci_dev *pci)
14121441
switch (pci->vendor) {
14131442
case PCI_VENDOR_ID_ATI:
14141443
case PCI_VENDOR_ID_AMD:
1444+
if (pci->devfn == 1) {
1445+
p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
1446+
pci->bus->number, 0);
1447+
if (p) {
1448+
/* ATPX is in the integrated GPU's ACPI namespace
1449+
* rather than the dGPU's namespace. However,
1450+
* the dGPU is the one who is involved in
1451+
* vgaswitcheroo.
1452+
*/
1453+
if (((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
1454+
atpx_present())
1455+
return p;
1456+
pci_dev_put(p);
1457+
}
1458+
}
1459+
break;
14151460
case PCI_VENDOR_ID_NVIDIA:
14161461
if (pci->devfn == 1) {
14171462
p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
@@ -2547,13 +2592,38 @@ static const struct pci_device_id azx_ids[] = {
25472592
{ PCI_DEVICE(0x1002, 0xaac8),
25482593
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
25492594
{ PCI_DEVICE(0x1002, 0xaad8),
2550-
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2551-
{ PCI_DEVICE(0x1002, 0xaae8),
2552-
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2595+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2596+
AZX_DCAPS_PM_RUNTIME },
25532597
{ PCI_DEVICE(0x1002, 0xaae0),
2554-
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2598+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2599+
AZX_DCAPS_PM_RUNTIME },
2600+
{ PCI_DEVICE(0x1002, 0xaae8),
2601+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2602+
AZX_DCAPS_PM_RUNTIME },
25552603
{ PCI_DEVICE(0x1002, 0xaaf0),
2556-
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
2604+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2605+
AZX_DCAPS_PM_RUNTIME },
2606+
{ PCI_DEVICE(0x1002, 0xaaf8),
2607+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2608+
AZX_DCAPS_PM_RUNTIME },
2609+
{ PCI_DEVICE(0x1002, 0xab00),
2610+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2611+
AZX_DCAPS_PM_RUNTIME },
2612+
{ PCI_DEVICE(0x1002, 0xab08),
2613+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2614+
AZX_DCAPS_PM_RUNTIME },
2615+
{ PCI_DEVICE(0x1002, 0xab10),
2616+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2617+
AZX_DCAPS_PM_RUNTIME },
2618+
{ PCI_DEVICE(0x1002, 0xab18),
2619+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2620+
AZX_DCAPS_PM_RUNTIME },
2621+
{ PCI_DEVICE(0x1002, 0xab20),
2622+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2623+
AZX_DCAPS_PM_RUNTIME },
2624+
{ PCI_DEVICE(0x1002, 0xab38),
2625+
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
2626+
AZX_DCAPS_PM_RUNTIME },
25572627
/* VIA VT8251/VT8237A */
25582628
{ PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
25592629
/* VIA GFX VT7122/VX900 */

sound/pci/hda/patch_hdmi.c

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <sound/hda_codec.h>
3333
#include "hda_local.h"
3434
#include "hda_jack.h"
35+
#include "hda_controller.h"
3536

3637
static bool static_hdmi_pcm;
3738
module_param(static_hdmi_pcm, bool, 0644);
@@ -1249,6 +1250,10 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
12491250
per_pin->cvt_nid = per_cvt->cvt_nid;
12501251
hinfo->nid = per_cvt->cvt_nid;
12511252

1253+
/* flip stripe flag for the assigned stream if supported */
1254+
if (get_wcaps(codec, per_cvt->cvt_nid) & AC_WCAP_STRIPE)
1255+
azx_stream(get_azx_dev(substream))->stripe = 1;
1256+
12521257
snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id);
12531258
snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
12541259
AC_VERB_SET_CONNECT_SEL,
@@ -1302,6 +1307,7 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
13021307
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
13031308
hda_nid_t pin_nid = per_pin->pin_nid;
13041309
int dev_id = per_pin->dev_id;
1310+
int conns;
13051311

13061312
if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
13071313
codec_warn(codec,
@@ -1312,10 +1318,18 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
13121318

13131319
snd_hda_set_dev_select(codec, pin_nid, dev_id);
13141320

1321+
if (spec->intel_hsw_fixup) {
1322+
conns = spec->num_cvts;
1323+
memcpy(per_pin->mux_nids, spec->cvt_nids,
1324+
sizeof(hda_nid_t) * conns);
1325+
} else {
1326+
conns = snd_hda_get_raw_connections(codec, pin_nid,
1327+
per_pin->mux_nids,
1328+
HDA_MAX_CONNECTIONS);
1329+
}
1330+
13151331
/* all the device entries on the same pin have the same conn list */
1316-
per_pin->num_mux_nids =
1317-
snd_hda_get_raw_connections(codec, pin_nid, per_pin->mux_nids,
1318-
HDA_MAX_CONNECTIONS);
1332+
per_pin->num_mux_nids = conns;
13191333

13201334
return 0;
13211335
}
@@ -1326,24 +1340,26 @@ static int hdmi_find_pcm_slot(struct hdmi_spec *spec,
13261340
int i;
13271341

13281342
/*
1329-
* generic_hdmi_build_pcms() allocates (num_nids + dev_num - 1)
1330-
* number of pcms.
1343+
* generic_hdmi_build_pcms() may allocate extra PCMs on some
1344+
* platforms (with maximum of 'num_nids + dev_num - 1')
13311345
*
13321346
* The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n
13331347
* if m==0. This guarantees that dynamic pcm assignments are compatible
1334-
* with the legacy static per_pin-pmc assignment that existed in the
1348+
* with the legacy static per_pin-pcm assignment that existed in the
13351349
* days before DP-MST.
13361350
*
1351+
* Intel DP-MST prefers this legacy behavior for compatibility, too.
1352+
*
13371353
* per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)).
13381354
*/
1339-
if (per_pin->dev_id == 0 &&
1340-
!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap))
1341-
return per_pin->pin_nid_idx;
1342-
1343-
if (per_pin->dev_id != 0 &&
1344-
!(test_bit(spec->num_nids + (per_pin->dev_id - 1),
1345-
&spec->pcm_bitmap))) {
1346-
return spec->num_nids + (per_pin->dev_id - 1);
1355+
1356+
if (per_pin->dev_id == 0 || spec->intel_hsw_fixup) {
1357+
if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap))
1358+
return per_pin->pin_nid_idx;
1359+
} else {
1360+
i = spec->num_nids + (per_pin->dev_id - 1);
1361+
if (i < spec->pcm_used && !(test_bit(i, &spec->pcm_bitmap)))
1362+
return i;
13471363
}
13481364

13491365
/* have a second try; check the area over num_nids */
@@ -1713,9 +1729,6 @@ static void hdmi_repoll_eld(struct work_struct *work)
17131729
mutex_unlock(&spec->pcm_lock);
17141730
}
17151731

1716-
static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
1717-
hda_nid_t nid);
1718-
17191732
static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
17201733
{
17211734
struct hdmi_spec *spec = codec->spec;
@@ -1790,8 +1803,6 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
17901803
per_pin->dev_id = i;
17911804
per_pin->non_pcm = false;
17921805
snd_hda_set_dev_select(codec, pin_nid, i);
1793-
if (spec->intel_hsw_fixup)
1794-
intel_haswell_fixup_connect_list(codec, pin_nid);
17951806
err = hdmi_read_pin_conn(codec, pin_idx);
17961807
if (err < 0)
17971808
return err;
@@ -2603,24 +2614,6 @@ static void generic_acomp_init(struct hda_codec *codec,
26032614
* Intel codec parsers and helpers
26042615
*/
26052616

2606-
static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
2607-
hda_nid_t nid)
2608-
{
2609-
struct hdmi_spec *spec = codec->spec;
2610-
hda_nid_t conns[4];
2611-
int nconns;
2612-
2613-
nconns = snd_hda_get_raw_connections(codec, nid, conns,
2614-
ARRAY_SIZE(conns));
2615-
if (nconns == spec->num_cvts &&
2616-
!memcmp(conns, spec->cvt_nids, spec->num_cvts * sizeof(hda_nid_t)))
2617-
return;
2618-
2619-
/* override pins connection list */
2620-
codec_dbg(codec, "hdmi: haswell: override pin connection 0x%x\n", nid);
2621-
snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids);
2622-
}
2623-
26242617
#define INTEL_GET_VENDOR_VERB 0xf81
26252618
#define INTEL_SET_VENDOR_VERB 0x781
26262619
#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
@@ -4063,6 +4056,7 @@ static int atihdmi_init(struct hda_codec *codec)
40634056
ATI_VERB_SET_MULTICHANNEL_MODE,
40644057
ATI_MULTICHANNEL_MODE_SINGLE);
40654058
}
4059+
codec->auto_runtime_pm = 1;
40664060

40674061
return 0;
40684062
}

0 commit comments

Comments
 (0)