Commit fc976f56 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown

ASoC: Intel: Skylake: Correct the handling of fmt_config flexible array

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: bc2bd45b ("ASoC: Intel: Skylake: Parse nhlt and register clock device")
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: default avatarCezary Rojewski <cezary.rojewski@intel.com>
Link: https://lore.kernel.org/r/20220630065638.11183-3-peter.ujfalusi@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 219af251
...@@ -111,11 +111,12 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, ...@@ -111,11 +111,12 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
if (fmt->fmt_count == 0) if (fmt->fmt_count == 0)
return; return;
fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config;
for (i = 0; i < fmt->fmt_count; i++) { for (i = 0; i < fmt->fmt_count; i++) {
struct nhlt_fmt_cfg *saved_fmt_cfg = fmt_cfg;
bool present = false; bool present = false;
fmt_cfg = &fmt->fmt_config[i]; wav_fmt = &saved_fmt_cfg->fmt_ext;
wav_fmt = &fmt_cfg->fmt_ext;
channels = wav_fmt->fmt.channels; channels = wav_fmt->fmt.channels;
bps = wav_fmt->fmt.bits_per_sample; bps = wav_fmt->fmt.bits_per_sample;
...@@ -133,12 +134,18 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, ...@@ -133,12 +134,18 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
* derive the rate. * derive the rate.
*/ */
for (j = i; j < fmt->fmt_count; j++) { for (j = i; j < fmt->fmt_count; j++) {
fmt_cfg = &fmt->fmt_config[j]; struct nhlt_fmt_cfg *tmp_fmt_cfg = fmt_cfg;
wav_fmt = &fmt_cfg->fmt_ext;
wav_fmt = &tmp_fmt_cfg->fmt_ext;
if ((fs == wav_fmt->fmt.samples_per_sec) && 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, channels = max_t(u16, channels,
wav_fmt->fmt.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; rate = channels * bps * fs;
...@@ -154,8 +161,11 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, ...@@ -154,8 +161,11 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
/* Fill rate and parent for sclk/sclkfs */ /* Fill rate and parent for sclk/sclkfs */
if (!present) { 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 *) i2s_config_ext = (struct skl_i2s_config_blob_ext *)
fmt->fmt_config[0].config.caps; first_fmt_cfg->config.caps;
/* MCLK Divider Source Select */ /* MCLK Divider Source Select */
if (is_legacy_blob(i2s_config_ext->hdr.sig)) { if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
...@@ -169,6 +179,9 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, ...@@ -169,6 +179,9 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
parent = skl_get_parent_clk(clk_src); 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 * Do not copy the config data if there is no parent
* clock available for this clock source select * clock available for this clock source select
...@@ -177,9 +190,9 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, ...@@ -177,9 +190,9 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
continue; continue;
sclk[id].rate_cfg[rate_index].rate = rate; 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].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; sclk[id].parent_name = parent->name;
sclkfs[id].parent_name = parent->name; sclkfs[id].parent_name = parent->name;
...@@ -193,13 +206,13 @@ static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk, ...@@ -193,13 +206,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_ext *i2s_config_ext;
struct skl_i2s_config_blob_legacy *i2s_config; 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; struct skl_clk_parent_src *parent;
u32 clkdiv, div_ratio; u32 clkdiv, div_ratio;
u8 clk_src; u8 clk_src;
fmt_cfg = &fmt->fmt_config[0].config; fmt_cfg = (struct nhlt_fmt_cfg *)fmt->fmt_config;
i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->caps; i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->config.caps;
/* MCLK Divider Source Select and divider */ /* MCLK Divider Source Select and divider */
if (is_legacy_blob(i2s_config_ext->hdr.sig)) { if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
...@@ -228,7 +241,7 @@ static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk, ...@@ -228,7 +241,7 @@ static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk,
return; return;
mclk[id].rate_cfg[0].rate = parent->rate/div_ratio; 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; mclk[id].parent_name = parent->name;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment