ASoC: Intel: Skylake: Correct the handling of fmt_config flexible array
[ Upstream commit fc976f5629afb4160ee77798b14a693eac903ffd ] The struct nhlt_format's fmt_config is a flexible array, it must not be used as normal array. When moving to the next nhlt_fmt_cfg we need to take into account the data behind the ->config.caps (indicated by ->config.size). The logic of the code also changed: it is no longer saves the _last_ fmt_cfg for all found rates. Fixes: bc2bd45b1f7f3 ("ASoC: Intel: Skylake: Parse nhlt and register clock device") Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://lore.kernel.org/r/20220630065638.11183-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
0d083ea282
commit
750a5e2e53
@ -213,11 +213,12 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
|
||||
if (fmt->fmt_count == 0)
|
||||
return;
|
||||
|
||||
fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config;
|
||||
for (i = 0; i < fmt->fmt_count; i++) {
|
||||
struct nhlt_fmt_cfg *saved_fmt_cfg = fmt_cfg;
|
||||
bool present = false;
|
||||
|
||||
fmt_cfg = &fmt->fmt_config[i];
|
||||
wav_fmt = &fmt_cfg->fmt_ext;
|
||||
wav_fmt = &saved_fmt_cfg->fmt_ext;
|
||||
|
||||
channels = wav_fmt->fmt.channels;
|
||||
bps = wav_fmt->fmt.bits_per_sample;
|
||||
@ -235,12 +236,18 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
|
||||
* derive the rate.
|
||||
*/
|
||||
for (j = i; j < fmt->fmt_count; j++) {
|
||||
fmt_cfg = &fmt->fmt_config[j];
|
||||
wav_fmt = &fmt_cfg->fmt_ext;
|
||||
struct nhlt_fmt_cfg *tmp_fmt_cfg = fmt_cfg;
|
||||
|
||||
wav_fmt = &tmp_fmt_cfg->fmt_ext;
|
||||
if ((fs == wav_fmt->fmt.samples_per_sec) &&
|
||||
(bps == wav_fmt->fmt.bits_per_sample))
|
||||
(bps == wav_fmt->fmt.bits_per_sample)) {
|
||||
channels = max_t(u16, channels,
|
||||
wav_fmt->fmt.channels);
|
||||
saved_fmt_cfg = tmp_fmt_cfg;
|
||||
}
|
||||
/* Move to the next nhlt_fmt_cfg */
|
||||
tmp_fmt_cfg = (struct nhlt_fmt_cfg *)(tmp_fmt_cfg->config.caps +
|
||||
tmp_fmt_cfg->config.size);
|
||||
}
|
||||
|
||||
rate = channels * bps * fs;
|
||||
@ -256,8 +263,11 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
|
||||
|
||||
/* Fill rate and parent for sclk/sclkfs */
|
||||
if (!present) {
|
||||
struct nhlt_fmt_cfg *first_fmt_cfg;
|
||||
|
||||
first_fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config;
|
||||
i2s_config_ext = (struct skl_i2s_config_blob_ext *)
|
||||
fmt->fmt_config[0].config.caps;
|
||||
first_fmt_cfg->config.caps;
|
||||
|
||||
/* MCLK Divider Source Select */
|
||||
if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
|
||||
@ -271,6 +281,9 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
|
||||
|
||||
parent = skl_get_parent_clk(clk_src);
|
||||
|
||||
/* Move to the next nhlt_fmt_cfg */
|
||||
fmt_cfg = (struct nhlt_fmt_cfg *)(fmt_cfg->config.caps +
|
||||
fmt_cfg->config.size);
|
||||
/*
|
||||
* Do not copy the config data if there is no parent
|
||||
* clock available for this clock source select
|
||||
@ -279,9 +292,9 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
|
||||
continue;
|
||||
|
||||
sclk[id].rate_cfg[rate_index].rate = rate;
|
||||
sclk[id].rate_cfg[rate_index].config = fmt_cfg;
|
||||
sclk[id].rate_cfg[rate_index].config = saved_fmt_cfg;
|
||||
sclkfs[id].rate_cfg[rate_index].rate = rate;
|
||||
sclkfs[id].rate_cfg[rate_index].config = fmt_cfg;
|
||||
sclkfs[id].rate_cfg[rate_index].config = saved_fmt_cfg;
|
||||
sclk[id].parent_name = parent->name;
|
||||
sclkfs[id].parent_name = parent->name;
|
||||
|
||||
@ -295,13 +308,13 @@ static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk,
|
||||
{
|
||||
struct skl_i2s_config_blob_ext *i2s_config_ext;
|
||||
struct skl_i2s_config_blob_legacy *i2s_config;
|
||||
struct nhlt_specific_cfg *fmt_cfg;
|
||||
struct nhlt_fmt_cfg *fmt_cfg;
|
||||
struct skl_clk_parent_src *parent;
|
||||
u32 clkdiv, div_ratio;
|
||||
u8 clk_src;
|
||||
|
||||
fmt_cfg = &fmt->fmt_config[0].config;
|
||||
i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->caps;
|
||||
fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config;
|
||||
i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->config.caps;
|
||||
|
||||
/* MCLK Divider Source Select and divider */
|
||||
if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
|
||||
@ -330,7 +343,7 @@ static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk,
|
||||
return;
|
||||
|
||||
mclk[id].rate_cfg[0].rate = parent->rate/div_ratio;
|
||||
mclk[id].rate_cfg[0].config = &fmt->fmt_config[0];
|
||||
mclk[id].rate_cfg[0].config = fmt_cfg;
|
||||
mclk[id].parent_name = parent->name;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user