162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// aw88395_device.c -- AW88395 function for ALSA Audio Driver 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (c) 2022-2023 AWINIC Technology CO., LTD 662306a36Sopenharmony_ci// 762306a36Sopenharmony_ci// Author: Bruce zhao <zhaolei@awinic.com> 862306a36Sopenharmony_ci// Author: Ben Yi <yijiangtao@awinic.com> 962306a36Sopenharmony_ci// 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/crc32.h> 1262306a36Sopenharmony_ci#include <linux/i2c.h> 1362306a36Sopenharmony_ci#include <linux/regmap.h> 1462306a36Sopenharmony_ci#include "aw88395_device.h" 1562306a36Sopenharmony_ci#include "aw88395_reg.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic int aw_dev_dsp_write_16bit(struct aw_device *aw_dev, 1862306a36Sopenharmony_ci unsigned short dsp_addr, unsigned int dsp_data) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci int ret; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, dsp_addr); 2362306a36Sopenharmony_ci if (ret) { 2462306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s write addr error, ret=%d", __func__, ret); 2562306a36Sopenharmony_ci return ret; 2662306a36Sopenharmony_ci } 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMDAT_REG, (u16)dsp_data); 2962306a36Sopenharmony_ci if (ret) { 3062306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s write data error, ret=%d", __func__, ret); 3162306a36Sopenharmony_ci return ret; 3262306a36Sopenharmony_ci } 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci return 0; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic int aw_dev_dsp_write_32bit(struct aw_device *aw_dev, 3862306a36Sopenharmony_ci unsigned short dsp_addr, unsigned int dsp_data) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci u16 temp_data; 4162306a36Sopenharmony_ci int ret; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, dsp_addr); 4462306a36Sopenharmony_ci if (ret) { 4562306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s write addr error, ret=%d", __func__, ret); 4662306a36Sopenharmony_ci return ret; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci temp_data = dsp_data & AW88395_DSP_16_DATA_MASK; 5062306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMDAT_REG, (u16)temp_data); 5162306a36Sopenharmony_ci if (ret) { 5262306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s write datal error, ret=%d", __func__, ret); 5362306a36Sopenharmony_ci return ret; 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci temp_data = dsp_data >> 16; 5762306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMDAT_REG, (u16)temp_data); 5862306a36Sopenharmony_ci if (ret) { 5962306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s write datah error, ret=%d", __func__, ret); 6062306a36Sopenharmony_ci return ret; 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci return 0; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int aw_dev_dsp_write(struct aw_device *aw_dev, 6762306a36Sopenharmony_ci unsigned short dsp_addr, unsigned int dsp_data, unsigned char data_type) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci u32 reg_value; 7062306a36Sopenharmony_ci int ret; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci mutex_lock(&aw_dev->dsp_lock); 7362306a36Sopenharmony_ci switch (data_type) { 7462306a36Sopenharmony_ci case AW88395_DSP_16_DATA: 7562306a36Sopenharmony_ci ret = aw_dev_dsp_write_16bit(aw_dev, dsp_addr, dsp_data); 7662306a36Sopenharmony_ci if (ret) 7762306a36Sopenharmony_ci dev_err(aw_dev->dev, "write dsp_addr[0x%x] 16-bit dsp_data[0x%x] failed", 7862306a36Sopenharmony_ci (u32)dsp_addr, dsp_data); 7962306a36Sopenharmony_ci break; 8062306a36Sopenharmony_ci case AW88395_DSP_32_DATA: 8162306a36Sopenharmony_ci ret = aw_dev_dsp_write_32bit(aw_dev, dsp_addr, dsp_data); 8262306a36Sopenharmony_ci if (ret) 8362306a36Sopenharmony_ci dev_err(aw_dev->dev, "write dsp_addr[0x%x] 32-bit dsp_data[0x%x] failed", 8462306a36Sopenharmony_ci (u32)dsp_addr, dsp_data); 8562306a36Sopenharmony_ci break; 8662306a36Sopenharmony_ci default: 8762306a36Sopenharmony_ci dev_err(aw_dev->dev, "data type[%d] unsupported", data_type); 8862306a36Sopenharmony_ci ret = -EINVAL; 8962306a36Sopenharmony_ci break; 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* clear dsp chip select state*/ 9362306a36Sopenharmony_ci if (regmap_read(aw_dev->regmap, AW88395_ID_REG, ®_value)) 9462306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s fail to clear chip state. Err=%d\n", __func__, ret); 9562306a36Sopenharmony_ci mutex_unlock(&aw_dev->dsp_lock); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci return ret; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic int aw_dev_dsp_read_16bit(struct aw_device *aw_dev, 10162306a36Sopenharmony_ci unsigned short dsp_addr, unsigned int *dsp_data) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci unsigned int temp_data; 10462306a36Sopenharmony_ci int ret; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, dsp_addr); 10762306a36Sopenharmony_ci if (ret) { 10862306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s write error, ret=%d", __func__, ret); 10962306a36Sopenharmony_ci return ret; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_DSPMDAT_REG, &temp_data); 11362306a36Sopenharmony_ci if (ret) { 11462306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret); 11562306a36Sopenharmony_ci return ret; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci *dsp_data = temp_data; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic int aw_dev_dsp_read_32bit(struct aw_device *aw_dev, 12362306a36Sopenharmony_ci unsigned short dsp_addr, unsigned int *dsp_data) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci unsigned int temp_data; 12662306a36Sopenharmony_ci int ret; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, dsp_addr); 12962306a36Sopenharmony_ci if (ret) { 13062306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s write error, ret=%d", __func__, ret); 13162306a36Sopenharmony_ci return ret; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_DSPMDAT_REG, &temp_data); 13562306a36Sopenharmony_ci if (ret) { 13662306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret); 13762306a36Sopenharmony_ci return ret; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci *dsp_data = temp_data; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_DSPMDAT_REG, &temp_data); 14262306a36Sopenharmony_ci if (ret) { 14362306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret); 14462306a36Sopenharmony_ci return ret; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci *dsp_data |= (temp_data << 16); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci return 0; 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic int aw_dev_dsp_read(struct aw_device *aw_dev, 15262306a36Sopenharmony_ci unsigned short dsp_addr, unsigned int *dsp_data, unsigned char data_type) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci u32 reg_value; 15562306a36Sopenharmony_ci int ret; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci mutex_lock(&aw_dev->dsp_lock); 15862306a36Sopenharmony_ci switch (data_type) { 15962306a36Sopenharmony_ci case AW88395_DSP_16_DATA: 16062306a36Sopenharmony_ci ret = aw_dev_dsp_read_16bit(aw_dev, dsp_addr, dsp_data); 16162306a36Sopenharmony_ci if (ret) 16262306a36Sopenharmony_ci dev_err(aw_dev->dev, "read dsp_addr[0x%x] 16-bit dsp_data[0x%x] failed", 16362306a36Sopenharmony_ci (u32)dsp_addr, *dsp_data); 16462306a36Sopenharmony_ci break; 16562306a36Sopenharmony_ci case AW88395_DSP_32_DATA: 16662306a36Sopenharmony_ci ret = aw_dev_dsp_read_32bit(aw_dev, dsp_addr, dsp_data); 16762306a36Sopenharmony_ci if (ret) 16862306a36Sopenharmony_ci dev_err(aw_dev->dev, "read dsp_addr[0x%x] 32r-bit dsp_data[0x%x] failed", 16962306a36Sopenharmony_ci (u32)dsp_addr, *dsp_data); 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci default: 17262306a36Sopenharmony_ci dev_err(aw_dev->dev, "data type[%d] unsupported", data_type); 17362306a36Sopenharmony_ci ret = -EINVAL; 17462306a36Sopenharmony_ci break; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* clear dsp chip select state*/ 17862306a36Sopenharmony_ci if (regmap_read(aw_dev->regmap, AW88395_ID_REG, ®_value)) 17962306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s fail to clear chip state. Err=%d\n", __func__, ret); 18062306a36Sopenharmony_ci mutex_unlock(&aw_dev->dsp_lock); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci return ret; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic int aw_dev_read_chipid(struct aw_device *aw_dev, u16 *chip_id) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci int reg_val; 18962306a36Sopenharmony_ci int ret; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_CHIP_ID_REG, ®_val); 19262306a36Sopenharmony_ci if (ret) { 19362306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s read chipid error. ret = %d", __func__, ret); 19462306a36Sopenharmony_ci return ret; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci dev_info(aw_dev->dev, "chip id = %x\n", reg_val); 19862306a36Sopenharmony_ci *chip_id = reg_val; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci return 0; 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic unsigned int reg_val_to_db(unsigned int value) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci return (((value >> AW88395_VOL_6DB_START) * AW88395_VOLUME_STEP_DB) + 20662306a36Sopenharmony_ci ((value & 0x3f) % AW88395_VOLUME_STEP_DB)); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic unsigned short db_to_reg_val(unsigned short value) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci return (((value / AW88395_VOLUME_STEP_DB) << AW88395_VOL_6DB_START) + 21262306a36Sopenharmony_ci (value % AW88395_VOLUME_STEP_DB)); 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic int aw_dev_dsp_fw_check(struct aw_device *aw_dev) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci struct aw_sec_data_desc *dsp_fw_desc; 21862306a36Sopenharmony_ci struct aw_prof_desc *set_prof_desc; 21962306a36Sopenharmony_ci u16 base_addr = AW88395_DSP_FW_ADDR; 22062306a36Sopenharmony_ci u16 addr = base_addr; 22162306a36Sopenharmony_ci u32 dsp_val; 22262306a36Sopenharmony_ci u16 bin_val; 22362306a36Sopenharmony_ci int ret, i; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci ret = aw88395_dev_get_prof_data(aw_dev, aw_dev->prof_cur, &set_prof_desc); 22662306a36Sopenharmony_ci if (ret) 22762306a36Sopenharmony_ci return ret; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* update reg */ 23062306a36Sopenharmony_ci dsp_fw_desc = &set_prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW]; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci for (i = 0; i < AW88395_FW_CHECK_PART; i++) { 23362306a36Sopenharmony_ci ret = aw_dev_dsp_read(aw_dev, addr, &dsp_val, AW88395_DSP_16_DATA); 23462306a36Sopenharmony_ci if (ret) { 23562306a36Sopenharmony_ci dev_err(aw_dev->dev, "dsp read failed"); 23662306a36Sopenharmony_ci return ret; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci bin_val = be16_to_cpup((void *)&dsp_fw_desc->data[2 * (addr - base_addr)]); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (dsp_val != bin_val) { 24262306a36Sopenharmony_ci dev_err(aw_dev->dev, "fw check failed, addr[0x%x], read[0x%x] != bindata[0x%x]", 24362306a36Sopenharmony_ci addr, dsp_val, bin_val); 24462306a36Sopenharmony_ci return -EINVAL; 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci addr += (dsp_fw_desc->len / 2) / AW88395_FW_CHECK_PART; 24862306a36Sopenharmony_ci if ((addr - base_addr) > dsp_fw_desc->len) { 24962306a36Sopenharmony_ci dev_err(aw_dev->dev, "fw check failed, addr[0x%x] too large", addr); 25062306a36Sopenharmony_ci return -EINVAL; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return 0; 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic int aw_dev_set_volume(struct aw_device *aw_dev, unsigned int value) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; 26062306a36Sopenharmony_ci unsigned int reg_value; 26162306a36Sopenharmony_ci u16 real_value, volume; 26262306a36Sopenharmony_ci int ret; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci volume = min((value + vol_desc->init_volume), (unsigned int)AW88395_MUTE_VOL); 26562306a36Sopenharmony_ci real_value = db_to_reg_val(volume); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* cal real value */ 26862306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_SYSCTRL2_REG, ®_value); 26962306a36Sopenharmony_ci if (ret) 27062306a36Sopenharmony_ci return ret; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "value 0x%x , reg:0x%x", value, real_value); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* [15 : 6] volume */ 27562306a36Sopenharmony_ci real_value = (real_value << AW88395_VOL_START_BIT) | (reg_value & AW88395_VOL_MASK); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* write value */ 27862306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_SYSCTRL2_REG, real_value); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci return ret; 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_civoid aw88395_dev_set_volume(struct aw_device *aw_dev, unsigned short set_vol) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci int ret; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci ret = aw_dev_set_volume(aw_dev, set_vol); 28862306a36Sopenharmony_ci if (ret) 28962306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "set volume failed"); 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_set_volume); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic void aw_dev_fade_in(struct aw_device *aw_dev) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci struct aw_volume_desc *desc = &aw_dev->volume_desc; 29662306a36Sopenharmony_ci u16 fade_in_vol = desc->ctl_volume; 29762306a36Sopenharmony_ci int fade_step = aw_dev->fade_step; 29862306a36Sopenharmony_ci int i; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (!aw_dev->fade_en) 30162306a36Sopenharmony_ci return; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (fade_step == 0 || aw_dev->fade_in_time == 0) { 30462306a36Sopenharmony_ci aw_dev_set_volume(aw_dev, fade_in_vol); 30562306a36Sopenharmony_ci return; 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci for (i = AW88395_MUTE_VOL; i >= fade_in_vol; i -= fade_step) { 30962306a36Sopenharmony_ci aw_dev_set_volume(aw_dev, i); 31062306a36Sopenharmony_ci usleep_range(aw_dev->fade_in_time, aw_dev->fade_in_time + 10); 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (i != fade_in_vol) 31462306a36Sopenharmony_ci aw_dev_set_volume(aw_dev, fade_in_vol); 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic void aw_dev_fade_out(struct aw_device *aw_dev) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci struct aw_volume_desc *desc = &aw_dev->volume_desc; 32062306a36Sopenharmony_ci int fade_step = aw_dev->fade_step; 32162306a36Sopenharmony_ci int i; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (!aw_dev->fade_en) 32462306a36Sopenharmony_ci return; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (fade_step == 0 || aw_dev->fade_out_time == 0) { 32762306a36Sopenharmony_ci aw_dev_set_volume(aw_dev, AW88395_MUTE_VOL); 32862306a36Sopenharmony_ci return; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci for (i = desc->ctl_volume; i <= AW88395_MUTE_VOL; i += fade_step) { 33262306a36Sopenharmony_ci aw_dev_set_volume(aw_dev, i); 33362306a36Sopenharmony_ci usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (i != AW88395_MUTE_VOL) { 33762306a36Sopenharmony_ci aw_dev_set_volume(aw_dev, AW88395_MUTE_VOL); 33862306a36Sopenharmony_ci usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic int aw_dev_modify_dsp_cfg(struct aw_device *aw_dev, 34362306a36Sopenharmony_ci unsigned int addr, unsigned int dsp_data, unsigned char data_type) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; 34662306a36Sopenharmony_ci unsigned int addr_offset; 34762306a36Sopenharmony_ci __le16 data1; 34862306a36Sopenharmony_ci __le32 data2; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "addr:0x%x, dsp_data:0x%x", addr, dsp_data); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci addr_offset = (addr - AW88395_DSP_CFG_ADDR) * 2; 35362306a36Sopenharmony_ci if (addr_offset > crc_dsp_cfg->len) { 35462306a36Sopenharmony_ci dev_err(aw_dev->dev, "addr_offset[%d] > crc_dsp_cfg->len[%d]", 35562306a36Sopenharmony_ci addr_offset, crc_dsp_cfg->len); 35662306a36Sopenharmony_ci return -EINVAL; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci switch (data_type) { 35962306a36Sopenharmony_ci case AW88395_DSP_16_DATA: 36062306a36Sopenharmony_ci data1 = cpu_to_le16((u16)dsp_data); 36162306a36Sopenharmony_ci memcpy(crc_dsp_cfg->data + addr_offset, (u8 *)&data1, 2); 36262306a36Sopenharmony_ci break; 36362306a36Sopenharmony_ci case AW88395_DSP_32_DATA: 36462306a36Sopenharmony_ci data2 = cpu_to_le32(dsp_data); 36562306a36Sopenharmony_ci memcpy(crc_dsp_cfg->data + addr_offset, (u8 *)&data2, 4); 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci default: 36862306a36Sopenharmony_ci dev_err(aw_dev->dev, "data type[%d] unsupported", data_type); 36962306a36Sopenharmony_ci return -EINVAL; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci return 0; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cistatic int aw_dev_dsp_set_cali_re(struct aw_device *aw_dev) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci u32 cali_re; 37862306a36Sopenharmony_ci int ret; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci cali_re = AW88395_SHOW_RE_TO_DSP_RE((aw_dev->cali_desc.cali_re + 38162306a36Sopenharmony_ci aw_dev->cali_desc.ra), AW88395_DSP_RE_SHIFT); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* set cali re to device */ 38462306a36Sopenharmony_ci ret = aw_dev_dsp_write(aw_dev, 38562306a36Sopenharmony_ci AW88395_DSP_REG_CFG_ADPZ_RE, cali_re, AW88395_DSP_32_DATA); 38662306a36Sopenharmony_ci if (ret) { 38762306a36Sopenharmony_ci dev_err(aw_dev->dev, "set cali re error"); 38862306a36Sopenharmony_ci return ret; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci ret = aw_dev_modify_dsp_cfg(aw_dev, AW88395_DSP_REG_CFG_ADPZ_RE, 39262306a36Sopenharmony_ci cali_re, AW88395_DSP_32_DATA); 39362306a36Sopenharmony_ci if (ret) 39462306a36Sopenharmony_ci dev_err(aw_dev->dev, "modify dsp cfg failed"); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci return ret; 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic void aw_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci int ret; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci if (flag) { 40462306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_I2SCFG1_REG, 40562306a36Sopenharmony_ci ~AW88395_I2STXEN_MASK, AW88395_I2STXEN_ENABLE_VALUE); 40662306a36Sopenharmony_ci } else { 40762306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_I2SCFG1_REG, 40862306a36Sopenharmony_ci ~AW88395_I2STXEN_MASK, AW88395_I2STXEN_DISABLE_VALUE); 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (ret) 41262306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s failed", __func__); 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic int aw_dev_dsp_set_crc32(struct aw_device *aw_dev) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; 41862306a36Sopenharmony_ci u32 crc_value, crc_data_len; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci /* get crc data len */ 42162306a36Sopenharmony_ci crc_data_len = (AW88395_DSP_REG_CRC_ADDR - AW88395_DSP_CFG_ADDR) * 2; 42262306a36Sopenharmony_ci if (crc_data_len > crc_dsp_cfg->len) { 42362306a36Sopenharmony_ci dev_err(aw_dev->dev, "crc data len :%d > cfg_data len:%d", 42462306a36Sopenharmony_ci crc_data_len, crc_dsp_cfg->len); 42562306a36Sopenharmony_ci return -EINVAL; 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci if (crc_data_len & 0x11) { 42962306a36Sopenharmony_ci dev_err(aw_dev->dev, "The crc data len :%d unsupport", crc_data_len); 43062306a36Sopenharmony_ci return -EINVAL; 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci crc_value = __crc32c_le(0xFFFFFFFF, crc_dsp_cfg->data, crc_data_len) ^ 0xFFFFFFFF; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return aw_dev_dsp_write(aw_dev, AW88395_DSP_REG_CRC_ADDR, crc_value, 43662306a36Sopenharmony_ci AW88395_DSP_32_DATA); 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic void aw_dev_dsp_check_crc_enable(struct aw_device *aw_dev, bool flag) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci int ret; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (flag) { 44462306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_HAGCCFG7_REG, 44562306a36Sopenharmony_ci ~AW88395_AGC_DSP_CTL_MASK, AW88395_AGC_DSP_CTL_ENABLE_VALUE); 44662306a36Sopenharmony_ci } else { 44762306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_HAGCCFG7_REG, 44862306a36Sopenharmony_ci ~AW88395_AGC_DSP_CTL_MASK, AW88395_AGC_DSP_CTL_DISABLE_VALUE); 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci if (ret) 45162306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s failed", __func__); 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic int aw_dev_dsp_check_st(struct aw_device *aw_dev) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci unsigned int reg_val; 45762306a36Sopenharmony_ci int ret; 45862306a36Sopenharmony_ci int i; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci for (i = 0; i < AW88395_DSP_ST_CHECK_MAX; i++) { 46162306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_SYSST_REG, ®_val); 46262306a36Sopenharmony_ci if (ret) { 46362306a36Sopenharmony_ci dev_err(aw_dev->dev, "read reg0x%x failed", AW88395_SYSST_REG); 46462306a36Sopenharmony_ci continue; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if ((reg_val & (~AW88395_DSPS_MASK)) != AW88395_DSPS_NORMAL_VALUE) { 46862306a36Sopenharmony_ci dev_err(aw_dev->dev, "check dsp st fail,reg_val:0x%04x", reg_val); 46962306a36Sopenharmony_ci ret = -EPERM; 47062306a36Sopenharmony_ci continue; 47162306a36Sopenharmony_ci } else { 47262306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "dsp st check ok, reg_val:0x%04x", reg_val); 47362306a36Sopenharmony_ci return 0; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci return ret; 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic void aw_dev_dsp_enable(struct aw_device *aw_dev, bool is_enable) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci int ret; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci if (is_enable) { 48562306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG, 48662306a36Sopenharmony_ci ~AW88395_DSPBY_MASK, AW88395_DSPBY_WORKING_VALUE); 48762306a36Sopenharmony_ci if (ret) 48862306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "enable dsp failed"); 48962306a36Sopenharmony_ci } else { 49062306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG, 49162306a36Sopenharmony_ci ~AW88395_DSPBY_MASK, AW88395_DSPBY_BYPASS_VALUE); 49262306a36Sopenharmony_ci if (ret) 49362306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "disable dsp failed"); 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic int aw_dev_dsp_check_crc32(struct aw_device *aw_dev) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci int ret; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (aw_dev->dsp_cfg == AW88395_DEV_DSP_BYPASS) { 50262306a36Sopenharmony_ci dev_info(aw_dev->dev, "dsp bypass"); 50362306a36Sopenharmony_ci return 0; 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci ret = aw_dev_dsp_set_crc32(aw_dev); 50762306a36Sopenharmony_ci if (ret) { 50862306a36Sopenharmony_ci dev_err(aw_dev->dev, "set dsp crc32 failed"); 50962306a36Sopenharmony_ci return ret; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci aw_dev_dsp_check_crc_enable(aw_dev, true); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* dsp enable */ 51562306a36Sopenharmony_ci aw_dev_dsp_enable(aw_dev, true); 51662306a36Sopenharmony_ci usleep_range(AW88395_5000_US, AW88395_5000_US + 100); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci ret = aw_dev_dsp_check_st(aw_dev); 51962306a36Sopenharmony_ci if (ret) { 52062306a36Sopenharmony_ci dev_err(aw_dev->dev, "check crc32 fail"); 52162306a36Sopenharmony_ci } else { 52262306a36Sopenharmony_ci aw_dev_dsp_check_crc_enable(aw_dev, false); 52362306a36Sopenharmony_ci aw_dev->dsp_crc_st = AW88395_DSP_CRC_OK; 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci return ret; 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic void aw_dev_pwd(struct aw_device *aw_dev, bool pwd) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci int ret; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci if (pwd) { 53462306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG, 53562306a36Sopenharmony_ci ~AW88395_PWDN_MASK, AW88395_PWDN_POWER_DOWN_VALUE); 53662306a36Sopenharmony_ci } else { 53762306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG, 53862306a36Sopenharmony_ci ~AW88395_PWDN_MASK, AW88395_PWDN_WORKING_VALUE); 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci if (ret) 54162306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s failed", __func__); 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_cistatic void aw_dev_amppd(struct aw_device *aw_dev, bool amppd) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci int ret; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci if (amppd) { 54962306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG, 55062306a36Sopenharmony_ci ~AW88395_AMPPD_MASK, AW88395_AMPPD_POWER_DOWN_VALUE); 55162306a36Sopenharmony_ci } else { 55262306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG, 55362306a36Sopenharmony_ci ~AW88395_AMPPD_MASK, AW88395_AMPPD_WORKING_VALUE); 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci if (ret) 55662306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s failed", __func__); 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_civoid aw88395_dev_mute(struct aw_device *aw_dev, bool is_mute) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci int ret; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (is_mute) { 56462306a36Sopenharmony_ci aw_dev_fade_out(aw_dev); 56562306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG, 56662306a36Sopenharmony_ci ~AW88395_HMUTE_MASK, AW88395_HMUTE_ENABLE_VALUE); 56762306a36Sopenharmony_ci } else { 56862306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG, 56962306a36Sopenharmony_ci ~AW88395_HMUTE_MASK, AW88395_HMUTE_DISABLE_VALUE); 57062306a36Sopenharmony_ci aw_dev_fade_in(aw_dev); 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci if (ret) 57462306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s failed", __func__); 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_mute); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic int aw_dev_get_icalk(struct aw_device *aw_dev, int16_t *icalk) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci unsigned int reg_val; 58162306a36Sopenharmony_ci u16 reg_icalk; 58262306a36Sopenharmony_ci int ret; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_EFRM2_REG, ®_val); 58562306a36Sopenharmony_ci if (ret) 58662306a36Sopenharmony_ci return ret; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci reg_icalk = reg_val & (~AW88395_EF_ISN_GESLP_MASK); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci if (reg_icalk & (~AW88395_EF_ISN_GESLP_SIGN_MASK)) 59162306a36Sopenharmony_ci reg_icalk = reg_icalk | AW88395_EF_ISN_GESLP_SIGN_NEG; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci *icalk = (int16_t)reg_icalk; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci return ret; 59662306a36Sopenharmony_ci} 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic int aw_dev_get_vcalk(struct aw_device *aw_dev, int16_t *vcalk) 59962306a36Sopenharmony_ci{ 60062306a36Sopenharmony_ci unsigned int reg_val; 60162306a36Sopenharmony_ci u16 reg_vcalk; 60262306a36Sopenharmony_ci int ret; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_EFRH_REG, ®_val); 60562306a36Sopenharmony_ci if (ret) 60662306a36Sopenharmony_ci return ret; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci reg_val = reg_val >> AW88395_EF_VSENSE_GAIN_SHIFT; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci reg_vcalk = (u16)reg_val & (~AW88395_EF_VSN_GESLP_MASK); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci if (reg_vcalk & (~AW88395_EF_VSN_GESLP_SIGN_MASK)) 61362306a36Sopenharmony_ci reg_vcalk = reg_vcalk | AW88395_EF_VSN_GESLP_SIGN_NEG; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci *vcalk = (int16_t)reg_vcalk; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci return ret; 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cistatic int aw_dev_get_vcalk_dac(struct aw_device *aw_dev, int16_t *vcalk) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci unsigned int reg_val; 62362306a36Sopenharmony_ci u16 reg_vcalk; 62462306a36Sopenharmony_ci int ret; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_EFRM2_REG, ®_val); 62762306a36Sopenharmony_ci if (ret) 62862306a36Sopenharmony_ci return ret; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci reg_vcalk = reg_val >> AW88395_EF_DAC_GESLP_SHIFT; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci if (reg_vcalk & AW88395_EF_DAC_GESLP_SIGN_MASK) 63362306a36Sopenharmony_ci reg_vcalk = reg_vcalk | AW88395_EF_DAC_GESLP_SIGN_NEG; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci *vcalk = (int16_t)reg_vcalk; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci return ret; 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cistatic int aw_dev_vsense_select(struct aw_device *aw_dev, int *vsense_select) 64162306a36Sopenharmony_ci{ 64262306a36Sopenharmony_ci unsigned int vsense_reg_val; 64362306a36Sopenharmony_ci int ret; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_I2SCFG3_REG, &vsense_reg_val); 64662306a36Sopenharmony_ci if (ret) { 64762306a36Sopenharmony_ci dev_err(aw_dev->dev, "read vsense_reg_val failed"); 64862306a36Sopenharmony_ci return ret; 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "vsense_reg = 0x%x", vsense_reg_val); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (vsense_reg_val & (~AW88395_VDSEL_MASK)) { 65362306a36Sopenharmony_ci *vsense_select = AW88395_DEV_VDSEL_VSENSE; 65462306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "vsense outside"); 65562306a36Sopenharmony_ci } else { 65662306a36Sopenharmony_ci *vsense_select = AW88395_DEV_VDSEL_DAC; 65762306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "vsense inside"); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci return 0; 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic int aw_dev_set_vcalb(struct aw_device *aw_dev) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci int16_t icalk_val, vcalk_val; 66662306a36Sopenharmony_ci int icalk, vsense_select; 66762306a36Sopenharmony_ci u32 vcalb_adj, reg_val; 66862306a36Sopenharmony_ci int vcalb, vcalk; 66962306a36Sopenharmony_ci int ret; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci ret = aw_dev_dsp_read(aw_dev, AW88395_DSP_REG_VCALB, &vcalb_adj, AW88395_DSP_16_DATA); 67262306a36Sopenharmony_ci if (ret) { 67362306a36Sopenharmony_ci dev_err(aw_dev->dev, "read vcalb_adj failed"); 67462306a36Sopenharmony_ci return ret; 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci ret = aw_dev_vsense_select(aw_dev, &vsense_select); 67862306a36Sopenharmony_ci if (ret) 67962306a36Sopenharmony_ci return ret; 68062306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "vsense_select = %d", vsense_select); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci ret = aw_dev_get_icalk(aw_dev, &icalk_val); 68362306a36Sopenharmony_ci if (ret) 68462306a36Sopenharmony_ci return ret; 68562306a36Sopenharmony_ci icalk = AW88395_CABL_BASE_VALUE + AW88395_ICABLK_FACTOR * icalk_val; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci switch (vsense_select) { 68862306a36Sopenharmony_ci case AW88395_DEV_VDSEL_VSENSE: 68962306a36Sopenharmony_ci ret = aw_dev_get_vcalk(aw_dev, &vcalk_val); 69062306a36Sopenharmony_ci if (ret) 69162306a36Sopenharmony_ci return ret; 69262306a36Sopenharmony_ci vcalk = AW88395_CABL_BASE_VALUE + AW88395_VCABLK_FACTOR * vcalk_val; 69362306a36Sopenharmony_ci vcalb = AW88395_VCAL_FACTOR * AW88395_VSCAL_FACTOR / 69462306a36Sopenharmony_ci AW88395_ISCAL_FACTOR * icalk / vcalk * vcalb_adj; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "vcalk_factor=%d, vscal_factor=%d, icalk=%d, vcalk=%d", 69762306a36Sopenharmony_ci AW88395_VCABLK_FACTOR, AW88395_VSCAL_FACTOR, icalk, vcalk); 69862306a36Sopenharmony_ci break; 69962306a36Sopenharmony_ci case AW88395_DEV_VDSEL_DAC: 70062306a36Sopenharmony_ci ret = aw_dev_get_vcalk_dac(aw_dev, &vcalk_val); 70162306a36Sopenharmony_ci if (ret) 70262306a36Sopenharmony_ci return ret; 70362306a36Sopenharmony_ci vcalk = AW88395_CABL_BASE_VALUE + AW88395_VCABLK_FACTOR_DAC * vcalk_val; 70462306a36Sopenharmony_ci vcalb = AW88395_VCAL_FACTOR * AW88395_VSCAL_FACTOR_DAC / 70562306a36Sopenharmony_ci AW88395_ISCAL_FACTOR * icalk / vcalk * vcalb_adj; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "vcalk_dac_factor=%d, vscal_dac_factor=%d, icalk=%d, vcalk=%d", 70862306a36Sopenharmony_ci AW88395_VCABLK_FACTOR_DAC, 70962306a36Sopenharmony_ci AW88395_VSCAL_FACTOR_DAC, icalk, vcalk); 71062306a36Sopenharmony_ci break; 71162306a36Sopenharmony_ci default: 71262306a36Sopenharmony_ci dev_err(aw_dev->dev, "unsupport vsense status"); 71362306a36Sopenharmony_ci return -EINVAL; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if ((vcalk == 0) || (AW88395_ISCAL_FACTOR == 0)) { 71762306a36Sopenharmony_ci dev_err(aw_dev->dev, "vcalk:%d or desc->iscal_factor:%d unsupported", 71862306a36Sopenharmony_ci vcalk, AW88395_ISCAL_FACTOR); 71962306a36Sopenharmony_ci return -EINVAL; 72062306a36Sopenharmony_ci } 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci vcalb = vcalb >> AW88395_VCALB_ADJ_FACTOR; 72362306a36Sopenharmony_ci reg_val = (u32)vcalb; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "vcalb=%d, reg_val=0x%x, vcalb_adj =0x%x", 72662306a36Sopenharmony_ci vcalb, reg_val, vcalb_adj); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci ret = aw_dev_dsp_write(aw_dev, AW88395_DSP_REG_VCALB, reg_val, AW88395_DSP_16_DATA); 72962306a36Sopenharmony_ci if (ret) { 73062306a36Sopenharmony_ci dev_err(aw_dev->dev, "write vcalb failed"); 73162306a36Sopenharmony_ci return ret; 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci ret = aw_dev_modify_dsp_cfg(aw_dev, AW88395_DSP_REG_VCALB, 73562306a36Sopenharmony_ci (u32)reg_val, AW88395_DSP_16_DATA); 73662306a36Sopenharmony_ci if (ret) 73762306a36Sopenharmony_ci dev_err(aw_dev->dev, "modify dsp cfg failed"); 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci return ret; 74062306a36Sopenharmony_ci} 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_cistatic int aw_dev_get_cali_f0_delay(struct aw_device *aw_dev) 74362306a36Sopenharmony_ci{ 74462306a36Sopenharmony_ci struct aw_cali_delay_desc *desc = &aw_dev->cali_delay_desc; 74562306a36Sopenharmony_ci u32 cali_delay; 74662306a36Sopenharmony_ci int ret; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci ret = aw_dev_dsp_read(aw_dev, 74962306a36Sopenharmony_ci AW88395_DSP_CALI_F0_DELAY, &cali_delay, AW88395_DSP_16_DATA); 75062306a36Sopenharmony_ci if (ret) 75162306a36Sopenharmony_ci dev_err(aw_dev->dev, "read cali delay failed, ret=%d", ret); 75262306a36Sopenharmony_ci else 75362306a36Sopenharmony_ci desc->delay = AW88395_CALI_DELAY_CACL(cali_delay); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "read cali delay: %d ms", desc->delay); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci return ret; 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic void aw_dev_get_int_status(struct aw_device *aw_dev, unsigned short *int_status) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci unsigned int reg_val; 76362306a36Sopenharmony_ci int ret; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_SYSINT_REG, ®_val); 76662306a36Sopenharmony_ci if (ret) 76762306a36Sopenharmony_ci dev_err(aw_dev->dev, "read interrupt reg fail, ret=%d", ret); 76862306a36Sopenharmony_ci else 76962306a36Sopenharmony_ci *int_status = reg_val; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "read interrupt reg = 0x%04x", *int_status); 77262306a36Sopenharmony_ci} 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_cistatic void aw_dev_clear_int_status(struct aw_device *aw_dev) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci u16 int_status; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci /* read int status and clear */ 77962306a36Sopenharmony_ci aw_dev_get_int_status(aw_dev, &int_status); 78062306a36Sopenharmony_ci /* make sure int status is clear */ 78162306a36Sopenharmony_ci aw_dev_get_int_status(aw_dev, &int_status); 78262306a36Sopenharmony_ci if (int_status) 78362306a36Sopenharmony_ci dev_info(aw_dev->dev, "int status(%d) is not cleaned.\n", int_status); 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_cistatic int aw_dev_get_iis_status(struct aw_device *aw_dev) 78762306a36Sopenharmony_ci{ 78862306a36Sopenharmony_ci unsigned int reg_val; 78962306a36Sopenharmony_ci int ret; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_SYSST_REG, ®_val); 79262306a36Sopenharmony_ci if (ret) 79362306a36Sopenharmony_ci return -EIO; 79462306a36Sopenharmony_ci if ((reg_val & AW88395_BIT_PLL_CHECK) != AW88395_BIT_PLL_CHECK) { 79562306a36Sopenharmony_ci dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val); 79662306a36Sopenharmony_ci return -EINVAL; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci return 0; 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic int aw_dev_check_mode1_pll(struct aw_device *aw_dev) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci int ret, i; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) { 80762306a36Sopenharmony_ci ret = aw_dev_get_iis_status(aw_dev); 80862306a36Sopenharmony_ci if (ret < 0) { 80962306a36Sopenharmony_ci dev_err(aw_dev->dev, "mode1 iis signal check error"); 81062306a36Sopenharmony_ci usleep_range(AW88395_2000_US, AW88395_2000_US + 10); 81162306a36Sopenharmony_ci } else { 81262306a36Sopenharmony_ci return 0; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci return -EPERM; 81762306a36Sopenharmony_ci} 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_cistatic int aw_dev_check_mode2_pll(struct aw_device *aw_dev) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci unsigned int reg_val; 82262306a36Sopenharmony_ci int ret, i; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_PLLCTRL1_REG, ®_val); 82562306a36Sopenharmony_ci if (ret) 82662306a36Sopenharmony_ci return ret; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci reg_val &= (~AW88395_CCO_MUX_MASK); 82962306a36Sopenharmony_ci if (reg_val == AW88395_CCO_MUX_DIVIDED_VALUE) { 83062306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "CCO_MUX is already divider"); 83162306a36Sopenharmony_ci return -EPERM; 83262306a36Sopenharmony_ci } 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci /* change mode2 */ 83562306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_PLLCTRL1_REG, 83662306a36Sopenharmony_ci ~AW88395_CCO_MUX_MASK, AW88395_CCO_MUX_DIVIDED_VALUE); 83762306a36Sopenharmony_ci if (ret) 83862306a36Sopenharmony_ci return ret; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) { 84162306a36Sopenharmony_ci ret = aw_dev_get_iis_status(aw_dev); 84262306a36Sopenharmony_ci if (ret) { 84362306a36Sopenharmony_ci dev_err(aw_dev->dev, "mode2 iis signal check error"); 84462306a36Sopenharmony_ci usleep_range(AW88395_2000_US, AW88395_2000_US + 10); 84562306a36Sopenharmony_ci } else { 84662306a36Sopenharmony_ci break; 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci /* change mode1 */ 85162306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_PLLCTRL1_REG, 85262306a36Sopenharmony_ci ~AW88395_CCO_MUX_MASK, AW88395_CCO_MUX_BYPASS_VALUE); 85362306a36Sopenharmony_ci if (ret == 0) { 85462306a36Sopenharmony_ci usleep_range(AW88395_2000_US, AW88395_2000_US + 10); 85562306a36Sopenharmony_ci for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) { 85662306a36Sopenharmony_ci ret = aw_dev_check_mode1_pll(aw_dev); 85762306a36Sopenharmony_ci if (ret < 0) { 85862306a36Sopenharmony_ci dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error"); 85962306a36Sopenharmony_ci usleep_range(AW88395_2000_US, AW88395_2000_US + 10); 86062306a36Sopenharmony_ci } else { 86162306a36Sopenharmony_ci break; 86262306a36Sopenharmony_ci } 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci return ret; 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_cistatic int aw_dev_check_syspll(struct aw_device *aw_dev) 87062306a36Sopenharmony_ci{ 87162306a36Sopenharmony_ci int ret; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci ret = aw_dev_check_mode1_pll(aw_dev); 87462306a36Sopenharmony_ci if (ret) { 87562306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check"); 87662306a36Sopenharmony_ci ret = aw_dev_check_mode2_pll(aw_dev); 87762306a36Sopenharmony_ci if (ret) { 87862306a36Sopenharmony_ci dev_err(aw_dev->dev, "mode2 check iis failed"); 87962306a36Sopenharmony_ci return ret; 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci } 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci return ret; 88462306a36Sopenharmony_ci} 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_cistatic int aw_dev_check_sysst(struct aw_device *aw_dev) 88762306a36Sopenharmony_ci{ 88862306a36Sopenharmony_ci unsigned int check_val; 88962306a36Sopenharmony_ci unsigned int reg_val; 89062306a36Sopenharmony_ci int ret, i; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) { 89362306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_SYSST_REG, ®_val); 89462306a36Sopenharmony_ci if (ret) 89562306a36Sopenharmony_ci return ret; 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci check_val = reg_val & (~AW88395_BIT_SYSST_CHECK_MASK) 89862306a36Sopenharmony_ci & AW88395_BIT_SYSST_CHECK; 89962306a36Sopenharmony_ci if (check_val != AW88395_BIT_SYSST_CHECK) { 90062306a36Sopenharmony_ci dev_err(aw_dev->dev, "check sysst fail, cnt=%d, reg_val=0x%04x, check:0x%x", 90162306a36Sopenharmony_ci i, reg_val, AW88395_BIT_SYSST_CHECK); 90262306a36Sopenharmony_ci usleep_range(AW88395_2000_US, AW88395_2000_US + 10); 90362306a36Sopenharmony_ci } else { 90462306a36Sopenharmony_ci return 0; 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci } 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci return -EPERM; 90962306a36Sopenharmony_ci} 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_cistatic int aw_dev_check_sysint(struct aw_device *aw_dev) 91262306a36Sopenharmony_ci{ 91362306a36Sopenharmony_ci u16 reg_val; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci aw_dev_get_int_status(aw_dev, ®_val); 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci if (reg_val & AW88395_BIT_SYSINT_CHECK) { 91862306a36Sopenharmony_ci dev_err(aw_dev->dev, "pa stop check fail:0x%04x", reg_val); 91962306a36Sopenharmony_ci return -EINVAL; 92062306a36Sopenharmony_ci } 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci return 0; 92362306a36Sopenharmony_ci} 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_cistatic void aw_dev_get_cur_mode_st(struct aw_device *aw_dev) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci struct aw_profctrl_desc *profctrl_desc = &aw_dev->profctrl_desc; 92862306a36Sopenharmony_ci unsigned int reg_val; 92962306a36Sopenharmony_ci int ret; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_SYSCTRL_REG, ®_val); 93262306a36Sopenharmony_ci if (ret) { 93362306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s failed", __func__); 93462306a36Sopenharmony_ci return; 93562306a36Sopenharmony_ci } 93662306a36Sopenharmony_ci if ((reg_val & (~AW88395_RCV_MODE_MASK)) == AW88395_RCV_MODE_RECEIVER_VALUE) 93762306a36Sopenharmony_ci profctrl_desc->cur_mode = AW88395_RCV_MODE; 93862306a36Sopenharmony_ci else 93962306a36Sopenharmony_ci profctrl_desc->cur_mode = AW88395_NOT_RCV_MODE; 94062306a36Sopenharmony_ci} 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_cistatic void aw_dev_get_dsp_config(struct aw_device *aw_dev, unsigned char *dsp_cfg) 94362306a36Sopenharmony_ci{ 94462306a36Sopenharmony_ci unsigned int reg_val = 0; 94562306a36Sopenharmony_ci int ret; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_SYSCTRL_REG, ®_val); 94862306a36Sopenharmony_ci if (ret) { 94962306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "%s failed", __func__); 95062306a36Sopenharmony_ci return; 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci if (reg_val & (~AW88395_DSPBY_MASK)) 95362306a36Sopenharmony_ci *dsp_cfg = AW88395_DEV_DSP_BYPASS; 95462306a36Sopenharmony_ci else 95562306a36Sopenharmony_ci *dsp_cfg = AW88395_DEV_DSP_WORK; 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_cistatic void aw_dev_select_memclk(struct aw_device *aw_dev, unsigned char flag) 95962306a36Sopenharmony_ci{ 96062306a36Sopenharmony_ci int ret; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci switch (flag) { 96362306a36Sopenharmony_ci case AW88395_DEV_MEMCLK_PLL: 96462306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_DBGCTRL_REG, 96562306a36Sopenharmony_ci ~AW88395_MEM_CLKSEL_MASK, 96662306a36Sopenharmony_ci AW88395_MEM_CLKSEL_DAP_HCLK_VALUE); 96762306a36Sopenharmony_ci if (ret) 96862306a36Sopenharmony_ci dev_err(aw_dev->dev, "memclk select pll failed"); 96962306a36Sopenharmony_ci break; 97062306a36Sopenharmony_ci case AW88395_DEV_MEMCLK_OSC: 97162306a36Sopenharmony_ci ret = regmap_update_bits(aw_dev->regmap, AW88395_DBGCTRL_REG, 97262306a36Sopenharmony_ci ~AW88395_MEM_CLKSEL_MASK, 97362306a36Sopenharmony_ci AW88395_MEM_CLKSEL_OSC_CLK_VALUE); 97462306a36Sopenharmony_ci if (ret) 97562306a36Sopenharmony_ci dev_err(aw_dev->dev, "memclk select OSC failed"); 97662306a36Sopenharmony_ci break; 97762306a36Sopenharmony_ci default: 97862306a36Sopenharmony_ci dev_err(aw_dev->dev, "unknown memclk config, flag=0x%x", flag); 97962306a36Sopenharmony_ci break; 98062306a36Sopenharmony_ci } 98162306a36Sopenharmony_ci} 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_cistatic int aw_dev_get_dsp_status(struct aw_device *aw_dev) 98462306a36Sopenharmony_ci{ 98562306a36Sopenharmony_ci unsigned int reg_val; 98662306a36Sopenharmony_ci int ret; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, AW88395_WDT_REG, ®_val); 98962306a36Sopenharmony_ci if (ret) 99062306a36Sopenharmony_ci return ret; 99162306a36Sopenharmony_ci if (!(reg_val & (~AW88395_WDT_CNT_MASK))) 99262306a36Sopenharmony_ci ret = -EPERM; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci return ret; 99562306a36Sopenharmony_ci} 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_cistatic int aw_dev_get_vmax(struct aw_device *aw_dev, unsigned int *vmax) 99862306a36Sopenharmony_ci{ 99962306a36Sopenharmony_ci return aw_dev_dsp_read(aw_dev, AW88395_DSP_REG_VMAX, vmax, AW88395_DSP_16_DATA); 100062306a36Sopenharmony_ci} 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_cistatic int aw_dev_update_reg_container(struct aw_device *aw_dev, 100362306a36Sopenharmony_ci unsigned char *data, unsigned int len) 100462306a36Sopenharmony_ci{ 100562306a36Sopenharmony_ci struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; 100662306a36Sopenharmony_ci unsigned int read_val; 100762306a36Sopenharmony_ci int16_t *reg_data; 100862306a36Sopenharmony_ci int data_len; 100962306a36Sopenharmony_ci u16 read_vol; 101062306a36Sopenharmony_ci u16 reg_val; 101162306a36Sopenharmony_ci u8 reg_addr; 101262306a36Sopenharmony_ci int i, ret; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci reg_data = (int16_t *)data; 101562306a36Sopenharmony_ci data_len = len >> 1; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci if (data_len & 0x1) { 101862306a36Sopenharmony_ci dev_err(aw_dev->dev, "data len:%d unsupported", data_len); 101962306a36Sopenharmony_ci return -EINVAL; 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci for (i = 0; i < data_len; i += 2) { 102362306a36Sopenharmony_ci reg_addr = reg_data[i]; 102462306a36Sopenharmony_ci reg_val = reg_data[i + 1]; 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci if (reg_addr == AW88395_SYSCTRL_REG) { 102762306a36Sopenharmony_ci ret = regmap_read(aw_dev->regmap, reg_addr, &read_val); 102862306a36Sopenharmony_ci if (ret) 102962306a36Sopenharmony_ci break; 103062306a36Sopenharmony_ci read_val &= (~AW88395_HMUTE_MASK); 103162306a36Sopenharmony_ci reg_val &= AW88395_HMUTE_MASK; 103262306a36Sopenharmony_ci reg_val |= read_val; 103362306a36Sopenharmony_ci } 103462306a36Sopenharmony_ci if (reg_addr == AW88395_HAGCCFG7_REG) 103562306a36Sopenharmony_ci reg_val &= AW88395_AGC_DSP_CTL_MASK; 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci if (reg_addr == AW88395_I2SCFG1_REG) { 103862306a36Sopenharmony_ci /* close tx */ 103962306a36Sopenharmony_ci reg_val &= AW88395_I2STXEN_MASK; 104062306a36Sopenharmony_ci reg_val |= AW88395_I2STXEN_DISABLE_VALUE; 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci if (reg_addr == AW88395_SYSCTRL2_REG) { 104462306a36Sopenharmony_ci read_vol = (reg_val & (~AW88395_VOL_MASK)) >> 104562306a36Sopenharmony_ci AW88395_VOL_START_BIT; 104662306a36Sopenharmony_ci aw_dev->volume_desc.init_volume = 104762306a36Sopenharmony_ci reg_val_to_db(read_vol); 104862306a36Sopenharmony_ci } 104962306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, reg_addr, reg_val); 105062306a36Sopenharmony_ci if (ret) 105162306a36Sopenharmony_ci break; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci } 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci aw_dev_get_cur_mode_st(aw_dev); 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci if (aw_dev->prof_cur != aw_dev->prof_index) { 105862306a36Sopenharmony_ci /* clear control volume when PA change profile */ 105962306a36Sopenharmony_ci vol_desc->ctl_volume = 0; 106062306a36Sopenharmony_ci } else { 106162306a36Sopenharmony_ci /* keep control volume when PA start with sync mode */ 106262306a36Sopenharmony_ci aw_dev_set_volume(aw_dev, vol_desc->ctl_volume); 106362306a36Sopenharmony_ci } 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci /* keep min volume */ 106662306a36Sopenharmony_ci if (aw_dev->fade_en) 106762306a36Sopenharmony_ci aw_dev_set_volume(aw_dev, AW88395_MUTE_VOL); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci aw_dev_get_dsp_config(aw_dev, &aw_dev->dsp_cfg); 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci return ret; 107262306a36Sopenharmony_ci} 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_cistatic int aw_dev_reg_update(struct aw_device *aw_dev, 107562306a36Sopenharmony_ci unsigned char *data, unsigned int len) 107662306a36Sopenharmony_ci{ 107762306a36Sopenharmony_ci int ret; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci if (!len || !data) { 108062306a36Sopenharmony_ci dev_err(aw_dev->dev, "reg data is null or len is 0"); 108162306a36Sopenharmony_ci return -EINVAL; 108262306a36Sopenharmony_ci } 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci ret = aw_dev_update_reg_container(aw_dev, data, len); 108562306a36Sopenharmony_ci if (ret) { 108662306a36Sopenharmony_ci dev_err(aw_dev->dev, "reg update failed"); 108762306a36Sopenharmony_ci return ret; 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci return 0; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic int aw_dev_get_ra(struct aw_cali_desc *cali_desc) 109462306a36Sopenharmony_ci{ 109562306a36Sopenharmony_ci struct aw_device *aw_dev = 109662306a36Sopenharmony_ci container_of(cali_desc, struct aw_device, cali_desc); 109762306a36Sopenharmony_ci u32 dsp_ra; 109862306a36Sopenharmony_ci int ret; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci ret = aw_dev_dsp_read(aw_dev, AW88395_DSP_REG_CFG_ADPZ_RA, 110162306a36Sopenharmony_ci &dsp_ra, AW88395_DSP_32_DATA); 110262306a36Sopenharmony_ci if (ret) { 110362306a36Sopenharmony_ci dev_err(aw_dev->dev, "read ra error"); 110462306a36Sopenharmony_ci return ret; 110562306a36Sopenharmony_ci } 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci cali_desc->ra = AW88395_DSP_RE_TO_SHOW_RE(dsp_ra, 110862306a36Sopenharmony_ci AW88395_DSP_RE_SHIFT); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci return ret; 111162306a36Sopenharmony_ci} 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_cistatic int aw_dev_dsp_update_container(struct aw_device *aw_dev, 111462306a36Sopenharmony_ci unsigned char *data, unsigned int len, unsigned short base) 111562306a36Sopenharmony_ci{ 111662306a36Sopenharmony_ci int i, ret; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci#ifdef AW88395_DSP_I2C_WRITES 111962306a36Sopenharmony_ci u32 tmp_len; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci mutex_lock(&aw_dev->dsp_lock); 112262306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, base); 112362306a36Sopenharmony_ci if (ret) 112462306a36Sopenharmony_ci goto error_operation; 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci for (i = 0; i < len; i += AW88395_MAX_RAM_WRITE_BYTE_SIZE) { 112762306a36Sopenharmony_ci if ((len - i) < AW88395_MAX_RAM_WRITE_BYTE_SIZE) 112862306a36Sopenharmony_ci tmp_len = len - i; 112962306a36Sopenharmony_ci else 113062306a36Sopenharmony_ci tmp_len = AW88395_MAX_RAM_WRITE_BYTE_SIZE; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci ret = regmap_raw_write(aw_dev->regmap, AW88395_DSPMDAT_REG, 113362306a36Sopenharmony_ci &data[i], tmp_len); 113462306a36Sopenharmony_ci if (ret) 113562306a36Sopenharmony_ci goto error_operation; 113662306a36Sopenharmony_ci } 113762306a36Sopenharmony_ci mutex_unlock(&aw_dev->dsp_lock); 113862306a36Sopenharmony_ci#else 113962306a36Sopenharmony_ci __be16 reg_val; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci mutex_lock(&aw_dev->dsp_lock); 114262306a36Sopenharmony_ci /* i2c write */ 114362306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, base); 114462306a36Sopenharmony_ci if (ret) 114562306a36Sopenharmony_ci goto error_operation; 114662306a36Sopenharmony_ci for (i = 0; i < len; i += 2) { 114762306a36Sopenharmony_ci reg_val = cpu_to_be16p((u16 *)(data + i)); 114862306a36Sopenharmony_ci ret = regmap_write(aw_dev->regmap, AW88395_DSPMDAT_REG, 114962306a36Sopenharmony_ci (u16)reg_val); 115062306a36Sopenharmony_ci if (ret) 115162306a36Sopenharmony_ci goto error_operation; 115262306a36Sopenharmony_ci } 115362306a36Sopenharmony_ci mutex_unlock(&aw_dev->dsp_lock); 115462306a36Sopenharmony_ci#endif 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci return 0; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_cierror_operation: 115962306a36Sopenharmony_ci mutex_unlock(&aw_dev->dsp_lock); 116062306a36Sopenharmony_ci return ret; 116162306a36Sopenharmony_ci} 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_cistatic int aw_dev_dsp_update_fw(struct aw_device *aw_dev, 116462306a36Sopenharmony_ci unsigned char *data, unsigned int len) 116562306a36Sopenharmony_ci{ 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "dsp firmware len:%d", len); 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci if (!len || !data) { 117062306a36Sopenharmony_ci dev_err(aw_dev->dev, "dsp firmware data is null or len is 0"); 117162306a36Sopenharmony_ci return -EINVAL; 117262306a36Sopenharmony_ci } 117362306a36Sopenharmony_ci aw_dev_dsp_update_container(aw_dev, data, len, AW88395_DSP_FW_ADDR); 117462306a36Sopenharmony_ci aw_dev->dsp_fw_len = len; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci return 0; 117762306a36Sopenharmony_ci} 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_cistatic int aw_dev_copy_to_crc_dsp_cfg(struct aw_device *aw_dev, 118062306a36Sopenharmony_ci unsigned char *data, unsigned int size) 118162306a36Sopenharmony_ci{ 118262306a36Sopenharmony_ci struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci if (!crc_dsp_cfg->data) { 118562306a36Sopenharmony_ci crc_dsp_cfg->data = devm_kzalloc(aw_dev->dev, size, GFP_KERNEL); 118662306a36Sopenharmony_ci if (!crc_dsp_cfg->data) 118762306a36Sopenharmony_ci return -ENOMEM; 118862306a36Sopenharmony_ci crc_dsp_cfg->len = size; 118962306a36Sopenharmony_ci } else if (crc_dsp_cfg->len < size) { 119062306a36Sopenharmony_ci devm_kfree(aw_dev->dev, crc_dsp_cfg->data); 119162306a36Sopenharmony_ci crc_dsp_cfg->data = devm_kzalloc(aw_dev->dev, size, GFP_KERNEL); 119262306a36Sopenharmony_ci if (!crc_dsp_cfg->data) 119362306a36Sopenharmony_ci return -ENOMEM; 119462306a36Sopenharmony_ci crc_dsp_cfg->len = size; 119562306a36Sopenharmony_ci } 119662306a36Sopenharmony_ci memcpy(crc_dsp_cfg->data, data, size); 119762306a36Sopenharmony_ci swab16_array((u16 *)crc_dsp_cfg->data, size >> 1); 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci return 0; 120062306a36Sopenharmony_ci} 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_cistatic int aw_dev_dsp_update_cfg(struct aw_device *aw_dev, 120362306a36Sopenharmony_ci unsigned char *data, unsigned int len) 120462306a36Sopenharmony_ci{ 120562306a36Sopenharmony_ci int ret; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "dsp config len:%d", len); 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci if (!len || !data) { 121062306a36Sopenharmony_ci dev_err(aw_dev->dev, "dsp config data is null or len is 0"); 121162306a36Sopenharmony_ci return -EINVAL; 121262306a36Sopenharmony_ci } 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci aw_dev_dsp_update_container(aw_dev, data, len, AW88395_DSP_CFG_ADDR); 121562306a36Sopenharmony_ci aw_dev->dsp_cfg_len = len; 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci ret = aw_dev_copy_to_crc_dsp_cfg(aw_dev, data, len); 121862306a36Sopenharmony_ci if (ret) 121962306a36Sopenharmony_ci return ret; 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci ret = aw_dev_set_vcalb(aw_dev); 122262306a36Sopenharmony_ci if (ret) 122362306a36Sopenharmony_ci return ret; 122462306a36Sopenharmony_ci ret = aw_dev_get_ra(&aw_dev->cali_desc); 122562306a36Sopenharmony_ci if (ret) 122662306a36Sopenharmony_ci return ret; 122762306a36Sopenharmony_ci ret = aw_dev_get_cali_f0_delay(aw_dev); 122862306a36Sopenharmony_ci if (ret) 122962306a36Sopenharmony_ci return ret; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci ret = aw_dev_get_vmax(aw_dev, &aw_dev->vmax_desc.init_vmax); 123262306a36Sopenharmony_ci if (ret) { 123362306a36Sopenharmony_ci dev_err(aw_dev->dev, "get vmax failed"); 123462306a36Sopenharmony_ci return ret; 123562306a36Sopenharmony_ci } 123662306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "get init vmax:0x%x", aw_dev->vmax_desc.init_vmax); 123762306a36Sopenharmony_ci aw_dev->dsp_crc_st = AW88395_DSP_CRC_NA; 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci return 0; 124062306a36Sopenharmony_ci} 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_cistatic int aw_dev_check_sram(struct aw_device *aw_dev) 124362306a36Sopenharmony_ci{ 124462306a36Sopenharmony_ci unsigned int reg_val; 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci mutex_lock(&aw_dev->dsp_lock); 124762306a36Sopenharmony_ci /* check the odd bits of reg 0x40 */ 124862306a36Sopenharmony_ci regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, AW88395_DSP_ODD_NUM_BIT_TEST); 124962306a36Sopenharmony_ci regmap_read(aw_dev->regmap, AW88395_DSPMADD_REG, ®_val); 125062306a36Sopenharmony_ci if (reg_val != AW88395_DSP_ODD_NUM_BIT_TEST) { 125162306a36Sopenharmony_ci dev_err(aw_dev->dev, "check reg 0x40 odd bit failed, read[0x%x] != write[0x%x]", 125262306a36Sopenharmony_ci reg_val, AW88395_DSP_ODD_NUM_BIT_TEST); 125362306a36Sopenharmony_ci goto error; 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci /* check the even bits of reg 0x40 */ 125762306a36Sopenharmony_ci regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, AW88395_DSP_EVEN_NUM_BIT_TEST); 125862306a36Sopenharmony_ci regmap_read(aw_dev->regmap, AW88395_DSPMADD_REG, ®_val); 125962306a36Sopenharmony_ci if (reg_val != AW88395_DSP_EVEN_NUM_BIT_TEST) { 126062306a36Sopenharmony_ci dev_err(aw_dev->dev, "check reg 0x40 even bit failed, read[0x%x] != write[0x%x]", 126162306a36Sopenharmony_ci reg_val, AW88395_DSP_EVEN_NUM_BIT_TEST); 126262306a36Sopenharmony_ci goto error; 126362306a36Sopenharmony_ci } 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci /* check dsp_fw_base_addr */ 126662306a36Sopenharmony_ci aw_dev_dsp_write_16bit(aw_dev, AW88395_DSP_FW_ADDR, AW88395_DSP_EVEN_NUM_BIT_TEST); 126762306a36Sopenharmony_ci aw_dev_dsp_read_16bit(aw_dev, AW88395_DSP_FW_ADDR, ®_val); 126862306a36Sopenharmony_ci if (reg_val != AW88395_DSP_EVEN_NUM_BIT_TEST) { 126962306a36Sopenharmony_ci dev_err(aw_dev->dev, "check dsp fw addr failed, read[0x%x] != write[0x%x]", 127062306a36Sopenharmony_ci reg_val, AW88395_DSP_EVEN_NUM_BIT_TEST); 127162306a36Sopenharmony_ci goto error; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci /* check dsp_cfg_base_addr */ 127562306a36Sopenharmony_ci aw_dev_dsp_write_16bit(aw_dev, AW88395_DSP_CFG_ADDR, AW88395_DSP_ODD_NUM_BIT_TEST); 127662306a36Sopenharmony_ci aw_dev_dsp_read_16bit(aw_dev, AW88395_DSP_CFG_ADDR, ®_val); 127762306a36Sopenharmony_ci if (reg_val != AW88395_DSP_ODD_NUM_BIT_TEST) { 127862306a36Sopenharmony_ci dev_err(aw_dev->dev, "check dsp cfg failed, read[0x%x] != write[0x%x]", 127962306a36Sopenharmony_ci reg_val, AW88395_DSP_ODD_NUM_BIT_TEST); 128062306a36Sopenharmony_ci goto error; 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci mutex_unlock(&aw_dev->dsp_lock); 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci return 0; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cierror: 128762306a36Sopenharmony_ci mutex_unlock(&aw_dev->dsp_lock); 128862306a36Sopenharmony_ci return -EPERM; 128962306a36Sopenharmony_ci} 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ciint aw88395_dev_fw_update(struct aw_device *aw_dev, bool up_dsp_fw_en, bool force_up_en) 129262306a36Sopenharmony_ci{ 129362306a36Sopenharmony_ci struct aw_prof_desc *prof_index_desc; 129462306a36Sopenharmony_ci struct aw_sec_data_desc *sec_desc; 129562306a36Sopenharmony_ci char *prof_name; 129662306a36Sopenharmony_ci int ret; 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci if ((aw_dev->prof_cur == aw_dev->prof_index) && 129962306a36Sopenharmony_ci (force_up_en == AW88395_FORCE_UPDATE_OFF)) { 130062306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "scene no change, not update"); 130162306a36Sopenharmony_ci return 0; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci if (aw_dev->fw_status == AW88395_DEV_FW_FAILED) { 130562306a36Sopenharmony_ci dev_err(aw_dev->dev, "fw status[%d] error", aw_dev->fw_status); 130662306a36Sopenharmony_ci return -EPERM; 130762306a36Sopenharmony_ci } 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci prof_name = aw88395_dev_get_prof_name(aw_dev, aw_dev->prof_index); 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "start update %s", prof_name); 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci ret = aw88395_dev_get_prof_data(aw_dev, aw_dev->prof_index, &prof_index_desc); 131462306a36Sopenharmony_ci if (ret) 131562306a36Sopenharmony_ci return ret; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci /* update reg */ 131862306a36Sopenharmony_ci sec_desc = prof_index_desc->sec_desc; 131962306a36Sopenharmony_ci ret = aw_dev_reg_update(aw_dev, sec_desc[AW88395_DATA_TYPE_REG].data, 132062306a36Sopenharmony_ci sec_desc[AW88395_DATA_TYPE_REG].len); 132162306a36Sopenharmony_ci if (ret) { 132262306a36Sopenharmony_ci dev_err(aw_dev->dev, "update reg failed"); 132362306a36Sopenharmony_ci return ret; 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci aw88395_dev_mute(aw_dev, true); 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci if (aw_dev->dsp_cfg == AW88395_DEV_DSP_WORK) 132962306a36Sopenharmony_ci aw_dev_dsp_enable(aw_dev, false); 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci aw_dev_select_memclk(aw_dev, AW88395_DEV_MEMCLK_OSC); 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci if (up_dsp_fw_en) { 133462306a36Sopenharmony_ci ret = aw_dev_check_sram(aw_dev); 133562306a36Sopenharmony_ci if (ret) { 133662306a36Sopenharmony_ci dev_err(aw_dev->dev, "check sram failed"); 133762306a36Sopenharmony_ci goto error; 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci /* update dsp firmware */ 134162306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "fw_ver: [%x]", prof_index_desc->fw_ver); 134262306a36Sopenharmony_ci ret = aw_dev_dsp_update_fw(aw_dev, sec_desc[AW88395_DATA_TYPE_DSP_FW].data, 134362306a36Sopenharmony_ci sec_desc[AW88395_DATA_TYPE_DSP_FW].len); 134462306a36Sopenharmony_ci if (ret) { 134562306a36Sopenharmony_ci dev_err(aw_dev->dev, "update dsp fw failed"); 134662306a36Sopenharmony_ci goto error; 134762306a36Sopenharmony_ci } 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci /* update dsp config */ 135162306a36Sopenharmony_ci ret = aw_dev_dsp_update_cfg(aw_dev, sec_desc[AW88395_DATA_TYPE_DSP_CFG].data, 135262306a36Sopenharmony_ci sec_desc[AW88395_DATA_TYPE_DSP_CFG].len); 135362306a36Sopenharmony_ci if (ret) { 135462306a36Sopenharmony_ci dev_err(aw_dev->dev, "update dsp cfg failed"); 135562306a36Sopenharmony_ci goto error; 135662306a36Sopenharmony_ci } 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci aw_dev_select_memclk(aw_dev, AW88395_DEV_MEMCLK_PLL); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci aw_dev->prof_cur = aw_dev->prof_index; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci return 0; 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_cierror: 136562306a36Sopenharmony_ci aw_dev_select_memclk(aw_dev, AW88395_DEV_MEMCLK_PLL); 136662306a36Sopenharmony_ci return ret; 136762306a36Sopenharmony_ci} 136862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_fw_update); 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_cistatic int aw_dev_dsp_check(struct aw_device *aw_dev) 137162306a36Sopenharmony_ci{ 137262306a36Sopenharmony_ci int ret, i; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci switch (aw_dev->dsp_cfg) { 137562306a36Sopenharmony_ci case AW88395_DEV_DSP_BYPASS: 137662306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "dsp bypass"); 137762306a36Sopenharmony_ci ret = 0; 137862306a36Sopenharmony_ci break; 137962306a36Sopenharmony_ci case AW88395_DEV_DSP_WORK: 138062306a36Sopenharmony_ci aw_dev_dsp_enable(aw_dev, false); 138162306a36Sopenharmony_ci aw_dev_dsp_enable(aw_dev, true); 138262306a36Sopenharmony_ci usleep_range(AW88395_1000_US, AW88395_1000_US + 10); 138362306a36Sopenharmony_ci for (i = 0; i < AW88395_DEV_DSP_CHECK_MAX; i++) { 138462306a36Sopenharmony_ci ret = aw_dev_get_dsp_status(aw_dev); 138562306a36Sopenharmony_ci if (ret) { 138662306a36Sopenharmony_ci dev_err(aw_dev->dev, "dsp wdt status error=%d", ret); 138762306a36Sopenharmony_ci usleep_range(AW88395_2000_US, AW88395_2000_US + 10); 138862306a36Sopenharmony_ci } 138962306a36Sopenharmony_ci } 139062306a36Sopenharmony_ci break; 139162306a36Sopenharmony_ci default: 139262306a36Sopenharmony_ci dev_err(aw_dev->dev, "unknown dsp cfg=%d", aw_dev->dsp_cfg); 139362306a36Sopenharmony_ci ret = -EINVAL; 139462306a36Sopenharmony_ci break; 139562306a36Sopenharmony_ci } 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci return ret; 139862306a36Sopenharmony_ci} 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_cistatic void aw_dev_update_cali_re(struct aw_cali_desc *cali_desc) 140162306a36Sopenharmony_ci{ 140262306a36Sopenharmony_ci struct aw_device *aw_dev = 140362306a36Sopenharmony_ci container_of(cali_desc, struct aw_device, cali_desc); 140462306a36Sopenharmony_ci int ret; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci if ((aw_dev->cali_desc.cali_re < AW88395_CALI_RE_MAX) && 140762306a36Sopenharmony_ci (aw_dev->cali_desc.cali_re > AW88395_CALI_RE_MIN)) { 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci ret = aw_dev_dsp_set_cali_re(aw_dev); 141062306a36Sopenharmony_ci if (ret) 141162306a36Sopenharmony_ci dev_err(aw_dev->dev, "set cali re failed"); 141262306a36Sopenharmony_ci } 141362306a36Sopenharmony_ci} 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ciint aw88395_dev_start(struct aw_device *aw_dev) 141662306a36Sopenharmony_ci{ 141762306a36Sopenharmony_ci int ret; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (aw_dev->status == AW88395_DEV_PW_ON) { 142062306a36Sopenharmony_ci dev_info(aw_dev->dev, "already power on"); 142162306a36Sopenharmony_ci return 0; 142262306a36Sopenharmony_ci } 142362306a36Sopenharmony_ci /* power on */ 142462306a36Sopenharmony_ci aw_dev_pwd(aw_dev, false); 142562306a36Sopenharmony_ci usleep_range(AW88395_2000_US, AW88395_2000_US + 10); 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci ret = aw_dev_check_syspll(aw_dev); 142862306a36Sopenharmony_ci if (ret) { 142962306a36Sopenharmony_ci dev_err(aw_dev->dev, "pll check failed cannot start"); 143062306a36Sopenharmony_ci goto pll_check_fail; 143162306a36Sopenharmony_ci } 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci /* amppd on */ 143462306a36Sopenharmony_ci aw_dev_amppd(aw_dev, false); 143562306a36Sopenharmony_ci usleep_range(AW88395_1000_US, AW88395_1000_US + 50); 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci /* check i2s status */ 143862306a36Sopenharmony_ci ret = aw_dev_check_sysst(aw_dev); 143962306a36Sopenharmony_ci if (ret) { 144062306a36Sopenharmony_ci dev_err(aw_dev->dev, "sysst check failed"); 144162306a36Sopenharmony_ci goto sysst_check_fail; 144262306a36Sopenharmony_ci } 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci if (aw_dev->dsp_cfg == AW88395_DEV_DSP_WORK) { 144562306a36Sopenharmony_ci /* dsp bypass */ 144662306a36Sopenharmony_ci aw_dev_dsp_enable(aw_dev, false); 144762306a36Sopenharmony_ci ret = aw_dev_dsp_fw_check(aw_dev); 144862306a36Sopenharmony_ci if (ret) 144962306a36Sopenharmony_ci goto dev_dsp_fw_check_fail; 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci aw_dev_update_cali_re(&aw_dev->cali_desc); 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci if (aw_dev->dsp_crc_st != AW88395_DSP_CRC_OK) { 145462306a36Sopenharmony_ci ret = aw_dev_dsp_check_crc32(aw_dev); 145562306a36Sopenharmony_ci if (ret) { 145662306a36Sopenharmony_ci dev_err(aw_dev->dev, "dsp crc check failed"); 145762306a36Sopenharmony_ci goto crc_check_fail; 145862306a36Sopenharmony_ci } 145962306a36Sopenharmony_ci } 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci ret = aw_dev_dsp_check(aw_dev); 146262306a36Sopenharmony_ci if (ret) { 146362306a36Sopenharmony_ci dev_err(aw_dev->dev, "dsp status check failed"); 146462306a36Sopenharmony_ci goto dsp_check_fail; 146562306a36Sopenharmony_ci } 146662306a36Sopenharmony_ci } else { 146762306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "start pa with dsp bypass"); 146862306a36Sopenharmony_ci } 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci /* enable tx feedback */ 147162306a36Sopenharmony_ci aw_dev_i2s_tx_enable(aw_dev, true); 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci /* close mute */ 147462306a36Sopenharmony_ci aw88395_dev_mute(aw_dev, false); 147562306a36Sopenharmony_ci /* clear inturrupt */ 147662306a36Sopenharmony_ci aw_dev_clear_int_status(aw_dev); 147762306a36Sopenharmony_ci aw_dev->status = AW88395_DEV_PW_ON; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci return 0; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_cidsp_check_fail: 148262306a36Sopenharmony_cicrc_check_fail: 148362306a36Sopenharmony_ci aw_dev_dsp_enable(aw_dev, false); 148462306a36Sopenharmony_cidev_dsp_fw_check_fail: 148562306a36Sopenharmony_cisysst_check_fail: 148662306a36Sopenharmony_ci aw_dev_clear_int_status(aw_dev); 148762306a36Sopenharmony_ci aw_dev_amppd(aw_dev, true); 148862306a36Sopenharmony_cipll_check_fail: 148962306a36Sopenharmony_ci aw_dev_pwd(aw_dev, true); 149062306a36Sopenharmony_ci aw_dev->status = AW88395_DEV_PW_OFF; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci return ret; 149362306a36Sopenharmony_ci} 149462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_start); 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ciint aw88395_dev_stop(struct aw_device *aw_dev) 149762306a36Sopenharmony_ci{ 149862306a36Sopenharmony_ci struct aw_sec_data_desc *dsp_cfg = 149962306a36Sopenharmony_ci &aw_dev->prof_info.prof_desc[aw_dev->prof_cur].sec_desc[AW88395_DATA_TYPE_DSP_CFG]; 150062306a36Sopenharmony_ci struct aw_sec_data_desc *dsp_fw = 150162306a36Sopenharmony_ci &aw_dev->prof_info.prof_desc[aw_dev->prof_cur].sec_desc[AW88395_DATA_TYPE_DSP_FW]; 150262306a36Sopenharmony_ci int int_st = 0; 150362306a36Sopenharmony_ci int ret; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci if (aw_dev->status == AW88395_DEV_PW_OFF) { 150662306a36Sopenharmony_ci dev_info(aw_dev->dev, "already power off"); 150762306a36Sopenharmony_ci return 0; 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci aw_dev->status = AW88395_DEV_PW_OFF; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci /* set mute */ 151362306a36Sopenharmony_ci aw88395_dev_mute(aw_dev, true); 151462306a36Sopenharmony_ci usleep_range(AW88395_4000_US, AW88395_4000_US + 100); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci /* close tx feedback */ 151762306a36Sopenharmony_ci aw_dev_i2s_tx_enable(aw_dev, false); 151862306a36Sopenharmony_ci usleep_range(AW88395_1000_US, AW88395_1000_US + 100); 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci /* check sysint state */ 152162306a36Sopenharmony_ci int_st = aw_dev_check_sysint(aw_dev); 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci /* close dsp */ 152462306a36Sopenharmony_ci aw_dev_dsp_enable(aw_dev, false); 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci /* enable amppd */ 152762306a36Sopenharmony_ci aw_dev_amppd(aw_dev, true); 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci if (int_st < 0) { 153062306a36Sopenharmony_ci /* system status anomaly */ 153162306a36Sopenharmony_ci aw_dev_select_memclk(aw_dev, AW88395_DEV_MEMCLK_OSC); 153262306a36Sopenharmony_ci ret = aw_dev_dsp_update_fw(aw_dev, dsp_fw->data, dsp_fw->len); 153362306a36Sopenharmony_ci if (ret) 153462306a36Sopenharmony_ci dev_err(aw_dev->dev, "update dsp fw failed"); 153562306a36Sopenharmony_ci ret = aw_dev_dsp_update_cfg(aw_dev, dsp_cfg->data, dsp_cfg->len); 153662306a36Sopenharmony_ci if (ret) 153762306a36Sopenharmony_ci dev_err(aw_dev->dev, "update dsp cfg failed"); 153862306a36Sopenharmony_ci aw_dev_select_memclk(aw_dev, AW88395_DEV_MEMCLK_PLL); 153962306a36Sopenharmony_ci } 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci /* set power down */ 154262306a36Sopenharmony_ci aw_dev_pwd(aw_dev, true); 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci return 0; 154562306a36Sopenharmony_ci} 154662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_stop); 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ciint aw88395_dev_init(struct aw_device *aw_dev, struct aw_container *aw_cfg) 154962306a36Sopenharmony_ci{ 155062306a36Sopenharmony_ci int ret; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci if ((!aw_dev) || (!aw_cfg)) { 155362306a36Sopenharmony_ci pr_err("aw_dev is NULL or aw_cfg is NULL"); 155462306a36Sopenharmony_ci return -ENOMEM; 155562306a36Sopenharmony_ci } 155662306a36Sopenharmony_ci ret = aw88395_dev_cfg_load(aw_dev, aw_cfg); 155762306a36Sopenharmony_ci if (ret) { 155862306a36Sopenharmony_ci dev_err(aw_dev->dev, "aw_dev acf parse failed"); 155962306a36Sopenharmony_ci return -EINVAL; 156062306a36Sopenharmony_ci } 156162306a36Sopenharmony_ci aw_dev->fade_in_time = AW88395_1000_US / 10; 156262306a36Sopenharmony_ci aw_dev->fade_out_time = AW88395_1000_US >> 1; 156362306a36Sopenharmony_ci aw_dev->prof_cur = aw_dev->prof_info.prof_desc[0].id; 156462306a36Sopenharmony_ci aw_dev->prof_index = aw_dev->prof_info.prof_desc[0].id; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci ret = aw88395_dev_fw_update(aw_dev, AW88395_FORCE_UPDATE_ON, AW88395_DSP_FW_UPDATE_ON); 156762306a36Sopenharmony_ci if (ret) { 156862306a36Sopenharmony_ci dev_err(aw_dev->dev, "fw update failed ret = %d\n", ret); 156962306a36Sopenharmony_ci return ret; 157062306a36Sopenharmony_ci } 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci /* set mute */ 157362306a36Sopenharmony_ci aw88395_dev_mute(aw_dev, true); 157462306a36Sopenharmony_ci usleep_range(AW88395_4000_US, AW88395_4000_US + 100); 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci /* close tx feedback */ 157762306a36Sopenharmony_ci aw_dev_i2s_tx_enable(aw_dev, false); 157862306a36Sopenharmony_ci usleep_range(AW88395_1000_US, AW88395_1000_US + 100); 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci /* close dsp */ 158162306a36Sopenharmony_ci aw_dev_dsp_enable(aw_dev, false); 158262306a36Sopenharmony_ci /* enable amppd */ 158362306a36Sopenharmony_ci aw_dev_amppd(aw_dev, true); 158462306a36Sopenharmony_ci /* set power down */ 158562306a36Sopenharmony_ci aw_dev_pwd(aw_dev, true); 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci return 0; 158862306a36Sopenharmony_ci} 158962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_init); 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_cistatic void aw88395_parse_channel_dt(struct aw_device *aw_dev) 159262306a36Sopenharmony_ci{ 159362306a36Sopenharmony_ci struct device_node *np = aw_dev->dev->of_node; 159462306a36Sopenharmony_ci u32 channel_value; 159562306a36Sopenharmony_ci int ret; 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci ret = of_property_read_u32(np, "sound-channel", &channel_value); 159862306a36Sopenharmony_ci if (ret) { 159962306a36Sopenharmony_ci dev_dbg(aw_dev->dev, 160062306a36Sopenharmony_ci "read sound-channel failed,use default 0"); 160162306a36Sopenharmony_ci aw_dev->channel = AW88395_DEV_DEFAULT_CH; 160262306a36Sopenharmony_ci return; 160362306a36Sopenharmony_ci } 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "read sound-channel value is: %d", 160662306a36Sopenharmony_ci channel_value); 160762306a36Sopenharmony_ci aw_dev->channel = channel_value; 160862306a36Sopenharmony_ci} 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_cistatic void aw88395_parse_fade_enable_dt(struct aw_device *aw_dev) 161162306a36Sopenharmony_ci{ 161262306a36Sopenharmony_ci struct device_node *np = aw_dev->dev->of_node; 161362306a36Sopenharmony_ci u32 fade_en; 161462306a36Sopenharmony_ci int ret; 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci ret = of_property_read_u32(np, "fade-enable", &fade_en); 161762306a36Sopenharmony_ci if (ret) { 161862306a36Sopenharmony_ci dev_dbg(aw_dev->dev, 161962306a36Sopenharmony_ci "read fade-enable failed, close fade_in_out"); 162062306a36Sopenharmony_ci fade_en = AW88395_FADE_IN_OUT_DEFAULT; 162162306a36Sopenharmony_ci } 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "read fade-enable value is: %d", fade_en); 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci aw_dev->fade_en = fade_en; 162662306a36Sopenharmony_ci} 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_cistatic int aw_dev_init(struct aw_device *aw_dev) 162962306a36Sopenharmony_ci{ 163062306a36Sopenharmony_ci aw_dev->chip_id = AW88395_CHIP_ID; 163162306a36Sopenharmony_ci /* call aw device init func */ 163262306a36Sopenharmony_ci aw_dev->acf = NULL; 163362306a36Sopenharmony_ci aw_dev->prof_info.prof_desc = NULL; 163462306a36Sopenharmony_ci aw_dev->prof_info.count = 0; 163562306a36Sopenharmony_ci aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; 163662306a36Sopenharmony_ci aw_dev->channel = 0; 163762306a36Sopenharmony_ci aw_dev->fw_status = AW88395_DEV_FW_FAILED; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci aw_dev->fade_step = AW88395_VOLUME_STEP_DB; 164062306a36Sopenharmony_ci aw_dev->volume_desc.ctl_volume = AW88395_VOL_DEFAULT_VALUE; 164162306a36Sopenharmony_ci aw88395_parse_channel_dt(aw_dev); 164262306a36Sopenharmony_ci aw88395_parse_fade_enable_dt(aw_dev); 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci return 0; 164562306a36Sopenharmony_ci} 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ciint aw88395_dev_get_profile_count(struct aw_device *aw_dev) 164862306a36Sopenharmony_ci{ 164962306a36Sopenharmony_ci return aw_dev->prof_info.count; 165062306a36Sopenharmony_ci} 165162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_get_profile_count); 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ciint aw88395_dev_get_profile_index(struct aw_device *aw_dev) 165462306a36Sopenharmony_ci{ 165562306a36Sopenharmony_ci return aw_dev->prof_index; 165662306a36Sopenharmony_ci} 165762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_get_profile_index); 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ciint aw88395_dev_set_profile_index(struct aw_device *aw_dev, int index) 166062306a36Sopenharmony_ci{ 166162306a36Sopenharmony_ci /* check the index whether is valid */ 166262306a36Sopenharmony_ci if ((index >= aw_dev->prof_info.count) || (index < 0)) 166362306a36Sopenharmony_ci return -EINVAL; 166462306a36Sopenharmony_ci /* check the index whether change */ 166562306a36Sopenharmony_ci if (aw_dev->prof_index == index) 166662306a36Sopenharmony_ci return -EINVAL; 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci aw_dev->prof_index = index; 166962306a36Sopenharmony_ci dev_dbg(aw_dev->dev, "set prof[%s]", 167062306a36Sopenharmony_ci aw_dev->prof_info.prof_name_list[aw_dev->prof_info.prof_desc[index].id]); 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci return 0; 167362306a36Sopenharmony_ci} 167462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_set_profile_index); 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_cichar *aw88395_dev_get_prof_name(struct aw_device *aw_dev, int index) 167762306a36Sopenharmony_ci{ 167862306a36Sopenharmony_ci struct aw_prof_info *prof_info = &aw_dev->prof_info; 167962306a36Sopenharmony_ci struct aw_prof_desc *prof_desc; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci if ((index >= aw_dev->prof_info.count) || (index < 0)) { 168262306a36Sopenharmony_ci dev_err(aw_dev->dev, "index[%d] overflow count[%d]", 168362306a36Sopenharmony_ci index, aw_dev->prof_info.count); 168462306a36Sopenharmony_ci return NULL; 168562306a36Sopenharmony_ci } 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci prof_desc = &aw_dev->prof_info.prof_desc[index]; 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci return prof_info->prof_name_list[prof_desc->id]; 169062306a36Sopenharmony_ci} 169162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_get_prof_name); 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ciint aw88395_dev_get_prof_data(struct aw_device *aw_dev, int index, 169462306a36Sopenharmony_ci struct aw_prof_desc **prof_desc) 169562306a36Sopenharmony_ci{ 169662306a36Sopenharmony_ci if ((index >= aw_dev->prof_info.count) || (index < 0)) { 169762306a36Sopenharmony_ci dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n", 169862306a36Sopenharmony_ci __func__, index, aw_dev->prof_info.count); 169962306a36Sopenharmony_ci return -EINVAL; 170062306a36Sopenharmony_ci } 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci *prof_desc = &aw_dev->prof_info.prof_desc[index]; 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci return 0; 170562306a36Sopenharmony_ci} 170662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_dev_get_prof_data); 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ciint aw88395_init(struct aw_device **aw_dev, struct i2c_client *i2c, struct regmap *regmap) 170962306a36Sopenharmony_ci{ 171062306a36Sopenharmony_ci u16 chip_id; 171162306a36Sopenharmony_ci int ret; 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci if (*aw_dev) { 171462306a36Sopenharmony_ci dev_info(&i2c->dev, "it should be initialized here.\n"); 171562306a36Sopenharmony_ci } else { 171662306a36Sopenharmony_ci *aw_dev = devm_kzalloc(&i2c->dev, sizeof(struct aw_device), GFP_KERNEL); 171762306a36Sopenharmony_ci if (!(*aw_dev)) 171862306a36Sopenharmony_ci return -ENOMEM; 171962306a36Sopenharmony_ci } 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci (*aw_dev)->i2c = i2c; 172262306a36Sopenharmony_ci (*aw_dev)->dev = &i2c->dev; 172362306a36Sopenharmony_ci (*aw_dev)->regmap = regmap; 172462306a36Sopenharmony_ci mutex_init(&(*aw_dev)->dsp_lock); 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci /* read chip id */ 172762306a36Sopenharmony_ci ret = aw_dev_read_chipid((*aw_dev), &chip_id); 172862306a36Sopenharmony_ci if (ret) { 172962306a36Sopenharmony_ci dev_err(&i2c->dev, "dev_read_chipid failed ret=%d", ret); 173062306a36Sopenharmony_ci return ret; 173162306a36Sopenharmony_ci } 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_ci switch (chip_id) { 173462306a36Sopenharmony_ci case AW88395_CHIP_ID: 173562306a36Sopenharmony_ci ret = aw_dev_init((*aw_dev)); 173662306a36Sopenharmony_ci break; 173762306a36Sopenharmony_ci default: 173862306a36Sopenharmony_ci ret = -EINVAL; 173962306a36Sopenharmony_ci dev_err((*aw_dev)->dev, "unsupported device"); 174062306a36Sopenharmony_ci break; 174162306a36Sopenharmony_ci } 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci return ret; 174462306a36Sopenharmony_ci} 174562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aw88395_init); 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ciMODULE_DESCRIPTION("AW88395 device lib"); 174862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1749