static int __init snddev_icodec_init(void) { s32 rc; struct snddev_icodec_drv_state *icodec_drv = &snddev_icodec_drv; rc = platform_driver_register(&snddev_icodec_driver); if (IS_ERR_VALUE(rc)) goto error_platform_driver; icodec_drv->rx_mclk = clk_get(NULL, "mi2s_codec_rx_m_clk"); if (IS_ERR(icodec_drv->rx_mclk)) goto error_rx_mclk; icodec_drv->rx_sclk = clk_get(NULL, "mi2s_codec_rx_s_clk"); if (IS_ERR(icodec_drv->rx_sclk)) goto error_rx_sclk; icodec_drv->tx_mclk = clk_get(NULL, "mi2s_codec_tx_m_clk"); if (IS_ERR(icodec_drv->tx_mclk)) goto error_tx_mclk; icodec_drv->tx_sclk = clk_get(NULL, "mi2s_codec_tx_s_clk"); if (IS_ERR(icodec_drv->tx_sclk)) goto error_tx_sclk; icodec_drv->lpa_codec_clk = clk_get(NULL, "lpa_codec_clk"); if (IS_ERR(icodec_drv->lpa_codec_clk)) goto error_lpa_codec_clk; icodec_drv->lpa_core_clk = clk_get(NULL, "lpa_core_clk"); if (IS_ERR(icodec_drv->lpa_core_clk)) goto error_lpa_core_clk; icodec_drv->lpa_p_clk = clk_get(NULL, "lpa_pclk"); if (IS_ERR(icodec_drv->lpa_p_clk)) goto error_lpa_p_clk; #ifdef CONFIG_DEBUG_FS debugfs_sdev_dent = debugfs_create_dir("snddev_icodec", 0); if (debugfs_sdev_dent) { debugfs_afelb = debugfs_create_file("afe_loopback", S_IFREG | S_IWUGO, debugfs_sdev_dent, (void *) "afe_loopback", &snddev_icodec_debug_fops); debugfs_adielb = debugfs_create_file("adie_loopback", S_IFREG | S_IWUGO, debugfs_sdev_dent, (void *) "adie_loopback", &snddev_icodec_debug_fops); } #endif mutex_init(&icodec_drv->rx_lock); mutex_init(&icodec_drv->tx_lock); icodec_drv->rx_active = 0; icodec_drv->tx_active = 0; icodec_drv->lpa = NULL; wake_lock_init(&icodec_drv->tx_idlelock, WAKE_LOCK_IDLE, "snddev_tx_idle"); wake_lock_init(&icodec_drv->rx_idlelock, WAKE_LOCK_IDLE, "snddev_rx_idle"); return 0; error_lpa_p_clk: clk_put(icodec_drv->lpa_core_clk); error_lpa_core_clk: clk_put(icodec_drv->lpa_codec_clk); error_lpa_codec_clk: clk_put(icodec_drv->tx_sclk); error_tx_sclk: clk_put(icodec_drv->tx_mclk); error_tx_mclk: clk_put(icodec_drv->rx_sclk); error_rx_sclk: clk_put(icodec_drv->rx_mclk); error_rx_mclk: platform_driver_unregister(&snddev_icodec_driver); error_platform_driver: MM_ERR("encounter error\n"); return -ENODEV; }
int __msm_adsp_write(struct msm_adsp_module *module, unsigned dsp_queue_addr, void *cmd_buf, size_t cmd_size) { uint32_t ctrl_word; uint32_t dsp_q_addr; uint32_t dsp_addr; uint32_t cmd_id = 0; int cnt = 0; int ret_status = 0; unsigned long flags; struct adsp_info *info; if (!module || !cmd_buf) { MM_ERR("Called with NULL parameters\n"); return -EINVAL; } info = module->info; spin_lock_irqsave(&adsp_write_lock, flags); if (module->state != ADSP_STATE_ENABLED) { spin_unlock_irqrestore(&adsp_write_lock, flags); MM_ERR("module %s not enabled before write\n", module->name); return -ENODEV; } if (adsp_validate_module(module->id)) { spin_unlock_irqrestore(&adsp_write_lock, flags); MM_ERR("module id validation failed %s %d\n", module->name, module->id); return -ENXIO; } if (dsp_queue_addr >= QDSP_MAX_NUM_QUEUES) { spin_unlock_irqrestore(&adsp_write_lock, flags); MM_ERR("Invalid Queue Index: %d\n", dsp_queue_addr); return -ENXIO; } if (adsp_validate_queue(module->id, dsp_queue_addr, cmd_size)) { spin_unlock_irqrestore(&adsp_write_lock, flags); return -EINVAL; } dsp_q_addr = adsp_get_queue_offset(info, dsp_queue_addr); dsp_q_addr &= ADSP_RTOS_WRITE_CTRL_WORD_DSP_ADDR_M; /* Poll until the ADSP is ready to accept a command. * Wait for 100us, return error if it's not responding. * If this returns an error, we need to disable ALL modules and * then retry. */ while (((ctrl_word = readl(info->write_ctrl)) & ADSP_RTOS_WRITE_CTRL_WORD_READY_M) != ADSP_RTOS_WRITE_CTRL_WORD_READY_V) { if (cnt > 50) { MM_ERR("timeout waiting for DSP write ready\n"); ret_status = -EIO; goto fail; } MM_DBG("waiting for DSP write ready\n"); udelay(2); cnt++; } /* Set the mutex bits */ ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_M); ctrl_word |= ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_NAVAIL_V; /* Clear the command bits */ ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_CMD_M); /* Set the queue address bits */ ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_DSP_ADDR_M); ctrl_word |= dsp_q_addr; writel(ctrl_word, info->write_ctrl); /* Generate an interrupt to the DSP. This notifies the DSP that * we are about to send a command on this particular queue. The * DSP will in response change its state. */ writel(1, info->send_irq); /* Poll until the adsp responds to the interrupt; this does not * generate an interrupt from the adsp. This should happen within * 5ms. */ cnt = 0; while ((readl(info->write_ctrl) & ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_M) == ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_NAVAIL_V) { if (cnt > 2500) { MM_ERR("timeout waiting for adsp ack\n"); ret_status = -EIO; goto fail; } udelay(2); cnt++; } /* Read the ctrl word */ ctrl_word = readl(info->write_ctrl); if ((ctrl_word & ADSP_RTOS_WRITE_CTRL_WORD_STATUS_M) != ADSP_RTOS_WRITE_CTRL_WORD_NO_ERR_V) { ret_status = -EAGAIN; goto fail; } else { /* No error */ /* Get the DSP buffer address */ dsp_addr = (ctrl_word & ADSP_RTOS_WRITE_CTRL_WORD_DSP_ADDR_M) + (uint32_t)MSM_AD5_BASE; if (dsp_addr < (uint32_t)(MSM_AD5_BASE + QDSP_RAMC_OFFSET)) { uint16_t *buf_ptr = (uint16_t *) cmd_buf; uint16_t *dsp_addr16 = (uint16_t *)dsp_addr; cmd_size /= sizeof(uint16_t); /* Save the command ID */ cmd_id = (uint32_t) buf_ptr[0]; /* Copy the command to DSP memory */ cmd_size++; while (--cmd_size) *dsp_addr16++ = *buf_ptr++; } else { uint32_t *buf_ptr = (uint32_t *) cmd_buf; uint32_t *dsp_addr32 = (uint32_t *)dsp_addr; cmd_size /= sizeof(uint32_t); /* Save the command ID */ cmd_id = buf_ptr[0]; cmd_size++; while (--cmd_size) *dsp_addr32++ = *buf_ptr++; } /* Set the mutex bits */ ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_M); ctrl_word |= ADSP_RTOS_WRITE_CTRL_WORD_MUTEX_NAVAIL_V; /* Set the command bits to write done */ ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_CMD_M); ctrl_word |= ADSP_RTOS_WRITE_CTRL_WORD_CMD_WRITE_DONE_V; /* Set the queue address bits */ ctrl_word &= ~(ADSP_RTOS_WRITE_CTRL_WORD_DSP_ADDR_M); ctrl_word |= dsp_q_addr; writel(ctrl_word, info->write_ctrl); /* Generate an interrupt to the DSP. It does not respond with * an interrupt, and we do not need to wait for it to * acknowledge, because it will hold the mutex lock until it's * ready to receive more commands again. */ writel(1, info->send_irq); module->num_commands++; } /* Ctrl word status bits were 00, no error in the ctrl word */ fail: spin_unlock_irqrestore(&adsp_write_lock, flags); return ret_status; }
static int msm_voice_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0; uint32_t rx_dev_id; uint32_t tx_dev_id; struct msm_snddev_info *rx_dev_info; struct msm_snddev_info *tx_dev_info; int set = ucontrol->value.integer.value[2]; u32 session_mask; if (!set) return -EPERM; /* Rx Device Routing */ rx_dev_id = ucontrol->value.integer.value[0]; rx_dev_info = audio_dev_ctrl_find_dev(rx_dev_id); if (IS_ERR(rx_dev_info)) { MM_ERR("pass invalid dev_id\n"); rc = PTR_ERR(rx_dev_info); return rc; } if (!(rx_dev_info->capability & SNDDEV_CAP_RX)) { MM_ERR("First Dev is supposed to be RX\n"); return -EFAULT; } MM_DBG("route cfg %d STREAM_VOICE_RX type\n", rx_dev_id); msm_set_voc_route(rx_dev_info, AUDIO_ROUTE_STREAM_VOICE_RX, rx_dev_id); session_mask = 0x1 << (8 * ((int)AUDDEV_CLNT_VOC-1)); broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, rx_dev_id, session_mask); /* Tx Device Routing */ tx_dev_id = ucontrol->value.integer.value[1]; tx_dev_info = audio_dev_ctrl_find_dev(tx_dev_id); if (IS_ERR(tx_dev_info)) { MM_ERR("pass invalid dev_id\n"); rc = PTR_ERR(tx_dev_info); return rc; } if (!(tx_dev_info->capability & SNDDEV_CAP_TX)) { MM_ERR("Second Dev is supposed to be Tx\n"); return -EFAULT; } MM_DBG("route cfg %d %d type\n", tx_dev_id, AUDIO_ROUTE_STREAM_VOICE_TX); msm_set_voc_route(tx_dev_info, AUDIO_ROUTE_STREAM_VOICE_TX, tx_dev_id); broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, tx_dev_id, session_mask); if (rx_dev_info->opened) broadcast_event(AUDDEV_EVT_DEV_RDY, rx_dev_id, session_mask); if (tx_dev_info->opened) broadcast_event(AUDDEV_EVT_DEV_RDY, tx_dev_id, session_mask); return rc; }
static void pcm_in_listener(u32 evt_id, union auddev_evt_data *evt_payload, void *private_data) { struct audio_in *audio = (struct audio_in *) private_data; unsigned long flags; MM_DBG("evt_id = 0x%8x\n", evt_id); switch (evt_id) { case AUDDEV_EVT_DEV_RDY: { MM_DBG("AUDDEV_EVT_DEV_RDY\n"); spin_lock_irqsave(&audio->dev_lock, flags); audio->dev_cnt++; audio->source |= (0x1 << evt_payload->routing_id); spin_unlock_irqrestore(&audio->dev_lock, flags); if ((audio->running == 1) && (audio->enabled == 1)) audpcm_in_record_config(audio, 1); break; } case AUDDEV_EVT_DEV_RLS: { MM_DBG("AUDDEV_EVT_DEV_RLS\n"); spin_lock_irqsave(&audio->dev_lock, flags); audio->dev_cnt--; audio->source &= ~(0x1 << evt_payload->routing_id); spin_unlock_irqrestore(&audio->dev_lock, flags); if (!audio->running || !audio->enabled) break; /* Turn of as per source */ if (audio->source) audpcm_in_record_config(audio, 1); else /* Turn off all */ audpcm_in_record_config(audio, 0); break; } case AUDDEV_EVT_FREQ_CHG: { MM_DBG("Encoder Driver got sample rate change event\n"); MM_DBG("sample rate %d\n", evt_payload->freq_info.sample_rate); MM_DBG("dev_type %d\n", evt_payload->freq_info.dev_type); MM_DBG("acdb_dev_id %d\n", evt_payload->freq_info.acdb_dev_id); if (audio->running == 1) { /* Stop Recording sample rate does not match with device sample rate */ if (evt_payload->freq_info.sample_rate != audio->samp_rate) { audpcm_in_record_config(audio, 0); audio->abort = 1; wake_up(&audio->wait); } } break; } default: MM_ERR("wrong event %d\n", evt_id); break; } }
static int audpcm_in_open(struct inode *inode, struct file *file) { struct audio_in *audio = &the_audio_in; int rc; int encid; mutex_lock(&audio->lock); if (audio->opened) { rc = -EBUSY; goto done; } /* Settings will be re-config at AUDIO_SET_CONFIG, * but at least we need to have initial config */ audio->channel_mode = AUDREC_CMD_MODE_MONO; audio->buffer_size = MONO_DATA_SIZE; audio->samp_rate = 8000; audio->enc_type = ENC_TYPE_WAV; audio->source = INTERNAL_CODEC_TX_SOURCE_MIX_MASK; encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name, &audio->queue_ids); if (encid < 0) { MM_ERR("No free encoder available\n"); rc = -ENODEV; goto done; } audio->enc_id = encid; rc = msm_adsp_get(audio->module_name, &audio->audrec, &audrec_adsp_ops, audio); if (rc) { audpreproc_aenc_free(audio->enc_id); goto done; } audio->stopped = 0; audio->source = 0; audio->abort = 0; audpcm_in_flush(audio); audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS | AUDDEV_EVT_FREQ_CHG; rc = auddev_register_evt_listner(audio->device_events, AUDDEV_CLNT_ENC, audio->enc_id, pcm_in_listener, (void *) audio); if (rc) { MM_ERR("failed to register device event listener\n"); goto evt_error; } file->private_data = audio; audio->opened = 1; rc = 0; done: mutex_unlock(&audio->lock); return rc; evt_error: msm_adsp_put(audio->audrec); audpreproc_aenc_free(audio->enc_id); mutex_unlock(&audio->lock); return rc; }
/* ------------------- device --------------------- */ static long audamrnb_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct audio_in *audio = file->private_data; int rc = 0; if (cmd == AUDIO_GET_STATS) { struct msm_audio_stats stats; stats.byte_count = atomic_read(&audio->in_bytes); stats.sample_count = atomic_read(&audio->in_samples); if (copy_to_user((void *) arg, &stats, sizeof(stats))) return -EFAULT; return rc; } mutex_lock(&audio->lock); switch (cmd) { case AUDIO_START: { uint32_t freq; freq = 48000; MM_DBG("AUDIO_START\n"); if (audio->in_call && (audio->voice_state != VOICE_STATE_INCALL)) { rc = -EPERM; break; } rc = msm_snddev_request_freq(&freq, audio->enc_id, SNDDEV_CAP_TX, AUDDEV_CLNT_ENC); MM_DBG("sample rate configured %d\n", freq); if (rc < 0) { MM_DBG(" Sample rate can not be set, return code %d\n", rc); msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX, AUDDEV_CLNT_ENC); MM_DBG("msm_snddev_withdraw_freq\n"); break; } /*update aurec session info in audpreproc layer*/ audio->session_info.session_id = audio->enc_id; /*amrnb works only on 8KHz*/ audio->session_info.sampling_freq = 8000; audpreproc_update_audrec_info(&audio->session_info); rc = audamrnb_in_enable(audio); if (!rc) { rc = wait_event_interruptible_timeout(audio->wait_enable, audio->running != 0, 1*HZ); MM_DBG("state %d rc = %d\n", audio->running, rc); if (audio->running == 0) rc = -ENODEV; else rc = 0; } audio->stopped = 0; break; } case AUDIO_STOP: { /*reset the sampling frequency information at audpreproc layer*/ audio->session_info.sampling_freq = 0; audpreproc_update_audrec_info(&audio->session_info); rc = audamrnb_in_disable(audio); rc = msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX, AUDDEV_CLNT_ENC); MM_DBG("msm_snddev_withdraw_freq\n"); audio->stopped = 1; break; } case AUDIO_FLUSH: { if (audio->stopped) { /* Make sure we're stopped and we wake any threads * that might be blocked holding the read_lock. * While audio->stopped read threads will always * exit immediately. */ wake_up(&audio->wait); mutex_lock(&audio->read_lock); audamrnb_in_flush(audio); mutex_unlock(&audio->read_lock); } break; } case AUDIO_SET_STREAM_CONFIG: { struct msm_audio_stream_config cfg; if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) { rc = -EFAULT; break; } /* Allow only single frame */ if (cfg.buffer_size != (FRAME_SIZE - 8)) rc = -EINVAL; else audio->buffer_size = cfg.buffer_size; break; } case AUDIO_GET_STREAM_CONFIG: { struct msm_audio_stream_config cfg; memset(&cfg, 0, sizeof(cfg)); cfg.buffer_size = audio->buffer_size; cfg.buffer_count = FRAME_NUM; if (copy_to_user((void *) arg, &cfg, sizeof(cfg))) rc = -EFAULT; break; } case AUDIO_GET_AMRNB_ENC_CONFIG_V2: { struct msm_audio_amrnb_enc_config_v2 cfg; memset(&cfg, 0, sizeof(cfg)); cfg.dtx_enable = ((audio->dtx_mode == -1) ? 1 : 0); cfg.band_mode = audio->used_mode; cfg.frame_format = audio->frame_format; if (copy_to_user((void *) arg, &cfg, sizeof(cfg))) rc = -EFAULT; break; } case AUDIO_SET_AMRNB_ENC_CONFIG_V2: { struct msm_audio_amrnb_enc_config_v2 cfg; if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) { rc = -EFAULT; break; } /* DSP does not support any other than default format */ if (audio->frame_format != cfg.frame_format) { rc = -EINVAL; break; } if (cfg.dtx_enable == 0) audio->dtx_mode = 0; else if (cfg.dtx_enable == 1) audio->dtx_mode = -1; else { rc = -EINVAL; break; } audio->used_mode = cfg.band_mode; break; } case AUDIO_SET_INCALL: { struct msm_voicerec_mode cfg; unsigned long flags; if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) { rc = -EFAULT; break; } if (cfg.rec_mode != VOC_REC_BOTH && cfg.rec_mode != VOC_REC_UPLINK && cfg.rec_mode != VOC_REC_DOWNLINK) { MM_ERR("invalid rec_mode\n"); rc = -EINVAL; break; } else { spin_lock_irqsave(&audio->dev_lock, flags); if (cfg.rec_mode == VOC_REC_UPLINK) audio->source = VOICE_UL_SOURCE_MIX_MASK; else if (cfg.rec_mode == VOC_REC_DOWNLINK) audio->source = VOICE_DL_SOURCE_MIX_MASK; else audio->source = VOICE_DL_SOURCE_MIX_MASK | VOICE_UL_SOURCE_MIX_MASK ; audio->in_call = 1; spin_unlock_irqrestore(&audio->dev_lock, flags); } break; } case AUDIO_GET_SESSION_ID: { if (copy_to_user((void *) arg, &audio->enc_id, sizeof(unsigned short))) { rc = -EFAULT; } break; } default: rc = -EINVAL; } mutex_unlock(&audio->lock); return rc; }
static int audamrnb_in_open(struct inode *inode, struct file *file) { struct audio_in *audio = &the_audio_amrnb_in; int rc; int encid; int len = 0; unsigned long ionflag = 0; ion_phys_addr_t addr = 0; struct ion_handle *handle = NULL; struct ion_client *client = NULL; mutex_lock(&audio->lock); if (audio->opened) { rc = -EBUSY; goto done; } client = msm_ion_client_create(UINT_MAX, "Audio_AMR_In_Client"); if (IS_ERR_OR_NULL(client)) { MM_ERR("Unable to create ION client\n"); rc = -ENOMEM; goto client_create_error; } audio->client = client; handle = ion_alloc(client, DMASZ, SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID)); if (IS_ERR_OR_NULL(handle)) { MM_ERR("Unable to create allocate O/P buffers\n"); rc = -ENOMEM; goto buff_alloc_error; } audio->buff_handle = handle; rc = ion_phys(client, handle, &addr, &len); if (rc) { MM_ERR("O/P buffers:Invalid phy: %x sz: %x\n", (unsigned int) addr, (unsigned int) len); goto buff_get_phys_error; } else { MM_INFO("O/P buffers:valid phy: %x sz: %x\n", (unsigned int) addr, (unsigned int) len); } audio->phys = (int32_t)addr; rc = ion_handle_get_flags(client, handle, &ionflag); if (rc) { MM_ERR("could not get flags for the handle\n"); goto buff_get_flags_error; } audio->map_v_read = ion_map_kernel(client, handle, ionflag); if (IS_ERR(audio->map_v_read)) { MM_ERR("could not map write buffers\n"); rc = -ENOMEM; goto buff_map_error; } audio->data = (char *)audio->map_v_read; MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n", audio->phys, (int)audio->data); MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\ (int) audio->data, (int) audio->phys); if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { rc = -EACCES; MM_ERR("Non tunnel encoding is not supported\n"); goto done; } else if (!(file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) { audio->mode = MSM_AUD_ENC_MODE_TUNNEL; MM_DBG("Opened for tunnel mode encoding\n"); } else { rc = -EACCES; goto done; } /* Settings will be re-config at AUDIO_SET_CONFIG, * but at least we need to have initial config */ audio->buffer_size = (FRAME_SIZE - 8); audio->enc_type = ENC_TYPE_AMRNB | audio->mode; audio->dtx_mode = -1; audio->frame_format = 0; audio->used_mode = 7; /* Bit Rate 12.2 kbps MR122 */ encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name, &audio->queue_ids); if (encid < 0) { MM_ERR("No free encoder available\n"); rc = -ENODEV; goto done; } audio->enc_id = encid; rc = msm_adsp_get(audio->module_name, &audio->audrec, &audrec_amrnb_adsp_ops, audio); if (rc) { audpreproc_aenc_free(audio->enc_id); goto done; } audio->stopped = 0; audio->source = 0; audamrnb_in_flush(audio); audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS | AUDDEV_EVT_VOICE_STATE_CHG; audio->voice_state = msm_get_voice_state(); rc = auddev_register_evt_listner(audio->device_events, AUDDEV_CLNT_ENC, audio->enc_id, amrnb_in_listener, (void *) audio); if (rc) { MM_ERR("failed to register device event listener\n"); goto evt_error; } audio->build_id = socinfo_get_build_id(); MM_DBG("Modem build id = %s\n", audio->build_id); file->private_data = audio; audio->opened = 1; done: mutex_unlock(&audio->lock); return rc; evt_error: msm_adsp_put(audio->audrec); audpreproc_aenc_free(audio->enc_id); mutex_unlock(&audio->lock); ion_unmap_kernel(client, audio->buff_handle); buff_map_error: buff_get_phys_error: buff_get_flags_error: ion_free(client, audio->buff_handle); buff_alloc_error: ion_client_destroy(client); client_create_error: return rc; }
/* ------------------- dsp preproc event handler--------------------- */ static void audpreproc_dsp_event(void *data, unsigned id, void *msg) { struct audio_in *audio = data; switch (id) { case AUDPREPROC_ERROR_MSG: { struct audpreproc_err_msg *err_msg = msg; MM_ERR("ERROR_MSG: stream id %d err idx %d\n", err_msg->stream_id, err_msg->aud_preproc_err_idx); /* Error case */ wake_up(&audio->wait_enable); break; } case AUDPREPROC_CMD_CFG_DONE_MSG: { MM_DBG("CMD_CFG_DONE_MSG \n"); break; } case AUDPREPROC_CMD_ENC_CFG_DONE_MSG: { struct audpreproc_cmd_enc_cfg_done_msg *enc_cfg_msg = msg; MM_DBG("CMD_ENC_CFG_DONE_MSG: stream id %d enc type \ 0x%8x\n", enc_cfg_msg->stream_id, enc_cfg_msg->rec_enc_type); /* Encoder enable success */ if (enc_cfg_msg->rec_enc_type & ENCODE_ENABLE) { if(audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) { MM_DBG("routing command\n"); audpreproc_cmd_cfg_routing_mode(audio); } else { audevrc_in_param_config(audio); } } else { /* Encoder disable success */ audio->running = 0; if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) audevrc_in_record_config(audio, 0); else wake_up(&audio->wait_enable); } break; } case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: { MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG\n"); if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) audevrc_in_mem_config(audio); else audpcm_config(audio); break; } case AUDPREPROC_CMD_ROUTING_MODE_DONE_MSG: { struct audpreproc_cmd_routing_mode_done\ *routing_cfg_done_msg = msg; if (routing_cfg_done_msg->configuration == 0) { MM_INFO("routing configuration failed\n"); audio->running = 0; } else audevrc_in_param_config(audio); break; } case AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG: { MM_DBG("AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG \n"); wake_up(&audio->wait_enable); break; } default: MM_ERR("Unknown Event id %d\n", id); } }
/* ------------------- dsp audrec event handler--------------------- */ static void audrec_dsp_event(void *data, unsigned id, size_t len, void (*getevent)(void *ptr, size_t len)) { struct audio_in *audio = data; switch (id) { case AUDREC_CMD_MEM_CFG_DONE_MSG: { MM_DBG("CMD_MEM_CFG_DONE MSG DONE\n"); audio->running = 1; if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) { if ((!audio->in_call && (audio->dev_cnt > 0)) || (audio->in_call && (audio->voice_state \ == VOICE_STATE_INCALL))) audevrc_in_record_config(audio, 1); } else { audpreproc_pcm_send_data(audio, 1); wake_up(&audio->wait_enable); } break; } case AUDREC_FATAL_ERR_MSG: { struct audrec_fatal_err_msg fatal_err_msg; getevent(&fatal_err_msg, AUDREC_FATAL_ERR_MSG_LEN); MM_ERR("FATAL_ERR_MSG: err id %d\n", fatal_err_msg.audrec_err_id); /* Error stop the encoder */ audio->stopped = 1; wake_up(&audio->wait); if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) wake_up(&audio->write_wait); break; } case AUDREC_UP_PACKET_READY_MSG: { struct audrec_up_pkt_ready_msg pkt_ready_msg; getevent(&pkt_ready_msg, AUDREC_UP_PACKET_READY_MSG_LEN); MM_DBG("UP_PACKET_READY_MSG: write cnt lsw %d \ write cnt msw %d read cnt lsw %d read cnt msw %d \n",\ pkt_ready_msg.audrec_packet_write_cnt_lsw, \ pkt_ready_msg.audrec_packet_write_cnt_msw, \ pkt_ready_msg.audrec_up_prev_read_cnt_lsw, \ pkt_ready_msg.audrec_up_prev_read_cnt_msw); audevrc_in_get_dsp_frames(audio); break; } case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: { MM_DBG("ptr_update recieved from DSP\n"); audpreproc_pcm_send_data(audio, 1); break; } case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: { MM_ERR("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG"); audevrc_in_mem_config(audio); break; } case AUDREC_UP_NT_PACKET_READY_MSG: { struct audrec_up_nt_packet_ready_msg pkt_ready_msg; getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN); MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \ write cnt msw %d read cnt lsw %d read cnt msw %d \n",\ pkt_ready_msg.audrec_packetwrite_cnt_lsw, \ pkt_ready_msg.audrec_packetwrite_cnt_msw, \ pkt_ready_msg.audrec_upprev_readcount_lsw, \ pkt_ready_msg.audrec_upprev_readcount_msw); audevrc_nt_in_get_dsp_frames(audio); break; } case AUDREC_CMD_EOS_ACK_MSG: { MM_DBG("eos ack recieved\n"); break; } case AUDREC_CMD_FLUSH_DONE_MSG: { audio->wflush = 0; audio->rflush = 0; audio->flush_ack = 1; wake_up(&audio->write_wait); MM_DBG("flush ack recieved\n"); break; } case ADSP_MESSAGE_ID: { MM_DBG("Received ADSP event:module audrectask\n"); break; } default: MM_ERR("Unknown Event id %d\n", id); } }
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"); } }
/* session id is 32 bit routing mask per device * 0-7 for voice clients * 8-15 for Decoder clients * 16-23 for Encoder clients * 24-31 Do not care */ void broadcast_event(u32 evt_id, u32 dev_id, u32 session_id) { int clnt_id = 0, i; union auddev_evt_data *evt_payload; struct msm_snd_evt_listner *callback; struct msm_snddev_info *dev_info = NULL; u32 session_mask = 0; static int pending_sent; MM_DBG(": evt_id = %d\n", evt_id); if ((evt_id != AUDDEV_EVT_START_VOICE) && (evt_id != AUDDEV_EVT_END_VOICE) && (evt_id != AUDDEV_EVT_STREAM_VOL_CHG) && (evt_id != AUDDEV_EVT_VOICE_STATE_CHG)) { dev_info = audio_dev_ctrl_find_dev(dev_id); if (IS_ERR(dev_info)) { MM_ERR("pass invalid dev_id\n"); return; } } if (event.cb != NULL) callback = event.cb; else return; mutex_lock(&session_lock); if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG) routing_info.voice_state = dev_id; evt_payload = kzalloc(sizeof(union auddev_evt_data), GFP_KERNEL); for (; ;) { if (!(evt_id & callback->evt_id)) { if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } clnt_id = callback->clnt_id; memset(evt_payload, 0, sizeof(union auddev_evt_data)); if ((evt_id == AUDDEV_EVT_START_VOICE) || (evt_id == AUDDEV_EVT_END_VOICE)) goto skip_check; if (callback->clnt_type == AUDDEV_CLNT_AUDIOCAL) goto aud_cal; session_mask = (0x1 << (clnt_id)) << (8 * ((int)callback->clnt_type-1)); if ((evt_id == AUDDEV_EVT_STREAM_VOL_CHG) || \ (evt_id == AUDDEV_EVT_VOICE_STATE_CHG)) { MM_DBG("AUDDEV_EVT_STREAM_VOL_CHG or\ AUDDEV_EVT_VOICE_STATE_CHG\n"); goto volume_strm; } MM_DBG("dev_info->sessions = %08x\n", dev_info->sessions); if ((!session_id && !(dev_info->sessions & session_mask)) || (session_id && ((dev_info->sessions & session_mask) != session_id))) { if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } if (evt_id == AUDDEV_EVT_DEV_CHG_VOICE) goto voc_events; volume_strm: if (callback->clnt_type == AUDDEV_CLNT_DEC) { MM_DBG("AUDDEV_CLNT_DEC\n"); if (evt_id == AUDDEV_EVT_STREAM_VOL_CHG) { MM_DBG("clnt_id = %d, session_id = 0x%8x\n", clnt_id, session_id); if (session_mask != session_id) goto sent_dec; else evt_payload->session_vol = msm_vol_ctl.volume; } else if (evt_id == AUDDEV_EVT_FREQ_CHG) { if (routing_info.dec_freq[clnt_id].evt) { routing_info.dec_freq[clnt_id].evt = 0; goto sent_dec; } else if (routing_info.dec_freq[clnt_id].freq == dev_info->set_sample_rate) goto sent_dec; else { evt_payload->freq_info.sample_rate = dev_info->set_sample_rate; evt_payload->freq_info.dev_type = dev_info->capability; evt_payload->freq_info.acdb_dev_id = dev_info->acdb_id; } } else if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG) evt_payload->voice_state = routing_info.voice_state; else evt_payload->routing_id = dev_info->copp_id; callback->auddev_evt_listener( evt_id, evt_payload, callback->private_data); sent_dec: if ((evt_id != AUDDEV_EVT_STREAM_VOL_CHG) && (evt_id != AUDDEV_EVT_VOICE_STATE_CHG)) routing_info.dec_freq[clnt_id].freq = dev_info->set_sample_rate; if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } if (callback->clnt_type == AUDDEV_CLNT_ENC) { MM_DBG("AUDDEV_CLNT_ENC\n"); if (evt_id == AUDDEV_EVT_FREQ_CHG) { if (routing_info.enc_freq[clnt_id].evt) { routing_info.enc_freq[clnt_id].evt = 0; goto sent_enc; } else { evt_payload->freq_info.sample_rate = dev_info->set_sample_rate; evt_payload->freq_info.dev_type = dev_info->capability; evt_payload->freq_info.acdb_dev_id = dev_info->acdb_id; } } else if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG) evt_payload->voice_state = routing_info.voice_state; else evt_payload->routing_id = dev_info->copp_id; callback->auddev_evt_listener( evt_id, evt_payload, callback->private_data); sent_enc: if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } aud_cal: if (callback->clnt_type == AUDDEV_CLNT_AUDIOCAL) { int temp_sessions; MM_DBG("AUDDEV_CLNT_AUDIOCAL\n"); if (evt_id == AUDDEV_EVT_VOICE_STATE_CHG) evt_payload->voice_state = routing_info.voice_state; else if (!dev_info->sessions) goto sent_aud_cal; else { evt_payload->audcal_info.dev_id = dev_info->copp_id; evt_payload->audcal_info.acdb_id = dev_info->acdb_id; evt_payload->audcal_info.dev_type = (dev_info->capability & SNDDEV_CAP_TX) ? SNDDEV_CAP_TX : SNDDEV_CAP_RX; evt_payload->audcal_info.sample_rate = dev_info->set_sample_rate ? dev_info->set_sample_rate : dev_info->sample_rate; } if (evt_payload->audcal_info.dev_type == SNDDEV_CAP_TX) { if (session_id == SESSION_IGNORE) temp_sessions = dev_info->sessions; else temp_sessions = session_id; evt_payload->audcal_info.sessions = (temp_sessions >> ((AUDDEV_CLNT_ENC-1) * 8)); } else { if (session_id == SESSION_IGNORE)
static int snddev_icodec_open(struct msm_snddev_info *dev_info) { int rc = 0; struct snddev_icodec_state *icodec; struct snddev_icodec_drv_state *drv = &snddev_icodec_drv; if (!dev_info) { rc = -EINVAL; goto error; } icodec = dev_info->private_data; if (icodec->data->capability & SNDDEV_CAP_RX) { mutex_lock(&drv->rx_lock); if (drv->rx_active) { mutex_unlock(&drv->rx_lock); rc = -EBUSY; goto error; } rc = snddev_icodec_open_rx(icodec); if (!IS_ERR_VALUE(rc)) { drv->rx_active = 1; if ((icodec->data->dev_vol_type & ( SNDDEV_DEV_VOL_DIGITAL | SNDDEV_DEV_VOL_ANALOG))) rc = snddev_icodec_set_device_volume_impl( dev_info, dev_info->dev_volume); if (IS_ERR_VALUE(rc)) { MM_ERR("Failed to set device volume" " impl for rx device\n"); snddev_icodec_close(dev_info); mutex_unlock(&drv->rx_lock); goto error; } } mutex_unlock(&drv->rx_lock); } else { mutex_lock(&drv->tx_lock); if (drv->tx_active) { mutex_unlock(&drv->tx_lock); rc = -EBUSY; goto error; } rc = snddev_icodec_open_tx(icodec); if (!IS_ERR_VALUE(rc)) { drv->tx_active = 1; if ((icodec->data->dev_vol_type & ( SNDDEV_DEV_VOL_DIGITAL | SNDDEV_DEV_VOL_ANALOG))) rc = snddev_icodec_set_device_volume_impl( dev_info, dev_info->dev_volume); if (IS_ERR_VALUE(rc)) { MM_ERR("Failed to set device volume" " impl for tx device\n"); snddev_icodec_close(dev_info); mutex_unlock(&drv->tx_lock); goto error; } } mutex_unlock(&drv->tx_lock); } error: return rc; }
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 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); lpa_cmd_enable_codec(drv->lpa, 1); /* 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; /* 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 long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct audio *audio = file->private_data; int rc = -EINVAL; if (cmd == AUDIO_GET_STATS) { struct msm_audio_stats stats; stats.byte_count = atomic_read(&audio->out_bytes); if (copy_to_user((void *) arg, &stats, sizeof(stats))) return -EFAULT; return 0; } mutex_lock(&audio->lock); switch (cmd) { case AUDIO_START: rc = audio_enable(audio); if (rc == 0) audio->enabled = 1; break; case AUDIO_STOP: if (audio->enabled) { audio->stopped = 1; rc = audio_disable(audio); if (rc == 0) { audio->enabled = 0; audio->running = 0; wake_up(&audio->wait); } else audio->stopped = 0; } break; case AUDIO_SET_CONFIG: { struct msm_audio_config config; if (copy_from_user(&config, (void *) arg, sizeof(config))) { rc = -EFAULT; break; } if (config.type == 0) { /* Selection for different PCM intect point */ } else { rc = -EINVAL; break; } rc = 0; break; } case AUDIO_GET_CONFIG: { struct msm_audio_config config; config.buffer_size = MAX_VOC_FRAME_SIZE * 2; config.buffer_count = MAX_VOC_FRAMES; config.sample_rate = 8000; config.channel_count = 1; config.type = 0; config.unused[0] = 0; config.unused[1] = 0; config.unused[2] = 0; if (copy_to_user((void *) arg, &config, sizeof(config))) rc = -EFAULT; else rc = 0; break; } default: { rc = -EINVAL; MM_ERR(" Unsupported ioctl 0x%8x\n", cmd); } } mutex_unlock(&audio->lock); return rc; }
static void handle_adsp_rtos_mtoa_app(struct rpc_request_hdr *req) { struct rpc_adsp_rtos_modem_to_app_args_t *args = (struct rpc_adsp_rtos_modem_to_app_args_t *)req; uint32_t event; uint32_t proc_id; #ifdef CONFIG_MACH_MOT uint32_t desc_field; #endif uint32_t module_id; uint32_t image; struct msm_adsp_module *module; struct adsp_rtos_mp_mtoa_type *pkt_ptr; struct queue_to_offset_type *qptr; struct queue_to_offset_type *qtbl; struct mod_to_queue_offsets *mqptr; struct mod_to_queue_offsets *mqtbl; uint32_t *mptr; uint32_t *mtbl; uint32_t q_idx; uint32_t num_entries; uint32_t entries_per_image; struct adsp_rtos_mp_mtoa_init_info_type *iptr; struct adsp_rtos_mp_mtoa_init_info_type *sptr; int32_t i_no, e_idx; event = be32_to_cpu(args->mtoa_pkt.mp_mtoa_header.event); proc_id = be32_to_cpu(args->mtoa_pkt.mp_mtoa_header.proc_id); #ifdef CONFIG_MACH_MOT desc_field = be32_to_cpu(args->mtoa_pkt.desc_field); if (desc_field == RPC_ADSP_RTOS_INIT_INFO) { pr_info("adsp:INIT_INFO Event\n"); #else if (event == RPC_ADSP_RTOS_INIT_INFO) { MM_INFO("INIT_INFO Event\n"); #endif sptr = &args->mtoa_pkt.adsp_rtos_mp_mtoa_data.mp_mtoa_init_packet; iptr = adsp_info.init_info_ptr; iptr->image_count = be32_to_cpu(sptr->image_count); iptr->num_queue_offsets = be32_to_cpu(sptr->num_queue_offsets); num_entries = iptr->num_queue_offsets; qptr = &sptr->queue_offsets_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { qtbl = &iptr->queue_offsets_tbl[i_no][0]; for (e_idx = 0; e_idx < num_entries; e_idx++) { qtbl[e_idx].offset = be32_to_cpu(qptr->offset); qtbl[e_idx].queue = be32_to_cpu(qptr->queue); q_idx = be32_to_cpu(qptr->queue); iptr->queue_offsets[i_no][q_idx] = qtbl[e_idx].offset; qptr++; } } num_entries = be32_to_cpu(sptr->num_task_module_entries); iptr->num_task_module_entries = num_entries; entries_per_image = num_entries / iptr->image_count; mptr = &sptr->task_to_module_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { mtbl = &iptr->task_to_module_tbl[i_no][0]; for (e_idx = 0; e_idx < entries_per_image; e_idx++) { mtbl[e_idx] = be32_to_cpu(*mptr); mptr++; } } iptr->module_table_size = be32_to_cpu(sptr->module_table_size); mptr = &sptr->module_entries[0]; for (i_no = 0; i_no < iptr->module_table_size; i_no++) iptr->module_entries[i_no] = be32_to_cpu(mptr[i_no]); mqptr = &sptr->mod_to_q_tbl[0]; mqtbl = &iptr->mod_to_q_tbl[0]; iptr->mod_to_q_entries = be32_to_cpu(sptr->mod_to_q_entries); for (e_idx = 0; e_idx < iptr->mod_to_q_entries; e_idx++) { mqtbl[e_idx].module = be32_to_cpu(mqptr->module); mqtbl[e_idx].q_type = be32_to_cpu(mqptr->q_type); mqtbl[e_idx].q_max_len = be32_to_cpu(mqptr->q_max_len); mqptr++; } adsp_info.init_info_state = ADSP_STATE_INIT_INFO; rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_SUCCESS); wake_up(&adsp_info.init_info_wait); return; } pkt_ptr = &args->mtoa_pkt.adsp_rtos_mp_mtoa_data.mp_mtoa_packet; module_id = be32_to_cpu(pkt_ptr->module); image = be32_to_cpu(pkt_ptr->image); MM_INFO("rpc event=%d, proc_id=%d, module=%d, image=%d\n", event, proc_id, module_id, image); module = find_adsp_module_by_id(&adsp_info, module_id); if (!module) { MM_ERR("module %d is not supported!\n", module_id); rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_GARBAGE_ARGS); return; } mutex_lock(&module->lock); switch (event) { case RPC_ADSP_RTOS_MOD_READY: MM_INFO("module %s: READY\n", module->name); module->state = ADSP_STATE_ENABLED; wake_up(&module->state_wait); adsp_set_image(module->info, image); break; case RPC_ADSP_RTOS_MOD_DISABLE: MM_INFO("module %s: DISABLED\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_SERVICE_RESET: MM_INFO("module %s: SERVICE_RESET\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_CMD_SUCCESS: MM_INFO("module %s: CMD_SUCCESS\n", module->name); break; case RPC_ADSP_RTOS_CMD_FAIL: MM_INFO("module %s: CMD_FAIL\n", module->name); break; case RPC_ADSP_RTOS_DISABLE_FAIL: MM_INFO("module %s: DISABLE_FAIL\n", module->name); break; default: MM_ERR("unknown event %d\n", event); rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_GARBAGE_ARGS); mutex_unlock(&module->lock); return; } rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_SUCCESS); mutex_unlock(&module->lock); #ifdef CONFIG_MSM_ADSP_REPORT_EVENTS #ifdef CONFIG_MACH_MOT event_addr = (uint32_t *)req; module->ops->event(module->driver_data, EVENT_MSG_ID, EVENT_LEN, read_event); #else modem_event_addr = (uint32_t *)req; module->ops->event(module->driver_data, EVENT_MSG_ID, EVENT_LEN, read_modem_event); #endif #endif } static int handle_adsp_rtos_mtoa(struct rpc_request_hdr *req) { switch (req->procedure) { case RPC_ADSP_RTOS_MTOA_NULL_PROC: rpc_send_accepted_void_reply(rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_SUCCESS); break; #ifdef CONFIG_MACH_MOT case RPC_ADSP_RTOS_MODEM_TO_APP_PROC: #else case RPC_ADSP_RTOS_MTOA_EVENT_INFO_PROC: #endif handle_adsp_rtos_mtoa_app(req); break; default: MM_ERR("unknowned proc %d\n", req->procedure); rpc_send_accepted_void_reply( rpc_cb_server_client, req->xid, RPC_ACCEPTSTAT_PROC_UNAVAIL); break; } return 0; } /* this should be common code with rpc_servers.c */ static int adsp_rpc_thread(void *data) { void *buffer; struct rpc_request_hdr *req; int rc; #ifdef CONFIG_MACH_MOT int exit =0; #endif do { rc = msm_rpc_read(rpc_cb_server_client, &buffer, -1, -1); if (rc < 0) { MM_ERR("could not read rpc: %d\n", rc); break; } req = (struct rpc_request_hdr *)buffer; req->type = be32_to_cpu(req->type); req->xid = be32_to_cpu(req->xid); req->rpc_vers = be32_to_cpu(req->rpc_vers); req->prog = be32_to_cpu(req->prog); req->vers = be32_to_cpu(req->vers); req->procedure = be32_to_cpu(req->procedure); if (req->type != 0) goto bad_rpc; if (req->rpc_vers != 2) goto bad_rpc; if (req->prog != rpc_adsp_rtos_mtoa_prog) goto bad_rpc; if (!msm_rpc_is_compatible_version(rpc_adsp_rtos_mtoa_vers, req->vers)) goto bad_rpc; handle_adsp_rtos_mtoa(req); kfree(buffer); continue; bad_rpc: MM_ERR("bogus rpc from modem\n"); kfree(buffer); #ifdef CONFIG_MACH_MOT } while (!exit); #else } while (1);
static void amrnb_in_listener(u32 evt_id, union auddev_evt_data *evt_payload, void *private_data) { struct audio_in *audio = (struct audio_in *) private_data; unsigned long flags; MM_DBG("evt_id = 0x%8x\n", evt_id); switch (evt_id) { case AUDDEV_EVT_DEV_RDY: { MM_DBG("AUDDEV_EVT_DEV_RDY\n"); spin_lock_irqsave(&audio->dev_lock, flags); audio->dev_cnt++; if (!audio->in_call) audio->source |= (0x1 << evt_payload->routing_id); spin_unlock_irqrestore(&audio->dev_lock, flags); if ((audio->running == 1) && (audio->enabled == 1)) audamrnb_in_record_config(audio, 1); break; } case AUDDEV_EVT_DEV_RLS: { MM_DBG("AUDDEV_EVT_DEV_RLS\n"); spin_lock_irqsave(&audio->dev_lock, flags); audio->dev_cnt--; if (!audio->in_call) audio->source &= ~(0x1 << evt_payload->routing_id); spin_unlock_irqrestore(&audio->dev_lock, flags); if ((!audio->running) || (!audio->enabled)) break; /* Turn of as per source */ if (audio->source) audamrnb_in_record_config(audio, 1); else /* Turn off all */ audamrnb_in_record_config(audio, 0); break; } case AUDDEV_EVT_VOICE_STATE_CHG: { MM_DBG("AUDDEV_EVT_VOICE_STATE_CHG, state = %d\n", evt_payload->voice_state); audio->voice_state = evt_payload->voice_state; if (audio->in_call && audio->running) { if (audio->voice_state == VOICE_STATE_INCALL) audamrnb_in_record_config(audio, 1); else if (audio->voice_state == VOICE_STATE_OFFCALL) { audamrnb_in_record_config(audio, 0); wake_up(&audio->wait); } } break; } default: MM_ERR("wrong event %d\n", evt_id); break; } }
static int audio_dev_ctrl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int rc = 0; struct audio_dev_ctrl_state *dev_ctrl = file->private_data; mutex_lock(&session_lock); switch (cmd) { case AUDIO_GET_NUM_SND_DEVICE: rc = put_user(dev_ctrl->num_dev, (uint32_t __user *) arg); break; case AUDIO_GET_SND_DEVICES: rc = audio_dev_ctrl_get_devices(dev_ctrl, (void __user *) arg); break; case AUDIO_ENABLE_SND_DEVICE: { struct msm_snddev_info *dev_info; u32 dev_id; if (get_user(dev_id, (u32 __user *) arg)) { rc = -EFAULT; break; } dev_info = audio_dev_ctrl_find_dev(dev_id); if (IS_ERR(dev_info)) rc = PTR_ERR(dev_info); else { rc = dev_info->dev_ops.open(dev_info); if (!rc) dev_info->opened = 1; wake_up(&audio_dev_ctrl.wait); } break; } case AUDIO_DISABLE_SND_DEVICE: { struct msm_snddev_info *dev_info; u32 dev_id; if (get_user(dev_id, (u32 __user *) arg)) { rc = -EFAULT; break; } dev_info = audio_dev_ctrl_find_dev(dev_id); if (IS_ERR(dev_info)) rc = PTR_ERR(dev_info); else { rc = dev_info->dev_ops.close(dev_info); dev_info->opened = 0; } break; } case AUDIO_ROUTE_STREAM: { struct msm_audio_route_config route_cfg; struct msm_snddev_info *dev_info; if (copy_from_user(&route_cfg, (void __user *) arg, sizeof(struct msm_audio_route_config))) { rc = -EFAULT; break; } MM_DBG("%s: route cfg %d %d type\n", __func__, route_cfg.dev_id, route_cfg.stream_type); dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id); if (IS_ERR(dev_info)) { MM_ERR("%s: pass invalid dev_id\n", __func__); rc = PTR_ERR(dev_info); break; } switch (route_cfg.stream_type) { case AUDIO_ROUTE_STREAM_VOICE_RX: if (!(dev_info->capability & SNDDEV_CAP_RX) | !(dev_info->capability & SNDDEV_CAP_VOICE)) { rc = -EINVAL; break; } dev_ctrl->voice_rx_dev = dev_info; break; case AUDIO_ROUTE_STREAM_VOICE_TX: if (!(dev_info->capability & SNDDEV_CAP_TX) | !(dev_info->capability & SNDDEV_CAP_VOICE)) { rc = -EINVAL; break; } dev_ctrl->voice_tx_dev = dev_info; break; } break; } default: rc = -EINVAL; } mutex_unlock(&session_lock); return rc; }
static ssize_t audamrnb_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct audio_in *audio = file->private_data; unsigned long flags; const char __user *start = buf; void *data; uint32_t index; uint32_t size; int rc = 0; mutex_lock(&audio->read_lock); while (count > 0) { rc = wait_event_interruptible( audio->wait, (audio->in_count > 0) || audio->stopped || (audio->in_call && audio->running && (audio->voice_state == VOICE_STATE_OFFCALL))); if (rc < 0) break; if (!audio->in_count) { if (audio->stopped) { rc = 0;/* End of File */ break; } else if (audio->in_call && audio->running && (audio->voice_state == VOICE_STATE_OFFCALL)) { MM_DBG("Not Permitted Voice Terminated\n"); rc = -EPERM; /* Voice Call stopped */ break; } } index = audio->in_tail; data = (uint8_t *) audio->in[index].data; size = audio->in[index].size; if (count >= size) { if (copy_to_user(buf, data, size)) { rc = -EFAULT; break; } spin_lock_irqsave(&audio->dsp_lock, flags); if (index != audio->in_tail) { /* overrun -- data is * invalid and we need to retry */ spin_unlock_irqrestore(&audio->dsp_lock, flags); continue; } audio->in[index].size = 0; audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1); audio->in_count--; spin_unlock_irqrestore(&audio->dsp_lock, flags); count -= size; buf += size; } else { MM_ERR("short read\n"); break; } } mutex_unlock(&audio->read_lock); if (buf > start) return buf - start; return rc; }
/* session id is 32 bit routing mask per device * 0-7 for voice clients * 8-15 for Decoder clients * 16-23 for Encoder clients * 24-31 Do not care */ void broadcast_event(u32 evt_id, u32 dev_id, u32 session_id) { int clnt_id = 0; union auddev_evt_data *evt_payload; struct msm_snd_evt_listner *callback; struct msm_snddev_info *dev_info = NULL; u32 session_mask = 0; static int pending_sent; MM_DBG(": evt_id = %d\n", evt_id); if ((evt_id != AUDDEV_EVT_START_VOICE) && (evt_id != AUDDEV_EVT_END_VOICE) && (evt_id != AUDDEV_EVT_STREAM_VOL_CHG)) { dev_info = audio_dev_ctrl_find_dev(dev_id); if (IS_ERR(dev_info)) return; } if (event.cb != NULL) callback = event.cb; else return; mutex_lock(&session_lock); evt_payload = kzalloc(sizeof(union auddev_evt_data), GFP_KERNEL); if (!evt_payload) { MM_ERR("%s: fail to allocate memory\n", __func__); return; } for (; ;) { if (!(evt_id & callback->evt_id)) { if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } clnt_id = callback->clnt_id; memset(evt_payload, 0, sizeof(union auddev_evt_data)); if ((evt_id == AUDDEV_EVT_START_VOICE) || (evt_id == AUDDEV_EVT_END_VOICE)) goto skip_check; if (callback->clnt_type == AUDDEV_CLNT_AUDIOCAL) goto aud_cal; session_mask = (0x1 << (clnt_id)) << (8 * ((int)callback->clnt_type-1)); if (evt_id == AUDDEV_EVT_STREAM_VOL_CHG) { MM_DBG("AUDDEV_EVT_STREAM_VOL_CHG\n"); goto volume_strm; } MM_DBG("dev_info->sessions = %08x\n", dev_info->sessions); if ((!session_id && !(dev_info->sessions & session_mask)) || (session_id && ((dev_info->sessions & session_mask) != session_id))) { if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } if (evt_id == AUDDEV_EVT_DEV_CHG_VOICE) goto voc_events; volume_strm: if (callback->clnt_type == AUDDEV_CLNT_DEC) { MM_DBG("AUDDEV_CLNT_DEC\n"); if (evt_id == AUDDEV_EVT_STREAM_VOL_CHG) { MM_DBG("clnt_id = %d, session_id = 0x%8x\n", clnt_id, session_id); if (session_mask != session_id) goto sent_dec; else evt_payload->session_vol = msm_vol_ctl.volume; } else if (evt_id == AUDDEV_EVT_FREQ_CHG) { if (routing_info.dec_freq[clnt_id].evt) { routing_info.dec_freq[clnt_id].evt = 0; goto sent_dec; } else if (routing_info.dec_freq[clnt_id].freq == dev_info->set_sample_rate) goto sent_dec; else { evt_payload->freq_info.sample_rate = dev_info->set_sample_rate; evt_payload->freq_info.dev_type = dev_info->capability; evt_payload->freq_info.acdb_dev_id = dev_info->acdb_id; } } else evt_payload->routing_id = dev_info->copp_id; callback->auddev_evt_listener( evt_id, evt_payload, callback->private_data); sent_dec: if (evt_id != AUDDEV_EVT_STREAM_VOL_CHG) routing_info.dec_freq[clnt_id].freq = dev_info->set_sample_rate; if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } if (callback->clnt_type == AUDDEV_CLNT_ENC) { MM_DBG("AUDDEV_CLNT_ENC\n"); if (evt_id == AUDDEV_EVT_FREQ_CHG) { if (routing_info.enc_freq[clnt_id].evt) { routing_info.enc_freq[clnt_id].evt = 0; goto sent_enc; } else { evt_payload->freq_info.sample_rate = dev_info->set_sample_rate; evt_payload->freq_info.dev_type = dev_info->capability; evt_payload->freq_info.acdb_dev_id = dev_info->acdb_id; } } else if (dev_info != NULL) evt_payload->routing_id = dev_info->copp_id; callback->auddev_evt_listener( evt_id, evt_payload, callback->private_data); sent_enc: if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } aud_cal: if (callback->clnt_type == AUDDEV_CLNT_AUDIOCAL) { MM_DBG("AUDDEV_CLNT_AUDIOCAL\n"); if (!dev_info->sessions) goto sent_aud_cal; evt_payload->audcal_info.dev_id = dev_info->copp_id; evt_payload->audcal_info.acdb_id = dev_info->acdb_id; evt_payload->audcal_info.dev_type = (dev_info->capability & SNDDEV_CAP_TX) ? SNDDEV_CAP_TX : SNDDEV_CAP_RX; evt_payload->audcal_info.sample_rate = dev_info->set_sample_rate ? dev_info->set_sample_rate : dev_info->sample_rate; callback->auddev_evt_listener( evt_id, evt_payload, callback->private_data); sent_aud_cal: if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } skip_check: voc_events: if (callback->clnt_type == AUDDEV_CLNT_VOC) { MM_DBG("AUDDEV_CLNT_VOC\n"); if (evt_id == AUDDEV_EVT_DEV_RLS) { if (!pending_sent) goto sent_voc; else pending_sent = 0; } if (evt_id == AUDDEV_EVT_REL_PENDING) pending_sent = 1; if (evt_id == AUDDEV_EVT_DEVICE_VOL_MUTE_CHG) { if (dev_info->capability & SNDDEV_CAP_TX) { evt_payload->voc_vm_info.dev_type = SNDDEV_CAP_TX; evt_payload->voc_vm_info.acdb_dev_id = dev_info->acdb_id; evt_payload-> voc_vm_info.dev_vm_val.mute = routing_info.tx_mute; } else { evt_payload->voc_vm_info.dev_type = SNDDEV_CAP_RX; evt_payload->voc_vm_info.acdb_dev_id = dev_info->acdb_id; if (routing_info.rx_mute == 1) /*mute rx*/ evt_payload-> voc_vm_info.dev_vm_val.mute = routing_info.rx_mute; else evt_payload-> voc_vm_info.dev_vm_val.vol = routing_info.voice_rx_vol; } } else if ((evt_id == AUDDEV_EVT_START_VOICE) || (evt_id == AUDDEV_EVT_END_VOICE)) memset(evt_payload, 0, sizeof(union auddev_evt_data)); else if (evt_id == AUDDEV_EVT_FREQ_CHG) { if (routing_info.voice_tx_sample_rate != dev_info->set_sample_rate) { routing_info.voice_tx_sample_rate = dev_info->set_sample_rate; evt_payload->freq_info.sample_rate = dev_info->set_sample_rate; evt_payload->freq_info.dev_type = dev_info->capability; evt_payload->freq_info.acdb_dev_id = dev_info->acdb_id; } else goto sent_voc; } else { evt_payload->voc_devinfo.dev_type = (dev_info->capability & SNDDEV_CAP_TX) ? SNDDEV_CAP_TX : SNDDEV_CAP_RX; evt_payload->voc_devinfo.acdb_dev_id = dev_info->acdb_id; evt_payload->voc_devinfo.dev_sample = dev_info->set_sample_rate ? dev_info->set_sample_rate : dev_info->sample_rate; evt_payload->voc_devinfo.dev_id = dev_id; if (dev_info->capability & SNDDEV_CAP_RX) evt_payload->voc_devinfo.vol_idx = dev_info->vol_idx; } callback->auddev_evt_listener( evt_id, evt_payload, callback->private_data); if (evt_id == AUDDEV_EVT_DEV_RLS) dev_info->sessions &= ~(0xFF); sent_voc: if (callback->cb_next == NULL) break; else { callback = callback->cb_next; continue; } } } kfree(evt_payload); mutex_unlock(&session_lock); }
static long snd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct snd_set_device_msg dmsg; struct snd_set_volume_msg vmsg; struct snd_avc_ctl_msg avc_msg; struct snd_agc_ctl_msg agc_msg; struct snd_set_lb_msg lb_msg; struct msm_snd_device_config dev; struct msm_snd_volume_config vol; struct snd_ctxt *snd = file->private_data; int rc = 0; uint32_t avc, agc; uint32_t set_lb; mutex_lock(&snd->lock); switch (cmd) { case SND_SET_DEVICE: if (copy_from_user(&dev, (void __user *) arg, sizeof(dev))) { MM_ERR("set device: invalid pointer\n"); rc = -EFAULT; break; } dmsg.args.device = cpu_to_be32(dev.device); dmsg.args.ear_mute = cpu_to_be32(dev.ear_mute); dmsg.args.mic_mute = cpu_to_be32(dev.mic_mute); if (check_mute(dev.ear_mute) < 0 || check_mute(dev.mic_mute) < 0) { MM_ERR("set device: invalid mute status\n"); rc = -EINVAL; break; } dmsg.args.cb_func = -1; dmsg.args.client_data = 0; MM_INFO("snd_set_device %d %d %d\n", dev.device, dev.ear_mute, dev.mic_mute); #if 0 rc = msm_rpc_call(snd->ept, SND_SET_DEVICE_PROC, &dmsg, sizeof(dmsg), 5 * HZ); #else if(SND_DEVICE_FM_STEREO_HEADSET_ZTE == dev.device) { rc = msm_rpc_call(snd->ept, SND_SET_FM_HEADSET_DEVICE_PROC, &dmsg, sizeof(dmsg), 5 * HZ); } else { rc = msm_rpc_call(snd->ept, SND_SET_DEVICE_PROC, &dmsg, sizeof(dmsg), 5 * HZ); } #endif if (dev.device != 28) { keep_snd_dev_info[SND_DEV] = dev.device; } keep_snd_dev_info[EAR_MUTE] = dev.ear_mute; keep_snd_dev_info[MIC_MUTE] = dev.mic_mute; break; case SND_SET_VOLUME: if (copy_from_user(&vol, (void __user *) arg, sizeof(vol))) { MM_ERR("set volume: invalid pointer\n"); rc = -EFAULT; break; } vmsg.args.device = cpu_to_be32(vol.device); vmsg.args.method = cpu_to_be32(vol.method); if (vol.method != SND_METHOD_VOICE) { MM_ERR("set volume: invalid method\n"); rc = -EINVAL; break; } vmsg.args.volume = cpu_to_be32(vol.volume); vmsg.args.cb_func = -1; vmsg.args.client_data = 0; MM_INFO("snd_set_volume %d %d %d\n", vol.device, vol.method, vol.volume); rc = msm_rpc_call(snd->ept, SND_SET_VOLUME_PROC, &vmsg, sizeof(vmsg), 5 * HZ); break; case SND_AVC_CTL: if (get_user(avc, (uint32_t __user *) arg)) { rc = -EFAULT; break; } else if ((avc != 1) && (avc != 0)) { rc = -EINVAL; break; } avc_msg.args.avc_ctl = cpu_to_be32(avc); avc_msg.args.cb_func = -1; avc_msg.args.client_data = 0; MM_INFO("snd_avc_ctl %d\n", avc); rc = msm_rpc_call(snd->ept, SND_AVC_CTL_PROC, &avc_msg, sizeof(avc_msg), 5 * HZ); break; case SND_AGC_CTL: if (get_user(agc, (uint32_t __user *) arg)) { rc = -EFAULT; break; } else if ((agc != 1) && (agc != 0)) { rc = -EINVAL; break; } agc_msg.args.agc_ctl = cpu_to_be32(agc); agc_msg.args.cb_func = -1; agc_msg.args.client_data = 0; MM_INFO("snd_agc_ctl %d\n", agc); rc = msm_rpc_call(snd->ept, SND_AGC_CTL_PROC, &agc_msg, sizeof(agc_msg), 5 * HZ); break; case SND_GET_NUM_ENDPOINTS: if (copy_to_user((void __user *)arg, &snd->snd_epts->num, sizeof(unsigned))) { MM_ERR("get endpoint: invalid pointer\n"); rc = -EFAULT; } break; case SND_GET_ENDPOINT: rc = get_endpoint(snd, arg); break; case SND_SET_AUDIO_LOOPBACK: if (get_user(set_lb, (uint32_t __user *) arg)) { rc = -EFAULT; break; } else if ((set_lb != 1) && (set_lb != 0)) { rc = -EINVAL; break; } lb_msg.args.lb_ctl = cpu_to_be32(set_lb); lb_msg.args.cb_func = -1; lb_msg.args.client_data = 0; pr_info("snd_lb_ctl %d\n", set_lb); rc = msm_rpc_call(snd->ept, SND_AUDIO_LOOPBACK_PROC, &lb_msg, sizeof(lb_msg), 5 * HZ); break; default: MM_ERR("unknown command\n"); rc = -EINVAL; break; } mutex_unlock(&snd->lock); return rc; }
static int msm_voice_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0; uint32_t rx_dev_id; uint32_t tx_dev_id; struct msm_snddev_info *rx_dev_info; struct msm_snddev_info *tx_dev_info; int set = ucontrol->value.integer.value[2]; u32 session_mask; if (!set) return -EPERM; /* Rx Device Routing */ rx_dev_id = ucontrol->value.integer.value[0]; rx_dev_info = audio_dev_ctrl_find_dev(rx_dev_id); if (IS_ERR(rx_dev_info)) { MM_ERR("pass invalid dev_id\n"); rc = PTR_ERR(rx_dev_info); return rc; } if (!(rx_dev_info->capability & SNDDEV_CAP_RX)) { MM_ERR("First Dev is supposed to be RX\n"); return -EFAULT; } msm_set_voc_route(rx_dev_info, AUDIO_ROUTE_STREAM_VOICE_RX, rx_dev_id); session_mask = 0x1 << (8 * ((int)AUDDEV_CLNT_VOC-1)); broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, rx_dev_id, session_mask); /* Tx Device Routing */ tx_dev_id = ucontrol->value.integer.value[1]; if (tx_dev_id == 3) { // Not sure if this is needed, but it works :) pr_info("ksatta: msm_voice_put() tx_dev_id is 3 (headset mic), changing to 10(speakerphone mic)."); tx_dev_id = 10; } tx_dev_info = audio_dev_ctrl_find_dev(tx_dev_id); if (IS_ERR(tx_dev_info)) { MM_ERR("pass invalid dev_id\n"); rc = PTR_ERR(tx_dev_info); return rc; } if (!(tx_dev_info->capability & SNDDEV_CAP_TX)) { MM_ERR("Second Dev is supposed to be Tx\n"); return -EFAULT; } //pr_info("ksatta: msm_voice_put() tx_dev_id:%Lu rx_dev_id:%Lu \n", (long long unsigned int) tx_dev_id, (long long unsigned int) rx_dev_id); msm_set_voc_route(tx_dev_info, AUDIO_ROUTE_STREAM_VOICE_TX, tx_dev_id); broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, tx_dev_id, session_mask); if (rx_dev_info->opened) broadcast_event(AUDDEV_EVT_DEV_RDY, rx_dev_id, session_mask); if (tx_dev_info->opened) broadcast_event(AUDDEV_EVT_DEV_RDY, tx_dev_id, session_mask); return rc; }
static ssize_t audpcm_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct audio_in *audio = file->private_data; unsigned long flags; const char __user *start = buf; void *data; uint32_t index; uint32_t size; int rc = 0; mutex_lock(&audio->read_lock); while (count > 0) { rc = wait_event_interruptible( audio->wait, (audio->in_count > 0) || audio->stopped || audio->abort); if (rc < 0) break; if (audio->stopped && !audio->in_count) { MM_DBG("Driver in stop state, No more buffer to read"); rc = 0;/* End of File */ break; } if (audio->abort) { rc = -EPERM; /* Not permitted due to abort */ break; } index = audio->in_tail; data = (uint8_t *) audio->in[index].data; size = audio->in[index].size; if (count >= size) { if (copy_to_user(buf, data, size)) { rc = -EFAULT; break; } spin_lock_irqsave(&audio->dsp_lock, flags); if (index != audio->in_tail) { /* overrun -- data is * invalid and we need to retry */ spin_unlock_irqrestore(&audio->dsp_lock, flags); continue; } audio->in[index].size = 0; audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1); audio->in_count--; spin_unlock_irqrestore(&audio->dsp_lock, flags); count -= size; buf += size; } else { MM_ERR("short read\n"); break; } } mutex_unlock(&audio->read_lock); if (buf > start) return buf - start; 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; 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; if (route_cfg.dev_id == 3) { // this is needed for sure pr_info("ksatta: msm_device_put() dev_id is 3(headset mic), changing to 10(speakerphone mic)"); route_cfg.dev_id = 10; } dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id); if (IS_ERR(dev_info)) { MM_ERR("pass invalid dev_id\n"); rc = PTR_ERR(dev_info); return rc; } //pr_info("ksatta: msm_device_put() dev name:'%s' set:%d\n", 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; MM_ERR("device freq =%d\n", set_freq); rc = dev_info->dev_ops.set_freq(dev_info, set_freq); if (rc < 0) { MM_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_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); } } 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_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); } } } return rc; }
static long snd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct snd_set_device_msg dmsg; struct snd_set_volume_msg vmsg; struct snd_avc_ctl_msg avc_msg; struct snd_agc_ctl_msg agc_msg; struct msm_snd_device_config dev; struct msm_snd_volume_config vol; struct snd_ctxt *snd = file->private_data; int rc = 0; uint32_t avc, agc; mutex_lock(&snd->lock); switch (cmd) { case SND_SET_DEVICE: if (copy_from_user(&dev, (void __user *) arg, sizeof(dev))) { MM_AUD_ERR("set device: invalid pointer\n"); rc = -EFAULT; break; } dmsg.args.device = cpu_to_be32(dev.device); dmsg.args.ear_mute = cpu_to_be32(dev.ear_mute); dmsg.args.mic_mute = cpu_to_be32(dev.mic_mute); if (check_mute(dev.ear_mute) < 0 || check_mute(dev.mic_mute) < 0) { MM_AUD_ERR("set device: invalid mute status\n"); rc = -EINVAL; break; } dmsg.args.cb_func = -1; dmsg.args.client_data = 0; MM_AUD_INFO("snd_set_device %d %d %d\n", dev.device, dev.ear_mute, dev.mic_mute); rc = msm_rpc_call(snd->ept, SND_SET_DEVICE_PROC, &dmsg, sizeof(dmsg), 5 * HZ); htc_pwrsink_audio_path_set(dmsg.args.device); break; case SND_SET_VOLUME: if (copy_from_user(&vol, (void __user *) arg, sizeof(vol))) { MM_AUD_ERR("set volume: invalid pointer\n"); rc = -EFAULT; break; } vmsg.args.device = cpu_to_be32(vol.device); vmsg.args.method = cpu_to_be32(vol.method); if (vol.method != SND_METHOD_VOICE) { MM_AUD_ERR("set volume: invalid method\n"); rc = -EINVAL; break; } vmsg.args.volume = cpu_to_be32(vol.volume); vmsg.args.cb_func = -1; vmsg.args.client_data = 0; MM_AUD_INFO("snd_set_volume %d %d %d\n", vol.device, vol.method, vol.volume); rc = msm_rpc_call(snd->ept, SND_SET_VOLUME_PROC, &vmsg, sizeof(vmsg), 5 * HZ); break; case SND_AVC_CTL: if (get_user(avc, (uint32_t __user *) arg)) { rc = -EFAULT; break; } else if ((avc != 1) && (avc != 0)) { rc = -EINVAL; break; } avc_msg.args.avc_ctl = cpu_to_be32(avc); avc_msg.args.cb_func = -1; avc_msg.args.client_data = 0; MM_AUD_INFO("snd_avc_ctl %d\n", avc); rc = msm_rpc_call(snd->ept, SND_AVC_CTL_PROC, &avc_msg, sizeof(avc_msg), 5 * HZ); break; case SND_AGC_CTL: if (get_user(agc, (uint32_t __user *) arg)) { rc = -EFAULT; break; } else if ((agc != 1) && (agc != 0)) { rc = -EINVAL; break; } agc_msg.args.agc_ctl = cpu_to_be32(agc); agc_msg.args.cb_func = -1; agc_msg.args.client_data = 0; MM_AUD_INFO("snd_agc_ctl %d\n", agc); rc = msm_rpc_call(snd->ept, SND_AGC_CTL_PROC, &agc_msg, sizeof(agc_msg), 5 * HZ); break; case SND_GET_NUM_ENDPOINTS: if (copy_to_user((void __user *)arg, &snd->snd_epts->num, sizeof(unsigned))) { MM_ERR("get endpoint: invalid pointer\n"); rc = -EFAULT; } break; case SND_GET_ENDPOINT: rc = get_endpoint(snd, arg); break; default: MM_AUD_ERR("unknown command\n"); rc = -EINVAL; break; } mutex_unlock(&snd->lock); return rc; }
static int msm_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int rc = 0; int enc_freq = 0; int requested_freq = 0; struct msm_audio_route_config route_cfg; struct msm_snddev_info *dev_info; int session_id = ucontrol->value.integer.value[0]; int set = ucontrol->value.integer.value[2]; u32 session_mask = 0; route_cfg.dev_id = ucontrol->value.integer.value[1]; if (ucontrol->id.numid == 2) route_cfg.stream_type = AUDIO_ROUTE_STREAM_PLAYBACK; else route_cfg.stream_type = AUDIO_ROUTE_STREAM_REC; dev_info = audio_dev_ctrl_find_dev(route_cfg.dev_id); if (IS_ERR(dev_info)) { MM_ERR("pass invalid dev_id\n"); rc = PTR_ERR(dev_info); return rc; } if (route_cfg.stream_type == AUDIO_ROUTE_STREAM_PLAYBACK) { rc = msm_snddev_set_dec(session_id, dev_info->copp_id, set); session_mask = (0x1 << (session_id) << (8 * ((int)AUDDEV_CLNT_DEC-1))); if (!set) { if (dev_info->opened) { broadcast_event(AUDDEV_EVT_REL_PENDING, route_cfg.dev_id, session_mask); broadcast_event(AUDDEV_EVT_DEV_RLS, route_cfg.dev_id, session_mask); } dev_info->sessions &= ~(session_mask); } else { dev_info->sessions = dev_info->sessions | session_mask; if (dev_info->opened) broadcast_event(AUDDEV_EVT_DEV_RDY, route_cfg.dev_id, session_mask); } } else { rc = msm_snddev_set_enc(session_id, dev_info->copp_id, set); session_mask = (0x1 << (session_id)) << (8 * ((int)AUDDEV_CLNT_ENC-1)); if (!set) { if (dev_info->opened) broadcast_event(AUDDEV_EVT_DEV_RLS, route_cfg.dev_id, session_mask); dev_info->sessions &= ~(session_mask); } else { dev_info->sessions = dev_info->sessions | session_mask; enc_freq = msm_snddev_get_enc_freq(session_id); requested_freq = enc_freq; if (enc_freq > 0) { rc = msm_snddev_request_freq(&enc_freq, session_id, SNDDEV_CAP_TX, AUDDEV_CLNT_ENC); MM_DBG("sample rate configured %d" "sample rate requested %d \n", enc_freq, requested_freq); if ((rc <= 0) || (enc_freq != requested_freq)) { MM_DBG("msm_snddev_withdraw_freq\n"); rc = msm_snddev_withdraw_freq (session_id, SNDDEV_CAP_TX, AUDDEV_CLNT_ENC); broadcast_event(AUDDEV_EVT_FREQ_CHG, route_cfg.dev_id, SESSION_IGNORE); } } if (dev_info->opened) broadcast_event(AUDDEV_EVT_DEV_RDY, route_cfg.dev_id, session_mask); } } if (rc < 0) { MM_ERR("device could not be assigned!\n"); return -EFAULT; } return rc; }
static void adsp_rtos_mtoa_cb(void *context, uint32_t param, void *evt_buf, uint32_t len) { struct adsp_rtos_mp_mtoa_s_type *args = NULL; uint32_t event = 0; uint32_t proc_id = 0; uint32_t module_id; uint32_t image; struct msm_adsp_module *module; struct adsp_rtos_mp_mtoa_type *pkt_ptr; struct queue_to_offset_type *qptr; struct queue_to_offset_type *qtbl; struct mod_to_queue_offsets *mqptr; struct mod_to_queue_offsets *mqtbl; uint32_t *mptr; uint32_t *mtbl; uint32_t q_idx; uint32_t num_entries; uint32_t entries_per_image; struct adsp_rtos_mp_mtoa_init_info_type *iptr; struct adsp_rtos_mp_mtoa_init_info_type *sptr; int32_t i_no, e_idx; static uint32_t init_info_completed; static uint32_t init_info_len = sizeof(struct adsp_rtos_mp_mtoa_header_type); static uint32_t next_init_info_byte; static uint32_t expected_byte = 1; uint32_t hdr_len = sizeof(struct adsp_rtos_mp_mtoa_header_type); if (len) { args = (struct adsp_rtos_mp_mtoa_s_type *) evt_buf; event = args->mp_mtoa_header.event; proc_id = args->mp_mtoa_header.proc_id; } if (!init_info_completed && event == RPC_ADSP_RTOS_INIT_INFO) { memcpy(((char *)adsp_info.raw_event) + init_info_len, (char *)evt_buf + hdr_len + 4, len - ((hdr_len + 4))); init_info_len += (len - (hdr_len + 4)); evt_buf += hdr_len; next_init_info_byte = *(uint32_t *) evt_buf; expected_byte += len; if (next_init_info_byte && (expected_byte != next_init_info_byte)) { MM_ERR("INIT_INFO - expecting next byte to be %d\n" "\tbut ADSPSVC indicated next byte to be %d\n", expected_byte, next_init_info_byte); return; } if (!next_init_info_byte) { args = adsp_info.raw_event; args->mp_mtoa_header.event = event; args->mp_mtoa_header.proc_id = proc_id; init_info_completed = 1; } else return; } if (event == RPC_ADSP_RTOS_INIT_INFO) { MM_INFO("INIT_INFO Event\n"); sptr = &args->adsp_rtos_mp_mtoa_data.mp_mtoa_init_packet; iptr = adsp_info.init_info_ptr; iptr->image_count = sptr->image_count; if (iptr->image_count > IMG_MAX) iptr->image_count = IMG_MAX; iptr->num_queue_offsets = sptr->num_queue_offsets; num_entries = iptr->num_queue_offsets; if (num_entries > ENTRIES_MAX) { num_entries = ENTRIES_MAX; iptr->num_queue_offsets = ENTRIES_MAX; } qptr = &sptr->queue_offsets_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { qtbl = &iptr->queue_offsets_tbl[i_no][0]; for (e_idx = 0; e_idx < num_entries; e_idx++) { qtbl[e_idx].offset = qptr->offset; qtbl[e_idx].queue = qptr->queue; q_idx = qptr->queue; iptr->queue_offsets[i_no][q_idx] = qtbl[e_idx].offset; qptr++; } } num_entries = sptr->num_task_module_entries; if (num_entries > ENTRIES_MAX) num_entries = ENTRIES_MAX; iptr->num_task_module_entries = num_entries; entries_per_image = num_entries / iptr->image_count; mptr = &sptr->task_to_module_tbl[0][0]; for (i_no = 0; i_no < iptr->image_count; i_no++) { mtbl = &iptr->task_to_module_tbl[i_no][0]; for (e_idx = 0; e_idx < entries_per_image; e_idx++) { mtbl[e_idx] = *mptr; mptr++; } } iptr->module_table_size = sptr->module_table_size; if (iptr->module_table_size > MODULES_MAX) iptr->module_table_size = MODULES_MAX; mptr = &sptr->module_entries[0]; for (i_no = 0; i_no < iptr->module_table_size; i_no++) iptr->module_entries[i_no] = mptr[i_no]; mqptr = &sptr->mod_to_q_tbl[0]; mqtbl = &iptr->mod_to_q_tbl[0]; iptr->mod_to_q_entries = sptr->mod_to_q_entries; if (iptr->mod_to_q_entries > ENTRIES_MAX) iptr->mod_to_q_entries = ENTRIES_MAX; for (e_idx = 0; e_idx < iptr->mod_to_q_entries; e_idx++) { mqtbl[e_idx].module = mqptr->module; mqtbl[e_idx].q_type = mqptr->q_type; mqtbl[e_idx].q_max_len = mqptr->q_max_len; mqptr++; } adsp_info.init_info_state = ADSP_STATE_INIT_INFO; kfree(adsp_info.raw_event); wake_up(&adsp_info.init_info_wait); return; } pkt_ptr = &args->adsp_rtos_mp_mtoa_data.mp_mtoa_packet; module_id = pkt_ptr->module; image = pkt_ptr->image; MM_INFO("rpc event=%d, proc_id=%d, module=%d, image=%d\n", event, proc_id, module_id, image); module = find_adsp_module_by_id(&adsp_info, module_id); if (!module) { MM_ERR("module %d is not supported!\n", module_id); return; } mutex_lock(&module->lock); switch (event) { case RPC_ADSP_RTOS_MOD_READY: MM_INFO("module %s: READY\n", module->name); module->state = ADSP_STATE_ENABLED; wake_up(&module->state_wait); adsp_set_image(module->info, image); break; case RPC_ADSP_RTOS_MOD_DISABLE: MM_INFO("module %s: DISABLED\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_SERVICE_RESET: MM_INFO("module %s: SERVICE_RESET\n", module->name); module->state = ADSP_STATE_DISABLED; wake_up(&module->state_wait); break; case RPC_ADSP_RTOS_CMD_SUCCESS: MM_INFO("module %s: CMD_SUCCESS\n", module->name); break; case RPC_ADSP_RTOS_CMD_FAIL: MM_INFO("module %s: CMD_FAIL\n", module->name); break; case RPC_ADSP_RTOS_DISABLE_FAIL: MM_INFO("module %s: DISABLE_FAIL\n", module->name); break; default: MM_ERR("unknown event %d\n", event); mutex_unlock(&module->lock); return; } #ifdef CONFIG_MSM_ADSP_REPORT_EVENTS event_addr = (uint32_t *)evt_buf; if (module->ops) module->ops->event(module->driver_data, EVENT_MSG_ID, EVENT_LEN, read_event); #endif mutex_unlock(&module->lock); }
static long q6_amrnb_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct amrnb *amrnb = file->private_data; int rc = 0; mutex_lock(&amrnb->lock); switch (cmd) { case AUDIO_SET_VOLUME: break; case AUDIO_GET_STATS: { struct msm_audio_stats stats; memset(&stats, 0, sizeof(stats)); if (copy_to_user((void *) arg, &stats, sizeof(stats))) { mutex_unlock(&amrnb->lock); return -EFAULT; } mutex_unlock(&amrnb->lock); return 0; } case AUDIO_START: { uint32_t acdb_id; if (arg == 0) { acdb_id = 0; } else { if (copy_from_user(&acdb_id, (void *) arg, sizeof(acdb_id))) { rc = -EFAULT; break; } } if (amrnb->audio_client) { rc = -EBUSY; break; } else { amrnb->audio_client = q6audio_open_amrnb( amrnb->str_cfg.buffer_size, amrnb->cfg.band_mode, amrnb->cfg.dtx_enable, amrnb->voicerec_mode.rec_mode, acdb_id); if (!amrnb->audio_client) { kfree(amrnb); rc = -ENOMEM; break; } } break; } case AUDIO_STOP: break; case AUDIO_FLUSH: break; case AUDIO_SET_INCALL: { if (copy_from_user(&amrnb->voicerec_mode, (void *)arg, sizeof(struct msm_voicerec_mode))) rc = -EFAULT; if (amrnb->voicerec_mode.rec_mode != AUDIO_FLAG_READ && amrnb->voicerec_mode.rec_mode != AUDIO_FLAG_INCALL_MIXED) { amrnb->voicerec_mode.rec_mode = AUDIO_FLAG_READ; MM_ERR("Invalid rec_mode\n"); rc = -EINVAL; } break; } case AUDIO_GET_STREAM_CONFIG: if (copy_to_user((void *)arg, &amrnb->str_cfg, sizeof(struct msm_audio_stream_config))) rc = -EFAULT; break; case AUDIO_SET_STREAM_CONFIG: if (copy_from_user(&amrnb->str_cfg, (void *)arg, sizeof(struct msm_audio_stream_config))) { rc = -EFAULT; break; } if (amrnb->str_cfg.buffer_size < 768) { MM_ERR("Buffer size too small\n"); rc = -EINVAL; break; } if (amrnb->str_cfg.buffer_count != 2) MM_INFO("Buffer count set to 2\n"); break; case AUDIO_SET_AMRNB_ENC_CONFIG: if (copy_from_user(&amrnb->cfg, (void *) arg, sizeof(struct msm_audio_amrnb_enc_config_v2))) rc = -EFAULT; break; case AUDIO_GET_AMRNB_ENC_CONFIG: if (copy_to_user((void *) arg, &amrnb->cfg, sizeof(struct msm_audio_amrnb_enc_config_v2))) rc = -EFAULT; break; default: rc = -EINVAL; } mutex_unlock(&amrnb->lock); 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; 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_ERR("pass invalid dev_id\n"); rc = PTR_ERR(dev_info); return rc; } MM_INFO("device %s set %d\n", 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; MM_ERR("device freq =%d\n", set_freq); rc = dev_info->dev_ops.set_freq(dev_info, set_freq); if (rc < 0) { MM_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_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); /* Event to notify client for device info */ broadcast_event(AUDDEV_EVT_DEVICE_INFO, route_cfg.dev_id, SESSION_IGNORE); } } 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_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); } } } return rc; }
/* must be called with audio->lock held */ static int audvoicememo_enable(struct audio_voicememo *audio) { struct audmgr_config cfg; struct snd_voc_rec_put_buf_msg bmsg; struct snd_voc_rec_start_msg msg; uint8_t index; uint32_t offset = 0; int rc; if (audio->enabled) return 0; /* Codec / method configure to audmgr client */ cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_8000; cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE; cfg.def_method = RPC_AUD_DEF_METHOD_RECORD; if (audio->voicememo_cfg.capability == RPC_VOC_CAP_IS733) cfg.codec = RPC_AUD_DEF_CODEC_VOC_13K; else if (audio->voicememo_cfg.capability == RPC_VOC_CAP_IS127) cfg.codec = RPC_AUD_DEF_CODEC_VOC_EVRC; else cfg.codec = RPC_AUD_DEF_CODEC_VOC_AMR; /* RPC_VOC_CAP_AMR */ cfg.snd_method = RPC_SND_METHOD_VOICE; rc = audmgr_enable(&audio->audmgr, &cfg); if (rc < 0) return rc; /* Configure VOC Rec buffer */ for (index = 0; index < MAX_REC_BUF_COUNT; index++) { audio->in[index].data = audio->rec_buf_ptr + offset; audio->in[index].addr = audio->phys + offset; audio->in[index].size = audio->rec_buf_size; audio->in[index].used = 0; audio->in[index].numframes = 0; offset += audio->rec_buf_size; bmsg.args.buf = (uint32_t) audio->in[index].data; bmsg.args.num_bytes = cpu_to_be32(audio->in[index].size); MM_DBG("rec_buf_ptr=0x%8x, rec_buf_size = 0x%8x\n", bmsg.args.buf, bmsg.args.num_bytes); msm_rpc_setup_req(&bmsg.hdr, audio->rpc_prog, audio->rpc_ver, SND_VOC_REC_PUT_BUF_PROC); audio->rpc_xid = bmsg.hdr.xid; audio->rpc_status = RPC_STATUS_FAILURE; msm_rpc_write(audio->sndept, &bmsg, sizeof(bmsg)); rc = wait_event_timeout(audio->wait, audio->rpc_status != RPC_STATUS_FAILURE, 1 * HZ); if (rc == 0) goto err; } /* Start Recording */ msg.args.param_status = cpu_to_be32(0x00000001); msg.args.rec_type = cpu_to_be32(audio->voicememo_cfg.rec_type); msg.args.rec_interval_ms = cpu_to_be32(audio->voicememo_cfg.rec_interval_ms); msg.args.auto_stop_ms = cpu_to_be32(audio->voicememo_cfg.auto_stop_ms); msg.args.capability = cpu_to_be32(audio->voicememo_cfg.capability); msg.args.max_rate = cpu_to_be32(audio->voicememo_cfg.max_rate); msg.args.min_rate = cpu_to_be32(audio->voicememo_cfg.min_rate); msg.args.frame_format = cpu_to_be32(audio->voicememo_cfg.frame_format); msg.args.dtx_enable = cpu_to_be32(audio->voicememo_cfg.dtx_enable); msg.args.data_req_ms = cpu_to_be32(audio->voicememo_cfg.data_req_ms); msg.args.rec_client_data = cpu_to_be32(REC_CLIENT_DATA); msg.args.cb_func_id = cpu_to_be32(DATA_CB_FUNC_ID); msg.args.sync_cb_func_id = cpu_to_be32(AV_SYNC_CB_FUNC_ID); msg.args.client_data = cpu_to_be32(CLIENT_DATA); msm_rpc_setup_req(&msg.hdr, audio->rpc_prog, audio->rpc_ver, SND_VOC_REC_START_PROC); audio->rpc_xid = msg.hdr.xid; audio->rpc_status = RPC_STATUS_FAILURE; msm_rpc_write(audio->sndept, &msg, sizeof(msg)); rc = wait_event_timeout(audio->wait, audio->rpc_status != RPC_STATUS_FAILURE, 1 * HZ); if (rc == 0) goto err; audio->rpc_xid = 0; audio->enabled = 1; isAudioEn = 1; //JRD added pmic_mic_en(true); return 0; err: audio->rpc_xid = 0; audmgr_disable(&audio->audmgr); MM_ERR("Fail\n"); return -1; }