1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #include <hal_cmd.h>
33 #include <sound/snd_core.h>
34 #include "sunxi-codec.h"
35 
36 
37 /*#define TEST_MODE*/
38 
39 #ifndef u32
40 #define u32 unsigned int
41 #endif
42 
43 #define ADDR_WIDTH  0x3f
44 
45 u32 read_prcm_wvalue(u32 addr, void *ADDA_PR_CFG_REG);
46 void write_prcm_wvalue(u32 addr, u32 val, void *ADDA_PR_CFG_REG);
47 
sunxi_codec_read(struct snd_codec * codec,unsigned int reg)48 unsigned int sunxi_codec_read(struct snd_codec *codec, unsigned int reg)
49 {
50     /* struct sunxi_codec_info *sunxi_codec = codec->private_data; */
51     unsigned int reg_val;
52 
53     if (reg >= SUNXI_PR_CFG) {
54         reg = reg - SUNXI_PR_CFG;
55         return read_prcm_wvalue(reg, codec->codec_base_addr + SUNXI_PR_CFG);
56     } else {
57 #ifdef TEST_MODE
58         reg_val = 0x1;
59 #else
60         reg_val = snd_readl(codec->codec_base_addr + reg);
61 #endif
62     }
63     return reg_val;
64 }
65 
sunxi_codec_write(struct snd_codec * codec,unsigned int reg,unsigned int val)66 unsigned int sunxi_codec_write(struct snd_codec *codec, unsigned int reg, unsigned int val)
67 {
68     /* struct sunxi_codec_info *sunxi_codec = codec->private_data; */
69 
70     if (reg >= SUNXI_PR_CFG) {
71         reg = reg - SUNXI_PR_CFG;
72         write_prcm_wvalue(reg, val, codec->codec_base_addr + SUNXI_PR_CFG);
73     } else {
74 #ifndef TEST_MODE
75         snd_writel(val, codec->codec_base_addr + reg);
76 #endif
77     }
78     return 0;
79 }
80 
read_prcm_wvalue(u32 addr,void * ADDA_PR_CFG_REG)81 u32 read_prcm_wvalue(u32 addr, void *ADDA_PR_CFG_REG)
82 {
83         u32 reg = 0;
84 
85 #ifndef TEST_MODE
86         reg = snd_readl(ADDA_PR_CFG_REG);
87         reg |= (0x1 << 28);
88         snd_writel(reg, ADDA_PR_CFG_REG);
89 
90         reg = snd_readl(ADDA_PR_CFG_REG);
91         reg &= ~(0x1 << 24);
92         snd_writel(reg, ADDA_PR_CFG_REG);
93 
94         reg = snd_readl(ADDA_PR_CFG_REG);
95         reg &= ~(ADDR_WIDTH << 16);
96         reg |= (addr << 16);
97         snd_writel(reg, ADDA_PR_CFG_REG);
98 
99         reg = snd_readl(ADDA_PR_CFG_REG);
100         reg &= (0xff << 0);
101 #endif
102 
103         return reg;
104 }
105 
write_prcm_wvalue(u32 addr,u32 val,void * ADDA_PR_CFG_REG)106 void write_prcm_wvalue(u32 addr, u32 val, void *ADDA_PR_CFG_REG)
107 {
108         u32 reg;
109 
110 #ifndef TEST_MODE
111         reg = snd_readl(ADDA_PR_CFG_REG);
112         reg |= (0x1 << 28);
113         snd_writel(reg, ADDA_PR_CFG_REG);
114 
115         reg = snd_readl(ADDA_PR_CFG_REG);
116         reg &= ~(ADDR_WIDTH << 16);
117         reg |= (addr << 16);
118         snd_writel(reg, ADDA_PR_CFG_REG);
119 
120         reg = snd_readl(ADDA_PR_CFG_REG);
121         reg &= ~(0xff << 8);
122         reg |= (val << 8);
123         snd_writel(reg, ADDA_PR_CFG_REG);
124 
125         reg = snd_readl(ADDA_PR_CFG_REG);
126         reg |= (0x1 << 24);
127         snd_writel(reg, ADDA_PR_CFG_REG);
128 
129         reg = snd_readl(ADDA_PR_CFG_REG);
130         reg &= ~(0x1 << 24);
131         snd_writel(reg, ADDA_PR_CFG_REG);
132 #endif
133 }
134 
135 #include <console.h>
sunxi_audiocodec_reg_dump(void)136 __attribute__((weak)) void sunxi_audiocodec_reg_dump(void)
137 {
138 
139 }
140 
cmd_audiocodec_dump(int argc,char * argv[])141 int cmd_audiocodec_dump(int argc, char *argv[])
142 {
143     /*TODO, add read,write function */
144     sunxi_audiocodec_reg_dump();
145 }
146 FINSH_FUNCTION_EXPORT_CMD(cmd_audiocodec_dump, audiocodec, audiocodec dump reg);
147