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