for (i = 0; i < AW88395_FW_CHECK_PART; i++) {
ret = aw_dev_dsp_read(aw_dev, addr, &dsp_val, AW88395_DSP_16_DATA); if (ret) {
dev_err(aw_dev->dev, "dsp read failed"); return ret;
}
for (i = AW88395_MUTE_VOL; i >= fade_in_vol; i -= fade_step) {
aw_dev_set_volume(aw_dev, i);
usleep_range(aw_dev->fade_in_time, aw_dev->fade_in_time + 10);
}
if (i != fade_in_vol)
aw_dev_set_volume(aw_dev, fade_in_vol);
}
staticvoid aw_dev_fade_out(struct aw_device *aw_dev)
{ struct aw_volume_desc *desc = &aw_dev->volume_desc; int fade_step = aw_dev->fade_step; int i;
for (i = desc->ctl_volume; i <= AW88395_MUTE_VOL; i += fade_step) {
aw_dev_set_volume(aw_dev, i);
usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10);
}
if (i != AW88395_MUTE_VOL) {
aw_dev_set_volume(aw_dev, AW88395_MUTE_VOL);
usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10);
}
}
/* set cali re to device */
ret = aw_dev_dsp_write(aw_dev,
AW88395_DSP_REG_CFG_ADPZ_RE, cali_re, AW88395_DSP_32_DATA); if (ret) {
dev_err(aw_dev->dev, "set cali re error"); return ret;
}
ret = aw_dev_modify_dsp_cfg(aw_dev, AW88395_DSP_REG_CFG_ADPZ_RE,
cali_re, AW88395_DSP_32_DATA); if (ret)
dev_err(aw_dev->dev, "modify dsp cfg failed");
return ret;
}
staticvoid aw_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag)
{ int ret;
if (flag) {
ret = regmap_update_bits(aw_dev->regmap, AW88395_I2SCFG1_REG,
~AW88395_I2STXEN_MASK, AW88395_I2STXEN_ENABLE_VALUE);
} else {
ret = regmap_update_bits(aw_dev->regmap, AW88395_I2SCFG1_REG,
~AW88395_I2STXEN_MASK, AW88395_I2STXEN_DISABLE_VALUE);
}
if (ret)
dev_dbg(aw_dev->dev, "%s failed", __func__);
}
staticvoid aw_dev_dsp_check_crc_enable(struct aw_device *aw_dev, bool flag)
{ int ret;
if (flag) {
ret = regmap_update_bits(aw_dev->regmap, AW88395_HAGCCFG7_REG,
~AW88395_AGC_DSP_CTL_MASK, AW88395_AGC_DSP_CTL_ENABLE_VALUE);
} else {
ret = regmap_update_bits(aw_dev->regmap, AW88395_HAGCCFG7_REG,
~AW88395_AGC_DSP_CTL_MASK, AW88395_AGC_DSP_CTL_DISABLE_VALUE);
} if (ret)
dev_dbg(aw_dev->dev, "%s failed", __func__);
}
staticint aw_dev_dsp_check_st(struct aw_device *aw_dev)
{ unsignedint reg_val; int ret; int i;
for (i = 0; i < AW88395_DSP_ST_CHECK_MAX; i++) {
ret = regmap_read(aw_dev->regmap, AW88395_SYSST_REG, ®_val); if (ret) {
dev_err(aw_dev->dev, "read reg0x%x failed", AW88395_SYSST_REG); continue;
}
if ((reg_val & (~AW88395_DSPS_MASK)) != AW88395_DSPS_NORMAL_VALUE) {
dev_err(aw_dev->dev, "check dsp st fail,reg_val:0x%04x", reg_val);
ret = -EPERM; continue;
} else {
dev_dbg(aw_dev->dev, "dsp st check ok, reg_val:0x%04x", reg_val); return0;
}
}
return ret;
}
staticvoid aw_dev_dsp_enable(struct aw_device *aw_dev, bool is_enable)
{ int ret;
if (is_enable) {
ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG,
~AW88395_DSPBY_MASK, AW88395_DSPBY_WORKING_VALUE); if (ret)
dev_dbg(aw_dev->dev, "enable dsp failed");
} else {
ret = regmap_update_bits(aw_dev->regmap, AW88395_SYSCTRL_REG,
~AW88395_DSPBY_MASK, AW88395_DSPBY_BYPASS_VALUE); if (ret)
dev_dbg(aw_dev->dev, "disable dsp failed");
}
}
staticint aw_dev_dsp_check_crc32(struct aw_device *aw_dev)
{ int ret;
if (aw_dev->dsp_cfg == AW88395_DEV_DSP_BYPASS) {
dev_info(aw_dev->dev, "dsp bypass"); return0;
}
ret = aw_dev_dsp_set_crc32(aw_dev); if (ret) {
dev_err(aw_dev->dev, "set dsp crc32 failed"); return ret;
}
/* 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); if (int_status)
dev_info(aw_dev->dev, "int status(%d) is not cleaned.\n", int_status);
}
staticint aw_dev_get_iis_status(struct aw_device *aw_dev)
{ unsignedint reg_val; int ret;
ret = regmap_read(aw_dev->regmap, AW88395_SYSST_REG, ®_val); if (ret) return -EIO; if ((reg_val & AW88395_BIT_PLL_CHECK) != AW88395_BIT_PLL_CHECK) {
dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val); return -EINVAL;
}
return0;
}
staticint aw_dev_check_mode1_pll(struct aw_device *aw_dev)
{ int ret, i;
for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) {
ret = aw_dev_get_iis_status(aw_dev); if (ret < 0) {
dev_err(aw_dev->dev, "mode1 iis signal check error");
usleep_range(AW88395_2000_US, AW88395_2000_US + 10);
} else { return0;
}
}
return -EPERM;
}
staticint aw_dev_check_mode2_pll(struct aw_device *aw_dev)
{ unsignedint reg_val; int ret, i;
ret = regmap_read(aw_dev->regmap, AW88395_PLLCTRL1_REG, ®_val); if (ret) return ret;
reg_val &= (~AW88395_CCO_MUX_MASK); if (reg_val == AW88395_CCO_MUX_DIVIDED_VALUE) {
dev_dbg(aw_dev->dev, "CCO_MUX is already divider"); return -EPERM;
}
/* change mode2 */
ret = regmap_update_bits(aw_dev->regmap, AW88395_PLLCTRL1_REG,
~AW88395_CCO_MUX_MASK, AW88395_CCO_MUX_DIVIDED_VALUE); if (ret) return ret;
for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) {
ret = aw_dev_get_iis_status(aw_dev); if (ret) {
dev_err(aw_dev->dev, "mode2 iis signal check error");
usleep_range(AW88395_2000_US, AW88395_2000_US + 10);
} else { break;
}
}
/* change mode1 */
ret = regmap_update_bits(aw_dev->regmap, AW88395_PLLCTRL1_REG,
~AW88395_CCO_MUX_MASK, AW88395_CCO_MUX_BYPASS_VALUE); if (ret == 0) {
usleep_range(AW88395_2000_US, AW88395_2000_US + 10); for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) {
ret = aw_dev_check_mode1_pll(aw_dev); if (ret < 0) {
dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error");
usleep_range(AW88395_2000_US, AW88395_2000_US + 10);
} else { break;
}
}
}
return ret;
}
staticint aw_dev_check_syspll(struct aw_device *aw_dev)
{ int ret;
ret = aw_dev_check_mode1_pll(aw_dev); if (ret) {
dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check");
ret = aw_dev_check_mode2_pll(aw_dev); if (ret) {
dev_err(aw_dev->dev, "mode2 check iis failed"); return ret;
}
}
for (i = 0; i < data_len; i += 2) {
reg_addr = reg_data[i];
reg_val = reg_data[i + 1];
if (reg_addr == AW88395_SYSCTRL_REG) {
ret = regmap_read(aw_dev->regmap, reg_addr, &read_val); if (ret) break;
read_val &= (~AW88395_HMUTE_MASK);
reg_val &= AW88395_HMUTE_MASK;
reg_val |= read_val;
} if (reg_addr == AW88395_HAGCCFG7_REG)
reg_val &= AW88395_AGC_DSP_CTL_MASK;
if (reg_addr == AW88395_I2SCFG1_REG) { /* close tx */
reg_val &= AW88395_I2STXEN_MASK;
reg_val |= AW88395_I2STXEN_DISABLE_VALUE;
}
if (reg_addr == AW88395_SYSCTRL2_REG) {
read_vol = (reg_val & (~AW88395_VOL_MASK)) >>
AW88395_VOL_START_BIT;
aw_dev->volume_desc.init_volume =
reg_val_to_db(read_vol);
}
ret = regmap_write(aw_dev->regmap, reg_addr, reg_val); if (ret) break;
}
aw_dev_get_cur_mode_st(aw_dev);
if (aw_dev->prof_cur != aw_dev->prof_index) { /* clear control volume when PA change profile */
vol_desc->ctl_volume = 0;
} else { /* keep control volume when PA start with sync mode */
aw_dev_set_volume(aw_dev, vol_desc->ctl_volume);
}
staticint aw_dev_dsp_update_container(struct aw_device *aw_dev, unsignedchar *data, unsignedint len, unsignedshort base)
{ int i, ret;
#ifdef AW88395_DSP_I2C_WRITES
u32 tmp_len;
mutex_lock(&aw_dev->dsp_lock);
ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, base); if (ret) goto error_operation;
for (i = 0; i < len; i += AW88395_MAX_RAM_WRITE_BYTE_SIZE) {
tmp_len = min(len - i, AW88395_MAX_RAM_WRITE_BYTE_SIZE);
ret = regmap_raw_write(aw_dev->regmap, AW88395_DSPMDAT_REG,
&data[i], tmp_len); if (ret) goto error_operation;
}
mutex_unlock(&aw_dev->dsp_lock); #else
__be16 reg_val;
mutex_lock(&aw_dev->dsp_lock); /* i2c write */
ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, base); if (ret) goto error_operation; for (i = 0; i < len; i += 2) {
reg_val = cpu_to_be16p((u16 *)(data + i));
ret = regmap_write(aw_dev->regmap, AW88395_DSPMDAT_REG,
(u16)reg_val); if (ret) goto error_operation;
}
mutex_unlock(&aw_dev->dsp_lock); #endif
if (!len || !data) {
dev_err(aw_dev->dev, "dsp firmware data is null or len is 0"); return -EINVAL;
}
aw_dev_dsp_update_container(aw_dev, data, len, AW88395_DSP_FW_ADDR);
aw_dev->dsp_fw_len = len;
ret = aw_dev_copy_to_crc_dsp_cfg(aw_dev, data, len); if (ret) return ret;
ret = aw_dev_set_vcalb(aw_dev); if (ret) return ret;
ret = aw_dev_get_ra(&aw_dev->cali_desc); if (ret) return ret;
ret = aw_dev_get_cali_f0_delay(aw_dev); if (ret) return ret;
if ((aw_dev->cali_desc.cali_re < AW88395_CALI_RE_MAX) &&
(aw_dev->cali_desc.cali_re > AW88395_CALI_RE_MIN)) {
ret = aw_dev_dsp_set_cali_re(aw_dev); if (ret)
dev_err(aw_dev->dev, "set cali re failed");
}
}
int aw88395_dev_start(struct aw_device *aw_dev)
{ int ret;
if (aw_dev->status == AW88395_DEV_PW_ON) {
dev_info(aw_dev->dev, "already power on"); return0;
} /* power on */
aw_dev_pwd(aw_dev, false);
usleep_range(AW88395_2000_US, AW88395_2000_US + 10);
ret = aw_dev_check_syspll(aw_dev); if (ret) {
dev_err(aw_dev->dev, "pll check failed cannot start"); goto pll_check_fail;
}
/* amppd on */
aw_dev_amppd(aw_dev, false);
usleep_range(AW88395_1000_US, AW88395_1000_US + 50);
/* check i2s status */
ret = aw_dev_check_sysst(aw_dev); if (ret) {
dev_err(aw_dev->dev, "sysst check failed"); goto sysst_check_fail;
}
if (aw_dev->dsp_cfg == AW88395_DEV_DSP_WORK) { /* dsp bypass */
aw_dev_dsp_enable(aw_dev, false);
ret = aw_dev_dsp_fw_check(aw_dev); if (ret) goto dev_dsp_fw_check_fail;
aw_dev_update_cali_re(&aw_dev->cali_desc);
if (aw_dev->dsp_crc_st != AW88395_DSP_CRC_OK) {
ret = aw_dev_dsp_check_crc32(aw_dev); if (ret) {
dev_err(aw_dev->dev, "dsp crc check failed"); goto crc_check_fail;
}
}
ret = aw_dev_dsp_check(aw_dev); if (ret) {
dev_err(aw_dev->dev, "dsp status check failed"); goto dsp_check_fail;
}
} else {
dev_dbg(aw_dev->dev, "start pa with dsp bypass");
}
int aw88395_dev_get_profile_count(struct aw_device *aw_dev)
{ return aw_dev->prof_info.count;
}
EXPORT_SYMBOL_GPL(aw88395_dev_get_profile_count);
int aw88395_dev_get_profile_index(struct aw_device *aw_dev)
{ return aw_dev->prof_index;
}
EXPORT_SYMBOL_GPL(aw88395_dev_get_profile_index);
int aw88395_dev_set_profile_index(struct aw_device *aw_dev, int index)
{ /* check the index whether is valid */ if ((index >= aw_dev->prof_info.count) || (index < 0)) return -EINVAL; /* check the index whether change */ if (aw_dev->prof_index == index) return -EINVAL;
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.169Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-14)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.