1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2018 Rockchip Electronics Co., Ltd
4 */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <power/pmic.h>
9 #include <power/rk8xx_pmic.h>
10 #include <sound.h>
11 #include "rk817_codec.h"
12
13 #define DBG(format, ...) \
14 printf("RK817: " format, ## __VA_ARGS__)
15
16 /* For route */
17 #define RK817_CODEC_PLAYBACK 1
18 #define RK817_CODEC_CAPTURE 2
19 #define RK817_CODEC_INCALL 4
20 #define RK817_CODEC_ALL (RK817_CODEC_PLAYBACK |\
21 RK817_CODEC_CAPTURE | RK817_CODEC_INCALL)
22
23 /*
24 * DDAC L/R volume setting
25 * 0db~-95db,0.375db/step,for example:
26 * 0: 0dB
27 * 0x0a: -3.75dB
28 * 0x7d: -46dB
29 * 0xff: -95dB
30 */
31 #define OUT_VOLUME (0x03)
32
33 #define CODEC_SET_SPK 1
34 #define CODEC_SET_HP 2
35 #define INITIAL_VOLUME 3
36
37 struct rk817_codec_priv {
38 struct udevice *dev;
39 struct rk8xx_priv *rk817;
40 unsigned int stereo_sysclk;
41 unsigned int rate;
42 unsigned int spk_volume;
43 unsigned int hp_volume;
44 bool use_ext_amplifier;
45 long int playback_path;
46 int spk_mute_delay;
47 int hp_mute_delay;
48 };
49
snd_soc_write(struct udevice * dev,unsigned int reg,unsigned int val)50 static int snd_soc_write(struct udevice *dev, unsigned int reg,
51 unsigned int val)
52 {
53 return pmic_reg_write(dev, reg, val);
54 }
55
snd_soc_update_bits(struct udevice * dev,unsigned int reg,unsigned int mask,unsigned int value)56 static int snd_soc_update_bits(struct udevice *dev, unsigned int reg,
57 unsigned int mask, unsigned int value)
58 {
59 return pmic_clrsetbits(dev, reg, mask, value);
60 }
61
rk817_reset(struct rk817_codec_priv * priv)62 static int rk817_reset(struct rk817_codec_priv *priv)
63 {
64 struct udevice *codec = priv->dev->parent;
65
66 snd_soc_write(codec, RK817_CODEC_DTOP_LPT_SRST, 0x40);
67 snd_soc_write(codec, RK817_CODEC_DDAC_POPD_DACST, 0x02);
68
69 return 0;
70 }
71
72 static struct rk817_reg_val_typ playback_power_up_list[] = {
73 {RK817_CODEC_AREF_RTCFG1, 0x40},
74 {RK817_CODEC_DDAC_POPD_DACST, 0x02},
75 {RK817_CODEC_DDAC_SR_LMT0, 0x02},
76 /* {RK817_CODEC_DTOP_DIGEN_CLKE, 0x0f}, */
77 /* APLL */
78 {RK817_CODEC_APLL_CFG0, 0x04},
79 {RK817_CODEC_APLL_CFG1, 0x58},
80 {RK817_CODEC_APLL_CFG2, 0x2d},
81 {RK817_CODEC_APLL_CFG3, 0x0c},
82 {RK817_CODEC_APLL_CFG4, 0xa5},
83 {RK817_CODEC_APLL_CFG5, 0x00},
84
85 {RK817_CODEC_DI2S_RXCMD_TSD, 0x00},
86 {RK817_CODEC_DI2S_RSD, 0x00},
87 /* {RK817_CODEC_DI2S_CKM, 0x00}, */
88 {RK817_CODEC_DI2S_RXCR1, 0x00},
89 {RK817_CODEC_DI2S_RXCMD_TSD, 0x20},
90 {RK817_CODEC_DTOP_VUCTIME, 0xf4},
91 {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x00},
92
93 {RK817_CODEC_DDAC_VOLL, 0x0a},
94 {RK817_CODEC_DDAC_VOLR, 0x0a},
95 };
96
97 #define RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN \
98 ARRAY_SIZE(playback_power_up_list)
99
100 static struct rk817_reg_val_typ playback_power_down_list[] = {
101 {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x01},
102 {RK817_CODEC_ADAC_CFG1, 0x0f},
103 /* HP */
104 {RK817_CODEC_AHP_CFG0, 0xe0},
105 {RK817_CODEC_AHP_CP, 0x09},
106 /* SPK */
107 {RK817_CODEC_ACLASSD_CFG1, 0x69},
108 };
109
110 #define RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN \
111 ARRAY_SIZE(playback_power_down_list)
112
rk817_codec_power_up(struct rk817_codec_priv * rk817,int type)113 static int rk817_codec_power_up(struct rk817_codec_priv *rk817, int type)
114 {
115 struct udevice *codec = rk817->dev->parent;
116 int i;
117
118 DBG("%s : power up %s %s %s\n", __func__,
119 type & RK817_CODEC_PLAYBACK ? "playback" : "",
120 type & RK817_CODEC_CAPTURE ? "capture" : "",
121 type & RK817_CODEC_INCALL ? "incall" : "");
122
123 if (type & RK817_CODEC_PLAYBACK) {
124 snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE,
125 DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN);
126 for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN; i++) {
127 snd_soc_write(codec, playback_power_up_list[i].reg,
128 playback_power_up_list[i].value);
129 }
130 }
131
132 return 0;
133 }
134
rk817_codec_power_down(struct rk817_codec_priv * rk817,int type)135 static int rk817_codec_power_down(struct rk817_codec_priv *rk817, int type)
136 {
137 struct udevice *codec = rk817->dev->parent;
138 int i;
139
140 DBG("%s : power down %s %s %s\n", __func__,
141 type & RK817_CODEC_PLAYBACK ? "playback" : "",
142 type & RK817_CODEC_CAPTURE ? "capture" : "",
143 type & RK817_CODEC_INCALL ? "incall" : "");
144
145 /* mute output for pop noise */
146 if ((type & RK817_CODEC_PLAYBACK) ||
147 (type & RK817_CODEC_INCALL)) {
148 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL,
149 DACMT_ENABLE, DACMT_ENABLE);
150 }
151
152 if (type & RK817_CODEC_PLAYBACK) {
153 for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) {
154 snd_soc_write(codec, playback_power_down_list[i].reg,
155 playback_power_down_list[i].value);
156 }
157 snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE,
158 DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS);
159 }
160
161 if (type == RK817_CODEC_ALL) {
162 for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) {
163 snd_soc_write(codec, playback_power_down_list[i].reg,
164 playback_power_down_list[i].value);
165 }
166 snd_soc_write(codec, RK817_CODEC_DTOP_DIGEN_CLKE, 0x00);
167 snd_soc_write(codec, RK817_CODEC_APLL_CFG5, 0x01);
168 snd_soc_write(codec, RK817_CODEC_AREF_RTCFG1, 0x06);
169 }
170
171 return 0;
172 }
173
rk817_playback_path_put(struct rk817_codec_priv * rk817,int path)174 static int rk817_playback_path_put(struct rk817_codec_priv *rk817, int path)
175 {
176 struct udevice *codec = rk817->dev->parent;
177 long int pre_path;
178
179 if (rk817->playback_path == path) {
180 DBG("%s : playback_path is not changed!\n", __func__);
181 return 0;
182 }
183
184 pre_path = rk817->playback_path;
185 rk817->playback_path = path;
186
187 DBG("%s : set playback_path %ld, pre_path %ld\n",
188 __func__, rk817->playback_path, pre_path);
189
190 switch (rk817->playback_path) {
191 case OFF:
192 rk817_codec_power_down(rk817, RK817_CODEC_PLAYBACK);
193 break;
194 case RCV:
195 case SPK_PATH:
196 case RING_SPK:
197 if (pre_path == OFF)
198 rk817_codec_power_up(rk817, RK817_CODEC_PLAYBACK);
199 if (!rk817->use_ext_amplifier) {
200 /* power on dac ibias/l/r */
201 snd_soc_write(codec, RK817_CODEC_ADAC_CFG1,
202 PWD_DACBIAS_ON | PWD_DACD_ON |
203 PWD_DACL_ON | PWD_DACR_ON);
204 /* CLASS D mode */
205 snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10);
206 /* CLASS D enable */
207 snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5);
208 /* restart CLASS D, OCPP/N */
209 snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4);
210 } else {
211 /* HP_CP_EN , CP 2.3V */
212 snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11);
213 /* power on HP two stage opamp ,HP amplitude 0db */
214 snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80);
215 /* power on dac ibias/l/r */
216 snd_soc_write(codec, RK817_CODEC_ADAC_CFG1,
217 PWD_DACBIAS_ON | PWD_DACD_DOWN |
218 PWD_DACL_ON | PWD_DACR_ON);
219 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL,
220 DACMT_ENABLE, DACMT_DISABLE);
221 }
222 snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->spk_volume);
223 snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->spk_volume);
224 break;
225 case HP_PATH:
226 case HP_NO_MIC:
227 case RING_HP:
228 case RING_HP_NO_MIC:
229 if (pre_path == OFF)
230 rk817_codec_power_up(rk817, RK817_CODEC_PLAYBACK);
231 /* HP_CP_EN , CP 2.3V */
232 snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11);
233 /* power on HP two stage opamp ,HP amplitude 0db */
234 snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80);
235 /* power on dac ibias/l/r */
236 snd_soc_write(codec, RK817_CODEC_ADAC_CFG1,
237 PWD_DACBIAS_ON | PWD_DACD_DOWN |
238 PWD_DACL_ON | PWD_DACR_ON);
239 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL,
240 DACMT_ENABLE, DACMT_DISABLE);
241
242 snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume);
243 snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume);
244 break;
245 case BT:
246 break;
247 case SPK_HP:
248 case RING_SPK_HP:
249 if (pre_path == OFF)
250 rk817_codec_power_up(rk817, RK817_CODEC_PLAYBACK);
251
252 /* HP_CP_EN , CP 2.3V */
253 snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11);
254 /* power on HP two stage opamp ,HP amplitude 0db */
255 snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80);
256
257 /* power on dac ibias/l/r */
258 snd_soc_write(codec, RK817_CODEC_ADAC_CFG1,
259 PWD_DACBIAS_ON | PWD_DACD_ON |
260 PWD_DACL_ON | PWD_DACR_ON);
261
262 if (!rk817->use_ext_amplifier) {
263 /* CLASS D mode */
264 snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10);
265 /* CLASS D enable */
266 snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5);
267 /* restart CLASS D, OCPP/N */
268 snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4);
269 }
270
271 snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume);
272 snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume);
273 break;
274 default:
275 return -EINVAL;
276 }
277
278 return 0;
279 }
280
rk817_hw_params(struct udevice * dev,unsigned int samplerate,unsigned int fmt,unsigned int channels)281 static int rk817_hw_params(struct udevice *dev, unsigned int samplerate,
282 unsigned int fmt, unsigned int channels)
283 {
284 struct rk817_codec_priv *rk817 = dev_get_priv(dev);
285 struct udevice *codec = rk817->dev->parent;
286
287 snd_soc_update_bits(codec, RK817_CODEC_DI2S_CKM,
288 RK817_I2S_MODE_MASK, RK817_I2S_MODE_SLV);
289 snd_soc_write(codec, RK817_CODEC_DI2S_RXCR2, VDW_RX_16BITS);
290 snd_soc_write(codec, RK817_CODEC_DI2S_TXCR2, VDW_TX_16BITS);
291
292 return 0;
293 }
294
rk817_digital_mute(struct rk817_codec_priv * rk817,int mute)295 static int rk817_digital_mute(struct rk817_codec_priv *rk817, int mute)
296 {
297 struct udevice *codec = rk817->dev->parent;
298
299 if (mute)
300 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL,
301 DACMT_ENABLE, DACMT_ENABLE);
302 else
303 snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL,
304 DACMT_ENABLE, DACMT_DISABLE);
305
306 return 0;
307 }
308
rk817_startup(struct udevice * dev)309 static int rk817_startup(struct udevice *dev)
310 {
311 struct rk817_codec_priv *rk817 = dev_get_priv(dev);
312
313 rk817_playback_path_put(rk817, SPK_HP);
314 rk817_digital_mute(rk817, 0);
315
316 return 0;
317 }
318
319 static const struct snd_soc_dai_ops rk817_codec_ops = {
320 .hw_params = rk817_hw_params,
321 .startup = rk817_startup,
322 };
323
rk817_codec_probe(struct udevice * dev)324 static int rk817_codec_probe(struct udevice *dev)
325 {
326 struct rk8xx_priv *rk817 = dev_get_priv(dev->parent);
327 struct rk817_codec_priv *rk817_codec = dev_get_priv(dev);
328
329 if (!rk817) {
330 printf("%s : rk817 is null\n", __func__);
331 return -EINVAL;
332 }
333
334 switch (rk817->variant) {
335 case RK809_ID:
336 case RK817_ID:
337 break;
338 default:
339 return -EINVAL;
340 }
341
342 rk817_codec->dev = dev;
343 rk817_codec->hp_volume = INITIAL_VOLUME;
344 rk817_codec->spk_volume = INITIAL_VOLUME;
345 rk817_codec->playback_path = OFF;
346 rk817_reset(rk817_codec);
347
348 return 0;
349 }
350
351 static const struct udevice_id rk817_codec_ids[] = {
352 { .compatible = "rockchip,rk817-codec" },
353 { }
354 };
355
356 U_BOOT_DRIVER(rk817) = {
357 .name = "rk817_codec",
358 .id = UCLASS_CODEC,
359 .of_match = rk817_codec_ids,
360 .probe = rk817_codec_probe,
361 .priv_auto_alloc_size = sizeof(struct rk817_codec_priv),
362 .ops = &rk817_codec_ops,
363 };
364
365 UCLASS_DRIVER(codec) = {
366 .id = UCLASS_CODEC,
367 .name = "codec",
368 };
369