18e8e69d6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2473eb87aSJeeja KP /* 3473eb87aSJeeja KP * skl-nhlt.c - Intel SKL Platform NHLT parsing 4473eb87aSJeeja KP * 5473eb87aSJeeja KP * Copyright (C) 2015 Intel Corp 6473eb87aSJeeja KP * Author: Sanjiv Kumar <sanjiv.kumar@intel.com> 7473eb87aSJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8473eb87aSJeeja KP * 9473eb87aSJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10473eb87aSJeeja KP */ 11f65cf7d6SYong Zhi #include <linux/pci.h> 1263643b59SPierre-Louis Bossart #include <sound/intel-nhlt.h> 13473eb87aSJeeja KP #include "skl.h" 14bc2bd45bSSriram Periyasamy #include "skl-i2s.h" 15473eb87aSJeeja KP 16473eb87aSJeeja KP static struct nhlt_specific_cfg *skl_get_specific_cfg( 17473eb87aSJeeja KP struct device *dev, struct nhlt_fmt *fmt, 1816882d24SJeeja KP u8 no_ch, u32 rate, u16 bps, u8 linktype) 19473eb87aSJeeja KP { 20473eb87aSJeeja KP struct nhlt_specific_cfg *sp_config; 21473eb87aSJeeja KP struct wav_fmt *wfmt; 22473eb87aSJeeja KP struct nhlt_fmt_cfg *fmt_config = fmt->fmt_config; 23473eb87aSJeeja KP int i; 24473eb87aSJeeja KP 25473eb87aSJeeja KP dev_dbg(dev, "Format count =%d\n", fmt->fmt_count); 26473eb87aSJeeja KP 27473eb87aSJeeja KP for (i = 0; i < fmt->fmt_count; i++) { 28473eb87aSJeeja KP wfmt = &fmt_config->fmt_ext.fmt; 29473eb87aSJeeja KP dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", wfmt->channels, 30473eb87aSJeeja KP wfmt->bits_per_sample, wfmt->samples_per_sec); 3116882d24SJeeja KP if (wfmt->channels == no_ch && wfmt->bits_per_sample == bps) { 3216882d24SJeeja KP /* 3316882d24SJeeja KP * if link type is dmic ignore rate check as the blob is 3416882d24SJeeja KP * generic for all rates 3516882d24SJeeja KP */ 36473eb87aSJeeja KP sp_config = &fmt_config->config; 3716882d24SJeeja KP if (linktype == NHLT_LINK_DMIC) 3816882d24SJeeja KP return sp_config; 39473eb87aSJeeja KP 4016882d24SJeeja KP if (wfmt->samples_per_sec == rate) 41473eb87aSJeeja KP return sp_config; 42473eb87aSJeeja KP } 43473eb87aSJeeja KP 44473eb87aSJeeja KP fmt_config = (struct nhlt_fmt_cfg *)(fmt_config->config.caps + 45473eb87aSJeeja KP fmt_config->config.size); 46473eb87aSJeeja KP } 47473eb87aSJeeja KP 48473eb87aSJeeja KP return NULL; 49473eb87aSJeeja KP } 50473eb87aSJeeja KP 51473eb87aSJeeja KP static void dump_config(struct device *dev, u32 instance_id, u8 linktype, 52473eb87aSJeeja KP u8 s_fmt, u8 num_channels, u32 s_rate, u8 dirn, u16 bps) 53473eb87aSJeeja KP { 54473eb87aSJeeja KP dev_dbg(dev, "Input configuration\n"); 55473eb87aSJeeja KP dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", num_channels, s_fmt, s_rate); 56473eb87aSJeeja KP dev_dbg(dev, "vbus_id=%d link_type=%d\n", instance_id, linktype); 57473eb87aSJeeja KP dev_dbg(dev, "bits_per_sample=%d\n", bps); 58473eb87aSJeeja KP } 59473eb87aSJeeja KP 60473eb87aSJeeja KP static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt, 61db2f586bSSenthilnathan Veppur u32 instance_id, u8 link_type, u8 dirn, u8 dev_type) 62473eb87aSJeeja KP { 63db2f586bSSenthilnathan Veppur dev_dbg(dev, "vbus_id=%d link_type=%d dir=%d dev_type = %d\n", 64db2f586bSSenthilnathan Veppur epnt->virtual_bus_id, epnt->linktype, 65db2f586bSSenthilnathan Veppur epnt->direction, epnt->device_type); 66473eb87aSJeeja KP 67473eb87aSJeeja KP if ((epnt->virtual_bus_id == instance_id) && 68473eb87aSJeeja KP (epnt->linktype == link_type) && 69e02b0330SGuneshwor Singh (epnt->direction == dirn)) { 70e02b0330SGuneshwor Singh /* do not check dev_type for DMIC link type */ 71e02b0330SGuneshwor Singh if (epnt->linktype == NHLT_LINK_DMIC) 72473eb87aSJeeja KP return true; 73e02b0330SGuneshwor Singh 74e02b0330SGuneshwor Singh if (epnt->device_type == dev_type) 75e02b0330SGuneshwor Singh return true; 76e02b0330SGuneshwor Singh } 77e02b0330SGuneshwor Singh 78473eb87aSJeeja KP return false; 79473eb87aSJeeja KP } 80473eb87aSJeeja KP 81473eb87aSJeeja KP struct nhlt_specific_cfg 82bcc2a2dcSCezary Rojewski *skl_get_ep_blob(struct skl_dev *skl, u32 instance, u8 link_type, 83db2f586bSSenthilnathan Veppur u8 s_fmt, u8 num_ch, u32 s_rate, 84db2f586bSSenthilnathan Veppur u8 dirn, u8 dev_type) 85473eb87aSJeeja KP { 86473eb87aSJeeja KP struct nhlt_fmt *fmt; 87473eb87aSJeeja KP struct nhlt_endpoint *epnt; 8876f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl); 89473eb87aSJeeja KP struct device *dev = bus->dev; 90473eb87aSJeeja KP struct nhlt_specific_cfg *sp_config; 91c286b3f9SJeeja KP struct nhlt_acpi_table *nhlt = skl->nhlt; 9283b50246SJeeja KP u16 bps = (s_fmt == 16) ? 16 : 32; 93473eb87aSJeeja KP u8 j; 94473eb87aSJeeja KP 95473eb87aSJeeja KP dump_config(dev, instance, link_type, s_fmt, num_ch, s_rate, dirn, bps); 96473eb87aSJeeja KP 97473eb87aSJeeja KP epnt = (struct nhlt_endpoint *)nhlt->desc; 98473eb87aSJeeja KP 99473eb87aSJeeja KP dev_dbg(dev, "endpoint count =%d\n", nhlt->endpoint_count); 100473eb87aSJeeja KP 101473eb87aSJeeja KP for (j = 0; j < nhlt->endpoint_count; j++) { 102db2f586bSSenthilnathan Veppur if (skl_check_ep_match(dev, epnt, instance, link_type, 103db2f586bSSenthilnathan Veppur dirn, dev_type)) { 104473eb87aSJeeja KP fmt = (struct nhlt_fmt *)(epnt->config.caps + 105473eb87aSJeeja KP epnt->config.size); 10616882d24SJeeja KP sp_config = skl_get_specific_cfg(dev, fmt, num_ch, 10716882d24SJeeja KP s_rate, bps, link_type); 108473eb87aSJeeja KP if (sp_config) 109473eb87aSJeeja KP return sp_config; 110473eb87aSJeeja KP } 111473eb87aSJeeja KP 112473eb87aSJeeja KP epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); 113473eb87aSJeeja KP } 114473eb87aSJeeja KP 115473eb87aSJeeja KP return NULL; 116473eb87aSJeeja KP } 1174b235c43SVinod Koul 1180cf5a171SSubhransu S. Prusty static void skl_nhlt_trim_space(char *trim) 1194b235c43SVinod Koul { 1200cf5a171SSubhransu S. Prusty char *s = trim; 1214b235c43SVinod Koul int cnt; 1224b235c43SVinod Koul int i; 1234b235c43SVinod Koul 1244b235c43SVinod Koul cnt = 0; 1254b235c43SVinod Koul for (i = 0; s[i]; i++) { 1264b235c43SVinod Koul if (!isspace(s[i])) 1274b235c43SVinod Koul s[cnt++] = s[i]; 1284b235c43SVinod Koul } 1294b235c43SVinod Koul 1304b235c43SVinod Koul s[cnt] = '\0'; 1314b235c43SVinod Koul } 1324b235c43SVinod Koul 133bcc2a2dcSCezary Rojewski int skl_nhlt_update_topology_bin(struct skl_dev *skl) 1344b235c43SVinod Koul { 1354b235c43SVinod Koul struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; 13676f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl); 1374b235c43SVinod Koul struct device *dev = bus->dev; 1384b235c43SVinod Koul 139855a06daSAmadeusz Sławiński dev_dbg(dev, "oem_id %.6s, oem_table_id %.8s oem_revision %d\n", 1404b235c43SVinod Koul nhlt->header.oem_id, nhlt->header.oem_table_id, 1414b235c43SVinod Koul nhlt->header.oem_revision); 1424b235c43SVinod Koul 1434b235c43SVinod Koul snprintf(skl->tplg_name, sizeof(skl->tplg_name), "%x-%.6s-%.8s-%d%s", 1444b235c43SVinod Koul skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id, 1454b235c43SVinod Koul nhlt->header.oem_revision, "-tplg.bin"); 1464b235c43SVinod Koul 1470cf5a171SSubhransu S. Prusty skl_nhlt_trim_space(skl->tplg_name); 1484b235c43SVinod Koul 1494b235c43SVinod Koul return 0; 1504b235c43SVinod Koul } 1510cf5a171SSubhransu S. Prusty 1520cf5a171SSubhransu S. Prusty static ssize_t skl_nhlt_platform_id_show(struct device *dev, 1530cf5a171SSubhransu S. Prusty struct device_attribute *attr, char *buf) 1540cf5a171SSubhransu S. Prusty { 1550cf5a171SSubhransu S. Prusty struct pci_dev *pci = to_pci_dev(dev); 15676f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci); 157bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 1580cf5a171SSubhransu S. Prusty struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; 1590cf5a171SSubhransu S. Prusty char platform_id[32]; 1600cf5a171SSubhransu S. Prusty 1610cf5a171SSubhransu S. Prusty sprintf(platform_id, "%x-%.6s-%.8s-%d", skl->pci_id, 1620cf5a171SSubhransu S. Prusty nhlt->header.oem_id, nhlt->header.oem_table_id, 1630cf5a171SSubhransu S. Prusty nhlt->header.oem_revision); 1640cf5a171SSubhransu S. Prusty 1650cf5a171SSubhransu S. Prusty skl_nhlt_trim_space(platform_id); 1660cf5a171SSubhransu S. Prusty return sprintf(buf, "%s\n", platform_id); 1670cf5a171SSubhransu S. Prusty } 1680cf5a171SSubhransu S. Prusty 1690cf5a171SSubhransu S. Prusty static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL); 1700cf5a171SSubhransu S. Prusty 171bcc2a2dcSCezary Rojewski int skl_nhlt_create_sysfs(struct skl_dev *skl) 1720cf5a171SSubhransu S. Prusty { 1730cf5a171SSubhransu S. Prusty struct device *dev = &skl->pci->dev; 1740cf5a171SSubhransu S. Prusty 1750cf5a171SSubhransu S. Prusty if (sysfs_create_file(&dev->kobj, &dev_attr_platform_id.attr)) 1760cf5a171SSubhransu S. Prusty dev_warn(dev, "Error creating sysfs entry\n"); 1770cf5a171SSubhransu S. Prusty 1780cf5a171SSubhransu S. Prusty return 0; 1790cf5a171SSubhransu S. Prusty } 1800cf5a171SSubhransu S. Prusty 181bcc2a2dcSCezary Rojewski void skl_nhlt_remove_sysfs(struct skl_dev *skl) 1820cf5a171SSubhransu S. Prusty { 1830cf5a171SSubhransu S. Prusty struct device *dev = &skl->pci->dev; 1840cf5a171SSubhransu S. Prusty 1859e6c382fSCezary Rojewski if (skl->nhlt) 1860cf5a171SSubhransu S. Prusty sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr); 1870cf5a171SSubhransu S. Prusty } 188bc2bd45bSSriram Periyasamy 189bc2bd45bSSriram Periyasamy /* 190bc2bd45bSSriram Periyasamy * Queries NHLT for all the fmt configuration for a particular endpoint and 191bc2bd45bSSriram Periyasamy * stores all possible rates supported in a rate table for the corresponding 192bc2bd45bSSriram Periyasamy * sclk/sclkfs. 193bc2bd45bSSriram Periyasamy */ 194bcc2a2dcSCezary Rojewski static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, 195bc2bd45bSSriram Periyasamy struct nhlt_fmt *fmt, u8 id) 196bc2bd45bSSriram Periyasamy { 1979afbc5ecSSriram Periyasamy struct skl_i2s_config_blob_ext *i2s_config_ext; 198bc2bd45bSSriram Periyasamy struct skl_i2s_config_blob_legacy *i2s_config; 199bc2bd45bSSriram Periyasamy struct skl_clk_parent_src *parent; 200bc2bd45bSSriram Periyasamy struct skl_ssp_clk *sclk, *sclkfs; 201bc2bd45bSSriram Periyasamy struct nhlt_fmt_cfg *fmt_cfg; 202bc2bd45bSSriram Periyasamy struct wav_fmt_ext *wav_fmt; 2038be54edbSPierre-Louis Bossart unsigned long rate; 204bc2bd45bSSriram Periyasamy bool present = false; 205bc2bd45bSSriram Periyasamy int rate_index = 0; 206bc2bd45bSSriram Periyasamy u16 channels, bps; 207bc2bd45bSSriram Periyasamy u8 clk_src; 208bc2bd45bSSriram Periyasamy int i, j; 209bc2bd45bSSriram Periyasamy u32 fs; 210bc2bd45bSSriram Periyasamy 211bc2bd45bSSriram Periyasamy sclk = &ssp_clks[SKL_SCLK_OFS]; 212bc2bd45bSSriram Periyasamy sclkfs = &ssp_clks[SKL_SCLKFS_OFS]; 213bc2bd45bSSriram Periyasamy 214bc2bd45bSSriram Periyasamy if (fmt->fmt_count == 0) 215bc2bd45bSSriram Periyasamy return; 216bc2bd45bSSriram Periyasamy 217bc2bd45bSSriram Periyasamy for (i = 0; i < fmt->fmt_count; i++) { 218bc2bd45bSSriram Periyasamy fmt_cfg = &fmt->fmt_config[i]; 219bc2bd45bSSriram Periyasamy wav_fmt = &fmt_cfg->fmt_ext; 220bc2bd45bSSriram Periyasamy 221bc2bd45bSSriram Periyasamy channels = wav_fmt->fmt.channels; 222bc2bd45bSSriram Periyasamy bps = wav_fmt->fmt.bits_per_sample; 223bc2bd45bSSriram Periyasamy fs = wav_fmt->fmt.samples_per_sec; 224bc2bd45bSSriram Periyasamy 225bc2bd45bSSriram Periyasamy /* 226bc2bd45bSSriram Periyasamy * In case of TDM configuration on a ssp, there can 227bc2bd45bSSriram Periyasamy * be more than one blob in which channel masks are 228bc2bd45bSSriram Periyasamy * different for each usecase for a specific rate and bps. 229bc2bd45bSSriram Periyasamy * But the sclk rate will be generated for the total 230bc2bd45bSSriram Periyasamy * number of channels used for that endpoint. 231bc2bd45bSSriram Periyasamy * 232bc2bd45bSSriram Periyasamy * So for the given fs and bps, choose blob which has 233bc2bd45bSSriram Periyasamy * the superset of all channels for that endpoint and 234bc2bd45bSSriram Periyasamy * derive the rate. 235bc2bd45bSSriram Periyasamy */ 236bc2bd45bSSriram Periyasamy for (j = i; j < fmt->fmt_count; j++) { 237bc2bd45bSSriram Periyasamy fmt_cfg = &fmt->fmt_config[j]; 238bc2bd45bSSriram Periyasamy wav_fmt = &fmt_cfg->fmt_ext; 239bc2bd45bSSriram Periyasamy if ((fs == wav_fmt->fmt.samples_per_sec) && 240bc2bd45bSSriram Periyasamy (bps == wav_fmt->fmt.bits_per_sample)) 241bc2bd45bSSriram Periyasamy channels = max_t(u16, channels, 242bc2bd45bSSriram Periyasamy wav_fmt->fmt.channels); 243bc2bd45bSSriram Periyasamy } 244bc2bd45bSSriram Periyasamy 245bc2bd45bSSriram Periyasamy rate = channels * bps * fs; 246bc2bd45bSSriram Periyasamy 247bc2bd45bSSriram Periyasamy /* check if the rate is added already to the given SSP's sclk */ 24887684d33SDan Carpenter for (j = 0; (j < SKL_MAX_CLK_RATES) && 24987684d33SDan Carpenter (sclk[id].rate_cfg[j].rate != 0); j++) { 250bc2bd45bSSriram Periyasamy if (sclk[id].rate_cfg[j].rate == rate) { 251bc2bd45bSSriram Periyasamy present = true; 252bc2bd45bSSriram Periyasamy break; 253bc2bd45bSSriram Periyasamy } 254bc2bd45bSSriram Periyasamy } 255bc2bd45bSSriram Periyasamy 256bc2bd45bSSriram Periyasamy /* Fill rate and parent for sclk/sclkfs */ 257bc2bd45bSSriram Periyasamy if (!present) { 2589afbc5ecSSriram Periyasamy i2s_config_ext = (struct skl_i2s_config_blob_ext *) 259bc2bd45bSSriram Periyasamy fmt->fmt_config[0].config.caps; 2609afbc5ecSSriram Periyasamy 2619afbc5ecSSriram Periyasamy /* MCLK Divider Source Select */ 2629afbc5ecSSriram Periyasamy if (is_legacy_blob(i2s_config_ext->hdr.sig)) { 2639afbc5ecSSriram Periyasamy i2s_config = ext_to_legacy_blob(i2s_config_ext); 2649afbc5ecSSriram Periyasamy clk_src = get_clk_src(i2s_config->mclk, 2659afbc5ecSSriram Periyasamy SKL_MNDSS_DIV_CLK_SRC_MASK); 2669afbc5ecSSriram Periyasamy } else { 2679afbc5ecSSriram Periyasamy clk_src = get_clk_src(i2s_config_ext->mclk, 2689afbc5ecSSriram Periyasamy SKL_MNDSS_DIV_CLK_SRC_MASK); 2699afbc5ecSSriram Periyasamy } 270bc2bd45bSSriram Periyasamy 271bc2bd45bSSriram Periyasamy parent = skl_get_parent_clk(clk_src); 272bc2bd45bSSriram Periyasamy 273bc2bd45bSSriram Periyasamy /* 274bc2bd45bSSriram Periyasamy * Do not copy the config data if there is no parent 275bc2bd45bSSriram Periyasamy * clock available for this clock source select 276bc2bd45bSSriram Periyasamy */ 277bc2bd45bSSriram Periyasamy if (!parent) 278bc2bd45bSSriram Periyasamy continue; 279bc2bd45bSSriram Periyasamy 280bc2bd45bSSriram Periyasamy sclk[id].rate_cfg[rate_index].rate = rate; 281bc2bd45bSSriram Periyasamy sclk[id].rate_cfg[rate_index].config = fmt_cfg; 282bc2bd45bSSriram Periyasamy sclkfs[id].rate_cfg[rate_index].rate = rate; 283bc2bd45bSSriram Periyasamy sclkfs[id].rate_cfg[rate_index].config = fmt_cfg; 284bc2bd45bSSriram Periyasamy sclk[id].parent_name = parent->name; 285bc2bd45bSSriram Periyasamy sclkfs[id].parent_name = parent->name; 286bc2bd45bSSriram Periyasamy 287bc2bd45bSSriram Periyasamy rate_index++; 288bc2bd45bSSriram Periyasamy } 289bc2bd45bSSriram Periyasamy } 290bc2bd45bSSriram Periyasamy } 291bc2bd45bSSriram Periyasamy 292bcc2a2dcSCezary Rojewski static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk, 293bc2bd45bSSriram Periyasamy struct nhlt_fmt *fmt, u8 id) 294bc2bd45bSSriram Periyasamy { 2959afbc5ecSSriram Periyasamy struct skl_i2s_config_blob_ext *i2s_config_ext; 296bc2bd45bSSriram Periyasamy struct skl_i2s_config_blob_legacy *i2s_config; 297bc2bd45bSSriram Periyasamy struct nhlt_specific_cfg *fmt_cfg; 298bc2bd45bSSriram Periyasamy struct skl_clk_parent_src *parent; 299bc2bd45bSSriram Periyasamy u32 clkdiv, div_ratio; 300bc2bd45bSSriram Periyasamy u8 clk_src; 301bc2bd45bSSriram Periyasamy 302bc2bd45bSSriram Periyasamy fmt_cfg = &fmt->fmt_config[0].config; 3039afbc5ecSSriram Periyasamy i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->caps; 304bc2bd45bSSriram Periyasamy 3059afbc5ecSSriram Periyasamy /* MCLK Divider Source Select and divider */ 3069afbc5ecSSriram Periyasamy if (is_legacy_blob(i2s_config_ext->hdr.sig)) { 3079afbc5ecSSriram Periyasamy i2s_config = ext_to_legacy_blob(i2s_config_ext); 3089afbc5ecSSriram Periyasamy clk_src = get_clk_src(i2s_config->mclk, 3099afbc5ecSSriram Periyasamy SKL_MCLK_DIV_CLK_SRC_MASK); 3109afbc5ecSSriram Periyasamy clkdiv = i2s_config->mclk.mdivr & 3119afbc5ecSSriram Periyasamy SKL_MCLK_DIV_RATIO_MASK; 3129afbc5ecSSriram Periyasamy } else { 3139afbc5ecSSriram Periyasamy clk_src = get_clk_src(i2s_config_ext->mclk, 3149afbc5ecSSriram Periyasamy SKL_MCLK_DIV_CLK_SRC_MASK); 3159afbc5ecSSriram Periyasamy clkdiv = i2s_config_ext->mclk.mdivr[0] & 3169afbc5ecSSriram Periyasamy SKL_MCLK_DIV_RATIO_MASK; 3179afbc5ecSSriram Periyasamy } 318bc2bd45bSSriram Periyasamy 319bc2bd45bSSriram Periyasamy /* bypass divider */ 320bc2bd45bSSriram Periyasamy div_ratio = 1; 321bc2bd45bSSriram Periyasamy 322bc2bd45bSSriram Periyasamy if (clkdiv != SKL_MCLK_DIV_RATIO_MASK) 323bc2bd45bSSriram Periyasamy /* Divider is 2 + clkdiv */ 324bc2bd45bSSriram Periyasamy div_ratio = clkdiv + 2; 325bc2bd45bSSriram Periyasamy 326bc2bd45bSSriram Periyasamy /* Calculate MCLK rate from source using div value */ 327bc2bd45bSSriram Periyasamy parent = skl_get_parent_clk(clk_src); 328bc2bd45bSSriram Periyasamy if (!parent) 329bc2bd45bSSriram Periyasamy return; 330bc2bd45bSSriram Periyasamy 331bc2bd45bSSriram Periyasamy mclk[id].rate_cfg[0].rate = parent->rate/div_ratio; 332bc2bd45bSSriram Periyasamy mclk[id].rate_cfg[0].config = &fmt->fmt_config[0]; 333bc2bd45bSSriram Periyasamy mclk[id].parent_name = parent->name; 334bc2bd45bSSriram Periyasamy } 335bc2bd45bSSriram Periyasamy 336bcc2a2dcSCezary Rojewski void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks) 337bc2bd45bSSriram Periyasamy { 338bc2bd45bSSriram Periyasamy struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; 339bc2bd45bSSriram Periyasamy struct nhlt_endpoint *epnt; 340bc2bd45bSSriram Periyasamy struct nhlt_fmt *fmt; 341bc2bd45bSSriram Periyasamy int i; 342bc2bd45bSSriram Periyasamy u8 id; 343bc2bd45bSSriram Periyasamy 344bc2bd45bSSriram Periyasamy epnt = (struct nhlt_endpoint *)nhlt->desc; 345bc2bd45bSSriram Periyasamy for (i = 0; i < nhlt->endpoint_count; i++) { 346bc2bd45bSSriram Periyasamy if (epnt->linktype == NHLT_LINK_SSP) { 347bc2bd45bSSriram Periyasamy id = epnt->virtual_bus_id; 348bc2bd45bSSriram Periyasamy 349bc2bd45bSSriram Periyasamy fmt = (struct nhlt_fmt *)(epnt->config.caps 350bc2bd45bSSriram Periyasamy + epnt->config.size); 351bc2bd45bSSriram Periyasamy 352bc2bd45bSSriram Periyasamy skl_get_ssp_clks(skl, ssp_clks, fmt, id); 353bc2bd45bSSriram Periyasamy skl_get_mclk(skl, ssp_clks, fmt, id); 354bc2bd45bSSriram Periyasamy } 355bc2bd45bSSriram Periyasamy epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); 356bc2bd45bSSriram Periyasamy } 357bc2bd45bSSriram Periyasamy } 358