static int msm_loopback_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0; struct msm_snddev_info *src_dev_info = NULL; /* TX device */ struct msm_snddev_info *dst_dev_info = NULL; /* RX device */ int dst_dev_id = ucontrol->value.integer.value[0]; int src_dev_id = ucontrol->value.integer.value[1]; int set = ucontrol->value.integer.value[2]; pr_debug("%s: dst=%d :src=%d set=%d\n", __func__, dst_dev_id, src_dev_id, set); dst_dev_info = audio_dev_ctrl_find_dev(dst_dev_id); if (IS_ERR(dst_dev_info)) { pr_err("dst_dev:%s:pass invalid dev_id\n", __func__); rc = PTR_ERR(dst_dev_info); return rc; } if (!(dst_dev_info->capability & SNDDEV_CAP_RX)) { pr_err("Destination device %d is not RX device\n", dst_dev_id); return -EFAULT; } src_dev_info = audio_dev_ctrl_find_dev(src_dev_id); if (IS_ERR(src_dev_info)) { pr_err("src_dev:%s:pass invalid dev_id\n", __func__); rc = PTR_ERR(src_dev_info); return rc; } if (!(src_dev_info->capability & SNDDEV_CAP_TX)) { pr_err("Source device %d is not TX device\n", src_dev_id); return -EFAULT; } if (set) { pr_debug("%s:%d:Enabling AFE_Loopback\n", __func__, __LINE__); src_dev = src_dev_id; dst_dev = dst_dev_id; loopback_status = 1; if ((dst_dev_info->opened) && (src_dev_info->opened)) rc = afe_loopback(LOOPBACK_ENABLE, dst_dev_info->copp_id, src_dev_info->copp_id); } else { pr_debug("%s:%d:Disabling AFE_Loopback\n", __func__, __LINE__); src_dev = DEVICE_IGNORE; dst_dev = DEVICE_IGNORE; loopback_status = 0; rc = afe_loopback(LOOPBACK_DISABLE, dst_dev_info->copp_id, src_dev_info->copp_id); } return rc; }
static void fm_audio_listner(u32 evt_id, union auddev_evt_data *evt_payload, void *private_data) { struct audio *audio = (struct audio *) private_data; switch (evt_id) { case AUDDEV_EVT_DEV_RDY: pr_info("%s :AUDDEV_EVT_DEV_RDY\n", __func__); if (evt_payload->routing_id == FM_COPP) { audio->fm_source = 1; audio->fm_src_copp_id = FM_COPP; } else { audio->fm_dest = 1; audio->fm_dst_copp_id = evt_payload->routing_id; } if (audio->enabled && audio->fm_dest && audio->fm_source) { afe_loopback_gain(audio->fm_src_copp_id, audio->volume); afe_loopback(FM_ENABLE, audio->fm_dst_copp_id, audio->fm_src_copp_id); audio->running = 1; } break; case AUDDEV_EVT_DEV_RLS: pr_info("%s: AUDDEV_EVT_DEV_RLS\n", __func__); if (evt_payload->routing_id == audio->fm_src_copp_id) audio->fm_source = 0; else audio->fm_dest = 0; if (audio->running && (!audio->fm_dest || !audio->fm_source)) { afe_loopback(FM_DISABLE, audio->fm_dst_copp_id, audio->fm_src_copp_id); audio->running = 0; } else { pr_err("%s: device switch happened\n", __func__); } break; case AUDDEV_EVT_STREAM_VOL_CHG: pr_debug("%s: AUDDEV_EVT_STREAM_VOL_CHG\n", __func__); if (audio->fm_source) { audio->volume = evt_payload->session_vol; afe_loopback_gain(audio->fm_src_copp_id, audio->volume); } break; default: pr_err("%s: ERROR:wrong event %08x\n", __func__, evt_id); break; } }
static ssize_t afe_debug_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { char *lb_str = filp->private_data; char lbuf[32]; int rc; unsigned long param[5]; if (cnt > sizeof(lbuf) - 1) return -EINVAL; rc = copy_from_user(lbuf, ubuf, cnt); if (rc) return -EFAULT; lbuf[cnt] = '\0'; if (!strcmp(lb_str, "afe_loopback")) { rc = afe_get_parameters(lbuf, param, 3); if (!rc) { pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1], param[2]); if ((param[0] != AFE_LOOPBACK_ON) && (param[0] != AFE_LOOPBACK_OFF)) { pr_err("%s: Error, parameter 0 incorrect\n", __func__); rc = -EINVAL; goto afe_error; } #ifdef CONFIG_RECINCALL if ((afe_validate_port(param[1]) < 0) || (afe_validate_port(param[2])) < 0) #else if ((param[1] >= AFE_MAX_PORTS) || (param[2] >= AFE_MAX_PORTS)) #endif { pr_err("%s: Error, invalid afe port\n", __func__); } if (this_afe.apr == NULL) { pr_err("%s: Error, AFE not opened\n", __func__); rc = -EINVAL; } else { rc = afe_loopback(param[0], param[1], param[2]); } } else { pr_err("%s: Error, invalid parameters\n", __func__); rc = -EINVAL; } } afe_error: if (rc == 0) rc = cnt; else pr_err("%s: rc = %d\n", __func__, rc); return rc; }
static int audio_disable(struct audio *audio) { /* break the AFE loopback here */ afe_loopback(FM_DISABLE, audio->fm_dst_copp_id, audio->fm_src_copp_id); return 0; }
static int fm_audio_disable(struct audio *audio) { afe_loopback(FM_DISABLE, audio->fm_dst_copp_id, audio->fm_src_copp_id); return 0; }
static int audio_disable(struct audio *audio) { /* break the AFE loopback here */ afe_loopback(FM_DISABLE, audio->fm_dest, audio->fm_source); return 0; }
static void fm_listner(u32 evt_id, union auddev_evt_data *evt_payload, void *private_data) { struct audio *audio = (struct audio *) private_data; switch (evt_id) { case AUDDEV_EVT_DEV_RDY: pr_info(":AUDDEV_EVT_DEV_RDY\n"); if (evt_payload->routing_id == FM_COPP) { audio->fm_source = 1; audio->fm_src_copp_id = FM_COPP; } else { audio->fm_dest = 1; audio->fm_dst_copp_id = evt_payload->routing_id; } if (audio->enabled && audio->fm_dest && audio->fm_source) { afe_loopback(FM_ENABLE, audio->fm_dest, audio->fm_source); audio->running = 1; } break; case AUDDEV_EVT_DEV_RLS: pr_info(":AUDDEV_EVT_DEV_RLS\n"); if (evt_payload->routing_id == audio->fm_source) audio->fm_source = 0; if (evt_payload->routing_id == audio->fm_dest) audio->fm_dest = 0; if (audio->running && (!audio->fm_dest || !audio->fm_source)) { afe_loopback(FM_DISABLE, audio->fm_dest, audio->fm_source); audio->running = 0; } break; default: pr_err(":ERROR:wrong event\n"); break; } }
static ssize_t afe_debug_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { char *lb_str = filp->private_data; char cmd; if (get_user(cmd, ubuf)) return -EFAULT; MM_INFO("%s %c\n", lb_str, cmd); if (!strcmp(lb_str, "afe_loopback")) { switch (cmd) { case '1': afe_loopback(1); break; case '0': afe_loopback(0); break; } } return cnt; }
void afe_ext_loopback(int enable, int rx_copp_id, int tx_copp_id) { struct afe_cmd_ext_loopback cmd; struct msm_afe_state *afe; afe = &the_afe_state; MM_DBG("enable %d\n", enable); if ((rx_copp_id == 0) && (tx_copp_id == 0)) { afe_loopback(enable); } else { memset(&cmd, 0, sizeof(cmd)); cmd.cmd_id = AFE_CMD_EXT_LOOPBACK; cmd.source_id = tx_copp_id; cmd.dst_id = rx_copp_id; if (enable) cmd.enable_flag = AFE_LOOPBACK_ENABLE_COMMAND; afe_send_queue(afe, &cmd, sizeof(cmd)); } }
static int fm_audio_enable(struct audio *audio) { if (audio->enabled) return 0; pr_info("%s: fm dest= %08x fm_source = %08x\n", __func__, audio->fm_dst_copp_id, audio->fm_src_copp_id); if (audio->fm_dest && audio->fm_source) { if (afe_loopback(FM_ENABLE, audio->fm_dst_copp_id, audio->fm_src_copp_id) < 0) { pr_err("%s: afe_loopback failed\n", __func__); } audio->running = 1; } audio->enabled = 1; return 0; }
static int audio_enable(struct audio *audio) { if (audio->enabled) return 0; pr_info("fm dest= %08x fm_source = %08x\n", audio->fm_dst_copp_id, audio->fm_src_copp_id); /* do afe loopback here */ if (audio->fm_dest && audio->fm_source) { if (afe_loopback(FM_ENABLE, audio->fm_dst_copp_id, audio->fm_src_copp_id) < 0) { pr_err("afe_loopback failed\n"); } audio->running = 1; } audio->enabled = 1; return 0; }
static ssize_t afe_debug_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { char *lb_str = filp->private_data; char lbuf[32]; int rc; unsigned long param[5]; if (cnt > sizeof(lbuf) - 1) return -EINVAL; rc = copy_from_user(lbuf, ubuf, cnt); if (rc) return -EFAULT; lbuf[cnt] = '\0'; if (!strcmp(lb_str, "afe_loopback")) { rc = afe_get_parameters(lbuf, param, 3); if (!rc) { pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1], param[2]); if ((param[0] != AFE_LOOPBACK_ON) && (param[0] != AFE_LOOPBACK_OFF)) { pr_err("%s: Error, parameter 0 incorrect\n", __func__); rc = -EINVAL; goto afe_error; } if ((afe_validate_port(param[1]) < 0) || (afe_validate_port(param[2])) < 0) { pr_err("%s: Error, invalid afe port\n", __func__); } if (this_afe.apr == NULL) { pr_err("%s: Error, AFE not opened\n", __func__); rc = -EINVAL; } else { rc = afe_loopback(param[0], param[1], param[2]); } } else { pr_err("%s: Error, invalid parameters\n", __func__); rc = -EINVAL; } } else if (!strcmp(lb_str, "afe_loopback_gain")) { rc = afe_get_parameters(lbuf, param, 2); if (!rc) { pr_info("%s %lu %lu\n", lb_str, param[0], param[1]); if (afe_validate_port(param[0]) < 0) { pr_err("%s: Error, invalid afe port\n", __func__); rc = -EINVAL; goto afe_error; } if (param[1] < 0 || param[1] > 100) { pr_err("%s: Error, volume shoud be 0 to 100" " percentage param = %lu\n", __func__, param[1]); rc = -EINVAL; goto afe_error; } param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100; if (this_afe.apr == NULL) { pr_err("%s: Error, AFE not opened\n", __func__); rc = -EINVAL; } else { rc = afe_loopback_gain(param[0], param[1]); } } else { pr_err("%s: Error, invalid parameters\n", __func__); rc = -EINVAL; } } afe_error: if (rc == 0) rc = cnt; else pr_err("%s: rc = %d\n", __func__, rc); return rc; }
static int msm_device_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0; int set = 0; struct msm_audio_route_config route_cfg; struct msm_snddev_info *dev_info; struct msm_snddev_info *dst_dev_info; struct msm_snddev_info *src_dev_info; int tx_freq = 0; int rx_freq = 0; u32 set_freq = 0; set = ucontrol->value.integer.value[0]; route_cfg.dev_id = ucontrol->id.numid - device_index; dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id); if (IS_ERR(dev_info)) { pr_err("%s:pass invalid dev_id\n", __func__); rc = PTR_ERR(dev_info); return rc; } pr_info("%s:device %s(%d) set %d : opened_dev(%d,%d)\n", __func__, dev_info->name, route_cfg.dev_id, set, opened_dev1, opened_dev2); if (set) { pr_info("Device %s Opened = %d\n", dev_info->name, dev_info->opened); if (!dev_info->opened) { #if defined(CONFIG_USA_MODEL_SGH_T989 ) || defined(CONFIG_USA_MODEL_SGH_I727) \ || defined(CONFIG_USA_MODEL_SGH_I757)|| defined (CONFIG_USA_MODEL_SGH_T769)\ || defined(CONFIG_USA_MODEL_SGH_I577) if(!strcmp(dev_info->name, "dualmic_handset_ef_tx")) { pr_debug("%s : dualmic_enabled\n",__func__); dualmic_enabled = 1; } #endif set_freq = dev_info->sample_rate; if (!msm_device_is_voice(route_cfg.dev_id)) { msm_get_voc_freq(&tx_freq, &rx_freq); if (dev_info->capability & SNDDEV_CAP_TX) set_freq = tx_freq; if (set_freq == 0) set_freq = dev_info->sample_rate; } else set_freq = dev_info->sample_rate; pr_err("%s:device freq =%d\n", __func__, set_freq); rc = dev_info->dev_ops.set_freq(dev_info, set_freq); if (rc < 0) { pr_err("%s:device freq failed!\n", __func__); return rc; } dev_info->set_sample_rate = rc; rc = 0; pr_info("Device trying to open : %s\n", dev_info->name); rc = dev_info->dev_ops.open(dev_info); if (rc < 0) { /*[[Safeguard code for device open issue -START //balaji.k This fix would work incase of EBUSY error when device is being opened & previous instance of device is not closed */ if(rc == -EBUSY) { struct msm_snddev_info * last_dev_info = NULL; int closing_dev = -1; pr_err("DEV_BUSY: Ebusy Error %s : route_cfg.dev_id 1: %d\n", __func__, route_cfg.dev_id); //Closing the last active device after sending the broadcast if (dev_info->capability & SNDDEV_CAP_TX) { last_dev_info = audio_dev_ctrl_find_dev(last_active_tx_opened_dev); closing_dev = last_active_tx_opened_dev; } if (dev_info->capability & SNDDEV_CAP_RX) { last_dev_info = audio_dev_ctrl_find_dev(last_active_rx_opened_dev); closing_dev = last_active_rx_opened_dev; } // to fix exception error if (IS_ERR(last_dev_info)) { pr_err("last_dev:%s:pass invalid dev_id\n", __func__); rc = PTR_ERR(last_dev_info); return rc; } broadcast_event(AUDDEV_EVT_REL_PENDING, closing_dev, SESSION_IGNORE); pr_err("DEV_BUSY:closing Last active Open dev (%d)\n", closing_dev); rc = dev_info->dev_ops.close(last_dev_info); pr_err("DEV_BUSY: %s : route_cfg.dev_id 2: %d\n", __func__, route_cfg.dev_id); if (rc < 0) { pr_err("DEV_BUSY : %s:Snd device failed close!\n", __func__); return rc; } else { //Device close is successful, so broadcasting release event. //if(opened_dev1 == route_cfg.dev_id) // Commented these as here we are closing the previous device opened_dev1 = -1; //else if(opened_dev2 == route_cfg.dev_id) opened_dev2 = -1; last_dev_info->opened= 0; broadcast_event(AUDDEV_EVT_DEV_RLS, closing_dev, SESSION_IGNORE); } dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id); if (IS_ERR(dev_info)) { pr_err("DEV_BUSY: %s:pass invalid dev_id\n", __func__); rc = PTR_ERR(dev_info); return rc; } pr_err("DEV_BUSY: Opening the Device Now %s : route_cfg.dev_id : %d\n", __func__, route_cfg.dev_id); rc = dev_info->dev_ops.open(dev_info); //Opening the intended device if(rc < 0) { pr_err("DEV_BUSY: %s, Device %d:Enabling %s failed\n", __func__, rc, dev_info->name); return rc; } else { // Maintaining the last Opened device- reqd for closing if EBUSY is encountered. if (dev_info->capability & SNDDEV_CAP_TX) last_active_tx_opened_dev = route_cfg.dev_id; else if(dev_info->capability & SNDDEV_CAP_RX) last_active_rx_opened_dev = route_cfg.dev_id; printk("Last active Open Txdev (%d) and Rxdev(%d)\n", last_active_tx_opened_dev, last_active_rx_opened_dev); } } else { pr_err("%s:Enabling %s failed\n", __func__, dev_info->name); return rc; } } else { // Maintaining the last Opened device- reqd for closing if EBUSY is encountered. if (dev_info->capability & SNDDEV_CAP_TX) last_active_tx_opened_dev = route_cfg.dev_id; else if(dev_info->capability & SNDDEV_CAP_RX) last_active_rx_opened_dev = route_cfg.dev_id; printk("Last active Open Txdev (%d) and Rxdev(%d)\n", last_active_tx_opened_dev, last_active_rx_opened_dev); } //Safeguard code for device open issue -END]] //balaji.k if(opened_dev1 == -1) opened_dev1 = route_cfg.dev_id; else opened_dev2 = route_cfg.dev_id; pr_info("%s:open done : opened_dev(%d,%d)\n", __func__, opened_dev1, opened_dev2); dev_info->opened = 1; broadcast_event(AUDDEV_EVT_DEV_RDY, route_cfg.dev_id, SESSION_IGNORE); if ((route_cfg.dev_id == src_dev) || (route_cfg.dev_id == dst_dev)) { dst_dev_info = audio_dev_ctrl_find_dev( dst_dev); if (IS_ERR(dst_dev_info)) { pr_err("dst_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(dst_dev_info); return rc; } src_dev_info = audio_dev_ctrl_find_dev( src_dev); if (IS_ERR(src_dev_info)) { pr_err("src_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(src_dev_info); return rc; } if ((dst_dev_info->opened) && (src_dev_info->opened)) { pr_debug("%d: Enable afe_loopback\n", __LINE__); afe_loopback(LOOPBACK_ENABLE, dst_dev_info->copp_id, src_dev_info->copp_id); loopback_status = 1; } } } } else { if (dev_info->opened) { #if defined(CONFIG_USA_MODEL_SGH_T989 ) || defined(CONFIG_USA_MODEL_SGH_I727) \ || defined(CONFIG_USA_MODEL_SGH_I757)|| defined (CONFIG_USA_MODEL_SGH_T769) || defined (CONFIG_USA_MODEL_SGH_I577) if((!strcmp(dev_info->name,"dualmic_handset_ef_tx"))&&(!strcmp(dev_info->name,"handset_call_rx"))) { pr_debug("%s : dualmic_disabled\n",__func__); dualmic_enabled = 0; } #endif broadcast_event(AUDDEV_EVT_REL_PENDING, route_cfg.dev_id, SESSION_IGNORE); printk("%s : Device trying to close : %s\n",__func__, dev_info->name); rc = dev_info->dev_ops.close(dev_info); if (rc < 0) { pr_err("%s:Snd device failed close!\n", __func__); return rc; } else { if(opened_dev1 == route_cfg.dev_id) opened_dev1 = -1; else if(opened_dev2 == route_cfg.dev_id) opened_dev2 = -1; pr_info("%s:close done : opened_dev(%d,%d)\n", __func__, opened_dev1, opened_dev2); dev_info->opened = 0; broadcast_event(AUDDEV_EVT_DEV_RLS, route_cfg.dev_id, SESSION_IGNORE); } if (loopback_status == 1) { if ((route_cfg.dev_id == src_dev) || (route_cfg.dev_id == dst_dev)) { dst_dev_info = audio_dev_ctrl_find_dev( dst_dev); if (IS_ERR(dst_dev_info)) { pr_err("dst_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(dst_dev_info); return rc; } src_dev_info = audio_dev_ctrl_find_dev( src_dev); if (IS_ERR(src_dev_info)) { pr_err("src_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(src_dev_info); return rc; } pr_debug("%d: Disable afe_loopback\n", __LINE__); afe_loopback(LOOPBACK_DISABLE, dst_dev_info->copp_id, src_dev_info->copp_id); loopback_status = 0; } } } } return rc; }
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"); } }
static int msm_device_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0; int set = 0; struct msm_audio_route_config route_cfg; struct msm_snddev_info *dev_info; struct msm_snddev_info *dst_dev_info; struct msm_snddev_info *src_dev_info; int tx_freq = 0; int rx_freq = 0; u32 set_freq = 0; set = ucontrol->value.integer.value[0]; route_cfg.dev_id = ucontrol->id.numid - device_index; dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id); if (IS_ERR(dev_info)) { MM_AUD_ERR("pass invalid dev_id\n"); rc = PTR_ERR(dev_info); return rc; } MM_INFO("device %s set %d\n", dev_info->name, set); pr_aud_info("[ALSA] msm_en_device (dev %s, id %d, enable %d, opened %d)\n", dev_info->name, route_cfg.dev_id, set, dev_info->opened); if (set) { if (!dev_info->opened) { set_freq = dev_info->sample_rate; if (!msm_device_is_voice(route_cfg.dev_id) && msm_get_call_state()) { msm_get_voc_freq(&tx_freq, &rx_freq); if (dev_info->capability & SNDDEV_CAP_TX) set_freq = tx_freq; if (dev_info->capability & SNDDEV_CAP_RX) set_freq = rx_freq; if (set_freq == 0) set_freq = dev_info->sample_rate; } else set_freq = dev_info->sample_rate; MM_AUD_INFO("device freq =%d\n", set_freq); rc = dev_info->dev_ops.set_freq(dev_info, set_freq); if (rc < 0) { MM_AUD_ERR("device freq failed!\n"); return rc; } dev_info->set_sample_rate = rc; rc = 0; rc = dev_info->dev_ops.open(dev_info); if (rc < 0) { MM_AUD_ERR("Enabling %s failed", dev_info->name); return rc; } dev_info->opened = 1; broadcast_event(AUDDEV_EVT_DEV_RDY, route_cfg.dev_id, SESSION_IGNORE); if ((route_cfg.dev_id == src_dev) || (route_cfg.dev_id == dst_dev)) { dst_dev_info = audio_dev_ctrl_find_dev( dst_dev); if (IS_ERR(dst_dev_info)) { pr_err("dst_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(dst_dev_info); return rc; } src_dev_info = audio_dev_ctrl_find_dev( src_dev); if (IS_ERR(src_dev_info)) { pr_err("src_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(src_dev_info); return rc; } if ((dst_dev_info->opened) && (src_dev_info->opened)) { pr_debug("%d: Enable afe_loopback\n", __LINE__); afe_loopback(LOOPBACK_ENABLE, dst_dev_info->copp_id, src_dev_info->copp_id); loopback_status = 1; } } } } else { if (dev_info->opened) { broadcast_event(AUDDEV_EVT_REL_PENDING, route_cfg.dev_id, SESSION_IGNORE); rc = dev_info->dev_ops.close(dev_info); if (rc < 0) { MM_AUD_ERR("Snd device failed close!\n"); return rc; } else { dev_info->opened = 0; broadcast_event(AUDDEV_EVT_DEV_RLS, route_cfg.dev_id, SESSION_IGNORE); } if (loopback_status == 1) { if ((route_cfg.dev_id == src_dev) || (route_cfg.dev_id == dst_dev)) { dst_dev_info = audio_dev_ctrl_find_dev( dst_dev); if (IS_ERR(dst_dev_info)) { pr_err("dst_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(dst_dev_info); return rc; } src_dev_info = audio_dev_ctrl_find_dev( src_dev); if (IS_ERR(src_dev_info)) { pr_err("src_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(src_dev_info); return rc; } pr_debug("%d: Disable afe_loopback\n", __LINE__); afe_loopback(LOOPBACK_DISABLE, dst_dev_info->copp_id, src_dev_info->copp_id); loopback_status = 0; } } } } return rc; }
static int msm_device_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0; int set = 0; struct msm_audio_route_config route_cfg; struct msm_snddev_info *dev_info; struct msm_snddev_info *dst_dev_info; struct msm_snddev_info *src_dev_info; int tx_freq = 0; int rx_freq = 0; u32 set_freq = 0; set = ucontrol->value.integer.value[0]; route_cfg.dev_id = ucontrol->id.numid - device_index; dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id); if (IS_ERR(dev_info)) { pr_err("%s:pass invalid dev_id\n", __func__); rc = PTR_ERR(dev_info); return rc; } pr_info("%s:device %s set %d\n", __func__, dev_info->name, set); if (set) { if (!dev_info->opened) { set_freq = dev_info->sample_rate; if (!msm_device_is_voice(route_cfg.dev_id)) { msm_get_voc_freq(&tx_freq, &rx_freq); if (dev_info->capability & SNDDEV_CAP_TX) set_freq = tx_freq; if (set_freq == 0) set_freq = dev_info->sample_rate; } else set_freq = dev_info->sample_rate; pr_err("%s:device freq =%d\n", __func__, set_freq); rc = dev_info->dev_ops.set_freq(dev_info, set_freq); if (rc < 0) { pr_err("%s:device freq failed!\n", __func__); return rc; } dev_info->set_sample_rate = rc; rc = 0; rc = dev_info->dev_ops.open(dev_info); if (rc < 0) { pr_err("%s:Enabling %s failed\n", __func__, dev_info->name); return rc; } dev_info->opened = 1; broadcast_event(AUDDEV_EVT_DEV_RDY, route_cfg.dev_id, SESSION_IGNORE); if ((route_cfg.dev_id == src_dev) || (route_cfg.dev_id == dst_dev)) { dst_dev_info = audio_dev_ctrl_find_dev( dst_dev); if (IS_ERR(dst_dev_info)) { pr_err("dst_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(dst_dev_info); return rc; } src_dev_info = audio_dev_ctrl_find_dev( src_dev); if (IS_ERR(src_dev_info)) { pr_err("src_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(src_dev_info); return rc; } if ((dst_dev_info->opened) && (src_dev_info->opened)) { pr_debug("%d: Enable afe_loopback\n", __LINE__); afe_loopback(LOOPBACK_ENABLE, dst_dev_info->copp_id, src_dev_info->copp_id); loopback_status = 1; } } #if defined(CONFIG_MFD_WM8994) if (configure_wm_hw(dev_info)) pr_err("%s: Could not configure wolfson hw properly!", __func__); #endif } } else { if (dev_info->opened) { broadcast_event(AUDDEV_EVT_REL_PENDING, route_cfg.dev_id, SESSION_IGNORE); rc = dev_info->dev_ops.close(dev_info); if (rc < 0) { pr_err("%s:Snd device failed close!\n", __func__); return rc; } else { dev_info->opened = 0; broadcast_event(AUDDEV_EVT_DEV_RLS, route_cfg.dev_id, SESSION_IGNORE); } if (loopback_status == 1) { if ((route_cfg.dev_id == src_dev) || (route_cfg.dev_id == dst_dev)) { dst_dev_info = audio_dev_ctrl_find_dev( dst_dev); if (IS_ERR(dst_dev_info)) { pr_err("dst_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(dst_dev_info); return rc; } src_dev_info = audio_dev_ctrl_find_dev( src_dev); if (IS_ERR(src_dev_info)) { pr_err("src_dev:%s:pass invalid" "dev_id\n", __func__); rc = PTR_ERR(src_dev_info); return rc; } pr_debug("%d: Disable afe_loopback\n", __LINE__); afe_loopback(LOOPBACK_DISABLE, dst_dev_info->copp_id, src_dev_info->copp_id); loopback_status = 0; } } } } return rc; }