static void debugfs_afe_loopback(u32 loop) { int trc; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; if (loop) { /* enable MI2S RX master block */ /* enable MI2S RX bit clock */ trc = clk_set_rate(drv->rx_mclk, SNDDEV_ICODEC_CLK_RATE(8000)); if (IS_ERR_VALUE(trc)) pr_err("%s: failed to set clk rate\n", __func__); clk_enable(drv->rx_mclk); clk_enable(drv->rx_sclk); clk_enable(drv->lpa_codec_clk); clk_enable(drv->lpa_core_clk); clk_enable(drv->lpa_p_clk); pr_info("%s: configure ADIE RX path\n", __func__); /* Configure ADIE */ adie_codec_open(&debug_rx_profile, &debugfs_rx_adie); adie_codec_setpath(debugfs_rx_adie, 8000, 256); adie_codec_proceed_stage(debugfs_rx_adie, ADIE_CODEC_DIGITAL_ANALOG_READY); pr_info("%s: Enable Handset Mic bias\n", __func__); /* enable MI2S TX master block */ /* enable MI2S TX bit clock */ clk_set_rate(drv->tx_mclk, SNDDEV_ICODEC_CLK_RATE(8000)); clk_enable(drv->tx_mclk); clk_enable(drv->tx_sclk); pr_info("%s: configure ADIE TX path\n", __func__); /* Configure ADIE */ adie_codec_open(&debug_tx_profile, &debugfs_tx_adie); adie_codec_setpath(debugfs_tx_adie, 8000, 256); adie_codec_proceed_stage(debugfs_tx_adie, ADIE_CODEC_DIGITAL_ANALOG_READY); } else { /* Disable ADIE */ adie_codec_proceed_stage(debugfs_rx_adie, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(debugfs_rx_adie); adie_codec_proceed_stage(debugfs_tx_adie, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(debugfs_tx_adie); /* Disable MI2S RX master block */ /* Disable MI2S RX bit clock */ clk_disable(drv->rx_sclk); clk_disable(drv->rx_mclk); /* Disable MI2S TX master block */ /* Disable MI2S TX bit clock */ clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); } }
static void debugfs_adie_loopback(u32 loop) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; if (loop) { /* enable MI2S RX master block */ /* enable MI2S RX bit clock */ clk_set_rate(drv->rx_mclk, SNDDEV_ICODEC_CLK_RATE(8000)); clk_enable(drv->rx_mclk); clk_enable(drv->rx_sclk); MM_INFO("configure ADIE RX path\n"); /* Configure ADIE */ adie_codec_open(&debug_rx_profile, &debugfs_rx_adie); adie_codec_setpath(debugfs_rx_adie, 8000, 256); adie_codec_proceed_stage(debugfs_rx_adie, ADIE_CODEC_DIGITAL_ANALOG_READY); MM_INFO("Enable Handset Mic bias\n"); pmic_hsed_enable(PM_HSED_CONTROLLER_0, PM_HSED_ENABLE_PWM_TCXO); /* enable MI2S TX master block */ /* enable MI2S TX bit clock */ clk_set_rate(drv->tx_mclk, SNDDEV_ICODEC_CLK_RATE(8000)); clk_enable(drv->tx_mclk); clk_enable(drv->tx_sclk); MM_INFO("configure ADIE TX path\n"); /* Configure ADIE */ adie_codec_open(&debug_tx_lb_profile, &debugfs_tx_adie); adie_codec_setpath(debugfs_tx_adie, 8000, 256); adie_codec_proceed_stage(debugfs_tx_adie, ADIE_CODEC_DIGITAL_ANALOG_READY); } else { /* Disable ADIE */ adie_codec_proceed_stage(debugfs_rx_adie, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(debugfs_rx_adie); adie_codec_proceed_stage(debugfs_tx_adie, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(debugfs_tx_adie); pmic_hsed_enable(PM_HSED_CONTROLLER_0, PM_HSED_ENABLE_OFF); /* Disable MI2S RX master block */ /* Disable MI2S RX bit clock */ clk_disable(drv->rx_sclk); clk_disable(drv->rx_mclk); /* Disable MI2S TX master block */ /* Disable MI2S TX bit clock */ clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); } }
static int snddev_icodec_open_rx(struct snddev_icodec_state *icodec) { int trc; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; wake_lock(&drv->rx_idlelock); /* enable MI2S RX master block */ /* enable MI2S RX bit clock */ trc = clk_set_rate(drv->rx_mclk, SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate)); if (IS_ERR_VALUE(trc)) goto error_invalid_freq; clk_enable(drv->rx_mclk); clk_enable(drv->rx_sclk); /* clk_set_rate(drv->lpa_codec_clk, 1); */ /* Remove if use pcom */ clk_enable(drv->lpa_p_clk); clk_enable(drv->lpa_codec_clk); clk_enable(drv->lpa_core_clk); /* Configure ADIE */ trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) goto error_adie; /* OSR default to 256, can be changed for power optimization * If OSR is to be changed, need clock API for setting the divider */ adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); /* Enable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); /* Enable power amplifier */ if (icodec->data->pamp_on) icodec->data->pamp_on(); icodec->enabled = 1; wake_unlock(&drv->rx_idlelock); return 0; error_adie: clk_disable(drv->lpa_p_clk); clk_disable(drv->lpa_codec_clk); clk_disable(drv->lpa_core_clk); clk_disable(drv->rx_sclk); clk_disable(drv->rx_mclk); error_invalid_freq: pr_err("%s: encounter error\n", __func__); wake_unlock(&drv->rx_idlelock); return -ENODEV; }
static int snddev_icodec_open_tx(struct snddev_icodec_state *icodec) { int trc; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;; wake_lock(&drv->tx_idlelock); /* Reuse pamp_on for TX platform-specific setup */ if (icodec->data->pamp_on) icodec->data->pamp_on(); /* enable MI2S TX master block */ /* enable MI2S TX bit clock */ trc = clk_set_rate(drv->tx_mclk, SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate)); if (IS_ERR_VALUE(trc)) goto error_invalid_freq; clk_enable(drv->tx_mclk); clk_enable(drv->tx_sclk); /* Enable ADIE */ trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) goto error_adie; /* Enable ADIE */ adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); icodec->enabled = 1; wake_unlock(&drv->tx_idlelock); return 0; error_adie: clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); error_invalid_freq: if (icodec->data->pamp_off) icodec->data->pamp_off(); pr_err("%s: encounter error\n", __func__); wake_unlock(&drv->tx_idlelock); return -ENODEV; }
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; afe_disable(AFE_HW_PATH_CODEC_TX); /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; /* Disable MI2S TX master block */ /* Disable MI2S TX bit clock */ clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); /* Disable mic bias */ pmic_hsed_enable(PM_HSED_CONTROLLER_0, PM_HSED_ENABLE_OFF); vreg_disable(drv->vreg_gp16); vreg_disable(drv->vreg_ncp); vreg_disable(drv->vreg_msme); vreg_disable(drv->vreg_rf2); icodec->enabled = 0; return 0; }
static int snddev_icodec_open_lb(struct snddev_icodec_state *icodec) { int trc; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; /* Voting for low power is ok here as all use cases are * supported in low power mode. */ if (drv->snddev_vreg) vreg_mode_vote(drv->snddev_vreg, 1, SNDDEV_LOW_POWER_MODE); if (icodec->data->voltage_on) icodec->data->voltage_on(); trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) pr_err("%s: adie codec open failed\n", __func__); else adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); if (icodec->adie_path) adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); if (icodec->data->pamp_on) icodec->data->pamp_on(); icodec->enabled = 1; return 0; }
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; pm_qos_update_request(&drv->tx_pm_qos_req, msm_cpuidle_get_deep_idle_latency()); if (drv->snddev_vreg) vreg_mode_vote(drv->snddev_vreg, 0, SNDDEV_HIGH_POWER_MODE); /* Disable ADIE */ if (icodec->adie_path) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } afe_close(icodec->data->copp_id); clk_disable_unprepare(drv->tx_bitclk); clk_disable_unprepare(drv->tx_osrclk); msm_snddev_tx_mclk_free(); /* Reuse pamp_off for TX platform-specific setup */ if (icodec->data->pamp_off) icodec->data->pamp_off(); icodec->enabled = 0; pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE); return 0; }
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; wake_lock(&drv->rx_idlelock); /* Disable power amplifier */ if (icodec->data->pamp_off) icodec->data->pamp_off(); /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; /* Disable LPA clocks */ clk_disable(drv->lpa_p_clk); clk_disable(drv->lpa_codec_clk); clk_disable(drv->lpa_core_clk); /* Disable MI2S RX master block */ /* Disable MI2S RX bit clock */ clk_disable(drv->rx_sclk); clk_disable(drv->rx_mclk); icodec->enabled = 0; wake_unlock(&drv->rx_idlelock); return 0; }
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; wake_lock(&drv->tx_idlelock); /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; /* Disable MI2S TX master block */ /* Disable MI2S TX bit clock */ clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); /* Reuse pamp_off for TX platform-specific setup */ if (icodec->data->pamp_off) icodec->data->pamp_off(); icodec->enabled = 0; wake_unlock(&drv->tx_idlelock); return 0; }
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; wake_lock(&drv->tx_idlelock); if (drv->snddev_vreg) vreg_mode_vote(drv->snddev_vreg, 0, SNDDEV_HIGH_POWER_MODE); /* Disable ADIE */ if (icodec->adie_path) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } afe_close(icodec->data->copp_id); clk_disable(drv->tx_bitclk); clk_disable(drv->tx_osrclk); msm_snddev_tx_mclk_free(); /* Reuse pamp_off for TX platform-specific setup */ if (icodec->data->pamp_off) icodec->data->pamp_off(); icodec->enabled = 0; wake_unlock(&drv->tx_idlelock); return 0; }
static int marimba_adie_codec_close(struct adie_codec_path *path_ptr) { int rc = 0; mutex_lock(&adie_codec.lock); if (!path_ptr) { rc = -EINVAL; goto error; } #if defined(CONFIG_MACH_ACER_A4) || defined(CONFIG_MACH_ACER_A5) if (path_ptr->curr_stage != ADIE_CODEC_DIGITAL_OFF) { mutex_unlock(&adie_codec.lock); adie_codec_proceed_stage(path_ptr, ADIE_CODEC_DIGITAL_OFF); mutex_lock(&adie_codec.lock); } #else if (path_ptr->curr_stage != ADIE_CODEC_DIGITAL_OFF) adie_codec_proceed_stage(path_ptr, ADIE_CODEC_DIGITAL_OFF); #endif BUG_ON(!adie_codec.ref_cnt); path_ptr->profile = NULL; adie_codec.ref_cnt--; if (!adie_codec.ref_cnt) { marimba_codec_bring_down(); if (adie_codec.codec_pdata && adie_codec.codec_pdata->marimba_codec_power) { rc = adie_codec.codec_pdata->marimba_codec_power(0); if (rc) { pr_err("%s: could not power down marimba " "codec\n", __func__); goto error; } } } error: mutex_unlock(&adie_codec.lock); return rc; }
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; struct snddev_icodec_data *data = icodec->data; wake_lock(&drv->rx_idlelock); /* Disable power amplifier */ if (icodec->data->pamp_on) icodec->data->pamp_on(0); if (!support_aic3254) { if (support_adie) { /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } } else { /* Restore default id for A3254 */ if (data->aic3254_id != data->default_aic3254_id) data->aic3254_id = data->default_aic3254_id; /* Disable External Codec A3254 */ if (aic3254_ops->aic3254_set_mode) aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_RX, DOWNLINK_OFF); } afe_disable(AFE_HW_PATH_CODEC_RX); /* Enable qtr headset amplifier */ if (icodec->data->pre_pamp_on) icodec->data->pre_pamp_on(0); /* Disable LPA Sub system */ lpa_cmd_enable_codec(drv->lpa, 0); lpa_put(drv->lpa); /* Disable LPA clocks */ clk_disable(drv->lpa_p_clk); clk_disable(drv->lpa_codec_clk); clk_disable(drv->lpa_core_clk); /* Disable MI2S RX master block */ /* Disable MI2S RX bit clock */ //HTC_CSP_START #ifndef CONFIG_CODEC_AIC3008 clk_disable(drv->rx_sclk); clk_disable(drv->rx_mclk); #endif //HTC_CSP_END icodec->enabled = 0; wake_unlock(&drv->rx_idlelock); return 0; }
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; struct snddev_icodec_data *data = icodec->data; wake_lock(&drv->rx_idlelock); if (drv->snddev_vreg) vreg_mode_vote(drv->snddev_vreg, 0, SNDDEV_HIGH_POWER_MODE); /* Disable power amplifier */ if (icodec->data->pamp_on) icodec->data->pamp_on(0); if (support_aic3254) { /* Restore default id for A3254 */ if (data->aic3254_id != data->default_aic3254_id) data->aic3254_id = data->default_aic3254_id; /* Disable External Codec A3254 */ if (aic3254_ops->aic3254_set_mode) aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_RX, DOWNLINK_OFF); } if (support_adie) { /* Disable ADIE */ if (icodec->adie_path) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } } afe_close(icodec->data->copp_id); if (icodec->data->voltage_on) icodec->data->voltage_on(0); clk_disable(drv->rx_bitclk); if (support_aic3254_use_mclk) snddev_icodec_rxclk_enable(icodec, 0); else clk_disable(drv->rx_osrclk); msm_snddev_rx_mclk_free(); icodec->enabled = 0; wake_unlock(&drv->rx_idlelock); return 0; }
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec) { int err; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; pm_qos_update_request(&drv->rx_pm_qos_req, msm_cpuidle_get_deep_idle_latency()); /* Remove the vote for SMPS mode*/ err = pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID, PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE); if (err != 0) MM_ERR("pmapp_smps_mode_vote error %d\n", err); /* Disable power amplifier */ if (icodec->data->pamp_off) icodec->data->pamp_off(); /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; afe_disable(AFE_HW_PATH_CODEC_RX); if (icodec->data->voltage_off) icodec->data->voltage_off(); /* Disable LPA Sub system */ lpa_cmd_enable_codec(drv->lpa, 0); lpa_put(drv->lpa); /* Disable LPA clocks */ clk_disable_unprepare(drv->lpa_p_clk); clk_disable_unprepare(drv->lpa_codec_clk); clk_disable_unprepare(drv->lpa_core_clk); /* Disable MI2S RX master block */ /* Disable MI2S RX bit clock */ clk_disable_unprepare(drv->rx_sclk); clk_disable_unprepare(drv->rx_mclk); icodec->enabled = 0; pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE); return 0; }
static int snddev_icodec_close_lb(struct snddev_icodec_state *icodec) { /* Disable power amplifier */ if (icodec->data->pamp_off) icodec->data->pamp_off(); if (icodec->adie_path) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } if (icodec->data->voltage_off) icodec->data->voltage_off(); return 0; }
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; struct snddev_icodec_data *data = icodec->data; wake_lock(&drv->tx_idlelock); afe_disable(AFE_HW_PATH_CODEC_TX); if (support_adie) { /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } if (support_aic3254) { /* Restore default id for A3254 */ if (data->aic3254_id != data->default_aic3254_id) data->aic3254_id = data->default_aic3254_id; /* Disable External Codec A3254 */ if (aic3254_ops->aic3254_set_mode) aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_TX, UPLINK_OFF); } /* Disable MI2S TX master block */ /* Disable MI2S TX bit clock */ //HTC_CSP_START #ifndef CONFIG_CODEC_AIC3008 clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); #endif //HTC_CSP_END /* Reuse pamp_off for TX platform-specific setup */ if (icodec->data->pamp_on) icodec->data->pamp_on(0); icodec->enabled = 0; wake_unlock(&drv->tx_idlelock); return 0; }
static int snddev_icodec_open_lb(struct snddev_icodec_state *icodec) { int trc; trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) pr_err("%s: adie codec open failed\n", __func__); else adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); if (icodec->adie_path) adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); if (icodec->data->pamp_on) icodec->data->pamp_on(); icodec->enabled = 1; return 0; }
int adie_codec_close(struct adie_codec_path *path_ptr) { int rc = 0; mutex_lock(&adie_codec.lock); if (!path_ptr) { rc = -EINVAL; goto error; } if (path_ptr->curr_stage != ADIE_CODEC_DIGITAL_OFF) adie_codec_proceed_stage(path_ptr, ADIE_CODEC_DIGITAL_OFF); BUG_ON(!adie_codec.ref_cnt); path_ptr->profile = NULL; adie_codec.ref_cnt--; if (!adie_codec.ref_cnt) { adie_codec_write(0xFF, 0xFF, 0x07); adie_codec_write(0xFF, 0xFF, 0x06); adie_codec_write(0xFF, 0xFF, 0x0e); adie_codec_write(0xFF, 0xFF, 0x08); adie_codec_write(0x03, 0xFF, 0x00); if (adie_codec.codec_pdata && adie_codec.codec_pdata->marimba_codec_power) { rc = adie_codec.codec_pdata->marimba_codec_power(0); if (rc) { pr_aud_err("%s: could not power down marimba " "codec\n", __func__); goto error; } } } error: mutex_unlock(&adie_codec.lock); return rc; }
static int snddev_icodec_close_tx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; int i, err; pm_qos_update_request(&drv->tx_pm_qos_req, msm_cpuidle_get_deep_idle_latency()); /* Remove the vote for SMPS mode*/ err = pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID, PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE); if (err != 0) MM_ERR("pmapp_smps_mode_vote error %d\n", err); afe_disable(AFE_HW_PATH_CODEC_TX); /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; /* Disable MI2S TX master block */ /* Disable MI2S TX bit clock */ clk_disable_unprepare(drv->tx_sclk); clk_disable_unprepare(drv->tx_mclk); /* Disable mic bias */ for (i = 0; i < icodec->data->pmctl_id_sz; i++) { pmic_hsed_enable(icodec->data->pmctl_id[i], PM_HSED_ENABLE_OFF); } /* Reuse pamp_off for TX platform-specific setup */ if (icodec->data->pamp_off) icodec->data->pamp_off(); icodec->enabled = 0; pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE); return 0; }
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; wake_lock(&drv->rx_idlelock); /* Disable power amplifier */ if (icodec->data->pamp_on) icodec->data->pamp_on(0); if (!support_aic3254 || !strcmp(icodec->data->name, "usb_headset_stereo_rx")) { /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } afe_disable(AFE_HW_PATH_CODEC_RX); /* Disable LPA Sub system */ lpa_cmd_enable_codec(drv->lpa, 0); lpa_put(drv->lpa); /* Disable LPA clocks */ clk_disable(drv->lpa_p_clk); clk_disable(drv->lpa_codec_clk); clk_disable(drv->lpa_core_clk); /* Disable MI2S RX master block */ /* Disable MI2S RX bit clock */ clk_disable(drv->rx_sclk); if (!support_aic3254) clk_disable(drv->rx_mclk); icodec->enabled = 0; wake_unlock(&drv->rx_idlelock); return 0; }
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; pr_info("%s\n", __func__); // pm_qos_update_request(&drv->rx_pm_qos_req, msm_cpuidle_get_deep_idle_latency()); if (drv->snddev_vreg) vreg_mode_vote(drv->snddev_vreg, 0, SNDDEV_HIGH_POWER_MODE); /* Disable power amplifier */ if (icodec->data->pamp_off) icodec->data->pamp_off(); /* Disable ADIE */ if (icodec->adie_path) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } afe_close(icodec->data->copp_id); if (icodec->data->voltage_off) icodec->data->voltage_off(); clk_disable_unprepare(drv->rx_bitclk); clk_disable_unprepare(drv->rx_osrclk); msm_snddev_rx_mclk_free(); icodec->enabled = 0; pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE); return 0; }
static int snddev_icodec_close_lb(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; /* Disable power amplifier */ if (icodec->data->pamp_off) icodec->data->pamp_off(); if (drv->snddev_vreg) vreg_mode_vote(drv->snddev_vreg, 0, SNDDEV_LOW_POWER_MODE); if (icodec->adie_path) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } if (icodec->data->voltage_off) icodec->data->voltage_off(); return 0; }
static int snddev_icodec_close_rx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; /* Disable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; afe_disable(AFE_HW_PATH_CODEC_RX); /* Disable MI2S RX master block */ /* Disable MI2S RX bit clock */ clk_disable(drv->rx_sclk); clk_disable(drv->rx_mclk); vreg_disable(drv->vreg_gp16); vreg_disable(drv->vreg_ncp); vreg_disable(drv->vreg_msme); vreg_disable(drv->vreg_rf2); icodec->enabled = 0; return 0; }
static int snddev_icodec_open_rx(struct snddev_icodec_state *icodec) { int trc, err; int smps_mode = PMAPP_SMPS_MODE_VOTE_PWM; struct msm_afe_config afe_config; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; struct lpa_codec_config lpa_config; wake_lock(&drv->rx_idlelock); if ((icodec->data->acdb_id == ACDB_ID_HEADSET_SPKR_MONO) || (icodec->data->acdb_id == ACDB_ID_HEADSET_SPKR_STEREO)) { /* Vote PMAPP_SMPS_MODE_VOTE_PFM for headset */ smps_mode = PMAPP_SMPS_MODE_VOTE_PFM; MM_DBG("snddev_icodec_open_rx: PMAPP_SMPS_MODE_VOTE_PFM \n"); } else MM_DBG("snddev_icodec_open_rx: PMAPP_SMPS_MODE_VOTE_PWM \n"); /* Vote for SMPS mode*/ err = pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID, PMAPP_VREG_S4, smps_mode); if (err != 0) MM_ERR("pmapp_smps_mode_vote error %d\n", err); /* enable MI2S RX master block */ /* enable MI2S RX bit clock */ trc = clk_set_rate(drv->rx_mclk, SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate)); if (IS_ERR_VALUE(trc)) goto error_invalid_freq; clk_enable(drv->rx_mclk); clk_enable(drv->rx_sclk); /* clk_set_rate(drv->lpa_codec_clk, 1); */ /* Remove if use pcom */ clk_enable(drv->lpa_p_clk); clk_enable(drv->lpa_codec_clk); clk_enable(drv->lpa_core_clk); /* Enable LPA sub system */ drv->lpa = lpa_get(); if (!drv->lpa) goto error_lpa; lpa_config.sample_rate = icodec->sample_rate; lpa_config.sample_width = 16; lpa_config.output_interface = LPA_OUTPUT_INTF_WB_CODEC; lpa_config.num_channels = icodec->data->channel_mode; lpa_cmd_codec_config(drv->lpa, &lpa_config); /* Set audio interconnect reg to LPA */ audio_interct_codec(AUDIO_INTERCT_LPA); /* Set MI2S */ mi2s_set_codec_output_path((icodec->data->channel_mode == 2 ? MI2S_CHAN_STEREO : MI2S_CHAN_MONO_PACKED), WT_16_BIT); if (icodec->data->voltage_on) icodec->data->voltage_on(); /* Configure ADIE */ trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) goto error_adie; /* OSR default to 256, can be changed for power optimization * If OSR is to be changed, need clock API for setting the divider */ adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); /* Start AFE */ afe_config.sample_rate = icodec->sample_rate / 1000; afe_config.channel_mode = icodec->data->channel_mode; afe_config.volume = AFE_VOLUME_UNITY; trc = afe_enable(AFE_HW_PATH_CODEC_RX, &afe_config); if (IS_ERR_VALUE(trc)) goto error_afe; lpa_cmd_enable_codec(drv->lpa, 1); /* Enable ADIE */ adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); /* Enable power amplifier */ if (icodec->data->pamp_on) icodec->data->pamp_on(); icodec->enabled = 1; wake_unlock(&drv->rx_idlelock); return 0; error_afe: adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; error_adie: lpa_put(drv->lpa); error_lpa: clk_disable(drv->lpa_p_clk); clk_disable(drv->lpa_codec_clk); clk_disable(drv->lpa_core_clk); clk_disable(drv->rx_sclk); clk_disable(drv->rx_mclk); error_invalid_freq: MM_ERR("encounter error\n"); wake_unlock(&drv->rx_idlelock); return -ENODEV; }
static int snddev_icodec_open_tx(struct snddev_icodec_state *icodec) { int trc; int afe_channel_mode; union afe_port_config afe_config; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;; pm_qos_update_request(&drv->tx_pm_qos_req, msm_cpuidle_get_deep_idle_latency()); if (drv->snddev_vreg) vreg_mode_vote(drv->snddev_vreg, 1, SNDDEV_HIGH_POWER_MODE); /* Reuse pamp_on for TX platform-specific setup */ if (icodec->data->pamp_on) { if (icodec->data->pamp_on()) { pr_err("%s: Error turning on tx power\n", __func__); goto error_pamp; } } msm_snddev_tx_mclk_request(); drv->tx_osrclk = clk_get_sys(NULL, "i2s_mic_osr_clk"); if (IS_ERR(drv->tx_osrclk)) pr_err("%s master clock Error\n", __func__); trc = clk_set_rate(drv->tx_osrclk, SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate)); if (IS_ERR_VALUE(trc)) { pr_err("ERROR setting m clock1\n"); goto error_invalid_freq; } clk_prepare_enable(drv->tx_osrclk); drv->tx_bitclk = clk_get_sys(NULL, "i2s_mic_bit_clk"); if (IS_ERR(drv->tx_bitclk)) pr_err("%s clock Error\n", __func__); /* Master clock = Sample Rate * OSR rate bit clock * OSR Rate bit clock = bit/sample * channel master * clock / bit clock = divider value = 8 */ if (msm_codec_i2s_slave_mode) { pr_info("%s: configuring bit clock for slave mode\n", __func__); trc = clk_set_rate(drv->tx_bitclk, 0); } else trc = clk_set_rate(drv->tx_bitclk, 8); clk_prepare_enable(drv->tx_bitclk); /* Enable ADIE */ trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) pr_err("%s: adie codec open failed\n", __func__); else adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); switch (icodec->data->channel_mode) { case 2: afe_channel_mode = MSM_AFE_STEREO; break; case 1: default: afe_channel_mode = MSM_AFE_MONO; break; } afe_config.mi2s.channel = afe_channel_mode; afe_config.mi2s.bitwidth = 16; afe_config.mi2s.line = 1; afe_config.mi2s.format = MSM_AFE_I2S_FORMAT_LPCM; if (msm_codec_i2s_slave_mode) afe_config.mi2s.ws = 0; else afe_config.mi2s.ws = 1; trc = afe_open(icodec->data->copp_id, &afe_config, icodec->sample_rate); if (icodec->adie_path) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); } if (msm_codec_i2s_slave_mode) adie_codec_set_master_mode(icodec->adie_path, 1); else adie_codec_set_master_mode(icodec->adie_path, 0); icodec->enabled = 1; pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE); return 0; error_invalid_freq: if (icodec->data->pamp_off) icodec->data->pamp_off(); pr_err("%s: encounter error\n", __func__); error_pamp: pm_qos_update_request(&drv->tx_pm_qos_req, PM_QOS_DEFAULT_VALUE); return -ENODEV; }
static int snddev_icodec_open_rx(struct snddev_icodec_state *icodec) { int trc; int afe_channel_mode; union afe_port_config afe_config; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; pm_qos_update_request(&drv->rx_pm_qos_req, msm_cpuidle_get_deep_idle_latency()); if (drv->snddev_vreg) { if (!strcmp(icodec->data->name, "headset_stereo_rx")) vreg_mode_vote(drv->snddev_vreg, 1, SNDDEV_LOW_POWER_MODE); else vreg_mode_vote(drv->snddev_vreg, 1, SNDDEV_HIGH_POWER_MODE); } msm_snddev_rx_mclk_request(); drv->rx_osrclk = clk_get_sys(NULL, "i2s_spkr_osr_clk"); if (IS_ERR(drv->rx_osrclk)) pr_err("%s master clock Error\n", __func__); trc = clk_set_rate(drv->rx_osrclk, SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate)); if (IS_ERR_VALUE(trc)) { pr_err("ERROR setting m clock1\n"); goto error_invalid_freq; } clk_prepare_enable(drv->rx_osrclk); drv->rx_bitclk = clk_get_sys(NULL, "i2s_spkr_bit_clk"); if (IS_ERR(drv->rx_bitclk)) pr_err("%s clock Error\n", __func__); /* Master clock = Sample Rate * OSR rate bit clock * OSR Rate bit clock = bit/sample * channel master * clock / bit clock = divider value = 8 */ if (msm_codec_i2s_slave_mode) { pr_info("%s: configuring bit clock for slave mode\n", __func__); trc = clk_set_rate(drv->rx_bitclk, 0); } else trc = clk_set_rate(drv->rx_bitclk, 8); if (IS_ERR_VALUE(trc)) { pr_err("ERROR setting m clock1\n"); goto error_adie; } clk_prepare_enable(drv->rx_bitclk); if (icodec->data->voltage_on) icodec->data->voltage_on(); /* Configure ADIE */ trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) pr_err("%s: adie codec open failed\n", __func__); else adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); /* OSR default to 256, can be changed for power optimization * If OSR is to be changed, need clock API for setting the divider */ switch (icodec->data->channel_mode) { case 2: afe_channel_mode = MSM_AFE_STEREO; break; case 1: default: afe_channel_mode = MSM_AFE_MONO; break; } afe_config.mi2s.channel = afe_channel_mode; afe_config.mi2s.bitwidth = 16; afe_config.mi2s.line = 1; afe_config.mi2s.format = MSM_AFE_I2S_FORMAT_LPCM; if (msm_codec_i2s_slave_mode) afe_config.mi2s.ws = 0; else afe_config.mi2s.ws = 1; trc = afe_open(icodec->data->copp_id, &afe_config, icodec->sample_rate); if (trc < 0) pr_err("%s: afe open failed, trc = %d\n", __func__, trc); /* Enable ADIE */ if (icodec->adie_path) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); } if (msm_codec_i2s_slave_mode) adie_codec_set_master_mode(icodec->adie_path, 1); else adie_codec_set_master_mode(icodec->adie_path, 0); /* Enable power amplifier */ if (icodec->data->pamp_on) { if (icodec->data->pamp_on()) { pr_err("%s: Error turning on rx power\n", __func__); goto error_pamp; } } icodec->enabled = 1; pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE); return 0; error_pamp: error_adie: clk_disable_unprepare(drv->rx_osrclk); error_invalid_freq: pr_err("%s: encounter error\n", __func__); pm_qos_update_request(&drv->rx_pm_qos_req, PM_QOS_DEFAULT_VALUE); return -ENODEV; }
static int snddev_icodec_open_tx(struct snddev_icodec_state *icodec) { int trc; struct msm_afe_config afe_config; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; printk("%s(): +++\n", __func__); wake_lock(&drv->tx_idlelock); /* Reuse pamp_on for TX platform-specific setup */ if (icodec->data->pamp_on) icodec->data->pamp_on(1); //HTC_AUD_START #ifndef CONFIG_CODEC_AIC3008 //HTC_AUD_END /* enable MI2S TX master block */ /* enable MI2S TX bit clock */ trc = clk_set_rate(drv->tx_mclk, SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate)); if (IS_ERR_VALUE(trc)) goto error_invalid_freq; clk_enable(drv->tx_mclk); clk_enable(drv->tx_sclk); //HTC_AUD_START #endif //HTC_AUD_END /* Set MI2S */ mi2s_set_codec_input_path((icodec->data->channel_mode == REAL_STEREO_CHANNEL_MODE ? MI2S_CHAN_STEREO : (icodec->data->channel_mode == 2 ? MI2S_CHAN_STEREO : MI2S_CHAN_MONO_RAW)), WT_16_BIT); /* Enable External Codec A3254 */ if (support_aic3254) { if (aic3254_ops->aic3254_set_mode) { if (msm_get_call_state() == 1) aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_TX, icodec->data->aic3254_voc_id); else aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_TX, icodec->data->aic3254_id); } } if (support_adie) { /* Configure ADIE */ trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) goto error_adie; /* Enable ADIE */ adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); if (adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY)) { /* icodec->adie_path->profile = NULL; */ goto error_adie; } if (adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY)) { /* icodec->adie_path->profile = NULL; */ goto error_adie; } } /* Start AFE */ afe_config.sample_rate = icodec->sample_rate / 1000; afe_config.channel_mode = icodec->data->channel_mode; afe_config.volume = AFE_VOLUME_UNITY; trc = afe_enable(AFE_HW_PATH_CODEC_TX, &afe_config); if (IS_ERR_VALUE(trc)) goto error_afe; icodec->enabled = 1; wake_unlock(&drv->tx_idlelock); printk("%s(): ---\n", __func__); return 0; error_afe: if (support_adie) { adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; } error_adie: //HTC_CSP_START #ifndef CONFIG_CODEC_AIC3008 clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); #endif //HTC_CSP_END //HTC_AUD_START #ifndef CONFIG_CODEC_AIC3008 //HTC_AUD_END error_invalid_freq: if (icodec->data->pamp_on) icodec->data->pamp_on(0); MM_AUD_ERR("%s: encounter error\n", __func__); wake_unlock(&drv->tx_idlelock); printk("%s(): ---\n", __func__); //HTC_AUD_START #endif //HTC_AUD_END return -ENODEV; }
static int snddev_icodec_open_tx(struct snddev_icodec_state *icodec) { int trc; int rc_clk; int afe_channel_mode; union afe_port_config afe_config; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;; wake_lock(&drv->tx_idlelock); if (drv->snddev_vreg) vreg_mode_vote(drv->snddev_vreg, 1, SNDDEV_HIGH_POWER_MODE); if (support_aic3254_use_mclk) { rc_clk = snddev_icodec_rxclk_enable(icodec, 1); if (IS_ERR_VALUE(rc_clk)) { pr_aud_err("%s Enable RX master clock Error\n", \ __func__); goto error_invalid_osrclk; } } msm_snddev_tx_mclk_request(); drv->tx_osrclk = clk_get(0, "i2s_mic_osr_clk"); if (IS_ERR(drv->tx_osrclk)) { pr_aud_err("%s master clock Error\n", __func__); goto error_invalid_osrclk; } trc = clk_set_rate(drv->tx_osrclk, SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate)); if (IS_ERR_VALUE(trc)) { pr_aud_err("ERROR setting m clock1\n"); goto error_invalid_freq; } clk_enable(drv->tx_osrclk); drv->tx_bitclk = clk_get(0, "i2s_mic_bit_clk"); if (IS_ERR(drv->tx_bitclk)) { pr_aud_err("%s clock Error\n", __func__); goto error_invalid_bitclk; } /* *************************************** * 1. CPU MASTER MODE: * Master clock = Sample Rate * OSR rate bit clock * OSR Rate bit clock = bit/sample * channel master * clock / bit clock = divider value = 8 * * 2. CPU SLAVE MODE: * bitclk = 0 * *************************************** */ if (msm_codec_i2s_slave_mode) { pr_debug("%s: configuring bit clock for slave mode\n", __func__); trc = clk_set_rate(drv->tx_bitclk, 0); } else trc = clk_set_rate(drv->tx_bitclk, 8); clk_enable(drv->tx_bitclk); if (support_aic3254) { if (aic3254_ops->aic3254_set_mode) { if (msm_get_call_state() == 1) aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_TX, icodec->data->aic3254_voc_id); else aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_TX, icodec->data->aic3254_id); } } if (support_adie) { /* Enable ADIE */ trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) pr_aud_err("%s: adie codec open failed\n", __func__); else adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); } switch (icodec->data->channel_mode) { case 2: afe_channel_mode = MSM_AFE_STEREO; break; case 1: default: afe_channel_mode = MSM_AFE_MONO; break; } afe_config.mi2s.channel = afe_channel_mode; afe_config.mi2s.bitwidth = 16; afe_config.mi2s.line = 1; if (msm_codec_i2s_slave_mode) afe_config.mi2s.ws = 0; else afe_config.mi2s.ws = 1; trc = afe_open(icodec->data->copp_id, &afe_config, icodec->sample_rate); if (icodec->adie_path && support_adie) { adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); if (msm_codec_i2s_slave_mode) adie_codec_set_master_mode(icodec->adie_path, 1); else adie_codec_set_master_mode(icodec->adie_path, 0); } /* Reuse pamp_on for TX platform-specific setup */ if (icodec->data->pamp_on) icodec->data->pamp_on(1); icodec->enabled = 1; wake_unlock(&drv->tx_idlelock); return 0; error_invalid_bitclk: clk_disable(drv->tx_osrclk); error_invalid_freq: error_invalid_osrclk: if (icodec->data->pamp_on) icodec->data->pamp_on(0); msm_snddev_tx_mclk_free(); pr_aud_err("%s: encounter error\n", __func__); wake_unlock(&drv->tx_idlelock); return -ENODEV; }
static int snddev_icodec_open_tx(struct snddev_icodec_state *icodec) { int trc; int i, err; struct msm_afe_config afe_config; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv;; wake_lock(&drv->tx_idlelock); /* Vote for PWM mode*/ err = pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID, PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_PWM); if (err != 0) MM_ERR("pmapp_smps_mode_vote error %d\n", err); /* Reuse pamp_on for TX platform-specific setup */ if (icodec->data->pamp_on) icodec->data->pamp_on(); for (i = 0; i < icodec->data->pmctl_id_sz; i++) { pmic_hsed_enable(icodec->data->pmctl_id[i], PM_HSED_ENABLE_PWM_TCXO); } /* enable MI2S TX master block */ /* enable MI2S TX bit clock */ trc = clk_set_rate(drv->tx_mclk, SNDDEV_ICODEC_CLK_RATE(icodec->sample_rate)); if (IS_ERR_VALUE(trc)) goto error_invalid_freq; clk_enable(drv->tx_mclk); clk_enable(drv->tx_sclk); /* Set MI2S */ mi2s_set_codec_input_path((icodec->data->channel_mode == REAL_STEREO_CHANNEL_MODE ? MI2S_CHAN_STEREO : (icodec->data->channel_mode == 2 ? MI2S_CHAN_STEREO : MI2S_CHAN_MONO_RAW)), WT_16_BIT); /* Configure ADIE */ trc = adie_codec_open(icodec->data->profile, &icodec->adie_path); if (IS_ERR_VALUE(trc)) goto error_adie; /* Enable ADIE */ adie_codec_setpath(icodec->adie_path, icodec->sample_rate, 256); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(icodec->adie_path, ADIE_CODEC_DIGITAL_ANALOG_READY); /* Start AFE */ afe_config.sample_rate = icodec->sample_rate / 1000; afe_config.channel_mode = icodec->data->channel_mode; afe_config.volume = AFE_VOLUME_UNITY; trc = afe_enable(AFE_HW_PATH_CODEC_TX, &afe_config); if (IS_ERR_VALUE(trc)) goto error_afe; icodec->enabled = 1; wake_unlock(&drv->tx_idlelock); return 0; error_afe: adie_codec_close(icodec->adie_path); icodec->adie_path = NULL; error_adie: clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); error_invalid_freq: /* Disable mic bias */ for (i = 0; i < icodec->data->pmctl_id_sz; i++) { pmic_hsed_enable(icodec->data->pmctl_id[i], PM_HSED_ENABLE_OFF); } if (icodec->data->pamp_off) icodec->data->pamp_off(); MM_ERR("encounter error\n"); wake_unlock(&drv->tx_idlelock); return -ENODEV; }
static void debugfs_afe_loopback(u32 loop) { int trc; struct msm_afe_config afe_config; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; struct lpa_codec_config lpa_config; if (loop) { /* Vote for SMPS mode*/ pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID, PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_PWM); /* enable MI2S RX master block */ /* enable MI2S RX bit clock */ trc = clk_set_rate(drv->rx_mclk, SNDDEV_ICODEC_CLK_RATE(8000)); if (IS_ERR_VALUE(trc)) MM_ERR("failed to set clk rate\n"); clk_enable(drv->rx_mclk); clk_enable(drv->rx_sclk); clk_enable(drv->lpa_p_clk); clk_enable(drv->lpa_codec_clk); clk_enable(drv->lpa_core_clk); /* Enable LPA sub system */ drv->lpa = lpa_get(); if (!drv->lpa) MM_ERR("failed to enable lpa\n"); lpa_config.sample_rate = 8000; lpa_config.sample_width = 16; lpa_config.output_interface = LPA_OUTPUT_INTF_WB_CODEC; lpa_config.num_channels = 1; lpa_cmd_codec_config(drv->lpa, &lpa_config); /* Set audio interconnect reg to LPA */ audio_interct_codec(AUDIO_INTERCT_LPA); mi2s_set_codec_output_path(MI2S_CHAN_MONO_PACKED, WT_16_BIT); MM_INFO("configure ADIE RX path\n"); /* Configure ADIE */ adie_codec_open(&debug_rx_profile, &debugfs_rx_adie); adie_codec_setpath(debugfs_rx_adie, 8000, 256); lpa_cmd_enable_codec(drv->lpa, 1); /* Start AFE for RX */ afe_config.sample_rate = 0x8; afe_config.channel_mode = 1; afe_config.volume = AFE_VOLUME_UNITY; MM_INFO("enable afe\n"); trc = afe_enable(AFE_HW_PATH_CODEC_RX, &afe_config); if (IS_ERR_VALUE(trc)) MM_ERR("fail to enable afe RX\n"); adie_codec_proceed_stage(debugfs_rx_adie, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(debugfs_rx_adie, ADIE_CODEC_DIGITAL_ANALOG_READY); /* Vote for PWM mode*/ pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID, PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_PWM); MM_INFO("Enable Handset Mic bias\n"); pmic_hsed_enable(PM_HSED_CONTROLLER_0, PM_HSED_ENABLE_PWM_TCXO); /* enable MI2S TX master block */ /* enable MI2S TX bit clock */ clk_set_rate(drv->tx_mclk, SNDDEV_ICODEC_CLK_RATE(8000)); clk_enable(drv->tx_mclk); clk_enable(drv->tx_sclk); /* Set MI2S */ mi2s_set_codec_input_path(MI2S_CHAN_MONO_PACKED, WT_16_BIT); MM_INFO("configure ADIE TX path\n"); /* Configure ADIE */ adie_codec_open(&debug_tx_profile, &debugfs_tx_adie); adie_codec_setpath(debugfs_tx_adie, 8000, 256); adie_codec_proceed_stage(debugfs_tx_adie, ADIE_CODEC_DIGITAL_READY); adie_codec_proceed_stage(debugfs_tx_adie, ADIE_CODEC_DIGITAL_ANALOG_READY); /* Start AFE for TX */ afe_config.sample_rate = 0x8; afe_config.channel_mode = 1; afe_config.volume = AFE_VOLUME_UNITY; trc = afe_enable(AFE_HW_PATH_CODEC_TX, &afe_config); if (IS_ERR_VALUE(trc)) MM_ERR("failed to enable AFE TX\n"); /* Set the volume level to non unity, to avoid loopback effect */ afe_device_volume_ctrl(AFE_HW_PATH_CODEC_RX, 0x0500); /* enable afe loopback */ afe_loopback(1); MM_INFO("AFE loopback enabled\n"); } else { /* disable afe loopback */ afe_loopback(0); /* Remove the vote for SMPS mode*/ pmapp_smps_mode_vote(SMPS_AUDIO_PLAYBACK_ID, PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE); /* Disable ADIE */ adie_codec_proceed_stage(debugfs_rx_adie, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(debugfs_rx_adie); /* Disable AFE for RX */ afe_disable(AFE_HW_PATH_CODEC_RX); /* Disable LPA Sub system */ lpa_cmd_enable_codec(drv->lpa, 0); lpa_put(drv->lpa); /* Disable LPA clocks */ clk_disable(drv->lpa_p_clk); clk_disable(drv->lpa_codec_clk); clk_disable(drv->lpa_core_clk); /* Disable MI2S RX master block */ /* Disable MI2S RX bit clock */ clk_disable(drv->rx_sclk); clk_disable(drv->rx_mclk); pmapp_smps_mode_vote(SMPS_AUDIO_RECORD_ID, PMAPP_VREG_S4, PMAPP_SMPS_MODE_VOTE_DONTCARE); /* Disable AFE for TX */ afe_disable(AFE_HW_PATH_CODEC_TX); /* Disable ADIE */ adie_codec_proceed_stage(debugfs_tx_adie, ADIE_CODEC_DIGITAL_OFF); adie_codec_close(debugfs_tx_adie); /* Disable MI2S TX master block */ /* Disable MI2S TX bit clock */ clk_disable(drv->tx_sclk); clk_disable(drv->tx_mclk); pmic_hsed_enable(PM_HSED_CONTROLLER_0, PM_HSED_ENABLE_OFF); MM_INFO("AFE loopback disabled\n"); } }