• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &reg_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, &reg_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, &reg_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, &reg_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