1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * aw883xx.c aw883xx codec module
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2020 AWINIC Technology CO., LTD
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Bruce zhao <zhaolei@awinic.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify it
10*4882a593Smuzhiyun * under the terms of the GNU General Public License as published by the
11*4882a593Smuzhiyun * Free Software Foundation; either version 2 of the License, or (at your
12*4882a593Smuzhiyun * option) any later version.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/i2c.h>
17*4882a593Smuzhiyun #include <sound/core.h>
18*4882a593Smuzhiyun #include <sound/pcm.h>
19*4882a593Smuzhiyun #include <sound/pcm_params.h>
20*4882a593Smuzhiyun #include <sound/soc.h>
21*4882a593Smuzhiyun #include <linux/of_gpio.h>
22*4882a593Smuzhiyun #include <linux/delay.h>
23*4882a593Smuzhiyun #include <linux/device.h>
24*4882a593Smuzhiyun #include <linux/firmware.h>
25*4882a593Smuzhiyun #include <linux/i2c.h>
26*4882a593Smuzhiyun #include <linux/debugfs.h>
27*4882a593Smuzhiyun #include <linux/version.h>
28*4882a593Smuzhiyun #include <linux/input.h>
29*4882a593Smuzhiyun #include <linux/timer.h>
30*4882a593Smuzhiyun #include <linux/workqueue.h>
31*4882a593Smuzhiyun #include <linux/hrtimer.h>
32*4882a593Smuzhiyun #include <linux/syscalls.h>
33*4882a593Smuzhiyun #include <linux/vmalloc.h>
34*4882a593Smuzhiyun #include <sound/tlv.h>
35*4882a593Smuzhiyun #include <linux/uaccess.h>
36*4882a593Smuzhiyun #include "aw_pid_2049_reg.h"
37*4882a593Smuzhiyun #include "aw883xx.h"
38*4882a593Smuzhiyun #include "aw_bin_parse.h"
39*4882a593Smuzhiyun #include "aw_device.h"
40*4882a593Smuzhiyun #include "aw_log.h"
41*4882a593Smuzhiyun #include "aw_spin.h"
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /******************************************************
44*4882a593Smuzhiyun *
45*4882a593Smuzhiyun * Marco
46*4882a593Smuzhiyun *
47*4882a593Smuzhiyun ******************************************************/
48*4882a593Smuzhiyun #define AW883XX_I2C_NAME "aw883xx_smartpa"
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #define AW883XX_DRIVER_VERSION "v1.2.0"
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun #define AW883XX_RATES (SNDRV_PCM_RATE_8000_48000 | \
53*4882a593Smuzhiyun SNDRV_PCM_RATE_96000)
54*4882a593Smuzhiyun #define AW883XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
55*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE | \
56*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE)
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #define AW883XX_ACF_FILE "aw883xx_acf.bin"
60*4882a593Smuzhiyun #define AW_REQUEST_FW_RETRIES 5 /* 5 times */
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun static unsigned int g_aw883xx_dev_cnt;
63*4882a593Smuzhiyun static DEFINE_MUTEX(g_aw883xx_lock);
64*4882a593Smuzhiyun static struct aw_container *g_awinic_cfg;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun static const char *const aw883xx_switch[] = {"Disable", "Enable"};
67*4882a593Smuzhiyun
aw883xx_platform_init(struct aw883xx * aw883xx)68*4882a593Smuzhiyun static int aw883xx_platform_init(struct aw883xx *aw883xx)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun #ifdef AW_QCOM_PLATFORM
71*4882a593Smuzhiyun aw883xx->aw_pa->platform = AW_QCOM;
72*4882a593Smuzhiyun return 0;
73*4882a593Smuzhiyun #elif defined AW_MTK_PLATFORM
74*4882a593Smuzhiyun aw883xx->aw_pa->platform = AW_MTK;
75*4882a593Smuzhiyun return 0;
76*4882a593Smuzhiyun #elif defined AW_SPRD_PLATFORM
77*4882a593Smuzhiyun aw883xx->aw_pa->platform = AW_SPRD;
78*4882a593Smuzhiyun return 0;
79*4882a593Smuzhiyun #else
80*4882a593Smuzhiyun return -EINVAL;
81*4882a593Smuzhiyun #endif
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
aw883xx_get_version(char * buf,int size)84*4882a593Smuzhiyun int aw883xx_get_version(char *buf, int size)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun if (size > strlen(AW883XX_DRIVER_VERSION)) {
87*4882a593Smuzhiyun memcpy(buf, AW883XX_DRIVER_VERSION, strlen(AW883XX_DRIVER_VERSION));
88*4882a593Smuzhiyun return strlen(AW883XX_DRIVER_VERSION);
89*4882a593Smuzhiyun } else {
90*4882a593Smuzhiyun return -ENOMEM;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /******************************************************
95*4882a593Smuzhiyun *
96*4882a593Smuzhiyun * aw883xx append suffix sound channel information
97*4882a593Smuzhiyun *
98*4882a593Smuzhiyun ******************************************************/
aw883xx_devm_kstrdup(struct device * dev,char * buf)99*4882a593Smuzhiyun static void *aw883xx_devm_kstrdup(struct device *dev, char *buf)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun char *str = NULL;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun str = devm_kzalloc(dev, strlen(buf) + 1, GFP_KERNEL);
104*4882a593Smuzhiyun if (!str) {
105*4882a593Smuzhiyun aw_pr_err("devm_kzalloc %s failed", buf);
106*4882a593Smuzhiyun return str;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun memcpy(str, buf, strlen(buf));
109*4882a593Smuzhiyun return str;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
aw883xx_append_i2c_suffix(const char * format,const char ** change_name,struct aw883xx * aw883xx)112*4882a593Smuzhiyun static int aw883xx_append_i2c_suffix(const char *format,
113*4882a593Smuzhiyun const char **change_name, struct aw883xx *aw883xx)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun char buf[64] = { 0 };
116*4882a593Smuzhiyun int i2cbus = aw883xx->i2c->adapter->nr;
117*4882a593Smuzhiyun int addr = aw883xx->i2c->addr;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun snprintf(buf, sizeof(buf), format, *change_name, i2cbus, addr);
120*4882a593Smuzhiyun *change_name = aw883xx_devm_kstrdup(aw883xx->dev, buf);
121*4882a593Smuzhiyun if (!(*change_name))
122*4882a593Smuzhiyun return -ENOMEM;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "change name :%s", *change_name);
125*4882a593Smuzhiyun return 0;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun /******************************************************
130*4882a593Smuzhiyun *
131*4882a593Smuzhiyun * aw883xx distinguish between codecs and components by version
132*4882a593Smuzhiyun *
133*4882a593Smuzhiyun ******************************************************/
134*4882a593Smuzhiyun #ifdef AW_KERNEL_VER_OVER_4_19_1
135*4882a593Smuzhiyun static struct aw_componet_codec_ops aw_componet_codec_ops = {
136*4882a593Smuzhiyun .kcontrol_codec = snd_soc_kcontrol_component,
137*4882a593Smuzhiyun .codec_get_drvdata = snd_soc_component_get_drvdata,
138*4882a593Smuzhiyun .add_codec_controls = snd_soc_add_component_controls,
139*4882a593Smuzhiyun .unregister_codec = snd_soc_unregister_component,
140*4882a593Smuzhiyun .register_codec = snd_soc_register_component,
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun #else
143*4882a593Smuzhiyun static struct aw_componet_codec_ops aw_componet_codec_ops = {
144*4882a593Smuzhiyun .kcontrol_codec = snd_soc_kcontrol_codec,
145*4882a593Smuzhiyun .codec_get_drvdata = snd_soc_codec_get_drvdata,
146*4882a593Smuzhiyun .add_codec_controls = snd_soc_add_codec_controls,
147*4882a593Smuzhiyun .unregister_codec = snd_soc_unregister_codec,
148*4882a593Smuzhiyun .register_codec = snd_soc_register_codec,
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun #endif
151*4882a593Smuzhiyun
aw883xx_get_codec(struct snd_soc_dai * dai)152*4882a593Smuzhiyun static aw_snd_soc_codec_t *aw883xx_get_codec(struct snd_soc_dai *dai)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun #ifdef AW_KERNEL_VER_OVER_4_19_1
155*4882a593Smuzhiyun return dai->component;
156*4882a593Smuzhiyun #else
157*4882a593Smuzhiyun return dai->codec;
158*4882a593Smuzhiyun #endif
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /******************************************************
162*4882a593Smuzhiyun *
163*4882a593Smuzhiyun * aw883xx reg write/read
164*4882a593Smuzhiyun *
165*4882a593Smuzhiyun ******************************************************/
166*4882a593Smuzhiyun
aw883xx_i2c_writes(struct aw883xx * aw883xx,uint8_t reg_addr,uint8_t * buf,uint16_t len)167*4882a593Smuzhiyun int aw883xx_i2c_writes(struct aw883xx *aw883xx,
168*4882a593Smuzhiyun uint8_t reg_addr, uint8_t *buf, uint16_t len)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun int ret = -1;
171*4882a593Smuzhiyun uint8_t *data = NULL;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun data = kmalloc(len + 1, GFP_KERNEL);
174*4882a593Smuzhiyun if (data == NULL) {
175*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "can not allocate memory");
176*4882a593Smuzhiyun return -ENOMEM;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun data[0] = reg_addr;
180*4882a593Smuzhiyun memcpy(&data[1], buf, len);
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun ret = i2c_master_send(aw883xx->i2c, data, len + 1);
183*4882a593Smuzhiyun if (ret < 0) {
184*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c master send error");
185*4882a593Smuzhiyun goto i2c_master_error;
186*4882a593Smuzhiyun } else if (ret != (len + 1)) {
187*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c master send error(size error)");
188*4882a593Smuzhiyun ret = -ENXIO;
189*4882a593Smuzhiyun goto i2c_master_error;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun kfree(data);
193*4882a593Smuzhiyun data = NULL;
194*4882a593Smuzhiyun return 0;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun i2c_master_error:
197*4882a593Smuzhiyun kfree(data);
198*4882a593Smuzhiyun data = NULL;
199*4882a593Smuzhiyun return ret;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
aw883xx_i2c_reads(struct aw883xx * aw883xx,uint8_t reg_addr,uint8_t * data_buf,uint16_t data_len)202*4882a593Smuzhiyun static int aw883xx_i2c_reads(struct aw883xx *aw883xx,
203*4882a593Smuzhiyun uint8_t reg_addr, uint8_t *data_buf,
204*4882a593Smuzhiyun uint16_t data_len)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun int ret;
207*4882a593Smuzhiyun struct i2c_msg msg[] = {
208*4882a593Smuzhiyun [0] = {
209*4882a593Smuzhiyun .addr = aw883xx->i2c->addr,
210*4882a593Smuzhiyun .flags = 0,
211*4882a593Smuzhiyun .len = sizeof(uint8_t),
212*4882a593Smuzhiyun .buf = ®_addr,
213*4882a593Smuzhiyun },
214*4882a593Smuzhiyun [1] = {
215*4882a593Smuzhiyun .addr = aw883xx->i2c->addr,
216*4882a593Smuzhiyun .flags = I2C_M_RD,
217*4882a593Smuzhiyun .len = data_len,
218*4882a593Smuzhiyun .buf = data_buf,
219*4882a593Smuzhiyun },
220*4882a593Smuzhiyun };
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun ret = i2c_transfer(aw883xx->i2c->adapter, msg, ARRAY_SIZE(msg));
223*4882a593Smuzhiyun if (ret < 0) {
224*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c_transfer failed");
225*4882a593Smuzhiyun return ret;
226*4882a593Smuzhiyun } else if (ret != AW883XX_READ_MSG_NUM) {
227*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "transfer failed(size error)");
228*4882a593Smuzhiyun return -ENXIO;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun return 0;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
aw883xx_i2c_write(struct aw883xx * aw883xx,uint8_t reg_addr,uint16_t reg_data)234*4882a593Smuzhiyun int aw883xx_i2c_write(struct aw883xx *aw883xx,
235*4882a593Smuzhiyun uint8_t reg_addr, uint16_t reg_data)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun int ret = -1;
238*4882a593Smuzhiyun uint8_t cnt = 0;
239*4882a593Smuzhiyun uint8_t buf[2] = {0};
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun buf[0] = (reg_data & 0xff00) >> 8;
242*4882a593Smuzhiyun buf[1] = (reg_data & 0x00ff) >> 0;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun while (cnt < AW_I2C_RETRIES) {
245*4882a593Smuzhiyun ret = aw883xx_i2c_writes(aw883xx, reg_addr, buf, 2);
246*4882a593Smuzhiyun if (ret < 0)
247*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c_write cnt=%d error=%d",
248*4882a593Smuzhiyun cnt, ret);
249*4882a593Smuzhiyun else
250*4882a593Smuzhiyun break;
251*4882a593Smuzhiyun cnt++;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun if (aw883xx->i2c_log_en)
255*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "write: reg = 0x%02x, val = 0x%04x",
256*4882a593Smuzhiyun reg_addr, reg_data);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun return ret;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
aw883xx_i2c_read(struct aw883xx * aw883xx,uint8_t reg_addr,uint16_t * reg_data)261*4882a593Smuzhiyun int aw883xx_i2c_read(struct aw883xx *aw883xx,
262*4882a593Smuzhiyun uint8_t reg_addr, uint16_t *reg_data)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun int ret = -1;
265*4882a593Smuzhiyun uint8_t cnt = 0;
266*4882a593Smuzhiyun uint8_t buf[2] = {0};
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun while (cnt < AW_I2C_RETRIES) {
269*4882a593Smuzhiyun ret = aw883xx_i2c_reads(aw883xx, reg_addr, buf, 2);
270*4882a593Smuzhiyun if (ret < 0) {
271*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c_read cnt=%d error=%d",
272*4882a593Smuzhiyun cnt, ret);
273*4882a593Smuzhiyun } else {
274*4882a593Smuzhiyun *reg_data = (buf[0] << 8) | (buf[1] << 0);
275*4882a593Smuzhiyun break;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun cnt++;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun if (aw883xx->i2c_log_en)
281*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "read: reg = 0x%02x, val = 0x%04x",
282*4882a593Smuzhiyun reg_addr, *reg_data);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun return ret;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
aw883xx_i2c_write_bits(struct aw883xx * aw883xx,uint8_t reg_addr,uint16_t mask,uint16_t reg_data)287*4882a593Smuzhiyun static int aw883xx_i2c_write_bits(struct aw883xx *aw883xx,
288*4882a593Smuzhiyun uint8_t reg_addr, uint16_t mask,
289*4882a593Smuzhiyun uint16_t reg_data)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun int ret = -1;
292*4882a593Smuzhiyun uint16_t reg_val = 0;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun ret = aw883xx_i2c_read(aw883xx, reg_addr, ®_val);
295*4882a593Smuzhiyun if (ret < 0) {
296*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c read error, ret=%d", ret);
297*4882a593Smuzhiyun return ret;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun reg_val &= mask;
300*4882a593Smuzhiyun reg_val |= reg_data;
301*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, reg_addr, reg_val);
302*4882a593Smuzhiyun if (ret < 0) {
303*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c read error, ret=%d", ret);
304*4882a593Smuzhiyun return ret;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun return 0;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
aw883xx_reg_write(struct aw883xx * aw883xx,uint8_t reg_addr,uint16_t reg_data)310*4882a593Smuzhiyun int aw883xx_reg_write(struct aw883xx *aw883xx,
311*4882a593Smuzhiyun uint8_t reg_addr, uint16_t reg_data)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun int ret = -1;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
316*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, reg_addr, reg_data);
317*4882a593Smuzhiyun if (ret < 0)
318*4882a593Smuzhiyun aw_dev_err(aw883xx->dev,
319*4882a593Smuzhiyun "write fail, reg = 0x%02x, val = 0x%04x, ret=%d",
320*4882a593Smuzhiyun reg_addr, reg_data, ret);
321*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun return ret;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
aw883xx_reg_read(struct aw883xx * aw883xx,uint8_t reg_addr,uint16_t * reg_data)326*4882a593Smuzhiyun int aw883xx_reg_read(struct aw883xx *aw883xx,
327*4882a593Smuzhiyun uint8_t reg_addr, uint16_t *reg_data)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun int ret = -1;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
332*4882a593Smuzhiyun ret = aw883xx_i2c_read(aw883xx, reg_addr, reg_data);
333*4882a593Smuzhiyun if (ret < 0)
334*4882a593Smuzhiyun aw_dev_err(aw883xx->dev,
335*4882a593Smuzhiyun "read fail: reg = 0x%02x, val = 0x%04x, ret=%d",
336*4882a593Smuzhiyun reg_addr, *reg_data, ret);
337*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun return ret;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
aw883xx_reg_write_bits(struct aw883xx * aw883xx,uint8_t reg_addr,uint16_t mask,uint16_t reg_data)342*4882a593Smuzhiyun int aw883xx_reg_write_bits(struct aw883xx *aw883xx,
343*4882a593Smuzhiyun uint8_t reg_addr, uint16_t mask, uint16_t reg_data)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun int ret = -1;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
348*4882a593Smuzhiyun ret = aw883xx_i2c_write_bits(aw883xx, reg_addr, mask, reg_data);
349*4882a593Smuzhiyun if (ret < 0)
350*4882a593Smuzhiyun aw_dev_err(aw883xx->dev,"fail, ret=%d", ret);
351*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun return ret;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
aw883xx_dsp_write_16bit(struct aw883xx * aw883xx,uint16_t dsp_addr,uint32_t dsp_data)356*4882a593Smuzhiyun static int aw883xx_dsp_write_16bit(struct aw883xx *aw883xx,
357*4882a593Smuzhiyun uint16_t dsp_addr, uint32_t dsp_data)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun int ret;
360*4882a593Smuzhiyun struct aw_dsp_mem_desc *desc = &aw883xx->aw_pa->dsp_mem_desc;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, desc->dsp_madd_reg, dsp_addr);
363*4882a593Smuzhiyun if (ret < 0) {
364*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c write error, ret=%d", ret);
365*4882a593Smuzhiyun return ret;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, desc->dsp_mdat_reg, (uint16_t)dsp_data);
369*4882a593Smuzhiyun if (ret < 0) {
370*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c write error, ret=%d", ret);
371*4882a593Smuzhiyun return ret;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun return 0;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
aw883xx_dsp_write_32bit(struct aw883xx * aw883xx,uint16_t dsp_addr,uint32_t dsp_data)377*4882a593Smuzhiyun static int aw883xx_dsp_write_32bit(struct aw883xx *aw883xx,
378*4882a593Smuzhiyun uint16_t dsp_addr, uint32_t dsp_data)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun int ret;
381*4882a593Smuzhiyun uint16_t temp_data = 0;
382*4882a593Smuzhiyun struct aw_dsp_mem_desc *desc = &aw883xx->aw_pa->dsp_mem_desc;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, desc->dsp_madd_reg, dsp_addr);
385*4882a593Smuzhiyun if (ret < 0) {
386*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c write error, ret=%d", ret);
387*4882a593Smuzhiyun return ret;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun temp_data = dsp_data & AW883XX_DSP_16_DATA_MASK;
391*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, desc->dsp_mdat_reg, temp_data);
392*4882a593Smuzhiyun if (ret < 0) {
393*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c write error, ret=%d", ret);
394*4882a593Smuzhiyun return ret;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun temp_data = dsp_data >> 16;
398*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, desc->dsp_mdat_reg, temp_data);
399*4882a593Smuzhiyun if (ret < 0) {
400*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c write error, ret=%d", ret);
401*4882a593Smuzhiyun return ret;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun return 0;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /******************************************************
408*4882a593Smuzhiyun * aw883xx clear dsp chip select state
409*4882a593Smuzhiyun ******************************************************/
aw883xx_clear_dsp_sel_st(struct aw883xx * aw883xx)410*4882a593Smuzhiyun static void aw883xx_clear_dsp_sel_st(struct aw883xx *aw883xx)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun uint16_t reg_value;
413*4882a593Smuzhiyun uint8_t reg = aw883xx->aw_pa->soft_rst.reg;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun aw883xx_i2c_read(aw883xx, reg, ®_value);
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
aw883xx_dsp_write(struct aw883xx * aw883xx,uint16_t dsp_addr,uint32_t dsp_data,uint8_t data_type)418*4882a593Smuzhiyun int aw883xx_dsp_write(struct aw883xx *aw883xx,
419*4882a593Smuzhiyun uint16_t dsp_addr, uint32_t dsp_data, uint8_t data_type)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun int ret = -1;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
424*4882a593Smuzhiyun if (data_type == AW_DSP_16_DATA) {
425*4882a593Smuzhiyun ret = aw883xx_dsp_write_16bit(aw883xx, dsp_addr, dsp_data);
426*4882a593Smuzhiyun if (ret < 0) {
427*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "write dsp_addr[0x%04x] 16 bit dsp_data[%04x] failed",
428*4882a593Smuzhiyun (uint32_t)dsp_addr, dsp_data);
429*4882a593Smuzhiyun goto exit;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun } else if (data_type == AW_DSP_32_DATA) {
432*4882a593Smuzhiyun ret = aw883xx_dsp_write_32bit(aw883xx, dsp_addr, dsp_data);
433*4882a593Smuzhiyun if (ret < 0) {
434*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "write dsp_addr[0x%04x] 32 bit dsp_data[%08x] failed",
435*4882a593Smuzhiyun (uint32_t)dsp_addr, dsp_data);
436*4882a593Smuzhiyun goto exit;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun } else {
439*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "data type[%d] unsupported", data_type);
440*4882a593Smuzhiyun ret = -EINVAL;
441*4882a593Smuzhiyun goto exit;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun exit:
445*4882a593Smuzhiyun aw883xx_clear_dsp_sel_st(aw883xx);
446*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
447*4882a593Smuzhiyun return ret;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun
aw883xx_dsp_read_16bit(struct aw883xx * aw883xx,uint16_t dsp_addr,uint32_t * dsp_data)451*4882a593Smuzhiyun static int aw883xx_dsp_read_16bit(struct aw883xx *aw883xx,
452*4882a593Smuzhiyun uint16_t dsp_addr, uint32_t *dsp_data)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun int ret;
455*4882a593Smuzhiyun uint16_t temp_data = 0;
456*4882a593Smuzhiyun struct aw_dsp_mem_desc *desc = &aw883xx->aw_pa->dsp_mem_desc;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, desc->dsp_madd_reg, dsp_addr);
459*4882a593Smuzhiyun if (ret < 0) {
460*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c write error, ret=%d", ret);
461*4882a593Smuzhiyun return ret;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun ret = aw883xx_i2c_read(aw883xx, desc->dsp_mdat_reg, &temp_data);
465*4882a593Smuzhiyun if (ret < 0) {
466*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c write error, ret=%d", ret);
467*4882a593Smuzhiyun return ret;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun *dsp_data = temp_data;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun return 0;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
aw883xx_dsp_read_32bit(struct aw883xx * aw883xx,uint16_t dsp_addr,uint32_t * dsp_data)475*4882a593Smuzhiyun static int aw883xx_dsp_read_32bit(struct aw883xx *aw883xx,
476*4882a593Smuzhiyun uint16_t dsp_addr, uint32_t *dsp_data)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun int ret;
479*4882a593Smuzhiyun uint16_t temp_data = 0;
480*4882a593Smuzhiyun struct aw_dsp_mem_desc *desc = &aw883xx->aw_pa->dsp_mem_desc;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun /*write dsp addr*/
483*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, desc->dsp_madd_reg, dsp_addr);
484*4882a593Smuzhiyun if (ret < 0) {
485*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c write error, ret=%d", ret);
486*4882a593Smuzhiyun return ret;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun /*get Low 16 bit data*/
490*4882a593Smuzhiyun ret = aw883xx_i2c_read(aw883xx, desc->dsp_mdat_reg, &temp_data);
491*4882a593Smuzhiyun if (ret < 0) {
492*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c read error, ret=%d", ret);
493*4882a593Smuzhiyun return ret;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun *dsp_data = temp_data;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun /*get high 16 bit data*/
499*4882a593Smuzhiyun ret = aw883xx_i2c_read(aw883xx, desc->dsp_mdat_reg, &temp_data);
500*4882a593Smuzhiyun if (ret < 0) {
501*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "i2c read error, ret=%d", ret);
502*4882a593Smuzhiyun return ret;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun *dsp_data |= (temp_data << 16);
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun return 0;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
aw883xx_dsp_read(struct aw883xx * aw883xx,uint16_t dsp_addr,uint32_t * dsp_data,uint8_t data_type)509*4882a593Smuzhiyun int aw883xx_dsp_read(struct aw883xx *aw883xx,
510*4882a593Smuzhiyun uint16_t dsp_addr, uint32_t *dsp_data, uint8_t data_type)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun int ret = -1;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
515*4882a593Smuzhiyun if (data_type == AW_DSP_16_DATA) {
516*4882a593Smuzhiyun ret = aw883xx_dsp_read_16bit(aw883xx, dsp_addr, dsp_data);
517*4882a593Smuzhiyun if (ret < 0) {
518*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "read dsp_addr[0x%04x] 16 bit dsp_data[%04x] failed",
519*4882a593Smuzhiyun (uint32_t)dsp_addr, *dsp_data);
520*4882a593Smuzhiyun goto exit;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun } else if (data_type == AW_DSP_32_DATA) {
523*4882a593Smuzhiyun ret = aw883xx_dsp_read_32bit(aw883xx, dsp_addr, dsp_data);
524*4882a593Smuzhiyun if (ret < 0) {
525*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "read dsp_addr[0x%04x] 32 bit dsp_data[%08x] failed",
526*4882a593Smuzhiyun (uint32_t)dsp_addr, *dsp_data);
527*4882a593Smuzhiyun goto exit;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun } else {
530*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "data type[%d] unsupported", data_type);
531*4882a593Smuzhiyun ret = -EINVAL;
532*4882a593Smuzhiyun goto exit;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun exit:
536*4882a593Smuzhiyun aw883xx_clear_dsp_sel_st(aw883xx);
537*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
538*4882a593Smuzhiyun return ret;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun /******************************************************
542*4882a593Smuzhiyun * aw883xx get dev num
543*4882a593Smuzhiyun ******************************************************/
aw883xx_get_dev_num(void)544*4882a593Smuzhiyun int aw883xx_get_dev_num(void)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun return g_aw883xx_dev_cnt;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun /******************************************************
550*4882a593Smuzhiyun * aw883xx interrupt
551*4882a593Smuzhiyun ******************************************************/
aw883xx_interrupt_work(struct work_struct * work)552*4882a593Smuzhiyun static void aw883xx_interrupt_work(struct work_struct *work)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun struct aw883xx *aw883xx = container_of(work,
555*4882a593Smuzhiyun struct aw883xx, interrupt_work.work);
556*4882a593Smuzhiyun int16_t reg_value;
557*4882a593Smuzhiyun int ret;
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun /*read reg value*/
562*4882a593Smuzhiyun ret = aw_dev_get_int_status(aw883xx->aw_pa, ®_value);
563*4882a593Smuzhiyun if (ret < 0)
564*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "get init_reg value failed");
565*4882a593Smuzhiyun else
566*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "int value 0x%x", reg_value);
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun /*clear init reg*/
569*4882a593Smuzhiyun aw_dev_clear_int_status(aw883xx->aw_pa);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun /*unmask interrupt*/
572*4882a593Smuzhiyun aw_dev_set_intmask(aw883xx->aw_pa, true);
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun /******************************************************
576*4882a593Smuzhiyun *
577*4882a593Smuzhiyun * Digital Audio Interface
578*4882a593Smuzhiyun *
579*4882a593Smuzhiyun ******************************************************/
aw883xx_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)580*4882a593Smuzhiyun static int aw883xx_startup(struct snd_pcm_substream *substream,
581*4882a593Smuzhiyun struct snd_soc_dai *dai)
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun aw_snd_soc_codec_t *codec = aw883xx_get_codec(dai);
584*4882a593Smuzhiyun struct aw883xx *aw883xx =
585*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
588*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "playback enter");
589*4882a593Smuzhiyun /*load cali re*/
590*4882a593Smuzhiyun if (AW_ERRO_CALI_RE_VALUE == aw883xx->aw_pa->cali_desc.cali_re)
591*4882a593Smuzhiyun aw_cali_get_cali_re(&aw883xx->aw_pa->cali_desc);
592*4882a593Smuzhiyun } else {
593*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "capture enter");
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun return 0;
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun
aw883xx_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)599*4882a593Smuzhiyun static int aw883xx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun aw_snd_soc_codec_t *codec = aw883xx_get_codec(dai);
602*4882a593Smuzhiyun /*struct aw883xx *aw883xx =
603*4882a593Smuzhiyun aw_componet_codec_ops.aw_snd_soc_codec_get_drvdata(codec); */
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun aw_dev_info(codec->dev, "fmt=0x%x", fmt);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun /* supported mode: regular I2S, slave, or PDM */
608*4882a593Smuzhiyun switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
609*4882a593Smuzhiyun case SND_SOC_DAIFMT_I2S:
610*4882a593Smuzhiyun if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) !=
611*4882a593Smuzhiyun SND_SOC_DAIFMT_CBS_CFS) {
612*4882a593Smuzhiyun aw_dev_err(codec->dev, "invalid codec master mode");
613*4882a593Smuzhiyun return -EINVAL;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun break;
616*4882a593Smuzhiyun default:
617*4882a593Smuzhiyun aw_dev_err(codec->dev, "unsupported DAI format %d",
618*4882a593Smuzhiyun fmt & SND_SOC_DAIFMT_FORMAT_MASK);
619*4882a593Smuzhiyun return -EINVAL;
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun return 0;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun
aw883xx_set_dai_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)625*4882a593Smuzhiyun static int aw883xx_set_dai_sysclk(struct snd_soc_dai *dai,
626*4882a593Smuzhiyun int clk_id, unsigned int freq, int dir)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun aw_snd_soc_codec_t *codec = aw883xx_get_codec(dai);
629*4882a593Smuzhiyun struct aw883xx *aw883xx =
630*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "freq=%d", freq);
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun aw883xx->sysclk = freq;
635*4882a593Smuzhiyun return 0;
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun
aw883xx_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)638*4882a593Smuzhiyun static int aw883xx_hw_params(struct snd_pcm_substream *substream,
639*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
640*4882a593Smuzhiyun struct snd_soc_dai *dai)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun aw_snd_soc_codec_t *codec = aw883xx_get_codec(dai);
643*4882a593Smuzhiyun struct aw883xx *aw883xx =
644*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun /* get CAPTURE rate param bit width*/
647*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
648*4882a593Smuzhiyun aw_dev_info(aw883xx->dev,
649*4882a593Smuzhiyun "STREAM_CAPTURE requested rate: %d, width = %d",
650*4882a593Smuzhiyun params_rate(params), params_width(params));
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun /* get PLAYBACK rate param bit width*/
654*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
655*4882a593Smuzhiyun aw_dev_info(aw883xx->dev,
656*4882a593Smuzhiyun "STREAM_PLAYBACK requested rate: %d, width = %d",
657*4882a593Smuzhiyun params_rate(params), params_width(params));
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun return 0;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
aw883xx_start_pa(struct aw883xx * aw883xx)663*4882a593Smuzhiyun static void aw883xx_start_pa(struct aw883xx *aw883xx)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun int ret, i;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun if (aw883xx->allow_pw == false) {
670*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "dev can not allow power");
671*4882a593Smuzhiyun return;
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun if (aw883xx->pstream == AW883XX_STREAM_CLOSE) {
675*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "pstream is close");
676*4882a593Smuzhiyun return;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun for (i = 0; i < AW_START_RETRIES; i++) {
680*4882a593Smuzhiyun ret = aw_device_start(aw883xx->aw_pa);
681*4882a593Smuzhiyun if (ret) {
682*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "start failed");
683*4882a593Smuzhiyun ret = aw_dev_fw_update(aw883xx->aw_pa, AW_DSP_FW_UPDATE_ON, true);
684*4882a593Smuzhiyun if (ret < 0) {
685*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "fw update failed");
686*4882a593Smuzhiyun continue;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun } else {
689*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "start success");
690*4882a593Smuzhiyun break;
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
aw883xx_startup_work(struct work_struct * work)695*4882a593Smuzhiyun static void aw883xx_startup_work(struct work_struct *work)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun struct aw883xx *aw883xx =
698*4882a593Smuzhiyun container_of(work, struct aw883xx, start_work.work);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun mutex_lock(&aw883xx->lock);
701*4882a593Smuzhiyun aw883xx_start_pa(aw883xx);
702*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
aw883xx_start(struct aw883xx * aw883xx,bool sync_start)705*4882a593Smuzhiyun static void aw883xx_start(struct aw883xx *aw883xx, bool sync_start)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun int ret;
708*4882a593Smuzhiyun int i;
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun if (aw883xx->aw_pa->fw_status == AW_DEV_FW_OK) {
711*4882a593Smuzhiyun if (aw883xx->allow_pw == false) {
712*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "dev can not allow power");
713*4882a593Smuzhiyun return;
714*4882a593Smuzhiyun }
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun if (aw883xx->aw_pa->status == AW_DEV_PW_ON)
717*4882a593Smuzhiyun return;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun for (i = 0; i < AW_START_RETRIES; i++) {
720*4882a593Smuzhiyun ret = aw_dev_fw_update(aw883xx->aw_pa, AW_DSP_FW_UPDATE_OFF,
721*4882a593Smuzhiyun aw883xx->phase_sync);
722*4882a593Smuzhiyun if (ret < 0) {
723*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "fw update failed");
724*4882a593Smuzhiyun continue;
725*4882a593Smuzhiyun } else {
726*4882a593Smuzhiyun /*firmware update success*/
727*4882a593Smuzhiyun if (sync_start == AW_SYNC_START)
728*4882a593Smuzhiyun aw883xx_start_pa(aw883xx);
729*4882a593Smuzhiyun else
730*4882a593Smuzhiyun queue_delayed_work(aw883xx->work_queue,
731*4882a593Smuzhiyun &aw883xx->start_work,
732*4882a593Smuzhiyun AW883XX_START_WORK_DELAY_MS);
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun return;
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun }
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun
aw883xx_mute(struct snd_soc_dai * dai,int mute,int stream)740*4882a593Smuzhiyun static int aw883xx_mute(struct snd_soc_dai *dai, int mute, int stream)
741*4882a593Smuzhiyun {
742*4882a593Smuzhiyun aw_snd_soc_codec_t *codec = aw883xx_get_codec(dai);
743*4882a593Smuzhiyun struct aw883xx *aw883xx =
744*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "mute state=%d", mute);
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun if (stream != SNDRV_PCM_STREAM_PLAYBACK) {
749*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "capture");
750*4882a593Smuzhiyun return 0;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (mute) {
754*4882a593Smuzhiyun aw883xx->pstream = AW883XX_STREAM_CLOSE;
755*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->start_work);
756*4882a593Smuzhiyun mutex_lock(&aw883xx->lock);
757*4882a593Smuzhiyun aw_device_stop(aw883xx->aw_pa);
758*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
759*4882a593Smuzhiyun } else {
760*4882a593Smuzhiyun aw883xx->pstream = AW883XX_STREAM_OPEN;
761*4882a593Smuzhiyun mutex_lock(&aw883xx->lock);
762*4882a593Smuzhiyun aw883xx_start(aw883xx, AW_ASYNC_START);
763*4882a593Smuzhiyun aw_hold_dsp_spin_st(&aw883xx->aw_pa->spin_desc);
764*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun return 0;
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun
aw883xx_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)770*4882a593Smuzhiyun static void aw883xx_shutdown(struct snd_pcm_substream *substream,
771*4882a593Smuzhiyun struct snd_soc_dai *dai)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun aw_snd_soc_codec_t *codec = aw883xx_get_codec(dai);
774*4882a593Smuzhiyun struct aw883xx *aw883xx =
775*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
778*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "stream playback");
779*4882a593Smuzhiyun else
780*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "stream capture");
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun static const struct snd_soc_dai_ops aw883xx_dai_ops = {
784*4882a593Smuzhiyun .startup = aw883xx_startup,
785*4882a593Smuzhiyun .set_fmt = aw883xx_set_fmt,
786*4882a593Smuzhiyun .set_sysclk = aw883xx_set_dai_sysclk,
787*4882a593Smuzhiyun .hw_params = aw883xx_hw_params,
788*4882a593Smuzhiyun .mute_stream = aw883xx_mute,
789*4882a593Smuzhiyun .shutdown = aw883xx_shutdown,
790*4882a593Smuzhiyun };
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun static struct snd_soc_dai_driver aw883xx_dai[] = {
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun .name = "aw883xx-aif",
795*4882a593Smuzhiyun .id = 1,
796*4882a593Smuzhiyun .playback = {
797*4882a593Smuzhiyun .stream_name = "Speaker_Playback",
798*4882a593Smuzhiyun .channels_min = 1,
799*4882a593Smuzhiyun .channels_max = 2,
800*4882a593Smuzhiyun .rates = AW883XX_RATES,
801*4882a593Smuzhiyun .formats = AW883XX_FORMATS,
802*4882a593Smuzhiyun },
803*4882a593Smuzhiyun .capture = {
804*4882a593Smuzhiyun .stream_name = "Speaker_Capture",
805*4882a593Smuzhiyun .channels_min = 1,
806*4882a593Smuzhiyun .channels_max = 2,
807*4882a593Smuzhiyun .rates = AW883XX_RATES,
808*4882a593Smuzhiyun .formats = AW883XX_FORMATS,
809*4882a593Smuzhiyun },
810*4882a593Smuzhiyun .ops = &aw883xx_dai_ops,
811*4882a593Smuzhiyun /*.symmetric_rates = 1,*/
812*4882a593Smuzhiyun },
813*4882a593Smuzhiyun };
814*4882a593Smuzhiyun
aw883xx_dai_drv_append_suffix(struct aw883xx * aw883xx,struct snd_soc_dai_driver * dai_drv,int num_dai)815*4882a593Smuzhiyun static int aw883xx_dai_drv_append_suffix(struct aw883xx *aw883xx,
816*4882a593Smuzhiyun struct snd_soc_dai_driver *dai_drv,
817*4882a593Smuzhiyun int num_dai)
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun int ret;
820*4882a593Smuzhiyun int i;
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun if ((dai_drv != NULL) && (num_dai > 0)) {
823*4882a593Smuzhiyun for (i = 0; i < num_dai; i++) {
824*4882a593Smuzhiyun ret = aw883xx_append_i2c_suffix("%s-%x-%x",
825*4882a593Smuzhiyun &dai_drv->name, aw883xx);
826*4882a593Smuzhiyun if (ret < 0)
827*4882a593Smuzhiyun return ret;
828*4882a593Smuzhiyun ret = aw883xx_append_i2c_suffix("%s_%x_%x",
829*4882a593Smuzhiyun &dai_drv->playback.stream_name, aw883xx);
830*4882a593Smuzhiyun if (ret < 0)
831*4882a593Smuzhiyun return ret;
832*4882a593Smuzhiyun ret = aw883xx_append_i2c_suffix("%s_%x_%x",
833*4882a593Smuzhiyun &dai_drv->capture.stream_name, aw883xx);
834*4882a593Smuzhiyun if (ret < 0)
835*4882a593Smuzhiyun return ret;
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "dai name [%s]", dai_drv[i].name);
838*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "pstream_name [%s]",
839*4882a593Smuzhiyun dai_drv[i].playback.stream_name);
840*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "cstream_name [%s]",
841*4882a593Smuzhiyun dai_drv[i].capture.stream_name);
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun return 0;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun /*****************************************************
849*4882a593Smuzhiyun *
850*4882a593Smuzhiyun * codec driver
851*4882a593Smuzhiyun *
852*4882a593Smuzhiyun *****************************************************/
aw883xx_get_fade_in_time(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)853*4882a593Smuzhiyun static int aw883xx_get_fade_in_time(struct snd_kcontrol *kcontrol,
854*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
855*4882a593Smuzhiyun {
856*4882a593Smuzhiyun unsigned int time;
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun aw_dev_get_fade_time(&time, true);
859*4882a593Smuzhiyun ucontrol->value.integer.value[0] = time;
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun aw_pr_dbg("step time %ld", ucontrol->value.integer.value[0]);
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun return 0;
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
aw883xx_set_fade_in_time(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)867*4882a593Smuzhiyun static int aw883xx_set_fade_in_time(struct snd_kcontrol *kcontrol,
868*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
869*4882a593Smuzhiyun {
870*4882a593Smuzhiyun struct soc_mixer_control *mc =
871*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun if ((ucontrol->value.integer.value[0] > mc->max) ||
874*4882a593Smuzhiyun (ucontrol->value.integer.value[0] < mc->min)) {
875*4882a593Smuzhiyun aw_pr_dbg("set val %ld overflow %d or less than :%d",
876*4882a593Smuzhiyun ucontrol->value.integer.value[0], mc->max, mc->min);
877*4882a593Smuzhiyun return 0;
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun aw_dev_set_fade_time(ucontrol->value.integer.value[0], true);
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun aw_pr_dbg("step time %ld", ucontrol->value.integer.value[0]);
882*4882a593Smuzhiyun return 0;
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun
aw883xx_get_fade_out_time(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)885*4882a593Smuzhiyun static int aw883xx_get_fade_out_time(struct snd_kcontrol *kcontrol,
886*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
887*4882a593Smuzhiyun {
888*4882a593Smuzhiyun unsigned int time;
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun aw_dev_get_fade_time(&time, false);
891*4882a593Smuzhiyun ucontrol->value.integer.value[0] = time;
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun aw_pr_dbg("step time %ld", ucontrol->value.integer.value[0]);
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun return 0;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
aw883xx_set_fade_out_time(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)898*4882a593Smuzhiyun static int aw883xx_set_fade_out_time(struct snd_kcontrol *kcontrol,
899*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun struct soc_mixer_control *mc =
902*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun if ((ucontrol->value.integer.value[0] > mc->max) ||
905*4882a593Smuzhiyun (ucontrol->value.integer.value[0] < mc->min)) {
906*4882a593Smuzhiyun aw_pr_dbg("set val %ld overflow %d or less than :%d",
907*4882a593Smuzhiyun ucontrol->value.integer.value[0], mc->max, mc->min);
908*4882a593Smuzhiyun return 0;
909*4882a593Smuzhiyun }
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun aw_dev_set_fade_time(ucontrol->value.integer.value[0], false);
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun aw_pr_dbg("step time %ld", ucontrol->value.integer.value[0]);
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun return 0;
916*4882a593Smuzhiyun }
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun static struct snd_kcontrol_new aw883xx_controls[] = {
919*4882a593Smuzhiyun SOC_SINGLE_EXT("aw883xx_fadein_us", 0, 0, 1000000, 0,
920*4882a593Smuzhiyun aw883xx_get_fade_in_time, aw883xx_set_fade_in_time),
921*4882a593Smuzhiyun SOC_SINGLE_EXT("aw883xx_fadeout_us", 0, 0, 1000000, 0,
922*4882a593Smuzhiyun aw883xx_get_fade_out_time, aw883xx_set_fade_out_time),
923*4882a593Smuzhiyun };
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun
aw883xx_add_codec_controls(struct aw883xx * aw883xx)926*4882a593Smuzhiyun static void aw883xx_add_codec_controls(struct aw883xx *aw883xx)
927*4882a593Smuzhiyun {
928*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun if (aw883xx->aw_pa->channel == 0) {
931*4882a593Smuzhiyun aw_componet_codec_ops.add_codec_controls(aw883xx->codec,
932*4882a593Smuzhiyun &aw883xx_controls[0], ARRAY_SIZE(aw883xx_controls));
933*4882a593Smuzhiyun aw_add_spin_controls((void *)aw883xx);
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun
aw883xx_profile_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)937*4882a593Smuzhiyun static int aw883xx_profile_info(struct snd_kcontrol *kcontrol,
938*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun int count;
941*4882a593Smuzhiyun char *name = NULL;
942*4882a593Smuzhiyun const char *prof_name = NULL;
943*4882a593Smuzhiyun aw_snd_soc_codec_t *codec =
944*4882a593Smuzhiyun aw_componet_codec_ops.kcontrol_codec(kcontrol);
945*4882a593Smuzhiyun struct aw883xx *aw883xx =
946*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
949*4882a593Smuzhiyun uinfo->count = 1;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun count = aw_dev_get_profile_count(aw883xx->aw_pa);
952*4882a593Smuzhiyun if (count <= 0) {
953*4882a593Smuzhiyun uinfo->value.enumerated.items = 0;
954*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "get count[%d] failed", count);
955*4882a593Smuzhiyun return 0;
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun uinfo->value.enumerated.items = count;
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun if (uinfo->value.enumerated.item >= count)
961*4882a593Smuzhiyun uinfo->value.enumerated.item = count - 1;
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun name = uinfo->value.enumerated.name;
964*4882a593Smuzhiyun count = uinfo->value.enumerated.item;
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun prof_name = aw_dev_get_prof_name(aw883xx->aw_pa, count);
967*4882a593Smuzhiyun if (prof_name == NULL) {
968*4882a593Smuzhiyun strlcpy(uinfo->value.enumerated.name, "null",
969*4882a593Smuzhiyun strlen("null") + 1);
970*4882a593Smuzhiyun return 0;
971*4882a593Smuzhiyun }
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun strlcpy(name, prof_name, sizeof(uinfo->value.enumerated.name));
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun return 0;
976*4882a593Smuzhiyun }
977*4882a593Smuzhiyun
aw883xx_profile_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)978*4882a593Smuzhiyun static int aw883xx_profile_get(struct snd_kcontrol *kcontrol,
979*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun aw_snd_soc_codec_t *codec =
982*4882a593Smuzhiyun aw_componet_codec_ops.kcontrol_codec(kcontrol);
983*4882a593Smuzhiyun struct aw883xx *aw883xx =
984*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun ucontrol->value.integer.value[0] = aw_dev_get_profile_index(aw883xx->aw_pa);
987*4882a593Smuzhiyun aw_dev_dbg(codec->dev, "profile index [%d]",
988*4882a593Smuzhiyun aw_dev_get_profile_index(aw883xx->aw_pa));
989*4882a593Smuzhiyun return 0;
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun
aw883xx_profile_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)993*4882a593Smuzhiyun static int aw883xx_profile_set(struct snd_kcontrol *kcontrol,
994*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
995*4882a593Smuzhiyun {
996*4882a593Smuzhiyun aw_snd_soc_codec_t *codec =
997*4882a593Smuzhiyun aw_componet_codec_ops.kcontrol_codec(kcontrol);
998*4882a593Smuzhiyun struct aw883xx *aw883xx =
999*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
1000*4882a593Smuzhiyun int ret;
1001*4882a593Smuzhiyun int cur_index;
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun if (aw883xx->dbg_en_prof == false) {
1004*4882a593Smuzhiyun aw_dev_info(codec->dev, "profile close");
1005*4882a593Smuzhiyun return 0;
1006*4882a593Smuzhiyun }
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun /* check value valid */
1009*4882a593Smuzhiyun ret = aw_dev_check_profile_index(aw883xx->aw_pa, ucontrol->value.integer.value[0]);
1010*4882a593Smuzhiyun if (ret) {
1011*4882a593Smuzhiyun aw_dev_info(codec->dev, "unsupported index %ld",
1012*4882a593Smuzhiyun ucontrol->value.integer.value[0]);
1013*4882a593Smuzhiyun return 0;
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun /*check cur_index == set value*/
1017*4882a593Smuzhiyun cur_index = aw_dev_get_profile_index(aw883xx->aw_pa);
1018*4882a593Smuzhiyun if (cur_index == ucontrol->value.integer.value[0]) {
1019*4882a593Smuzhiyun aw_dev_info(codec->dev, "index no change");
1020*4882a593Smuzhiyun return 0;
1021*4882a593Smuzhiyun }
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun /*pa stop or stopping just set profile*/
1024*4882a593Smuzhiyun mutex_lock(&aw883xx->lock);
1025*4882a593Smuzhiyun aw_dev_set_profile_index(aw883xx->aw_pa, ucontrol->value.integer.value[0]);
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun if (aw883xx->pstream) {
1028*4882a593Smuzhiyun aw_device_stop(aw883xx->aw_pa);
1029*4882a593Smuzhiyun aw883xx_start(aw883xx, AW_SYNC_START);
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun aw_dev_info(codec->dev, "profile id %ld", ucontrol->value.integer.value[0]);
1035*4882a593Smuzhiyun return 0;
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun
aw883xx_switch_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1038*4882a593Smuzhiyun static int aw883xx_switch_info(struct snd_kcontrol *kcontrol,
1039*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
1040*4882a593Smuzhiyun {
1041*4882a593Smuzhiyun int count;
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1044*4882a593Smuzhiyun uinfo->count = 1;
1045*4882a593Smuzhiyun count = 2;
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun uinfo->value.enumerated.items = count;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun if (uinfo->value.enumerated.item >= count)
1050*4882a593Smuzhiyun uinfo->value.enumerated.item = count - 1;
1051*4882a593Smuzhiyun
1052*4882a593Smuzhiyun strlcpy(uinfo->value.enumerated.name,
1053*4882a593Smuzhiyun aw883xx_switch[uinfo->value.enumerated.item],
1054*4882a593Smuzhiyun strlen(aw883xx_switch[uinfo->value.enumerated.item]) + 1);
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun return 0;
1057*4882a593Smuzhiyun }
1058*4882a593Smuzhiyun
aw883xx_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1059*4882a593Smuzhiyun static int aw883xx_switch_get(struct snd_kcontrol *kcontrol,
1060*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
1061*4882a593Smuzhiyun {
1062*4882a593Smuzhiyun aw_snd_soc_codec_t *codec =
1063*4882a593Smuzhiyun aw_componet_codec_ops.kcontrol_codec(kcontrol);
1064*4882a593Smuzhiyun struct aw883xx *aw883xx =
1065*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun ucontrol->value.integer.value[0] = aw883xx->allow_pw;
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun return 0;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun
aw883xx_switch_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1072*4882a593Smuzhiyun static int aw883xx_switch_set(struct snd_kcontrol *kcontrol,
1073*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
1074*4882a593Smuzhiyun {
1075*4882a593Smuzhiyun aw_snd_soc_codec_t *codec =
1076*4882a593Smuzhiyun aw_componet_codec_ops.kcontrol_codec(kcontrol);
1077*4882a593Smuzhiyun struct aw883xx *aw883xx =
1078*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun aw_dev_info(codec->dev, "set value:%ld", ucontrol->value.integer.value[0]);
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun if (ucontrol->value.integer.value[0] == aw883xx->allow_pw) {
1083*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "PA switch not change");
1084*4882a593Smuzhiyun return 0;
1085*4882a593Smuzhiyun }
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun if (aw883xx->pstream) {
1088*4882a593Smuzhiyun if (ucontrol->value.integer.value[0] == 0) {
1089*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->start_work);
1090*4882a593Smuzhiyun mutex_lock(&aw883xx->lock);
1091*4882a593Smuzhiyun aw_device_stop(aw883xx->aw_pa);
1092*4882a593Smuzhiyun aw883xx->allow_pw = false;
1093*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
1094*4882a593Smuzhiyun } else {
1095*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->start_work);
1096*4882a593Smuzhiyun mutex_lock(&aw883xx->lock);
1097*4882a593Smuzhiyun aw883xx->allow_pw = true;
1098*4882a593Smuzhiyun aw883xx_start(aw883xx, AW_SYNC_START);
1099*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
1100*4882a593Smuzhiyun }
1101*4882a593Smuzhiyun } else {
1102*4882a593Smuzhiyun mutex_lock(&aw883xx->lock);
1103*4882a593Smuzhiyun if (ucontrol->value.integer.value[0])
1104*4882a593Smuzhiyun aw883xx->allow_pw = true;
1105*4882a593Smuzhiyun else
1106*4882a593Smuzhiyun aw883xx->allow_pw = false;
1107*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun return 0;
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun
aw883xx_monitor_switch_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1113*4882a593Smuzhiyun static int aw883xx_monitor_switch_info(struct snd_kcontrol *kcontrol,
1114*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
1115*4882a593Smuzhiyun {
1116*4882a593Smuzhiyun int count;
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1119*4882a593Smuzhiyun uinfo->count = 1;
1120*4882a593Smuzhiyun count = 2;
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun uinfo->value.enumerated.items = count;
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun if (uinfo->value.enumerated.item >= count)
1125*4882a593Smuzhiyun uinfo->value.enumerated.item = count - 1;
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun strlcpy(uinfo->value.enumerated.name,
1128*4882a593Smuzhiyun aw883xx_switch[uinfo->value.enumerated.item],
1129*4882a593Smuzhiyun strlen(aw883xx_switch[uinfo->value.enumerated.item]) + 1);
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun return 0;
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun
aw883xx_monitor_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1134*4882a593Smuzhiyun static int aw883xx_monitor_switch_get(struct snd_kcontrol *kcontrol,
1135*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
1136*4882a593Smuzhiyun {
1137*4882a593Smuzhiyun aw_snd_soc_codec_t *codec =
1138*4882a593Smuzhiyun aw_componet_codec_ops.kcontrol_codec(kcontrol);
1139*4882a593Smuzhiyun struct aw883xx *aw883xx =
1140*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
1141*4882a593Smuzhiyun struct aw_monitor_desc *monitor_desc = &aw883xx->aw_pa->monitor_desc;
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun ucontrol->value.integer.value[0] = monitor_desc->monitor_cfg.monitor_switch;
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun return 0;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun
aw883xx_monitor_switch_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1148*4882a593Smuzhiyun static int aw883xx_monitor_switch_set(struct snd_kcontrol *kcontrol,
1149*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
1150*4882a593Smuzhiyun {
1151*4882a593Smuzhiyun aw_snd_soc_codec_t *codec =
1152*4882a593Smuzhiyun aw_componet_codec_ops.kcontrol_codec(kcontrol);
1153*4882a593Smuzhiyun struct aw883xx *aw883xx =
1154*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(codec);
1155*4882a593Smuzhiyun struct aw_monitor_desc *monitor_desc = &aw883xx->aw_pa->monitor_desc;
1156*4882a593Smuzhiyun uint32_t enable = 0;
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun aw_dev_info(codec->dev, "set monitor_switch:%ld", ucontrol->value.integer.value[0]);
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun enable = ucontrol->value.integer.value[0];
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun if (monitor_desc->monitor_cfg.monitor_switch == enable) {
1163*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "monitor_switch not change");
1164*4882a593Smuzhiyun return 0;
1165*4882a593Smuzhiyun } else {
1166*4882a593Smuzhiyun monitor_desc->monitor_cfg.monitor_switch = enable;
1167*4882a593Smuzhiyun if (enable)
1168*4882a593Smuzhiyun aw_monitor_start(monitor_desc);
1169*4882a593Smuzhiyun }
1170*4882a593Smuzhiyun
1171*4882a593Smuzhiyun return 0;
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun
aw883xx_dynamic_create_controls(struct aw883xx * aw883xx)1174*4882a593Smuzhiyun static int aw883xx_dynamic_create_controls(struct aw883xx *aw883xx)
1175*4882a593Smuzhiyun {
1176*4882a593Smuzhiyun struct snd_kcontrol_new *aw883xx_dev_control = NULL;
1177*4882a593Smuzhiyun char *kctl_name = NULL;
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun aw883xx_dev_control = devm_kzalloc(aw883xx->codec->dev,
1180*4882a593Smuzhiyun sizeof(struct snd_kcontrol_new) * AW_KCONTROL_NUM, GFP_KERNEL);
1181*4882a593Smuzhiyun if (aw883xx_dev_control == NULL) {
1182*4882a593Smuzhiyun aw_dev_err(aw883xx->codec->dev, "kcontrol malloc failed!");
1183*4882a593Smuzhiyun return -ENOMEM;
1184*4882a593Smuzhiyun }
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun kctl_name = devm_kzalloc(aw883xx->codec->dev, AW_NAME_BUF_MAX, GFP_KERNEL);
1187*4882a593Smuzhiyun if (kctl_name == NULL)
1188*4882a593Smuzhiyun return -ENOMEM;
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun snprintf(kctl_name, AW_NAME_BUF_MAX, "aw_dev_%u_prof",
1191*4882a593Smuzhiyun aw883xx->aw_pa->channel);
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun aw883xx_dev_control[0].name = kctl_name;
1194*4882a593Smuzhiyun aw883xx_dev_control[0].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1195*4882a593Smuzhiyun aw883xx_dev_control[0].info = aw883xx_profile_info;
1196*4882a593Smuzhiyun aw883xx_dev_control[0].get = aw883xx_profile_get;
1197*4882a593Smuzhiyun aw883xx_dev_control[0].put = aw883xx_profile_set;
1198*4882a593Smuzhiyun
1199*4882a593Smuzhiyun kctl_name = devm_kzalloc(aw883xx->codec->dev, AW_NAME_BUF_MAX, GFP_KERNEL);
1200*4882a593Smuzhiyun if (!kctl_name)
1201*4882a593Smuzhiyun return -ENOMEM;
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun snprintf(kctl_name, AW_NAME_BUF_MAX, "aw_dev_%u_switch", aw883xx->aw_pa->channel);
1204*4882a593Smuzhiyun
1205*4882a593Smuzhiyun aw883xx_dev_control[1].name = kctl_name;
1206*4882a593Smuzhiyun aw883xx_dev_control[1].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1207*4882a593Smuzhiyun aw883xx_dev_control[1].info = aw883xx_switch_info;
1208*4882a593Smuzhiyun aw883xx_dev_control[1].get = aw883xx_switch_get;
1209*4882a593Smuzhiyun aw883xx_dev_control[1].put = aw883xx_switch_set;
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun kctl_name = devm_kzalloc(aw883xx->codec->dev, AW_NAME_BUF_MAX, GFP_KERNEL);
1212*4882a593Smuzhiyun if (!kctl_name)
1213*4882a593Smuzhiyun return -ENOMEM;
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun snprintf(kctl_name, AW_NAME_BUF_MAX, "aw_dev_%u_monitor_switch", aw883xx->aw_pa->channel);
1216*4882a593Smuzhiyun
1217*4882a593Smuzhiyun aw883xx_dev_control[2].name = kctl_name;
1218*4882a593Smuzhiyun aw883xx_dev_control[2].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1219*4882a593Smuzhiyun aw883xx_dev_control[2].info = aw883xx_monitor_switch_info;
1220*4882a593Smuzhiyun aw883xx_dev_control[2].get = aw883xx_monitor_switch_get;
1221*4882a593Smuzhiyun aw883xx_dev_control[2].put = aw883xx_monitor_switch_set;
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun aw_componet_codec_ops.add_codec_controls(aw883xx->codec,
1224*4882a593Smuzhiyun aw883xx_dev_control, AW_KCONTROL_NUM);
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun return 0;
1227*4882a593Smuzhiyun }
1228*4882a593Smuzhiyun
aw883xx_request_firmware_file(struct aw883xx * aw883xx)1229*4882a593Smuzhiyun static int aw883xx_request_firmware_file(struct aw883xx *aw883xx)
1230*4882a593Smuzhiyun {
1231*4882a593Smuzhiyun const struct firmware *cont = NULL;
1232*4882a593Smuzhiyun struct aw_container *aw_cfg = NULL;
1233*4882a593Smuzhiyun int ret = -1;
1234*4882a593Smuzhiyun int i;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun aw883xx->aw_pa->fw_status = AW_DEV_FW_FAILED;
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun for (i = 0; i < AW_REQUEST_FW_RETRIES; i++) {
1239*4882a593Smuzhiyun ret = request_firmware(&cont, AW883XX_ACF_FILE, aw883xx->dev);
1240*4882a593Smuzhiyun if ((ret < 0) || (!cont)) {
1241*4882a593Smuzhiyun aw883xx->fw_retry_cnt++;
1242*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "load [%s] try [%d]!",
1243*4882a593Smuzhiyun AW883XX_ACF_FILE, aw883xx->fw_retry_cnt);
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun if (aw883xx->fw_retry_cnt == AW_REQUEST_FW_RETRIES) {
1246*4882a593Smuzhiyun aw883xx->fw_retry_cnt = 0;
1247*4882a593Smuzhiyun return ret;
1248*4882a593Smuzhiyun }
1249*4882a593Smuzhiyun msleep(1000);
1250*4882a593Smuzhiyun } else {
1251*4882a593Smuzhiyun break;
1252*4882a593Smuzhiyun }
1253*4882a593Smuzhiyun }
1254*4882a593Smuzhiyun
1255*4882a593Smuzhiyun if (!cont)
1256*4882a593Smuzhiyun return -ENOMEM;
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "loaded %s - size: %zu",
1259*4882a593Smuzhiyun AW883XX_ACF_FILE, cont ? cont->size : 0);
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun mutex_lock(&g_aw883xx_lock);
1262*4882a593Smuzhiyun if (g_awinic_cfg == NULL) {
1263*4882a593Smuzhiyun aw_cfg = vzalloc(cont->size + sizeof(int));
1264*4882a593Smuzhiyun if (aw_cfg == NULL) {
1265*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "aw883xx_cfg devm_kzalloc failed");
1266*4882a593Smuzhiyun release_firmware(cont);
1267*4882a593Smuzhiyun mutex_unlock(&g_aw883xx_lock);
1268*4882a593Smuzhiyun return -ENOMEM;
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun aw_cfg->len = cont->size;
1271*4882a593Smuzhiyun memcpy(aw_cfg->data, cont->data, cont->size);
1272*4882a593Smuzhiyun ret = aw_dev_load_acf_check(aw_cfg);
1273*4882a593Smuzhiyun if (ret < 0) {
1274*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "Load [%s] failed ....!", AW883XX_ACF_FILE);
1275*4882a593Smuzhiyun vfree(aw_cfg);
1276*4882a593Smuzhiyun aw_cfg = NULL;
1277*4882a593Smuzhiyun release_firmware(cont);
1278*4882a593Smuzhiyun mutex_unlock(&g_aw883xx_lock);
1279*4882a593Smuzhiyun return ret;
1280*4882a593Smuzhiyun }
1281*4882a593Smuzhiyun g_awinic_cfg = aw_cfg;
1282*4882a593Smuzhiyun } else {
1283*4882a593Smuzhiyun aw_cfg = g_awinic_cfg;
1284*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "[%s] already loaded...", AW883XX_ACF_FILE);
1285*4882a593Smuzhiyun }
1286*4882a593Smuzhiyun release_firmware(cont);
1287*4882a593Smuzhiyun mutex_unlock(&g_aw883xx_lock);
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun mutex_lock(&aw883xx->lock);
1290*4882a593Smuzhiyun /*aw device init*/
1291*4882a593Smuzhiyun ret = aw_device_init(aw883xx->aw_pa, aw_cfg);
1292*4882a593Smuzhiyun if (ret < 0) {
1293*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "dev init failed");
1294*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
1295*4882a593Smuzhiyun return ret;
1296*4882a593Smuzhiyun }
1297*4882a593Smuzhiyun
1298*4882a593Smuzhiyun aw883xx_dynamic_create_controls(aw883xx);
1299*4882a593Smuzhiyun
1300*4882a593Smuzhiyun aw_check_spin_mode(&aw883xx->aw_pa->spin_desc);
1301*4882a593Smuzhiyun
1302*4882a593Smuzhiyun mutex_unlock(&aw883xx->lock);
1303*4882a593Smuzhiyun
1304*4882a593Smuzhiyun return 0;
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun
aw883xx_fw_wrok(struct work_struct * work)1307*4882a593Smuzhiyun static void aw883xx_fw_wrok(struct work_struct *work)
1308*4882a593Smuzhiyun {
1309*4882a593Smuzhiyun struct aw883xx *aw883xx = container_of(work,
1310*4882a593Smuzhiyun struct aw883xx, acf_work.work);
1311*4882a593Smuzhiyun int ret;
1312*4882a593Smuzhiyun
1313*4882a593Smuzhiyun ret = aw883xx_request_firmware_file(aw883xx);
1314*4882a593Smuzhiyun if (ret < 0)
1315*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "load profile failed");
1316*4882a593Smuzhiyun
1317*4882a593Smuzhiyun }
1318*4882a593Smuzhiyun
aw883xx_load_fw(struct aw883xx * aw883xx)1319*4882a593Smuzhiyun static void aw883xx_load_fw(struct aw883xx *aw883xx)
1320*4882a593Smuzhiyun {
1321*4882a593Smuzhiyun
1322*4882a593Smuzhiyun if (aw883xx->aw_pa->platform == AW_QCOM) {
1323*4882a593Smuzhiyun /*QCOM sync loading*/
1324*4882a593Smuzhiyun aw883xx_request_firmware_file(aw883xx);
1325*4882a593Smuzhiyun } else {
1326*4882a593Smuzhiyun /*async loading*/
1327*4882a593Smuzhiyun queue_delayed_work(aw883xx->work_queue,
1328*4882a593Smuzhiyun &aw883xx->acf_work,
1329*4882a593Smuzhiyun msecs_to_jiffies(AW883XX_LOAD_FW_DELAY_TIME));
1330*4882a593Smuzhiyun }
1331*4882a593Smuzhiyun }
1332*4882a593Smuzhiyun
1333*4882a593Smuzhiyun #ifdef AW_MTK_PLATFORM
1334*4882a593Smuzhiyun
1335*4882a593Smuzhiyun static const struct snd_soc_dapm_widget aw883xx_dapm_widgets[] = {
1336*4882a593Smuzhiyun /* playback */
1337*4882a593Smuzhiyun SND_SOC_DAPM_AIF_IN("AIF_RX", "Speaker_Playback", 0, SND_SOC_NOPM, 0, 0),
1338*4882a593Smuzhiyun SND_SOC_DAPM_OUTPUT("audio_out"),
1339*4882a593Smuzhiyun /* capture */
1340*4882a593Smuzhiyun SND_SOC_DAPM_AIF_OUT("AIF_TX", "Speaker_Capture", 0, SND_SOC_NOPM, 0, 0),
1341*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("iv_in"),
1342*4882a593Smuzhiyun };
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun static const struct snd_soc_dapm_route aw883xx_audio_map[] = {
1345*4882a593Smuzhiyun {"audio_out", NULL, "AIF_RX"},
1346*4882a593Smuzhiyun {"AIF_TX", NULL, "iv_in"},
1347*4882a593Smuzhiyun };
1348*4882a593Smuzhiyun
1349*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
snd_soc_codec_get_dapm(struct snd_soc_codec * codec)1350*4882a593Smuzhiyun static struct snd_soc_dapm_context *snd_soc_codec_get_dapm(struct snd_soc_codec *codec)
1351*4882a593Smuzhiyun {
1352*4882a593Smuzhiyun return &codec->dapm;
1353*4882a593Smuzhiyun }
1354*4882a593Smuzhiyun #endif
1355*4882a593Smuzhiyun
aw883xx_add_widgets(struct aw883xx * aw883xx)1356*4882a593Smuzhiyun static int aw883xx_add_widgets(struct aw883xx *aw883xx)
1357*4882a593Smuzhiyun {
1358*4882a593Smuzhiyun int i = 0;
1359*4882a593Smuzhiyun int ret;
1360*4882a593Smuzhiyun struct snd_soc_dapm_widget *aw_widgets = NULL;
1361*4882a593Smuzhiyun struct snd_soc_dapm_route *aw_route = NULL;
1362*4882a593Smuzhiyun #ifdef AW_KERNEL_VER_OVER_4_19_1
1363*4882a593Smuzhiyun struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(aw883xx->codec);
1364*4882a593Smuzhiyun #else
1365*4882a593Smuzhiyun struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(aw883xx->codec);
1366*4882a593Smuzhiyun #endif
1367*4882a593Smuzhiyun
1368*4882a593Smuzhiyun /*add widgets*/
1369*4882a593Smuzhiyun aw_widgets = devm_kzalloc(aw883xx->dev,
1370*4882a593Smuzhiyun sizeof(struct snd_soc_dapm_widget) * ARRAY_SIZE(aw883xx_dapm_widgets),
1371*4882a593Smuzhiyun GFP_KERNEL);
1372*4882a593Smuzhiyun if (!aw_widgets)
1373*4882a593Smuzhiyun return -ENOMEM;
1374*4882a593Smuzhiyun
1375*4882a593Smuzhiyun memcpy(aw_widgets, aw883xx_dapm_widgets,
1376*4882a593Smuzhiyun sizeof(struct snd_soc_dapm_widget) * ARRAY_SIZE(aw883xx_dapm_widgets));
1377*4882a593Smuzhiyun
1378*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(aw883xx_dapm_widgets); i++) {
1379*4882a593Smuzhiyun if (aw_widgets[i].name) {
1380*4882a593Smuzhiyun ret = aw883xx_append_i2c_suffix("%s_%x_%x", &aw_widgets[i].name, aw883xx);
1381*4882a593Smuzhiyun if (ret < 0) {
1382*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "aw_widgets.name append i2c suffix failed!\n");
1383*4882a593Smuzhiyun return ret;
1384*4882a593Smuzhiyun }
1385*4882a593Smuzhiyun }
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun if (aw_widgets[i].sname) {
1388*4882a593Smuzhiyun ret = aw883xx_append_i2c_suffix("%s_%x_%x", &aw_widgets[i].sname, aw883xx);
1389*4882a593Smuzhiyun if (ret < 0) {
1390*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "aw_widgets.name append i2c suffix failed!");
1391*4882a593Smuzhiyun return ret;
1392*4882a593Smuzhiyun }
1393*4882a593Smuzhiyun }
1394*4882a593Smuzhiyun }
1395*4882a593Smuzhiyun
1396*4882a593Smuzhiyun snd_soc_dapm_new_controls(dapm, aw_widgets, ARRAY_SIZE(aw883xx_dapm_widgets));
1397*4882a593Smuzhiyun
1398*4882a593Smuzhiyun /*add route*/
1399*4882a593Smuzhiyun aw_route = devm_kzalloc(aw883xx->dev,
1400*4882a593Smuzhiyun sizeof(struct snd_soc_dapm_route) * ARRAY_SIZE(aw883xx_audio_map),
1401*4882a593Smuzhiyun GFP_KERNEL);
1402*4882a593Smuzhiyun if (!aw_route)
1403*4882a593Smuzhiyun return -ENOMEM;
1404*4882a593Smuzhiyun
1405*4882a593Smuzhiyun memcpy(aw_route, aw883xx_audio_map,
1406*4882a593Smuzhiyun sizeof(struct snd_soc_dapm_route) * ARRAY_SIZE(aw883xx_audio_map));
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(aw883xx_audio_map); i++) {
1409*4882a593Smuzhiyun if (aw_route[i].sink) {
1410*4882a593Smuzhiyun ret = aw883xx_append_i2c_suffix("%s_%x_%x", &aw_route[i].sink, aw883xx);
1411*4882a593Smuzhiyun if (ret < 0) {
1412*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "aw_route.sink append i2c suffix failed!");
1413*4882a593Smuzhiyun return ret;
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun if (aw_route[i].source) {
1418*4882a593Smuzhiyun ret = aw883xx_append_i2c_suffix("%s_%x_%x", &aw_route[i].source, aw883xx);
1419*4882a593Smuzhiyun if (ret < 0) {
1420*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "aw_route.source append i2c suffix failed!");
1421*4882a593Smuzhiyun return ret;
1422*4882a593Smuzhiyun }
1423*4882a593Smuzhiyun }
1424*4882a593Smuzhiyun }
1425*4882a593Smuzhiyun snd_soc_dapm_add_routes(dapm, aw_route, ARRAY_SIZE(aw883xx_audio_map));
1426*4882a593Smuzhiyun
1427*4882a593Smuzhiyun return 0;
1428*4882a593Smuzhiyun }
1429*4882a593Smuzhiyun #endif
1430*4882a593Smuzhiyun
aw883xx_codec_probe(aw_snd_soc_codec_t * aw_codec)1431*4882a593Smuzhiyun static int aw883xx_codec_probe(aw_snd_soc_codec_t *aw_codec)
1432*4882a593Smuzhiyun {
1433*4882a593Smuzhiyun struct aw883xx *aw883xx =
1434*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(aw_codec);
1435*4882a593Smuzhiyun
1436*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun /*destroy_workqueue(struct workqueue_struct *wq)*/
1439*4882a593Smuzhiyun aw883xx->work_queue = create_singlethread_workqueue("aw883xx");
1440*4882a593Smuzhiyun if (!aw883xx->work_queue) {
1441*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "create workqueue failed !");
1442*4882a593Smuzhiyun return -EINVAL;
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun
1445*4882a593Smuzhiyun INIT_DELAYED_WORK(&aw883xx->interrupt_work, aw883xx_interrupt_work);
1446*4882a593Smuzhiyun INIT_DELAYED_WORK(&aw883xx->start_work, aw883xx_startup_work);
1447*4882a593Smuzhiyun INIT_DELAYED_WORK(&aw883xx->acf_work, aw883xx_fw_wrok);
1448*4882a593Smuzhiyun
1449*4882a593Smuzhiyun aw883xx->codec = aw_codec;
1450*4882a593Smuzhiyun
1451*4882a593Smuzhiyun aw883xx_add_codec_controls(aw883xx);
1452*4882a593Smuzhiyun #ifdef AW_MTK_PLATFORM
1453*4882a593Smuzhiyun aw883xx_add_widgets(aw883xx);
1454*4882a593Smuzhiyun #endif
1455*4882a593Smuzhiyun aw883xx_load_fw(aw883xx);
1456*4882a593Smuzhiyun
1457*4882a593Smuzhiyun return 0;
1458*4882a593Smuzhiyun }
1459*4882a593Smuzhiyun
1460*4882a593Smuzhiyun #ifdef AW_KERNEL_VER_OVER_4_19_1
aw883xx_codec_remove(aw_snd_soc_codec_t * aw_codec)1461*4882a593Smuzhiyun static void aw883xx_codec_remove(aw_snd_soc_codec_t *aw_codec)
1462*4882a593Smuzhiyun {
1463*4882a593Smuzhiyun struct aw883xx *aw883xx =
1464*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(aw_codec);
1465*4882a593Smuzhiyun
1466*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
1467*4882a593Smuzhiyun
1468*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->interrupt_work);
1469*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->acf_work);
1470*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->aw_pa->monitor_desc.delay_work);
1471*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->start_work);
1472*4882a593Smuzhiyun
1473*4882a593Smuzhiyun if (aw883xx->work_queue)
1474*4882a593Smuzhiyun destroy_workqueue(aw883xx->work_queue);
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun aw_dev_deinit(aw883xx->aw_pa);
1477*4882a593Smuzhiyun }
1478*4882a593Smuzhiyun #else
aw883xx_codec_remove(aw_snd_soc_codec_t * aw_codec)1479*4882a593Smuzhiyun static int aw883xx_codec_remove(aw_snd_soc_codec_t *aw_codec)
1480*4882a593Smuzhiyun {
1481*4882a593Smuzhiyun struct aw883xx *aw883xx =
1482*4882a593Smuzhiyun aw_componet_codec_ops.codec_get_drvdata(aw_codec);
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->interrupt_work);
1487*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->acf_work);
1488*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->aw_pa->monitor_desc.delay_work);
1489*4882a593Smuzhiyun cancel_delayed_work_sync(&aw883xx->start_work);
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun if (aw883xx->work_queue)
1492*4882a593Smuzhiyun destroy_workqueue(aw883xx->work_queue);
1493*4882a593Smuzhiyun
1494*4882a593Smuzhiyun aw_dev_deinit(aw883xx->aw_pa);
1495*4882a593Smuzhiyun
1496*4882a593Smuzhiyun return 0;
1497*4882a593Smuzhiyun }
1498*4882a593Smuzhiyun #endif
1499*4882a593Smuzhiyun
1500*4882a593Smuzhiyun #ifdef AW_KERNEL_VER_OVER_4_19_1
1501*4882a593Smuzhiyun static struct snd_soc_component_driver soc_codec_dev_aw883xx = {
1502*4882a593Smuzhiyun .probe = aw883xx_codec_probe,
1503*4882a593Smuzhiyun .remove = aw883xx_codec_remove,
1504*4882a593Smuzhiyun };
1505*4882a593Smuzhiyun #else
1506*4882a593Smuzhiyun static struct snd_soc_codec_driver soc_codec_dev_aw883xx = {
1507*4882a593Smuzhiyun .probe = aw883xx_codec_probe,
1508*4882a593Smuzhiyun .remove = aw883xx_codec_remove,
1509*4882a593Smuzhiyun };
1510*4882a593Smuzhiyun #endif
1511*4882a593Smuzhiyun
aw883xx_componet_codec_register(struct aw883xx * aw883xx)1512*4882a593Smuzhiyun static int aw883xx_componet_codec_register(struct aw883xx *aw883xx)
1513*4882a593Smuzhiyun {
1514*4882a593Smuzhiyun struct snd_soc_dai_driver *dai_drv = NULL;
1515*4882a593Smuzhiyun int ret;
1516*4882a593Smuzhiyun
1517*4882a593Smuzhiyun dai_drv = devm_kzalloc(aw883xx->dev, sizeof(aw883xx_dai), GFP_KERNEL);
1518*4882a593Smuzhiyun if (dai_drv == NULL) {
1519*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "dai_driver malloc failed");
1520*4882a593Smuzhiyun return -ENOMEM;
1521*4882a593Smuzhiyun }
1522*4882a593Smuzhiyun
1523*4882a593Smuzhiyun memcpy(dai_drv, aw883xx_dai, sizeof(aw883xx_dai));
1524*4882a593Smuzhiyun
1525*4882a593Smuzhiyun ret = aw883xx_dai_drv_append_suffix(aw883xx, dai_drv, 1);
1526*4882a593Smuzhiyun if (ret < 0)
1527*4882a593Smuzhiyun return ret;
1528*4882a593Smuzhiyun
1529*4882a593Smuzhiyun ret = aw883xx->codec_ops->register_codec(aw883xx->dev,
1530*4882a593Smuzhiyun &soc_codec_dev_aw883xx,
1531*4882a593Smuzhiyun dai_drv, ARRAY_SIZE(aw883xx_dai));
1532*4882a593Smuzhiyun if (ret < 0) {
1533*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "failed to register aw883xx: %d", ret);
1534*4882a593Smuzhiyun return ret;
1535*4882a593Smuzhiyun }
1536*4882a593Smuzhiyun
1537*4882a593Smuzhiyun return 0;
1538*4882a593Smuzhiyun }
1539*4882a593Smuzhiyun
1540*4882a593Smuzhiyun
aw883xx_malloc_init(struct i2c_client * i2c)1541*4882a593Smuzhiyun static struct aw883xx *aw883xx_malloc_init(struct i2c_client *i2c)
1542*4882a593Smuzhiyun {
1543*4882a593Smuzhiyun struct aw883xx *aw883xx = devm_kzalloc(&i2c->dev,
1544*4882a593Smuzhiyun sizeof(struct aw883xx), GFP_KERNEL);
1545*4882a593Smuzhiyun if (aw883xx == NULL) {
1546*4882a593Smuzhiyun aw_dev_err(&i2c->dev, "devm_kzalloc failed");
1547*4882a593Smuzhiyun return NULL;
1548*4882a593Smuzhiyun }
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun aw883xx->dev = &i2c->dev;
1551*4882a593Smuzhiyun aw883xx->i2c = i2c;
1552*4882a593Smuzhiyun aw883xx->aw_pa = NULL;
1553*4882a593Smuzhiyun aw883xx->codec = NULL;
1554*4882a593Smuzhiyun aw883xx->codec_ops = &aw_componet_codec_ops;
1555*4882a593Smuzhiyun aw883xx->dbg_en_prof = true;
1556*4882a593Smuzhiyun aw883xx->allow_pw = true;
1557*4882a593Smuzhiyun aw883xx->work_queue = NULL;
1558*4882a593Smuzhiyun aw883xx->i2c_log_en = 0;
1559*4882a593Smuzhiyun mutex_init(&aw883xx->lock);
1560*4882a593Smuzhiyun mutex_init(&aw883xx->i2c_lock);
1561*4882a593Smuzhiyun
1562*4882a593Smuzhiyun return aw883xx;
1563*4882a593Smuzhiyun }
1564*4882a593Smuzhiyun
aw883xx_gpio_request(struct aw883xx * aw883xx)1565*4882a593Smuzhiyun static int aw883xx_gpio_request(struct aw883xx *aw883xx)
1566*4882a593Smuzhiyun {
1567*4882a593Smuzhiyun int ret;
1568*4882a593Smuzhiyun
1569*4882a593Smuzhiyun if (gpio_is_valid(aw883xx->reset_gpio)) {
1570*4882a593Smuzhiyun ret = devm_gpio_request_one(aw883xx->dev, aw883xx->reset_gpio,
1571*4882a593Smuzhiyun GPIOF_OUT_INIT_LOW, "aw883xx_rst");
1572*4882a593Smuzhiyun if (ret) {
1573*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "rst request failed");
1574*4882a593Smuzhiyun return ret;
1575*4882a593Smuzhiyun }
1576*4882a593Smuzhiyun }
1577*4882a593Smuzhiyun
1578*4882a593Smuzhiyun if (gpio_is_valid(aw883xx->irq_gpio)) {
1579*4882a593Smuzhiyun ret = devm_gpio_request_one(aw883xx->dev, aw883xx->irq_gpio,
1580*4882a593Smuzhiyun GPIOF_DIR_IN, "aw883xx_int");
1581*4882a593Smuzhiyun if (ret) {
1582*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "int request failed");
1583*4882a593Smuzhiyun return ret;
1584*4882a593Smuzhiyun }
1585*4882a593Smuzhiyun }
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun return 0;
1588*4882a593Smuzhiyun }
1589*4882a593Smuzhiyun
1590*4882a593Smuzhiyun /*****************************************************
1591*4882a593Smuzhiyun *
1592*4882a593Smuzhiyun * device tree
1593*4882a593Smuzhiyun *
1594*4882a593Smuzhiyun *****************************************************/
aw883xx_parse_gpio_dt(struct aw883xx * aw883xx)1595*4882a593Smuzhiyun static int aw883xx_parse_gpio_dt(struct aw883xx *aw883xx)
1596*4882a593Smuzhiyun {
1597*4882a593Smuzhiyun struct device_node *np = aw883xx->dev->of_node;
1598*4882a593Smuzhiyun
1599*4882a593Smuzhiyun aw883xx->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
1600*4882a593Smuzhiyun if (aw883xx->reset_gpio < 0) {
1601*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "no reset gpio provided, will not hw reset");
1602*4882a593Smuzhiyun /* return -EIO; */
1603*4882a593Smuzhiyun } else {
1604*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "reset gpio provided ok");
1605*4882a593Smuzhiyun }
1606*4882a593Smuzhiyun
1607*4882a593Smuzhiyun aw883xx->irq_gpio = of_get_named_gpio(np, "irq-gpio", 0);
1608*4882a593Smuzhiyun if (aw883xx->irq_gpio < 0)
1609*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "no irq gpio provided.");
1610*4882a593Smuzhiyun else
1611*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "irq gpio provided ok.");
1612*4882a593Smuzhiyun
1613*4882a593Smuzhiyun return 0;
1614*4882a593Smuzhiyun }
1615*4882a593Smuzhiyun
aw883xx_parse_sync_flag_dt(struct aw883xx * aw883xx)1616*4882a593Smuzhiyun static void aw883xx_parse_sync_flag_dt(struct aw883xx *aw883xx)
1617*4882a593Smuzhiyun {
1618*4882a593Smuzhiyun int ret;
1619*4882a593Smuzhiyun int32_t sync_enable = 0;
1620*4882a593Smuzhiyun struct device_node *np = aw883xx->dev->of_node;
1621*4882a593Smuzhiyun
1622*4882a593Smuzhiyun ret = of_property_read_u32(np, "sync-flag", &sync_enable);
1623*4882a593Smuzhiyun if (ret < 0) {
1624*4882a593Smuzhiyun aw_dev_info(aw883xx->dev,
1625*4882a593Smuzhiyun "read sync flag failed,default phase sync off");
1626*4882a593Smuzhiyun sync_enable = false;
1627*4882a593Smuzhiyun } else {
1628*4882a593Smuzhiyun aw_dev_info(aw883xx->dev,
1629*4882a593Smuzhiyun "sync flag is %d", sync_enable);
1630*4882a593Smuzhiyun }
1631*4882a593Smuzhiyun
1632*4882a593Smuzhiyun aw883xx->phase_sync = sync_enable;
1633*4882a593Smuzhiyun }
1634*4882a593Smuzhiyun
aw883xx_parse_dt(struct aw883xx * aw883xx)1635*4882a593Smuzhiyun static int aw883xx_parse_dt(struct aw883xx *aw883xx)
1636*4882a593Smuzhiyun {
1637*4882a593Smuzhiyun aw883xx_parse_sync_flag_dt(aw883xx);
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun return aw883xx_parse_gpio_dt(aw883xx);
1640*4882a593Smuzhiyun }
1641*4882a593Smuzhiyun
aw883xx_hw_reset(struct aw883xx * aw883xx)1642*4882a593Smuzhiyun static int aw883xx_hw_reset(struct aw883xx *aw883xx)
1643*4882a593Smuzhiyun {
1644*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
1645*4882a593Smuzhiyun
1646*4882a593Smuzhiyun if (gpio_is_valid(aw883xx->reset_gpio)) {
1647*4882a593Smuzhiyun gpio_set_value_cansleep(aw883xx->reset_gpio, 0);
1648*4882a593Smuzhiyun usleep_range(AW_1000_US, AW_1000_US + 10);
1649*4882a593Smuzhiyun gpio_set_value_cansleep(aw883xx->reset_gpio, 1);
1650*4882a593Smuzhiyun usleep_range(AW_1000_US, AW_1000_US + 10);
1651*4882a593Smuzhiyun } else {
1652*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "failed");
1653*4882a593Smuzhiyun }
1654*4882a593Smuzhiyun return 0;
1655*4882a593Smuzhiyun }
1656*4882a593Smuzhiyun
aw883xx_read_chipid(struct aw883xx * aw883xx)1657*4882a593Smuzhiyun static int aw883xx_read_chipid(struct aw883xx *aw883xx)
1658*4882a593Smuzhiyun {
1659*4882a593Smuzhiyun int ret = -1;
1660*4882a593Smuzhiyun uint16_t reg_val = 0;
1661*4882a593Smuzhiyun
1662*4882a593Smuzhiyun ret = aw883xx_reg_read(aw883xx, AW883XX_CHIP_ID_REG, ®_val);
1663*4882a593Smuzhiyun if (ret < 0) {
1664*4882a593Smuzhiyun aw_dev_err(aw883xx->dev,
1665*4882a593Smuzhiyun "failed to read chip id, ret=%d", ret);
1666*4882a593Smuzhiyun return -EIO;
1667*4882a593Smuzhiyun }
1668*4882a593Smuzhiyun
1669*4882a593Smuzhiyun aw883xx->chip_id = reg_val;
1670*4882a593Smuzhiyun aw_dev_info(aw883xx->dev,
1671*4882a593Smuzhiyun "read chip id: 0x%x", reg_val);
1672*4882a593Smuzhiyun
1673*4882a593Smuzhiyun return 0;
1674*4882a593Smuzhiyun }
1675*4882a593Smuzhiyun
1676*4882a593Smuzhiyun /******************************************************
1677*4882a593Smuzhiyun *
1678*4882a593Smuzhiyun * irq
1679*4882a593Smuzhiyun *
1680*4882a593Smuzhiyun ******************************************************/
aw883xx_irq(int irq,void * data)1681*4882a593Smuzhiyun static irqreturn_t aw883xx_irq(int irq, void *data)
1682*4882a593Smuzhiyun {
1683*4882a593Smuzhiyun struct aw883xx *aw883xx = data;
1684*4882a593Smuzhiyun
1685*4882a593Smuzhiyun if (aw883xx == NULL) {
1686*4882a593Smuzhiyun aw_pr_err("pointer is NULL");
1687*4882a593Smuzhiyun return -EINVAL;
1688*4882a593Smuzhiyun }
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
1691*4882a593Smuzhiyun /*mask all irq*/
1692*4882a593Smuzhiyun aw_dev_set_intmask(aw883xx->aw_pa, false);
1693*4882a593Smuzhiyun
1694*4882a593Smuzhiyun /*upload workqueue*/
1695*4882a593Smuzhiyun if (aw883xx->work_queue)
1696*4882a593Smuzhiyun queue_delayed_work(aw883xx->work_queue,
1697*4882a593Smuzhiyun &aw883xx->interrupt_work, 0);
1698*4882a593Smuzhiyun
1699*4882a593Smuzhiyun return IRQ_HANDLED;
1700*4882a593Smuzhiyun }
1701*4882a593Smuzhiyun
aw883xx_interrupt_init(struct aw883xx * aw883xx)1702*4882a593Smuzhiyun static int aw883xx_interrupt_init(struct aw883xx *aw883xx)
1703*4882a593Smuzhiyun {
1704*4882a593Smuzhiyun int irq_flags;
1705*4882a593Smuzhiyun int ret;
1706*4882a593Smuzhiyun
1707*4882a593Smuzhiyun if (gpio_is_valid(aw883xx->irq_gpio)) {
1708*4882a593Smuzhiyun irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
1709*4882a593Smuzhiyun ret = devm_request_threaded_irq(aw883xx->dev,
1710*4882a593Smuzhiyun gpio_to_irq(aw883xx->irq_gpio),
1711*4882a593Smuzhiyun NULL, aw883xx_irq, irq_flags,
1712*4882a593Smuzhiyun "aw883xx", aw883xx);
1713*4882a593Smuzhiyun if (ret) {
1714*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "Failed to request IRQ %d: %d",
1715*4882a593Smuzhiyun gpio_to_irq(aw883xx->irq_gpio), ret);
1716*4882a593Smuzhiyun return ret;
1717*4882a593Smuzhiyun }
1718*4882a593Smuzhiyun } else {
1719*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "skipping IRQ registration");
1720*4882a593Smuzhiyun }
1721*4882a593Smuzhiyun
1722*4882a593Smuzhiyun return 0;
1723*4882a593Smuzhiyun }
1724*4882a593Smuzhiyun
1725*4882a593Smuzhiyun
1726*4882a593Smuzhiyun /******************************************************
1727*4882a593Smuzhiyun *
1728*4882a593Smuzhiyun * sys group attribute: reg
1729*4882a593Smuzhiyun *
1730*4882a593Smuzhiyun ******************************************************/
aw883xx_reg_show(struct device * dev,struct device_attribute * attr,char * buf)1731*4882a593Smuzhiyun static ssize_t aw883xx_reg_show(struct device *dev,
1732*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
1733*4882a593Smuzhiyun {
1734*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
1735*4882a593Smuzhiyun int reg_num = aw883xx->aw_pa->ops.aw_get_reg_num();
1736*4882a593Smuzhiyun ssize_t len = 0;
1737*4882a593Smuzhiyun uint8_t i = 0;
1738*4882a593Smuzhiyun uint16_t reg_val = 0;
1739*4882a593Smuzhiyun
1740*4882a593Smuzhiyun for (i = 0; i < reg_num; i++) {
1741*4882a593Smuzhiyun if (aw883xx->aw_pa->ops.aw_check_rd_access(i)) {
1742*4882a593Smuzhiyun aw883xx_reg_read(aw883xx, i, ®_val);
1743*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len,
1744*4882a593Smuzhiyun "reg:0x%02x=0x%04x\n", i, reg_val);
1745*4882a593Smuzhiyun }
1746*4882a593Smuzhiyun }
1747*4882a593Smuzhiyun
1748*4882a593Smuzhiyun return len;
1749*4882a593Smuzhiyun }
1750*4882a593Smuzhiyun
aw883xx_reg_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1751*4882a593Smuzhiyun static ssize_t aw883xx_reg_store(struct device *dev,
1752*4882a593Smuzhiyun struct device_attribute *attr, const char *buf,
1753*4882a593Smuzhiyun size_t count)
1754*4882a593Smuzhiyun {
1755*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
1756*4882a593Smuzhiyun unsigned int databuf[2] = { 0 };
1757*4882a593Smuzhiyun
1758*4882a593Smuzhiyun if (2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1]))
1759*4882a593Smuzhiyun aw883xx_reg_write(aw883xx, databuf[0], databuf[1]);
1760*4882a593Smuzhiyun
1761*4882a593Smuzhiyun return count;
1762*4882a593Smuzhiyun }
1763*4882a593Smuzhiyun
aw883xx_rw_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1764*4882a593Smuzhiyun static ssize_t aw883xx_rw_store(struct device *dev,
1765*4882a593Smuzhiyun struct device_attribute *attr, const char *buf,
1766*4882a593Smuzhiyun size_t count)
1767*4882a593Smuzhiyun {
1768*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
1769*4882a593Smuzhiyun unsigned int databuf[2] = { 0 };
1770*4882a593Smuzhiyun
1771*4882a593Smuzhiyun if (2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) {
1772*4882a593Smuzhiyun aw883xx->reg_addr = (uint8_t)databuf[0];
1773*4882a593Smuzhiyun if (aw883xx->aw_pa->ops.aw_check_rd_access(databuf[0]))
1774*4882a593Smuzhiyun aw883xx_reg_write(aw883xx, databuf[0], databuf[1]);
1775*4882a593Smuzhiyun } else if (1 == sscanf(buf, "%x", &databuf[0])) {
1776*4882a593Smuzhiyun aw883xx->reg_addr = (uint8_t)databuf[0];
1777*4882a593Smuzhiyun }
1778*4882a593Smuzhiyun
1779*4882a593Smuzhiyun return count;
1780*4882a593Smuzhiyun }
1781*4882a593Smuzhiyun
aw883xx_rw_show(struct device * dev,struct device_attribute * attr,char * buf)1782*4882a593Smuzhiyun static ssize_t aw883xx_rw_show(struct device *dev,
1783*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
1784*4882a593Smuzhiyun {
1785*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
1786*4882a593Smuzhiyun ssize_t len = 0;
1787*4882a593Smuzhiyun uint16_t reg_val = 0;
1788*4882a593Smuzhiyun
1789*4882a593Smuzhiyun if (aw883xx->aw_pa->ops.aw_check_rd_access(aw883xx->reg_addr)) {
1790*4882a593Smuzhiyun aw883xx_reg_read(aw883xx, aw883xx->reg_addr, ®_val);
1791*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len,
1792*4882a593Smuzhiyun "reg:0x%02x=0x%04x\n", aw883xx->reg_addr,
1793*4882a593Smuzhiyun reg_val);
1794*4882a593Smuzhiyun }
1795*4882a593Smuzhiyun
1796*4882a593Smuzhiyun return len;
1797*4882a593Smuzhiyun }
1798*4882a593Smuzhiyun
aw883xx_drv_ver_show(struct device * dev,struct device_attribute * attr,char * buf)1799*4882a593Smuzhiyun static ssize_t aw883xx_drv_ver_show(struct device *dev,
1800*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
1801*4882a593Smuzhiyun {
1802*4882a593Smuzhiyun ssize_t len = 0;
1803*4882a593Smuzhiyun
1804*4882a593Smuzhiyun len += snprintf(buf+len, PAGE_SIZE-len,
1805*4882a593Smuzhiyun "driver_ver: %s \n", AW883XX_DRIVER_VERSION);
1806*4882a593Smuzhiyun
1807*4882a593Smuzhiyun return len;
1808*4882a593Smuzhiyun }
1809*4882a593Smuzhiyun
aw883xx_dsp_rw_show(struct device * dev,struct device_attribute * attr,char * buf)1810*4882a593Smuzhiyun static ssize_t aw883xx_dsp_rw_show(struct device *dev,
1811*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
1812*4882a593Smuzhiyun {
1813*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
1814*4882a593Smuzhiyun ssize_t len = 0;
1815*4882a593Smuzhiyun uint16_t reg_val = 0;
1816*4882a593Smuzhiyun
1817*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
1818*4882a593Smuzhiyun aw883xx_i2c_write(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_madd_reg, aw883xx->dsp_addr);
1819*4882a593Smuzhiyun aw883xx_i2c_read(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_mdat_reg, ®_val);
1820*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len,
1821*4882a593Smuzhiyun "dsp:0x%04x=0x%04x\n", aw883xx->dsp_addr, reg_val);
1822*4882a593Smuzhiyun aw883xx_i2c_read(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_mdat_reg, ®_val);
1823*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len,
1824*4882a593Smuzhiyun "dsp:0x%04x=0x%04x\n", aw883xx->dsp_addr + 1, reg_val);
1825*4882a593Smuzhiyun aw883xx_clear_dsp_sel_st(aw883xx);
1826*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
1827*4882a593Smuzhiyun
1828*4882a593Smuzhiyun return len;
1829*4882a593Smuzhiyun }
1830*4882a593Smuzhiyun
aw883xx_dsp_rw_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1831*4882a593Smuzhiyun static ssize_t aw883xx_dsp_rw_store(struct device *dev,
1832*4882a593Smuzhiyun struct device_attribute *attr,
1833*4882a593Smuzhiyun const char *buf, size_t count)
1834*4882a593Smuzhiyun {
1835*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
1836*4882a593Smuzhiyun unsigned int databuf[2] = { 0 };
1837*4882a593Smuzhiyun
1838*4882a593Smuzhiyun if (2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) {
1839*4882a593Smuzhiyun aw883xx->dsp_addr = (unsigned int)databuf[0];
1840*4882a593Smuzhiyun aw883xx_dsp_write(aw883xx, databuf[0], databuf[1], AW_DSP_16_DATA);
1841*4882a593Smuzhiyun aw_dev_dbg(aw883xx->dev, "get param: %x %x",
1842*4882a593Smuzhiyun databuf[0], databuf[1]);
1843*4882a593Smuzhiyun } else if (1 == sscanf(buf, "%x", &databuf[0])) {
1844*4882a593Smuzhiyun aw883xx->dsp_addr = (unsigned int)databuf[0];
1845*4882a593Smuzhiyun aw_dev_dbg(aw883xx->dev, "get param: %x",
1846*4882a593Smuzhiyun databuf[0]);
1847*4882a593Smuzhiyun }
1848*4882a593Smuzhiyun aw883xx_clear_dsp_sel_st(aw883xx);
1849*4882a593Smuzhiyun
1850*4882a593Smuzhiyun return count;
1851*4882a593Smuzhiyun }
1852*4882a593Smuzhiyun
aw883xx_awrw_write(struct aw883xx * aw883xx,const char * buf,size_t count)1853*4882a593Smuzhiyun static int aw883xx_awrw_write(struct aw883xx *aw883xx, const char *buf, size_t count)
1854*4882a593Smuzhiyun {
1855*4882a593Smuzhiyun int i, ret;
1856*4882a593Smuzhiyun char *data_buf = NULL;
1857*4882a593Smuzhiyun int str_len, data_len, temp_data;
1858*4882a593Smuzhiyun struct aw883xx_i2c_packet *packet = &aw883xx->i2c_packet;
1859*4882a593Smuzhiyun uint32_t dsp_addr_h = 0, dsp_addr_l = 0;
1860*4882a593Smuzhiyun
1861*4882a593Smuzhiyun data_len = AWRW_DATA_BYTES * packet->reg_num;
1862*4882a593Smuzhiyun
1863*4882a593Smuzhiyun str_len = count - AWRW_HDR_LEN - 1;
1864*4882a593Smuzhiyun if ((data_len * 5 - 1) > str_len) {
1865*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "data_str_len [%d], requeset len [%d]",
1866*4882a593Smuzhiyun str_len, (data_len * 5 - 1));
1867*4882a593Smuzhiyun return -EINVAL;
1868*4882a593Smuzhiyun }
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun if (packet->reg_addr == aw883xx->aw_pa->dsp_mem_desc.dsp_madd_reg) {
1871*4882a593Smuzhiyun if (sscanf(buf + AWRW_HDR_LEN + 1, "0x%02x 0x%02x", &dsp_addr_h, &dsp_addr_l) == 2) {
1872*4882a593Smuzhiyun packet->dsp_addr = (dsp_addr_h << 8) | dsp_addr_l;
1873*4882a593Smuzhiyun packet->dsp_status = AWRW_DSP_READY;
1874*4882a593Smuzhiyun aw_dev_dbg(aw883xx->dev, "write:reg_addr[0x%02x], dsp_base_addr:[0x%02x]",
1875*4882a593Smuzhiyun packet->reg_addr, packet->dsp_addr);
1876*4882a593Smuzhiyun return 0;
1877*4882a593Smuzhiyun } else {
1878*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "get reg 0x%x data failed", packet->reg_addr);
1879*4882a593Smuzhiyun return -EINVAL;
1880*4882a593Smuzhiyun }
1881*4882a593Smuzhiyun }
1882*4882a593Smuzhiyun
1883*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
1884*4882a593Smuzhiyun if (packet->reg_addr == aw883xx->aw_pa->dsp_mem_desc.dsp_mdat_reg) {
1885*4882a593Smuzhiyun if (packet->dsp_status != AWRW_DSP_READY) {
1886*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "please write reg[0x40] first");
1887*4882a593Smuzhiyun ret = -EINVAL;
1888*4882a593Smuzhiyun goto exit;
1889*4882a593Smuzhiyun }
1890*4882a593Smuzhiyun aw883xx_i2c_write(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_madd_reg, packet->dsp_addr);
1891*4882a593Smuzhiyun packet->dsp_status = AWRW_DSP_ST_NONE;
1892*4882a593Smuzhiyun }
1893*4882a593Smuzhiyun
1894*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "write:reg_addr[0x%02x], reg_num[%d]",
1895*4882a593Smuzhiyun packet->reg_addr, packet->reg_num);
1896*4882a593Smuzhiyun
1897*4882a593Smuzhiyun data_buf = devm_kzalloc(aw883xx->dev, data_len, GFP_KERNEL);
1898*4882a593Smuzhiyun if (data_buf == NULL) {
1899*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "alloc memory failed");
1900*4882a593Smuzhiyun ret = -ENOMEM;
1901*4882a593Smuzhiyun goto exit;
1902*4882a593Smuzhiyun }
1903*4882a593Smuzhiyun
1904*4882a593Smuzhiyun for (i = 0; i < data_len; i++) {
1905*4882a593Smuzhiyun sscanf(buf + AWRW_HDR_LEN + 1 + i * 5, "0x%02x", &temp_data);
1906*4882a593Smuzhiyun data_buf[i] = temp_data;
1907*4882a593Smuzhiyun
1908*4882a593Smuzhiyun }
1909*4882a593Smuzhiyun
1910*4882a593Smuzhiyun ret = aw883xx_i2c_writes(aw883xx, packet->reg_addr, data_buf, data_len);
1911*4882a593Smuzhiyun if (ret < 0) {
1912*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "write failed");
1913*4882a593Smuzhiyun devm_kfree(aw883xx->dev, data_buf);
1914*4882a593Smuzhiyun data_buf = NULL;
1915*4882a593Smuzhiyun goto exit;
1916*4882a593Smuzhiyun }
1917*4882a593Smuzhiyun
1918*4882a593Smuzhiyun devm_kfree(aw883xx->dev, data_buf);
1919*4882a593Smuzhiyun data_buf = NULL;
1920*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "write success");
1921*4882a593Smuzhiyun exit:
1922*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
1923*4882a593Smuzhiyun return ret;
1924*4882a593Smuzhiyun }
1925*4882a593Smuzhiyun
aw883xx_awrw_data_check(struct aw883xx * aw883xx,int * data)1926*4882a593Smuzhiyun static int aw883xx_awrw_data_check(struct aw883xx *aw883xx, int *data)
1927*4882a593Smuzhiyun {
1928*4882a593Smuzhiyun if ((data[AWRW_HDR_ADDR_BYTES] != AWRW_ADDR_BYTES) ||
1929*4882a593Smuzhiyun (data[AWRW_HDR_DATA_BYTES] != AWRW_DATA_BYTES)) {
1930*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "addr_bytes [%d] or data_bytes [%d] unsupport",
1931*4882a593Smuzhiyun data[AWRW_HDR_ADDR_BYTES], data[AWRW_HDR_DATA_BYTES]);
1932*4882a593Smuzhiyun return -EINVAL;
1933*4882a593Smuzhiyun }
1934*4882a593Smuzhiyun
1935*4882a593Smuzhiyun return 0;
1936*4882a593Smuzhiyun }
1937*4882a593Smuzhiyun
1938*4882a593Smuzhiyun /* flag addr_bytes data_bytes reg_num reg_addr*/
aw883xx_awrw_parse_buf(struct aw883xx * aw883xx,const char * buf,size_t count)1939*4882a593Smuzhiyun static int aw883xx_awrw_parse_buf(struct aw883xx *aw883xx, const char *buf, size_t count)
1940*4882a593Smuzhiyun {
1941*4882a593Smuzhiyun int data[AWRW_HDR_MAX] = { 0 };
1942*4882a593Smuzhiyun struct aw883xx_i2c_packet *packet = &aw883xx->i2c_packet;
1943*4882a593Smuzhiyun int ret;
1944*4882a593Smuzhiyun
1945*4882a593Smuzhiyun if (sscanf(buf, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
1946*4882a593Smuzhiyun &data[AWRW_HDR_WR_FLAG], &data[AWRW_HDR_ADDR_BYTES], &data[AWRW_HDR_DATA_BYTES],
1947*4882a593Smuzhiyun &data[AWRW_HDR_REG_NUM], &data[AWRW_HDR_REG_ADDR]) == 5) {
1948*4882a593Smuzhiyun
1949*4882a593Smuzhiyun ret = aw883xx_awrw_data_check(aw883xx, data);
1950*4882a593Smuzhiyun if (ret < 0)
1951*4882a593Smuzhiyun return ret;
1952*4882a593Smuzhiyun
1953*4882a593Smuzhiyun packet->reg_addr = data[AWRW_HDR_REG_ADDR];
1954*4882a593Smuzhiyun packet->reg_num = data[AWRW_HDR_REG_NUM];
1955*4882a593Smuzhiyun
1956*4882a593Smuzhiyun if (data[AWRW_HDR_WR_FLAG] == AWRW_FLAG_WRITE) {
1957*4882a593Smuzhiyun return aw883xx_awrw_write(aw883xx, buf, count);
1958*4882a593Smuzhiyun } else if (data[AWRW_HDR_WR_FLAG] == AWRW_FLAG_READ) {
1959*4882a593Smuzhiyun packet->i2c_status = AWRW_I2C_ST_READ;
1960*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "read_cmd:reg_addr[0x%02x], reg_num[%d]",
1961*4882a593Smuzhiyun packet->reg_addr, packet->reg_num);
1962*4882a593Smuzhiyun
1963*4882a593Smuzhiyun } else {
1964*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "please check str format, unsupport flag %d", data[AWRW_HDR_WR_FLAG]);
1965*4882a593Smuzhiyun return -EINVAL;
1966*4882a593Smuzhiyun }
1967*4882a593Smuzhiyun } else {
1968*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "can not parse string");
1969*4882a593Smuzhiyun return -EINVAL;
1970*4882a593Smuzhiyun }
1971*4882a593Smuzhiyun
1972*4882a593Smuzhiyun return 0;
1973*4882a593Smuzhiyun }
1974*4882a593Smuzhiyun
aw883xx_awrw_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1975*4882a593Smuzhiyun static ssize_t aw883xx_awrw_store(struct device *dev,
1976*4882a593Smuzhiyun struct device_attribute *attr, const char *buf, size_t count)
1977*4882a593Smuzhiyun {
1978*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
1979*4882a593Smuzhiyun int ret;
1980*4882a593Smuzhiyun
1981*4882a593Smuzhiyun if (count < AWRW_HDR_LEN) {
1982*4882a593Smuzhiyun aw_dev_err(dev, "data count too smaller, please check write format");
1983*4882a593Smuzhiyun aw_dev_err(dev, "string %s", buf);
1984*4882a593Smuzhiyun return -EINVAL;
1985*4882a593Smuzhiyun }
1986*4882a593Smuzhiyun
1987*4882a593Smuzhiyun ret = aw883xx_awrw_parse_buf(aw883xx, buf, count);
1988*4882a593Smuzhiyun if (ret)
1989*4882a593Smuzhiyun return -EINVAL;
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun
1992*4882a593Smuzhiyun return count;
1993*4882a593Smuzhiyun }
1994*4882a593Smuzhiyun
aw883xx_awrw_show(struct device * dev,struct device_attribute * attr,char * buf)1995*4882a593Smuzhiyun static ssize_t aw883xx_awrw_show(struct device *dev,
1996*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
1997*4882a593Smuzhiyun {
1998*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
1999*4882a593Smuzhiyun struct aw883xx_i2c_packet *packet = &aw883xx->i2c_packet;
2000*4882a593Smuzhiyun int data_len, len = 0;
2001*4882a593Smuzhiyun int ret, i;
2002*4882a593Smuzhiyun uint8_t *reg_data = NULL;
2003*4882a593Smuzhiyun
2004*4882a593Smuzhiyun if (packet->i2c_status != AWRW_I2C_ST_READ) {
2005*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "please write read cmd first");
2006*4882a593Smuzhiyun return -EINVAL;
2007*4882a593Smuzhiyun }
2008*4882a593Smuzhiyun
2009*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
2010*4882a593Smuzhiyun if (packet->reg_addr == aw883xx->aw_pa->dsp_mem_desc.dsp_mdat_reg) {
2011*4882a593Smuzhiyun if (packet->dsp_status != AWRW_DSP_READY) {
2012*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "please write reg[0x40] first");
2013*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
2014*4882a593Smuzhiyun return -EINVAL;
2015*4882a593Smuzhiyun }
2016*4882a593Smuzhiyun ret = aw883xx_i2c_write(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_madd_reg, packet->dsp_addr);
2017*4882a593Smuzhiyun if (ret < 0) {
2018*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
2019*4882a593Smuzhiyun return ret;
2020*4882a593Smuzhiyun }
2021*4882a593Smuzhiyun packet->dsp_status = AWRW_DSP_ST_NONE;
2022*4882a593Smuzhiyun }
2023*4882a593Smuzhiyun
2024*4882a593Smuzhiyun data_len = AWRW_DATA_BYTES * packet->reg_num;
2025*4882a593Smuzhiyun reg_data = devm_kzalloc(dev, data_len, GFP_KERNEL);
2026*4882a593Smuzhiyun if (reg_data == NULL) {
2027*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "memory alloc failed");
2028*4882a593Smuzhiyun ret = -EINVAL;
2029*4882a593Smuzhiyun goto exit;
2030*4882a593Smuzhiyun }
2031*4882a593Smuzhiyun
2032*4882a593Smuzhiyun ret = aw883xx_i2c_reads(aw883xx, packet->reg_addr, reg_data, data_len);
2033*4882a593Smuzhiyun if (ret < 0) {
2034*4882a593Smuzhiyun ret = -EFAULT;
2035*4882a593Smuzhiyun goto exit;
2036*4882a593Smuzhiyun }
2037*4882a593Smuzhiyun
2038*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "reg_addr 0x%02x, reg_num %d",
2039*4882a593Smuzhiyun packet->reg_addr, packet->reg_num);
2040*4882a593Smuzhiyun
2041*4882a593Smuzhiyun for (i = 0; i < data_len; i++) {
2042*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len,
2043*4882a593Smuzhiyun "0x%02x,", reg_data[i]);
2044*4882a593Smuzhiyun
2045*4882a593Smuzhiyun }
2046*4882a593Smuzhiyun ret = len;
2047*4882a593Smuzhiyun
2048*4882a593Smuzhiyun exit:
2049*4882a593Smuzhiyun if (reg_data) {
2050*4882a593Smuzhiyun devm_kfree(dev, reg_data);
2051*4882a593Smuzhiyun reg_data = NULL;
2052*4882a593Smuzhiyun }
2053*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
2054*4882a593Smuzhiyun packet->i2c_status = AWRW_I2C_ST_NONE;
2055*4882a593Smuzhiyun return ret;
2056*4882a593Smuzhiyun }
2057*4882a593Smuzhiyun
aw883xx_fade_step_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2058*4882a593Smuzhiyun static ssize_t aw883xx_fade_step_store(struct device *dev,
2059*4882a593Smuzhiyun struct device_attribute *attr, const char *buf, size_t count)
2060*4882a593Smuzhiyun {
2061*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2062*4882a593Smuzhiyun unsigned int databuf = 0;
2063*4882a593Smuzhiyun
2064*4882a593Smuzhiyun if (1 == sscanf(buf, "%d", &databuf)) {
2065*4882a593Smuzhiyun if (databuf > (aw883xx->aw_pa->volume_desc.mute_volume)) {
2066*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "step overflow %d Db", databuf);
2067*4882a593Smuzhiyun return count;
2068*4882a593Smuzhiyun }
2069*4882a593Smuzhiyun aw_dev_set_fade_vol_step(aw883xx->aw_pa, databuf);
2070*4882a593Smuzhiyun }
2071*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "set step %d DB Done", databuf);
2072*4882a593Smuzhiyun
2073*4882a593Smuzhiyun return count;
2074*4882a593Smuzhiyun }
2075*4882a593Smuzhiyun
aw883xx_fade_step_show(struct device * dev,struct device_attribute * attr,char * buf)2076*4882a593Smuzhiyun static ssize_t aw883xx_fade_step_show(struct device *dev,
2077*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2078*4882a593Smuzhiyun {
2079*4882a593Smuzhiyun ssize_t len = 0;
2080*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2081*4882a593Smuzhiyun
2082*4882a593Smuzhiyun len += snprintf(buf+len, PAGE_SIZE-len,
2083*4882a593Smuzhiyun "step: %d \n", aw_dev_get_fade_vol_step(aw883xx->aw_pa));
2084*4882a593Smuzhiyun
2085*4882a593Smuzhiyun return len;
2086*4882a593Smuzhiyun }
2087*4882a593Smuzhiyun
aw883xx_dbg_prof_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2088*4882a593Smuzhiyun static ssize_t aw883xx_dbg_prof_store(struct device *dev,
2089*4882a593Smuzhiyun struct device_attribute *attr, const char *buf, size_t count)
2090*4882a593Smuzhiyun {
2091*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2092*4882a593Smuzhiyun unsigned int databuf = 0;
2093*4882a593Smuzhiyun
2094*4882a593Smuzhiyun if (1 == sscanf(buf, "%d", &databuf)) {
2095*4882a593Smuzhiyun if (databuf)
2096*4882a593Smuzhiyun aw883xx->dbg_en_prof = true;
2097*4882a593Smuzhiyun else
2098*4882a593Smuzhiyun aw883xx->dbg_en_prof = false;
2099*4882a593Smuzhiyun }
2100*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "en_prof %d Done", databuf);
2101*4882a593Smuzhiyun
2102*4882a593Smuzhiyun return count;
2103*4882a593Smuzhiyun }
2104*4882a593Smuzhiyun
aw883xx_dbg_prof_show(struct device * dev,struct device_attribute * attr,char * buf)2105*4882a593Smuzhiyun static ssize_t aw883xx_dbg_prof_show(struct device *dev,
2106*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2107*4882a593Smuzhiyun {
2108*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2109*4882a593Smuzhiyun ssize_t len = 0;
2110*4882a593Smuzhiyun
2111*4882a593Smuzhiyun len += snprintf(buf+len, PAGE_SIZE-len,
2112*4882a593Smuzhiyun " %d\n", aw883xx->dbg_en_prof);
2113*4882a593Smuzhiyun
2114*4882a593Smuzhiyun return len;
2115*4882a593Smuzhiyun }
2116*4882a593Smuzhiyun
aw883xx_spk_temp_show(struct device * dev,struct device_attribute * attr,char * buf)2117*4882a593Smuzhiyun static ssize_t aw883xx_spk_temp_show(struct device *dev,
2118*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2119*4882a593Smuzhiyun {
2120*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2121*4882a593Smuzhiyun ssize_t len = 0;
2122*4882a593Smuzhiyun int ret;
2123*4882a593Smuzhiyun int32_t te;
2124*4882a593Smuzhiyun
2125*4882a593Smuzhiyun ret = aw_cali_svc_get_dev_te(&aw883xx->aw_pa->cali_desc, &te);
2126*4882a593Smuzhiyun if (ret < 0)
2127*4882a593Smuzhiyun return ret;
2128*4882a593Smuzhiyun
2129*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len,
2130*4882a593Smuzhiyun "Temp:%d\n", te);
2131*4882a593Smuzhiyun
2132*4882a593Smuzhiyun return len;
2133*4882a593Smuzhiyun }
2134*4882a593Smuzhiyun
aw883xx_sync_flag_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2135*4882a593Smuzhiyun static ssize_t aw883xx_sync_flag_store(struct device *dev,
2136*4882a593Smuzhiyun struct device_attribute *attr,
2137*4882a593Smuzhiyun const char *buf, size_t count)
2138*4882a593Smuzhiyun {
2139*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2140*4882a593Smuzhiyun unsigned int flag = 0;
2141*4882a593Smuzhiyun int ret;
2142*4882a593Smuzhiyun
2143*4882a593Smuzhiyun ret = kstrtouint(buf, 0, &flag);
2144*4882a593Smuzhiyun if (ret < 0)
2145*4882a593Smuzhiyun return ret;
2146*4882a593Smuzhiyun
2147*4882a593Smuzhiyun flag = ((flag == false) ? false : true);
2148*4882a593Smuzhiyun
2149*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "set phase sync flag : [%d]", flag);
2150*4882a593Smuzhiyun
2151*4882a593Smuzhiyun aw883xx->phase_sync = flag;
2152*4882a593Smuzhiyun
2153*4882a593Smuzhiyun return count;
2154*4882a593Smuzhiyun }
2155*4882a593Smuzhiyun
aw883xx_sync_flag_show(struct device * dev,struct device_attribute * attr,char * buf)2156*4882a593Smuzhiyun static ssize_t aw883xx_sync_flag_show(struct device *dev,
2157*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2158*4882a593Smuzhiyun {
2159*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2160*4882a593Smuzhiyun ssize_t len = 0;
2161*4882a593Smuzhiyun
2162*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len,
2163*4882a593Smuzhiyun "sync flag : %d\n", aw883xx->phase_sync);
2164*4882a593Smuzhiyun
2165*4882a593Smuzhiyun return len;
2166*4882a593Smuzhiyun }
2167*4882a593Smuzhiyun
aw883xx_fade_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2168*4882a593Smuzhiyun static ssize_t aw883xx_fade_enable_store(struct device *dev,
2169*4882a593Smuzhiyun struct device_attribute *attr, const char *buf, size_t count)
2170*4882a593Smuzhiyun {
2171*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2172*4882a593Smuzhiyun uint32_t fade_en = 0;
2173*4882a593Smuzhiyun
2174*4882a593Smuzhiyun if (1 == sscanf(buf, "%u", &fade_en))
2175*4882a593Smuzhiyun aw883xx->aw_pa->fade_en = fade_en;
2176*4882a593Smuzhiyun
2177*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "set fade_en %d", aw883xx->aw_pa->fade_en);
2178*4882a593Smuzhiyun
2179*4882a593Smuzhiyun return count;
2180*4882a593Smuzhiyun }
2181*4882a593Smuzhiyun
aw883xx_fade_enable_show(struct device * dev,struct device_attribute * attr,char * buf)2182*4882a593Smuzhiyun static ssize_t aw883xx_fade_enable_show(struct device *dev,
2183*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2184*4882a593Smuzhiyun {
2185*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2186*4882a593Smuzhiyun ssize_t len = 0;
2187*4882a593Smuzhiyun
2188*4882a593Smuzhiyun len += snprintf(buf+len, PAGE_SIZE-len,
2189*4882a593Smuzhiyun "fade_en: %d\n", aw883xx->aw_pa->fade_en);
2190*4882a593Smuzhiyun
2191*4882a593Smuzhiyun return len;
2192*4882a593Smuzhiyun }
2193*4882a593Smuzhiyun
aw883xx_dsp_re_show(struct device * dev,struct device_attribute * attr,char * buf)2194*4882a593Smuzhiyun static ssize_t aw883xx_dsp_re_show(struct device *dev,
2195*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2196*4882a593Smuzhiyun {
2197*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2198*4882a593Smuzhiyun ssize_t len = 0;
2199*4882a593Smuzhiyun int ret;
2200*4882a593Smuzhiyun uint32_t read_re = 0;
2201*4882a593Smuzhiyun
2202*4882a593Smuzhiyun ret = aw_cali_read_cali_re_from_dsp(&aw883xx->aw_pa->cali_desc, &read_re);
2203*4882a593Smuzhiyun if (ret < 0) {
2204*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "%s:read dsp re fail\n", __func__);
2205*4882a593Smuzhiyun return ret;
2206*4882a593Smuzhiyun }
2207*4882a593Smuzhiyun
2208*4882a593Smuzhiyun len += snprintf((char *)(buf + len),
2209*4882a593Smuzhiyun PAGE_SIZE - len,
2210*4882a593Smuzhiyun "dsp_re: %d\n", read_re);
2211*4882a593Smuzhiyun
2212*4882a593Smuzhiyun return len;
2213*4882a593Smuzhiyun }
2214*4882a593Smuzhiyun
aw883xx_log_en_show(struct device * dev,struct device_attribute * attr,char * buf)2215*4882a593Smuzhiyun static ssize_t aw883xx_log_en_show(struct device *dev,
2216*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2217*4882a593Smuzhiyun {
2218*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2219*4882a593Smuzhiyun ssize_t len = 0;
2220*4882a593Smuzhiyun
2221*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len, "i2c_log_en: %d\n",
2222*4882a593Smuzhiyun aw883xx->i2c_log_en);
2223*4882a593Smuzhiyun
2224*4882a593Smuzhiyun return len;
2225*4882a593Smuzhiyun }
2226*4882a593Smuzhiyun
aw883xx_log_en_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2227*4882a593Smuzhiyun static ssize_t aw883xx_log_en_store(struct device *dev,
2228*4882a593Smuzhiyun struct device_attribute *attr, const char *buf, size_t count)
2229*4882a593Smuzhiyun {
2230*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2231*4882a593Smuzhiyun uint32_t log_en = 0;
2232*4882a593Smuzhiyun
2233*4882a593Smuzhiyun if (1 == sscanf(buf, "%u", &log_en))
2234*4882a593Smuzhiyun aw883xx->i2c_log_en = log_en;
2235*4882a593Smuzhiyun
2236*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "set i2c_log_en: %d",
2237*4882a593Smuzhiyun aw883xx->i2c_log_en);
2238*4882a593Smuzhiyun
2239*4882a593Smuzhiyun return count;
2240*4882a593Smuzhiyun }
2241*4882a593Smuzhiyun
aw883xx_dsp_log_info(struct aw883xx * aw883xx,unsigned int base_addr,uint32_t data_len,char * format)2242*4882a593Smuzhiyun static int aw883xx_dsp_log_info(struct aw883xx *aw883xx, unsigned int base_addr,
2243*4882a593Smuzhiyun uint32_t data_len, char *format)
2244*4882a593Smuzhiyun {
2245*4882a593Smuzhiyun uint16_t reg_val = 0;
2246*4882a593Smuzhiyun char *dsp_reg_info = NULL;
2247*4882a593Smuzhiyun ssize_t dsp_info_len = 0;
2248*4882a593Smuzhiyun int i;
2249*4882a593Smuzhiyun
2250*4882a593Smuzhiyun dsp_reg_info = devm_kzalloc(aw883xx->dev, AW_NAME_BUF_MAX, GFP_KERNEL);
2251*4882a593Smuzhiyun if (dsp_reg_info == NULL) {
2252*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "dsp_reg_info kzalloc failed");
2253*4882a593Smuzhiyun return -ENOMEM;
2254*4882a593Smuzhiyun }
2255*4882a593Smuzhiyun
2256*4882a593Smuzhiyun mutex_lock(&aw883xx->i2c_lock);
2257*4882a593Smuzhiyun aw883xx_i2c_write(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_madd_reg, base_addr);
2258*4882a593Smuzhiyun
2259*4882a593Smuzhiyun for (i = 0; i < data_len; i += 2) {
2260*4882a593Smuzhiyun aw883xx_i2c_read(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_mdat_reg, ®_val);
2261*4882a593Smuzhiyun dsp_info_len += snprintf(dsp_reg_info + dsp_info_len, AW_NAME_BUF_MAX - dsp_info_len,
2262*4882a593Smuzhiyun "%02x,%02x,", (reg_val >> 0) & 0xff,
2263*4882a593Smuzhiyun (reg_val >> 8) & 0xff);
2264*4882a593Smuzhiyun if ((i / 2 + 1) % 8 == 0) {
2265*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "%s: %s", format, dsp_reg_info);
2266*4882a593Smuzhiyun dsp_info_len = 0;
2267*4882a593Smuzhiyun memset(dsp_reg_info, 0, AW_NAME_BUF_MAX);
2268*4882a593Smuzhiyun }
2269*4882a593Smuzhiyun
2270*4882a593Smuzhiyun if (((data_len) % 8 != 0) &&
2271*4882a593Smuzhiyun (i == (data_len - 2))) {
2272*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "%s: %s", format, dsp_reg_info);
2273*4882a593Smuzhiyun dsp_info_len = 0;
2274*4882a593Smuzhiyun memset(dsp_reg_info, 0, AW_NAME_BUF_MAX);
2275*4882a593Smuzhiyun }
2276*4882a593Smuzhiyun }
2277*4882a593Smuzhiyun
2278*4882a593Smuzhiyun memset(dsp_reg_info, 0, AW_NAME_BUF_MAX);
2279*4882a593Smuzhiyun devm_kfree(aw883xx->dev, dsp_reg_info);
2280*4882a593Smuzhiyun dsp_reg_info = NULL;
2281*4882a593Smuzhiyun mutex_unlock(&aw883xx->i2c_lock);
2282*4882a593Smuzhiyun
2283*4882a593Smuzhiyun return 0;
2284*4882a593Smuzhiyun }
2285*4882a593Smuzhiyun
aw883xx_dsp_show(struct device * dev,struct device_attribute * attr,char * buf)2286*4882a593Smuzhiyun static ssize_t aw883xx_dsp_show(struct device *dev,
2287*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2288*4882a593Smuzhiyun {
2289*4882a593Smuzhiyun struct aw883xx *aw883xx = dev_get_drvdata(dev);
2290*4882a593Smuzhiyun ssize_t len = 0;
2291*4882a593Smuzhiyun int ret = -1;
2292*4882a593Smuzhiyun uint32_t data_len;
2293*4882a593Smuzhiyun
2294*4882a593Smuzhiyun if (aw883xx->aw_pa->dsp_cfg == AW_DEV_DSP_BYPASS) {
2295*4882a593Smuzhiyun len += snprintf((char *)(buf + len), PAGE_SIZE - len,
2296*4882a593Smuzhiyun "%s: dsp bypass\n", __func__);
2297*4882a593Smuzhiyun } else {
2298*4882a593Smuzhiyun len += snprintf((char *)(buf + len), PAGE_SIZE - len,
2299*4882a593Smuzhiyun "%s: dsp working\n", __func__);
2300*4882a593Smuzhiyun ret = aw_dev_get_iis_status(aw883xx->aw_pa);
2301*4882a593Smuzhiyun if (ret < 0) {
2302*4882a593Smuzhiyun len += snprintf((char *)(buf + len),
2303*4882a593Smuzhiyun PAGE_SIZE - len,
2304*4882a593Smuzhiyun "%s: no iis signal\n",
2305*4882a593Smuzhiyun __func__);
2306*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "no iis signal, dsp show failed");
2307*4882a593Smuzhiyun return len;
2308*4882a593Smuzhiyun }
2309*4882a593Smuzhiyun
2310*4882a593Smuzhiyun len += snprintf(buf + len, PAGE_SIZE - len,
2311*4882a593Smuzhiyun "dsp firmware and config info is displayed in the kernel log\n");
2312*4882a593Smuzhiyun
2313*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "dsp_firmware_len:%d", aw883xx->aw_pa->dsp_fw_len);
2314*4882a593Smuzhiyun ret = aw883xx_dsp_log_info(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_fw_base_addr,
2315*4882a593Smuzhiyun aw883xx->aw_pa->dsp_fw_len, "dsp_fw");
2316*4882a593Smuzhiyun if (ret < 0) {
2317*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "dsp_fw display failed");
2318*4882a593Smuzhiyun return len;
2319*4882a593Smuzhiyun }
2320*4882a593Smuzhiyun
2321*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "dsp_config_len:%d", aw883xx->aw_pa->dsp_cfg_len);
2322*4882a593Smuzhiyun ret = aw883xx_dsp_log_info(aw883xx, aw883xx->aw_pa->dsp_mem_desc.dsp_cfg_base_addr,
2323*4882a593Smuzhiyun aw883xx->aw_pa->dsp_cfg_len, "dsp_config");
2324*4882a593Smuzhiyun if (ret < 0) {
2325*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "dsp_config display failed");
2326*4882a593Smuzhiyun return len;
2327*4882a593Smuzhiyun }
2328*4882a593Smuzhiyun
2329*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "dsp_config:0x8180-0x83fc");
2330*4882a593Smuzhiyun data_len = 2 * (aw883xx->aw_pa->dsp_st_desc.dsp_reg_e1 -
2331*4882a593Smuzhiyun aw883xx->aw_pa->dsp_st_desc.dsp_reg_s1);
2332*4882a593Smuzhiyun ret = aw883xx_dsp_log_info(aw883xx, aw883xx->aw_pa->dsp_st_desc.dsp_reg_s1,
2333*4882a593Smuzhiyun data_len, "dsp_st");
2334*4882a593Smuzhiyun if (ret < 0) {
2335*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "dsp_config:0x8180-0x83fc failed");
2336*4882a593Smuzhiyun return len;
2337*4882a593Smuzhiyun }
2338*4882a593Smuzhiyun
2339*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "dsp_config:0x9c00-0x9c5c");
2340*4882a593Smuzhiyun data_len = 2 * (aw883xx->aw_pa->dsp_st_desc.dsp_reg_e2 -
2341*4882a593Smuzhiyun aw883xx->aw_pa->dsp_st_desc.dsp_reg_s2);
2342*4882a593Smuzhiyun ret = aw883xx_dsp_log_info(aw883xx, aw883xx->aw_pa->dsp_st_desc.dsp_reg_s2,
2343*4882a593Smuzhiyun data_len, "dsp_st");
2344*4882a593Smuzhiyun if (ret < 0) {
2345*4882a593Smuzhiyun aw_dev_err(aw883xx->dev, "dsp_config:0x9c00-0x9c5c display failed");
2346*4882a593Smuzhiyun return len;
2347*4882a593Smuzhiyun }
2348*4882a593Smuzhiyun }
2349*4882a593Smuzhiyun return len;
2350*4882a593Smuzhiyun }
2351*4882a593Smuzhiyun
2352*4882a593Smuzhiyun static DEVICE_ATTR(reg, S_IWUSR | S_IRUGO,
2353*4882a593Smuzhiyun aw883xx_reg_show, aw883xx_reg_store);
2354*4882a593Smuzhiyun static DEVICE_ATTR(rw, S_IWUSR | S_IRUGO,
2355*4882a593Smuzhiyun aw883xx_rw_show, aw883xx_rw_store);
2356*4882a593Smuzhiyun static DEVICE_ATTR(drv_ver, S_IRUGO,
2357*4882a593Smuzhiyun aw883xx_drv_ver_show, NULL);
2358*4882a593Smuzhiyun static DEVICE_ATTR(dsp_rw, S_IWUSR | S_IRUGO,
2359*4882a593Smuzhiyun aw883xx_dsp_rw_show, aw883xx_dsp_rw_store);
2360*4882a593Smuzhiyun static DEVICE_ATTR(awrw, S_IWUSR | S_IRUGO,
2361*4882a593Smuzhiyun aw883xx_awrw_show, aw883xx_awrw_store);
2362*4882a593Smuzhiyun static DEVICE_ATTR(fade_step, S_IWUSR | S_IRUGO,
2363*4882a593Smuzhiyun aw883xx_fade_step_show, aw883xx_fade_step_store);
2364*4882a593Smuzhiyun static DEVICE_ATTR(dbg_prof, S_IWUSR | S_IRUGO,
2365*4882a593Smuzhiyun aw883xx_dbg_prof_show, aw883xx_dbg_prof_store);
2366*4882a593Smuzhiyun static DEVICE_ATTR(spk_temp, S_IRUGO,
2367*4882a593Smuzhiyun aw883xx_spk_temp_show, NULL);
2368*4882a593Smuzhiyun static DEVICE_ATTR(phase_sync, S_IWUSR | S_IRUGO,
2369*4882a593Smuzhiyun aw883xx_sync_flag_show, aw883xx_sync_flag_store);
2370*4882a593Smuzhiyun static DEVICE_ATTR(fade_en, S_IWUSR | S_IRUGO,
2371*4882a593Smuzhiyun aw883xx_fade_enable_show, aw883xx_fade_enable_store);
2372*4882a593Smuzhiyun static DEVICE_ATTR(dsp_re, S_IRUGO,
2373*4882a593Smuzhiyun aw883xx_dsp_re_show, NULL);
2374*4882a593Smuzhiyun static DEVICE_ATTR(i2c_log_en, S_IWUSR | S_IRUGO,
2375*4882a593Smuzhiyun aw883xx_log_en_show, aw883xx_log_en_store);
2376*4882a593Smuzhiyun static DEVICE_ATTR(dsp, S_IRUGO,
2377*4882a593Smuzhiyun aw883xx_dsp_show, NULL);
2378*4882a593Smuzhiyun
2379*4882a593Smuzhiyun
2380*4882a593Smuzhiyun static struct attribute *aw883xx_attributes[] = {
2381*4882a593Smuzhiyun &dev_attr_reg.attr,
2382*4882a593Smuzhiyun &dev_attr_rw.attr,
2383*4882a593Smuzhiyun &dev_attr_drv_ver.attr,
2384*4882a593Smuzhiyun &dev_attr_dsp_rw.attr,
2385*4882a593Smuzhiyun &dev_attr_awrw.attr,
2386*4882a593Smuzhiyun &dev_attr_fade_step.attr,
2387*4882a593Smuzhiyun &dev_attr_dbg_prof.attr,
2388*4882a593Smuzhiyun &dev_attr_spk_temp.attr,
2389*4882a593Smuzhiyun &dev_attr_phase_sync.attr,
2390*4882a593Smuzhiyun &dev_attr_fade_en.attr,
2391*4882a593Smuzhiyun &dev_attr_dsp_re.attr,
2392*4882a593Smuzhiyun &dev_attr_i2c_log_en.attr,
2393*4882a593Smuzhiyun &dev_attr_dsp.attr,
2394*4882a593Smuzhiyun NULL
2395*4882a593Smuzhiyun };
2396*4882a593Smuzhiyun
2397*4882a593Smuzhiyun static struct attribute_group aw883xx_attribute_group = {
2398*4882a593Smuzhiyun .attrs = aw883xx_attributes
2399*4882a593Smuzhiyun };
2400*4882a593Smuzhiyun
2401*4882a593Smuzhiyun
2402*4882a593Smuzhiyun
2403*4882a593Smuzhiyun /******************************************************
2404*4882a593Smuzhiyun *
2405*4882a593Smuzhiyun * i2c driver
2406*4882a593Smuzhiyun *
2407*4882a593Smuzhiyun ******************************************************/
aw883xx_i2c_probe(struct i2c_client * i2c,const struct i2c_device_id * id)2408*4882a593Smuzhiyun static int aw883xx_i2c_probe(struct i2c_client *i2c,
2409*4882a593Smuzhiyun const struct i2c_device_id *id)
2410*4882a593Smuzhiyun {
2411*4882a593Smuzhiyun struct aw883xx *aw883xx = NULL;
2412*4882a593Smuzhiyun int ret = -1;
2413*4882a593Smuzhiyun
2414*4882a593Smuzhiyun aw_dev_info(&i2c->dev, "enter");
2415*4882a593Smuzhiyun
2416*4882a593Smuzhiyun if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
2417*4882a593Smuzhiyun aw_dev_err(&i2c->dev, "check_functionality failed");
2418*4882a593Smuzhiyun return -EIO;
2419*4882a593Smuzhiyun }
2420*4882a593Smuzhiyun
2421*4882a593Smuzhiyun aw883xx = aw883xx_malloc_init(i2c);
2422*4882a593Smuzhiyun if (aw883xx == NULL) {
2423*4882a593Smuzhiyun aw_dev_err(&i2c->dev, "malloc aw883xx failed");
2424*4882a593Smuzhiyun return -ENOMEM;
2425*4882a593Smuzhiyun }
2426*4882a593Smuzhiyun i2c_set_clientdata(i2c, aw883xx);
2427*4882a593Smuzhiyun
2428*4882a593Smuzhiyun ret = aw883xx_parse_dt(aw883xx);
2429*4882a593Smuzhiyun if (ret < 0) {
2430*4882a593Smuzhiyun aw_dev_err(&i2c->dev, "parse dts failed");
2431*4882a593Smuzhiyun return ret;
2432*4882a593Smuzhiyun }
2433*4882a593Smuzhiyun
2434*4882a593Smuzhiyun /*get gpio resource*/
2435*4882a593Smuzhiyun ret = aw883xx_gpio_request(aw883xx);
2436*4882a593Smuzhiyun if (ret)
2437*4882a593Smuzhiyun return ret;
2438*4882a593Smuzhiyun
2439*4882a593Smuzhiyun /* hardware reset */
2440*4882a593Smuzhiyun aw883xx_hw_reset(aw883xx);
2441*4882a593Smuzhiyun
2442*4882a593Smuzhiyun /* aw883xx chip id */
2443*4882a593Smuzhiyun ret = aw883xx_read_chipid(aw883xx);
2444*4882a593Smuzhiyun if (ret < 0) {
2445*4882a593Smuzhiyun aw_dev_err(&i2c->dev, "aw883xx_read_chipid failed ret=%d", ret);
2446*4882a593Smuzhiyun return ret;
2447*4882a593Smuzhiyun }
2448*4882a593Smuzhiyun
2449*4882a593Smuzhiyun /*aw pa init*/
2450*4882a593Smuzhiyun ret = aw883xx_init(aw883xx);
2451*4882a593Smuzhiyun if (ret < 0)
2452*4882a593Smuzhiyun return ret;
2453*4882a593Smuzhiyun
2454*4882a593Smuzhiyun ret = aw883xx_platform_init(aw883xx);
2455*4882a593Smuzhiyun if (ret < 0) {
2456*4882a593Smuzhiyun aw_dev_err(&i2c->dev, "get platform failed");
2457*4882a593Smuzhiyun return ret;
2458*4882a593Smuzhiyun }
2459*4882a593Smuzhiyun
2460*4882a593Smuzhiyun ret = aw883xx_interrupt_init(aw883xx);
2461*4882a593Smuzhiyun if (ret < 0)
2462*4882a593Smuzhiyun return ret;
2463*4882a593Smuzhiyun
2464*4882a593Smuzhiyun ret = aw883xx_componet_codec_register(aw883xx);
2465*4882a593Smuzhiyun if (ret) {
2466*4882a593Smuzhiyun aw_dev_err(&i2c->dev, "codec register failed");
2467*4882a593Smuzhiyun return ret;
2468*4882a593Smuzhiyun }
2469*4882a593Smuzhiyun
2470*4882a593Smuzhiyun ret = sysfs_create_group(&i2c->dev.kobj, &aw883xx_attribute_group);
2471*4882a593Smuzhiyun if (ret < 0) {
2472*4882a593Smuzhiyun aw_dev_info(&i2c->dev, "error creating sysfs attr files");
2473*4882a593Smuzhiyun goto err_sysfs;
2474*4882a593Smuzhiyun }
2475*4882a593Smuzhiyun
2476*4882a593Smuzhiyun dev_set_drvdata(&i2c->dev, aw883xx);
2477*4882a593Smuzhiyun
2478*4882a593Smuzhiyun /*add device to total list*/
2479*4882a593Smuzhiyun mutex_lock(&g_aw883xx_lock);
2480*4882a593Smuzhiyun g_aw883xx_dev_cnt++;
2481*4882a593Smuzhiyun mutex_unlock(&g_aw883xx_lock);
2482*4882a593Smuzhiyun
2483*4882a593Smuzhiyun aw_dev_info(&i2c->dev, "dev_cnt %d probe completed successfully",
2484*4882a593Smuzhiyun g_aw883xx_dev_cnt);
2485*4882a593Smuzhiyun
2486*4882a593Smuzhiyun return 0;
2487*4882a593Smuzhiyun
2488*4882a593Smuzhiyun
2489*4882a593Smuzhiyun err_sysfs:
2490*4882a593Smuzhiyun aw_componet_codec_ops.unregister_codec(&i2c->dev);
2491*4882a593Smuzhiyun return ret;
2492*4882a593Smuzhiyun }
2493*4882a593Smuzhiyun
aw883xx_i2c_remove(struct i2c_client * i2c)2494*4882a593Smuzhiyun static int aw883xx_i2c_remove(struct i2c_client *i2c)
2495*4882a593Smuzhiyun {
2496*4882a593Smuzhiyun struct aw883xx *aw883xx = i2c_get_clientdata(i2c);
2497*4882a593Smuzhiyun
2498*4882a593Smuzhiyun aw_dev_info(aw883xx->dev, "enter");
2499*4882a593Smuzhiyun
2500*4882a593Smuzhiyun if (gpio_to_irq(aw883xx->irq_gpio))
2501*4882a593Smuzhiyun devm_free_irq(&i2c->dev,
2502*4882a593Smuzhiyun gpio_to_irq(aw883xx->irq_gpio),
2503*4882a593Smuzhiyun aw883xx);
2504*4882a593Smuzhiyun
2505*4882a593Smuzhiyun if (gpio_is_valid(aw883xx->irq_gpio))
2506*4882a593Smuzhiyun devm_gpio_free(&i2c->dev, aw883xx->irq_gpio);
2507*4882a593Smuzhiyun if (gpio_is_valid(aw883xx->reset_gpio))
2508*4882a593Smuzhiyun devm_gpio_free(&i2c->dev, aw883xx->reset_gpio);
2509*4882a593Smuzhiyun
2510*4882a593Smuzhiyun sysfs_remove_group(&aw883xx->dev->kobj,
2511*4882a593Smuzhiyun &aw883xx_attribute_group);
2512*4882a593Smuzhiyun
2513*4882a593Smuzhiyun /*free device resource */
2514*4882a593Smuzhiyun aw_device_remove(aw883xx->aw_pa);
2515*4882a593Smuzhiyun
2516*4882a593Smuzhiyun aw_componet_codec_ops.unregister_codec(&i2c->dev);
2517*4882a593Smuzhiyun
2518*4882a593Smuzhiyun mutex_lock(&g_aw883xx_lock);
2519*4882a593Smuzhiyun g_aw883xx_dev_cnt--;
2520*4882a593Smuzhiyun if (g_aw883xx_dev_cnt == 0) {
2521*4882a593Smuzhiyun vfree(g_awinic_cfg);
2522*4882a593Smuzhiyun g_awinic_cfg = NULL;
2523*4882a593Smuzhiyun }
2524*4882a593Smuzhiyun mutex_unlock(&g_aw883xx_lock);
2525*4882a593Smuzhiyun
2526*4882a593Smuzhiyun return 0;
2527*4882a593Smuzhiyun }
2528*4882a593Smuzhiyun
2529*4882a593Smuzhiyun static const struct i2c_device_id aw883xx_i2c_id[] = {
2530*4882a593Smuzhiyun {AW883XX_I2C_NAME, 0},
2531*4882a593Smuzhiyun {}
2532*4882a593Smuzhiyun };
2533*4882a593Smuzhiyun
2534*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, aw883xx_i2c_id);
2535*4882a593Smuzhiyun
2536*4882a593Smuzhiyun static struct of_device_id aw883xx_dt_match[] = {
2537*4882a593Smuzhiyun {.compatible = "awinic,aw883xx_smartpa"},
2538*4882a593Smuzhiyun {},
2539*4882a593Smuzhiyun };
2540*4882a593Smuzhiyun
2541*4882a593Smuzhiyun static struct i2c_driver aw883xx_i2c_driver = {
2542*4882a593Smuzhiyun .driver = {
2543*4882a593Smuzhiyun .name = AW883XX_I2C_NAME,
2544*4882a593Smuzhiyun .owner = THIS_MODULE,
2545*4882a593Smuzhiyun .of_match_table = of_match_ptr(aw883xx_dt_match),
2546*4882a593Smuzhiyun },
2547*4882a593Smuzhiyun .probe = aw883xx_i2c_probe,
2548*4882a593Smuzhiyun .remove = aw883xx_i2c_remove,
2549*4882a593Smuzhiyun .id_table = aw883xx_i2c_id,
2550*4882a593Smuzhiyun };
2551*4882a593Smuzhiyun
aw883xx_i2c_init(void)2552*4882a593Smuzhiyun static int __init aw883xx_i2c_init(void)
2553*4882a593Smuzhiyun {
2554*4882a593Smuzhiyun int ret = -1;
2555*4882a593Smuzhiyun
2556*4882a593Smuzhiyun aw_pr_info("aw883xx driver version %s", AW883XX_DRIVER_VERSION);
2557*4882a593Smuzhiyun
2558*4882a593Smuzhiyun ret = i2c_add_driver(&aw883xx_i2c_driver);
2559*4882a593Smuzhiyun if (ret)
2560*4882a593Smuzhiyun aw_pr_err("fail to add aw883xx device into i2c");
2561*4882a593Smuzhiyun
2562*4882a593Smuzhiyun return ret;
2563*4882a593Smuzhiyun }
2564*4882a593Smuzhiyun module_init(aw883xx_i2c_init);
2565*4882a593Smuzhiyun
aw883xx_i2c_exit(void)2566*4882a593Smuzhiyun static void __exit aw883xx_i2c_exit(void)
2567*4882a593Smuzhiyun {
2568*4882a593Smuzhiyun i2c_del_driver(&aw883xx_i2c_driver);
2569*4882a593Smuzhiyun }
2570*4882a593Smuzhiyun module_exit(aw883xx_i2c_exit);
2571*4882a593Smuzhiyun
2572*4882a593Smuzhiyun MODULE_DESCRIPTION("ASoC AW883XX Smart PA Driver");
2573*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
2574*4882a593Smuzhiyun
2575