18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci// Copyright (c) 2020 Intel Corporation 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci/* 58c2ecf20Sopenharmony_ci * sof_sdw_rt1316 - Helpers to handle RT1316 from generic machine driver 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/device.h> 98c2ecf20Sopenharmony_ci#include <linux/errno.h> 108c2ecf20Sopenharmony_ci#include <sound/control.h> 118c2ecf20Sopenharmony_ci#include <sound/soc.h> 128c2ecf20Sopenharmony_ci#include <sound/soc-acpi.h> 138c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h> 148c2ecf20Sopenharmony_ci#include "sof_sdw_common.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget rt1316_widgets[] = { 178c2ecf20Sopenharmony_ci SND_SOC_DAPM_SPK("Speaker", NULL), 188c2ecf20Sopenharmony_ci}; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci * dapm routes for rt1316 will be registered dynamically according 228c2ecf20Sopenharmony_ci * to the number of rt1316 used. The first two entries will be registered 238c2ecf20Sopenharmony_ci * for one codec case, and the last two entries are also registered 248c2ecf20Sopenharmony_ci * if two 1316s are used. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route rt1316_map[] = { 278c2ecf20Sopenharmony_ci { "Speaker", NULL, "rt1316-1 SPOL" }, 288c2ecf20Sopenharmony_ci { "Speaker", NULL, "rt1316-1 SPOR" }, 298c2ecf20Sopenharmony_ci { "Speaker", NULL, "rt1316-2 SPOL" }, 308c2ecf20Sopenharmony_ci { "Speaker", NULL, "rt1316-2 SPOR" }, 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt1316_controls[] = { 348c2ecf20Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Speaker"), 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic int first_spk_init(struct snd_soc_pcm_runtime *rtd) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci struct snd_soc_card *card = rtd->card; 408c2ecf20Sopenharmony_ci int ret; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci card->components = devm_kasprintf(card->dev, GFP_KERNEL, 438c2ecf20Sopenharmony_ci "%s spk:rt1316", 448c2ecf20Sopenharmony_ci card->components); 458c2ecf20Sopenharmony_ci if (!card->components) 468c2ecf20Sopenharmony_ci return -ENOMEM; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci ret = snd_soc_add_card_controls(card, rt1316_controls, 498c2ecf20Sopenharmony_ci ARRAY_SIZE(rt1316_controls)); 508c2ecf20Sopenharmony_ci if (ret) { 518c2ecf20Sopenharmony_ci dev_err(card->dev, "rt1316 controls addition failed: %d\n", ret); 528c2ecf20Sopenharmony_ci return ret; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci ret = snd_soc_dapm_new_controls(&card->dapm, rt1316_widgets, 568c2ecf20Sopenharmony_ci ARRAY_SIZE(rt1316_widgets)); 578c2ecf20Sopenharmony_ci if (ret) { 588c2ecf20Sopenharmony_ci dev_err(card->dev, "rt1316 widgets addition failed: %d\n", ret); 598c2ecf20Sopenharmony_ci return ret; 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map, 2); 638c2ecf20Sopenharmony_ci if (ret) 648c2ecf20Sopenharmony_ci dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci return ret; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int second_spk_init(struct snd_soc_pcm_runtime *rtd) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct snd_soc_card *card = rtd->card; 728c2ecf20Sopenharmony_ci int ret; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map + 2, 2); 758c2ecf20Sopenharmony_ci if (ret) 768c2ecf20Sopenharmony_ci dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return ret; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic int all_spk_init(struct snd_soc_pcm_runtime *rtd) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci int ret; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci ret = first_spk_init(rtd); 868c2ecf20Sopenharmony_ci if (ret) 878c2ecf20Sopenharmony_ci return ret; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci return second_spk_init(rtd); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciint sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link, 938c2ecf20Sopenharmony_ci struct snd_soc_dai_link *dai_links, 948c2ecf20Sopenharmony_ci struct sof_sdw_codec_info *info, 958c2ecf20Sopenharmony_ci bool playback) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci /* Count amp number and do init on playback link only. */ 988c2ecf20Sopenharmony_ci if (!playback) 998c2ecf20Sopenharmony_ci return 0; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci info->amp_num++; 1028c2ecf20Sopenharmony_ci if (info->amp_num == 1) 1038c2ecf20Sopenharmony_ci dai_links->init = first_spk_init; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (info->amp_num == 2) { 1068c2ecf20Sopenharmony_ci /* 1078c2ecf20Sopenharmony_ci * if two 1316s are in one dai link, the init function 1088c2ecf20Sopenharmony_ci * in this dai link will be first set for the first speaker, 1098c2ecf20Sopenharmony_ci * and it should be reset to initialize all speakers when 1108c2ecf20Sopenharmony_ci * the second speaker is found. 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci if (dai_links->init) 1138c2ecf20Sopenharmony_ci dai_links->init = all_spk_init; 1148c2ecf20Sopenharmony_ci else 1158c2ecf20Sopenharmony_ci dai_links->init = second_spk_init; 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci return 0; 1198c2ecf20Sopenharmony_ci} 120