194e412c2SWeidong Wang // SPDX-License-Identifier: GPL-2.0-only
294e412c2SWeidong Wang //
394e412c2SWeidong Wang // aw88166.c -- ALSA SoC AW88166 codec support
494e412c2SWeidong Wang //
594e412c2SWeidong Wang // Copyright (c) 2025 AWINIC Technology CO., LTD
694e412c2SWeidong Wang //
794e412c2SWeidong Wang // Author: Weidong Wang <wangweidong.a@awinic.com>
894e412c2SWeidong Wang //
994e412c2SWeidong Wang
1094e412c2SWeidong Wang #include <linux/crc32.h>
1194e412c2SWeidong Wang #include <linux/firmware.h>
1294e412c2SWeidong Wang #include <linux/gpio/consumer.h>
1394e412c2SWeidong Wang #include <linux/i2c.h>
14*84dea31dSThorsten Blum #include <linux/minmax.h>
1594e412c2SWeidong Wang #include <linux/regmap.h>
1694e412c2SWeidong Wang #include <sound/soc.h>
1794e412c2SWeidong Wang #include "aw88166.h"
1894e412c2SWeidong Wang #include "aw88395/aw88395_device.h"
1994e412c2SWeidong Wang
2094e412c2SWeidong Wang struct aw88166 {
2194e412c2SWeidong Wang struct aw_device *aw_pa;
2294e412c2SWeidong Wang struct mutex lock;
2394e412c2SWeidong Wang struct gpio_desc *reset_gpio;
2494e412c2SWeidong Wang struct delayed_work start_work;
2594e412c2SWeidong Wang struct regmap *regmap;
2694e412c2SWeidong Wang struct aw_container *aw_cfg;
2794e412c2SWeidong Wang
2894e412c2SWeidong Wang unsigned int check_val;
2994e412c2SWeidong Wang unsigned int crc_init_val;
3094e412c2SWeidong Wang unsigned int vcalb_init_val;
3194e412c2SWeidong Wang unsigned int re_init_val;
3294e412c2SWeidong Wang unsigned int dither_st;
3394e412c2SWeidong Wang bool phase_sync;
3494e412c2SWeidong Wang };
3594e412c2SWeidong Wang
3694e412c2SWeidong Wang static const struct regmap_config aw88166_remap_config = {
3794e412c2SWeidong Wang .val_bits = 16,
3894e412c2SWeidong Wang .reg_bits = 8,
3994e412c2SWeidong Wang .max_register = AW88166_REG_MAX,
4094e412c2SWeidong Wang .reg_format_endian = REGMAP_ENDIAN_LITTLE,
4194e412c2SWeidong Wang .val_format_endian = REGMAP_ENDIAN_BIG,
4294e412c2SWeidong Wang };
4394e412c2SWeidong Wang
aw_dev_dsp_write_16bit(struct aw_device * aw_dev,unsigned short dsp_addr,unsigned int dsp_data)4494e412c2SWeidong Wang static int aw_dev_dsp_write_16bit(struct aw_device *aw_dev,
4594e412c2SWeidong Wang unsigned short dsp_addr, unsigned int dsp_data)
4694e412c2SWeidong Wang {
4794e412c2SWeidong Wang int ret;
4894e412c2SWeidong Wang
4994e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_DSPMADD_REG, dsp_addr);
5094e412c2SWeidong Wang if (ret) {
5194e412c2SWeidong Wang dev_err(aw_dev->dev, "%s write addr error, ret=%d", __func__, ret);
5294e412c2SWeidong Wang return ret;
5394e412c2SWeidong Wang }
5494e412c2SWeidong Wang
5594e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_DSPMDAT_REG, (u16)dsp_data);
5694e412c2SWeidong Wang if (ret) {
5794e412c2SWeidong Wang dev_err(aw_dev->dev, "%s write data error, ret=%d", __func__, ret);
5894e412c2SWeidong Wang return ret;
5994e412c2SWeidong Wang }
6094e412c2SWeidong Wang
6194e412c2SWeidong Wang return 0;
6294e412c2SWeidong Wang }
6394e412c2SWeidong Wang
aw_dev_dsp_read_16bit(struct aw_device * aw_dev,unsigned short dsp_addr,unsigned int * dsp_data)6494e412c2SWeidong Wang static int aw_dev_dsp_read_16bit(struct aw_device *aw_dev,
6594e412c2SWeidong Wang unsigned short dsp_addr, unsigned int *dsp_data)
6694e412c2SWeidong Wang {
6794e412c2SWeidong Wang unsigned int temp_data;
6894e412c2SWeidong Wang int ret;
6994e412c2SWeidong Wang
7094e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_DSPMADD_REG, dsp_addr);
7194e412c2SWeidong Wang if (ret) {
7294e412c2SWeidong Wang dev_err(aw_dev->dev, "%s write error, ret=%d", __func__, ret);
7394e412c2SWeidong Wang return ret;
7494e412c2SWeidong Wang }
7594e412c2SWeidong Wang
7694e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_DSPMDAT_REG, &temp_data);
7794e412c2SWeidong Wang if (ret) {
7894e412c2SWeidong Wang dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret);
7994e412c2SWeidong Wang return ret;
8094e412c2SWeidong Wang }
8194e412c2SWeidong Wang *dsp_data = temp_data;
8294e412c2SWeidong Wang
8394e412c2SWeidong Wang return 0;
8494e412c2SWeidong Wang }
8594e412c2SWeidong Wang
aw_dev_dsp_read_32bit(struct aw_device * aw_dev,unsigned short dsp_addr,unsigned int * dsp_data)8694e412c2SWeidong Wang static int aw_dev_dsp_read_32bit(struct aw_device *aw_dev,
8794e412c2SWeidong Wang unsigned short dsp_addr, unsigned int *dsp_data)
8894e412c2SWeidong Wang {
8994e412c2SWeidong Wang unsigned int temp_data;
9094e412c2SWeidong Wang int ret;
9194e412c2SWeidong Wang
9294e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_DSPMADD_REG, dsp_addr);
9394e412c2SWeidong Wang if (ret) {
9494e412c2SWeidong Wang dev_err(aw_dev->dev, "%s write error, ret=%d", __func__, ret);
9594e412c2SWeidong Wang return ret;
9694e412c2SWeidong Wang }
9794e412c2SWeidong Wang
9894e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_DSPMDAT_REG, &temp_data);
9994e412c2SWeidong Wang if (ret) {
10094e412c2SWeidong Wang dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret);
10194e412c2SWeidong Wang return ret;
10294e412c2SWeidong Wang }
10394e412c2SWeidong Wang *dsp_data = temp_data;
10494e412c2SWeidong Wang
10594e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_DSPMDAT_REG, &temp_data);
10694e412c2SWeidong Wang if (ret) {
10794e412c2SWeidong Wang dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret);
10894e412c2SWeidong Wang return ret;
10994e412c2SWeidong Wang }
11094e412c2SWeidong Wang *dsp_data |= (temp_data << 16);
11194e412c2SWeidong Wang
11294e412c2SWeidong Wang return 0;
11394e412c2SWeidong Wang }
11494e412c2SWeidong Wang
aw_dev_dsp_read(struct aw_device * aw_dev,unsigned short dsp_addr,unsigned int * dsp_data,unsigned char data_type)11594e412c2SWeidong Wang static int aw_dev_dsp_read(struct aw_device *aw_dev,
11694e412c2SWeidong Wang unsigned short dsp_addr, unsigned int *dsp_data, unsigned char data_type)
11794e412c2SWeidong Wang {
11894e412c2SWeidong Wang u32 reg_value;
11994e412c2SWeidong Wang int ret;
12094e412c2SWeidong Wang
12194e412c2SWeidong Wang mutex_lock(&aw_dev->dsp_lock);
12294e412c2SWeidong Wang switch (data_type) {
12394e412c2SWeidong Wang case AW88166_DSP_16_DATA:
12494e412c2SWeidong Wang ret = aw_dev_dsp_read_16bit(aw_dev, dsp_addr, dsp_data);
12594e412c2SWeidong Wang if (ret)
12694e412c2SWeidong Wang dev_err(aw_dev->dev, "read dsp_addr[0x%x] 16-bit failed", (u32)dsp_addr);
12794e412c2SWeidong Wang break;
12894e412c2SWeidong Wang case AW88166_DSP_32_DATA:
12994e412c2SWeidong Wang ret = aw_dev_dsp_read_32bit(aw_dev, dsp_addr, dsp_data);
13094e412c2SWeidong Wang if (ret)
13194e412c2SWeidong Wang dev_err(aw_dev->dev, "read dsp_addr[0x%x] 32-bit failed", (u32)dsp_addr);
13294e412c2SWeidong Wang break;
13394e412c2SWeidong Wang default:
13494e412c2SWeidong Wang dev_err(aw_dev->dev, "data type[%d] unsupported", data_type);
13594e412c2SWeidong Wang ret = -EINVAL;
13694e412c2SWeidong Wang break;
13794e412c2SWeidong Wang }
13894e412c2SWeidong Wang
13994e412c2SWeidong Wang /* clear dsp chip select state */
14094e412c2SWeidong Wang if (regmap_read(aw_dev->regmap, AW88166_ID_REG, ®_value))
14194e412c2SWeidong Wang dev_err(aw_dev->dev, "%s fail to clear chip state. ret=%d\n", __func__, ret);
14294e412c2SWeidong Wang mutex_unlock(&aw_dev->dsp_lock);
14394e412c2SWeidong Wang
14494e412c2SWeidong Wang return ret;
14594e412c2SWeidong Wang }
14694e412c2SWeidong Wang
aw_dev_pwd(struct aw_device * aw_dev,bool pwd)14794e412c2SWeidong Wang static void aw_dev_pwd(struct aw_device *aw_dev, bool pwd)
14894e412c2SWeidong Wang {
14994e412c2SWeidong Wang int ret;
15094e412c2SWeidong Wang
15194e412c2SWeidong Wang if (pwd)
15294e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG,
15394e412c2SWeidong Wang ~AW88166_PWDN_MASK, AW88166_PWDN_POWER_DOWN_VALUE);
15494e412c2SWeidong Wang else
15594e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG,
15694e412c2SWeidong Wang ~AW88166_PWDN_MASK, AW88166_PWDN_WORKING_VALUE);
15794e412c2SWeidong Wang
15894e412c2SWeidong Wang if (ret)
15994e412c2SWeidong Wang dev_dbg(aw_dev->dev, "%s failed", __func__);
16094e412c2SWeidong Wang }
16194e412c2SWeidong Wang
aw_dev_get_int_status(struct aw_device * aw_dev,unsigned short * int_status)16294e412c2SWeidong Wang static void aw_dev_get_int_status(struct aw_device *aw_dev, unsigned short *int_status)
16394e412c2SWeidong Wang {
16494e412c2SWeidong Wang unsigned int reg_val;
16594e412c2SWeidong Wang int ret;
16694e412c2SWeidong Wang
16794e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_SYSINT_REG, ®_val);
16894e412c2SWeidong Wang if (ret)
16994e412c2SWeidong Wang dev_err(aw_dev->dev, "read interrupt reg fail, ret=%d", ret);
17094e412c2SWeidong Wang else
17194e412c2SWeidong Wang *int_status = reg_val;
17294e412c2SWeidong Wang
17394e412c2SWeidong Wang dev_dbg(aw_dev->dev, "read interrupt reg=0x%04x", *int_status);
17494e412c2SWeidong Wang }
17594e412c2SWeidong Wang
aw_dev_clear_int_status(struct aw_device * aw_dev)17694e412c2SWeidong Wang static void aw_dev_clear_int_status(struct aw_device *aw_dev)
17794e412c2SWeidong Wang {
17894e412c2SWeidong Wang u16 int_status;
17994e412c2SWeidong Wang
18094e412c2SWeidong Wang /* read int status and clear */
18194e412c2SWeidong Wang aw_dev_get_int_status(aw_dev, &int_status);
18294e412c2SWeidong Wang /* make sure int status is clear */
18394e412c2SWeidong Wang aw_dev_get_int_status(aw_dev, &int_status);
18494e412c2SWeidong Wang if (int_status)
18594e412c2SWeidong Wang dev_dbg(aw_dev->dev, "int status(%d) is not cleaned.\n", int_status);
18694e412c2SWeidong Wang }
18794e412c2SWeidong Wang
aw_dev_get_iis_status(struct aw_device * aw_dev)18894e412c2SWeidong Wang static int aw_dev_get_iis_status(struct aw_device *aw_dev)
18994e412c2SWeidong Wang {
19094e412c2SWeidong Wang unsigned int reg_val;
19194e412c2SWeidong Wang int ret;
19294e412c2SWeidong Wang
19394e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_SYSST_REG, ®_val);
19494e412c2SWeidong Wang if (ret)
19594e412c2SWeidong Wang return ret;
19694e412c2SWeidong Wang if ((reg_val & AW88166_BIT_PLL_CHECK) != AW88166_BIT_PLL_CHECK) {
19794e412c2SWeidong Wang dev_err(aw_dev->dev, "check pll lock fail, reg_val:0x%04x", reg_val);
19894e412c2SWeidong Wang return -EINVAL;
19994e412c2SWeidong Wang }
20094e412c2SWeidong Wang
20194e412c2SWeidong Wang return 0;
20294e412c2SWeidong Wang }
20394e412c2SWeidong Wang
aw_dev_check_mode1_pll(struct aw_device * aw_dev)20494e412c2SWeidong Wang static int aw_dev_check_mode1_pll(struct aw_device *aw_dev)
20594e412c2SWeidong Wang {
20694e412c2SWeidong Wang int ret, i;
20794e412c2SWeidong Wang
20894e412c2SWeidong Wang for (i = 0; i < AW88166_DEV_SYSST_CHECK_MAX; i++) {
20994e412c2SWeidong Wang ret = aw_dev_get_iis_status(aw_dev);
21094e412c2SWeidong Wang if (ret) {
21194e412c2SWeidong Wang dev_err(aw_dev->dev, "mode1 iis signal check error");
21294e412c2SWeidong Wang usleep_range(AW88166_2000_US, AW88166_2000_US + 10);
21394e412c2SWeidong Wang } else {
21494e412c2SWeidong Wang return 0;
21594e412c2SWeidong Wang }
21694e412c2SWeidong Wang }
21794e412c2SWeidong Wang
21894e412c2SWeidong Wang return -EPERM;
21994e412c2SWeidong Wang }
22094e412c2SWeidong Wang
aw_dev_check_mode2_pll(struct aw_device * aw_dev)22194e412c2SWeidong Wang static int aw_dev_check_mode2_pll(struct aw_device *aw_dev)
22294e412c2SWeidong Wang {
22394e412c2SWeidong Wang unsigned int reg_val;
22494e412c2SWeidong Wang int ret, i;
22594e412c2SWeidong Wang
22694e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_PLLCTRL2_REG, ®_val);
22794e412c2SWeidong Wang if (ret)
22894e412c2SWeidong Wang return ret;
22994e412c2SWeidong Wang
23094e412c2SWeidong Wang reg_val &= (~AW88166_CCO_MUX_MASK);
23194e412c2SWeidong Wang if (reg_val == AW88166_CCO_MUX_DIVIDED_VALUE) {
23294e412c2SWeidong Wang dev_dbg(aw_dev->dev, "CCO_MUX is already divider");
23394e412c2SWeidong Wang return -EPERM;
23494e412c2SWeidong Wang }
23594e412c2SWeidong Wang
23694e412c2SWeidong Wang /* change mode2 */
23794e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_PLLCTRL2_REG,
23894e412c2SWeidong Wang ~AW88166_CCO_MUX_MASK, AW88166_CCO_MUX_DIVIDED_VALUE);
23994e412c2SWeidong Wang if (ret)
24094e412c2SWeidong Wang return ret;
24194e412c2SWeidong Wang
24294e412c2SWeidong Wang for (i = 0; i < AW88166_DEV_SYSST_CHECK_MAX; i++) {
24394e412c2SWeidong Wang ret = aw_dev_get_iis_status(aw_dev);
24494e412c2SWeidong Wang if (ret) {
24594e412c2SWeidong Wang dev_err(aw_dev->dev, "mode2 iis signal check error");
24694e412c2SWeidong Wang usleep_range(AW88166_2000_US, AW88166_2000_US + 10);
24794e412c2SWeidong Wang } else {
24894e412c2SWeidong Wang break;
24994e412c2SWeidong Wang }
25094e412c2SWeidong Wang }
25194e412c2SWeidong Wang
25294e412c2SWeidong Wang /* change mode1 */
25394e412c2SWeidong Wang regmap_update_bits(aw_dev->regmap, AW88166_PLLCTRL2_REG,
25494e412c2SWeidong Wang ~AW88166_CCO_MUX_MASK, AW88166_CCO_MUX_BYPASS_VALUE);
25594e412c2SWeidong Wang if (ret == 0) {
25694e412c2SWeidong Wang usleep_range(AW88166_2000_US, AW88166_2000_US + 10);
25794e412c2SWeidong Wang for (i = 0; i < AW88166_DEV_SYSST_CHECK_MAX; i++) {
25894e412c2SWeidong Wang ret = aw_dev_get_iis_status(aw_dev);
25994e412c2SWeidong Wang if (ret) {
26094e412c2SWeidong Wang dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error");
26194e412c2SWeidong Wang usleep_range(AW88166_2000_US, AW88166_2000_US + 10);
26294e412c2SWeidong Wang } else {
26394e412c2SWeidong Wang break;
26494e412c2SWeidong Wang }
26594e412c2SWeidong Wang }
26694e412c2SWeidong Wang }
26794e412c2SWeidong Wang
26894e412c2SWeidong Wang return ret;
26994e412c2SWeidong Wang }
27094e412c2SWeidong Wang
aw_dev_check_syspll(struct aw_device * aw_dev)27194e412c2SWeidong Wang static int aw_dev_check_syspll(struct aw_device *aw_dev)
27294e412c2SWeidong Wang {
27394e412c2SWeidong Wang int ret;
27494e412c2SWeidong Wang
27594e412c2SWeidong Wang ret = aw_dev_check_mode1_pll(aw_dev);
27694e412c2SWeidong Wang if (ret) {
27794e412c2SWeidong Wang dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check");
27894e412c2SWeidong Wang ret = aw_dev_check_mode2_pll(aw_dev);
27994e412c2SWeidong Wang if (ret) {
28094e412c2SWeidong Wang dev_err(aw_dev->dev, "mode2 check iis failed");
28194e412c2SWeidong Wang return ret;
28294e412c2SWeidong Wang }
28394e412c2SWeidong Wang }
28494e412c2SWeidong Wang
28594e412c2SWeidong Wang return 0;
28694e412c2SWeidong Wang }
28794e412c2SWeidong Wang
aw_dev_check_sysst(struct aw_device * aw_dev)28894e412c2SWeidong Wang static int aw_dev_check_sysst(struct aw_device *aw_dev)
28994e412c2SWeidong Wang {
29094e412c2SWeidong Wang unsigned int check_val;
29194e412c2SWeidong Wang unsigned int reg_val;
29294e412c2SWeidong Wang int ret, i;
29394e412c2SWeidong Wang
29494e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_PWMCTRL3_REG, ®_val);
29594e412c2SWeidong Wang if (ret)
29694e412c2SWeidong Wang return ret;
29794e412c2SWeidong Wang
29894e412c2SWeidong Wang if (reg_val & (~AW88166_NOISE_GATE_EN_MASK))
29994e412c2SWeidong Wang check_val = AW88166_BIT_SYSST_NOSWS_CHECK;
30094e412c2SWeidong Wang else
30194e412c2SWeidong Wang check_val = AW88166_BIT_SYSST_SWS_CHECK;
30294e412c2SWeidong Wang
30394e412c2SWeidong Wang for (i = 0; i < AW88166_DEV_SYSST_CHECK_MAX; i++) {
30494e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_SYSST_REG, ®_val);
30594e412c2SWeidong Wang if (ret)
30694e412c2SWeidong Wang return ret;
30794e412c2SWeidong Wang
30894e412c2SWeidong Wang if ((reg_val & (~AW88166_BIT_SYSST_CHECK_MASK) & check_val) != check_val) {
30994e412c2SWeidong Wang dev_err(aw_dev->dev, "check sysst fail, cnt=%d, reg_val=0x%04x, check:0x%x",
31094e412c2SWeidong Wang i, reg_val, AW88166_BIT_SYSST_NOSWS_CHECK);
31194e412c2SWeidong Wang usleep_range(AW88166_2000_US, AW88166_2000_US + 10);
31294e412c2SWeidong Wang } else {
31394e412c2SWeidong Wang return 0;
31494e412c2SWeidong Wang }
31594e412c2SWeidong Wang }
31694e412c2SWeidong Wang
31794e412c2SWeidong Wang return -EPERM;
31894e412c2SWeidong Wang }
31994e412c2SWeidong Wang
aw_dev_amppd(struct aw_device * aw_dev,bool amppd)32094e412c2SWeidong Wang static void aw_dev_amppd(struct aw_device *aw_dev, bool amppd)
32194e412c2SWeidong Wang {
32294e412c2SWeidong Wang int ret;
32394e412c2SWeidong Wang
32494e412c2SWeidong Wang if (amppd)
32594e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG,
32694e412c2SWeidong Wang ~AW88166_AMPPD_MASK, AW88166_AMPPD_POWER_DOWN_VALUE);
32794e412c2SWeidong Wang else
32894e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG,
32994e412c2SWeidong Wang ~AW88166_AMPPD_MASK, AW88166_AMPPD_WORKING_VALUE);
33094e412c2SWeidong Wang
33194e412c2SWeidong Wang if (ret)
33294e412c2SWeidong Wang dev_dbg(aw_dev->dev, "%s failed", __func__);
33394e412c2SWeidong Wang }
33494e412c2SWeidong Wang
aw_dev_dsp_enable(struct aw_device * aw_dev,bool is_enable)33594e412c2SWeidong Wang static void aw_dev_dsp_enable(struct aw_device *aw_dev, bool is_enable)
33694e412c2SWeidong Wang {
33794e412c2SWeidong Wang int ret;
33894e412c2SWeidong Wang
33994e412c2SWeidong Wang if (is_enable)
34094e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG,
34194e412c2SWeidong Wang ~AW88166_DSPBY_MASK, AW88166_DSPBY_WORKING_VALUE);
34294e412c2SWeidong Wang else
34394e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG,
34494e412c2SWeidong Wang ~AW88166_DSPBY_MASK, AW88166_DSPBY_BYPASS_VALUE);
34594e412c2SWeidong Wang
34694e412c2SWeidong Wang if (ret)
34794e412c2SWeidong Wang dev_dbg(aw_dev->dev, "%s failed\n", __func__);
34894e412c2SWeidong Wang }
34994e412c2SWeidong Wang
aw88166_dev_get_icalk(struct aw88166 * aw88166,int16_t * icalk)35094e412c2SWeidong Wang static int aw88166_dev_get_icalk(struct aw88166 *aw88166, int16_t *icalk)
35194e412c2SWeidong Wang {
35294e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
35394e412c2SWeidong Wang unsigned int efrm_reg_val, efrl_reg_val;
35494e412c2SWeidong Wang uint16_t ef_isn_geslp, ef_isn_h5bits;
35594e412c2SWeidong Wang uint16_t icalk_val;
35694e412c2SWeidong Wang int ret;
35794e412c2SWeidong Wang
35894e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_EFRM2_REG, &efrm_reg_val);
35994e412c2SWeidong Wang if (ret)
36094e412c2SWeidong Wang return ret;
36194e412c2SWeidong Wang
36294e412c2SWeidong Wang ef_isn_geslp = (efrm_reg_val & (~AW88166_EF_ISN_GESLP_MASK)) >>
36394e412c2SWeidong Wang AW88166_EF_ISN_GESLP_SHIFT;
36494e412c2SWeidong Wang
36594e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_EFRL_REG, &efrl_reg_val);
36694e412c2SWeidong Wang if (ret)
36794e412c2SWeidong Wang return ret;
36894e412c2SWeidong Wang
36994e412c2SWeidong Wang ef_isn_h5bits = (efrl_reg_val & (~AW88166_EF_ISN_H5BITS_MASK)) >>
37094e412c2SWeidong Wang AW88166_EF_ISN_H5BITS_SHIFT;
37194e412c2SWeidong Wang
37294e412c2SWeidong Wang if (aw88166->check_val == AW_EF_AND_CHECK)
37394e412c2SWeidong Wang icalk_val = ef_isn_geslp & (ef_isn_h5bits | AW88166_EF_ISN_H5BITS_SIGN_MASK);
37494e412c2SWeidong Wang else
37594e412c2SWeidong Wang icalk_val = ef_isn_geslp | (ef_isn_h5bits & (~AW88166_EF_ISN_H5BITS_SIGN_MASK));
37694e412c2SWeidong Wang
37794e412c2SWeidong Wang if (icalk_val & (~AW88166_ICALK_SIGN_MASK))
37894e412c2SWeidong Wang icalk_val = icalk_val | AW88166_ICALK_NEG_MASK;
37994e412c2SWeidong Wang *icalk = (int16_t)icalk_val;
38094e412c2SWeidong Wang
38194e412c2SWeidong Wang return 0;
38294e412c2SWeidong Wang }
38394e412c2SWeidong Wang
aw88166_dev_get_vcalk(struct aw88166 * aw88166,int16_t * vcalk)38494e412c2SWeidong Wang static int aw88166_dev_get_vcalk(struct aw88166 *aw88166, int16_t *vcalk)
38594e412c2SWeidong Wang {
38694e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
38794e412c2SWeidong Wang unsigned int efrm_reg_val, efrl_reg_val;
38894e412c2SWeidong Wang uint16_t ef_vsn_geslp, ef_vsn_h3bits;
38994e412c2SWeidong Wang uint16_t vcalk_val;
39094e412c2SWeidong Wang int ret;
39194e412c2SWeidong Wang
39294e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_EFRM2_REG, &efrm_reg_val);
39394e412c2SWeidong Wang if (ret)
39494e412c2SWeidong Wang return ret;
39594e412c2SWeidong Wang
39694e412c2SWeidong Wang ef_vsn_geslp = (efrm_reg_val & (~AW88166_EF_VSN_GESLP_MASK)) >>
39794e412c2SWeidong Wang AW88166_EF_VSN_GESLP_SHIFT;
39894e412c2SWeidong Wang
39994e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_EFRL_REG, &efrl_reg_val);
40094e412c2SWeidong Wang if (ret)
40194e412c2SWeidong Wang return ret;
40294e412c2SWeidong Wang
40394e412c2SWeidong Wang ef_vsn_h3bits = (efrl_reg_val & (~AW88166_EF_VSN_H3BITS_MASK)) >>
40494e412c2SWeidong Wang AW88166_EF_VSN_H3BITS_SHIFT;
40594e412c2SWeidong Wang
40694e412c2SWeidong Wang if (aw88166->check_val == AW_EF_AND_CHECK)
40794e412c2SWeidong Wang vcalk_val = ef_vsn_geslp & (ef_vsn_h3bits | AW88166_EF_VSN_H3BITS_SIGN_MASK);
40894e412c2SWeidong Wang else
40994e412c2SWeidong Wang vcalk_val = ef_vsn_geslp | (ef_vsn_h3bits & (~AW88166_EF_VSN_H3BITS_SIGN_MASK));
41094e412c2SWeidong Wang
41194e412c2SWeidong Wang if (vcalk_val & (~AW88166_VCALK_SIGN_MASK))
41294e412c2SWeidong Wang vcalk_val = vcalk_val | AW88166_VCALK_NEG_MASK;
41394e412c2SWeidong Wang *vcalk = (int16_t)vcalk_val;
41494e412c2SWeidong Wang
41594e412c2SWeidong Wang return 0;
41694e412c2SWeidong Wang }
41794e412c2SWeidong Wang
aw88166_dev_set_vcalb(struct aw88166 * aw88166)41894e412c2SWeidong Wang static int aw88166_dev_set_vcalb(struct aw88166 *aw88166)
41994e412c2SWeidong Wang {
42094e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
42194e412c2SWeidong Wang int32_t ical_k, vcal_k, vcalb;
42294e412c2SWeidong Wang int16_t icalk, vcalk;
42394e412c2SWeidong Wang unsigned int reg_val;
42494e412c2SWeidong Wang int ret;
42594e412c2SWeidong Wang
42694e412c2SWeidong Wang ret = aw88166_dev_get_icalk(aw88166, &icalk);
42794e412c2SWeidong Wang if (ret) {
42894e412c2SWeidong Wang dev_err(aw_dev->dev, "get icalk failed\n");
42994e412c2SWeidong Wang return ret;
43094e412c2SWeidong Wang }
43194e412c2SWeidong Wang ical_k = icalk * AW88166_ICABLK_FACTOR + AW88166_CABL_BASE_VALUE;
43294e412c2SWeidong Wang
43394e412c2SWeidong Wang ret = aw88166_dev_get_vcalk(aw88166, &vcalk);
43494e412c2SWeidong Wang if (ret) {
43594e412c2SWeidong Wang dev_err(aw_dev->dev, "get vbcalk failed\n");
43694e412c2SWeidong Wang return ret;
43794e412c2SWeidong Wang }
43894e412c2SWeidong Wang vcal_k = vcalk * AW88166_VCABLK_FACTOR + AW88166_CABL_BASE_VALUE;
43994e412c2SWeidong Wang
44094e412c2SWeidong Wang vcalb = AW88166_VCALB_ACCURACY * AW88166_VSCAL_FACTOR /
44194e412c2SWeidong Wang AW88166_ISCAL_FACTOR * ical_k / vcal_k * aw88166->vcalb_init_val;
44294e412c2SWeidong Wang
44394e412c2SWeidong Wang vcalb = vcalb >> AW88166_VCALB_ADJ_FACTOR;
44494e412c2SWeidong Wang reg_val = (uint32_t)vcalb;
44594e412c2SWeidong Wang
44694e412c2SWeidong Wang regmap_write(aw_dev->regmap, AW88166_DSPVCALB_REG, reg_val);
44794e412c2SWeidong Wang
44894e412c2SWeidong Wang return 0;
44994e412c2SWeidong Wang }
45094e412c2SWeidong Wang
aw_dev_init_vcalb_update(struct aw88166 * aw88166,int flag)45194e412c2SWeidong Wang static int aw_dev_init_vcalb_update(struct aw88166 *aw88166, int flag)
45294e412c2SWeidong Wang {
45394e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
45494e412c2SWeidong Wang int ret;
45594e412c2SWeidong Wang
45694e412c2SWeidong Wang switch (flag) {
45794e412c2SWeidong Wang case AW88166_RECOVERY_SEC_DATA:
45894e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_DSPVCALB_REG, aw88166->vcalb_init_val);
45994e412c2SWeidong Wang break;
46094e412c2SWeidong Wang case AW88166_RECORD_SEC_DATA:
46194e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_DSPVCALB_REG, &aw88166->vcalb_init_val);
46294e412c2SWeidong Wang break;
46394e412c2SWeidong Wang default:
46494e412c2SWeidong Wang dev_err(aw_dev->dev, "unsupported type:%d\n", flag);
46594e412c2SWeidong Wang ret = -EINVAL;
46694e412c2SWeidong Wang break;
46794e412c2SWeidong Wang }
46894e412c2SWeidong Wang
46994e412c2SWeidong Wang return ret;
47094e412c2SWeidong Wang }
47194e412c2SWeidong Wang
aw_dev_init_re_update(struct aw88166 * aw88166,int flag)47294e412c2SWeidong Wang static int aw_dev_init_re_update(struct aw88166 *aw88166, int flag)
47394e412c2SWeidong Wang {
47494e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
47594e412c2SWeidong Wang unsigned int re_temp_h, re_temp_l;
47694e412c2SWeidong Wang int ret;
47794e412c2SWeidong Wang
47894e412c2SWeidong Wang switch (flag) {
47994e412c2SWeidong Wang case AW88166_RECOVERY_SEC_DATA:
48094e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_ACR1_REG, aw88166->re_init_val >> 16);
48194e412c2SWeidong Wang if (ret)
48294e412c2SWeidong Wang return ret;
48394e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_ACR2_REG,
48494e412c2SWeidong Wang (uint16_t)aw88166->re_init_val);
48594e412c2SWeidong Wang if (ret)
48694e412c2SWeidong Wang return ret;
48794e412c2SWeidong Wang break;
48894e412c2SWeidong Wang case AW88166_RECORD_SEC_DATA:
48994e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_ACR1_REG, &re_temp_h);
49094e412c2SWeidong Wang if (ret)
49194e412c2SWeidong Wang return ret;
49294e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_ACR2_REG, &re_temp_l);
49394e412c2SWeidong Wang if (ret)
49494e412c2SWeidong Wang return ret;
49594e412c2SWeidong Wang aw88166->re_init_val = (re_temp_h << 16) + re_temp_l;
49694e412c2SWeidong Wang break;
49794e412c2SWeidong Wang default:
49894e412c2SWeidong Wang dev_err(aw_dev->dev, "unsupported type:%d\n", flag);
49994e412c2SWeidong Wang ret = -EINVAL;
50094e412c2SWeidong Wang break;
50194e412c2SWeidong Wang }
50294e412c2SWeidong Wang
50394e412c2SWeidong Wang return ret;
50494e412c2SWeidong Wang }
50594e412c2SWeidong Wang
aw_dev_backup_sec_record(struct aw88166 * aw88166)50694e412c2SWeidong Wang static void aw_dev_backup_sec_record(struct aw88166 *aw88166)
50794e412c2SWeidong Wang {
50894e412c2SWeidong Wang aw_dev_init_vcalb_update(aw88166, AW88166_RECORD_SEC_DATA);
50994e412c2SWeidong Wang aw_dev_init_re_update(aw88166, AW88166_RECOVERY_SEC_DATA);
51094e412c2SWeidong Wang }
51194e412c2SWeidong Wang
aw_dev_backup_sec_recovery(struct aw88166 * aw88166)51294e412c2SWeidong Wang static void aw_dev_backup_sec_recovery(struct aw88166 *aw88166)
51394e412c2SWeidong Wang {
51494e412c2SWeidong Wang aw_dev_init_vcalb_update(aw88166, AW88166_RECOVERY_SEC_DATA);
51594e412c2SWeidong Wang aw_dev_init_re_update(aw88166, AW88166_RECOVERY_SEC_DATA);
51694e412c2SWeidong Wang }
51794e412c2SWeidong Wang
aw_dev_update_cali_re(struct aw_cali_desc * cali_desc)51894e412c2SWeidong Wang static int aw_dev_update_cali_re(struct aw_cali_desc *cali_desc)
51994e412c2SWeidong Wang {
52094e412c2SWeidong Wang struct aw_device *aw_dev =
52194e412c2SWeidong Wang container_of(cali_desc, struct aw_device, cali_desc);
52294e412c2SWeidong Wang uint16_t re_lbits, re_hbits;
52394e412c2SWeidong Wang u32 cali_re;
52494e412c2SWeidong Wang int ret;
52594e412c2SWeidong Wang
52694e412c2SWeidong Wang if ((aw_dev->cali_desc.cali_re >= AW88166_CALI_RE_MAX) ||
52794e412c2SWeidong Wang (aw_dev->cali_desc.cali_re <= AW88166_CALI_RE_MIN))
52894e412c2SWeidong Wang return -EINVAL;
52994e412c2SWeidong Wang
53094e412c2SWeidong Wang cali_re = AW88166_SHOW_RE_TO_DSP_RE((aw_dev->cali_desc.cali_re +
53194e412c2SWeidong Wang aw_dev->cali_desc.ra), AW88166_DSP_RE_SHIFT);
53294e412c2SWeidong Wang
53394e412c2SWeidong Wang re_hbits = (cali_re & (~AW88166_CALI_RE_HBITS_MASK)) >> AW88166_CALI_RE_HBITS_SHIFT;
53494e412c2SWeidong Wang re_lbits = (cali_re & (~AW88166_CALI_RE_LBITS_MASK)) >> AW88166_CALI_RE_LBITS_SHIFT;
53594e412c2SWeidong Wang
53694e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_ACR1_REG, re_hbits);
53794e412c2SWeidong Wang if (ret) {
53894e412c2SWeidong Wang dev_err(aw_dev->dev, "set cali re error");
53994e412c2SWeidong Wang return ret;
54094e412c2SWeidong Wang }
54194e412c2SWeidong Wang
54294e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_ACR2_REG, re_lbits);
54394e412c2SWeidong Wang if (ret)
54494e412c2SWeidong Wang dev_err(aw_dev->dev, "set cali re error");
54594e412c2SWeidong Wang
54694e412c2SWeidong Wang return ret;
54794e412c2SWeidong Wang }
54894e412c2SWeidong Wang
aw_dev_fw_crc_check(struct aw_device * aw_dev)54994e412c2SWeidong Wang static int aw_dev_fw_crc_check(struct aw_device *aw_dev)
55094e412c2SWeidong Wang {
55194e412c2SWeidong Wang uint16_t check_val, fw_len_val;
55294e412c2SWeidong Wang unsigned int reg_val;
55394e412c2SWeidong Wang int ret;
55494e412c2SWeidong Wang
55594e412c2SWeidong Wang /* calculate fw_end_addr */
55694e412c2SWeidong Wang fw_len_val = ((aw_dev->dsp_fw_len / AW_FW_ADDR_LEN) - 1) + AW88166_CRC_FW_BASE_ADDR;
55794e412c2SWeidong Wang
55894e412c2SWeidong Wang /* write fw_end_addr to crc_end_addr */
55994e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG,
56094e412c2SWeidong Wang ~AW88166_CRC_END_ADDR_MASK, fw_len_val);
56194e412c2SWeidong Wang if (ret)
56294e412c2SWeidong Wang return ret;
56394e412c2SWeidong Wang /* enable fw crc check */
56494e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG,
56594e412c2SWeidong Wang ~AW88166_CRC_CODE_EN_MASK, AW88166_CRC_CODE_EN_ENABLE_VALUE);
56694e412c2SWeidong Wang
56794e412c2SWeidong Wang usleep_range(AW88166_2000_US, AW88166_2000_US + 10);
56894e412c2SWeidong Wang
56994e412c2SWeidong Wang /* read crc check result */
57094e412c2SWeidong Wang regmap_read(aw_dev->regmap, AW88166_HAGCST_REG, ®_val);
57194e412c2SWeidong Wang if (ret)
57294e412c2SWeidong Wang return ret;
57394e412c2SWeidong Wang
57494e412c2SWeidong Wang check_val = (reg_val & (~AW88166_CRC_CHECK_BITS_MASK)) >> AW88166_CRC_CHECK_START_BIT;
57594e412c2SWeidong Wang
57694e412c2SWeidong Wang /* disable fw crc check */
57794e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG,
57894e412c2SWeidong Wang ~AW88166_CRC_CODE_EN_MASK, AW88166_CRC_CODE_EN_DISABLE_VALUE);
57994e412c2SWeidong Wang if (ret)
58094e412c2SWeidong Wang return ret;
58194e412c2SWeidong Wang
58294e412c2SWeidong Wang if (check_val != AW88166_CRC_CHECK_PASS_VAL) {
58394e412c2SWeidong Wang dev_err(aw_dev->dev, "%s failed, check_val 0x%x != 0x%x\n",
58494e412c2SWeidong Wang __func__, check_val, AW88166_CRC_CHECK_PASS_VAL);
58594e412c2SWeidong Wang ret = -EINVAL;
58694e412c2SWeidong Wang }
58794e412c2SWeidong Wang
58894e412c2SWeidong Wang return ret;
58994e412c2SWeidong Wang }
59094e412c2SWeidong Wang
aw_dev_cfg_crc_check(struct aw_device * aw_dev)59194e412c2SWeidong Wang static int aw_dev_cfg_crc_check(struct aw_device *aw_dev)
59294e412c2SWeidong Wang {
59394e412c2SWeidong Wang uint16_t check_val, cfg_len_val;
59494e412c2SWeidong Wang unsigned int reg_val;
59594e412c2SWeidong Wang int ret;
59694e412c2SWeidong Wang
59794e412c2SWeidong Wang /* calculate cfg end addr */
59894e412c2SWeidong Wang cfg_len_val = ((aw_dev->dsp_cfg_len / AW_FW_ADDR_LEN) - 1) + AW88166_CRC_CFG_BASE_ADDR;
59994e412c2SWeidong Wang
60094e412c2SWeidong Wang /* write cfg_end_addr to crc_end_addr */
60194e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG,
60294e412c2SWeidong Wang ~AW88166_CRC_END_ADDR_MASK, cfg_len_val);
60394e412c2SWeidong Wang if (ret)
60494e412c2SWeidong Wang return ret;
60594e412c2SWeidong Wang
60694e412c2SWeidong Wang /* enable cfg crc check */
60794e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG,
60894e412c2SWeidong Wang ~AW88166_CRC_CFG_EN_MASK, AW88166_CRC_CFG_EN_ENABLE_VALUE);
60994e412c2SWeidong Wang if (ret)
61094e412c2SWeidong Wang return ret;
61194e412c2SWeidong Wang
61294e412c2SWeidong Wang usleep_range(AW88166_1000_US, AW88166_1000_US + 10);
61394e412c2SWeidong Wang
61494e412c2SWeidong Wang /* read crc check result */
61594e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_HAGCST_REG, ®_val);
61694e412c2SWeidong Wang if (ret)
61794e412c2SWeidong Wang return ret;
61894e412c2SWeidong Wang
61994e412c2SWeidong Wang check_val = (reg_val & (~AW88166_CRC_CHECK_BITS_MASK)) >> AW88166_CRC_CHECK_START_BIT;
62094e412c2SWeidong Wang
62194e412c2SWeidong Wang /* disable cfg crc check */
62294e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG,
62394e412c2SWeidong Wang ~AW88166_CRC_CFG_EN_MASK, AW88166_CRC_CFG_EN_DISABLE_VALUE);
62494e412c2SWeidong Wang if (ret)
62594e412c2SWeidong Wang return ret;
62694e412c2SWeidong Wang
62794e412c2SWeidong Wang if (check_val != AW88166_CRC_CHECK_PASS_VAL) {
62894e412c2SWeidong Wang dev_err(aw_dev->dev, "crc_check failed, check val 0x%x != 0x%x\n",
62994e412c2SWeidong Wang check_val, AW88166_CRC_CHECK_PASS_VAL);
63094e412c2SWeidong Wang ret = -EINVAL;
63194e412c2SWeidong Wang }
63294e412c2SWeidong Wang
63394e412c2SWeidong Wang return ret;
63494e412c2SWeidong Wang }
63594e412c2SWeidong Wang
aw_dev_hw_crc_check(struct aw88166 * aw88166)63694e412c2SWeidong Wang static int aw_dev_hw_crc_check(struct aw88166 *aw88166)
63794e412c2SWeidong Wang {
63894e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
63994e412c2SWeidong Wang int ret;
64094e412c2SWeidong Wang
64194e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_I2SCFG1_REG,
64294e412c2SWeidong Wang ~AW88166_RAM_CG_BYP_MASK, AW88166_RAM_CG_BYP_BYPASS_VALUE);
64394e412c2SWeidong Wang if (ret)
64494e412c2SWeidong Wang return ret;
64594e412c2SWeidong Wang
64694e412c2SWeidong Wang ret = aw_dev_fw_crc_check(aw_dev);
64794e412c2SWeidong Wang if (ret) {
64894e412c2SWeidong Wang dev_err(aw_dev->dev, "fw_crc_check failed\n");
64994e412c2SWeidong Wang goto crc_check_failed;
65094e412c2SWeidong Wang }
65194e412c2SWeidong Wang
65294e412c2SWeidong Wang ret = aw_dev_cfg_crc_check(aw_dev);
65394e412c2SWeidong Wang if (ret) {
65494e412c2SWeidong Wang dev_err(aw_dev->dev, "cfg_crc_check failed\n");
65594e412c2SWeidong Wang goto crc_check_failed;
65694e412c2SWeidong Wang }
65794e412c2SWeidong Wang
65894e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_CRCCTRL_REG, aw88166->crc_init_val);
65994e412c2SWeidong Wang if (ret)
66094e412c2SWeidong Wang return ret;
66194e412c2SWeidong Wang
66294e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_I2SCFG1_REG,
66394e412c2SWeidong Wang ~AW88166_RAM_CG_BYP_MASK, AW88166_RAM_CG_BYP_WORK_VALUE);
66494e412c2SWeidong Wang
66594e412c2SWeidong Wang return ret;
66694e412c2SWeidong Wang
66794e412c2SWeidong Wang crc_check_failed:
66894e412c2SWeidong Wang regmap_update_bits(aw_dev->regmap, AW88166_I2SCFG1_REG,
66994e412c2SWeidong Wang ~AW88166_RAM_CG_BYP_MASK, AW88166_RAM_CG_BYP_WORK_VALUE);
67094e412c2SWeidong Wang return ret;
67194e412c2SWeidong Wang }
67294e412c2SWeidong Wang
aw_dev_i2s_tx_enable(struct aw_device * aw_dev,bool flag)67394e412c2SWeidong Wang static void aw_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag)
67494e412c2SWeidong Wang {
67594e412c2SWeidong Wang int ret;
67694e412c2SWeidong Wang
67794e412c2SWeidong Wang if (flag)
67894e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_I2SCTRL3_REG,
67994e412c2SWeidong Wang ~AW88166_I2STXEN_MASK, AW88166_I2STXEN_ENABLE_VALUE);
68094e412c2SWeidong Wang else
68194e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_I2SCTRL3_REG,
68294e412c2SWeidong Wang ~AW88166_I2STXEN_MASK, AW88166_I2STXEN_DISABLE_VALUE);
68394e412c2SWeidong Wang
68494e412c2SWeidong Wang if (ret)
68594e412c2SWeidong Wang dev_dbg(aw_dev->dev, "%s failed", __func__);
68694e412c2SWeidong Wang }
68794e412c2SWeidong Wang
aw_dev_get_dsp_status(struct aw_device * aw_dev)68894e412c2SWeidong Wang static int aw_dev_get_dsp_status(struct aw_device *aw_dev)
68994e412c2SWeidong Wang {
69094e412c2SWeidong Wang unsigned int reg_val;
69194e412c2SWeidong Wang int ret;
69294e412c2SWeidong Wang
69394e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_WDT_REG, ®_val);
69494e412c2SWeidong Wang if (ret)
69594e412c2SWeidong Wang return ret;
69694e412c2SWeidong Wang if (!(reg_val & (~AW88166_WDT_CNT_MASK)))
69794e412c2SWeidong Wang return -EPERM;
69894e412c2SWeidong Wang
69994e412c2SWeidong Wang return 0;
70094e412c2SWeidong Wang }
70194e412c2SWeidong Wang
aw_dev_dsp_check(struct aw_device * aw_dev)70294e412c2SWeidong Wang static int aw_dev_dsp_check(struct aw_device *aw_dev)
70394e412c2SWeidong Wang {
70494e412c2SWeidong Wang int ret, i;
70594e412c2SWeidong Wang
70694e412c2SWeidong Wang switch (aw_dev->dsp_cfg) {
70794e412c2SWeidong Wang case AW88166_DEV_DSP_BYPASS:
70894e412c2SWeidong Wang dev_dbg(aw_dev->dev, "dsp bypass");
70994e412c2SWeidong Wang ret = 0;
71094e412c2SWeidong Wang break;
71194e412c2SWeidong Wang case AW88166_DEV_DSP_WORK:
71294e412c2SWeidong Wang aw_dev_dsp_enable(aw_dev, false);
71394e412c2SWeidong Wang aw_dev_dsp_enable(aw_dev, true);
71494e412c2SWeidong Wang usleep_range(AW88166_1000_US, AW88166_1000_US + 10);
71594e412c2SWeidong Wang for (i = 0; i < AW88166_DEV_DSP_CHECK_MAX; i++) {
71694e412c2SWeidong Wang ret = aw_dev_get_dsp_status(aw_dev);
71794e412c2SWeidong Wang if (ret) {
71894e412c2SWeidong Wang dev_err(aw_dev->dev, "dsp wdt status error=%d", ret);
71994e412c2SWeidong Wang usleep_range(AW88166_2000_US, AW88166_2000_US + 10);
72094e412c2SWeidong Wang }
72194e412c2SWeidong Wang }
72294e412c2SWeidong Wang break;
72394e412c2SWeidong Wang default:
72494e412c2SWeidong Wang dev_err(aw_dev->dev, "unknown dsp cfg=%d", aw_dev->dsp_cfg);
72594e412c2SWeidong Wang ret = -EINVAL;
72694e412c2SWeidong Wang break;
72794e412c2SWeidong Wang }
72894e412c2SWeidong Wang
72994e412c2SWeidong Wang return ret;
73094e412c2SWeidong Wang }
73194e412c2SWeidong Wang
aw_dev_set_volume(struct aw_device * aw_dev,unsigned int value)73294e412c2SWeidong Wang static int aw_dev_set_volume(struct aw_device *aw_dev, unsigned int value)
73394e412c2SWeidong Wang {
73494e412c2SWeidong Wang struct aw_volume_desc *vol_desc = &aw_dev->volume_desc;
73594e412c2SWeidong Wang unsigned int reg_value;
73694e412c2SWeidong Wang u16 real_value;
73794e412c2SWeidong Wang int ret;
73894e412c2SWeidong Wang
73994e412c2SWeidong Wang real_value = min((value + vol_desc->init_volume), (unsigned int)AW88166_MUTE_VOL);
74094e412c2SWeidong Wang
74194e412c2SWeidong Wang ret = regmap_read(aw_dev->regmap, AW88166_SYSCTRL2_REG, ®_value);
74294e412c2SWeidong Wang if (ret)
74394e412c2SWeidong Wang return ret;
74494e412c2SWeidong Wang
74594e412c2SWeidong Wang dev_dbg(aw_dev->dev, "value 0x%x , reg:0x%x", value, real_value);
74694e412c2SWeidong Wang
74794e412c2SWeidong Wang real_value = (real_value << AW88166_VOL_START_BIT) | (reg_value & AW88166_VOL_MASK);
74894e412c2SWeidong Wang
74994e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_SYSCTRL2_REG, real_value);
75094e412c2SWeidong Wang
75194e412c2SWeidong Wang return ret;
75294e412c2SWeidong Wang }
75394e412c2SWeidong Wang
aw_dev_fade_in(struct aw_device * aw_dev)75494e412c2SWeidong Wang static void aw_dev_fade_in(struct aw_device *aw_dev)
75594e412c2SWeidong Wang {
75694e412c2SWeidong Wang struct aw_volume_desc *desc = &aw_dev->volume_desc;
75794e412c2SWeidong Wang u16 fade_in_vol = desc->ctl_volume;
75894e412c2SWeidong Wang int fade_step = aw_dev->fade_step;
75994e412c2SWeidong Wang int i;
76094e412c2SWeidong Wang
76194e412c2SWeidong Wang if (fade_step == 0 || aw_dev->fade_in_time == 0) {
76294e412c2SWeidong Wang aw_dev_set_volume(aw_dev, fade_in_vol);
76394e412c2SWeidong Wang return;
76494e412c2SWeidong Wang }
76594e412c2SWeidong Wang
76694e412c2SWeidong Wang for (i = AW88166_MUTE_VOL; i >= fade_in_vol; i -= fade_step) {
76794e412c2SWeidong Wang aw_dev_set_volume(aw_dev, i);
76894e412c2SWeidong Wang usleep_range(aw_dev->fade_in_time, aw_dev->fade_in_time + 10);
76994e412c2SWeidong Wang }
77094e412c2SWeidong Wang
77194e412c2SWeidong Wang if (i != fade_in_vol)
77294e412c2SWeidong Wang aw_dev_set_volume(aw_dev, fade_in_vol);
77394e412c2SWeidong Wang }
77494e412c2SWeidong Wang
aw_dev_fade_out(struct aw_device * aw_dev)77594e412c2SWeidong Wang static void aw_dev_fade_out(struct aw_device *aw_dev)
77694e412c2SWeidong Wang {
77794e412c2SWeidong Wang struct aw_volume_desc *desc = &aw_dev->volume_desc;
77894e412c2SWeidong Wang int fade_step = aw_dev->fade_step;
77994e412c2SWeidong Wang int i;
78094e412c2SWeidong Wang
78194e412c2SWeidong Wang if (fade_step == 0 || aw_dev->fade_out_time == 0) {
78294e412c2SWeidong Wang aw_dev_set_volume(aw_dev, AW88166_MUTE_VOL);
78394e412c2SWeidong Wang return;
78494e412c2SWeidong Wang }
78594e412c2SWeidong Wang
78694e412c2SWeidong Wang for (i = desc->ctl_volume; i <= AW88166_MUTE_VOL; i += fade_step) {
78794e412c2SWeidong Wang aw_dev_set_volume(aw_dev, i);
78894e412c2SWeidong Wang usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10);
78994e412c2SWeidong Wang }
79094e412c2SWeidong Wang
79194e412c2SWeidong Wang if (i != AW88166_MUTE_VOL) {
79294e412c2SWeidong Wang aw_dev_set_volume(aw_dev, AW88166_MUTE_VOL);
79394e412c2SWeidong Wang usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10);
79494e412c2SWeidong Wang }
79594e412c2SWeidong Wang }
79694e412c2SWeidong Wang
aw88166_dev_mute(struct aw_device * aw_dev,bool is_mute)79794e412c2SWeidong Wang static void aw88166_dev_mute(struct aw_device *aw_dev, bool is_mute)
79894e412c2SWeidong Wang {
79994e412c2SWeidong Wang if (is_mute) {
80094e412c2SWeidong Wang aw_dev_fade_out(aw_dev);
80194e412c2SWeidong Wang regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG,
80294e412c2SWeidong Wang ~AW88166_HMUTE_MASK, AW88166_HMUTE_ENABLE_VALUE);
80394e412c2SWeidong Wang } else {
80494e412c2SWeidong Wang regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG,
80594e412c2SWeidong Wang ~AW88166_HMUTE_MASK, AW88166_HMUTE_DISABLE_VALUE);
80694e412c2SWeidong Wang aw_dev_fade_in(aw_dev);
80794e412c2SWeidong Wang }
80894e412c2SWeidong Wang }
80994e412c2SWeidong Wang
aw88166_dev_set_dither(struct aw88166 * aw88166,bool dither)81094e412c2SWeidong Wang static void aw88166_dev_set_dither(struct aw88166 *aw88166, bool dither)
81194e412c2SWeidong Wang {
81294e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
81394e412c2SWeidong Wang
81494e412c2SWeidong Wang if (dither)
81594e412c2SWeidong Wang regmap_update_bits(aw_dev->regmap, AW88166_DBGCTRL_REG,
81694e412c2SWeidong Wang ~AW88166_DITHER_EN_MASK, AW88166_DITHER_EN_ENABLE_VALUE);
81794e412c2SWeidong Wang else
81894e412c2SWeidong Wang regmap_update_bits(aw_dev->regmap, AW88166_DBGCTRL_REG,
81994e412c2SWeidong Wang ~AW88166_DITHER_EN_MASK, AW88166_DITHER_EN_DISABLE_VALUE);
82094e412c2SWeidong Wang }
82194e412c2SWeidong Wang
aw88166_dev_start(struct aw88166 * aw88166)82294e412c2SWeidong Wang static int aw88166_dev_start(struct aw88166 *aw88166)
82394e412c2SWeidong Wang {
82494e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
82594e412c2SWeidong Wang int ret;
82694e412c2SWeidong Wang
82794e412c2SWeidong Wang if (aw_dev->status == AW88166_DEV_PW_ON) {
82894e412c2SWeidong Wang dev_dbg(aw_dev->dev, "already power on");
82994e412c2SWeidong Wang return 0;
83094e412c2SWeidong Wang }
83194e412c2SWeidong Wang
83294e412c2SWeidong Wang aw88166_dev_set_dither(aw88166, false);
83394e412c2SWeidong Wang
83494e412c2SWeidong Wang /* power on */
83594e412c2SWeidong Wang aw_dev_pwd(aw_dev, false);
83694e412c2SWeidong Wang usleep_range(AW88166_2000_US, AW88166_2000_US + 10);
83794e412c2SWeidong Wang
83894e412c2SWeidong Wang ret = aw_dev_check_syspll(aw_dev);
83994e412c2SWeidong Wang if (ret) {
84094e412c2SWeidong Wang dev_err(aw_dev->dev, "pll check failed cannot start\n");
84194e412c2SWeidong Wang goto pll_check_fail;
84294e412c2SWeidong Wang }
84394e412c2SWeidong Wang
84494e412c2SWeidong Wang /* amppd on */
84594e412c2SWeidong Wang aw_dev_amppd(aw_dev, false);
84694e412c2SWeidong Wang usleep_range(AW88166_1000_US, AW88166_1000_US + 50);
84794e412c2SWeidong Wang
84894e412c2SWeidong Wang /* check i2s status */
84994e412c2SWeidong Wang ret = aw_dev_check_sysst(aw_dev);
85094e412c2SWeidong Wang if (ret) {
85194e412c2SWeidong Wang dev_err(aw_dev->dev, "sysst check failed\n");
85294e412c2SWeidong Wang goto sysst_check_fail;
85394e412c2SWeidong Wang }
85494e412c2SWeidong Wang
85594e412c2SWeidong Wang if (aw_dev->dsp_cfg == AW88166_DEV_DSP_WORK) {
85694e412c2SWeidong Wang aw_dev_backup_sec_recovery(aw88166);
85794e412c2SWeidong Wang ret = aw_dev_hw_crc_check(aw88166);
85894e412c2SWeidong Wang if (ret) {
85994e412c2SWeidong Wang dev_err(aw_dev->dev, "dsp crc check failed\n");
86094e412c2SWeidong Wang goto crc_check_fail;
86194e412c2SWeidong Wang }
86294e412c2SWeidong Wang aw_dev_dsp_enable(aw_dev, false);
86394e412c2SWeidong Wang aw88166_dev_set_vcalb(aw88166);
86494e412c2SWeidong Wang aw_dev_update_cali_re(&aw_dev->cali_desc);
86594e412c2SWeidong Wang ret = aw_dev_dsp_check(aw_dev);
86694e412c2SWeidong Wang if (ret) {
86794e412c2SWeidong Wang dev_err(aw_dev->dev, "dsp status check failed\n");
86894e412c2SWeidong Wang goto dsp_check_fail;
86994e412c2SWeidong Wang }
87094e412c2SWeidong Wang } else {
87194e412c2SWeidong Wang dev_dbg(aw_dev->dev, "start pa with dsp bypass");
87294e412c2SWeidong Wang }
87394e412c2SWeidong Wang
87494e412c2SWeidong Wang /* enable tx feedback */
87594e412c2SWeidong Wang aw_dev_i2s_tx_enable(aw_dev, true);
87694e412c2SWeidong Wang
87794e412c2SWeidong Wang if (aw88166->dither_st == AW88166_DITHER_EN_ENABLE_VALUE)
87894e412c2SWeidong Wang aw88166_dev_set_dither(aw88166, true);
87994e412c2SWeidong Wang
88094e412c2SWeidong Wang /* close mute */
88194e412c2SWeidong Wang aw88166_dev_mute(aw_dev, false);
88294e412c2SWeidong Wang /* clear inturrupt */
88394e412c2SWeidong Wang aw_dev_clear_int_status(aw_dev);
88494e412c2SWeidong Wang aw_dev->status = AW88166_DEV_PW_ON;
88594e412c2SWeidong Wang
88694e412c2SWeidong Wang return 0;
88794e412c2SWeidong Wang
88894e412c2SWeidong Wang dsp_check_fail:
88994e412c2SWeidong Wang crc_check_fail:
89094e412c2SWeidong Wang aw_dev_dsp_enable(aw_dev, false);
89194e412c2SWeidong Wang sysst_check_fail:
89294e412c2SWeidong Wang aw_dev_clear_int_status(aw_dev);
89394e412c2SWeidong Wang aw_dev_amppd(aw_dev, true);
89494e412c2SWeidong Wang pll_check_fail:
89594e412c2SWeidong Wang aw_dev_pwd(aw_dev, true);
89694e412c2SWeidong Wang aw_dev->status = AW88166_DEV_PW_OFF;
89794e412c2SWeidong Wang
89894e412c2SWeidong Wang return ret;
89994e412c2SWeidong Wang }
90094e412c2SWeidong Wang
aw_dev_dsp_update_container(struct aw_device * aw_dev,unsigned char * data,unsigned int len,unsigned short base)90194e412c2SWeidong Wang static int aw_dev_dsp_update_container(struct aw_device *aw_dev,
90294e412c2SWeidong Wang unsigned char *data, unsigned int len, unsigned short base)
90394e412c2SWeidong Wang {
90494e412c2SWeidong Wang u32 tmp_len;
90594e412c2SWeidong Wang int i, ret;
90694e412c2SWeidong Wang
90794e412c2SWeidong Wang mutex_lock(&aw_dev->dsp_lock);
90894e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, AW88166_DSPMADD_REG, base);
90994e412c2SWeidong Wang if (ret)
91094e412c2SWeidong Wang goto error_operation;
91194e412c2SWeidong Wang
91294e412c2SWeidong Wang for (i = 0; i < len; i += AW88166_MAX_RAM_WRITE_BYTE_SIZE) {
913*84dea31dSThorsten Blum tmp_len = min(len - i, AW88166_MAX_RAM_WRITE_BYTE_SIZE);
91494e412c2SWeidong Wang ret = regmap_raw_write(aw_dev->regmap, AW88166_DSPMDAT_REG,
91594e412c2SWeidong Wang &data[i], tmp_len);
91694e412c2SWeidong Wang if (ret)
91794e412c2SWeidong Wang goto error_operation;
91894e412c2SWeidong Wang }
91994e412c2SWeidong Wang mutex_unlock(&aw_dev->dsp_lock);
92094e412c2SWeidong Wang
92194e412c2SWeidong Wang return 0;
92294e412c2SWeidong Wang
92394e412c2SWeidong Wang error_operation:
92494e412c2SWeidong Wang mutex_unlock(&aw_dev->dsp_lock);
92594e412c2SWeidong Wang return ret;
92694e412c2SWeidong Wang }
92794e412c2SWeidong Wang
aw_dev_get_ra(struct aw_cali_desc * cali_desc)92894e412c2SWeidong Wang static int aw_dev_get_ra(struct aw_cali_desc *cali_desc)
92994e412c2SWeidong Wang {
93094e412c2SWeidong Wang struct aw_device *aw_dev =
93194e412c2SWeidong Wang container_of(cali_desc, struct aw_device, cali_desc);
93294e412c2SWeidong Wang u32 dsp_ra;
93394e412c2SWeidong Wang int ret;
93494e412c2SWeidong Wang
93594e412c2SWeidong Wang ret = aw_dev_dsp_read(aw_dev, AW88166_DSP_REG_CFG_ADPZ_RA,
93694e412c2SWeidong Wang &dsp_ra, AW88166_DSP_32_DATA);
93794e412c2SWeidong Wang if (ret) {
93894e412c2SWeidong Wang dev_err(aw_dev->dev, "read ra error\n");
93994e412c2SWeidong Wang return ret;
94094e412c2SWeidong Wang }
94194e412c2SWeidong Wang
94294e412c2SWeidong Wang cali_desc->ra = AW88166_DSP_RE_TO_SHOW_RE(dsp_ra,
94394e412c2SWeidong Wang AW88166_DSP_RE_SHIFT);
94494e412c2SWeidong Wang
94594e412c2SWeidong Wang return 0;
94694e412c2SWeidong Wang }
94794e412c2SWeidong Wang
aw_dev_dsp_update_cfg(struct aw_device * aw_dev,unsigned char * data,unsigned int len)94894e412c2SWeidong Wang static int aw_dev_dsp_update_cfg(struct aw_device *aw_dev,
94994e412c2SWeidong Wang unsigned char *data, unsigned int len)
95094e412c2SWeidong Wang {
95194e412c2SWeidong Wang int ret;
95294e412c2SWeidong Wang
95394e412c2SWeidong Wang dev_dbg(aw_dev->dev, "dsp config len:%d", len);
95494e412c2SWeidong Wang
95594e412c2SWeidong Wang if (!len || !data) {
95694e412c2SWeidong Wang dev_err(aw_dev->dev, "dsp config data is null or len is 0\n");
95794e412c2SWeidong Wang return -EINVAL;
95894e412c2SWeidong Wang }
95994e412c2SWeidong Wang
96094e412c2SWeidong Wang ret = aw_dev_dsp_update_container(aw_dev, data, len, AW88166_DSP_CFG_ADDR);
96194e412c2SWeidong Wang if (ret)
96294e412c2SWeidong Wang return ret;
96394e412c2SWeidong Wang
96494e412c2SWeidong Wang aw_dev->dsp_cfg_len = len;
96594e412c2SWeidong Wang
96694e412c2SWeidong Wang ret = aw_dev_get_ra(&aw_dev->cali_desc);
96794e412c2SWeidong Wang
96894e412c2SWeidong Wang return ret;
96994e412c2SWeidong Wang }
97094e412c2SWeidong Wang
aw_dev_dsp_update_fw(struct aw_device * aw_dev,unsigned char * data,unsigned int len)97194e412c2SWeidong Wang static int aw_dev_dsp_update_fw(struct aw_device *aw_dev,
97294e412c2SWeidong Wang unsigned char *data, unsigned int len)
97394e412c2SWeidong Wang {
97494e412c2SWeidong Wang int ret;
97594e412c2SWeidong Wang
97694e412c2SWeidong Wang dev_dbg(aw_dev->dev, "dsp firmware len:%d", len);
97794e412c2SWeidong Wang
97894e412c2SWeidong Wang if (!len || !data) {
97994e412c2SWeidong Wang dev_err(aw_dev->dev, "dsp firmware data is null or len is 0\n");
98094e412c2SWeidong Wang return -EINVAL;
98194e412c2SWeidong Wang }
98294e412c2SWeidong Wang
98394e412c2SWeidong Wang aw_dev->dsp_fw_len = len;
98494e412c2SWeidong Wang ret = aw_dev_dsp_update_container(aw_dev, data, len, AW88166_DSP_FW_ADDR);
98594e412c2SWeidong Wang
98694e412c2SWeidong Wang return ret;
98794e412c2SWeidong Wang }
98894e412c2SWeidong Wang
aw_dev_check_sram(struct aw_device * aw_dev)98994e412c2SWeidong Wang static int aw_dev_check_sram(struct aw_device *aw_dev)
99094e412c2SWeidong Wang {
99194e412c2SWeidong Wang unsigned int reg_val;
99294e412c2SWeidong Wang
99394e412c2SWeidong Wang mutex_lock(&aw_dev->dsp_lock);
99494e412c2SWeidong Wang /* read dsp_rom_check_reg */
99594e412c2SWeidong Wang aw_dev_dsp_read_16bit(aw_dev, AW88166_DSP_ROM_CHECK_ADDR, ®_val);
99694e412c2SWeidong Wang if (reg_val != AW88166_DSP_ROM_CHECK_DATA) {
99794e412c2SWeidong Wang dev_err(aw_dev->dev, "check dsp rom failed, read[0x%x] != check[0x%x]\n",
99894e412c2SWeidong Wang reg_val, AW88166_DSP_ROM_CHECK_DATA);
99994e412c2SWeidong Wang goto error;
100094e412c2SWeidong Wang }
100194e412c2SWeidong Wang
100294e412c2SWeidong Wang /* check dsp_cfg_base_addr */
100394e412c2SWeidong Wang aw_dev_dsp_write_16bit(aw_dev, AW88166_DSP_CFG_ADDR, AW88166_DSP_ODD_NUM_BIT_TEST);
100494e412c2SWeidong Wang aw_dev_dsp_read_16bit(aw_dev, AW88166_DSP_CFG_ADDR, ®_val);
100594e412c2SWeidong Wang if (reg_val != AW88166_DSP_ODD_NUM_BIT_TEST) {
100694e412c2SWeidong Wang dev_err(aw_dev->dev, "check dsp cfg failed, read[0x%x] != write[0x%x]\n",
100794e412c2SWeidong Wang reg_val, AW88166_DSP_ODD_NUM_BIT_TEST);
100894e412c2SWeidong Wang goto error;
100994e412c2SWeidong Wang }
101094e412c2SWeidong Wang mutex_unlock(&aw_dev->dsp_lock);
101194e412c2SWeidong Wang
101294e412c2SWeidong Wang return 0;
101394e412c2SWeidong Wang error:
101494e412c2SWeidong Wang mutex_unlock(&aw_dev->dsp_lock);
101594e412c2SWeidong Wang return -EPERM;
101694e412c2SWeidong Wang }
101794e412c2SWeidong Wang
aw_dev_select_memclk(struct aw_device * aw_dev,unsigned char flag)101894e412c2SWeidong Wang static void aw_dev_select_memclk(struct aw_device *aw_dev, unsigned char flag)
101994e412c2SWeidong Wang {
102094e412c2SWeidong Wang int ret;
102194e412c2SWeidong Wang
102294e412c2SWeidong Wang switch (flag) {
102394e412c2SWeidong Wang case AW88166_DEV_MEMCLK_PLL:
102494e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_DBGCTRL_REG,
102594e412c2SWeidong Wang ~AW88166_MEM_CLKSEL_MASK,
102694e412c2SWeidong Wang AW88166_MEM_CLKSEL_DAPHCLK_VALUE);
102794e412c2SWeidong Wang if (ret)
102894e412c2SWeidong Wang dev_err(aw_dev->dev, "memclk select pll failed\n");
102994e412c2SWeidong Wang break;
103094e412c2SWeidong Wang case AW88166_DEV_MEMCLK_OSC:
103194e412c2SWeidong Wang ret = regmap_update_bits(aw_dev->regmap, AW88166_DBGCTRL_REG,
103294e412c2SWeidong Wang ~AW88166_MEM_CLKSEL_MASK,
103394e412c2SWeidong Wang AW88166_MEM_CLKSEL_OSCCLK_VALUE);
103494e412c2SWeidong Wang if (ret)
103594e412c2SWeidong Wang dev_err(aw_dev->dev, "memclk select OSC failed\n");
103694e412c2SWeidong Wang break;
103794e412c2SWeidong Wang default:
103894e412c2SWeidong Wang dev_err(aw_dev->dev, "unknown memclk config, flag=0x%x\n", flag);
103994e412c2SWeidong Wang break;
104094e412c2SWeidong Wang }
104194e412c2SWeidong Wang }
104294e412c2SWeidong Wang
aw_dev_update_reg_container(struct aw88166 * aw88166,unsigned char * data,unsigned int len)104394e412c2SWeidong Wang static int aw_dev_update_reg_container(struct aw88166 *aw88166,
104494e412c2SWeidong Wang unsigned char *data, unsigned int len)
104594e412c2SWeidong Wang {
104694e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
104794e412c2SWeidong Wang struct aw_volume_desc *vol_desc = &aw_dev->volume_desc;
104894e412c2SWeidong Wang u16 read_vol, reg_val;
104994e412c2SWeidong Wang int data_len, i, ret;
105094e412c2SWeidong Wang int16_t *reg_data;
105194e412c2SWeidong Wang u8 reg_addr;
105294e412c2SWeidong Wang
105394e412c2SWeidong Wang reg_data = (int16_t *)data;
105494e412c2SWeidong Wang data_len = len >> 1;
105594e412c2SWeidong Wang
105694e412c2SWeidong Wang if (data_len & 0x1) {
105794e412c2SWeidong Wang dev_err(aw_dev->dev, "data len:%d unsupported\n", data_len);
105894e412c2SWeidong Wang return -EINVAL;
105994e412c2SWeidong Wang }
106094e412c2SWeidong Wang
106194e412c2SWeidong Wang for (i = 0; i < data_len; i += 2) {
106294e412c2SWeidong Wang reg_addr = reg_data[i];
106394e412c2SWeidong Wang reg_val = reg_data[i + 1];
106494e412c2SWeidong Wang
106594e412c2SWeidong Wang if (reg_addr == AW88166_DSPVCALB_REG) {
106694e412c2SWeidong Wang aw88166->vcalb_init_val = reg_val;
106794e412c2SWeidong Wang continue;
106894e412c2SWeidong Wang }
106994e412c2SWeidong Wang
107094e412c2SWeidong Wang if (reg_addr == AW88166_SYSCTRL_REG) {
107194e412c2SWeidong Wang if (reg_val & (~AW88166_DSPBY_MASK))
107294e412c2SWeidong Wang aw_dev->dsp_cfg = AW88166_DEV_DSP_BYPASS;
107394e412c2SWeidong Wang else
107494e412c2SWeidong Wang aw_dev->dsp_cfg = AW88166_DEV_DSP_WORK;
107594e412c2SWeidong Wang
107694e412c2SWeidong Wang reg_val &= (AW88166_HMUTE_MASK | AW88166_PWDN_MASK |
107794e412c2SWeidong Wang AW88166_DSPBY_MASK);
107894e412c2SWeidong Wang reg_val |= (AW88166_HMUTE_ENABLE_VALUE | AW88166_PWDN_POWER_DOWN_VALUE |
107994e412c2SWeidong Wang AW88166_DSPBY_BYPASS_VALUE);
108094e412c2SWeidong Wang }
108194e412c2SWeidong Wang
108294e412c2SWeidong Wang if (reg_addr == AW88166_I2SCTRL3_REG) {
108394e412c2SWeidong Wang reg_val &= AW88166_I2STXEN_MASK;
108494e412c2SWeidong Wang reg_val |= AW88166_I2STXEN_DISABLE_VALUE;
108594e412c2SWeidong Wang }
108694e412c2SWeidong Wang
108794e412c2SWeidong Wang if (reg_addr == AW88166_SYSCTRL2_REG) {
108894e412c2SWeidong Wang read_vol = (reg_val & (~AW88166_VOL_MASK)) >>
108994e412c2SWeidong Wang AW88166_VOL_START_BIT;
109094e412c2SWeidong Wang aw_dev->volume_desc.init_volume = read_vol;
109194e412c2SWeidong Wang }
109294e412c2SWeidong Wang
109394e412c2SWeidong Wang if (reg_addr == AW88166_DBGCTRL_REG) {
109494e412c2SWeidong Wang if ((reg_val & (~AW88166_EF_DBMD_MASK)) == AW88166_EF_DBMD_OR_VALUE)
109594e412c2SWeidong Wang aw88166->check_val = AW_EF_OR_CHECK;
109694e412c2SWeidong Wang else
109794e412c2SWeidong Wang aw88166->check_val = AW_EF_AND_CHECK;
109894e412c2SWeidong Wang
109994e412c2SWeidong Wang aw88166->dither_st = reg_val & (~AW88166_DITHER_EN_MASK);
110094e412c2SWeidong Wang }
110194e412c2SWeidong Wang
110294e412c2SWeidong Wang if (reg_addr == AW88166_ACR1_REG) {
110394e412c2SWeidong Wang aw88166->re_init_val |= (uint32_t)reg_val << 16;
110494e412c2SWeidong Wang continue;
110594e412c2SWeidong Wang }
110694e412c2SWeidong Wang
110794e412c2SWeidong Wang if (reg_addr == AW88166_ACR2_REG) {
110894e412c2SWeidong Wang aw88166->re_init_val |= (uint32_t)reg_val;
110994e412c2SWeidong Wang continue;
111094e412c2SWeidong Wang }
111194e412c2SWeidong Wang
111294e412c2SWeidong Wang if (reg_addr == AW88166_CRCCTRL_REG)
111394e412c2SWeidong Wang aw88166->crc_init_val = reg_val;
111494e412c2SWeidong Wang
111594e412c2SWeidong Wang ret = regmap_write(aw_dev->regmap, reg_addr, reg_val);
111694e412c2SWeidong Wang if (ret)
111794e412c2SWeidong Wang return ret;
111894e412c2SWeidong Wang }
111994e412c2SWeidong Wang
112094e412c2SWeidong Wang aw_dev_pwd(aw_dev, false);
112194e412c2SWeidong Wang usleep_range(AW88166_1000_US, AW88166_1000_US + 10);
112294e412c2SWeidong Wang
112394e412c2SWeidong Wang if (aw_dev->prof_cur != aw_dev->prof_index)
112494e412c2SWeidong Wang vol_desc->ctl_volume = 0;
112594e412c2SWeidong Wang else
112694e412c2SWeidong Wang aw_dev_set_volume(aw_dev, vol_desc->ctl_volume);
112794e412c2SWeidong Wang
112894e412c2SWeidong Wang return 0;
112994e412c2SWeidong Wang }
113094e412c2SWeidong Wang
aw_dev_reg_update(struct aw88166 * aw88166,unsigned char * data,unsigned int len)113194e412c2SWeidong Wang static int aw_dev_reg_update(struct aw88166 *aw88166,
113294e412c2SWeidong Wang unsigned char *data, unsigned int len)
113394e412c2SWeidong Wang {
113494e412c2SWeidong Wang int ret;
113594e412c2SWeidong Wang
113694e412c2SWeidong Wang if (!len || !data) {
113794e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "reg data is null or len is 0\n");
113894e412c2SWeidong Wang return -EINVAL;
113994e412c2SWeidong Wang }
114094e412c2SWeidong Wang
114194e412c2SWeidong Wang ret = aw_dev_update_reg_container(aw88166, data, len);
114294e412c2SWeidong Wang if (ret)
114394e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "reg update failed\n");
114494e412c2SWeidong Wang
114594e412c2SWeidong Wang return ret;
114694e412c2SWeidong Wang }
114794e412c2SWeidong Wang
aw88166_dev_get_prof_name(struct aw_device * aw_dev,int index,char ** prof_name)114894e412c2SWeidong Wang static int aw88166_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name)
114994e412c2SWeidong Wang {
115094e412c2SWeidong Wang struct aw_prof_info *prof_info = &aw_dev->prof_info;
115194e412c2SWeidong Wang struct aw_prof_desc *prof_desc;
115294e412c2SWeidong Wang
115394e412c2SWeidong Wang if ((index >= aw_dev->prof_info.count) || (index < 0)) {
115494e412c2SWeidong Wang dev_err(aw_dev->dev, "index[%d] overflow count[%d]\n",
115594e412c2SWeidong Wang index, aw_dev->prof_info.count);
115694e412c2SWeidong Wang return -EINVAL;
115794e412c2SWeidong Wang }
115894e412c2SWeidong Wang
115994e412c2SWeidong Wang prof_desc = &aw_dev->prof_info.prof_desc[index];
116094e412c2SWeidong Wang
116194e412c2SWeidong Wang *prof_name = prof_info->prof_name_list[prof_desc->id];
116294e412c2SWeidong Wang
116394e412c2SWeidong Wang return 0;
116494e412c2SWeidong Wang }
116594e412c2SWeidong Wang
aw88166_dev_get_prof_data(struct aw_device * aw_dev,int index,struct aw_prof_desc ** prof_desc)116694e412c2SWeidong Wang static int aw88166_dev_get_prof_data(struct aw_device *aw_dev, int index,
116794e412c2SWeidong Wang struct aw_prof_desc **prof_desc)
116894e412c2SWeidong Wang {
116994e412c2SWeidong Wang if ((index >= aw_dev->prof_info.count) || (index < 0)) {
117094e412c2SWeidong Wang dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n",
117194e412c2SWeidong Wang __func__, index, aw_dev->prof_info.count);
117294e412c2SWeidong Wang return -EINVAL;
117394e412c2SWeidong Wang }
117494e412c2SWeidong Wang
117594e412c2SWeidong Wang *prof_desc = &aw_dev->prof_info.prof_desc[index];
117694e412c2SWeidong Wang
117794e412c2SWeidong Wang return 0;
117894e412c2SWeidong Wang }
117994e412c2SWeidong Wang
aw88166_dev_fw_update(struct aw88166 * aw88166,bool up_dsp_fw_en,bool force_up_en)118094e412c2SWeidong Wang static int aw88166_dev_fw_update(struct aw88166 *aw88166, bool up_dsp_fw_en, bool force_up_en)
118194e412c2SWeidong Wang {
118294e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
118394e412c2SWeidong Wang struct aw_prof_desc *prof_index_desc;
118494e412c2SWeidong Wang struct aw_sec_data_desc *sec_desc;
118594e412c2SWeidong Wang char *prof_name;
118694e412c2SWeidong Wang int ret;
118794e412c2SWeidong Wang
118894e412c2SWeidong Wang if ((aw_dev->prof_cur == aw_dev->prof_index) &&
118994e412c2SWeidong Wang (force_up_en == AW88166_FORCE_UPDATE_OFF)) {
119094e412c2SWeidong Wang dev_dbg(aw_dev->dev, "scene no change, not update");
119194e412c2SWeidong Wang return 0;
119294e412c2SWeidong Wang }
119394e412c2SWeidong Wang
119494e412c2SWeidong Wang if (aw_dev->fw_status == AW88166_DEV_FW_FAILED) {
119594e412c2SWeidong Wang dev_err(aw_dev->dev, "fw status[%d] error\n", aw_dev->fw_status);
119694e412c2SWeidong Wang return -EPERM;
119794e412c2SWeidong Wang }
119894e412c2SWeidong Wang
119994e412c2SWeidong Wang ret = aw88166_dev_get_prof_name(aw_dev, aw_dev->prof_index, &prof_name);
120094e412c2SWeidong Wang if (ret)
120194e412c2SWeidong Wang return ret;
120294e412c2SWeidong Wang
120394e412c2SWeidong Wang dev_dbg(aw_dev->dev, "start update %s", prof_name);
120494e412c2SWeidong Wang
120594e412c2SWeidong Wang ret = aw88166_dev_get_prof_data(aw_dev, aw_dev->prof_index, &prof_index_desc);
120694e412c2SWeidong Wang if (ret)
120794e412c2SWeidong Wang return ret;
120894e412c2SWeidong Wang
120994e412c2SWeidong Wang /* update reg */
121094e412c2SWeidong Wang sec_desc = prof_index_desc->sec_desc;
121194e412c2SWeidong Wang ret = aw_dev_reg_update(aw88166, sec_desc[AW88395_DATA_TYPE_REG].data,
121294e412c2SWeidong Wang sec_desc[AW88395_DATA_TYPE_REG].len);
121394e412c2SWeidong Wang if (ret) {
121494e412c2SWeidong Wang dev_err(aw_dev->dev, "update reg failed\n");
121594e412c2SWeidong Wang return ret;
121694e412c2SWeidong Wang }
121794e412c2SWeidong Wang
121894e412c2SWeidong Wang aw88166_dev_mute(aw_dev, true);
121994e412c2SWeidong Wang
122094e412c2SWeidong Wang if (aw_dev->dsp_cfg == AW88166_DEV_DSP_WORK)
122194e412c2SWeidong Wang aw_dev_dsp_enable(aw_dev, false);
122294e412c2SWeidong Wang
122394e412c2SWeidong Wang aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_OSC);
122494e412c2SWeidong Wang
122594e412c2SWeidong Wang ret = aw_dev_check_sram(aw_dev);
122694e412c2SWeidong Wang if (ret) {
122794e412c2SWeidong Wang dev_err(aw_dev->dev, "check sram failed\n");
122894e412c2SWeidong Wang goto error;
122994e412c2SWeidong Wang }
123094e412c2SWeidong Wang
123194e412c2SWeidong Wang aw_dev_backup_sec_recovery(aw88166);
123294e412c2SWeidong Wang
123394e412c2SWeidong Wang if (up_dsp_fw_en) {
123494e412c2SWeidong Wang dev_dbg(aw_dev->dev, "fw_ver: [%x]", prof_index_desc->fw_ver);
123594e412c2SWeidong Wang ret = aw_dev_dsp_update_fw(aw_dev, sec_desc[AW88395_DATA_TYPE_DSP_FW].data,
123694e412c2SWeidong Wang sec_desc[AW88395_DATA_TYPE_DSP_FW].len);
123794e412c2SWeidong Wang if (ret) {
123894e412c2SWeidong Wang dev_err(aw_dev->dev, "update dsp fw failed\n");
123994e412c2SWeidong Wang goto error;
124094e412c2SWeidong Wang }
124194e412c2SWeidong Wang }
124294e412c2SWeidong Wang
124394e412c2SWeidong Wang /* update dsp config */
124494e412c2SWeidong Wang ret = aw_dev_dsp_update_cfg(aw_dev, sec_desc[AW88395_DATA_TYPE_DSP_CFG].data,
124594e412c2SWeidong Wang sec_desc[AW88395_DATA_TYPE_DSP_CFG].len);
124694e412c2SWeidong Wang if (ret) {
124794e412c2SWeidong Wang dev_err(aw_dev->dev, "update dsp cfg failed\n");
124894e412c2SWeidong Wang goto error;
124994e412c2SWeidong Wang }
125094e412c2SWeidong Wang
125194e412c2SWeidong Wang aw_dev_backup_sec_record(aw88166);
125294e412c2SWeidong Wang
125394e412c2SWeidong Wang aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_PLL);
125494e412c2SWeidong Wang
125594e412c2SWeidong Wang aw_dev->prof_cur = aw_dev->prof_index;
125694e412c2SWeidong Wang
125794e412c2SWeidong Wang return 0;
125894e412c2SWeidong Wang
125994e412c2SWeidong Wang error:
126094e412c2SWeidong Wang aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_PLL);
126194e412c2SWeidong Wang return ret;
126294e412c2SWeidong Wang }
126394e412c2SWeidong Wang
aw88166_start_pa(struct aw88166 * aw88166)126494e412c2SWeidong Wang static void aw88166_start_pa(struct aw88166 *aw88166)
126594e412c2SWeidong Wang {
126694e412c2SWeidong Wang int ret, i;
126794e412c2SWeidong Wang
126894e412c2SWeidong Wang for (i = 0; i < AW88166_START_RETRIES; i++) {
126994e412c2SWeidong Wang ret = aw88166_dev_start(aw88166);
127094e412c2SWeidong Wang if (ret) {
127194e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "aw88166 device start failed. retry = %d", i);
127294e412c2SWeidong Wang ret = aw88166_dev_fw_update(aw88166, AW88166_DSP_FW_UPDATE_ON, true);
127394e412c2SWeidong Wang if (ret) {
127494e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "fw update failed");
127594e412c2SWeidong Wang continue;
127694e412c2SWeidong Wang }
127794e412c2SWeidong Wang } else {
127894e412c2SWeidong Wang dev_dbg(aw88166->aw_pa->dev, "start success\n");
127994e412c2SWeidong Wang break;
128094e412c2SWeidong Wang }
128194e412c2SWeidong Wang }
128294e412c2SWeidong Wang }
128394e412c2SWeidong Wang
aw88166_startup_work(struct work_struct * work)128494e412c2SWeidong Wang static void aw88166_startup_work(struct work_struct *work)
128594e412c2SWeidong Wang {
128694e412c2SWeidong Wang struct aw88166 *aw88166 =
128794e412c2SWeidong Wang container_of(work, struct aw88166, start_work.work);
128894e412c2SWeidong Wang
128994e412c2SWeidong Wang mutex_lock(&aw88166->lock);
129094e412c2SWeidong Wang aw88166_start_pa(aw88166);
129194e412c2SWeidong Wang mutex_unlock(&aw88166->lock);
129294e412c2SWeidong Wang }
129394e412c2SWeidong Wang
aw88166_start(struct aw88166 * aw88166,bool sync_start)129494e412c2SWeidong Wang static void aw88166_start(struct aw88166 *aw88166, bool sync_start)
129594e412c2SWeidong Wang {
129694e412c2SWeidong Wang int ret;
129794e412c2SWeidong Wang
129894e412c2SWeidong Wang if (aw88166->aw_pa->fw_status != AW88166_DEV_FW_OK)
129994e412c2SWeidong Wang return;
130094e412c2SWeidong Wang
130194e412c2SWeidong Wang if (aw88166->aw_pa->status == AW88166_DEV_PW_ON)
130294e412c2SWeidong Wang return;
130394e412c2SWeidong Wang
130494e412c2SWeidong Wang ret = aw88166_dev_fw_update(aw88166, AW88166_DSP_FW_UPDATE_OFF, aw88166->phase_sync);
130594e412c2SWeidong Wang if (ret) {
130694e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "fw update failed\n");
130794e412c2SWeidong Wang return;
130894e412c2SWeidong Wang }
130994e412c2SWeidong Wang
131094e412c2SWeidong Wang if (sync_start == AW88166_SYNC_START)
131194e412c2SWeidong Wang aw88166_start_pa(aw88166);
131294e412c2SWeidong Wang else
131394e412c2SWeidong Wang queue_delayed_work(system_wq,
131494e412c2SWeidong Wang &aw88166->start_work,
131594e412c2SWeidong Wang AW88166_START_WORK_DELAY_MS);
131694e412c2SWeidong Wang }
131794e412c2SWeidong Wang
aw_dev_check_sysint(struct aw_device * aw_dev)131894e412c2SWeidong Wang static int aw_dev_check_sysint(struct aw_device *aw_dev)
131994e412c2SWeidong Wang {
132094e412c2SWeidong Wang u16 reg_val;
132194e412c2SWeidong Wang
132294e412c2SWeidong Wang aw_dev_get_int_status(aw_dev, ®_val);
132394e412c2SWeidong Wang if (reg_val & AW88166_BIT_SYSINT_CHECK) {
132494e412c2SWeidong Wang dev_err(aw_dev->dev, "pa stop check fail:0x%04x\n", reg_val);
132594e412c2SWeidong Wang return -EINVAL;
132694e412c2SWeidong Wang }
132794e412c2SWeidong Wang
132894e412c2SWeidong Wang return 0;
132994e412c2SWeidong Wang }
133094e412c2SWeidong Wang
aw88166_stop(struct aw_device * aw_dev)133194e412c2SWeidong Wang static int aw88166_stop(struct aw_device *aw_dev)
133294e412c2SWeidong Wang {
133394e412c2SWeidong Wang struct aw_sec_data_desc *dsp_cfg =
133494e412c2SWeidong Wang &aw_dev->prof_info.prof_desc[aw_dev->prof_cur].sec_desc[AW88395_DATA_TYPE_DSP_CFG];
133594e412c2SWeidong Wang struct aw_sec_data_desc *dsp_fw =
133694e412c2SWeidong Wang &aw_dev->prof_info.prof_desc[aw_dev->prof_cur].sec_desc[AW88395_DATA_TYPE_DSP_FW];
133794e412c2SWeidong Wang int int_st;
133894e412c2SWeidong Wang
133994e412c2SWeidong Wang if (aw_dev->status == AW88166_DEV_PW_OFF) {
134094e412c2SWeidong Wang dev_dbg(aw_dev->dev, "already power off");
134194e412c2SWeidong Wang return 0;
134294e412c2SWeidong Wang }
134394e412c2SWeidong Wang
134494e412c2SWeidong Wang aw_dev->status = AW88166_DEV_PW_OFF;
134594e412c2SWeidong Wang
134694e412c2SWeidong Wang aw88166_dev_mute(aw_dev, true);
134794e412c2SWeidong Wang usleep_range(AW88166_4000_US, AW88166_4000_US + 100);
134894e412c2SWeidong Wang
134994e412c2SWeidong Wang aw_dev_i2s_tx_enable(aw_dev, false);
135094e412c2SWeidong Wang usleep_range(AW88166_1000_US, AW88166_1000_US + 100);
135194e412c2SWeidong Wang
135294e412c2SWeidong Wang int_st = aw_dev_check_sysint(aw_dev);
135394e412c2SWeidong Wang
135494e412c2SWeidong Wang aw_dev_dsp_enable(aw_dev, false);
135594e412c2SWeidong Wang
135694e412c2SWeidong Wang aw_dev_amppd(aw_dev, true);
135794e412c2SWeidong Wang
135894e412c2SWeidong Wang if (int_st) {
135994e412c2SWeidong Wang aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_OSC);
136094e412c2SWeidong Wang aw_dev_dsp_update_fw(aw_dev, dsp_fw->data, dsp_fw->len);
136194e412c2SWeidong Wang aw_dev_dsp_update_cfg(aw_dev, dsp_cfg->data, dsp_cfg->len);
136294e412c2SWeidong Wang aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_PLL);
136394e412c2SWeidong Wang }
136494e412c2SWeidong Wang
136594e412c2SWeidong Wang aw_dev_pwd(aw_dev, true);
136694e412c2SWeidong Wang
136794e412c2SWeidong Wang return 0;
136894e412c2SWeidong Wang }
136994e412c2SWeidong Wang
137094e412c2SWeidong Wang static struct snd_soc_dai_driver aw88166_dai[] = {
137194e412c2SWeidong Wang {
137294e412c2SWeidong Wang .name = "aw88166-aif",
137394e412c2SWeidong Wang .id = 1,
137494e412c2SWeidong Wang .playback = {
137594e412c2SWeidong Wang .stream_name = "Speaker_Playback",
137694e412c2SWeidong Wang .channels_min = 1,
137794e412c2SWeidong Wang .channels_max = 2,
137894e412c2SWeidong Wang .rates = AW88166_RATES,
137994e412c2SWeidong Wang .formats = AW88166_FORMATS,
138094e412c2SWeidong Wang },
138194e412c2SWeidong Wang .capture = {
138294e412c2SWeidong Wang .stream_name = "Speaker_Capture",
138394e412c2SWeidong Wang .channels_min = 1,
138494e412c2SWeidong Wang .channels_max = 2,
138594e412c2SWeidong Wang .rates = AW88166_RATES,
138694e412c2SWeidong Wang .formats = AW88166_FORMATS,
138794e412c2SWeidong Wang },
138894e412c2SWeidong Wang },
138994e412c2SWeidong Wang };
139094e412c2SWeidong Wang
aw88166_get_fade_in_time(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)139194e412c2SWeidong Wang static int aw88166_get_fade_in_time(struct snd_kcontrol *kcontrol,
139294e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
139394e412c2SWeidong Wang {
139494e412c2SWeidong Wang struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
139594e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component);
139694e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
139794e412c2SWeidong Wang
139894e412c2SWeidong Wang ucontrol->value.integer.value[0] = aw_dev->fade_in_time;
139994e412c2SWeidong Wang
140094e412c2SWeidong Wang return 0;
140194e412c2SWeidong Wang }
140294e412c2SWeidong Wang
aw88166_set_fade_in_time(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)140394e412c2SWeidong Wang static int aw88166_set_fade_in_time(struct snd_kcontrol *kcontrol,
140494e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
140594e412c2SWeidong Wang {
140694e412c2SWeidong Wang struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
140794e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component);
140894e412c2SWeidong Wang struct soc_mixer_control *mc =
140994e412c2SWeidong Wang (struct soc_mixer_control *)kcontrol->private_value;
141094e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
141194e412c2SWeidong Wang int time;
141294e412c2SWeidong Wang
141394e412c2SWeidong Wang time = ucontrol->value.integer.value[0];
141494e412c2SWeidong Wang
141594e412c2SWeidong Wang if (time < mc->min || time > mc->max)
141694e412c2SWeidong Wang return -EINVAL;
141794e412c2SWeidong Wang
141894e412c2SWeidong Wang if (time != aw_dev->fade_in_time) {
141994e412c2SWeidong Wang aw_dev->fade_in_time = time;
142094e412c2SWeidong Wang return 1;
142194e412c2SWeidong Wang }
142294e412c2SWeidong Wang
142394e412c2SWeidong Wang return 0;
142494e412c2SWeidong Wang }
142594e412c2SWeidong Wang
aw88166_get_fade_out_time(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)142694e412c2SWeidong Wang static int aw88166_get_fade_out_time(struct snd_kcontrol *kcontrol,
142794e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
142894e412c2SWeidong Wang {
142994e412c2SWeidong Wang struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
143094e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component);
143194e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
143294e412c2SWeidong Wang
143394e412c2SWeidong Wang ucontrol->value.integer.value[0] = aw_dev->fade_out_time;
143494e412c2SWeidong Wang
143594e412c2SWeidong Wang return 0;
143694e412c2SWeidong Wang }
143794e412c2SWeidong Wang
aw88166_set_fade_out_time(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)143894e412c2SWeidong Wang static int aw88166_set_fade_out_time(struct snd_kcontrol *kcontrol,
143994e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
144094e412c2SWeidong Wang {
144194e412c2SWeidong Wang struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
144294e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component);
144394e412c2SWeidong Wang struct soc_mixer_control *mc =
144494e412c2SWeidong Wang (struct soc_mixer_control *)kcontrol->private_value;
144594e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
144694e412c2SWeidong Wang int time;
144794e412c2SWeidong Wang
144894e412c2SWeidong Wang time = ucontrol->value.integer.value[0];
144994e412c2SWeidong Wang if (time < mc->min || time > mc->max)
145094e412c2SWeidong Wang return -EINVAL;
145194e412c2SWeidong Wang
145294e412c2SWeidong Wang if (time != aw_dev->fade_out_time) {
145394e412c2SWeidong Wang aw_dev->fade_out_time = time;
145494e412c2SWeidong Wang return 1;
145594e412c2SWeidong Wang }
145694e412c2SWeidong Wang
145794e412c2SWeidong Wang return 0;
145894e412c2SWeidong Wang }
145994e412c2SWeidong Wang
aw88166_dev_set_profile_index(struct aw_device * aw_dev,int index)146094e412c2SWeidong Wang static int aw88166_dev_set_profile_index(struct aw_device *aw_dev, int index)
146194e412c2SWeidong Wang {
146294e412c2SWeidong Wang /* check the index whether is valid */
146394e412c2SWeidong Wang if ((index >= aw_dev->prof_info.count) || (index < 0))
146494e412c2SWeidong Wang return -EINVAL;
146594e412c2SWeidong Wang /* check the index whether change */
146694e412c2SWeidong Wang if (aw_dev->prof_index == index)
146794e412c2SWeidong Wang return -EINVAL;
146894e412c2SWeidong Wang
146994e412c2SWeidong Wang aw_dev->prof_index = index;
147094e412c2SWeidong Wang dev_dbg(aw_dev->dev, "set prof[%s]",
147194e412c2SWeidong Wang aw_dev->prof_info.prof_name_list[aw_dev->prof_info.prof_desc[index].id]);
147294e412c2SWeidong Wang
147394e412c2SWeidong Wang return 0;
147494e412c2SWeidong Wang }
147594e412c2SWeidong Wang
aw88166_profile_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)147694e412c2SWeidong Wang static int aw88166_profile_info(struct snd_kcontrol *kcontrol,
147794e412c2SWeidong Wang struct snd_ctl_elem_info *uinfo)
147894e412c2SWeidong Wang {
147994e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
148094e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
148194e412c2SWeidong Wang char *prof_name, *name;
148294e412c2SWeidong Wang int count, ret;
148394e412c2SWeidong Wang
148494e412c2SWeidong Wang uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
148594e412c2SWeidong Wang uinfo->count = 1;
148694e412c2SWeidong Wang
148794e412c2SWeidong Wang count = aw88166->aw_pa->prof_info.count;
148894e412c2SWeidong Wang if (count <= 0) {
148994e412c2SWeidong Wang uinfo->value.enumerated.items = 0;
149094e412c2SWeidong Wang return 0;
149194e412c2SWeidong Wang }
149294e412c2SWeidong Wang
149394e412c2SWeidong Wang uinfo->value.enumerated.items = count;
149494e412c2SWeidong Wang
149594e412c2SWeidong Wang if (uinfo->value.enumerated.item >= count)
149694e412c2SWeidong Wang uinfo->value.enumerated.item = count - 1;
149794e412c2SWeidong Wang
149894e412c2SWeidong Wang name = uinfo->value.enumerated.name;
149994e412c2SWeidong Wang count = uinfo->value.enumerated.item;
150094e412c2SWeidong Wang
150194e412c2SWeidong Wang ret = aw88166_dev_get_prof_name(aw88166->aw_pa, count, &prof_name);
150294e412c2SWeidong Wang if (ret) {
150394e412c2SWeidong Wang strscpy(uinfo->value.enumerated.name, "null",
150494e412c2SWeidong Wang strlen("null") + 1);
150594e412c2SWeidong Wang return 0;
150694e412c2SWeidong Wang }
150794e412c2SWeidong Wang
150894e412c2SWeidong Wang strscpy(name, prof_name, sizeof(uinfo->value.enumerated.name));
150994e412c2SWeidong Wang
151094e412c2SWeidong Wang return 0;
151194e412c2SWeidong Wang }
151294e412c2SWeidong Wang
aw88166_profile_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)151394e412c2SWeidong Wang static int aw88166_profile_get(struct snd_kcontrol *kcontrol,
151494e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
151594e412c2SWeidong Wang {
151694e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
151794e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
151894e412c2SWeidong Wang
151994e412c2SWeidong Wang ucontrol->value.integer.value[0] = aw88166->aw_pa->prof_index;
152094e412c2SWeidong Wang
152194e412c2SWeidong Wang return 0;
152294e412c2SWeidong Wang }
152394e412c2SWeidong Wang
aw88166_profile_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)152494e412c2SWeidong Wang static int aw88166_profile_set(struct snd_kcontrol *kcontrol,
152594e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
152694e412c2SWeidong Wang {
152794e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
152894e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
152994e412c2SWeidong Wang int ret;
153094e412c2SWeidong Wang
153194e412c2SWeidong Wang mutex_lock(&aw88166->lock);
153294e412c2SWeidong Wang ret = aw88166_dev_set_profile_index(aw88166->aw_pa, ucontrol->value.integer.value[0]);
153394e412c2SWeidong Wang if (ret) {
153494e412c2SWeidong Wang dev_dbg(codec->dev, "profile index does not change");
153594e412c2SWeidong Wang mutex_unlock(&aw88166->lock);
153694e412c2SWeidong Wang return 0;
153794e412c2SWeidong Wang }
153894e412c2SWeidong Wang
153994e412c2SWeidong Wang if (aw88166->aw_pa->status) {
154094e412c2SWeidong Wang aw88166_stop(aw88166->aw_pa);
154194e412c2SWeidong Wang aw88166_start(aw88166, AW88166_SYNC_START);
154294e412c2SWeidong Wang }
154394e412c2SWeidong Wang
154494e412c2SWeidong Wang mutex_unlock(&aw88166->lock);
154594e412c2SWeidong Wang
154694e412c2SWeidong Wang return 1;
154794e412c2SWeidong Wang }
154894e412c2SWeidong Wang
aw88166_volume_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)154994e412c2SWeidong Wang static int aw88166_volume_get(struct snd_kcontrol *kcontrol,
155094e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
155194e412c2SWeidong Wang {
155294e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
155394e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
155494e412c2SWeidong Wang struct aw_volume_desc *vol_desc = &aw88166->aw_pa->volume_desc;
155594e412c2SWeidong Wang
155694e412c2SWeidong Wang ucontrol->value.integer.value[0] = vol_desc->ctl_volume;
155794e412c2SWeidong Wang
155894e412c2SWeidong Wang return 0;
155994e412c2SWeidong Wang }
156094e412c2SWeidong Wang
aw88166_volume_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)156194e412c2SWeidong Wang static int aw88166_volume_set(struct snd_kcontrol *kcontrol,
156294e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
156394e412c2SWeidong Wang {
156494e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
156594e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
156694e412c2SWeidong Wang struct aw_volume_desc *vol_desc = &aw88166->aw_pa->volume_desc;
156794e412c2SWeidong Wang struct soc_mixer_control *mc =
156894e412c2SWeidong Wang (struct soc_mixer_control *)kcontrol->private_value;
156994e412c2SWeidong Wang int value;
157094e412c2SWeidong Wang
157194e412c2SWeidong Wang value = ucontrol->value.integer.value[0];
157294e412c2SWeidong Wang if (value < mc->min || value > mc->max)
157394e412c2SWeidong Wang return -EINVAL;
157494e412c2SWeidong Wang
157594e412c2SWeidong Wang if (vol_desc->ctl_volume != value) {
157694e412c2SWeidong Wang vol_desc->ctl_volume = value;
157794e412c2SWeidong Wang aw_dev_set_volume(aw88166->aw_pa, vol_desc->ctl_volume);
157894e412c2SWeidong Wang
157994e412c2SWeidong Wang return 1;
158094e412c2SWeidong Wang }
158194e412c2SWeidong Wang
158294e412c2SWeidong Wang return 0;
158394e412c2SWeidong Wang }
158494e412c2SWeidong Wang
aw88166_get_fade_step(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)158594e412c2SWeidong Wang static int aw88166_get_fade_step(struct snd_kcontrol *kcontrol,
158694e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
158794e412c2SWeidong Wang {
158894e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
158994e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
159094e412c2SWeidong Wang
159194e412c2SWeidong Wang ucontrol->value.integer.value[0] = aw88166->aw_pa->fade_step;
159294e412c2SWeidong Wang
159394e412c2SWeidong Wang return 0;
159494e412c2SWeidong Wang }
159594e412c2SWeidong Wang
aw88166_set_fade_step(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)159694e412c2SWeidong Wang static int aw88166_set_fade_step(struct snd_kcontrol *kcontrol,
159794e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
159894e412c2SWeidong Wang {
159994e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
160094e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
160194e412c2SWeidong Wang struct soc_mixer_control *mc =
160294e412c2SWeidong Wang (struct soc_mixer_control *)kcontrol->private_value;
160394e412c2SWeidong Wang int value;
160494e412c2SWeidong Wang
160594e412c2SWeidong Wang value = ucontrol->value.integer.value[0];
160694e412c2SWeidong Wang if (value < mc->min || value > mc->max)
160794e412c2SWeidong Wang return -EINVAL;
160894e412c2SWeidong Wang
160994e412c2SWeidong Wang if (aw88166->aw_pa->fade_step != value) {
161094e412c2SWeidong Wang aw88166->aw_pa->fade_step = value;
161194e412c2SWeidong Wang return 1;
161294e412c2SWeidong Wang }
161394e412c2SWeidong Wang
161494e412c2SWeidong Wang return 0;
161594e412c2SWeidong Wang }
161694e412c2SWeidong Wang
aw88166_re_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)161794e412c2SWeidong Wang static int aw88166_re_get(struct snd_kcontrol *kcontrol,
161894e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
161994e412c2SWeidong Wang {
162094e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
162194e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
162294e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
162394e412c2SWeidong Wang
162494e412c2SWeidong Wang ucontrol->value.integer.value[0] = aw_dev->cali_desc.cali_re;
162594e412c2SWeidong Wang
162694e412c2SWeidong Wang return 0;
162794e412c2SWeidong Wang }
162894e412c2SWeidong Wang
aw88166_re_set(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)162994e412c2SWeidong Wang static int aw88166_re_set(struct snd_kcontrol *kcontrol,
163094e412c2SWeidong Wang struct snd_ctl_elem_value *ucontrol)
163194e412c2SWeidong Wang {
163294e412c2SWeidong Wang struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
163394e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec);
163494e412c2SWeidong Wang struct soc_mixer_control *mc =
163594e412c2SWeidong Wang (struct soc_mixer_control *)kcontrol->private_value;
163694e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
163794e412c2SWeidong Wang int value;
163894e412c2SWeidong Wang
163994e412c2SWeidong Wang value = ucontrol->value.integer.value[0];
164094e412c2SWeidong Wang if (value < mc->min || value > mc->max)
164194e412c2SWeidong Wang return -EINVAL;
164294e412c2SWeidong Wang
164394e412c2SWeidong Wang if (aw_dev->cali_desc.cali_re != value) {
164494e412c2SWeidong Wang aw_dev->cali_desc.cali_re = value;
164594e412c2SWeidong Wang return 1;
164694e412c2SWeidong Wang }
164794e412c2SWeidong Wang
164894e412c2SWeidong Wang return 0;
164994e412c2SWeidong Wang }
165094e412c2SWeidong Wang
aw88166_dev_init(struct aw88166 * aw88166,struct aw_container * aw_cfg)165194e412c2SWeidong Wang static int aw88166_dev_init(struct aw88166 *aw88166, struct aw_container *aw_cfg)
165294e412c2SWeidong Wang {
165394e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
165494e412c2SWeidong Wang int ret;
165594e412c2SWeidong Wang
165694e412c2SWeidong Wang ret = aw88395_dev_cfg_load(aw_dev, aw_cfg);
165794e412c2SWeidong Wang if (ret) {
165894e412c2SWeidong Wang dev_err(aw_dev->dev, "aw_dev acf parse failed\n");
165994e412c2SWeidong Wang return -EINVAL;
166094e412c2SWeidong Wang }
166194e412c2SWeidong Wang aw_dev->fade_in_time = AW88166_1000_US / 10;
166294e412c2SWeidong Wang aw_dev->fade_out_time = AW88166_1000_US >> 1;
166394e412c2SWeidong Wang aw_dev->prof_cur = aw_dev->prof_info.prof_desc[0].id;
166494e412c2SWeidong Wang aw_dev->prof_index = aw_dev->prof_info.prof_desc[0].id;
166594e412c2SWeidong Wang
166694e412c2SWeidong Wang ret = aw88166_dev_fw_update(aw88166, AW88166_FORCE_UPDATE_ON, AW88166_DSP_FW_UPDATE_ON);
166794e412c2SWeidong Wang if (ret) {
166894e412c2SWeidong Wang dev_err(aw_dev->dev, "fw update failed ret = %d\n", ret);
166994e412c2SWeidong Wang return ret;
167094e412c2SWeidong Wang }
167194e412c2SWeidong Wang
167294e412c2SWeidong Wang aw88166_dev_mute(aw_dev, true);
167394e412c2SWeidong Wang
167494e412c2SWeidong Wang /* close tx feedback */
167594e412c2SWeidong Wang aw_dev_i2s_tx_enable(aw_dev, false);
167694e412c2SWeidong Wang usleep_range(AW88166_1000_US, AW88166_1000_US + 100);
167794e412c2SWeidong Wang
167894e412c2SWeidong Wang /* enable amppd */
167994e412c2SWeidong Wang aw_dev_amppd(aw_dev, true);
168094e412c2SWeidong Wang
168194e412c2SWeidong Wang /* close dsp */
168294e412c2SWeidong Wang aw_dev_dsp_enable(aw_dev, false);
168394e412c2SWeidong Wang /* set power down */
168494e412c2SWeidong Wang aw_dev_pwd(aw_dev, true);
168594e412c2SWeidong Wang
168694e412c2SWeidong Wang return 0;
168794e412c2SWeidong Wang }
168894e412c2SWeidong Wang
aw88166_request_firmware_file(struct aw88166 * aw88166)168994e412c2SWeidong Wang static int aw88166_request_firmware_file(struct aw88166 *aw88166)
169094e412c2SWeidong Wang {
169194e412c2SWeidong Wang const struct firmware *cont = NULL;
169294e412c2SWeidong Wang int ret;
169394e412c2SWeidong Wang
169494e412c2SWeidong Wang aw88166->aw_pa->fw_status = AW88166_DEV_FW_FAILED;
169594e412c2SWeidong Wang
169694e412c2SWeidong Wang ret = request_firmware(&cont, AW88166_ACF_FILE, aw88166->aw_pa->dev);
169794e412c2SWeidong Wang if (ret) {
169894e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "request [%s] failed!\n", AW88166_ACF_FILE);
169994e412c2SWeidong Wang return ret;
170094e412c2SWeidong Wang }
170194e412c2SWeidong Wang
170294e412c2SWeidong Wang dev_dbg(aw88166->aw_pa->dev, "loaded %s - size: %zu\n",
170394e412c2SWeidong Wang AW88166_ACF_FILE, cont ? cont->size : 0);
170494e412c2SWeidong Wang
170594e412c2SWeidong Wang aw88166->aw_cfg = devm_kzalloc(aw88166->aw_pa->dev,
170694e412c2SWeidong Wang struct_size(aw88166->aw_cfg, data, cont->size), GFP_KERNEL);
170794e412c2SWeidong Wang if (!aw88166->aw_cfg) {
170894e412c2SWeidong Wang release_firmware(cont);
170994e412c2SWeidong Wang return -ENOMEM;
171094e412c2SWeidong Wang }
171194e412c2SWeidong Wang aw88166->aw_cfg->len = (int)cont->size;
171294e412c2SWeidong Wang memcpy(aw88166->aw_cfg->data, cont->data, cont->size);
171394e412c2SWeidong Wang release_firmware(cont);
171494e412c2SWeidong Wang
171594e412c2SWeidong Wang ret = aw88395_dev_load_acf_check(aw88166->aw_pa, aw88166->aw_cfg);
171694e412c2SWeidong Wang if (ret) {
171794e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "load [%s] failed!\n", AW88166_ACF_FILE);
171894e412c2SWeidong Wang return ret;
171994e412c2SWeidong Wang }
172094e412c2SWeidong Wang
172194e412c2SWeidong Wang mutex_lock(&aw88166->lock);
172294e412c2SWeidong Wang /* aw device init */
172394e412c2SWeidong Wang ret = aw88166_dev_init(aw88166, aw88166->aw_cfg);
172494e412c2SWeidong Wang if (ret)
172594e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "dev init failed\n");
172694e412c2SWeidong Wang mutex_unlock(&aw88166->lock);
172794e412c2SWeidong Wang
172894e412c2SWeidong Wang return ret;
172994e412c2SWeidong Wang }
173094e412c2SWeidong Wang
173194e412c2SWeidong Wang static const struct snd_kcontrol_new aw88166_controls[] = {
173294e412c2SWeidong Wang SOC_SINGLE_EXT("PCM Playback Volume", AW88166_SYSCTRL2_REG,
173394e412c2SWeidong Wang 6, AW88166_MUTE_VOL, 0, aw88166_volume_get,
173494e412c2SWeidong Wang aw88166_volume_set),
173594e412c2SWeidong Wang SOC_SINGLE_EXT("Fade Step", 0, 0, AW88166_MUTE_VOL, 0,
173694e412c2SWeidong Wang aw88166_get_fade_step, aw88166_set_fade_step),
173794e412c2SWeidong Wang SOC_SINGLE_EXT("Volume Ramp Up Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN,
173894e412c2SWeidong Wang aw88166_get_fade_in_time, aw88166_set_fade_in_time),
173994e412c2SWeidong Wang SOC_SINGLE_EXT("Volume Ramp Down Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN,
174094e412c2SWeidong Wang aw88166_get_fade_out_time, aw88166_set_fade_out_time),
174194e412c2SWeidong Wang SOC_SINGLE_EXT("Calib", 0, 0, AW88166_CALI_RE_MAX, 0,
174294e412c2SWeidong Wang aw88166_re_get, aw88166_re_set),
174394e412c2SWeidong Wang AW88166_PROFILE_EXT("AW88166 Profile Set", aw88166_profile_info,
174494e412c2SWeidong Wang aw88166_profile_get, aw88166_profile_set),
174594e412c2SWeidong Wang };
174694e412c2SWeidong Wang
aw88166_playback_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)174794e412c2SWeidong Wang static int aw88166_playback_event(struct snd_soc_dapm_widget *w,
174894e412c2SWeidong Wang struct snd_kcontrol *k, int event)
174994e412c2SWeidong Wang {
175094e412c2SWeidong Wang struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
175194e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component);
175294e412c2SWeidong Wang
175394e412c2SWeidong Wang mutex_lock(&aw88166->lock);
175494e412c2SWeidong Wang switch (event) {
175594e412c2SWeidong Wang case SND_SOC_DAPM_PRE_PMU:
175694e412c2SWeidong Wang aw88166_start(aw88166, AW88166_ASYNC_START);
175794e412c2SWeidong Wang break;
175894e412c2SWeidong Wang case SND_SOC_DAPM_POST_PMD:
175994e412c2SWeidong Wang aw88166_stop(aw88166->aw_pa);
176094e412c2SWeidong Wang break;
176194e412c2SWeidong Wang default:
176294e412c2SWeidong Wang break;
176394e412c2SWeidong Wang }
176494e412c2SWeidong Wang mutex_unlock(&aw88166->lock);
176594e412c2SWeidong Wang
176694e412c2SWeidong Wang return 0;
176794e412c2SWeidong Wang }
176894e412c2SWeidong Wang
176994e412c2SWeidong Wang static const struct snd_soc_dapm_widget aw88166_dapm_widgets[] = {
177094e412c2SWeidong Wang /* playback */
177194e412c2SWeidong Wang SND_SOC_DAPM_AIF_IN_E("AIF_RX", "Speaker_Playback", 0, SND_SOC_NOPM, 0, 0,
177294e412c2SWeidong Wang aw88166_playback_event,
177394e412c2SWeidong Wang SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
177494e412c2SWeidong Wang SND_SOC_DAPM_OUTPUT("DAC Output"),
177594e412c2SWeidong Wang
177694e412c2SWeidong Wang /* capture */
177794e412c2SWeidong Wang SND_SOC_DAPM_AIF_OUT("AIF_TX", "Speaker_Capture", 0, SND_SOC_NOPM, 0, 0),
177894e412c2SWeidong Wang SND_SOC_DAPM_INPUT("ADC Input"),
177994e412c2SWeidong Wang };
178094e412c2SWeidong Wang
178194e412c2SWeidong Wang static const struct snd_soc_dapm_route aw88166_audio_map[] = {
178294e412c2SWeidong Wang {"DAC Output", NULL, "AIF_RX"},
178394e412c2SWeidong Wang {"AIF_TX", NULL, "ADC Input"},
178494e412c2SWeidong Wang };
178594e412c2SWeidong Wang
aw88166_codec_probe(struct snd_soc_component * component)178694e412c2SWeidong Wang static int aw88166_codec_probe(struct snd_soc_component *component)
178794e412c2SWeidong Wang {
178894e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component);
178994e412c2SWeidong Wang int ret;
179094e412c2SWeidong Wang
179194e412c2SWeidong Wang INIT_DELAYED_WORK(&aw88166->start_work, aw88166_startup_work);
179294e412c2SWeidong Wang
179394e412c2SWeidong Wang ret = aw88166_request_firmware_file(aw88166);
179494e412c2SWeidong Wang if (ret)
179594e412c2SWeidong Wang dev_err(aw88166->aw_pa->dev, "%s failed\n", __func__);
179694e412c2SWeidong Wang
179794e412c2SWeidong Wang return ret;
179894e412c2SWeidong Wang }
179994e412c2SWeidong Wang
aw88166_codec_remove(struct snd_soc_component * aw_codec)180094e412c2SWeidong Wang static void aw88166_codec_remove(struct snd_soc_component *aw_codec)
180194e412c2SWeidong Wang {
180294e412c2SWeidong Wang struct aw88166 *aw88166 = snd_soc_component_get_drvdata(aw_codec);
180394e412c2SWeidong Wang
180494e412c2SWeidong Wang cancel_delayed_work_sync(&aw88166->start_work);
180594e412c2SWeidong Wang }
180694e412c2SWeidong Wang
180794e412c2SWeidong Wang static const struct snd_soc_component_driver soc_codec_dev_aw88166 = {
180894e412c2SWeidong Wang .probe = aw88166_codec_probe,
180994e412c2SWeidong Wang .remove = aw88166_codec_remove,
181094e412c2SWeidong Wang .dapm_widgets = aw88166_dapm_widgets,
181194e412c2SWeidong Wang .num_dapm_widgets = ARRAY_SIZE(aw88166_dapm_widgets),
181294e412c2SWeidong Wang .dapm_routes = aw88166_audio_map,
181394e412c2SWeidong Wang .num_dapm_routes = ARRAY_SIZE(aw88166_audio_map),
181494e412c2SWeidong Wang .controls = aw88166_controls,
181594e412c2SWeidong Wang .num_controls = ARRAY_SIZE(aw88166_controls),
181694e412c2SWeidong Wang };
181794e412c2SWeidong Wang
aw88166_hw_reset(struct aw88166 * aw88166)181894e412c2SWeidong Wang static void aw88166_hw_reset(struct aw88166 *aw88166)
181994e412c2SWeidong Wang {
182094e412c2SWeidong Wang if (aw88166->reset_gpio) {
182194e412c2SWeidong Wang gpiod_set_value_cansleep(aw88166->reset_gpio, 1);
182294e412c2SWeidong Wang usleep_range(AW88166_1000_US, AW88166_1000_US + 10);
182394e412c2SWeidong Wang gpiod_set_value_cansleep(aw88166->reset_gpio, 0);
182494e412c2SWeidong Wang usleep_range(AW88166_1000_US, AW88166_1000_US + 10);
182594e412c2SWeidong Wang }
182694e412c2SWeidong Wang }
182794e412c2SWeidong Wang
aw88166_parse_channel_dt(struct aw88166 * aw88166)182894e412c2SWeidong Wang static void aw88166_parse_channel_dt(struct aw88166 *aw88166)
182994e412c2SWeidong Wang {
183094e412c2SWeidong Wang struct aw_device *aw_dev = aw88166->aw_pa;
183194e412c2SWeidong Wang struct device_node *np = aw_dev->dev->of_node;
183294e412c2SWeidong Wang u32 channel_value;
183394e412c2SWeidong Wang
183494e412c2SWeidong Wang of_property_read_u32(np, "awinic,audio-channel", &channel_value);
183594e412c2SWeidong Wang aw_dev->channel = channel_value;
183694e412c2SWeidong Wang aw88166->phase_sync = of_property_read_bool(np, "awinic,sync-flag");
183794e412c2SWeidong Wang }
183894e412c2SWeidong Wang
aw88166_init(struct aw88166 * aw88166,struct i2c_client * i2c,struct regmap * regmap)183994e412c2SWeidong Wang static int aw88166_init(struct aw88166 *aw88166, struct i2c_client *i2c, struct regmap *regmap)
184094e412c2SWeidong Wang {
184194e412c2SWeidong Wang struct aw_device *aw_dev;
184294e412c2SWeidong Wang unsigned int chip_id;
184394e412c2SWeidong Wang int ret;
184494e412c2SWeidong Wang
184594e412c2SWeidong Wang ret = regmap_read(regmap, AW88166_ID_REG, &chip_id);
184694e412c2SWeidong Wang if (ret) {
184794e412c2SWeidong Wang dev_err(&i2c->dev, "%s read chipid error. ret = %d\n", __func__, ret);
184894e412c2SWeidong Wang return ret;
184994e412c2SWeidong Wang }
185094e412c2SWeidong Wang
185194e412c2SWeidong Wang aw_dev = devm_kzalloc(&i2c->dev, sizeof(*aw_dev), GFP_KERNEL);
185294e412c2SWeidong Wang if (!aw_dev)
185394e412c2SWeidong Wang return -ENOMEM;
185494e412c2SWeidong Wang aw88166->aw_pa = aw_dev;
185594e412c2SWeidong Wang
185694e412c2SWeidong Wang aw_dev->i2c = i2c;
185794e412c2SWeidong Wang aw_dev->dev = &i2c->dev;
185894e412c2SWeidong Wang aw_dev->regmap = regmap;
185994e412c2SWeidong Wang mutex_init(&aw_dev->dsp_lock);
186094e412c2SWeidong Wang
186194e412c2SWeidong Wang aw_dev->chip_id = chip_id;
186294e412c2SWeidong Wang aw_dev->acf = NULL;
186394e412c2SWeidong Wang aw_dev->prof_info.prof_desc = NULL;
186494e412c2SWeidong Wang aw_dev->prof_info.count = 0;
186594e412c2SWeidong Wang aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID;
186694e412c2SWeidong Wang aw_dev->channel = AW88166_DEV_DEFAULT_CH;
186794e412c2SWeidong Wang aw_dev->fw_status = AW88166_DEV_FW_FAILED;
186894e412c2SWeidong Wang
186994e412c2SWeidong Wang aw_dev->fade_step = AW88166_VOLUME_STEP_DB;
187094e412c2SWeidong Wang aw_dev->volume_desc.ctl_volume = AW88166_VOL_DEFAULT_VALUE;
187194e412c2SWeidong Wang
187294e412c2SWeidong Wang aw88166_parse_channel_dt(aw88166);
187394e412c2SWeidong Wang
187494e412c2SWeidong Wang return 0;
187594e412c2SWeidong Wang }
187694e412c2SWeidong Wang
aw88166_i2c_probe(struct i2c_client * i2c)187794e412c2SWeidong Wang static int aw88166_i2c_probe(struct i2c_client *i2c)
187894e412c2SWeidong Wang {
187994e412c2SWeidong Wang struct aw88166 *aw88166;
188094e412c2SWeidong Wang int ret;
188194e412c2SWeidong Wang
188294e412c2SWeidong Wang if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
188394e412c2SWeidong Wang return dev_err_probe(&i2c->dev, -ENXIO, "check_functionality failed\n");
188494e412c2SWeidong Wang
188594e412c2SWeidong Wang aw88166 = devm_kzalloc(&i2c->dev, sizeof(*aw88166), GFP_KERNEL);
188694e412c2SWeidong Wang if (!aw88166)
188794e412c2SWeidong Wang return -ENOMEM;
188894e412c2SWeidong Wang
188994e412c2SWeidong Wang mutex_init(&aw88166->lock);
189094e412c2SWeidong Wang
189194e412c2SWeidong Wang i2c_set_clientdata(i2c, aw88166);
189294e412c2SWeidong Wang
189394e412c2SWeidong Wang aw88166->reset_gpio = devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_LOW);
189494e412c2SWeidong Wang if (IS_ERR(aw88166->reset_gpio))
189594e412c2SWeidong Wang return dev_err_probe(&i2c->dev, PTR_ERR(aw88166->reset_gpio),
189694e412c2SWeidong Wang "reset gpio not defined\n");
189794e412c2SWeidong Wang aw88166_hw_reset(aw88166);
189894e412c2SWeidong Wang
189994e412c2SWeidong Wang aw88166->regmap = devm_regmap_init_i2c(i2c, &aw88166_remap_config);
190094e412c2SWeidong Wang if (IS_ERR(aw88166->regmap))
190194e412c2SWeidong Wang return dev_err_probe(&i2c->dev, PTR_ERR(aw88166->regmap),
190294e412c2SWeidong Wang "failed to init regmap\n");
190394e412c2SWeidong Wang
190494e412c2SWeidong Wang /* aw pa init */
190594e412c2SWeidong Wang ret = aw88166_init(aw88166, i2c, aw88166->regmap);
190694e412c2SWeidong Wang if (ret)
190794e412c2SWeidong Wang return ret;
190894e412c2SWeidong Wang
190994e412c2SWeidong Wang return devm_snd_soc_register_component(&i2c->dev,
191094e412c2SWeidong Wang &soc_codec_dev_aw88166,
191194e412c2SWeidong Wang aw88166_dai, ARRAY_SIZE(aw88166_dai));
191294e412c2SWeidong Wang }
191394e412c2SWeidong Wang
191494e412c2SWeidong Wang static const struct i2c_device_id aw88166_i2c_id[] = {
191594e412c2SWeidong Wang { AW88166_I2C_NAME },
191694e412c2SWeidong Wang { }
191794e412c2SWeidong Wang };
191894e412c2SWeidong Wang MODULE_DEVICE_TABLE(i2c, aw88166_i2c_id);
191994e412c2SWeidong Wang
192094e412c2SWeidong Wang static struct i2c_driver aw88166_i2c_driver = {
192194e412c2SWeidong Wang .driver = {
192294e412c2SWeidong Wang .name = AW88166_I2C_NAME,
192394e412c2SWeidong Wang },
192494e412c2SWeidong Wang .probe = aw88166_i2c_probe,
192594e412c2SWeidong Wang .id_table = aw88166_i2c_id,
192694e412c2SWeidong Wang };
192794e412c2SWeidong Wang module_i2c_driver(aw88166_i2c_driver);
192894e412c2SWeidong Wang
192994e412c2SWeidong Wang MODULE_DESCRIPTION("ASoC AW88166 Smart PA Driver");
193094e412c2SWeidong Wang MODULE_LICENSE("GPL v2");
1931