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_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_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 (trc < 0) pr_aud_err("%s: afe open failed, trc = %d\n", __func__, trc); 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; }