1
2
3
4
5
6
7
8#include <linux/device.h>
9#include <linux/errno.h>
10#include <sound/soc.h>
11#include <sound/soc-acpi.h>
12#include "sof_sdw_common.h"
13#include "../../codecs/rt1308.h"
14
15static const struct snd_soc_dapm_widget rt1308_widgets[] = {
16 SND_SOC_DAPM_SPK("Speaker", NULL),
17};
18
19
20
21
22
23
24
25static const struct snd_soc_dapm_route rt1308_map[] = {
26 { "Speaker", NULL, "rt1308-1 SPOL" },
27 { "Speaker", NULL, "rt1308-1 SPOR" },
28 { "Speaker", NULL, "rt1308-2 SPOL" },
29 { "Speaker", NULL, "rt1308-2 SPOR" },
30};
31
32static const struct snd_kcontrol_new rt1308_controls[] = {
33 SOC_DAPM_PIN_SWITCH("Speaker"),
34};
35
36static int first_spk_init(struct snd_soc_pcm_runtime *rtd)
37{
38 struct snd_soc_card *card = rtd->card;
39 int ret;
40
41 card->components = devm_kasprintf(card->dev, GFP_KERNEL,
42 "%s spk:rt1308",
43 card->components);
44 if (!card->components)
45 return -ENOMEM;
46
47 ret = snd_soc_add_card_controls(card, rt1308_controls,
48 ARRAY_SIZE(rt1308_controls));
49 if (ret) {
50 dev_err(card->dev, "rt1308 controls addition failed: %d\n", ret);
51 return ret;
52 }
53
54 ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_widgets,
55 ARRAY_SIZE(rt1308_widgets));
56 if (ret) {
57 dev_err(card->dev, "rt1308 widgets addition failed: %d\n", ret);
58 return ret;
59 }
60
61 ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map, 2);
62 if (ret)
63 dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret);
64
65 return ret;
66}
67
68static int second_spk_init(struct snd_soc_pcm_runtime *rtd)
69{
70 struct snd_soc_card *card = rtd->card;
71 int ret;
72
73 ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map + 2, 2);
74 if (ret)
75 dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret);
76
77 return ret;
78}
79
80static int all_spk_init(struct snd_soc_pcm_runtime *rtd)
81{
82 int ret;
83
84 ret = first_spk_init(rtd);
85 if (ret)
86 return ret;
87
88 return second_spk_init(rtd);
89}
90
91static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream,
92 struct snd_pcm_hw_params *params)
93{
94 struct snd_soc_pcm_runtime *rtd = substream->private_data;
95 struct snd_soc_card *card = rtd->card;
96 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
97 int clk_id, clk_freq, pll_out;
98 int err;
99
100 clk_id = RT1308_PLL_S_MCLK;
101 clk_freq = 38400000;
102
103 pll_out = params_rate(params) * 512;
104
105
106 err = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out);
107 if (err < 0) {
108 dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", err);
109 return err;
110 }
111
112
113 err = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out,
114 SND_SOC_CLOCK_IN);
115 if (err < 0) {
116 dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", err);
117 return err;
118 }
119
120 return 0;
121}
122
123
124struct snd_soc_ops sof_sdw_rt1308_i2s_ops = {
125 .hw_params = rt1308_i2s_hw_params,
126};
127
128int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link,
129 struct snd_soc_dai_link *dai_links,
130 struct sof_sdw_codec_info *info,
131 bool playback)
132{
133 info->amp_num++;
134 if (info->amp_num == 1)
135 dai_links->init = first_spk_init;
136
137 if (info->amp_num == 2) {
138
139
140
141
142
143
144 if (dai_links->init)
145 dai_links->init = all_spk_init;
146 else
147 dai_links->init = second_spk_init;
148 }
149
150 return 0;
151}
152