WIP FPC-III support
[linux/fpc-iii.git] / sound / soc / intel / boards / sof_realtek_common.c
blobf3cf73c620ba5ea439e90a76203b3003b97eed13
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2020 Intel Corporation. All rights reserved.
5 #include <linux/device.h>
6 #include <linux/kernel.h>
7 #include <sound/pcm.h>
8 #include <sound/pcm_params.h>
9 #include <sound/soc.h>
10 #include <sound/soc-dai.h>
11 #include <sound/soc-dapm.h>
12 #include <uapi/sound/asound.h>
13 #include "../../codecs/rt1011.h"
14 #include "sof_realtek_common.h"
17 * Current only 2-amp configuration is supported for rt1011
19 static const struct snd_soc_dapm_route rt1011_dapm_routes[] = {
20 /* speaker */
21 { "Left Spk", NULL, "Left SPO" },
22 { "Right Spk", NULL, "Right SPO" },
26 * Make sure device's Unique ID follows this configuration:
28 * Two speakers:
29 * 0: left, 1: right
30 * Four speakers:
31 * 0: Woofer left, 1: Woofer right
32 * 2: Tweeter left, 3: Tweeter right
34 static struct snd_soc_codec_conf rt1011_codec_confs[] = {
36 .dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME),
37 .name_prefix = "Left",
40 .dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME),
41 .name_prefix = "Right",
45 static struct snd_soc_dai_link_component rt1011_dai_link_components[] = {
47 .name = RT1011_DEV0_NAME,
48 .dai_name = RT1011_CODEC_DAI,
51 .name = RT1011_DEV1_NAME,
52 .dai_name = RT1011_CODEC_DAI,
56 static const struct {
57 unsigned int tx;
58 unsigned int rx;
59 } rt1011_tdm_mask[] = {
60 {.tx = 0x4, .rx = 0x1},
61 {.tx = 0x8, .rx = 0x2},
64 static int rt1011_hw_params(struct snd_pcm_substream *substream,
65 struct snd_pcm_hw_params *params)
67 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
68 struct snd_soc_dai *codec_dai;
69 int srate, i, ret = 0;
71 srate = params_rate(params);
73 for_each_rtd_codec_dais(rtd, i, codec_dai) {
74 /* 100 Fs to drive 24 bit data */
75 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK,
76 100 * srate, 256 * srate);
77 if (ret < 0) {
78 dev_err(codec_dai->dev, "fail to set pll, ret %d\n",
79 ret);
80 return ret;
83 ret = snd_soc_dai_set_sysclk(codec_dai, RT1011_FS_SYS_PRE_S_PLL1,
84 256 * srate, SND_SOC_CLOCK_IN);
85 if (ret < 0) {
86 dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n",
87 ret);
88 return ret;
91 if (i >= ARRAY_SIZE(rt1011_tdm_mask)) {
92 dev_err(codec_dai->dev, "invalid codec index %d\n",
93 i);
94 return -ENODEV;
97 ret = snd_soc_dai_set_tdm_slot(codec_dai, rt1011_tdm_mask[i].tx,
98 rt1011_tdm_mask[i].rx, 4,
99 params_width(params));
100 if (ret < 0) {
101 dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n",
102 ret);
103 return ret;
107 return 0;
110 static const struct snd_soc_ops rt1011_ops = {
111 .hw_params = rt1011_hw_params,
114 static int rt1011_init(struct snd_soc_pcm_runtime *rtd)
116 struct snd_soc_card *card = rtd->card;
117 int ret;
119 ret = snd_soc_dapm_add_routes(&card->dapm, rt1011_dapm_routes,
120 ARRAY_SIZE(rt1011_dapm_routes));
121 if (ret)
122 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
123 return ret;
126 void sof_rt1011_dai_link(struct snd_soc_dai_link *link)
128 link->codecs = rt1011_dai_link_components;
129 link->num_codecs = ARRAY_SIZE(rt1011_dai_link_components);
130 link->init = rt1011_init;
131 link->ops = &rt1011_ops;
134 void sof_rt1011_codec_conf(struct snd_soc_card *card)
136 card->codec_conf = rt1011_codec_confs;
137 card->num_configs = ARRAY_SIZE(rt1011_codec_confs);