0001
0002
0003
0004
0005 #include <linux/device.h>
0006 #include <linux/kernel.h>
0007 #include <sound/pcm.h>
0008 #include <sound/pcm_params.h>
0009 #include <sound/soc.h>
0010 #include <sound/soc-acpi.h>
0011 #include <sound/soc-dai.h>
0012 #include <sound/soc-dapm.h>
0013 #include <sound/sof.h>
0014 #include <uapi/sound/asound.h>
0015 #include "../../codecs/rt1011.h"
0016 #include "../../codecs/rt1015.h"
0017 #include "../../codecs/rt1308.h"
0018 #include "sof_realtek_common.h"
0019
0020
0021
0022
0023 static const struct snd_soc_dapm_route speaker_map_lr[] = {
0024
0025 { "Left Spk", NULL, "Left SPO" },
0026 { "Right Spk", NULL, "Right SPO" },
0027 };
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 static struct snd_soc_codec_conf rt1011_codec_confs[] = {
0039 {
0040 .dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME),
0041 .name_prefix = "Left",
0042 },
0043 {
0044 .dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME),
0045 .name_prefix = "Right",
0046 },
0047 };
0048
0049 static struct snd_soc_dai_link_component rt1011_dai_link_components[] = {
0050 {
0051 .name = RT1011_DEV0_NAME,
0052 .dai_name = RT1011_CODEC_DAI,
0053 },
0054 {
0055 .name = RT1011_DEV1_NAME,
0056 .dai_name = RT1011_CODEC_DAI,
0057 },
0058 };
0059
0060 static const struct {
0061 unsigned int tx;
0062 unsigned int rx;
0063 } rt1011_tdm_mask[] = {
0064 {.tx = 0x4, .rx = 0x1},
0065 {.tx = 0x8, .rx = 0x2},
0066 };
0067
0068 static int rt1011_hw_params(struct snd_pcm_substream *substream,
0069 struct snd_pcm_hw_params *params)
0070 {
0071 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0072 struct snd_soc_dai *codec_dai;
0073 int srate, i, ret = 0;
0074
0075 srate = params_rate(params);
0076
0077 for_each_rtd_codec_dais(rtd, i, codec_dai) {
0078
0079 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK,
0080 100 * srate, 256 * srate);
0081 if (ret < 0) {
0082 dev_err(codec_dai->dev, "fail to set pll, ret %d\n",
0083 ret);
0084 return ret;
0085 }
0086
0087 ret = snd_soc_dai_set_sysclk(codec_dai, RT1011_FS_SYS_PRE_S_PLL1,
0088 256 * srate, SND_SOC_CLOCK_IN);
0089 if (ret < 0) {
0090 dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n",
0091 ret);
0092 return ret;
0093 }
0094
0095 if (i >= ARRAY_SIZE(rt1011_tdm_mask)) {
0096 dev_err(codec_dai->dev, "invalid codec index %d\n",
0097 i);
0098 return -ENODEV;
0099 }
0100
0101 ret = snd_soc_dai_set_tdm_slot(codec_dai, rt1011_tdm_mask[i].tx,
0102 rt1011_tdm_mask[i].rx, 4,
0103 params_width(params));
0104 if (ret < 0) {
0105 dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n",
0106 ret);
0107 return ret;
0108 }
0109 }
0110
0111 return 0;
0112 }
0113
0114 static const struct snd_soc_ops rt1011_ops = {
0115 .hw_params = rt1011_hw_params,
0116 };
0117
0118 static int rt1011_init(struct snd_soc_pcm_runtime *rtd)
0119 {
0120 struct snd_soc_card *card = rtd->card;
0121 int ret;
0122
0123 ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr,
0124 ARRAY_SIZE(speaker_map_lr));
0125 if (ret)
0126 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
0127 return ret;
0128 }
0129
0130 void sof_rt1011_dai_link(struct snd_soc_dai_link *link)
0131 {
0132 link->codecs = rt1011_dai_link_components;
0133 link->num_codecs = ARRAY_SIZE(rt1011_dai_link_components);
0134 link->init = rt1011_init;
0135 link->ops = &rt1011_ops;
0136 }
0137 EXPORT_SYMBOL_NS(sof_rt1011_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
0138
0139 void sof_rt1011_codec_conf(struct snd_soc_card *card)
0140 {
0141 card->codec_conf = rt1011_codec_confs;
0142 card->num_configs = ARRAY_SIZE(rt1011_codec_confs);
0143 }
0144 EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = {
0157
0158 { "Left Spk", NULL, "Speaker" },
0159 { "Right Spk", NULL, "Speaker" },
0160 };
0161
0162 static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = {
0163
0164 { "Left Spk", NULL, "Left Speaker" },
0165 { "Right Spk", NULL, "Right Speaker" },
0166 };
0167
0168 static struct snd_soc_codec_conf rt1015p_codec_confs[] = {
0169 {
0170 .dlc = COMP_CODEC_CONF(RT1015P_DEV0_NAME),
0171 .name_prefix = "Left",
0172 },
0173 {
0174 .dlc = COMP_CODEC_CONF(RT1015P_DEV1_NAME),
0175 .name_prefix = "Right",
0176 },
0177 };
0178
0179 static struct snd_soc_dai_link_component rt1015p_dai_link_components[] = {
0180 {
0181 .name = RT1015P_DEV0_NAME,
0182 .dai_name = RT1015P_CODEC_DAI,
0183 },
0184 {
0185 .name = RT1015P_DEV1_NAME,
0186 .dai_name = RT1015P_CODEC_DAI,
0187 },
0188 };
0189
0190 static int rt1015p_get_num_codecs(void)
0191 {
0192 static int dev_num;
0193
0194 if (dev_num)
0195 return dev_num;
0196
0197 if (!acpi_dev_present("RTL1015", "1", -1))
0198 dev_num = 1;
0199 else
0200 dev_num = 2;
0201
0202 return dev_num;
0203 }
0204
0205 static int rt1015p_hw_params(struct snd_pcm_substream *substream,
0206 struct snd_pcm_hw_params *params)
0207 {
0208
0209
0210 return 0;
0211 }
0212
0213 static const struct snd_soc_ops rt1015p_ops = {
0214 .hw_params = rt1015p_hw_params,
0215 };
0216
0217 static int rt1015p_init(struct snd_soc_pcm_runtime *rtd)
0218 {
0219 struct snd_soc_card *card = rtd->card;
0220 int ret;
0221
0222 if (rt1015p_get_num_codecs() == 1)
0223 ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes,
0224 ARRAY_SIZE(rt1015p_1dev_dapm_routes));
0225 else
0226 ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_2dev_dapm_routes,
0227 ARRAY_SIZE(rt1015p_2dev_dapm_routes));
0228 if (ret)
0229 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
0230 return ret;
0231 }
0232
0233 void sof_rt1015p_dai_link(struct snd_soc_dai_link *link)
0234 {
0235 link->codecs = rt1015p_dai_link_components;
0236 link->num_codecs = rt1015p_get_num_codecs();
0237 link->init = rt1015p_init;
0238 link->ops = &rt1015p_ops;
0239 }
0240 EXPORT_SYMBOL_NS(sof_rt1015p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
0241
0242 void sof_rt1015p_codec_conf(struct snd_soc_card *card)
0243 {
0244 if (rt1015p_get_num_codecs() == 1)
0245 return;
0246
0247 card->codec_conf = rt1015p_codec_confs;
0248 card->num_configs = ARRAY_SIZE(rt1015p_codec_confs);
0249 }
0250 EXPORT_SYMBOL_NS(sof_rt1015p_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
0251
0252
0253
0254
0255
0256 static int rt1015_hw_params(struct snd_pcm_substream *substream,
0257 struct snd_pcm_hw_params *params)
0258 {
0259 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0260 struct snd_soc_dai *codec_dai;
0261 int i, fs = 64, ret;
0262
0263 for_each_rtd_codec_dais(rtd, i, codec_dai) {
0264 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
0265 params_rate(params) * fs,
0266 params_rate(params) * 256);
0267 if (ret)
0268 return ret;
0269
0270 ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
0271 params_rate(params) * 256,
0272 SND_SOC_CLOCK_IN);
0273 if (ret)
0274 return ret;
0275 }
0276
0277 return 0;
0278 }
0279
0280 static int rt1015_hw_params_pll_and_tdm(struct snd_pcm_substream *substream,
0281 struct snd_pcm_hw_params *params)
0282 {
0283 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0284 struct snd_soc_dai *codec_dai;
0285 int i, fs = 100, ret;
0286
0287 for_each_rtd_codec_dais(rtd, i, codec_dai) {
0288 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
0289 params_rate(params) * fs,
0290 params_rate(params) * 256);
0291 if (ret)
0292 return ret;
0293
0294 ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
0295 params_rate(params) * 256,
0296 SND_SOC_CLOCK_IN);
0297 if (ret)
0298 return ret;
0299 }
0300
0301 ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0),
0302 0x0, 0x1, 4, 24);
0303 if (ret)
0304 return ret;
0305
0306
0307 ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 1),
0308 0x0, 0x2, 4, 24);
0309 if (ret)
0310 return ret;
0311
0312 return 0;
0313 }
0314
0315 static struct snd_soc_ops rt1015_ops = {
0316 .hw_params = rt1015_hw_params,
0317 };
0318
0319 static struct snd_soc_codec_conf rt1015_amp_conf[] = {
0320 {
0321 .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME),
0322 .name_prefix = "Left",
0323 },
0324 {
0325 .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME),
0326 .name_prefix = "Right",
0327 },
0328 };
0329
0330 static struct snd_soc_dai_link_component rt1015_components[] = {
0331 {
0332 .name = RT1015_DEV0_NAME,
0333 .dai_name = RT1015_CODEC_DAI,
0334 },
0335 {
0336 .name = RT1015_DEV1_NAME,
0337 .dai_name = RT1015_CODEC_DAI,
0338 },
0339 };
0340
0341 static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
0342 {
0343 return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr,
0344 ARRAY_SIZE(speaker_map_lr));
0345 }
0346
0347 void sof_rt1015_codec_conf(struct snd_soc_card *card)
0348 {
0349 card->codec_conf = rt1015_amp_conf;
0350 card->num_configs = ARRAY_SIZE(rt1015_amp_conf);
0351 }
0352 EXPORT_SYMBOL_NS(sof_rt1015_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
0353
0354 void sof_rt1015_dai_link(struct snd_soc_dai_link *link, unsigned int fs)
0355 {
0356 link->codecs = rt1015_components;
0357 link->num_codecs = ARRAY_SIZE(rt1015_components);
0358 link->init = speaker_codec_init_lr;
0359 link->ops = &rt1015_ops;
0360
0361 if (fs == 100)
0362 rt1015_ops.hw_params = rt1015_hw_params_pll_and_tdm;
0363 }
0364 EXPORT_SYMBOL_NS(sof_rt1015_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
0365
0366
0367
0368
0369 static const struct snd_kcontrol_new rt1308_kcontrols[] = {
0370 SOC_DAPM_PIN_SWITCH("Speakers"),
0371 };
0372
0373 static const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = {
0374 SND_SOC_DAPM_SPK("Speakers", NULL),
0375 };
0376
0377 static const struct snd_soc_dapm_route rt1308_dapm_routes[] = {
0378
0379 {"Speakers", NULL, "SPOL"},
0380 {"Speakers", NULL, "SPOR"},
0381 };
0382
0383 static struct snd_soc_dai_link_component rt1308_components[] = {
0384 {
0385 .name = RT1308_DEV0_NAME,
0386 .dai_name = RT1308_CODEC_DAI,
0387 }
0388 };
0389
0390 static int rt1308_init(struct snd_soc_pcm_runtime *rtd)
0391 {
0392 struct snd_soc_card *card = rtd->card;
0393 int ret;
0394
0395 ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_dapm_widgets,
0396 ARRAY_SIZE(rt1308_dapm_widgets));
0397 if (ret) {
0398 dev_err(rtd->dev, "fail to add dapm controls, ret %d\n", ret);
0399 return ret;
0400 }
0401
0402 ret = snd_soc_add_card_controls(card, rt1308_kcontrols,
0403 ARRAY_SIZE(rt1308_kcontrols));
0404 if (ret) {
0405 dev_err(rtd->dev, "fail to add card controls, ret %d\n", ret);
0406 return ret;
0407 }
0408
0409 ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_dapm_routes,
0410 ARRAY_SIZE(rt1308_dapm_routes));
0411
0412 if (ret)
0413 dev_err(rtd->dev, "fail to add dapm routes, ret %d\n", ret);
0414
0415 return ret;
0416 }
0417
0418 static int rt1308_hw_params(struct snd_pcm_substream *substream,
0419 struct snd_pcm_hw_params *params)
0420 {
0421 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0422 struct snd_soc_card *card = rtd->card;
0423 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0424 int clk_id, clk_freq, pll_out;
0425 int ret;
0426
0427 clk_id = RT1308_PLL_S_MCLK;
0428
0429 clk_freq = sof_dai_get_mclk(rtd);
0430
0431 pll_out = params_rate(params) * 512;
0432
0433
0434 ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out);
0435 if (ret < 0) {
0436 dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", ret);
0437 return ret;
0438 }
0439
0440
0441 ret = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out,
0442 SND_SOC_CLOCK_IN);
0443 if (ret < 0)
0444 dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", ret);
0445
0446 return ret;
0447 }
0448
0449 static const struct snd_soc_ops rt1308_ops = {
0450 .hw_params = rt1308_hw_params,
0451 };
0452
0453 void sof_rt1308_dai_link(struct snd_soc_dai_link *link)
0454 {
0455 link->codecs = rt1308_components;
0456 link->num_codecs = ARRAY_SIZE(rt1308_components);
0457 link->init = rt1308_init;
0458 link->ops = &rt1308_ops;
0459 }
0460 EXPORT_SYMBOL_NS(sof_rt1308_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
0461
0462
0463
0464
0465
0466 static const struct snd_soc_dapm_route rt1019p_dapm_routes[] = {
0467
0468 { "Left Spk", NULL, "Speaker" },
0469 { "Right Spk", NULL, "Speaker" },
0470 };
0471
0472 static struct snd_soc_dai_link_component rt1019p_components[] = {
0473 {
0474 .name = RT1019P_DEV0_NAME,
0475 .dai_name = RT1019P_CODEC_DAI,
0476 },
0477 };
0478
0479 static int rt1019p_init(struct snd_soc_pcm_runtime *rtd)
0480 {
0481 struct snd_soc_card *card = rtd->card;
0482 int ret;
0483
0484 ret = snd_soc_dapm_add_routes(&card->dapm, rt1019p_dapm_routes,
0485 ARRAY_SIZE(rt1019p_dapm_routes));
0486 if (ret) {
0487 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
0488 return ret;
0489 }
0490 return ret;
0491 }
0492
0493 void sof_rt1019p_dai_link(struct snd_soc_dai_link *link)
0494 {
0495 link->codecs = rt1019p_components;
0496 link->num_codecs = ARRAY_SIZE(rt1019p_components);
0497 link->init = rt1019p_init;
0498 }
0499 EXPORT_SYMBOL_NS(sof_rt1019p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
0500
0501 MODULE_DESCRIPTION("ASoC Intel SOF Realtek helpers");
0502 MODULE_LICENSE("GPL");