xref: /openbmc/linux/sound/soc/codecs/rt9120.c (revision fe38b4d6)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/bits.h>
4 #include <linux/delay.h>
5 #include <linux/gpio/consumer.h>
6 #include <linux/i2c.h>
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/regmap.h>
10 #include <linux/regulator/consumer.h>
11 #include <sound/pcm.h>
12 #include <sound/pcm_params.h>
13 #include <sound/soc.h>
14 #include <sound/tlv.h>
15 
16 #define RT9120_REG_DEVID	0x00
17 #define RT9120_REG_I2SFMT	0x02
18 #define RT9120_REG_I2SWL	0x03
19 #define RT9120_REG_SDIOSEL	0x04
20 #define RT9120_REG_SYSCTL	0x05
21 #define RT9120_REG_SPKGAIN	0x07
22 #define RT9120_REG_VOLRAMP	0x0A
23 #define RT9120_REG_ERRRPT	0x10
24 #define RT9120_REG_MSVOL	0x20
25 #define RT9120_REG_SWRESET	0x40
26 #define RT9120_REG_INTERNAL0	0x65
27 #define RT9120_REG_INTERNAL1	0x69
28 #define RT9120_REG_UVPOPT	0x6C
29 
30 #define RT9120_VID_MASK		GENMASK(15, 8)
31 #define RT9120_SWRST_MASK	BIT(7)
32 #define RT9120_MUTE_MASK	GENMASK(5, 4)
33 #define RT9120_I2SFMT_MASK	GENMASK(4, 2)
34 #define RT9120_I2SFMT_SHIFT	2
35 #define RT9120_CFG_FMT_I2S	0
36 #define RT9120_CFG_FMT_LEFTJ	1
37 #define RT9120_CFG_FMT_RIGHTJ	2
38 #define RT9120_CFG_FMT_DSPA	3
39 #define RT9120_CFG_FMT_DSPB	7
40 #define RT9120_AUDBIT_MASK	GENMASK(1, 0)
41 #define RT9120_CFG_AUDBIT_16	0
42 #define RT9120_CFG_AUDBIT_20	1
43 #define RT9120_CFG_AUDBIT_24	2
44 #define RT9120_AUDWL_MASK	GENMASK(5, 0)
45 #define RT9120_CFG_WORDLEN_16	16
46 #define RT9120_CFG_WORDLEN_24	24
47 #define RT9120_CFG_WORDLEN_32	32
48 #define RT9120_DVDD_UVSEL_MASK	GENMASK(5, 4)
49 
50 #define RT9120_VENDOR_ID	0x4200
51 #define RT9120_RESET_WAITMS	20
52 #define RT9120_CHIPON_WAITMS	20
53 #define RT9120_AMPON_WAITMS	50
54 #define RT9120_AMPOFF_WAITMS	100
55 #define RT9120_LVAPP_THRESUV	2000000
56 
57 /* 8000 to 192000 supported , only 176400 not support */
58 #define RT9120_RATES_MASK	(SNDRV_PCM_RATE_8000_192000 &\
59 				 ~SNDRV_PCM_RATE_176400)
60 #define RT9120_FMTS_MASK	(SNDRV_PCM_FMTBIT_S16_LE |\
61 				 SNDRV_PCM_FMTBIT_S24_LE |\
62 				 SNDRV_PCM_FMTBIT_S32_LE)
63 
64 struct rt9120_data {
65 	struct device *dev;
66 	struct regmap *regmap;
67 };
68 
69 /* 11bit [min,max,step] = [-103.9375dB, 24dB, 0.0625dB] */
70 static const DECLARE_TLV_DB_SCALE(digital_tlv, -1039375, 625, 1);
71 
72 /* {6, 8, 10, 12, 13, 14, 15, 16}dB */
73 static const DECLARE_TLV_DB_RANGE(classd_tlv,
74 	0, 3, TLV_DB_SCALE_ITEM(600, 200, 0),
75 	4, 7, TLV_DB_SCALE_ITEM(1300, 100, 0)
76 );
77 
78 static const char * const sdo_select_text[] = {
79 	"None", "INTF", "Final", "RMS Detect"
80 };
81 
82 static const struct soc_enum sdo_select_enum =
83 	SOC_ENUM_SINGLE(RT9120_REG_SDIOSEL, 4, ARRAY_SIZE(sdo_select_text),
84 			sdo_select_text);
85 
86 static const struct snd_kcontrol_new rt9120_snd_controls[] = {
87 	SOC_SINGLE_TLV("MS Volume", RT9120_REG_MSVOL, 0, 2047, 1, digital_tlv),
88 	SOC_SINGLE_TLV("SPK Gain Volume", RT9120_REG_SPKGAIN, 0, 7, 0, classd_tlv),
89 	SOC_SINGLE("PBTL Switch", RT9120_REG_SYSCTL, 3, 1, 0),
90 	SOC_ENUM("SDO Select", sdo_select_enum),
91 };
92 
93 static int internal_power_event(struct snd_soc_dapm_widget *w,
94 				struct snd_kcontrol *kcontrol, int event)
95 {
96 	struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
97 
98 	switch (event) {
99 	case SND_SOC_DAPM_PRE_PMU:
100 		snd_soc_component_write(comp, RT9120_REG_ERRRPT, 0);
101 		break;
102 	case SND_SOC_DAPM_POST_PMU:
103 		msleep(RT9120_AMPON_WAITMS);
104 		break;
105 	case SND_SOC_DAPM_POST_PMD:
106 		msleep(RT9120_AMPOFF_WAITMS);
107 		break;
108 	default:
109 		break;
110 	}
111 
112 	return 0;
113 }
114 
115 static const struct snd_soc_dapm_widget rt9120_dapm_widgets[] = {
116 	SND_SOC_DAPM_MIXER("DMIX", SND_SOC_NOPM, 0, 0, NULL, 0),
117 	SND_SOC_DAPM_DAC("LDAC", NULL, SND_SOC_NOPM, 0, 0),
118 	SND_SOC_DAPM_DAC("RDAC", NULL, SND_SOC_NOPM, 0, 0),
119 	SND_SOC_DAPM_SUPPLY("PWND", RT9120_REG_SYSCTL, 6, 1,
120 			    internal_power_event, SND_SOC_DAPM_PRE_PMU |
121 			    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
122 	SND_SOC_DAPM_PGA("SPKL PA", SND_SOC_NOPM, 0, 0, NULL, 0),
123 	SND_SOC_DAPM_PGA("SPKR PA", SND_SOC_NOPM, 0, 0, NULL, 0),
124 	SND_SOC_DAPM_OUTPUT("SPKL"),
125 	SND_SOC_DAPM_OUTPUT("SPKR"),
126 };
127 
128 static const struct snd_soc_dapm_route rt9120_dapm_routes[] = {
129 	{ "DMIX", NULL, "AIF Playback" },
130 	/* SPKL */
131 	{ "LDAC", NULL, "PWND" },
132 	{ "LDAC", NULL, "DMIX" },
133 	{ "SPKL PA", NULL, "LDAC" },
134 	{ "SPKL", NULL, "SPKL PA" },
135 	/* SPKR */
136 	{ "RDAC", NULL, "PWND" },
137 	{ "RDAC", NULL, "DMIX" },
138 	{ "SPKR PA", NULL, "RDAC" },
139 	{ "SPKR", NULL, "SPKR PA" },
140 	/* Cap */
141 	{ "AIF Capture", NULL, "LDAC" },
142 	{ "AIF Capture", NULL, "RDAC" },
143 };
144 
145 static int rt9120_codec_probe(struct snd_soc_component *comp)
146 {
147 	struct rt9120_data *data = snd_soc_component_get_drvdata(comp);
148 
149 	snd_soc_component_init_regmap(comp, data->regmap);
150 
151 	/* Internal setting */
152 	snd_soc_component_write(comp, RT9120_REG_INTERNAL1, 0x03);
153 	snd_soc_component_write(comp, RT9120_REG_INTERNAL0, 0x69);
154 	return 0;
155 }
156 
157 static const struct snd_soc_component_driver rt9120_component_driver = {
158 	.probe = rt9120_codec_probe,
159 	.controls = rt9120_snd_controls,
160 	.num_controls = ARRAY_SIZE(rt9120_snd_controls),
161 	.dapm_widgets = rt9120_dapm_widgets,
162 	.num_dapm_widgets = ARRAY_SIZE(rt9120_dapm_widgets),
163 	.dapm_routes = rt9120_dapm_routes,
164 	.num_dapm_routes = ARRAY_SIZE(rt9120_dapm_routes),
165 };
166 
167 static int rt9120_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
168 {
169 	struct snd_soc_component *comp = dai->component;
170 	unsigned int format;
171 
172 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
173 	case SND_SOC_DAIFMT_I2S:
174 		format = RT9120_CFG_FMT_I2S;
175 		break;
176 	case SND_SOC_DAIFMT_LEFT_J:
177 		format = RT9120_CFG_FMT_LEFTJ;
178 		break;
179 	case SND_SOC_DAIFMT_RIGHT_J:
180 		format = RT9120_CFG_FMT_RIGHTJ;
181 		break;
182 	case SND_SOC_DAIFMT_DSP_A:
183 		format = RT9120_CFG_FMT_DSPA;
184 		break;
185 	case SND_SOC_DAIFMT_DSP_B:
186 		format = RT9120_CFG_FMT_DSPB;
187 		break;
188 	default:
189 		dev_err(dai->dev, "Unknown dai format\n");
190 		return -EINVAL;
191 	}
192 
193 	snd_soc_component_update_bits(comp, RT9120_REG_I2SFMT,
194 				      RT9120_I2SFMT_MASK,
195 				      format << RT9120_I2SFMT_SHIFT);
196 	return 0;
197 }
198 
199 static int rt9120_hw_params(struct snd_pcm_substream *substream,
200 			    struct snd_pcm_hw_params *param,
201 			    struct snd_soc_dai *dai)
202 {
203 	struct snd_soc_component *comp = dai->component;
204 	unsigned int param_width, param_slot_width;
205 	int width;
206 
207 	switch (width = params_width(param)) {
208 	case 16:
209 		param_width = RT9120_CFG_AUDBIT_16;
210 		break;
211 	case 20:
212 		param_width = RT9120_CFG_AUDBIT_20;
213 		break;
214 	case 24:
215 	case 32:
216 		param_width = RT9120_CFG_AUDBIT_24;
217 		break;
218 	default:
219 		dev_err(dai->dev, "Unsupported data width [%d]\n", width);
220 		return -EINVAL;
221 	}
222 
223 	snd_soc_component_update_bits(comp, RT9120_REG_I2SFMT,
224 				      RT9120_AUDBIT_MASK, param_width);
225 
226 	switch (width = params_physical_width(param)) {
227 	case 16:
228 		param_slot_width = RT9120_CFG_WORDLEN_16;
229 		break;
230 	case 24:
231 		param_slot_width = RT9120_CFG_WORDLEN_24;
232 		break;
233 	case 32:
234 		param_slot_width = RT9120_CFG_WORDLEN_32;
235 		break;
236 	default:
237 		dev_err(dai->dev, "Unsupported slot width [%d]\n", width);
238 		return -EINVAL;
239 	}
240 
241 	snd_soc_component_update_bits(comp, RT9120_REG_I2SWL,
242 				      RT9120_AUDWL_MASK, param_slot_width);
243 	return 0;
244 }
245 
246 static const struct snd_soc_dai_ops rt9120_dai_ops = {
247 	.set_fmt = rt9120_set_fmt,
248 	.hw_params = rt9120_hw_params,
249 };
250 
251 static struct snd_soc_dai_driver rt9120_dai = {
252 	.name = "rt9120_aif",
253 	.playback = {
254 		.stream_name = "AIF Playback",
255 		.rates = RT9120_RATES_MASK,
256 		.formats = RT9120_FMTS_MASK,
257 		.rate_max = 192000,
258 		.rate_min = 8000,
259 		.channels_min = 1,
260 		.channels_max = 2,
261 	},
262 	.capture = {
263 		.stream_name = "AIF Capture",
264 		.rates = RT9120_RATES_MASK,
265 		.formats = RT9120_FMTS_MASK,
266 		.rate_max = 192000,
267 		.rate_min = 8000,
268 		.channels_min = 1,
269 		.channels_max = 2,
270 	},
271 	.ops = &rt9120_dai_ops,
272 	.symmetric_rate = 1,
273 	.symmetric_sample_bits = 1,
274 };
275 
276 static const struct regmap_range rt9120_rd_yes_ranges[] = {
277 	regmap_reg_range(0x00, 0x0C),
278 	regmap_reg_range(0x10, 0x15),
279 	regmap_reg_range(0x20, 0x27),
280 	regmap_reg_range(0x30, 0x38),
281 	regmap_reg_range(0x3A, 0x40),
282 	regmap_reg_range(0x65, 0x65),
283 	regmap_reg_range(0x69, 0x69),
284 	regmap_reg_range(0x6C, 0x6C)
285 };
286 
287 static const struct regmap_access_table rt9120_rd_table = {
288 	.yes_ranges = rt9120_rd_yes_ranges,
289 	.n_yes_ranges = ARRAY_SIZE(rt9120_rd_yes_ranges),
290 };
291 
292 static const struct regmap_range rt9120_wr_yes_ranges[] = {
293 	regmap_reg_range(0x00, 0x00),
294 	regmap_reg_range(0x02, 0x0A),
295 	regmap_reg_range(0x10, 0x15),
296 	regmap_reg_range(0x20, 0x27),
297 	regmap_reg_range(0x30, 0x38),
298 	regmap_reg_range(0x3A, 0x3D),
299 	regmap_reg_range(0x40, 0x40),
300 	regmap_reg_range(0x65, 0x65),
301 	regmap_reg_range(0x69, 0x69),
302 	regmap_reg_range(0x6C, 0x6C)
303 };
304 
305 static const struct regmap_access_table rt9120_wr_table = {
306 	.yes_ranges = rt9120_wr_yes_ranges,
307 	.n_yes_ranges = ARRAY_SIZE(rt9120_wr_yes_ranges),
308 };
309 
310 static int rt9120_get_reg_size(unsigned int reg)
311 {
312 	switch (reg) {
313 	case 0x00:
314 	case 0x09:
315 	case 0x20 ... 0x27:
316 		return 2;
317 	case 0x30 ... 0x3D:
318 		return 3;
319 	case 0x3E ... 0x3F:
320 		return 4;
321 	default:
322 		return 1;
323 	}
324 }
325 
326 static int rt9120_reg_read(void *context, unsigned int reg, unsigned int *val)
327 {
328 	struct rt9120_data *data = context;
329 	struct i2c_client *i2c = to_i2c_client(data->dev);
330 	int size = rt9120_get_reg_size(reg);
331 	u8 raw[4] = {0};
332 	int ret;
333 
334 	ret = i2c_smbus_read_i2c_block_data(i2c, reg, size, raw);
335 	if (ret < 0)
336 		return ret;
337 	else if (ret != size)
338 		return -EIO;
339 
340 	switch (size) {
341 	case 4:
342 		*val = be32_to_cpup((__be32 *)raw);
343 		break;
344 	case 3:
345 		*val = raw[0] << 16 | raw[1] << 8 | raw[0];
346 		break;
347 	case 2:
348 		*val = be16_to_cpup((__be16 *)raw);
349 		break;
350 	default:
351 		*val = raw[0];
352 	}
353 
354 	return 0;
355 }
356 
357 static int rt9120_reg_write(void *context, unsigned int reg, unsigned int val)
358 {
359 	struct rt9120_data *data = context;
360 	struct i2c_client *i2c = to_i2c_client(data->dev);
361 	int size = rt9120_get_reg_size(reg);
362 	__be32 be32_val;
363 	u8 *rawp = (u8 *)&be32_val;
364 	int offs = 4 - size;
365 
366 	be32_val = cpu_to_be32(val);
367 	return i2c_smbus_write_i2c_block_data(i2c, reg, size, rawp + offs);
368 }
369 
370 static const struct regmap_config rt9120_regmap_config = {
371 	.reg_bits = 8,
372 	.val_bits = 32,
373 	.max_register = RT9120_REG_UVPOPT,
374 
375 	.reg_read = rt9120_reg_read,
376 	.reg_write = rt9120_reg_write,
377 
378 	.wr_table = &rt9120_wr_table,
379 	.rd_table = &rt9120_rd_table,
380 };
381 
382 static int rt9120_check_vendor_info(struct rt9120_data *data)
383 {
384 	unsigned int devid;
385 	int ret;
386 
387 	ret = regmap_read(data->regmap, RT9120_REG_DEVID, &devid);
388 	if (ret)
389 		return ret;
390 
391 	if ((devid & RT9120_VID_MASK) != RT9120_VENDOR_ID) {
392 		dev_err(data->dev, "DEVID not correct [0x%04x]\n", devid);
393 		return -ENODEV;
394 	}
395 
396 	return 0;
397 }
398 
399 static int rt9120_do_register_reset(struct rt9120_data *data)
400 {
401 	int ret;
402 
403 	ret = regmap_write(data->regmap, RT9120_REG_SWRESET,
404 			   RT9120_SWRST_MASK);
405 	if (ret)
406 		return ret;
407 
408 	msleep(RT9120_RESET_WAITMS);
409 	return 0;
410 }
411 
412 static int rt9120_probe(struct i2c_client *i2c)
413 {
414 	struct rt9120_data *data;
415 	struct gpio_desc *pwdnn_gpio;
416 	struct regulator *dvdd_supply;
417 	int dvdd_supply_volt, ret;
418 
419 	data = devm_kzalloc(&i2c->dev, sizeof(*data), GFP_KERNEL);
420 	if (!data)
421 		return -ENOMEM;
422 
423 	data->dev = &i2c->dev;
424 	i2c_set_clientdata(i2c, data);
425 
426 	pwdnn_gpio = devm_gpiod_get_optional(&i2c->dev, "pwdnn",
427 					     GPIOD_OUT_HIGH);
428 	if (IS_ERR(pwdnn_gpio)) {
429 		dev_err(&i2c->dev, "Failed to initialize 'pwdnn' gpio\n");
430 		return PTR_ERR(pwdnn_gpio);
431 	} else if (pwdnn_gpio) {
432 		dev_dbg(&i2c->dev, "'pwdnn' from low to high, wait chip on\n");
433 		msleep(RT9120_CHIPON_WAITMS);
434 	}
435 
436 	data->regmap = devm_regmap_init(&i2c->dev, NULL, data,
437 					&rt9120_regmap_config);
438 	if (IS_ERR(data->regmap)) {
439 		ret = PTR_ERR(data->regmap);
440 		dev_err(&i2c->dev, "Failed to init regmap [%d]\n", ret);
441 		return ret;
442 	}
443 
444 	ret = rt9120_check_vendor_info(data);
445 	if (ret) {
446 		dev_err(&i2c->dev, "Failed to check vendor info\n");
447 		return ret;
448 	}
449 
450 	ret = rt9120_do_register_reset(data);
451 	if (ret) {
452 		dev_err(&i2c->dev, "Failed to do register reset\n");
453 		return ret;
454 	}
455 
456 	dvdd_supply = devm_regulator_get(&i2c->dev, "dvdd");
457 	if (IS_ERR(dvdd_supply)) {
458 		dev_err(&i2c->dev, "No dvdd regulator found\n");
459 		return PTR_ERR(dvdd_supply);
460 	}
461 
462 	dvdd_supply_volt = regulator_get_voltage(dvdd_supply);
463 	if (dvdd_supply_volt <= RT9120_LVAPP_THRESUV) {
464 		dev_dbg(&i2c->dev, "dvdd low voltage design\n");
465 		ret = regmap_update_bits(data->regmap, RT9120_REG_UVPOPT,
466 					 RT9120_DVDD_UVSEL_MASK, 0);
467 		if (ret) {
468 			dev_err(&i2c->dev, "Failed to config dvdd uvsel\n");
469 			return ret;
470 		}
471 	}
472 
473 	return devm_snd_soc_register_component(&i2c->dev,
474 					       &rt9120_component_driver,
475 					       &rt9120_dai, 1);
476 }
477 
478 static const struct of_device_id __maybe_unused rt9120_device_table[] = {
479 	{ .compatible = "richtek,rt9120", },
480 	{ }
481 };
482 MODULE_DEVICE_TABLE(of, rt9120_device_table);
483 
484 static struct i2c_driver rt9120_driver = {
485 	.driver = {
486 		.name = "rt9120",
487 		.of_match_table = rt9120_device_table,
488 	},
489 	.probe_new = rt9120_probe,
490 };
491 module_i2c_driver(rt9120_driver);
492 
493 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
494 MODULE_DESCRIPTION("RT9120 Audio Amplifier Driver");
495 MODULE_LICENSE("GPL");
496