Skip to content

Commit 4f143ec

Browse files
committed
ASoC: Intel: Skylake: Topology and shutdown fixes
Merge series from Cezary Rojewski <[email protected]>: Even though skylake-driver is going to be replaced by the avs-driver, the goal is to keep it functional on all the configurations it supports until its EOL. When comparing chrome trees against upstream skylake-driver, couple fixes pop up that are not part of upstream repository. These fixes are backed up by real bugs (issue trackers), address real problems. There is no reason for them to stay in the internal tree. Patches 1-4 combined together address issue where the driver updates the presumably static audio format descriptions coming from the topology files through its "fixup" functions. As long as given audio format is used by a single path, nothing collides and any updates are harmless. However, when multiple paths e.g.: DMIC and HDMI1 utilize the same audio format descriptor, any updates caused by the opening of the first path, may cause the second to fail. The 5th change from the set fixes driver hang sporadically occurring during shutdown procedure. Once HDAudio links are powered down along with the AudioDSP, the hang stops reproducing. The last change helps survive in environments with limited/fragmented memory. While the BDL is small already, other buffers can be allocated using scatter-gather. This basically aligns the code with what the avs-driver does.
2 parents 38eef3b + 451d85c commit 4f143ec

File tree

4 files changed

+44
-62
lines changed

4 files changed

+44
-62
lines changed

sound/soc/intel/skylake/skl-sst-cldma.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/io.h>
1212
#include <linux/mm.h>
1313
#include <linux/delay.h>
14+
#include <sound/hda_register.h>
1415
#include "../common/sst-dsp.h"
1516
#include "../common/sst-dsp-priv.h"
1617

@@ -79,21 +80,25 @@ static void skl_cldma_setup_bdle(struct sst_dsp *ctx,
7980
__le32 **bdlp, int size, int with_ioc)
8081
{
8182
__le32 *bdl = *bdlp;
83+
int remaining = ctx->cl_dev.bufsize;
84+
int offset = 0;
8285

8386
ctx->cl_dev.frags = 0;
84-
while (size > 0) {
85-
phys_addr_t addr = virt_to_phys(dmab_data->area +
86-
(ctx->cl_dev.frags * ctx->cl_dev.bufsize));
87+
while (remaining > 0) {
88+
phys_addr_t addr;
89+
int chunk;
8790

91+
addr = snd_sgbuf_get_addr(dmab_data, offset);
8892
bdl[0] = cpu_to_le32(lower_32_bits(addr));
8993
bdl[1] = cpu_to_le32(upper_32_bits(addr));
94+
chunk = snd_sgbuf_get_chunk_size(dmab_data, offset, size);
95+
bdl[2] = cpu_to_le32(chunk);
9096

91-
bdl[2] = cpu_to_le32(ctx->cl_dev.bufsize);
92-
93-
size -= ctx->cl_dev.bufsize;
94-
bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01);
97+
remaining -= chunk;
98+
bdl[3] = (remaining > 0) ? 0 : cpu_to_le32(0x01);
9599

96100
bdl += 4;
101+
offset += chunk;
97102
ctx->cl_dev.frags++;
98103
}
99104
}
@@ -338,15 +343,15 @@ int skl_cldma_prepare(struct sst_dsp *ctx)
338343
ctx->cl_dev.ops.cl_stop_dma = skl_cldma_stop;
339344

340345
/* Allocate buffer*/
341-
ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev,
342-
&ctx->cl_dev.dmab_data, ctx->cl_dev.bufsize);
346+
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, ctx->dev, ctx->cl_dev.bufsize,
347+
&ctx->cl_dev.dmab_data);
343348
if (ret < 0) {
344349
dev_err(ctx->dev, "Alloc buffer for base fw failed: %x\n", ret);
345350
return ret;
346351
}
352+
347353
/* Setup Code loader BDL */
348-
ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev,
349-
&ctx->cl_dev.dmab_bdl, PAGE_SIZE);
354+
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, ctx->dev, BDL_SIZE, &ctx->cl_dev.dmab_bdl);
350355
if (ret < 0) {
351356
dev_err(ctx->dev, "Alloc buffer for blde failed: %x\n", ret);
352357
ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data);

sound/soc/intel/skylake/skl-topology.c

Lines changed: 24 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -582,36 +582,10 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl,
582582
return ret;
583583
}
584584

585-
static bool skl_tplg_is_multi_fmt(struct skl_dev *skl, struct skl_pipe *pipe)
585+
static void skl_tplg_set_pipe_config_idx(struct skl_pipe *pipe, int idx)
586586
{
587-
struct skl_pipe_fmt *cur_fmt;
588-
struct skl_pipe_fmt *next_fmt;
589-
int i;
590-
591-
if (pipe->nr_cfgs <= 1)
592-
return false;
593-
594-
if (pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
595-
return true;
596-
597-
for (i = 0; i < pipe->nr_cfgs - 1; i++) {
598-
if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) {
599-
cur_fmt = &pipe->configs[i].out_fmt;
600-
next_fmt = &pipe->configs[i + 1].out_fmt;
601-
} else {
602-
cur_fmt = &pipe->configs[i].in_fmt;
603-
next_fmt = &pipe->configs[i + 1].in_fmt;
604-
}
605-
606-
if (!CHECK_HW_PARAMS(cur_fmt->channels, cur_fmt->freq,
607-
cur_fmt->bps,
608-
next_fmt->channels,
609-
next_fmt->freq,
610-
next_fmt->bps))
611-
return true;
612-
}
613-
614-
return false;
587+
pipe->cur_config_idx = idx;
588+
pipe->memory_pages = pipe->configs[idx].mem_pages;
615589
}
616590

617591
/*
@@ -632,24 +606,14 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig)
632606
int i;
633607

634608
if (pipe->nr_cfgs == 0) {
635-
pipe->cur_config_idx = 0;
636-
return 0;
637-
}
638-
639-
if (skl_tplg_is_multi_fmt(skl, pipe)) {
640-
pipe->cur_config_idx = pipe->pipe_config_idx;
641-
pipe->memory_pages = pconfig->mem_pages;
642-
dev_dbg(skl->dev, "found pipe config idx:%d\n",
643-
pipe->cur_config_idx);
609+
skl_tplg_set_pipe_config_idx(pipe, 0);
644610
return 0;
645611
}
646612

647613
if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE || pipe->nr_cfgs == 1) {
648614
dev_dbg(skl->dev, "No conn_type or just 1 pathcfg, taking 0th for %d\n",
649615
pipe->ppl_id);
650-
pipe->cur_config_idx = 0;
651-
pipe->memory_pages = pconfig->mem_pages;
652-
616+
skl_tplg_set_pipe_config_idx(pipe, 0);
653617
return 0;
654618
}
655619

@@ -668,10 +632,8 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig)
668632

669633
if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt,
670634
fmt->channels, fmt->freq, fmt->bps)) {
671-
pipe->cur_config_idx = i;
672-
pipe->memory_pages = pconfig->mem_pages;
635+
skl_tplg_set_pipe_config_idx(pipe, i);
673636
dev_dbg(skl->dev, "Using pipe config: %d\n", i);
674-
675637
return 0;
676638
}
677639
}
@@ -1391,9 +1353,9 @@ static int skl_tplg_multi_config_set_get(struct snd_kcontrol *kcontrol,
13911353
return -EIO;
13921354

13931355
if (is_set)
1394-
pipe->pipe_config_idx = ucontrol->value.enumerated.item[0];
1356+
skl_tplg_set_pipe_config_idx(pipe, ucontrol->value.enumerated.item[0]);
13951357
else
1396-
ucontrol->value.enumerated.item[0] = pipe->pipe_config_idx;
1358+
ucontrol->value.enumerated.item[0] = pipe->cur_config_idx;
13971359

13981360
return 0;
13991361
}
@@ -1837,20 +1799,28 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
18371799
{
18381800
struct nhlt_specific_cfg *cfg;
18391801
struct skl_pipe *pipe = mconfig->pipe;
1802+
struct skl_pipe_params save = *pipe->p_params;
18401803
struct skl_pipe_fmt *pipe_fmt;
18411804
struct skl_dev *skl = get_skl_ctx(dai->dev);
18421805
int link_type = skl_tplg_be_link_type(mconfig->dev_type);
18431806
u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type);
1807+
int ret;
18441808

18451809
skl_tplg_fill_dma_id(mconfig, params);
18461810

18471811
if (link_type == NHLT_LINK_HDA)
18481812
return 0;
18491813

1814+
*pipe->p_params = *params;
1815+
ret = skl_tplg_get_pipe_config(skl, mconfig);
1816+
if (ret)
1817+
goto err;
1818+
1819+
dev_dbg(skl->dev, "%s using pipe config: %d\n", __func__, pipe->cur_config_idx);
18501820
if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK)
1851-
pipe_fmt = &pipe->configs[pipe->pipe_config_idx].out_fmt;
1821+
pipe_fmt = &pipe->configs[pipe->cur_config_idx].out_fmt;
18521822
else
1853-
pipe_fmt = &pipe->configs[pipe->pipe_config_idx].in_fmt;
1823+
pipe_fmt = &pipe->configs[pipe->cur_config_idx].in_fmt;
18541824

18551825
/* update the blob based on virtual bus_id*/
18561826
cfg = intel_nhlt_get_endpoint_blob(dai->dev, skl->nhlt,
@@ -1865,10 +1835,15 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
18651835
dev_err(dai->dev, "Blob NULL for id:%d type:%d dirn:%d ch:%d, freq:%d, fmt:%d\n",
18661836
mconfig->vbus_id, link_type, params->stream,
18671837
params->ch, params->s_freq, params->s_fmt);
1868-
return -EINVAL;
1838+
ret = -EINVAL;
1839+
goto err;
18691840
}
18701841

18711842
return 0;
1843+
1844+
err:
1845+
*pipe->p_params = save;
1846+
return ret;
18721847
}
18731848

18741849
static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai,

sound/soc/intel/skylake/skl-topology.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,6 @@ struct skl_pipe {
324324
struct skl_path_config configs[SKL_MAX_PATH_CONFIGS];
325325
struct list_head w_list;
326326
bool passthru;
327-
u32 pipe_config_idx;
328327
};
329328

330329
enum skl_module_state {

sound/soc/intel/skylake/skl.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,10 @@ static void skl_shutdown(struct pci_dev *pci)
11071107
if (!skl->init_done)
11081108
return;
11091109

1110-
snd_hdac_stop_streams_and_chip(bus);
1110+
snd_hdac_stop_streams(bus);
1111+
snd_hdac_ext_bus_link_power_down_all(bus);
1112+
skl_dsp_sleep(skl->dsp);
1113+
11111114
list_for_each_entry(s, &bus->stream_list, list) {
11121115
stream = stream_to_hdac_ext_stream(s);
11131116
snd_hdac_ext_stream_decouple(bus, stream, false);

0 commit comments

Comments
 (0)