1 /*
2 * Copyright (c) 2021 iSoftStone Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/slab.h>
12 #include <linux/regulator/consumer.h>
13 #include <linux/of.h>
14 #include <linux/clk.h>
15 #include <linux/reset.h>
16 #include <linux/device.h>
17 #include <linux/ioport.h>
18 #include <linux/regmap.h>
19 #include <linux/of_address.h>
20 #include <linux/of_gpio.h>
21
22 #include "t507_codec_impl_linux.h"
23 #include "audio_control.h"
24 #include "audio_core.h"
25 #include "audio_driver_log.h"
26 #include "audio_platform_base.h"
27 #include "osal_io.h"
28 #include <asm/io.h>
29
30 #include "t507_codec_impl_linux.h"
31
32 #define DRV_NAME "sunxi-snd-codec"
33
34 static struct platform_device *g_codec_pdev;
35
36 static struct regmap_config g_codec_regmap_config = {
37 .reg_bits = 32,
38 .reg_stride = 4,
39 .val_bits = 32,
40 .max_register = SUNXI_AUDIO_MAX_REG,
41 .cache_type = REGCACHE_NONE,
42 };
43
44 struct sunxi_codec_mem_info {
45 struct resource res;
46 void __iomem *membase;
47 struct resource *memregion;
48 struct regmap *regmap;
49 };
50
51 struct sunxi_codec_clk_info {
52 struct clk *clk_pll_audio;
53 struct clk *clk_pll_audiox4;
54 struct clk *clk_audio;
55
56 struct clk *clk_bus;
57 struct reset_control *clk_rst;
58 };
59
60 struct sunxi_codec_rglt_info {
61 struct regulator *avcc;
62 };
63
64 struct sunxi_codec_dts_info {
65 uint32_t lineout_vol;
66 };
67
68 struct sunxi_codec_info {
69 struct platform_device *pdev;
70
71 struct sunxi_codec_mem_info mem_info;
72 struct sunxi_codec_clk_info clk_info;
73 struct sunxi_codec_rglt_info rglt_info;
74 struct sunxi_codec_dts_info dts_info;
75
76 /* uint32_t pa_pin_max; */
77 /* struct pa_config *pa_cfg; */
78 };
79
80 #define REG_LABEL(constant) {#constant, constant, 0}
81 #define REG_LABEL_END {NULL, 0, 0}
82 struct reg_label {
83 const char *name;
84 const uint32_t address;
85 uint32_t value;
86 };
87 static struct reg_label g_reg_labels[] = {
88 REG_LABEL(SUNXI_DAC_DPC),
89 REG_LABEL(SUNXI_DAC_FIFO_CTL),
90 REG_LABEL(SUNXI_DAC_FIFO_STA),
91 REG_LABEL(SUNXI_DAC_CNT),
92 REG_LABEL(SUNXI_DAC_DG_REG),
93 REG_LABEL(AC_DAC_REG),
94 REG_LABEL(AC_MIXER_REG),
95 REG_LABEL(AC_RAMP_REG),
96 REG_LABEL_END,
97 };
98
99 struct sample_rate {
100 uint32_t samplerate;
101 uint32_t rate_bit;
102 };
103 static const struct sample_rate g_sample_rate_conv[] = {
104 {44100, 0},
105 {48000, 0},
106 {8000, 5},
107 {32000, 1},
108 {22050, 2},
109 {24000, 2},
110 {16000, 3},
111 {11025, 4},
112 {12000, 4},
113 {192000, 6},
114 {96000, 7},
115 };
116
117 #define KCONTROL_RENDER_VOL 0x00
118 #define KCONTROL_RENDER_MUTE 0x02
119
120 struct KcontrolRender {
121 uint32_t vol;
122 uint32_t mute;
123
124 uint32_t todo;
125 };
126
127 struct KcontrolRender g_KctrlRender = {
128 .vol = 0x1f,
129 .mute = false,
130
131 .todo = 0,
132 };
133
134 /*******************************************************************************
135 * for adm api
136 ******************************************************************************/
T507CodecImplRegmapWrite(uint32_t reg,uint32_t val)137 void T507CodecImplRegmapWrite(uint32_t reg, uint32_t val)
138 {
139 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
140 struct regmap *regmap = codec_info->mem_info.regmap;
141
142 regmap_write(regmap, reg, val);
143 }
144
T507CodecImplRegmapRead(uint32_t reg,uint32_t * val)145 void T507CodecImplRegmapRead(uint32_t reg, uint32_t *val)
146 {
147 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
148 struct regmap *regmap = codec_info->mem_info.regmap;
149
150 regmap_read(regmap, reg, val);
151 }
152
T507CodecImplGetCtrlOps(const struct AudioKcontrol * kcontrol,struct AudioCtrlElemValue * elemValue)153 int32_t T507CodecImplGetCtrlOps(const struct AudioKcontrol *kcontrol, struct AudioCtrlElemValue *elemValue)
154 {
155 uint32_t curValue;
156 uint32_t rcurValue;
157 struct AudioMixerControl *mixerCtrl = NULL;
158
159 AUDIO_DRIVER_LOG_DEBUG("");
160
161 if (kcontrol == NULL || kcontrol->privateValue <= 0 || elemValue == NULL) {
162 AUDIO_DRIVER_LOG_ERR("Audio input param is NULL.");
163 return HDF_ERR_INVALID_OBJECT;
164 }
165 mixerCtrl = (struct AudioMixerControl *)((volatile uintptr_t)kcontrol->privateValue);
166 if (mixerCtrl == NULL) {
167 AUDIO_DRIVER_LOG_ERR("mixerCtrl is NULL.");
168 return HDF_FAILURE;
169 }
170
171 switch (mixerCtrl->reg) {
172 case KCONTROL_RENDER_VOL:
173 curValue = g_KctrlRender.vol;
174 rcurValue = g_KctrlRender.vol;
175 break;
176 case KCONTROL_RENDER_MUTE:
177 curValue = g_KctrlRender.mute;
178 rcurValue = g_KctrlRender.mute;
179 break;
180 default:
181 curValue = g_KctrlRender.todo;
182 rcurValue = g_KctrlRender.todo;
183 break;
184 }
185
186 if (AudioGetCtrlOpsReg(elemValue, mixerCtrl, curValue) != HDF_SUCCESS ||
187 AudioGetCtrlOpsRReg(elemValue, mixerCtrl, rcurValue) != HDF_SUCCESS) {
188 AUDIO_DRIVER_LOG_ERR("Audio codec get kcontrol reg and rreg failed.");
189 return HDF_FAILURE;
190 }
191
192 return HDF_SUCCESS;
193 }
194
T507CodecImplUpdateRegBits(const struct AudioMixerControl * mixerControl,uint32_t value)195 static void T507CodecImplUpdateRegBits(const struct AudioMixerControl *mixerControl, uint32_t value)
196 {
197 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
198 struct regmap *regmap = codec_info->mem_info.regmap;
199
200 if (mixerControl == NULL) {
201 AUDIO_DRIVER_LOG_ERR("param mixerControl is null.");
202 return;
203 }
204
205 AUDIO_DRIVER_LOG_DEBUG("value -> %u", value);
206
207 switch (mixerControl->reg) {
208 case KCONTROL_RENDER_VOL:
209 g_KctrlRender.vol = value;
210 break;
211 case KCONTROL_RENDER_MUTE:
212 g_KctrlRender.mute = value;
213 break;
214 default:
215 break;
216 }
217
218 if (g_KctrlRender.mute) {
219 regmap_update_bits(regmap, AC_DAC_REG, 0x1F << LINEOUT_VOL, 0 << LINEOUT_VOL);
220 } else {
221 regmap_update_bits(regmap, AC_DAC_REG, 0x1F << LINEOUT_VOL, g_KctrlRender.vol << LINEOUT_VOL);
222 }
223 }
224
T507CodecImplSetCtrlOps(const struct AudioKcontrol * kcontrol,const struct AudioCtrlElemValue * elemValue)225 int32_t T507CodecImplSetCtrlOps(const struct AudioKcontrol *kcontrol, const struct AudioCtrlElemValue *elemValue)
226 {
227 uint32_t value;
228 uint32_t rvalue;
229 bool updateRReg = false;
230 struct AudioMixerControl *mixerCtrl = NULL;
231
232 AUDIO_DRIVER_LOG_DEBUG("");
233
234 if (kcontrol == NULL || (kcontrol->privateValue <= 0) || elemValue == NULL) {
235 AUDIO_DRIVER_LOG_ERR("Audio input param is NULL.");
236 return HDF_ERR_INVALID_OBJECT;
237 }
238
239 mixerCtrl = (struct AudioMixerControl *)((volatile uintptr_t)kcontrol->privateValue);
240 if (AudioSetCtrlOpsReg(kcontrol, elemValue, mixerCtrl, &value) != HDF_SUCCESS) {
241 AUDIO_DRIVER_LOG_ERR("AudioSetCtrlOpsReg is failed.");
242 return HDF_ERR_INVALID_OBJECT;
243 }
244 T507CodecImplUpdateRegBits(mixerCtrl, value);
245
246 if (AudioSetCtrlOpsRReg(elemValue, mixerCtrl, &rvalue, &updateRReg) != HDF_SUCCESS) {
247 AUDIO_DRIVER_LOG_ERR("AudioSetCtrlOpsRReg is failed.");
248 return HDF_ERR_INVALID_OBJECT;
249 }
250 if (updateRReg) {
251 T507CodecImplUpdateRegBits(mixerCtrl, rvalue);
252 }
253
254 return HDF_SUCCESS;
255 }
256
257 /* ops api: read default reg value form codec_config.hcs */
T507CodecImplRegDefaultInit(struct AudioRegCfgGroupNode ** regCfgGroup)258 int32_t T507CodecImplRegDefaultInit(struct AudioRegCfgGroupNode **regCfgGroup)
259 {
260 int32_t i;
261 struct AudioAddrConfig *regAttr = NULL;
262
263 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
264 struct regmap *regmap = codec_info->mem_info.regmap;
265
266 AUDIO_DRIVER_LOG_DEBUG("");
267
268 if (regCfgGroup == NULL || regCfgGroup[AUDIO_INIT_GROUP] == NULL ||
269 regCfgGroup[AUDIO_INIT_GROUP]->addrCfgItem == NULL || regCfgGroup[AUDIO_INIT_GROUP]->itemNum <= 0) {
270 AUDIO_DRIVER_LOG_ERR("input invalid parameter.");
271 return HDF_FAILURE;
272 }
273 regAttr = regCfgGroup[AUDIO_INIT_GROUP]->addrCfgItem;
274
275 for (i = 0; i < regCfgGroup[AUDIO_INIT_GROUP]->itemNum; i++) {
276 regmap_write(regmap, regAttr[i].addr, regAttr[i].value);
277 }
278
279 AUDIO_DRIVER_LOG_DEBUG("success.");
280 return HDF_SUCCESS;
281 }
282
T507CodecImplStartup(enum AudioStreamType streamType)283 int32_t T507CodecImplStartup(enum AudioStreamType streamType)
284 {
285 AUDIO_DRIVER_LOG_DEBUG("");
286
287 if (streamType == AUDIO_CAPTURE_STREAM) {
288 /* audiocodec unsupport capture */
289 return HDF_SUCCESS;
290 }
291
292 AUDIO_DRIVER_LOG_DEBUG("success.");
293 return HDF_SUCCESS;
294 }
295
T507CodecImplHwParams(enum AudioStreamType streamType,enum AudioFormat format,uint32_t channels,uint32_t rate)296 int32_t T507CodecImplHwParams(enum AudioStreamType streamType, enum AudioFormat format, uint32_t channels, uint32_t rate)
297 {
298 int i;
299 uint32_t freq_point;
300 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
301 struct sunxi_codec_clk_info *clk_info = &codec_info->clk_info;
302 struct regmap *regmap = codec_info->mem_info.regmap;
303
304 AUDIO_DRIVER_LOG_DEBUG("");
305
306 if (streamType == AUDIO_CAPTURE_STREAM) {
307 /* audiocodec unsupport capture */
308 return HDF_SUCCESS;
309 }
310
311 /* set pll clk */
312 switch (rate) {
313 case 8000:
314 case 12000:
315 case 16000:
316 case 24000:
317 case 32000:
318 case 48000:
319 case 64000:
320 case 96000:
321 case 192000:
322 freq_point = 24576000;
323 break;
324 case 11025:
325 case 22050:
326 case 44100:
327 case 88200:
328 case 176400:
329 freq_point = 22579200;
330 break;
331 default:
332 AUDIO_DRIVER_LOG_ERR("rate: %d is not define.", rate);
333 return HDF_FAILURE;
334 }
335 AUDIO_DRIVER_LOG_DEBUG(" freq_point %u", freq_point);
336
337 /* moduleclk freq = 49.152/45.1584M, audio clk source = 98.304/90.3168M, own sun50iw9 */
338 if (clk_set_rate(clk_info->clk_pll_audiox4, freq_point * 4)) {
339 AUDIO_DRIVER_LOG_ERR("clk pllaudio set rate failed");
340 return -EINVAL;
341 }
342 if (clk_set_rate(clk_info->clk_audio, freq_point * 2)) {
343 AUDIO_DRIVER_LOG_ERR("clk audio set rate failed");
344 return -EINVAL;
345 }
346
347 /* set bits */
348 switch (format) {
349 case AUDIO_FORMAT_TYPE_PCM_16_BIT:
350 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x3 << DAC_FIFO_MODE, 0x3 << DAC_FIFO_MODE);
351 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x1 << TX_SAMPLE_BITS, 0x0 << TX_SAMPLE_BITS);
352 AUDIO_DRIVER_LOG_DEBUG(" format 16");
353 break;
354 case AUDIO_FORMAT_TYPE_PCM_24_BIT:
355 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x3 << DAC_FIFO_MODE, 0x0 << DAC_FIFO_MODE);
356 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x1 << TX_SAMPLE_BITS, 0x1 << TX_SAMPLE_BITS);
357 AUDIO_DRIVER_LOG_DEBUG(" format 24");
358 break;
359 default:
360 AUDIO_DRIVER_LOG_ERR("format: %d is not define.", format);
361 return HDF_FAILURE;
362 }
363
364 /* set rate */
365 i = 0;
366 for (i = 0; i < ARRAY_SIZE(g_sample_rate_conv); i++) {
367 if (g_sample_rate_conv[i].samplerate == rate)
368 break;
369 }
370 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x7 << DAC_FS, g_sample_rate_conv[i].rate_bit << DAC_FS);
371 AUDIO_DRIVER_LOG_DEBUG(" rate %u", rate);
372
373 /* set channels */
374 switch (channels) {
375 case 1:
376 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x1 << DAC_MONO_EN, 0x1 << DAC_MONO_EN);
377 break;
378 case 2:
379 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x1 << DAC_MONO_EN, 0x0 << DAC_MONO_EN);
380 break;
381 default:
382 AUDIO_DRIVER_LOG_ERR("channel: %d is not define.", channels);
383 return HDF_FAILURE;
384 }
385 AUDIO_DRIVER_LOG_DEBUG(" channels %u", channels);
386
387 /* clear fifo */
388 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x1 << DAC_FIFO_FLUSH, 0x1 << DAC_FIFO_FLUSH);
389 regmap_write(regmap, SUNXI_DAC_FIFO_STA, 1 << DAC_TXE_INT | 1 << DAC_TXU_INT | 1 << DAC_TXO_INT);
390 regmap_write(regmap, SUNXI_DAC_CNT, 0);
391
392 AUDIO_DRIVER_LOG_DEBUG("success.");
393 return HDF_SUCCESS;
394 }
395
renderRouteCtrl(bool enable)396 static void renderRouteCtrl(bool enable)
397 {
398 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
399 struct regmap *regmap = codec_info->mem_info.regmap;
400
401 AUDIO_DRIVER_LOG_DEBUG("");
402
403 if (enable) {
404 regmap_update_bits(regmap, SUNXI_DAC_DPC, 0x1 << EN_DA, 0x1 << EN_DA);
405 regmap_update_bits(regmap, AC_DAC_REG, 0x1 << DACLEN, 0x1 << DACLEN);
406 regmap_update_bits(regmap, AC_DAC_REG, 0x1 << DACREN, 0x1 << DACREN);
407 regmap_update_bits(regmap, AC_DAC_REG, 0x1 << LINEOUTL_EN, 0x1 << LINEOUTL_EN);
408 regmap_update_bits(regmap, AC_DAC_REG, 0x1 << LINEOUTR_EN, 0x1 << LINEOUTR_EN);
409 regmap_update_bits(regmap, AC_RAMP_REG, 0x1 << RDEN, 0x1 << RDEN);
410 } else {
411 regmap_update_bits(regmap, AC_RAMP_REG, 0x1 << RDEN, 0x0 << RDEN);
412 regmap_update_bits(regmap, AC_DAC_REG, 0x1 << LINEOUTL_EN, 0x0 << LINEOUTL_EN);
413 regmap_update_bits(regmap, AC_DAC_REG, 0x1 << LINEOUTR_EN, 0x0 << LINEOUTR_EN);
414 regmap_update_bits(regmap, AC_DAC_REG, 0x1 << DACLEN, 0x0 << DACLEN);
415 regmap_update_bits(regmap, AC_DAC_REG, 0x1 << DACREN, 0x0 << DACREN);
416 regmap_update_bits(regmap, SUNXI_DAC_DPC, 0x1 << EN_DA, 0x0 << EN_DA);
417 }
418 }
419
T507CodecImplTrigger(enum AudioStreamType streamType,bool enable)420 int32_t T507CodecImplTrigger(enum AudioStreamType streamType, bool enable)
421 {
422 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
423 struct regmap *regmap = codec_info->mem_info.regmap;
424
425 AUDIO_DRIVER_LOG_DEBUG("");
426
427 if (streamType == AUDIO_CAPTURE_STREAM) {
428 /* audiocodec unsupport capture */
429 return HDF_SUCCESS;
430 }
431
432 renderRouteCtrl(enable);
433
434 if (enable) {
435 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 1 << DAC_DRQ_EN, 1 << DAC_DRQ_EN);
436 } else {
437 regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 1 << DAC_DRQ_EN, 0 << DAC_DRQ_EN);
438 }
439
440 AUDIO_DRIVER_LOG_DEBUG("success.");
441 return HDF_SUCCESS;
442 }
443
444 /*******************************************************************************
445 * for linux probe
446 *******************************************************************************/
447 static int snd_sunxi_codec_clk_init(struct platform_device *pdev, struct sunxi_codec_clk_info *clk_info);
448 static void snd_sunxi_codec_clk_exit(struct platform_device *pdev, struct sunxi_codec_clk_info *clk_info);
449 static int snd_sunxi_codec_clk_enable(struct platform_device *pdev, struct sunxi_codec_clk_info *clk_info);
450 static void snd_sunxi_codec_clk_disable(struct platform_device *pdev, struct sunxi_codec_clk_info *clk_info);
451
452 static int snd_sunxi_codec_rglt_init(struct platform_device *pdev, struct sunxi_codec_rglt_info *rglt_info);
453 static void snd_sunxi_codec_rglt_exit(struct platform_device *pdev, struct sunxi_codec_rglt_info *rglt_info);
454 /* static int snd_sunxi_codec_rglt_enable(struct platform_device *pdev, struct sunxi_codec_rglt_info *rglt_info); */
455 /* static void snd_sunxi_codec_rglt_disable(struct platform_device *pdev, struct sunxi_codec_rglt_info *rglt_info); */
456
snd_sunxi_codec_mem_init(struct platform_device * pdev,struct sunxi_codec_mem_info * mem_info)457 static int snd_sunxi_codec_mem_init(struct platform_device *pdev, struct sunxi_codec_mem_info *mem_info)
458 {
459 int ret = 0;
460 struct device_node *np = pdev->dev.of_node;
461
462 AUDIO_DRIVER_LOG_DEBUG("");
463
464 ret = of_address_to_resource(np, 0, &mem_info->res);
465 if (ret) {
466 AUDIO_DRIVER_LOG_ERR("parse device node resource failed");
467 ret = -EINVAL;
468 goto err_of_addr_to_resource;
469 }
470
471 mem_info->memregion = devm_request_mem_region(&pdev->dev, mem_info->res.start, resource_size(&mem_info->res), DRV_NAME);
472 if (IS_ERR_OR_NULL(mem_info->memregion)) {
473 AUDIO_DRIVER_LOG_ERR("memory region already claimed");
474 ret = -EBUSY;
475 goto err_devm_request_region;
476 }
477
478 mem_info->membase = devm_ioremap(&pdev->dev, mem_info->memregion->start, resource_size(mem_info->memregion));
479 if (IS_ERR_OR_NULL(mem_info->membase)) {
480 AUDIO_DRIVER_LOG_ERR("ioremap failed");
481 ret = -EBUSY;
482 goto err_devm_ioremap;
483 }
484
485 mem_info->regmap = devm_regmap_init_mmio(&pdev->dev, mem_info->membase, &g_codec_regmap_config);
486 if (IS_ERR_OR_NULL(mem_info->regmap)) {
487 AUDIO_DRIVER_LOG_ERR("regmap init failed");
488 ret = -EINVAL;
489 goto err_devm_regmap_init;
490 }
491
492 return 0;
493
494 err_devm_regmap_init:
495 devm_iounmap(&pdev->dev, mem_info->membase);
496 err_devm_ioremap:
497 devm_release_mem_region(&pdev->dev, mem_info->memregion->start, resource_size(mem_info->memregion));
498 err_devm_request_region:
499 err_of_addr_to_resource:
500 return ret;
501 }
502
snd_sunxi_codec_mem_exit(struct platform_device * pdev,struct sunxi_codec_mem_info * mem_info)503 static void snd_sunxi_codec_mem_exit(struct platform_device *pdev, struct sunxi_codec_mem_info *mem_info)
504 {
505 AUDIO_DRIVER_LOG_DEBUG("");
506
507 devm_iounmap(&pdev->dev, mem_info->membase);
508 devm_release_mem_region(&pdev->dev, mem_info->memregion->start, resource_size(mem_info->memregion));
509 }
510
snd_sunxi_codec_clk_init(struct platform_device * pdev,struct sunxi_codec_clk_info * clk_info)511 static int snd_sunxi_codec_clk_init(struct platform_device *pdev, struct sunxi_codec_clk_info *clk_info)
512 {
513 int ret = 0;
514 struct device_node *np = pdev->dev.of_node;
515
516 AUDIO_DRIVER_LOG_DEBUG("");
517
518 /* get rst clk */
519 clk_info->clk_rst = devm_reset_control_get(&pdev->dev, NULL);
520 if (IS_ERR_OR_NULL(clk_info->clk_rst)) {
521 AUDIO_DRIVER_LOG_ERR("clk rst get failed\n");
522 ret = PTR_ERR(clk_info->clk_rst);
523 goto err_get_clk_rst;
524 }
525
526 /* get bus clk */
527 clk_info->clk_bus = of_clk_get_by_name(np, "clk_bus_audio");
528 if (IS_ERR_OR_NULL(clk_info->clk_bus)) {
529 AUDIO_DRIVER_LOG_ERR("clk bus get failed\n");
530 ret = PTR_ERR(clk_info->clk_bus);
531 goto err_get_clk_bus;
532 }
533
534 /* get parent clk */
535 clk_info->clk_pll_audio = of_clk_get_by_name(np, "clk_pll_audio");
536 if (IS_ERR_OR_NULL(clk_info->clk_pll_audio)) {
537 AUDIO_DRIVER_LOG_ERR("clk pll audio get failed");
538 ret = PTR_ERR(clk_info->clk_pll_audio);
539 goto err_get_clk_pll_audio;
540 }
541
542 clk_info->clk_pll_audiox4 = of_clk_get_by_name(np, "clk_pll_audio_4x");
543 if (IS_ERR_OR_NULL(clk_info->clk_pll_audiox4)) {
544 AUDIO_DRIVER_LOG_ERR("clk pll audio4x get failed");
545 ret = PTR_ERR(clk_info->clk_pll_audiox4);
546 goto err_get_clk_pll_audiox4;
547 }
548
549 /* get module clk */
550 clk_info->clk_audio = of_clk_get_by_name(np, "clk_audio");
551 if (IS_ERR_OR_NULL(clk_info->clk_audio)) {
552 AUDIO_DRIVER_LOG_ERR("clk audio get failed");
553 ret = PTR_ERR(clk_info->clk_audio);
554 goto err_get_clk_audio;
555 }
556
557 /* set clk audio parent of pllaudio */
558 if (clk_set_parent(clk_info->clk_audio, clk_info->clk_pll_audiox4)) {
559 AUDIO_DRIVER_LOG_ERR("set parent clk audio failed");
560 ret = -EINVAL;
561 goto err_set_parent;
562 }
563
564 ret = snd_sunxi_codec_clk_enable(pdev, clk_info);
565 if (ret) {
566 AUDIO_DRIVER_LOG_ERR("clk enable failed");
567 ret = -EINVAL;
568 goto err_clk_enable;
569 }
570
571 return 0;
572
573 err_clk_enable:
574 err_set_parent:
575 clk_put(clk_info->clk_audio);
576 err_get_clk_audio:
577 clk_put(clk_info->clk_pll_audiox4);
578 err_get_clk_pll_audiox4:
579 clk_put(clk_info->clk_pll_audio);
580 err_get_clk_pll_audio:
581 clk_put(clk_info->clk_bus);
582 err_get_clk_bus:
583 err_get_clk_rst:
584 return ret;
585 }
586
snd_sunxi_codec_clk_exit(struct platform_device * pdev,struct sunxi_codec_clk_info * clk_info)587 static void snd_sunxi_codec_clk_exit(struct platform_device *pdev, struct sunxi_codec_clk_info *clk_info)
588 {
589 AUDIO_DRIVER_LOG_DEBUG("");
590
591 snd_sunxi_codec_clk_disable(pdev, clk_info);
592 clk_put(clk_info->clk_audio);
593 clk_put(clk_info->clk_pll_audiox4);
594 clk_put(clk_info->clk_pll_audio);
595 clk_put(clk_info->clk_bus);
596 }
597
snd_sunxi_codec_clk_enable(struct platform_device * pdev,struct sunxi_codec_clk_info * clk_info)598 static int snd_sunxi_codec_clk_enable(struct platform_device *pdev, struct sunxi_codec_clk_info *clk_info)
599 {
600 int ret = 0;
601
602 AUDIO_DRIVER_LOG_DEBUG("");
603
604 if (reset_control_deassert(clk_info->clk_rst)) {
605 AUDIO_DRIVER_LOG_ERR("clk rst deassert failed\n");
606 ret = -EINVAL;
607 goto err_deassert_rst;
608 }
609
610 if (clk_prepare_enable(clk_info->clk_bus)) {
611 AUDIO_DRIVER_LOG_ERR("clk bus enable failed\n");
612 goto err_enable_clk_bus;
613 }
614
615 if (clk_prepare_enable(clk_info->clk_pll_audio)) {
616 AUDIO_DRIVER_LOG_ERR("pllaudio enable failed");
617 goto err_enable_clk_pll_audio;
618 }
619
620 if (clk_prepare_enable(clk_info->clk_pll_audiox4)) {
621 AUDIO_DRIVER_LOG_ERR("pllaudiox4 enable failed");
622 goto err_enable_clk_pll_audiox4;
623 }
624
625 if (clk_prepare_enable(clk_info->clk_audio)) {
626 AUDIO_DRIVER_LOG_ERR("dacclk enable failed");
627 goto err_enable_clk_audio;
628 }
629
630 return 0;
631
632 err_enable_clk_audio:
633 clk_disable_unprepare(clk_info->clk_pll_audiox4);
634 err_enable_clk_pll_audiox4:
635 clk_disable_unprepare(clk_info->clk_pll_audio);
636 err_enable_clk_pll_audio:
637 clk_disable_unprepare(clk_info->clk_bus);
638 err_enable_clk_bus:
639 reset_control_assert(clk_info->clk_rst);
640 err_deassert_rst:
641 return ret;
642 }
643
snd_sunxi_codec_clk_disable(struct platform_device * pdev,struct sunxi_codec_clk_info * clk_info)644 static void snd_sunxi_codec_clk_disable(struct platform_device *pdev, struct sunxi_codec_clk_info *clk_info)
645 {
646 AUDIO_DRIVER_LOG_DEBUG("");
647
648 clk_disable_unprepare(clk_info->clk_audio);
649 clk_disable_unprepare(clk_info->clk_pll_audiox4);
650 clk_disable_unprepare(clk_info->clk_pll_audio);
651 clk_disable_unprepare(clk_info->clk_bus);
652 reset_control_assert(clk_info->clk_rst);
653 }
654
snd_sunxi_codec_rglt_init(struct platform_device * pdev,struct sunxi_codec_rglt_info * rglt_info)655 static int snd_sunxi_codec_rglt_init(struct platform_device *pdev, struct sunxi_codec_rglt_info *rglt_info)
656 {
657 int ret = 0;
658
659 AUDIO_DRIVER_LOG_DEBUG("");
660
661 rglt_info->avcc = regulator_get(&pdev->dev, "avcc");
662 if (IS_ERR_OR_NULL(rglt_info->avcc)) {
663 AUDIO_DRIVER_LOG_ERR("get avcc failed");
664 ret = -EFAULT;
665 goto err_regulator_get_avcc;
666 }
667 ret = regulator_set_voltage(rglt_info->avcc, 1800000, 1800000);
668 if (ret < 0) {
669 AUDIO_DRIVER_LOG_ERR("set avcc voltage failed");
670 ret = -EFAULT;
671 goto err_regulator_set_vol_avcc;
672 }
673 ret = regulator_enable(rglt_info->avcc);
674 if (ret < 0) {
675 AUDIO_DRIVER_LOG_ERR("enable avcc failed");
676 ret = -EFAULT;
677 goto err_regulator_enable_avcc;
678 }
679
680 return 0;
681
682 err_regulator_enable_avcc:
683 err_regulator_set_vol_avcc:
684 if (rglt_info->avcc) {
685 regulator_put(rglt_info->avcc);
686 }
687 err_regulator_get_avcc:
688 return ret;
689 }
690
snd_sunxi_codec_rglt_exit(struct platform_device * pdev,struct sunxi_codec_rglt_info * rglt_info)691 static void snd_sunxi_codec_rglt_exit(struct platform_device *pdev, struct sunxi_codec_rglt_info *rglt_info)
692 {
693 AUDIO_DRIVER_LOG_DEBUG("");
694
695 if (rglt_info->avcc) {
696 if (!IS_ERR_OR_NULL(rglt_info->avcc)) {
697 regulator_disable(rglt_info->avcc);
698 regulator_put(rglt_info->avcc);
699 }
700 }
701 }
702
703 #if 0
704 static int snd_sunxi_codec_rglt_enable(struct platform_device *pdev, struct sunxi_codec_rglt_info *rglt_info)
705 {
706 int ret;
707
708 AUDIO_DRIVER_LOG_DEBUG("");
709
710 if (rglt_info->avcc)
711 if (!IS_ERR_OR_NULL(rglt_info->avcc)) {
712 ret = regulator_enable(rglt_info->avcc);
713 if (ret) {
714 AUDIO_DRIVER_LOG_ERR("enable avcc failed");
715 return -1;
716 }
717 }
718
719 return 0;
720 }
721
722 static void snd_sunxi_codec_rglt_disable(struct platform_device *pdev, struct sunxi_codec_rglt_info *rglt_info)
723 {
724 AUDIO_DRIVER_LOG_DEBUG("");
725
726 if (rglt_info->avcc) {
727 if (!IS_ERR_OR_NULL(rglt_info->avcc)) {
728 regulator_disable(rglt_info->avcc);
729 }
730 }
731 }
732 #endif
733
snd_sunxi_dts_params_init(struct platform_device * pdev,struct sunxi_codec_dts_info * dts_info)734 static void snd_sunxi_dts_params_init(struct platform_device *pdev, struct sunxi_codec_dts_info *dts_info)
735 {
736 int ret = 0;
737 uint32_t temp_val;
738 struct device_node *np = pdev->dev.of_node;
739
740 AUDIO_DRIVER_LOG_DEBUG("");
741
742 /* lineout volume */
743 ret = of_property_read_u32(np, "lineout-vol", &temp_val);
744 if (ret < 0) {
745 dts_info->lineout_vol = 0;
746 } else {
747 dts_info->lineout_vol = temp_val;
748 }
749
750 AUDIO_DRIVER_LOG_DEBUG("lineout vol -> %u\n", dts_info->lineout_vol);
751 }
752
753 /* sysfs debug */
snd_sunxi_debug_show_reg(struct device * dev,struct device_attribute * attr,char * buf)754 static ssize_t snd_sunxi_debug_show_reg(struct device *dev, struct device_attribute *attr, char *buf)
755 {
756 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
757 struct regmap *regmap = codec_info->mem_info.regmap;
758 size_t count = 0, i = 0;
759 uint32_t reg_val;
760 uint32_t size = ARRAY_SIZE(g_reg_labels);
761
762 while ((i < size) && (g_reg_labels[i].name != NULL)) {
763 regmap_read(regmap, g_reg_labels[i].address, ®_val);
764 printk("%-30s [0x%03x]: 0x%8x save_val:0x%x\n",
765 g_reg_labels[i].name,
766 g_reg_labels[i].address, reg_val,
767 g_reg_labels[i].value);
768 i++;
769 }
770
771 return count;
772 }
773
snd_sunxi_debug_store_reg(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)774 static ssize_t snd_sunxi_debug_store_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
775 {
776 struct sunxi_codec_info *codec_info = dev_get_drvdata(&g_codec_pdev->dev);
777 struct regmap *regmap = codec_info->mem_info.regmap;
778 int scanf_cnt;
779 uint32_t reg_val;
780 uint32_t input_reg_val = 0;
781 uint32_t input_reg_offset = 0;
782
783 scanf_cnt = sscanf(buf, "0x%x 0x%x", &input_reg_offset, &input_reg_val);
784 if (scanf_cnt == 0 || scanf_cnt > 2) {
785 pr_info("usage read : echo 0x > audio_reg\n");
786 pr_info("usage write: echo 0x 0x > audio_reg\n");
787 return count;
788 }
789
790 if (input_reg_offset > SUNXI_AUDIO_MAX_REG) {
791 pr_info("reg offset > audio max reg[0x%x]\n", SUNXI_AUDIO_MAX_REG);
792 return count;
793 }
794
795 if (scanf_cnt == 1) {
796 regmap_read(regmap, input_reg_offset, ®_val);
797 pr_info("reg[0x%03x]: 0x%x\n", input_reg_offset, reg_val);
798 return count;
799 } else if (scanf_cnt == 2) {
800 regmap_read(regmap, input_reg_offset, ®_val);
801 pr_info("reg[0x%03x]: 0x%x (old)\n", input_reg_offset, reg_val);
802 regmap_write(regmap, input_reg_offset, input_reg_val);
803 regmap_read(regmap, input_reg_offset, ®_val);
804 pr_info("reg[0x%03x]: 0x%x (new)\n", input_reg_offset, reg_val);
805 }
806
807 return count;
808 }
809
810 static DEVICE_ATTR(audio_reg, 0644, snd_sunxi_debug_show_reg, snd_sunxi_debug_store_reg);
811
812 static struct attribute *audio_debug_attrs[] = {
813 &dev_attr_audio_reg.attr,
814 NULL,
815 };
816
817 static struct attribute_group debug_attr = {
818 .name = "audio_debug",
819 .attrs = audio_debug_attrs,
820 };
821
sunxi_internal_codec_dev_probe(struct platform_device * pdev)822 static int sunxi_internal_codec_dev_probe(struct platform_device *pdev)
823 {
824 int ret;
825 struct device *dev = &pdev->dev;
826 struct device_node *np = pdev->dev.of_node;
827 struct sunxi_codec_info *codec_info;
828 struct sunxi_codec_mem_info *mem_info;
829 struct sunxi_codec_clk_info *clk_info;
830 struct sunxi_codec_rglt_info *rglt_info;
831 struct sunxi_codec_dts_info *dts_info;
832
833 AUDIO_DRIVER_LOG_DEBUG("");
834
835 /* sunxi codec info */
836 codec_info = devm_kzalloc(dev, sizeof(struct sunxi_codec_info), GFP_KERNEL);
837 if (!codec_info) {
838 AUDIO_DRIVER_LOG_ERR("can't allocate sunxi codec memory");
839 ret = -ENOMEM;
840 goto err_devm_kzalloc;
841 }
842 dev_set_drvdata(dev, codec_info);
843 mem_info = &codec_info->mem_info;
844 clk_info = &codec_info->clk_info;
845 rglt_info = &codec_info->rglt_info;
846 dts_info = &codec_info->dts_info;
847
848 /* memio init */
849 ret = snd_sunxi_codec_mem_init(pdev, mem_info);
850 if (ret) {
851 AUDIO_DRIVER_LOG_ERR("mem init failed");
852 ret = -ENOMEM;
853 goto err_mem_init;
854 }
855
856 /* clk init */
857 ret = snd_sunxi_codec_clk_init(pdev, clk_info);
858 if (ret) {
859 AUDIO_DRIVER_LOG_ERR("clk init failed");
860 ret = -ENOMEM;
861 goto err_clk_init;
862 }
863
864 /* regulator init */
865 ret = snd_sunxi_codec_rglt_init(pdev, rglt_info);
866 if (ret) {
867 AUDIO_DRIVER_LOG_ERR("regulator init failed");
868 ret = -ENOMEM;
869 goto err_regulator_init;
870 }
871
872 /* dts_params init */
873 snd_sunxi_dts_params_init(pdev, dts_info);
874
875 ret = sysfs_create_group(&pdev->dev.kobj, &debug_attr);
876 if (ret)
877 AUDIO_DRIVER_LOG_ERR("sysfs debug create failed");
878
879 g_codec_pdev = pdev;
880
881 AUDIO_DRIVER_LOG_DEBUG("register internal-codec codec success");
882
883 return 0;
884
885 snd_sunxi_codec_rglt_exit(pdev, rglt_info);
886 err_regulator_init:
887 snd_sunxi_codec_clk_exit(pdev, clk_info);
888 err_clk_init:
889 snd_sunxi_codec_mem_exit(pdev, mem_info);
890 err_mem_init:
891 devm_kfree(dev, codec_info);
892 err_devm_kzalloc:
893 of_node_put(np);
894
895 return ret;
896 }
897
sunxi_internal_codec_dev_remove(struct platform_device * pdev)898 static int sunxi_internal_codec_dev_remove(struct platform_device *pdev)
899 {
900 struct device *dev = &pdev->dev;
901 struct sunxi_codec_info *codec_info = dev_get_drvdata(dev);
902 struct sunxi_codec_mem_info *mem_info = &codec_info->mem_info;
903 struct sunxi_codec_clk_info *clk_info = &codec_info->clk_info;
904 struct sunxi_codec_rglt_info *rglt_info = &codec_info->rglt_info;
905
906 AUDIO_DRIVER_LOG_DEBUG("");
907
908 sysfs_remove_group(&pdev->dev.kobj, &debug_attr);
909
910 snd_sunxi_codec_mem_exit(pdev, mem_info);
911 snd_sunxi_codec_clk_exit(pdev, clk_info);
912 snd_sunxi_codec_rglt_exit(pdev, rglt_info);
913
914 /* sunxi codec custom info free */
915 devm_kfree(dev, codec_info);
916 of_node_put(pdev->dev.of_node);
917
918 AUDIO_DRIVER_LOG_DEBUG("unregister internal-codec codec success");
919
920 return 0;
921 }
922
923 static const struct of_device_id sunxi_internal_codec_of_match[] = {
924 { .compatible = "allwinner," DRV_NAME, },
925 {},
926 };
927 MODULE_DEVICE_TABLE(of, sunxi_internal_codec_of_match);
928
929 static struct platform_driver sunxi_internal_codec_driver = {
930 .driver = {
931 .name = DRV_NAME,
932 .owner = THIS_MODULE,
933 .of_match_table = sunxi_internal_codec_of_match,
934 },
935 .probe = sunxi_internal_codec_dev_probe,
936 .remove = sunxi_internal_codec_dev_remove,
937 };
938
939 module_platform_driver(sunxi_internal_codec_driver);
940
941 MODULE_DESCRIPTION("sunxi soundcard codec of internal-codec");
942