xref: /kernel/linux/linux-6.6/sound/soc/uniphier/evea.c (revision 62306a36)
1// SPDX-License-Identifier: GPL-2.0
2//
3// Socionext UniPhier EVEA ADC/DAC codec driver.
4//
5// Copyright (c) 2016-2017 Socionext Inc.
6
7#include <linux/clk.h>
8#include <linux/module.h>
9#include <linux/of.h>
10#include <linux/regmap.h>
11#include <linux/reset.h>
12#include <sound/pcm.h>
13#include <sound/soc.h>
14
15#define DRV_NAME        "evea"
16#define EVEA_RATES      SNDRV_PCM_RATE_48000
17#define EVEA_FORMATS    SNDRV_PCM_FMTBIT_S32_LE
18
19#define AADCPOW(n)                           (0x0078 + 0x04 * (n))
20#define   AADCPOW_AADC_POWD                   BIT(0)
21#define ALINSW1                              0x0088
22#define   ALINSW1_SEL1_SHIFT                  3
23#define AHPOUTPOW                            0x0098
24#define   AHPOUTPOW_HP_ON                     BIT(4)
25#define ALINEPOW                             0x009c
26#define   ALINEPOW_LIN2_POWD                  BIT(3)
27#define   ALINEPOW_LIN1_POWD                  BIT(4)
28#define ALO1OUTPOW                           0x00a8
29#define   ALO1OUTPOW_LO1_ON                   BIT(4)
30#define ALO2OUTPOW                           0x00ac
31#define   ALO2OUTPOW_ADAC2_MUTE               BIT(0)
32#define   ALO2OUTPOW_LO2_ON                   BIT(4)
33#define AANAPOW                              0x00b8
34#define   AANAPOW_A_POWD                      BIT(4)
35#define ADACSEQ1(n)                          (0x0144 + 0x40 * (n))
36#define   ADACSEQ1_MMUTE                      BIT(1)
37#define ADACSEQ2(n)                          (0x0160 + 0x40 * (n))
38#define   ADACSEQ2_ADACIN_FIX                 BIT(0)
39#define ADAC1ODC                             0x0200
40#define   ADAC1ODC_HP_DIS_RES_MASK            GENMASK(2, 1)
41#define   ADAC1ODC_HP_DIS_RES_OFF             (0x0 << 1)
42#define   ADAC1ODC_HP_DIS_RES_ON              (0x3 << 1)
43#define   ADAC1ODC_ADAC_RAMPCLT_MASK          GENMASK(8, 7)
44#define   ADAC1ODC_ADAC_RAMPCLT_NORMAL        (0x0 << 7)
45#define   ADAC1ODC_ADAC_RAMPCLT_REDUCE        (0x1 << 7)
46
47struct evea_priv {
48	struct clk *clk, *clk_exiv;
49	struct reset_control *rst, *rst_exiv, *rst_adamv;
50	struct regmap *regmap;
51
52	int switch_lin;
53	int switch_lo;
54	int switch_hp;
55};
56
57static const char * const linsw1_sel1_text[] = {
58	"LIN1", "LIN2", "LIN3"
59};
60
61static SOC_ENUM_SINGLE_DECL(linsw1_sel1_enum,
62	ALINSW1, ALINSW1_SEL1_SHIFT,
63	linsw1_sel1_text);
64
65static const struct snd_kcontrol_new linesw1_mux[] = {
66	SOC_DAPM_ENUM("Line In 1 Source", linsw1_sel1_enum),
67};
68
69static const struct snd_soc_dapm_widget evea_widgets[] = {
70	SND_SOC_DAPM_ADC("ADC", NULL, SND_SOC_NOPM, 0, 0),
71	SND_SOC_DAPM_MUX("Line In 1 Mux", SND_SOC_NOPM, 0, 0, linesw1_mux),
72	SND_SOC_DAPM_INPUT("LIN1_LP"),
73	SND_SOC_DAPM_INPUT("LIN1_RP"),
74	SND_SOC_DAPM_INPUT("LIN2_LP"),
75	SND_SOC_DAPM_INPUT("LIN2_RP"),
76	SND_SOC_DAPM_INPUT("LIN3_LP"),
77	SND_SOC_DAPM_INPUT("LIN3_RP"),
78
79	SND_SOC_DAPM_DAC("DAC HP", NULL, SND_SOC_NOPM, 0, 0),
80	SND_SOC_DAPM_DAC("DAC LO1", NULL, SND_SOC_NOPM, 0, 0),
81	SND_SOC_DAPM_DAC("DAC LO2", NULL, SND_SOC_NOPM, 0, 0),
82	SND_SOC_DAPM_OUTPUT("HP1_L"),
83	SND_SOC_DAPM_OUTPUT("HP1_R"),
84	SND_SOC_DAPM_OUTPUT("LO2_L"),
85	SND_SOC_DAPM_OUTPUT("LO2_R"),
86};
87
88static const struct snd_soc_dapm_route evea_routes[] = {
89	{ "Line In 1", NULL, "ADC" },
90	{ "ADC", NULL, "Line In 1 Mux" },
91	{ "Line In 1 Mux", "LIN1", "LIN1_LP" },
92	{ "Line In 1 Mux", "LIN1", "LIN1_RP" },
93	{ "Line In 1 Mux", "LIN2", "LIN2_LP" },
94	{ "Line In 1 Mux", "LIN2", "LIN2_RP" },
95	{ "Line In 1 Mux", "LIN3", "LIN3_LP" },
96	{ "Line In 1 Mux", "LIN3", "LIN3_RP" },
97
98	{ "DAC HP", NULL, "Headphone 1" },
99	{ "DAC LO1", NULL, "Line Out 1" },
100	{ "DAC LO2", NULL, "Line Out 2" },
101	{ "HP1_L", NULL, "DAC HP" },
102	{ "HP1_R", NULL, "DAC HP" },
103	{ "LO2_L", NULL, "DAC LO2" },
104	{ "LO2_R", NULL, "DAC LO2" },
105};
106
107static void evea_set_power_state_on(struct evea_priv *evea)
108{
109	struct regmap *map = evea->regmap;
110
111	regmap_update_bits(map, AANAPOW, AANAPOW_A_POWD,
112			   AANAPOW_A_POWD);
113
114	regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK,
115			   ADAC1ODC_HP_DIS_RES_ON);
116
117	regmap_update_bits(map, ADAC1ODC, ADAC1ODC_ADAC_RAMPCLT_MASK,
118			   ADAC1ODC_ADAC_RAMPCLT_REDUCE);
119
120	regmap_update_bits(map, ADACSEQ2(0), ADACSEQ2_ADACIN_FIX, 0);
121	regmap_update_bits(map, ADACSEQ2(1), ADACSEQ2_ADACIN_FIX, 0);
122	regmap_update_bits(map, ADACSEQ2(2), ADACSEQ2_ADACIN_FIX, 0);
123}
124
125static void evea_set_power_state_off(struct evea_priv *evea)
126{
127	struct regmap *map = evea->regmap;
128
129	regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK,
130			   ADAC1ODC_HP_DIS_RES_ON);
131
132	regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE,
133			   ADACSEQ1_MMUTE);
134	regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE,
135			   ADACSEQ1_MMUTE);
136	regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE,
137			   ADACSEQ1_MMUTE);
138
139	regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON, 0);
140	regmap_update_bits(map, ALO2OUTPOW, ALO2OUTPOW_LO2_ON, 0);
141	regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON, 0);
142}
143
144static int evea_update_switch_lin(struct evea_priv *evea)
145{
146	struct regmap *map = evea->regmap;
147
148	if (evea->switch_lin) {
149		regmap_update_bits(map, ALINEPOW,
150				   ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD,
151				   ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD);
152
153		regmap_update_bits(map, AADCPOW(0), AADCPOW_AADC_POWD,
154				   AADCPOW_AADC_POWD);
155		regmap_update_bits(map, AADCPOW(1), AADCPOW_AADC_POWD,
156				   AADCPOW_AADC_POWD);
157	} else {
158		regmap_update_bits(map, AADCPOW(0), AADCPOW_AADC_POWD, 0);
159		regmap_update_bits(map, AADCPOW(1), AADCPOW_AADC_POWD, 0);
160
161		regmap_update_bits(map, ALINEPOW,
162				   ALINEPOW_LIN2_POWD | ALINEPOW_LIN1_POWD, 0);
163	}
164
165	return 0;
166}
167
168static int evea_update_switch_lo(struct evea_priv *evea)
169{
170	struct regmap *map = evea->regmap;
171
172	if (evea->switch_lo) {
173		regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE, 0);
174		regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE, 0);
175
176		regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON,
177				   ALO1OUTPOW_LO1_ON);
178		regmap_update_bits(map, ALO2OUTPOW,
179				   ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON,
180				   ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON);
181	} else {
182		regmap_update_bits(map, ADACSEQ1(0), ADACSEQ1_MMUTE,
183				   ADACSEQ1_MMUTE);
184		regmap_update_bits(map, ADACSEQ1(2), ADACSEQ1_MMUTE,
185				   ADACSEQ1_MMUTE);
186
187		regmap_update_bits(map, ALO1OUTPOW, ALO1OUTPOW_LO1_ON, 0);
188		regmap_update_bits(map, ALO2OUTPOW,
189				   ALO2OUTPOW_ADAC2_MUTE | ALO2OUTPOW_LO2_ON,
190				   0);
191	}
192
193	return 0;
194}
195
196static int evea_update_switch_hp(struct evea_priv *evea)
197{
198	struct regmap *map = evea->regmap;
199
200	if (evea->switch_hp) {
201		regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE, 0);
202
203		regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON,
204				   AHPOUTPOW_HP_ON);
205
206		regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK,
207				   ADAC1ODC_HP_DIS_RES_OFF);
208	} else {
209		regmap_update_bits(map, ADAC1ODC, ADAC1ODC_HP_DIS_RES_MASK,
210				   ADAC1ODC_HP_DIS_RES_ON);
211
212		regmap_update_bits(map, ADACSEQ1(1), ADACSEQ1_MMUTE,
213				   ADACSEQ1_MMUTE);
214
215		regmap_update_bits(map, AHPOUTPOW, AHPOUTPOW_HP_ON, 0);
216	}
217
218	return 0;
219}
220
221static void evea_update_switch_all(struct evea_priv *evea)
222{
223	evea_update_switch_lin(evea);
224	evea_update_switch_lo(evea);
225	evea_update_switch_hp(evea);
226}
227
228static int evea_get_switch_lin(struct snd_kcontrol *kcontrol,
229			       struct snd_ctl_elem_value *ucontrol)
230{
231	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
232	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
233
234	ucontrol->value.integer.value[0] = evea->switch_lin;
235
236	return 0;
237}
238
239static int evea_set_switch_lin(struct snd_kcontrol *kcontrol,
240			       struct snd_ctl_elem_value *ucontrol)
241{
242	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
243	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
244
245	if (evea->switch_lin == ucontrol->value.integer.value[0])
246		return 0;
247
248	evea->switch_lin = ucontrol->value.integer.value[0];
249
250	return evea_update_switch_lin(evea);
251}
252
253static int evea_get_switch_lo(struct snd_kcontrol *kcontrol,
254			      struct snd_ctl_elem_value *ucontrol)
255{
256	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
257	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
258
259	ucontrol->value.integer.value[0] = evea->switch_lo;
260
261	return 0;
262}
263
264static int evea_set_switch_lo(struct snd_kcontrol *kcontrol,
265			      struct snd_ctl_elem_value *ucontrol)
266{
267	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
268	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
269
270	if (evea->switch_lo == ucontrol->value.integer.value[0])
271		return 0;
272
273	evea->switch_lo = ucontrol->value.integer.value[0];
274
275	return evea_update_switch_lo(evea);
276}
277
278static int evea_get_switch_hp(struct snd_kcontrol *kcontrol,
279			      struct snd_ctl_elem_value *ucontrol)
280{
281	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
282	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
283
284	ucontrol->value.integer.value[0] = evea->switch_hp;
285
286	return 0;
287}
288
289static int evea_set_switch_hp(struct snd_kcontrol *kcontrol,
290			      struct snd_ctl_elem_value *ucontrol)
291{
292	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
293	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
294
295	if (evea->switch_hp == ucontrol->value.integer.value[0])
296		return 0;
297
298	evea->switch_hp = ucontrol->value.integer.value[0];
299
300	return evea_update_switch_hp(evea);
301}
302
303static const struct snd_kcontrol_new evea_controls[] = {
304	SOC_SINGLE_BOOL_EXT("Line Capture Switch", 0,
305			    evea_get_switch_lin, evea_set_switch_lin),
306	SOC_SINGLE_BOOL_EXT("Line Playback Switch", 0,
307			    evea_get_switch_lo, evea_set_switch_lo),
308	SOC_SINGLE_BOOL_EXT("Headphone Playback Switch", 0,
309			    evea_get_switch_hp, evea_set_switch_hp),
310};
311
312static int evea_codec_probe(struct snd_soc_component *component)
313{
314	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
315
316	evea->switch_lin = 1;
317	evea->switch_lo = 1;
318	evea->switch_hp = 1;
319
320	evea_set_power_state_on(evea);
321	evea_update_switch_all(evea);
322
323	return 0;
324}
325
326static int evea_codec_suspend(struct snd_soc_component *component)
327{
328	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
329
330	evea_set_power_state_off(evea);
331
332	reset_control_assert(evea->rst_adamv);
333	reset_control_assert(evea->rst_exiv);
334	reset_control_assert(evea->rst);
335
336	clk_disable_unprepare(evea->clk_exiv);
337	clk_disable_unprepare(evea->clk);
338
339	return 0;
340}
341
342static int evea_codec_resume(struct snd_soc_component *component)
343{
344	struct evea_priv *evea = snd_soc_component_get_drvdata(component);
345	int ret;
346
347	ret = clk_prepare_enable(evea->clk);
348	if (ret)
349		return ret;
350
351	ret = clk_prepare_enable(evea->clk_exiv);
352	if (ret)
353		goto err_out_clock;
354
355	ret = reset_control_deassert(evea->rst);
356	if (ret)
357		goto err_out_clock_exiv;
358
359	ret = reset_control_deassert(evea->rst_exiv);
360	if (ret)
361		goto err_out_reset;
362
363	ret = reset_control_deassert(evea->rst_adamv);
364	if (ret)
365		goto err_out_reset_exiv;
366
367	evea_set_power_state_on(evea);
368	evea_update_switch_all(evea);
369
370	return 0;
371
372err_out_reset_exiv:
373	reset_control_assert(evea->rst_exiv);
374
375err_out_reset:
376	reset_control_assert(evea->rst);
377
378err_out_clock_exiv:
379	clk_disable_unprepare(evea->clk_exiv);
380
381err_out_clock:
382	clk_disable_unprepare(evea->clk);
383
384	return ret;
385}
386
387static struct snd_soc_component_driver soc_codec_evea = {
388	.probe			= evea_codec_probe,
389	.suspend		= evea_codec_suspend,
390	.resume			= evea_codec_resume,
391	.dapm_widgets		= evea_widgets,
392	.num_dapm_widgets	= ARRAY_SIZE(evea_widgets),
393	.dapm_routes		= evea_routes,
394	.num_dapm_routes	= ARRAY_SIZE(evea_routes),
395	.controls		= evea_controls,
396	.num_controls		= ARRAY_SIZE(evea_controls),
397	.idle_bias_on		= 1,
398	.use_pmdown_time	= 1,
399	.endianness		= 1,
400};
401
402static struct snd_soc_dai_driver soc_dai_evea[] = {
403	{
404		.name     = DRV_NAME "-line1",
405		.playback = {
406			.stream_name  = "Line Out 1",
407			.formats      = EVEA_FORMATS,
408			.rates        = EVEA_RATES,
409			.channels_min = 2,
410			.channels_max = 2,
411		},
412		.capture = {
413			.stream_name  = "Line In 1",
414			.formats      = EVEA_FORMATS,
415			.rates        = EVEA_RATES,
416			.channels_min = 2,
417			.channels_max = 2,
418		},
419	},
420	{
421		.name     = DRV_NAME "-hp1",
422		.playback = {
423			.stream_name  = "Headphone 1",
424			.formats      = EVEA_FORMATS,
425			.rates        = EVEA_RATES,
426			.channels_min = 2,
427			.channels_max = 2,
428		},
429	},
430	{
431		.name     = DRV_NAME "-lo2",
432		.playback = {
433			.stream_name  = "Line Out 2",
434			.formats      = EVEA_FORMATS,
435			.rates        = EVEA_RATES,
436			.channels_min = 2,
437			.channels_max = 2,
438		},
439	},
440};
441
442static const struct regmap_config evea_regmap_config = {
443	.reg_bits      = 32,
444	.reg_stride    = 4,
445	.val_bits      = 32,
446	.max_register  = 0xffc,
447	.cache_type    = REGCACHE_NONE,
448};
449
450static int evea_probe(struct platform_device *pdev)
451{
452	struct evea_priv *evea;
453	void __iomem *preg;
454	int ret;
455
456	evea = devm_kzalloc(&pdev->dev, sizeof(struct evea_priv), GFP_KERNEL);
457	if (!evea)
458		return -ENOMEM;
459
460	evea->clk = devm_clk_get(&pdev->dev, "evea");
461	if (IS_ERR(evea->clk))
462		return PTR_ERR(evea->clk);
463
464	evea->clk_exiv = devm_clk_get(&pdev->dev, "exiv");
465	if (IS_ERR(evea->clk_exiv))
466		return PTR_ERR(evea->clk_exiv);
467
468	evea->rst = devm_reset_control_get_shared(&pdev->dev, "evea");
469	if (IS_ERR(evea->rst))
470		return PTR_ERR(evea->rst);
471
472	evea->rst_exiv = devm_reset_control_get_shared(&pdev->dev, "exiv");
473	if (IS_ERR(evea->rst_exiv))
474		return PTR_ERR(evea->rst_exiv);
475
476	preg = devm_platform_ioremap_resource(pdev, 0);
477	if (IS_ERR(preg))
478		return PTR_ERR(preg);
479
480	evea->regmap = devm_regmap_init_mmio(&pdev->dev, preg,
481					     &evea_regmap_config);
482	if (IS_ERR(evea->regmap))
483		return PTR_ERR(evea->regmap);
484
485	ret = clk_prepare_enable(evea->clk);
486	if (ret)
487		return ret;
488
489	ret = clk_prepare_enable(evea->clk_exiv);
490	if (ret)
491		goto err_out_clock;
492
493	ret = reset_control_deassert(evea->rst);
494	if (ret)
495		goto err_out_clock_exiv;
496
497	ret = reset_control_deassert(evea->rst_exiv);
498	if (ret)
499		goto err_out_reset;
500
501	/* ADAMV will hangup if EXIV reset is asserted */
502	evea->rst_adamv = devm_reset_control_get_shared(&pdev->dev, "adamv");
503	if (IS_ERR(evea->rst_adamv)) {
504		ret = PTR_ERR(evea->rst_adamv);
505		goto err_out_reset_exiv;
506	}
507
508	ret = reset_control_deassert(evea->rst_adamv);
509	if (ret)
510		goto err_out_reset_exiv;
511
512	platform_set_drvdata(pdev, evea);
513
514	ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_evea,
515				     soc_dai_evea, ARRAY_SIZE(soc_dai_evea));
516	if (ret)
517		goto err_out_reset_adamv;
518
519	return 0;
520
521err_out_reset_adamv:
522	reset_control_assert(evea->rst_adamv);
523
524err_out_reset_exiv:
525	reset_control_assert(evea->rst_exiv);
526
527err_out_reset:
528	reset_control_assert(evea->rst);
529
530err_out_clock_exiv:
531	clk_disable_unprepare(evea->clk_exiv);
532
533err_out_clock:
534	clk_disable_unprepare(evea->clk);
535
536	return ret;
537}
538
539static void evea_remove(struct platform_device *pdev)
540{
541	struct evea_priv *evea = platform_get_drvdata(pdev);
542
543	reset_control_assert(evea->rst_adamv);
544	reset_control_assert(evea->rst_exiv);
545	reset_control_assert(evea->rst);
546
547	clk_disable_unprepare(evea->clk_exiv);
548	clk_disable_unprepare(evea->clk);
549}
550
551static const struct of_device_id evea_of_match[] __maybe_unused = {
552	{ .compatible = "socionext,uniphier-evea", },
553	{}
554};
555MODULE_DEVICE_TABLE(of, evea_of_match);
556
557static struct platform_driver evea_codec_driver = {
558	.driver = {
559		.name = DRV_NAME,
560		.of_match_table = of_match_ptr(evea_of_match),
561	},
562	.probe  = evea_probe,
563	.remove_new = evea_remove,
564};
565module_platform_driver(evea_codec_driver);
566
567MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
568MODULE_DESCRIPTION("UniPhier EVEA codec driver");
569MODULE_LICENSE("GPL v2");
570