aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSriram Periyasamy <sriramx.periyasamy@intel.com>2018-01-04 06:25:15 -0500
committerMark Brown <broonie@kernel.org>2018-01-26 07:51:22 -0500
commit9afbc5ec76526d412de1c5c368524aae36eb608d (patch)
treec0bc9d49cf8e17df3f81017e9a545792df3ffaa2
parent01f50d69bebe1bb0b30bba1eba3cdaf1f02dd7c4 (diff)
ASoC: Intel: Skylake: Add extended I2S config blob support in Clock driver
Extended I2S config blob supports multiple mclk dividers in NHLT blob. This patch detects whether the I2S blob is legacy or extended based on the signature value and chooses the mclk source and divider accordingly. Signed-off-by: Sriram Periyasamy <sriramx.periyasamy@intel.com> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/intel/skylake/skl-i2s.h31
-rw-r--r--sound/soc/intel/skylake/skl-nhlt.c41
2 files changed, 60 insertions, 12 deletions
diff --git a/sound/soc/intel/skylake/skl-i2s.h b/sound/soc/intel/skylake/skl-i2s.h
index dcf819bc688f..ad0a1bbca13c 100644
--- a/sound/soc/intel/skylake/skl-i2s.h
+++ b/sound/soc/intel/skylake/skl-i2s.h
@@ -27,6 +27,12 @@
27#define SKL_SHIFT(x) (ffs(x) - 1) 27#define SKL_SHIFT(x) (ffs(x) - 1)
28#define SKL_MCLK_DIV_RATIO_MASK GENMASK(11, 0) 28#define SKL_MCLK_DIV_RATIO_MASK GENMASK(11, 0)
29 29
30#define is_legacy_blob(x) (x.signature != 0xEE)
31#define ext_to_legacy_blob(i2s_config_blob_ext) \
32 ((struct skl_i2s_config_blob_legacy *) i2s_config_blob_ext)
33
34#define get_clk_src(mclk, mask) \
35 ((mclk.mdivctrl & mask) >> SKL_SHIFT(mask))
30struct skl_i2s_config { 36struct skl_i2s_config {
31 u32 ssc0; 37 u32 ssc0;
32 u32 ssc1; 38 u32 ssc1;
@@ -45,6 +51,24 @@ struct skl_i2s_config_mclk {
45 u32 mdivr; 51 u32 mdivr;
46}; 52};
47 53
54struct skl_i2s_config_mclk_ext {
55 u32 mdivctrl;
56 u32 mdivr_count;
57 u32 mdivr[0];
58} __packed;
59
60struct skl_i2s_config_blob_signature {
61 u32 minor_ver : 8;
62 u32 major_ver : 8;
63 u32 resvdz : 8;
64 u32 signature : 8;
65} __packed;
66
67struct skl_i2s_config_blob_header {
68 struct skl_i2s_config_blob_signature sig;
69 u32 size;
70};
71
48/** 72/**
49 * struct skl_i2s_config_blob_legacy - Structure defines I2S Gateway 73 * struct skl_i2s_config_blob_legacy - Structure defines I2S Gateway
50 * configuration legacy blob 74 * configuration legacy blob
@@ -61,4 +85,11 @@ struct skl_i2s_config_blob_legacy {
61 struct skl_i2s_config_mclk mclk; 85 struct skl_i2s_config_mclk mclk;
62}; 86};
63 87
88struct skl_i2s_config_blob_ext {
89 u32 gtw_attr;
90 struct skl_i2s_config_blob_header hdr;
91 u32 tdm_ts_group[SKL_I2S_MAX_TIME_SLOTS];
92 struct skl_i2s_config i2s_cfg;
93 struct skl_i2s_config_mclk_ext mclk;
94} __packed;
64#endif /* __SOUND_SOC_SKL_I2S_H */ 95#endif /* __SOUND_SOC_SKL_I2S_H */
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c
index 3b1d2b828c1b..b9b140275be0 100644
--- a/sound/soc/intel/skylake/skl-nhlt.c
+++ b/sound/soc/intel/skylake/skl-nhlt.c
@@ -28,6 +28,7 @@ static guid_t osc_guid =
28 GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, 28 GUID_INIT(0xA69F886E, 0x6CEB, 0x4594,
29 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); 29 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53);
30 30
31
31struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) 32struct nhlt_acpi_table *skl_nhlt_init(struct device *dev)
32{ 33{
33 acpi_handle handle; 34 acpi_handle handle;
@@ -287,6 +288,7 @@ void skl_nhlt_remove_sysfs(struct skl *skl)
287static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks, 288static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks,
288 struct nhlt_fmt *fmt, u8 id) 289 struct nhlt_fmt *fmt, u8 id)
289{ 290{
291 struct skl_i2s_config_blob_ext *i2s_config_ext;
290 struct skl_i2s_config_blob_legacy *i2s_config; 292 struct skl_i2s_config_blob_legacy *i2s_config;
291 struct skl_clk_parent_src *parent; 293 struct skl_clk_parent_src *parent;
292 struct skl_ssp_clk *sclk, *sclkfs; 294 struct skl_ssp_clk *sclk, *sclkfs;
@@ -347,12 +349,18 @@ static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks,
347 349
348 /* Fill rate and parent for sclk/sclkfs */ 350 /* Fill rate and parent for sclk/sclkfs */
349 if (!present) { 351 if (!present) {
350 /* MCLK Divider Source Select */ 352 i2s_config_ext = (struct skl_i2s_config_blob_ext *)
351 i2s_config = (struct skl_i2s_config_blob_legacy *)
352 fmt->fmt_config[0].config.caps; 353 fmt->fmt_config[0].config.caps;
353 clk_src = ((i2s_config->mclk.mdivctrl) 354
354 & SKL_MNDSS_DIV_CLK_SRC_MASK) >> 355 /* MCLK Divider Source Select */
355 SKL_SHIFT(SKL_MNDSS_DIV_CLK_SRC_MASK); 356 if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
357 i2s_config = ext_to_legacy_blob(i2s_config_ext);
358 clk_src = get_clk_src(i2s_config->mclk,
359 SKL_MNDSS_DIV_CLK_SRC_MASK);
360 } else {
361 clk_src = get_clk_src(i2s_config_ext->mclk,
362 SKL_MNDSS_DIV_CLK_SRC_MASK);
363 }
356 364
357 parent = skl_get_parent_clk(clk_src); 365 parent = skl_get_parent_clk(clk_src);
358 366
@@ -378,6 +386,7 @@ static void skl_get_ssp_clks(struct skl *skl, struct skl_ssp_clk *ssp_clks,
378static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk, 386static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk,
379 struct nhlt_fmt *fmt, u8 id) 387 struct nhlt_fmt *fmt, u8 id)
380{ 388{
389 struct skl_i2s_config_blob_ext *i2s_config_ext;
381 struct skl_i2s_config_blob_legacy *i2s_config; 390 struct skl_i2s_config_blob_legacy *i2s_config;
382 struct nhlt_specific_cfg *fmt_cfg; 391 struct nhlt_specific_cfg *fmt_cfg;
383 struct skl_clk_parent_src *parent; 392 struct skl_clk_parent_src *parent;
@@ -385,13 +394,21 @@ static void skl_get_mclk(struct skl *skl, struct skl_ssp_clk *mclk,
385 u8 clk_src; 394 u8 clk_src;
386 395
387 fmt_cfg = &fmt->fmt_config[0].config; 396 fmt_cfg = &fmt->fmt_config[0].config;
388 i2s_config = (struct skl_i2s_config_blob_legacy *)fmt_cfg->caps; 397 i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->caps;
389 398
390 /* MCLK Divider Source Select */ 399 /* MCLK Divider Source Select and divider */
391 clk_src = ((i2s_config->mclk.mdivctrl) & SKL_MCLK_DIV_CLK_SRC_MASK) >> 400 if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
392 SKL_SHIFT(SKL_MCLK_DIV_CLK_SRC_MASK); 401 i2s_config = ext_to_legacy_blob(i2s_config_ext);
393 402 clk_src = get_clk_src(i2s_config->mclk,
394 clkdiv = i2s_config->mclk.mdivr & SKL_MCLK_DIV_RATIO_MASK; 403 SKL_MCLK_DIV_CLK_SRC_MASK);
404 clkdiv = i2s_config->mclk.mdivr &
405 SKL_MCLK_DIV_RATIO_MASK;
406 } else {
407 clk_src = get_clk_src(i2s_config_ext->mclk,
408 SKL_MCLK_DIV_CLK_SRC_MASK);
409 clkdiv = i2s_config_ext->mclk.mdivr[0] &
410 SKL_MCLK_DIV_RATIO_MASK;
411 }
395 412
396 /* bypass divider */ 413 /* bypass divider */
397 div_ratio = 1; 414 div_ratio = 1;