0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <sound/sof.h>
0010 #include "../../codecs/cs35l41.h"
0011 #include "sof_cirrus_common.h"
0012
0013
0014
0015
0016 static const struct snd_kcontrol_new cs35l41_kcontrols[] = {
0017 SOC_DAPM_PIN_SWITCH("WL Spk"),
0018 SOC_DAPM_PIN_SWITCH("WR Spk"),
0019 SOC_DAPM_PIN_SWITCH("TL Spk"),
0020 SOC_DAPM_PIN_SWITCH("TR Spk"),
0021 };
0022
0023 static const struct snd_soc_dapm_widget cs35l41_dapm_widgets[] = {
0024 SND_SOC_DAPM_SPK("WL Spk", NULL),
0025 SND_SOC_DAPM_SPK("WR Spk", NULL),
0026 SND_SOC_DAPM_SPK("TL Spk", NULL),
0027 SND_SOC_DAPM_SPK("TR Spk", NULL),
0028 };
0029
0030 static const struct snd_soc_dapm_route cs35l41_dapm_routes[] = {
0031
0032 {"WL Spk", NULL, "WL SPK"},
0033 {"WR Spk", NULL, "WR SPK"},
0034 {"TL Spk", NULL, "TL SPK"},
0035 {"TR Spk", NULL, "TR SPK"},
0036 };
0037
0038 static struct snd_soc_dai_link_component cs35l41_components[] = {
0039 {
0040 .name = CS35L41_DEV0_NAME,
0041 .dai_name = CS35L41_CODEC_DAI,
0042 },
0043 {
0044 .name = CS35L41_DEV1_NAME,
0045 .dai_name = CS35L41_CODEC_DAI,
0046 },
0047 {
0048 .name = CS35L41_DEV2_NAME,
0049 .dai_name = CS35L41_CODEC_DAI,
0050 },
0051 {
0052 .name = CS35L41_DEV3_NAME,
0053 .dai_name = CS35L41_CODEC_DAI,
0054 },
0055 };
0056
0057
0058
0059
0060
0061
0062
0063
0064 static struct snd_soc_codec_conf cs35l41_codec_conf[] = {
0065 {
0066 .dlc = COMP_CODEC_CONF(CS35L41_DEV0_NAME),
0067 .name_prefix = "TL",
0068 },
0069 {
0070 .dlc = COMP_CODEC_CONF(CS35L41_DEV1_NAME),
0071 .name_prefix = "WL",
0072 },
0073 {
0074 .dlc = COMP_CODEC_CONF(CS35L41_DEV2_NAME),
0075 .name_prefix = "TR",
0076 },
0077 {
0078 .dlc = COMP_CODEC_CONF(CS35L41_DEV3_NAME),
0079 .name_prefix = "WR",
0080 },
0081 };
0082
0083 static int cs35l41_init(struct snd_soc_pcm_runtime *rtd)
0084 {
0085 struct snd_soc_card *card = rtd->card;
0086 int ret;
0087
0088 ret = snd_soc_dapm_new_controls(&card->dapm, cs35l41_dapm_widgets,
0089 ARRAY_SIZE(cs35l41_dapm_widgets));
0090 if (ret) {
0091 dev_err(rtd->dev, "fail to add dapm controls, ret %d\n", ret);
0092 return ret;
0093 }
0094
0095 ret = snd_soc_add_card_controls(card, cs35l41_kcontrols,
0096 ARRAY_SIZE(cs35l41_kcontrols));
0097 if (ret) {
0098 dev_err(rtd->dev, "fail to add card controls, ret %d\n", ret);
0099 return ret;
0100 }
0101
0102 ret = snd_soc_dapm_add_routes(&card->dapm, cs35l41_dapm_routes,
0103 ARRAY_SIZE(cs35l41_dapm_routes));
0104
0105 if (ret)
0106 dev_err(rtd->dev, "fail to add dapm routes, ret %d\n", ret);
0107
0108 return ret;
0109 }
0110
0111
0112
0113
0114
0115
0116
0117 static const struct {
0118 unsigned int rx[2];
0119 } cs35l41_channel_map[] = {
0120 {.rx = {0, 1}},
0121 {.rx = {0, 1}},
0122 {.rx = {1, 0}},
0123 {.rx = {1, 0}},
0124 };
0125
0126 static int cs35l41_hw_params(struct snd_pcm_substream *substream,
0127 struct snd_pcm_hw_params *params)
0128 {
0129 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0130 struct snd_soc_dai *codec_dai;
0131 int clk_freq, i, ret;
0132
0133 clk_freq = sof_dai_get_bclk(rtd);
0134
0135 if (clk_freq <= 0) {
0136 dev_err(rtd->dev, "fail to get bclk freq, ret %d\n", clk_freq);
0137 return -EINVAL;
0138 }
0139
0140 for_each_rtd_codec_dais(rtd, i, codec_dai) {
0141
0142 ret = snd_soc_dai_set_sysclk(codec_dai, CS35L41_CLKID_SCLK,
0143 clk_freq, SND_SOC_CLOCK_IN);
0144 if (ret < 0) {
0145 dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n",
0146 ret);
0147 return ret;
0148 }
0149
0150
0151 ret = snd_soc_component_set_sysclk(codec_dai->component,
0152 CS35L41_CLKID_SCLK, 0,
0153 clk_freq, SND_SOC_CLOCK_IN);
0154 if (ret < 0) {
0155 dev_err(codec_dai->dev, "fail to set component sysclk, ret %d\n",
0156 ret);
0157 return ret;
0158 }
0159
0160
0161 ret = snd_soc_dai_set_channel_map(codec_dai, 0, NULL,
0162 ARRAY_SIZE(cs35l41_channel_map[i].rx),
0163 (unsigned int *)cs35l41_channel_map[i].rx);
0164 if (ret < 0) {
0165 dev_err(codec_dai->dev, "fail to set channel map, ret %d\n",
0166 ret);
0167 return ret;
0168 }
0169 }
0170
0171 return 0;
0172 }
0173
0174 static const struct snd_soc_ops cs35l41_ops = {
0175 .hw_params = cs35l41_hw_params,
0176 };
0177
0178 void cs35l41_set_dai_link(struct snd_soc_dai_link *link)
0179 {
0180 link->codecs = cs35l41_components;
0181 link->num_codecs = ARRAY_SIZE(cs35l41_components);
0182 link->init = cs35l41_init;
0183 link->ops = &cs35l41_ops;
0184 }
0185 EXPORT_SYMBOL_NS(cs35l41_set_dai_link, SND_SOC_INTEL_SOF_CIRRUS_COMMON);
0186
0187 void cs35l41_set_codec_conf(struct snd_soc_card *card)
0188 {
0189 card->codec_conf = cs35l41_codec_conf;
0190 card->num_configs = ARRAY_SIZE(cs35l41_codec_conf);
0191 }
0192 EXPORT_SYMBOL_NS(cs35l41_set_codec_conf, SND_SOC_INTEL_SOF_CIRRUS_COMMON);
0193
0194 MODULE_DESCRIPTION("ASoC Intel SOF Cirrus Logic helpers");
0195 MODULE_LICENSE("GPL");