^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * skl-nhlt.c - Intel SKL Platform NHLT parsing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015 Intel Corp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Sanjiv Kumar <sanjiv.kumar@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sound/intel-nhlt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "skl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "skl-i2s.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static struct nhlt_specific_cfg *skl_get_specific_cfg(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct device *dev, struct nhlt_fmt *fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u8 no_ch, u32 rate, u16 bps, u8 linktype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct nhlt_specific_cfg *sp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct wav_fmt *wfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct nhlt_fmt_cfg *fmt_config = fmt->fmt_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) dev_dbg(dev, "Format count =%d\n", fmt->fmt_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) for (i = 0; i < fmt->fmt_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) wfmt = &fmt_config->fmt_ext.fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", wfmt->channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) wfmt->bits_per_sample, wfmt->samples_per_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (wfmt->channels == no_ch && wfmt->bits_per_sample == bps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * if link type is dmic ignore rate check as the blob is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * generic for all rates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) sp_config = &fmt_config->config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (linktype == NHLT_LINK_DMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return sp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (wfmt->samples_per_sec == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return sp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) fmt_config = (struct nhlt_fmt_cfg *)(fmt_config->config.caps +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) fmt_config->config.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static void dump_config(struct device *dev, u32 instance_id, u8 linktype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 s_fmt, u8 num_channels, u32 s_rate, u8 dirn, u16 bps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) dev_dbg(dev, "Input configuration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) dev_dbg(dev, "ch=%d fmt=%d s_rate=%d\n", num_channels, s_fmt, s_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) dev_dbg(dev, "vbus_id=%d link_type=%d\n", instance_id, linktype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) dev_dbg(dev, "bits_per_sample=%d\n", bps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static bool skl_check_ep_match(struct device *dev, struct nhlt_endpoint *epnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 instance_id, u8 link_type, u8 dirn, u8 dev_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) dev_dbg(dev, "vbus_id=%d link_type=%d dir=%d dev_type = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) epnt->virtual_bus_id, epnt->linktype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) epnt->direction, epnt->device_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if ((epnt->virtual_bus_id == instance_id) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) (epnt->linktype == link_type) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) (epnt->direction == dirn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* do not check dev_type for DMIC link type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (epnt->linktype == NHLT_LINK_DMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (epnt->device_type == dev_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct nhlt_specific_cfg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *skl_get_ep_blob(struct skl_dev *skl, u32 instance, u8 link_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u8 s_fmt, u8 num_ch, u32 s_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u8 dirn, u8 dev_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct nhlt_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct nhlt_endpoint *epnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct hdac_bus *bus = skl_to_bus(skl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct device *dev = bus->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct nhlt_specific_cfg *sp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct nhlt_acpi_table *nhlt = skl->nhlt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u16 bps = (s_fmt == 16) ? 16 : 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u8 j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) dump_config(dev, instance, link_type, s_fmt, num_ch, s_rate, dirn, bps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) epnt = (struct nhlt_endpoint *)nhlt->desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dev_dbg(dev, "endpoint count =%d\n", nhlt->endpoint_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) for (j = 0; j < nhlt->endpoint_count; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (skl_check_ep_match(dev, epnt, instance, link_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dirn, dev_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) fmt = (struct nhlt_fmt *)(epnt->config.caps +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) epnt->config.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sp_config = skl_get_specific_cfg(dev, fmt, num_ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) s_rate, bps, link_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (sp_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return sp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void skl_nhlt_trim_space(char *trim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) char *s = trim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) for (i = 0; s[i]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (!isspace(s[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) s[cnt++] = s[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) s[cnt] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int skl_nhlt_update_topology_bin(struct skl_dev *skl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct hdac_bus *bus = skl_to_bus(skl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct device *dev = bus->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) dev_dbg(dev, "oem_id %.6s, oem_table_id %.8s oem_revision %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) nhlt->header.oem_id, nhlt->header.oem_table_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) nhlt->header.oem_revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) snprintf(skl->tplg_name, sizeof(skl->tplg_name), "%x-%.6s-%.8s-%d%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) nhlt->header.oem_revision, "-tplg.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) skl_nhlt_trim_space(skl->tplg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static ssize_t skl_nhlt_platform_id_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct pci_dev *pci = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct hdac_bus *bus = pci_get_drvdata(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct skl_dev *skl = bus_to_skl(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) char platform_id[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) sprintf(platform_id, "%x-%.6s-%.8s-%d", skl->pci_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) nhlt->header.oem_id, nhlt->header.oem_table_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) nhlt->header.oem_revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) skl_nhlt_trim_space(platform_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return sprintf(buf, "%s\n", platform_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static DEVICE_ATTR(platform_id, 0444, skl_nhlt_platform_id_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int skl_nhlt_create_sysfs(struct skl_dev *skl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct device *dev = &skl->pci->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (sysfs_create_file(&dev->kobj, &dev_attr_platform_id.attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dev_warn(dev, "Error creating sysfs entry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) void skl_nhlt_remove_sysfs(struct skl_dev *skl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct device *dev = &skl->pci->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (skl->nhlt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) sysfs_remove_file(&dev->kobj, &dev_attr_platform_id.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Queries NHLT for all the fmt configuration for a particular endpoint and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * stores all possible rates supported in a rate table for the corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * sclk/sclkfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct nhlt_fmt *fmt, u8 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct skl_i2s_config_blob_ext *i2s_config_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct skl_i2s_config_blob_legacy *i2s_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct skl_clk_parent_src *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct skl_ssp_clk *sclk, *sclkfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct nhlt_fmt_cfg *fmt_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct wav_fmt_ext *wav_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) bool present = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int rate_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u16 channels, bps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u8 clk_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u32 fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) sclk = &ssp_clks[SKL_SCLK_OFS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) sclkfs = &ssp_clks[SKL_SCLKFS_OFS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (fmt->fmt_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) for (i = 0; i < fmt->fmt_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) fmt_cfg = &fmt->fmt_config[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) wav_fmt = &fmt_cfg->fmt_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) channels = wav_fmt->fmt.channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) bps = wav_fmt->fmt.bits_per_sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) fs = wav_fmt->fmt.samples_per_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * In case of TDM configuration on a ssp, there can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * be more than one blob in which channel masks are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * different for each usecase for a specific rate and bps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * But the sclk rate will be generated for the total
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * number of channels used for that endpoint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * So for the given fs and bps, choose blob which has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * the superset of all channels for that endpoint and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * derive the rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) for (j = i; j < fmt->fmt_count; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) fmt_cfg = &fmt->fmt_config[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) wav_fmt = &fmt_cfg->fmt_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if ((fs == wav_fmt->fmt.samples_per_sec) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) (bps == wav_fmt->fmt.bits_per_sample))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) channels = max_t(u16, channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) wav_fmt->fmt.channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) rate = channels * bps * fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* check if the rate is added already to the given SSP's sclk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) for (j = 0; (j < SKL_MAX_CLK_RATES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) (sclk[id].rate_cfg[j].rate != 0); j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (sclk[id].rate_cfg[j].rate == rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) present = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* Fill rate and parent for sclk/sclkfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) i2s_config_ext = (struct skl_i2s_config_blob_ext *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) fmt->fmt_config[0].config.caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* MCLK Divider Source Select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) i2s_config = ext_to_legacy_blob(i2s_config_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) clk_src = get_clk_src(i2s_config->mclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) SKL_MNDSS_DIV_CLK_SRC_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) clk_src = get_clk_src(i2s_config_ext->mclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) SKL_MNDSS_DIV_CLK_SRC_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) parent = skl_get_parent_clk(clk_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * Do not copy the config data if there is no parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * clock available for this clock source select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) sclk[id].rate_cfg[rate_index].rate = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) sclk[id].rate_cfg[rate_index].config = fmt_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) sclkfs[id].rate_cfg[rate_index].rate = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) sclkfs[id].rate_cfg[rate_index].config = fmt_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) sclk[id].parent_name = parent->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) sclkfs[id].parent_name = parent->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) rate_index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static void skl_get_mclk(struct skl_dev *skl, struct skl_ssp_clk *mclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct nhlt_fmt *fmt, u8 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct skl_i2s_config_blob_ext *i2s_config_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct skl_i2s_config_blob_legacy *i2s_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct nhlt_specific_cfg *fmt_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct skl_clk_parent_src *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) u32 clkdiv, div_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) u8 clk_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) fmt_cfg = &fmt->fmt_config[0].config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) i2s_config_ext = (struct skl_i2s_config_blob_ext *)fmt_cfg->caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* MCLK Divider Source Select and divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (is_legacy_blob(i2s_config_ext->hdr.sig)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) i2s_config = ext_to_legacy_blob(i2s_config_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) clk_src = get_clk_src(i2s_config->mclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) SKL_MCLK_DIV_CLK_SRC_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) clkdiv = i2s_config->mclk.mdivr &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) SKL_MCLK_DIV_RATIO_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) clk_src = get_clk_src(i2s_config_ext->mclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) SKL_MCLK_DIV_CLK_SRC_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) clkdiv = i2s_config_ext->mclk.mdivr[0] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) SKL_MCLK_DIV_RATIO_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /* bypass divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) div_ratio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (clkdiv != SKL_MCLK_DIV_RATIO_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* Divider is 2 + clkdiv */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) div_ratio = clkdiv + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* Calculate MCLK rate from source using div value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) parent = skl_get_parent_clk(clk_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) mclk[id].rate_cfg[0].rate = parent->rate/div_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) mclk[id].rate_cfg[0].config = &fmt->fmt_config[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) mclk[id].parent_name = parent->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) void skl_get_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct nhlt_endpoint *epnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct nhlt_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u8 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) epnt = (struct nhlt_endpoint *)nhlt->desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) for (i = 0; i < nhlt->endpoint_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (epnt->linktype == NHLT_LINK_SSP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) id = epnt->virtual_bus_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) fmt = (struct nhlt_fmt *)(epnt->config.caps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) + epnt->config.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) skl_get_ssp_clks(skl, ssp_clks, fmt, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) skl_get_mclk(skl, ssp_clks, fmt, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }