// SPDX-License-Identifier: GPL-2.0+ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "aw_data_type.h" #include "aw_log.h" #include "aw_device.h" #include "aw_bin_parse.h" #include "aw_calib.h" #define AW_DEV_SYSST_CHECK_MAX (10) enum { AW_EXT_DSP_WRITE_NONE = 0, AW_EXT_DSP_WRITE, }; static unsigned int g_fade_in_time = AW_1000_US / 10; static unsigned int g_fade_out_time = AW_1000_US >> 1; static LIST_HEAD(g_dev_list); static DEFINE_MUTEX(g_dev_lock); static int aw_dev_reg_dump(struct aw_device *aw_dev) { int reg_num = aw_dev->ops.aw_get_reg_num(); uint8_t i = 0; uint16_t reg_val = 0; for (i = 0; i < reg_num; i++) { if (aw_dev->ops.aw_check_rd_access(i)) { aw_dev->ops.aw_reg_read(aw_dev, i, ®_val); aw_dev_info(aw_dev->dev, "read: reg = 0x%02x, val = 0x%04x", i, reg_val); } } return 0; } static void aw_dev_fade_in(struct aw_device *aw_dev) { int i = 0; struct aw_volume_desc *desc = &aw_dev->volume_desc; int fade_step = aw_dev->fade_step; if (!aw_dev->fade_en) return; if (fade_step == 0 || g_fade_in_time == 0) { aw_dev->ops.aw_set_volume(aw_dev, desc->init_volume); return; } /*volume up*/ for (i = desc->mute_volume; i >= desc->init_volume; i -= fade_step) { aw_dev->ops.aw_set_volume(aw_dev, i); usleep_range(g_fade_in_time, g_fade_in_time + 10); } if (i != desc->init_volume) aw_dev->ops.aw_set_volume(aw_dev, desc->init_volume); } static void aw_dev_fade_out(struct aw_device *aw_dev) { int i = 0; uint16_t start_volume = 0; struct aw_volume_desc *desc = &aw_dev->volume_desc; int fade_step = aw_dev->fade_step; if (!aw_dev->fade_en) return; if (fade_step == 0 || g_fade_out_time == 0) { aw_dev->ops.aw_set_volume(aw_dev, desc->mute_volume); return; } aw_dev->ops.aw_get_volume(aw_dev, &start_volume); for (i = start_volume; i <= desc->mute_volume; i += fade_step) { aw_dev->ops.aw_set_volume(aw_dev, i); usleep_range(g_fade_out_time, g_fade_out_time + 10); } if (i != desc->mute_volume) { aw_dev->ops.aw_set_volume(aw_dev, desc->mute_volume); usleep_range(g_fade_out_time, g_fade_out_time + 10); } } int aw_dev_get_fade_vol_step(struct aw_device *aw_dev) { return aw_dev->fade_step; } void aw_dev_set_fade_vol_step(struct aw_device *aw_dev, unsigned int step) { aw_dev->fade_step = step; } void aw_dev_get_fade_time(unsigned int *time, bool fade_in) { if (fade_in) *time = g_fade_in_time; else *time = g_fade_out_time; } void aw_dev_set_fade_time(unsigned int time, bool fade_in) { if (fade_in) g_fade_in_time = time; else g_fade_out_time = time; } static uint64_t aw_dev_dsp_crc32_reflect(uint64_t ref, uint8_t ch) { int i; uint64_t value = 0; for (i = 1; i < (ch + 1); i++) { if (ref & 1) value |= (uint64_t)1 << (ch - i); ref >>= 1; } return value; } static uint32_t aw_dev_calc_dsp_cfg_crc32(uint8_t *buf, uint32_t len) { uint8_t i; uint32_t crc = 0xffffffff; while (len--) { for (i = 1; i != 0; i <<= 1) { if ((crc & 0x80000000) != 0) { crc <<= 1; crc ^= 0x1EDC6F41; } else { crc <<= 1; } if ((*buf & i) != 0) crc ^= 0x1EDC6F41; } buf++; } return (aw_dev_dsp_crc32_reflect(crc, 32)^0xffffffff); } static int aw_dev_set_dsp_crc32(struct aw_device *aw_dev) { uint32_t crc_value; uint32_t crc_data_len = 0; int ret = 0; struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; struct aw_dsp_crc_desc *desc = &aw_dev->dsp_crc_desc; /*get crc data len*/ crc_data_len = (desc->dsp_reg - aw_dev->dsp_mem_desc.dsp_cfg_base_addr) * 2; if (crc_data_len > crc_dsp_cfg->len) { aw_dev_err(aw_dev->dev, "crc data len :%d > cfg_data len:%d", crc_data_len, crc_dsp_cfg->len); return ret; } if (crc_data_len % 4 != 0) { aw_dev_err(aw_dev->dev, "The crc data len :%d unsupport", crc_data_len); return ret; } crc_value = aw_dev_calc_dsp_cfg_crc32(crc_dsp_cfg->data, crc_data_len); aw_dev_info(aw_dev->dev, "crc_value:0x%x", crc_value); ret = aw_dev->ops.aw_dsp_write(aw_dev, desc->dsp_reg, crc_value, desc->data_type); if (ret < 0) { aw_dev_err(aw_dev->dev, "set dsp crc value failed"); return ret; } return 0; } static int aw_dev_dsp_crc_check_enable(struct aw_device *aw_dev, bool flag) { struct aw_dsp_crc_desc *dsp_crc_desc = &aw_dev->dsp_crc_desc; int ret; aw_dev_info(aw_dev->dev, "enter,flag:%d", flag); if (flag) { ret = aw_dev->ops.aw_reg_write_bits(aw_dev, dsp_crc_desc->ctl_reg, dsp_crc_desc->ctl_mask, dsp_crc_desc->ctl_enable); if (ret < 0) { aw_dev_err(aw_dev->dev, "enable dsp crc failed"); return ret; } } else { ret = aw_dev->ops.aw_reg_write_bits(aw_dev, dsp_crc_desc->ctl_reg, dsp_crc_desc->ctl_mask, dsp_crc_desc->ctl_disable); if (ret < 0) { aw_dev_err(aw_dev->dev, "close dsp crc failed"); return ret; } } return 0; } static int aw_dev_dsp_st_check(struct aw_device *aw_dev) { struct aw_sysst_desc *desc = &aw_dev->sysst_desc; int ret = -1; uint16_t reg_val = 0; int i; for (i = 0; i < AW_DSP_ST_CHECK_MAX; i++) { ret = aw_dev->ops.aw_reg_read(aw_dev, desc->reg, ®_val); if (ret < 0) { aw_dev_err(aw_dev->dev, "read reg0x%x failed", desc->reg); continue; } if ((reg_val & (~desc->dsp_mask)) != desc->dsp_check) { aw_dev_err(aw_dev->dev, "check dsp st fail,reg_val:0x%04x", reg_val); ret = -EINVAL; continue; } else { aw_dev_info(aw_dev->dev, "dsp st check ok, reg_val:0x%04x", reg_val); return 0; } } return ret; } static int aw_dev_dsp_crc32_check(struct aw_device *aw_dev) { int ret; if (aw_dev->dsp_cfg == AW_DEV_DSP_BYPASS) { aw_dev_info(aw_dev->dev, "dsp bypass"); return 0; } ret = aw_dev_set_dsp_crc32(aw_dev); if (ret < 0) { aw_dev_info(aw_dev->dev, "set dsp crc32 failed"); return ret; } aw_dev_dsp_crc_check_enable(aw_dev, true); /*dsp enable*/ aw_dev_dsp_enable(aw_dev, true); usleep_range(AW_5000_US, AW_5000_US + 100); ret = aw_dev_dsp_st_check(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "check crc32 fail"); return ret; } aw_dev_dsp_crc_check_enable(aw_dev, false); aw_dev->dsp_crc_st = AW_DSP_CRC_OK; return 0; } static void aw_dev_pwd(struct aw_device *aw_dev, bool pwd) { struct aw_pwd_desc *pwd_desc = &aw_dev->pwd_desc; aw_dev_dbg(aw_dev->dev, "enter"); if (pwd) { aw_dev->ops.aw_reg_write_bits(aw_dev, pwd_desc->reg, pwd_desc->mask, pwd_desc->enable); } else { aw_dev->ops.aw_reg_write_bits(aw_dev, pwd_desc->reg, pwd_desc->mask, pwd_desc->disable); } aw_dev_info(aw_dev->dev, "done"); } static void aw_dev_amppd(struct aw_device *aw_dev, bool amppd) { struct aw_amppd_desc *amppd_desc = &aw_dev->amppd_desc; aw_dev_dbg(aw_dev->dev, "enter"); if (amppd) { aw_dev->ops.aw_reg_write_bits(aw_dev, amppd_desc->reg, amppd_desc->mask, amppd_desc->enable); } else { aw_dev->ops.aw_reg_write_bits(aw_dev, amppd_desc->reg, amppd_desc->mask, amppd_desc->disable); } aw_dev_info(aw_dev->dev, "done"); } void aw_dev_mute(struct aw_device *aw_dev, bool mute) { struct aw_mute_desc *mute_desc = &aw_dev->mute_desc; aw_dev_dbg(aw_dev->dev, "enter"); if (mute || (aw_dev->cali_desc.cali_result == CALI_RESULT_ERROR)) { aw_dev_fade_out(aw_dev); aw_dev->ops.aw_reg_write_bits(aw_dev, mute_desc->reg, mute_desc->mask, mute_desc->enable); } else { aw_dev->ops.aw_reg_write_bits(aw_dev, mute_desc->reg, mute_desc->mask, mute_desc->disable); aw_dev_fade_in(aw_dev); } aw_dev_info(aw_dev->dev, "done"); } int aw_dev_get_hmute(struct aw_device *aw_dev) { uint16_t reg_val = 0; int ret; struct aw_mute_desc *desc = &aw_dev->mute_desc; aw_dev_dbg(aw_dev->dev, "enter"); ret = aw_dev->ops.aw_reg_read(aw_dev, desc->reg, ®_val); if (ret < 0) return ret; if (reg_val & (~desc->mask)) ret = 1; else ret = 0; return ret; } static int aw_dev_get_icalk(struct aw_device *aw_dev, int16_t *icalk) { int ret = -1; uint16_t reg_val = 0; uint16_t reg_icalk = 0; struct aw_vcalb_desc *desc = &aw_dev->vcalb_desc; ret = aw_dev->ops.aw_reg_read(aw_dev, desc->icalk_reg, ®_val); if (ret < 0) { aw_dev_err(aw_dev->dev, "reg read failed"); return ret; } reg_icalk = reg_val & (~desc->icalk_reg_mask); if (reg_icalk & (~desc->icalk_sign_mask)) reg_icalk = reg_icalk | desc->icalk_neg_mask; *icalk = (int16_t)reg_icalk; return 0; } static int aw_dev_get_vcalk(struct aw_device *aw_dev, int16_t *vcalk) { int ret = -1; uint16_t reg_val = 0; uint16_t reg_vcalk = 0; struct aw_vcalb_desc *desc = &aw_dev->vcalb_desc; ret = aw_dev->ops.aw_reg_read(aw_dev, desc->vcalk_reg, ®_val); if (ret < 0) { aw_dev_err(aw_dev->dev, "reg read failed"); return ret; } reg_val = reg_val >> desc->vcalk_shift; reg_vcalk = (uint16_t)reg_val & (~desc->vcalk_reg_mask); if (reg_vcalk & (~desc->vcalk_sign_mask)) reg_vcalk = reg_vcalk | desc->vcalk_neg_mask; *vcalk = (int16_t)reg_vcalk; return 0; } static int aw_dev_get_vcalk_dac(struct aw_device *aw_dev, int16_t *vcalk) { int ret = -1; uint16_t reg_val = 0; uint16_t reg_vcalk = 0; struct aw_vcalb_desc *desc = &aw_dev->vcalb_desc; ret = aw_dev->ops.aw_reg_read(aw_dev, desc->icalk_reg, ®_val); if (ret < 0) { aw_dev_err(aw_dev->dev, "reg read failed"); return ret; } reg_vcalk = reg_val >> desc->vcalk_dac_shift; if (reg_vcalk & desc->vcalk_dac_mask) reg_vcalk = reg_vcalk | desc->vcalk_dac_neg_mask; *vcalk = (int16_t)reg_vcalk; return 0; } int aw_dev_modify_dsp_cfg(struct aw_device *aw_dev, unsigned int addr, uint32_t dsp_data, unsigned char data_type) { uint32_t addr_offset = 0; int len = 0; uint8_t temp_data[4] = { 0 }; struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; aw_dev_dbg(aw_dev->dev, "addr:0x%x, dsp_data:0x%x", addr, dsp_data); if (data_type == AW_DSP_16_DATA) { temp_data[0] = (uint8_t)(dsp_data & 0x00ff); temp_data[1] = (uint8_t)((dsp_data & 0xff00) >> 8); len = 2; } else if (data_type == AW_DSP_32_DATA) { temp_data[0] = (uint8_t)(dsp_data & 0x000000ff); temp_data[1] = (uint8_t)((dsp_data & 0x0000ff00) >> 8); temp_data[2] = (uint8_t)((dsp_data & 0x00ff0000) >> 16); temp_data[3] = (uint8_t)((dsp_data & 0xff000000) >> 24); len = 4; } else { aw_dev_err(aw_dev->dev, "data type[%d] unsupported", data_type); return -EINVAL; } addr_offset = (addr - aw_dev->dsp_mem_desc.dsp_cfg_base_addr) * 2; if (addr_offset > crc_dsp_cfg->len) { aw_dev_err(aw_dev->dev, "addr_offset[%d] > crc_dsp_cfg->len[%d]", addr_offset, crc_dsp_cfg->len); return -EINVAL; } memcpy(crc_dsp_cfg->data + addr_offset, temp_data, len); return 0; } static int aw_dev_vsense_select(struct aw_device *aw_dev, int *vsense_select) { int ret = -1; struct aw_vcalb_desc *desc = &aw_dev->vcalb_desc; uint16_t vsense_reg_val; ret = aw_dev->ops.aw_reg_read(aw_dev, desc->vcalb_vsense_reg, &vsense_reg_val); if (ret < 0) { aw_dev_err(aw_dev->dev, "read vsense_reg_val failed"); return ret; } aw_dev_dbg(aw_dev->dev, "vsense_reg = 0x%x", vsense_reg_val); if (vsense_reg_val & (~desc->vcalk_vdsel_mask)) { *vsense_select = AW_DEV_VDSEL_VSENSE; aw_dev_info(aw_dev->dev, "vsense outside"); return 0; } *vsense_select = AW_DEV_VDSEL_DAC; aw_dev_info(aw_dev->dev, "vsense inside"); return 0; } static int aw_dev_set_vcalb(struct aw_device *aw_dev) { int ret = -1; uint32_t reg_val = 0; int vcalb; int icalk; int vcalk; int16_t icalk_val = 0; int16_t vcalk_val = 0; struct aw_vcalb_desc *desc = &aw_dev->vcalb_desc; uint32_t vcalb_adj; int vsense_select = -1; ret = aw_dev->ops.aw_dsp_read(aw_dev, desc->vcalb_dsp_reg, &vcalb_adj, desc->data_type); if (ret < 0) { aw_dev_err(aw_dev->dev, "read vcalb_adj failed"); return ret; } ret = aw_dev_vsense_select(aw_dev, &vsense_select); aw_dev_dbg(aw_dev->dev, "vsense_select = %d", vsense_select); if (ret < 0) { return ret; } aw_dev_get_icalk(aw_dev, &icalk_val); icalk = desc->cabl_base_value + desc->icalk_value_factor * icalk_val; if (vsense_select == AW_DEV_VDSEL_VSENSE) { aw_dev_get_vcalk(aw_dev, &vcalk_val); vcalk = desc->cabl_base_value + desc->vcalk_value_factor * vcalk_val; vcalb = desc->vcal_factor * desc->vscal_factor / desc->iscal_factor * icalk / vcalk * vcalb_adj; aw_dev_dbg(aw_dev->dev, "vcalk_factor=%d, vscal_factor=%d, icalk=%d, vcalk=%d", desc->vcalk_value_factor, desc->vscal_factor, icalk, vcalk); } else if (vsense_select == AW_DEV_VDSEL_DAC) { aw_dev_get_vcalk_dac(aw_dev, &vcalk_val); vcalk = desc->cabl_base_value + desc->vcalk_value_factor_vsense_in * vcalk_val; vcalb = desc->vcal_factor * desc->vscal_factor_vsense_in / desc->iscal_factor * icalk / vcalk * vcalb_adj; aw_dev_dbg(aw_dev->dev, "vcalk_dac_factor=%d, vscal_dac_factor=%d, icalk=%d, vcalk=%d", desc->vcalk_value_factor_vsense_in, desc->vscal_factor_vsense_in, icalk, vcalk); } else { aw_dev_err(aw_dev->dev, "unsupport vsense status"); return -EINVAL; } if ((vcalk == 0) || (desc->iscal_factor == 0)) { aw_dev_err(aw_dev->dev, "vcalk:%d or desc->iscal_factor:%d unsupported", vcalk, desc->iscal_factor); return -EINVAL; } vcalb = vcalb >> aw_dev->vcalb_desc.vcalb_adj_shift; reg_val = (uint32_t)vcalb; aw_dev_dbg(aw_dev->dev, "vcalb=%d, reg_val=0x%x, vcalb_adj =0x%x", vcalb, reg_val, vcalb_adj); ret = aw_dev->ops.aw_dsp_write(aw_dev, desc->vcalb_dsp_reg, reg_val, desc->data_type); if (ret < 0) { aw_dev_err(aw_dev->dev, "write vcalb failed"); return ret; } ret = aw_dev_modify_dsp_cfg(aw_dev, desc->vcalb_dsp_reg, (uint32_t)reg_val, desc->data_type); if (ret < 0) { aw_dev_err(aw_dev->dev, "modify dsp cfg failed"); return ret; } aw_dev_info(aw_dev->dev, "done"); return ret; } static int aw_dev_get_cali_f0_delay(struct aw_device *aw_dev) { struct aw_cali_delay_desc *desc = &aw_dev->cali_delay_desc; uint32_t cali_delay = 0; int ret = -1; ret = aw_dev->ops.aw_dsp_read(aw_dev, desc->dsp_reg, &cali_delay, desc->data_type); if (ret < 0) { aw_dev_err(aw_dev->dev, "read cali delay failed, ret=%d", ret); return ret; } desc->delay = AW_CALI_DELAY_CACL(cali_delay); aw_dev_info(aw_dev->dev, "read cali delay: %d ms", desc->delay); return 0; } int aw_dev_get_int_status(struct aw_device *aw_dev, uint16_t *int_status) { int ret = -1; uint16_t reg_val = 0; ret = aw_dev->ops.aw_reg_read(aw_dev, aw_dev->int_desc.st_reg, ®_val); if (ret < 0) aw_dev_err(aw_dev->dev, "read interrupt reg fail, ret=%d", ret); else *int_status = reg_val; aw_dev_dbg(aw_dev->dev, "read interrupt reg = 0x%04x", *int_status); return ret; } void aw_dev_clear_int_status(struct aw_device *aw_dev) { uint16_t int_status = 0; /*read int status and clear*/ aw_dev_get_int_status(aw_dev, &int_status); /*make sure int status is clear*/ aw_dev_get_int_status(aw_dev, &int_status); aw_dev_info(aw_dev->dev, "done"); } int aw_dev_get_iis_status(struct aw_device *aw_dev) { int ret = -1; uint16_t reg_val = 0; struct aw_sysst_desc *desc = &aw_dev->sysst_desc; aw_dev_dbg(aw_dev->dev, "enter"); aw_dev->ops.aw_reg_read(aw_dev, desc->reg, ®_val); if ((reg_val & desc->pll_check) == desc->pll_check) ret = 0; else aw_dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val); return ret; } static int aw_dev_mode1_pll_check(struct aw_device *aw_dev) { int ret = -1; uint16_t i = 0; for (i = 0; i < AW_DEV_SYSST_CHECK_MAX; i++) { ret = aw_dev_get_iis_status(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "mode1 iis signal check error"); usleep_range(AW_2000_US, AW_2000_US + 10); } else { return 0; } } return ret; } static int aw_dev_mode2_pll_check(struct aw_device *aw_dev) { int ret = -1; uint16_t i = 0; uint16_t reg_val = 0; struct aw_cco_mux_desc *cco_mux_desc = &aw_dev->cco_mux_desc; aw_dev->ops.aw_reg_read(aw_dev, cco_mux_desc->reg, ®_val); reg_val &= (~cco_mux_desc->mask); if (reg_val == cco_mux_desc->divider) { aw_dev_dbg(aw_dev->dev, "CCO_MUX is already divider"); return ret; } /* change mode2 */ aw_dev->ops.aw_reg_write_bits(aw_dev, cco_mux_desc->reg, cco_mux_desc->mask, cco_mux_desc->divider); for (i = 0; i < AW_DEV_SYSST_CHECK_MAX; i++) { ret = aw_dev_get_iis_status(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "mode2 iis signal check error"); usleep_range(AW_2000_US, AW_2000_US + 10); } else { break; } } /* change mode1*/ aw_dev->ops.aw_reg_write_bits(aw_dev, cco_mux_desc->reg, cco_mux_desc->mask, cco_mux_desc->bypass); if (ret == 0) { usleep_range(AW_2000_US, AW_2000_US + 10); for (i = 0; i < AW_DEV_SYSST_CHECK_MAX; i++) { ret = aw_dev_mode1_pll_check(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error"); usleep_range(AW_2000_US, AW_2000_US + 10); } else { break; } } } return ret; } int aw_dev_syspll_check(struct aw_device *aw_dev) { int ret = -1; ret = aw_dev_mode1_pll_check(aw_dev); if (ret < 0) { aw_dev_info(aw_dev->dev, "mode1 check iis failed try switch to mode2 check"); ret = aw_dev_mode2_pll_check(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "mode2 check iis failed"); return ret; } } return ret; } int aw_dev_sysst_check(struct aw_device *aw_dev) { int ret = -1; unsigned char i; uint16_t reg_val = 0; struct aw_sysst_desc *desc = &aw_dev->sysst_desc; for (i = 0; i < AW_DEV_SYSST_CHECK_MAX; i++) { aw_dev->ops.aw_reg_read(aw_dev, desc->reg, ®_val); if (((reg_val & (~desc->st_mask)) & desc->st_check) == desc->st_check) { ret = 0; break; } else { aw_dev_dbg(aw_dev->dev, "check fail, cnt=%d, reg_val=0x%04x", i, reg_val); usleep_range(AW_2000_US, AW_2000_US + 10); } } if (ret < 0) aw_dev_err(aw_dev->dev, "check fail"); return ret; } static int aw_dev_get_monitor_sysint_st(struct aw_device *aw_dev) { int ret = 0; struct aw_int_desc *desc = &aw_dev->int_desc; if ((desc->intst_mask) & (desc->sysint_st)) { aw_dev_err(aw_dev->dev, "monitor check fail:0x%04x", desc->sysint_st); ret = -EINVAL; } desc->sysint_st = 0; return ret; } static int aw_dev_sysint_check(struct aw_device *aw_dev) { int ret = 0; uint16_t reg_val = 0; struct aw_int_desc *desc = &aw_dev->int_desc; aw_dev_get_int_status(aw_dev, ®_val); if (reg_val & (desc->intst_mask)) { aw_dev_err(aw_dev->dev, "pa stop check fail:0x%04x", reg_val); ret = -EINVAL; } return ret; } static void aw_dev_get_cur_mode_st(struct aw_device *aw_dev) { uint16_t reg_val; struct aw_profctrl_desc *profctrl_desc = &aw_dev->profctrl_desc; aw_dev->ops.aw_reg_read(aw_dev, aw_dev->pwd_desc.reg, ®_val); if ((reg_val & (~profctrl_desc->mask)) == profctrl_desc->rcv_mode_val) profctrl_desc->cur_mode = AW_RCV_MODE; else profctrl_desc->cur_mode = AW_NOT_RCV_MODE; } int aw_dev_set_intmask(struct aw_device *aw_dev, bool flag) { int ret = -1; struct aw_int_desc *desc = &aw_dev->int_desc; if (flag) ret = aw_dev->ops.aw_reg_write(aw_dev, desc->mask_reg, desc->int_mask); else ret = aw_dev->ops.aw_reg_write(aw_dev, desc->mask_reg, desc->mask_default); aw_dev_info(aw_dev->dev, "done"); return ret; } void aw_dev_dsp_enable(struct aw_device *aw_dev, bool dsp) { int ret = -1; struct aw_dsp_en_desc *desc = &aw_dev->dsp_en_desc; if (dsp) { ret = aw_dev->ops.aw_reg_write_bits(aw_dev, desc->reg, desc->mask, desc->enable); if (ret < 0) aw_dev_err(aw_dev->dev, "enable dsp failed"); } else { ret = aw_dev->ops.aw_reg_write_bits(aw_dev, desc->reg, desc->mask, desc->disable); if (ret < 0) aw_dev_err(aw_dev->dev, "disable dsp failed"); } aw_dev_info(aw_dev->dev, "done"); } static int aw_dev_get_dsp_config(struct aw_device *aw_dev, unsigned char *dsp_cfg) { int ret = -1; uint16_t reg_val = 0; struct aw_dsp_en_desc *desc = &aw_dev->dsp_en_desc; ret = aw_dev->ops.aw_reg_read(aw_dev, desc->reg, ®_val); if (ret < 0) { aw_dev_err(aw_dev->dev, "reg read failed"); return ret; } if (reg_val & (~desc->mask)) *dsp_cfg = AW_DEV_DSP_BYPASS; else *dsp_cfg = AW_DEV_DSP_WORK; aw_dev_info(aw_dev->dev, "done"); return 0; } void aw_dev_memclk_select(struct aw_device *aw_dev, unsigned char flag) { struct aw_memclk_desc *desc = &aw_dev->memclk_desc; int ret = -1; if (flag == AW_DEV_MEMCLK_PLL) { ret = aw_dev->ops.aw_reg_write_bits(aw_dev, desc->reg, desc->mask, desc->mcu_hclk); if (ret < 0) aw_dev_err(aw_dev->dev, "memclk select pll failed"); } else if (flag == AW_DEV_MEMCLK_OSC) { ret = aw_dev->ops.aw_reg_write_bits(aw_dev, desc->reg, desc->mask, desc->osc_clk); if (ret < 0) aw_dev_err(aw_dev->dev, "memclk select OSC failed"); } else { aw_dev_err(aw_dev->dev, "unknown memclk config, flag=0x%x", flag); } aw_dev_info(aw_dev->dev, "done"); } int aw_dev_get_dsp_status(struct aw_device *aw_dev) { int ret = -1; uint16_t reg_val = 0; struct aw_watch_dog_desc *desc = &aw_dev->watch_dog_desc; aw_dev_info(aw_dev->dev, "enter"); aw_dev->ops.aw_reg_read(aw_dev, desc->reg, ®_val); if (reg_val & (~desc->mask)) ret = 0; return ret; } static int aw_dev_get_vmax(struct aw_device *aw_dev, unsigned int *vmax) { int ret = -1; struct aw_vmax_desc *desc = &aw_dev->vmax_desc; ret = aw_dev->ops.aw_dsp_read(aw_dev, desc->dsp_reg, vmax, desc->data_type); if (ret < 0) { aw_dev_err(aw_dev->dev, "get vmax failed"); return ret; } return 0; } /****************************************************** * * aw_dev update cfg * ******************************************************/ static int aw_dev_reg_container_update(struct aw_device *aw_dev, uint8_t *data, uint32_t len) { int i, ret = 0; uint8_t reg_addr = 0; uint16_t reg_val = 0; uint16_t read_val; struct aw_int_desc *int_desc = &aw_dev->int_desc; int16_t *reg_data = NULL; int data_len; aw_dev_dbg(aw_dev->dev, "enter"); reg_data = (int16_t *)data; data_len = len >> 1; if (data_len % 2 != 0) { aw_dev_err(aw_dev->dev, "data len:%d unsupported", data_len); return -EINVAL; } for (i = 0; i < data_len; i += 2) { reg_addr = reg_data[i]; reg_val = reg_data[i + 1]; aw_dev_dbg(aw_dev->dev, "reg = 0x%02x, val = 0x%04x", reg_addr, reg_val); if (reg_addr == int_desc->mask_reg) { int_desc->int_mask = reg_val; reg_val = int_desc->mask_default; } if (reg_addr == aw_dev->mute_desc.reg) { aw_dev->ops.aw_reg_read(aw_dev, reg_addr, &read_val); read_val &= (~aw_dev->mute_desc.mask); reg_val &= aw_dev->mute_desc.mask; reg_val |= read_val; } if (reg_addr == aw_dev->dsp_crc_desc.ctl_reg) { reg_val &= aw_dev->dsp_crc_desc.ctl_mask; } if (reg_addr == aw_dev->chansel_desc.txchan_reg) { /*close tx*/ reg_val &= aw_dev->tx_en_desc.tx_en_mask; reg_val |= aw_dev->tx_en_desc.tx_disable; } ret = aw_dev->ops.aw_reg_write(aw_dev, reg_addr, reg_val); if (ret < 0) break; } aw_hold_reg_spin_st(&aw_dev->spin_desc); aw_dev_get_cur_mode_st(aw_dev); aw_dev->ops.aw_get_volume(aw_dev, (uint16_t *)&aw_dev->volume_desc.init_volume); /*keep min volume*/ if (aw_dev->fade_en) aw_dev->ops.aw_set_volume(aw_dev, aw_dev->volume_desc.mute_volume); aw_dev_get_dsp_config(aw_dev, &aw_dev->dsp_cfg); aw_dev_dbg(aw_dev->dev, "exit"); return ret; } static int aw_dev_reg_update(struct aw_device *aw_dev, uint8_t *data, uint32_t len) { aw_dev_dbg(aw_dev->dev, "reg len:%d", len); if (len && (data != NULL)) { aw_dev_reg_container_update(aw_dev, data, len); } else { aw_dev_err(aw_dev->dev, "reg data is null or len is 0"); return -EPERM; } return 0; } static int aw_dev_dsp_container_update(struct aw_device *aw_dev, uint8_t *data, uint32_t len, uint16_t base) { int i; struct aw_dsp_mem_desc *dsp_mem_desc = &aw_dev->dsp_mem_desc; #ifdef AW_DSP_I2C_WRITES uint32_t tmp_len = 0; #else uint16_t reg_val = 0; #endif aw_dev_dbg(aw_dev->dev, "enter"); mutex_lock(aw_dev->i2c_lock); #ifdef AW_DSP_I2C_WRITES /* i2c writes */ aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_madd_reg, base); for (i = 0; i < len; i += AW_MAX_RAM_WRITE_BYTE_SIZE) { if ((len - i) < AW_MAX_RAM_WRITE_BYTE_SIZE) tmp_len = len - i; else tmp_len = AW_MAX_RAM_WRITE_BYTE_SIZE; aw_dev->ops.aw_i2c_writes(aw_dev, dsp_mem_desc->dsp_mdat_reg, &data[i], tmp_len); } #else /* i2c write */ aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_madd_reg, base); for (i = 0; i < len; i += 2) { reg_val = (data[i] << 8) + data[i + 1]; aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_mdat_reg, reg_val); } #endif mutex_unlock(aw_dev->i2c_lock); aw_dev_dbg(aw_dev->dev, "exit"); return 0; } int aw_dev_dsp_fw_update(struct aw_device *aw_dev, uint8_t *data, uint32_t len) { struct aw_dsp_mem_desc *dsp_mem_desc = &aw_dev->dsp_mem_desc; aw_dev_dbg(aw_dev->dev, "dsp firmware len:%d", len); if (len && (data != NULL)) { aw_dev_dsp_container_update(aw_dev, data, len, dsp_mem_desc->dsp_fw_base_addr); aw_dev->dsp_fw_len = len; } else { aw_dev_err(aw_dev->dev, "dsp firmware data is null or len is 0"); return -EPERM; } return 0; } static int aw_dev_copy_to_crc_dsp_cfg(struct aw_device *aw_dev, uint8_t *data, uint32_t size) { struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; int ret; if (crc_dsp_cfg->data == NULL) { crc_dsp_cfg->data = devm_kzalloc(aw_dev->dev, size, GFP_KERNEL); if (!crc_dsp_cfg->data) { aw_dev_err(aw_dev->dev, "error allocating memory"); return -ENOMEM; } crc_dsp_cfg->len = size; } else if (crc_dsp_cfg->len < size) { devm_kfree(aw_dev->dev, crc_dsp_cfg->data); crc_dsp_cfg->data = NULL; crc_dsp_cfg->data = devm_kzalloc(aw_dev->dev, size, GFP_KERNEL); if (!crc_dsp_cfg->data) { aw_dev_err(aw_dev->dev, "error allocating memory"); return -ENOMEM; } } memcpy(crc_dsp_cfg->data, data, size); ret = aw_dev_dsp_data_order(aw_dev, crc_dsp_cfg->data, size); if (ret < 0) return ret; return 0; } int aw_dev_dsp_cfg_update(struct aw_device *aw_dev, uint8_t *data, uint32_t len) { struct aw_dsp_mem_desc *dsp_mem_desc = &aw_dev->dsp_mem_desc; int ret; aw_dev_dbg(aw_dev->dev, "dsp config len:%d", len); if (len && (data != NULL)) { aw_dev_dsp_container_update(aw_dev, data, len, dsp_mem_desc->dsp_cfg_base_addr); aw_dev->dsp_cfg_len = len; ret = aw_dev_copy_to_crc_dsp_cfg(aw_dev, data, len); if (ret < 0) return ret; aw_dev_set_vcalb(aw_dev); aw_cali_svc_get_ra(&aw_dev->cali_desc); aw_dev_get_cali_f0_delay(aw_dev); if (aw_dev->ops.aw_get_hw_mon_st) { ret = aw_dev->ops.aw_get_hw_mon_st(aw_dev, &aw_dev->monitor_desc.hw_mon_en, &aw_dev->monitor_desc.hw_temp_flag); if (ret < 0) return ret; } ret = aw_dev_get_vmax(aw_dev, &aw_dev->vmax_desc.init_vmax); if (ret < 0) { aw_dev_err(aw_dev->dev, "get vmax failed"); return ret; } else { aw_dev_info(aw_dev->dev, "get init vmax:0x%x", aw_dev->vmax_desc.init_vmax); } aw_dev->dsp_crc_st = AW_DSP_CRC_NA; } else { aw_dev_err(aw_dev->dev, "dsp config data is null or len is 0"); return -EPERM; } return 0; } static int aw_dev_sram_check(struct aw_device *aw_dev) { int ret = -1; uint16_t reg_val = 0; struct aw_dsp_mem_desc *dsp_mem_desc = &aw_dev->dsp_mem_desc; mutex_lock(aw_dev->i2c_lock); /*check the odd bits of reg 0x40*/ aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_madd_reg, AW_DSP_ODD_NUM_BIT_TEST); aw_dev->ops.aw_i2c_read(aw_dev, dsp_mem_desc->dsp_madd_reg, ®_val); if (AW_DSP_ODD_NUM_BIT_TEST != reg_val) { aw_dev_err(aw_dev->dev, "check reg 0x40 odd bit failed, read[0x%x] does not match write[0x%x]", reg_val, AW_DSP_ODD_NUM_BIT_TEST); goto error; } /*check the even bits of reg 0x40*/ aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_madd_reg, AW_DSP_EVEN_NUM_BIT_TEST); aw_dev->ops.aw_i2c_read(aw_dev, dsp_mem_desc->dsp_madd_reg, ®_val); if (AW_DSP_EVEN_NUM_BIT_TEST != reg_val) { aw_dev_err(aw_dev->dev, "check reg 0x40 even bit failed, read[0x%x] does not match write[0x%x]", reg_val, AW_DSP_EVEN_NUM_BIT_TEST); goto error; } /*check dsp_fw_base_addr*/ aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_madd_reg, dsp_mem_desc->dsp_fw_base_addr); aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_mdat_reg, AW_DSP_EVEN_NUM_BIT_TEST); aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_madd_reg, dsp_mem_desc->dsp_fw_base_addr); aw_dev->ops.aw_i2c_read(aw_dev, dsp_mem_desc->dsp_mdat_reg, ®_val); if (AW_DSP_EVEN_NUM_BIT_TEST != reg_val) { aw_dev_err(aw_dev->dev, "check dsp fw addr failed, read[0x%x] does not match write[0x%x]", reg_val, AW_DSP_EVEN_NUM_BIT_TEST); goto error; } /*check dsp_cfg_base_addr*/ aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_madd_reg, dsp_mem_desc->dsp_cfg_base_addr); aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_mdat_reg, AW_DSP_ODD_NUM_BIT_TEST); aw_dev->ops.aw_i2c_write(aw_dev, dsp_mem_desc->dsp_madd_reg, dsp_mem_desc->dsp_cfg_base_addr); aw_dev->ops.aw_i2c_read(aw_dev, dsp_mem_desc->dsp_mdat_reg, ®_val); if (AW_DSP_ODD_NUM_BIT_TEST != reg_val) { aw_dev_err(aw_dev->dev, "check dsp cfg failed, read[0x%x] does not match write[0x%x]", reg_val, AW_DSP_ODD_NUM_BIT_TEST); goto error; } mutex_unlock(aw_dev->i2c_lock); return 0; error: mutex_unlock(aw_dev->i2c_lock); return ret; } int aw_dev_fw_update(struct aw_device *aw_dev, bool up_dsp_fw_en, bool force_up_en) { int ret = -1; struct aw_prof_desc *set_prof_desc = NULL; struct aw_sec_data_desc *sec_desc = NULL; char *prof_name = NULL; if ((aw_dev->cur_prof == aw_dev->set_prof) && (force_up_en == AW_FORCE_UPDATE_OFF)) { aw_dev_info(aw_dev->dev, "scene no change, not update"); return 0; } if (aw_dev->fw_status == AW_DEV_FW_FAILED) { aw_dev_err(aw_dev->dev, "fw status[%d] error", aw_dev->fw_status); return -EPERM; } prof_name = aw_dev_get_prof_name(aw_dev, aw_dev->set_prof); if (prof_name == NULL) return -ENOMEM; aw_dev_info(aw_dev->dev, "start update %s", prof_name); ret = aw_dev_get_prof_data(aw_dev, aw_dev->set_prof, &set_prof_desc); if (ret < 0) return ret; /*update reg*/ sec_desc = set_prof_desc->sec_desc; ret = aw_dev_reg_update(aw_dev, sec_desc[AW_DATA_TYPE_REG].data, sec_desc[AW_DATA_TYPE_REG].len); if (ret < 0) { aw_dev_err(aw_dev->dev, "update reg failed"); return ret; } aw_dev_mute(aw_dev, true); if (aw_dev->dsp_cfg == AW_DEV_DSP_WORK) aw_dev_dsp_enable(aw_dev, false); aw_dev_memclk_select(aw_dev, AW_DEV_MEMCLK_OSC); if (up_dsp_fw_en) { ret = aw_dev_sram_check(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "check sram failed"); goto error; } /*update dsp firmware*/ aw_dev_info(aw_dev->dev, "fw_ver: [%x]", set_prof_desc->fw_ver); ret = aw_dev_dsp_fw_update(aw_dev, sec_desc[AW_DATA_TYPE_DSP_FW].data, sec_desc[AW_DATA_TYPE_DSP_FW].len); if (ret < 0) { aw_dev_err(aw_dev->dev, "update dsp fw failed"); goto error; } } /*update dsp config*/ ret = aw_dev_dsp_cfg_update(aw_dev, sec_desc[AW_DATA_TYPE_DSP_CFG].data, sec_desc[AW_DATA_TYPE_DSP_CFG].len); if (ret < 0) { aw_dev_err(aw_dev->dev, "update dsp cfg failed"); goto error; } aw_dev_memclk_select(aw_dev, AW_DEV_MEMCLK_PLL); aw_dev->cur_prof = aw_dev->set_prof; aw_dev_info(aw_dev->dev, "load %s done", prof_name); return 0; error: aw_dev_memclk_select(aw_dev, AW_DEV_MEMCLK_PLL); return ret; } int aw_dev_dsp_check(struct aw_device *aw_dev) { int ret = -1; uint16_t i = 0; aw_dev_dbg(aw_dev->dev, "enter"); if (aw_dev->dsp_cfg == AW_DEV_DSP_BYPASS) { aw_dev_dbg(aw_dev->dev, "dsp bypass"); return 0; } else if (aw_dev->dsp_cfg == AW_DEV_DSP_WORK) { for (i = 0; i < AW_DEV_DSP_CHECK_MAX; i++) { aw_dev_dsp_enable(aw_dev, false); aw_dev_dsp_enable(aw_dev, true); usleep_range(AW_1000_US, AW_1000_US + 10); ret = aw_dev_get_dsp_status(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "dsp wdt status error=%d", ret); usleep_range(AW_2000_US, AW_2000_US + 10); } else { return 0; } } } else { aw_dev_err(aw_dev->dev, "unknown dsp cfg=%d", aw_dev->dsp_cfg); return -EINVAL; } return -EINVAL; } static int aw_dev_set_cfg_f0_fs(struct aw_device *aw_dev) { uint32_t f0_fs = 0; struct aw_cfgf0_fs_desc *cfgf0_fs_desc = &aw_dev->cfgf0_fs_desc; int ret; if (aw_dev->ops.aw_set_cfg_f0_fs) { aw_dev->ops.aw_set_cfg_f0_fs(aw_dev, &f0_fs); ret = aw_dev_modify_dsp_cfg(aw_dev, cfgf0_fs_desc->dsp_reg, f0_fs, cfgf0_fs_desc->data_type); if (ret < 0) { aw_dev_err(aw_dev->dev, "modify dsp cfg failed"); return ret; } } return 0; } static void aw_dev_cali_re_update(struct aw_cali_desc *cali_desc) { struct aw_device *aw_dev = container_of(cali_desc, struct aw_device, cali_desc); if (aw_dev->cali_desc.cali_re < aw_dev->re_range.re_max && aw_dev->cali_desc.cali_re > aw_dev->re_range.re_min) { aw_cali_svc_set_cali_re_to_dsp(&aw_dev->cali_desc); } else { aw_dev_err(aw_dev->dev, "cali_re:%d out of range, no set", aw_dev->cali_desc.cali_re); } } int aw_device_start(struct aw_device *aw_dev) { int ret = -1; aw_dev_info(aw_dev->dev, "enter"); if (aw_dev->status == AW_DEV_PW_ON) { aw_dev_info(aw_dev->dev, "already power on"); return 0; } /*power on*/ aw_dev_pwd(aw_dev, false); usleep_range(AW_2000_US, AW_2000_US + 10); ret = aw_dev_syspll_check(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "pll check failed cannot start"); aw_dev_reg_dump(aw_dev); goto pll_check_fail; } /*amppd on*/ aw_dev_amppd(aw_dev, false); usleep_range(AW_1000_US, AW_1000_US + 50); /*check i2s status*/ ret = aw_dev_sysst_check(aw_dev); if (ret < 0) { /*check failed*/ aw_dev_reg_dump(aw_dev); goto sysst_check_fail; } if (aw_dev->dsp_cfg == AW_DEV_DSP_WORK) { /*dsp bypass*/ aw_dev_dsp_enable(aw_dev, false); if (aw_dev->ops.aw_dsp_fw_check) { ret = aw_dev->ops.aw_dsp_fw_check(aw_dev); if (ret < 0) { aw_dev_reg_dump(aw_dev); goto dsp_fw_check_fail; } } aw_dev_set_cfg_f0_fs(aw_dev); aw_dev_cali_re_update(&aw_dev->cali_desc); if (aw_dev->dsp_crc_st != AW_DSP_CRC_OK) { ret = aw_dev_dsp_crc32_check(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "dsp crc check failed"); aw_dev_reg_dump(aw_dev); goto crc_check_fail; } } ret = aw_dev_dsp_check(aw_dev); if (ret < 0) { aw_dev_err(aw_dev->dev, "check dsp status failed"); aw_dev_reg_dump(aw_dev); goto dsp_check_fail; } } else { aw_dev_dbg(aw_dev->dev, "start pa with dsp bypass"); } /*enable tx feedback*/ if (aw_dev->ops.aw_i2s_tx_enable) aw_dev->ops.aw_i2s_tx_enable(aw_dev, true); /*close mute*/ aw_dev_mute(aw_dev, false); /*clear inturrupt*/ aw_dev_clear_int_status(aw_dev); /*set inturrupt mask*/ aw_dev_set_intmask(aw_dev, true); aw_monitor_start(&aw_dev->monitor_desc); aw_dev->status = AW_DEV_PW_ON; aw_dev_info(aw_dev->dev, "done"); return 0; dsp_check_fail: crc_check_fail: aw_dev_dsp_enable(aw_dev, false); dsp_fw_check_fail: sysst_check_fail: /*clear interrupt*/ aw_dev_clear_int_status(aw_dev); aw_dev_amppd(aw_dev, true); pll_check_fail: aw_dev_pwd(aw_dev, true); aw_dev->status = AW_DEV_PW_OFF; return ret; } int aw_device_stop(struct aw_device *aw_dev) { struct aw_sec_data_desc *dsp_cfg = &aw_dev->prof_info.prof_desc[aw_dev->cur_prof].sec_desc[AW_DATA_TYPE_DSP_CFG]; struct aw_sec_data_desc *dsp_fw = &aw_dev->prof_info.prof_desc[aw_dev->cur_prof].sec_desc[AW_DATA_TYPE_DSP_FW]; int int_st = 0; int monitor_int_st = 0; aw_dev_dbg(aw_dev->dev, "enter"); if (aw_dev->status == AW_DEV_PW_OFF) { aw_dev_info(aw_dev->dev, "already power off"); return 0; } aw_dev->status = AW_DEV_PW_OFF; aw_monitor_stop(&aw_dev->monitor_desc); /*set mute*/ aw_dev_mute(aw_dev, true); usleep_range(AW_4000_US, AW_4000_US + 100); /*close tx feedback*/ if (aw_dev->ops.aw_i2s_tx_enable) aw_dev->ops.aw_i2s_tx_enable(aw_dev, false); usleep_range(AW_1000_US, AW_1000_US + 100); /*set defaut int mask*/ aw_dev_set_intmask(aw_dev, false); /*check sysint state*/ int_st = aw_dev_sysint_check(aw_dev); /*close dsp*/ aw_dev_dsp_enable(aw_dev, false); /*enable amppd*/ aw_dev_amppd(aw_dev, true); /*check monitor process sysint state*/ monitor_int_st = aw_dev_get_monitor_sysint_st(aw_dev); if (int_st < 0 || monitor_int_st < 0) { /*system status anomaly*/ aw_dev_memclk_select(aw_dev, AW_DEV_MEMCLK_OSC); aw_dev_dsp_cfg_update(aw_dev, dsp_cfg->data, dsp_cfg->len); aw_dev_dsp_fw_update(aw_dev, dsp_fw->data, dsp_fw->len); aw_dev_memclk_select(aw_dev, AW_DEV_MEMCLK_PLL); } /*set power down*/ aw_dev_pwd(aw_dev, true); aw_dev_info(aw_dev->dev, "done"); return 0; } /*deinit aw_device*/ void aw_dev_deinit(struct aw_device *aw_dev) { if (aw_dev == NULL) return; if (aw_dev->prof_info.prof_desc != NULL) { devm_kfree(aw_dev->dev, aw_dev->prof_info.prof_desc); aw_dev->prof_info.prof_desc = NULL; } aw_dev->prof_info.count = 0; if (aw_dev->crc_dsp_cfg.data != NULL) { aw_dev->crc_dsp_cfg.len = 0; devm_kfree(aw_dev->dev, aw_dev->crc_dsp_cfg.data); aw_dev->crc_dsp_cfg.data = NULL; } } /*init aw_device*/ int aw_device_init(struct aw_device *aw_dev, struct aw_container *aw_cfg) { int ret; if (aw_dev == NULL || aw_cfg == NULL) { aw_pr_err("aw_dev is NULL or aw_cfg is NULL"); return -ENOMEM; } ret = aw_dev_cfg_load(aw_dev, aw_cfg); if (ret < 0) { aw_dev_deinit(aw_dev); aw_dev_err(aw_dev->dev, "aw_dev acf parse failed"); return -EINVAL; } aw_dev->cur_prof = aw_dev->prof_info.prof_desc[0].id; aw_dev->set_prof = aw_dev->prof_info.prof_desc[0].id; ret = aw_dev_fw_update(aw_dev, AW_FORCE_UPDATE_ON, AW_DSP_FW_UPDATE_ON); if (ret < 0) { aw_dev_err(aw_dev->dev, "fw update failed"); return ret; } aw_dev_set_intmask(aw_dev, false); /*set mute*/ aw_dev_mute(aw_dev, true); /*close tx feedback*/ if (aw_dev->ops.aw_i2s_tx_enable) aw_dev->ops.aw_i2s_tx_enable(aw_dev, false); usleep_range(AW_1000_US, AW_1000_US + 100); /*enable amppd*/ aw_dev_amppd(aw_dev, true); /*close dsp*/ aw_dev_dsp_enable(aw_dev, false); /*set power down*/ aw_dev_pwd(aw_dev, true); mutex_lock(&g_dev_lock); list_add(&aw_dev->list_node, &g_dev_list); mutex_unlock(&g_dev_lock); aw_dev_info(aw_dev->dev, "init done"); return 0; } static void aw883xx_parse_channel_dt(struct aw_device *aw_dev) { int ret; uint32_t channel_value; struct device_node *np = aw_dev->dev->of_node; ret = of_property_read_u32(np, "sound-channel", &channel_value); if (ret < 0) { aw_dev_info(aw_dev->dev, "read sound-channel failed,use default 0"); aw_dev->channel = AW_DEV_DEFAULT_CH; return; } aw_dev_dbg(aw_dev->dev, "read sound-channel value is: %d", channel_value); aw_dev->channel = channel_value; } static void aw883xx_parse_fade_enable_dt(struct aw_device *aw_dev) { int ret = -1; struct device_node *np = aw_dev->dev->of_node; uint32_t fade_en; ret = of_property_read_u32(np, "fade-enable", &fade_en); if (ret < 0) { aw_dev_info(aw_dev->dev, "read fade-enable failed, close fade_in_out"); fade_en = AW_FADE_IN_OUT_DEFAULT; } else { aw_dev_info(aw_dev->dev, "read fade-enable value is: %d", fade_en); } aw_dev->fade_en = fade_en; } static void aw883xx_parse_re_range_dt(struct aw_device *aw_dev) { int ret; uint32_t re_max; uint32_t re_min; struct device_node *np = aw_dev->dev->of_node; ret = of_property_read_u32(np, "re-min", &re_min); if (ret < 0) { aw_dev->re_range.re_min = aw_dev->re_range.re_min_default; aw_dev_info(aw_dev->dev, "read re-min value failed, set deafult value:[%d]mohm", aw_dev->re_range.re_min); } else { aw_dev_info(aw_dev->dev, "parse re-min:[%d]", re_min); aw_dev->re_range.re_min = re_min; } ret = of_property_read_u32(np, "re-max", &re_max); if (ret < 0) { aw_dev->re_range.re_max = aw_dev->re_range.re_max_default; aw_dev_info(aw_dev->dev, "read re-max failed, set deafult value:[%d]mohm", aw_dev->re_range.re_max); } else { aw_dev_info(aw_dev->dev, "parse re-max:[%d]", re_max); aw_dev->re_range.re_max = re_max; } } static void aw_device_parse_dt(struct aw_device *aw_dev) { aw883xx_parse_channel_dt(aw_dev); aw883xx_parse_fade_enable_dt(aw_dev); aw883xx_parse_re_range_dt(aw_dev); } int aw_dev_get_list_head(struct list_head **head) { if (list_empty(&g_dev_list)) return -EINVAL; *head = &g_dev_list; return 0; } int aw_device_probe(struct aw_device *aw_dev) { INIT_LIST_HEAD(&aw_dev->list_node); aw_device_parse_dt(aw_dev); aw_cali_init(&aw_dev->cali_desc); aw_monitor_init(&aw_dev->monitor_desc); aw_spin_init(&aw_dev->spin_desc); return 0; } int aw_device_remove(struct aw_device *aw_dev) { aw_monitor_deinit(&aw_dev->monitor_desc); aw_cali_deinit(&aw_dev->cali_desc); return 0; }