diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/cs35l56.c | 8 | ||||
-rw-r--r-- | sound/soc/codecs/es8316.c | 19 | ||||
-rw-r--r-- | sound/soc/intel/boards/sof_cirrus_common.c | 7 | ||||
-rw-r--r-- | sound/soc/intel/boards/sof_sdw.c | 181 | ||||
-rw-r--r-- | sound/soc/intel/boards/sof_sdw_common.h | 3 | ||||
-rw-r--r-- | sound/soc/intel/boards/sof_sdw_max98373.c | 22 | ||||
-rw-r--r-- | sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 17 | ||||
-rw-r--r-- | sound/soc/sof/intel/apl.c | 4 | ||||
-rw-r--r-- | sound/soc/sof/intel/cnl.c | 4 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-common-ops.c | 1 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-dsp.c | 60 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda.h | 6 | ||||
-rw-r--r-- | sound/soc/sof/intel/icl.c | 4 | ||||
-rw-r--r-- | sound/soc/sof/intel/mtl.c | 2 | ||||
-rw-r--r-- | sound/soc/sof/intel/tgl.c | 4 |
15 files changed, 224 insertions, 118 deletions
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index c0a857cfb8cb..46762f7f1449 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -859,10 +859,8 @@ static void cs35l56_dsp_work(struct work_struct *work) } ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN); - if (ret) { - dev_dbg(cs35l56->dev, "%s: CS35L56_MBOX_CMD_SHUTDOWN ret %d\n", __func__, ret); + if (ret) goto err; - } if (cs35l56->rev < CS35L56_REVID_B0) reg = CS35L56_DSP1_PM_CUR_STATE_A1; @@ -1033,9 +1031,7 @@ int cs35l56_runtime_suspend(struct device *dev) * Enable auto-hibernate. If it is woken by some other wake source * it will automatically return to hibernate. */ - ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); - if (ret) - dev_warn(cs35l56->dev, "ALLOW_HIBERNATE failed: %d\n", ret); + cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE); /* * Must enter cache-only first so there can't be any more register diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index f7d7a9c91e04..a27d80956459 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -803,14 +803,15 @@ static const struct snd_soc_component_driver soc_component_dev_es8316 = { .endianness = 1, }; -static const struct regmap_range es8316_volatile_ranges[] = { - regmap_reg_range(ES8316_GPIO_FLAG, ES8316_GPIO_FLAG), -}; - -static const struct regmap_access_table es8316_volatile_table = { - .yes_ranges = es8316_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(es8316_volatile_ranges), -}; +static bool es8316_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ES8316_GPIO_FLAG: + return true; + default: + return false; + } +} static const struct regmap_config es8316_regmap = { .reg_bits = 8, @@ -818,7 +819,7 @@ static const struct regmap_config es8316_regmap = { .use_single_read = true, .use_single_write = true, .max_register = 0x53, - .volatile_table = &es8316_volatile_table, + .volatile_reg = es8316_volatile_reg, .cache_type = REGCACHE_RBTREE, }; diff --git a/sound/soc/intel/boards/sof_cirrus_common.c b/sound/soc/intel/boards/sof_cirrus_common.c index 851c516c8f5b..8b8b07e4f2fe 100644 --- a/sound/soc/intel/boards/sof_cirrus_common.c +++ b/sound/soc/intel/boards/sof_cirrus_common.c @@ -168,11 +168,16 @@ static int cs35l41_compute_codec_conf(void) continue; } physdev = get_device(acpi_get_first_physical_node(adev)); + acpi_dev_put(adev); + if (!physdev) { + pr_devel("Cannot find physical node for HID %s UID %u (%s)\n", CS35L41_HID, + uid, cs35l41_name_prefixes[uid]); + return 0; + } cs35l41_components[sz].name = dev_name(physdev); cs35l41_components[sz].dai_name = CS35L41_CODEC_DAI; cs35l41_codec_conf[sz].dlc.name = dev_name(physdev); cs35l41_codec_conf[sz].name_prefix = cs35l41_name_prefixes[uid]; - acpi_dev_put(adev); sz++; } diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6897705a193c..6faf4a43eaf5 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -621,7 +621,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {true, true}, .dai_name = "max98373-aif1", .init = sof_sdw_mx8373_init, - .codec_card_late_probe = sof_sdw_mx8373_late_probe, .codec_type = SOF_SDW_CODEC_TYPE_AMP, }, { @@ -733,34 +732,36 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li int stream; u64 adr; - adr = link->adr_d->adr; - codec_index = find_codec_info_part(adr); - if (codec_index < 0) - return codec_index; + for (i = 0; i < link->num_adr; i++) { + adr = link->adr_d[i].adr; + codec_index = find_codec_info_part(adr); + if (codec_index < 0) + return codec_index; - if (codec_info_list[codec_index].codec_type < _codec_type) - dev_warn(dev, - "Unexpected address table ordering. Expected order: jack -> amp -> mic\n"); + if (codec_info_list[codec_index].codec_type < _codec_type) + dev_warn(dev, + "Unexpected address table ordering. Expected order: jack -> amp -> mic\n"); - _codec_type = codec_info_list[codec_index].codec_type; + _codec_type = codec_info_list[codec_index].codec_type; - endpoint = link->adr_d->endpoints; + endpoint = link->adr_d[i].endpoints; - /* count DAI number for playback and capture */ - for_each_pcm_streams(stream) { - if (!codec_info_list[codec_index].direction[stream]) - continue; + /* count DAI number for playback and capture */ + for_each_pcm_streams(stream) { + if (!codec_info_list[codec_index].direction[stream]) + continue; - (*sdw_cpu_dai_num)++; + (*sdw_cpu_dai_num)++; - /* count BE for each non-aggregated slave or group */ - if (!endpoint->aggregated || no_aggregation || - !group_visited[endpoint->group_id]) - (*sdw_be_num)++; - } + /* count BE for each non-aggregated slave or group */ + if (!endpoint->aggregated || no_aggregation || + !group_visited[endpoint->group_id]) + (*sdw_be_num)++; + } - if (endpoint->aggregated) - group_visited[endpoint->group_id] = true; + if (endpoint->aggregated) + group_visited[endpoint->group_id] = true; + } } return 0; @@ -830,17 +831,19 @@ static int create_codec_dai_name(struct device *dev, int offset, struct snd_soc_codec_conf *codec_conf, int codec_count, - int *codec_conf_index) + int *codec_conf_index, + int adr_index) { + int _codec_index = -1; int i; /* sanity check */ - if (*codec_conf_index + link->num_adr > codec_count) { + if (*codec_conf_index + link->num_adr - adr_index > codec_count) { dev_err(dev, "codec_conf: out-of-bounds access requested\n"); return -EINVAL; } - for (i = 0; i < link->num_adr; i++) { + for (i = adr_index; i < link->num_adr; i++) { unsigned int sdw_version, unique_id, mfg_id; unsigned int link_id, part_id, class_id; int codec_index, comp_index; @@ -856,7 +859,7 @@ static int create_codec_dai_name(struct device *dev, part_id = SDW_PART_ID(adr); class_id = SDW_CLASS_ID(adr); - comp_index = i + offset; + comp_index = i - adr_index + offset; if (is_unique_device(link, sdw_version, mfg_id, part_id, class_id, i)) { codec_str = "sdw:%01x:%04x:%04x:%02x"; @@ -878,6 +881,11 @@ static int create_codec_dai_name(struct device *dev, codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; + if (_codec_index != -1 && codec_index != _codec_index) { + dev_dbg(dev, "Different devices on the same sdw link\n"); + break; + } + _codec_index = codec_index; codec[comp_index].dai_name = codec_info_list[codec_index].dai_name; @@ -944,16 +952,16 @@ static int set_codec_init_func(struct snd_soc_card *card, static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, struct device *dev, int *cpu_dai_id, int *cpu_dai_num, int *codec_num, unsigned int *group_id, - bool *group_generated) + bool *group_generated, int adr_index) { const struct snd_soc_acpi_adr_device *adr_d; const struct snd_soc_acpi_link_adr *adr_next; bool no_aggregation; int index = 0; + int i; no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; - *codec_num = adr_link->num_adr; - adr_d = adr_link->adr_d; + adr_d = &adr_link->adr_d[adr_index]; /* make sure the link mask has a single bit set */ if (!is_power_of_2(adr_link->mask)) @@ -962,12 +970,21 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, cpu_dai_id[index++] = ffs(adr_link->mask) - 1; if (!adr_d->endpoints->aggregated || no_aggregation) { *cpu_dai_num = 1; + *codec_num = 1; *group_id = 0; return 0; } *group_id = adr_d->endpoints->group_id; + /* Count endpoints with the same group_id in the adr_link */ + *codec_num = 0; + for (i = 0; i < adr_link->num_adr; i++) { + if (adr_link->adr_d[i].endpoints->aggregated && + adr_link->adr_d[i].endpoints->group_id == *group_id) + (*codec_num)++; + } + /* gather other link ID of slaves in the same group */ for (adr_next = adr_link + 1; adr_next && adr_next->num_adr; adr_next++) { @@ -988,7 +1005,11 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, } cpu_dai_id[index++] = ffs(adr_next->mask) - 1; - *codec_num += adr_next->num_adr; + for (i = 0; i < adr_next->num_adr; i++) { + if (adr_next->adr_d[i].endpoints->aggregated && + adr_next->adr_d[i].endpoints->group_id == *group_id) + (*codec_num)++; + } } /* @@ -1001,6 +1022,8 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, return 0; } +static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; + static int create_sdw_dailink(struct snd_soc_card *card, struct device *dev, int *link_index, struct snd_soc_dai_link *dai_links, @@ -1011,7 +1034,9 @@ static int create_sdw_dailink(struct snd_soc_card *card, struct snd_soc_codec_conf *codec_conf, int codec_count, int *link_id, int *codec_conf_index, - bool *ignore_pch_dmic) + bool *ignore_pch_dmic, + bool append_codec_type, + int adr_index) { const struct snd_soc_acpi_link_adr *link_next; struct snd_soc_dai_link_component *codecs; @@ -1027,7 +1052,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int k; ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, - &group_id, group_generated); + &group_id, group_generated, adr_index); if (ret) return ret; @@ -1050,7 +1075,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, continue; ret = create_codec_dai_name(dev, link_next, codecs, codec_idx, - codec_conf, codec_count, codec_conf_index); + codec_conf, codec_count, codec_conf_index, adr_index); if (ret < 0) return ret; @@ -1060,7 +1085,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, } /* find codec info to create BE DAI */ - codec_index = find_codec_info_part(link->adr_d[0].adr); + codec_index = find_codec_info_part(link->adr_d[adr_index].adr); if (codec_index < 0) return codec_index; @@ -1087,14 +1112,22 @@ static int create_sdw_dailink(struct snd_soc_card *card, static const char * const sdw_stream_name[] = { "SDW%d-Playback", "SDW%d-Capture", + "SDW%d-Playback-%s", + "SDW%d-Capture-%s", }; if (!codec_info_list[codec_index].direction[stream]) continue; /* create stream name according to first link id */ - name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream], cpu_dai_id[0]); + if (append_codec_type) { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream + 2], cpu_dai_id[0], + type_strings[codec_info_list[codec_index].codec_type]); + } else { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], cpu_dai_id[0]); + } if (!name) return -ENOMEM; @@ -1210,6 +1243,7 @@ static int sof_card_dai_links_create(struct device *dev, const struct snd_soc_acpi_link_adr *adr_link; struct snd_soc_dai_link_component *cpus; struct snd_soc_codec_conf *codec_conf; + bool append_codec_type = false; bool ignore_pch_dmic = false; int codec_conf_count; int codec_conf_index = 0; @@ -1301,31 +1335,54 @@ static int sof_card_dai_links_create(struct device *dev, for (i = 0; i < SDW_MAX_GROUPS; i++) group_generated[i] = false; - /* generate DAI links by each sdw link */ for (; adr_link->num_adr; adr_link++) { - const struct snd_soc_acpi_endpoint *endpoint; - - endpoint = adr_link->adr_d->endpoints; - if (endpoint->aggregated && !endpoint->group_id) { - dev_err(dev, "invalid group id on link %x", - adr_link->mask); - continue; + /* + * If there are two or more different devices on the same sdw link, we have to + * append the codec type to the dai link name to prevent duplicated dai link name. + * The same type devices on the same sdw link will be in the same + * snd_soc_acpi_adr_device array. They won't be described in different adr_links. + */ + for (i = 0; i < adr_link->num_adr; i++) { + for (j = 0; j < i; j++) { + if ((SDW_PART_ID(adr_link->adr_d[i].adr) != + SDW_PART_ID(adr_link->adr_d[j].adr)) || + (SDW_MFG_ID(adr_link->adr_d[i].adr) != + SDW_MFG_ID(adr_link->adr_d[i].adr))) { + append_codec_type = true; + goto out; + } + } } + } +out: - /* this group has been generated */ - if (endpoint->aggregated && - group_generated[endpoint->group_id]) - continue; + /* generate DAI links by each sdw link */ + for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { + for (i = 0; i < adr_link->num_adr; i++) { + const struct snd_soc_acpi_endpoint *endpoint; - ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, - sdw_cpu_dai_num, cpus, adr_link, - &cpu_id, group_generated, - codec_conf, codec_conf_count, - &be_id, &codec_conf_index, - &ignore_pch_dmic); - if (ret < 0) { - dev_err(dev, "failed to create dai link %d", link_index); - return ret; + endpoint = adr_link->adr_d[i].endpoints; + if (endpoint->aggregated && !endpoint->group_id) { + dev_err(dev, "invalid group id on link %x", + adr_link->mask); + continue; + } + + /* this group has been generated */ + if (endpoint->aggregated && + group_generated[endpoint->group_id]) + continue; + + ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num, + sdw_cpu_dai_num, cpus, adr_link, + &cpu_id, group_generated, + codec_conf, codec_conf_count, + &be_id, &codec_conf_index, + &ignore_pch_dmic, append_codec_type, i); + if (ret < 0) { + dev_err(dev, "failed to create dai link %d", link_index); + return ret; + } } } @@ -1490,12 +1547,12 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card) int i; for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - if (!codec_info_list[i].late_probe) - continue; + if (codec_info_list[i].codec_card_late_probe) { + ret = codec_info_list[i].codec_card_late_probe(card); - ret = codec_info_list[i].codec_card_late_probe(card); - if (ret < 0) - return ret; + if (ret < 0) + return ret; + } } if (ctx->idisp_codec) diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 350010b0e5f4..081ab7eac5b6 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -74,7 +74,6 @@ struct sof_sdw_codec_info { bool playback); int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - bool late_probe; int (*codec_card_late_probe)(struct snd_soc_card *card); }; @@ -159,8 +158,6 @@ int sof_sdw_mx8373_init(struct snd_soc_card *card, struct sof_sdw_codec_info *info, bool playback); -int sof_sdw_mx8373_late_probe(struct snd_soc_card *card); - /* RT5682 support */ int sof_sdw_rt5682_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index 77a3f32db11e..3d7df58c0f1d 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -120,6 +120,16 @@ static const struct snd_soc_ops max_98373_sdw_ops = { .shutdown = sdw_shutdown, }; +static int mx8373_sdw_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_dapm_context *dapm = &card->dapm; + + /* Disable Left and Right Spk pin after boot */ + snd_soc_dapm_disable_pin(dapm, "Left Spk"); + snd_soc_dapm_disable_pin(dapm, "Right Spk"); + return snd_soc_dapm_sync(dapm); +} + int sof_sdw_mx8373_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, @@ -130,19 +140,9 @@ int sof_sdw_mx8373_init(struct snd_soc_card *card, if (info->amp_num == 2) dai_links->init = spk_init; - info->late_probe = true; + info->codec_card_late_probe = mx8373_sdw_late_probe; dai_links->ops = &max_98373_sdw_ops; return 0; } - -int sof_sdw_mx8373_late_probe(struct snd_soc_card *card) -{ - struct snd_soc_dapm_context *dapm = &card->dapm; - - /* Disable Left and Right Spk pin after boot */ - snd_soc_dapm_disable_pin(dapm, "Left Spk"); - snd_soc_dapm_disable_pin(dapm, "Right Spk"); - return snd_soc_dapm_sync(dapm); -} diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 13cbd8e9d41f..749d371a86ae 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -284,6 +284,15 @@ static const struct snd_soc_acpi_link_adr rpl_sdw_rt1316_link12_rt714_link0[] = {} }; +static const struct snd_soc_acpi_link_adr rplp_crb[] = { + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt711_sdca_2_adr), + .adr_d = rt711_sdca_2_adr, + }, + {} +}; + static const struct snd_soc_acpi_codecs rpl_rt5682_hp = { .num_codecs = 2, .codecs = {"10EC5682", "RTL5682"}, @@ -348,7 +357,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[] = { .link_mask = 0x1, /* link0 required */ .links = rpl_rvp, .drv_name = "sof_sdw", - .sof_tplg_filename = "sof-rpl-rt711.tplg", + .sof_tplg_filename = "sof-rpl-rt711-l0.tplg", + }, + { + .link_mask = 0x4, /* link2 required */ + .links = rplp_crb, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-rpl-rt711-l2.tplg", }, {}, }; diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 0e7a7e4ad976..e1f25a8f0c32 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -48,6 +48,8 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_apl_ops.ipc_dump = hda_ipc_dump; + + sof_apl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -73,6 +75,8 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_apl_ops.ipc_dump = hda_ipc4_dump; + + sof_apl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index a08a77fa946b..a95222e53ecf 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -395,6 +395,8 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_cnl_ops.ipc_dump = cnl_ipc_dump; + + sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -420,6 +422,8 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_cnl_ops.ipc_dump = cnl_ipc4_dump; + + sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index 397303b3ac9d..8e1cd0babd32 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -89,7 +89,6 @@ struct snd_sof_dsp_ops sof_hda_common_ops = { .runtime_resume = hda_dsp_runtime_resume, .runtime_idle = hda_dsp_runtime_idle, .set_hw_params_upon_resume = hda_dsp_set_hw_params_upon_resume, - .set_power_state = hda_dsp_set_power_state, /* ALSA HW info flags */ .hw_info = SNDRV_PCM_INFO_MMAP | diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 77df536cf901..44f39a520bb3 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -574,31 +574,11 @@ static void hda_dsp_state_log(struct snd_sof_dev *sdev) * is called again either because of a new IPC sent to the DSP or * during system suspend/resume. */ -int hda_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state) +static int hda_dsp_set_power_state(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) { int ret = 0; - /* - * When the DSP is already in D0I3 and the target state is D0I3, - * it could be the case that the DSP is in D0I3 during S0 - * and the system is suspending to S0Ix. Therefore, - * hda_dsp_set_D0_state() must be called to disable trace DMA - * by sending the PM_GATE IPC to the FW. - */ - if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && - sdev->system_suspend_target == SOF_SUSPEND_S0IX) - goto set_state; - - /* - * For all other cases, return without doing anything if - * the DSP is already in the target state. - */ - if (target_state->state == sdev->dsp_power_state.state && - target_state->substate == sdev->dsp_power_state.substate) - return 0; - -set_state: switch (target_state->state) { case SOF_DSP_PM_D0: ret = hda_dsp_set_D0_state(sdev, target_state); @@ -630,6 +610,42 @@ set_state: return ret; } +int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) +{ + /* + * When the DSP is already in D0I3 and the target state is D0I3, + * it could be the case that the DSP is in D0I3 during S0 + * and the system is suspending to S0Ix. Therefore, + * hda_dsp_set_D0_state() must be called to disable trace DMA + * by sending the PM_GATE IPC to the FW. + */ + if (target_state->substate == SOF_HDA_DSP_PM_D0I3 && + sdev->system_suspend_target == SOF_SUSPEND_S0IX) + return hda_dsp_set_power_state(sdev, target_state); + + /* + * For all other cases, return without doing anything if + * the DSP is already in the target state. + */ + if (target_state->state == sdev->dsp_power_state.state && + target_state->substate == sdev->dsp_power_state.substate) + return 0; + + return hda_dsp_set_power_state(sdev, target_state); +} + +int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state) +{ + /* Return without doing anything if the DSP is already in the target state */ + if (target_state->state == sdev->dsp_power_state.state && + target_state->substate == sdev->dsp_power_state.substate) + return 0; + + return hda_dsp_set_power_state(sdev, target_state); +} + /* * Audio DSP states may transform as below:- * diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 0e0cfa81a8f2..c4befacde23e 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -584,8 +584,10 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev); void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev); bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask); -int hda_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state); +int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state); +int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target_state); int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state); int hda_dsp_resume(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 435941a1692f..0f249efc6a5a 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -116,6 +116,8 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_icl_ops.ipc_dump = cnl_ipc_dump; + + sof_icl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -141,6 +143,8 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_icl_ops.ipc_dump = cnl_ipc4_dump; + + sof_icl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* debug */ diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 9f969e07fc27..46caf3ccde66 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -668,6 +668,8 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev) /* set DAI ops */ hda_set_dai_drv_ops(sdev, &sof_mtl_ops); + sof_mtl_ops.set_power_state = hda_dsp_set_power_state_ipc4; + return 0; }; EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 58ac3a46e6a7..2713b7dc7931 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -71,6 +71,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_tgl_ops.ipc_dump = cnl_ipc_dump; + + sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { @@ -96,6 +98,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_tgl_ops.ipc_dump = cnl_ipc4_dump; + + sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } /* set DAI driver ops */ |