static int snddev_icodec_rxclk_enable(struct snddev_icodec_state *icodec, int en) { int trc; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; mutex_lock(&drv->rx_mclk_lock); if (en) { if (aic3254_use_mclk_counter == 0) { drv->rx_osrclk = clk_get(0, "i2s_spkr_osr_clk"); if (IS_ERR(drv->rx_osrclk)) { pr_aud_err("%s turning on RX MCLK Error\n", \ __func__); goto error_invalid_osrclk; } trc = clk_set_rate(drv->rx_osrclk, \ SNDDEV_ICODEC_CLK_RATE(\ icodec->sample_rate)); if (IS_ERR_VALUE(trc)) { pr_aud_err("ERROR setting RX m clock1\n"); goto error_invalid_freq; } clk_enable(drv->rx_osrclk); } aic3254_use_mclk_counter++; } else { if (aic3254_use_mclk_counter > 0) { aic3254_use_mclk_counter--; if (aic3254_use_mclk_counter == 0) clk_disable(drv->rx_osrclk); } else pr_aud_info("%s: counter error!\n", __func__); } mutex_unlock(&drv->rx_mclk_lock); pr_aud_info("%s: en: %d counter: %d\n", __func__, en, \ aic3254_use_mclk_counter); return 0; error_invalid_osrclk: error_invalid_freq: pr_aud_err("%s: encounter error\n", __func__); msm_snddev_rx_mclk_free(); mutex_unlock(&drv->rx_mclk_lock); return -ENODEV; }
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) { 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_rx(struct snddev_icodec_state *icodec) { struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; 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_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(drv->rx_bitclk); clk_disable(drv->rx_osrclk); msm_snddev_rx_mclk_free(); icodec->enabled = 0; wake_unlock(&drv->rx_idlelock); return 0; }
static int snddev_icodec_open_rx(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->rx_idlelock); 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); } 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_freq; } } else { msm_snddev_rx_mclk_request(); drv->rx_osrclk = clk_get(0, "i2s_spkr_osr_clk"); if (IS_ERR(drv->rx_osrclk)) pr_aud_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_aud_err("ERROR setting m clock1\n"); goto error_invalid_freq; } clk_enable(drv->rx_osrclk); } drv->rx_bitclk = clk_get(0, "i2s_spkr_bit_clk"); if (IS_ERR(drv->rx_bitclk)) pr_aud_err("%s clock Error\n", __func__); /* *************************************** * 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->rx_bitclk, 0); } else trc = clk_set_rate(drv->rx_bitclk, 8); if (IS_ERR_VALUE(trc)) { pr_aud_err("ERROR setting m clock1\n"); goto error_adie; } clk_enable(drv->rx_bitclk); if (icodec->data->voltage_on) icodec->data->voltage_on(1); if (support_aic3254) { if (aic3254_ops->aic3254_set_mode) { if (msm_get_call_state() == 1) aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_RX, icodec->data->aic3254_voc_id); else aic3254_ops->aic3254_set_mode(AIC3254_CONFIG_RX, icodec->data->aic3254_id); } } if (support_adie) { /* Configure 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); /* 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; 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 (support_adie) { /* 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) icodec->data->pamp_on(1); icodec->enabled = 1; wake_unlock(&drv->rx_idlelock); return 0; error_adie: clk_disable(drv->rx_bitclk); clk_disable(drv->rx_osrclk); error_invalid_freq: pr_aud_err("%s: encounter error\n", __func__); msm_snddev_rx_mclk_free(); wake_unlock(&drv->rx_idlelock); return -ENODEV; }