static int audqcelp_in_release(struct inode *inode, struct file *file) { struct audio_in *audio = file->private_data; MM_DBG("\n"); mutex_lock(&audio->lock); audio->in_call = 0; auddev_unregister_evt_listner(AUDDEV_CLNT_ENC, audio->enc_id); audqcelp_in_disable(audio); audqcelp_in_flush(audio); msm_adsp_put(audio->audrec); audpreproc_aenc_free(audio->enc_id); audio->audrec = NULL; audio->opened = 0; mutex_unlock(&audio->lock); return 0; }
static int audqcelp_in_release(struct inode *inode, struct file *file) { struct audio_in *audio = file->private_data; MM_DBG("\n"); mutex_lock(&audio->lock); audio->in_call = 0; /* with draw frequency for session incase not stopped the driver */ msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX, AUDDEV_CLNT_ENC); auddev_unregister_evt_listner(AUDDEV_CLNT_ENC, audio->enc_id); audqcelp_in_disable(audio); audqcelp_in_flush(audio); msm_adsp_put(audio->audrec); audpreproc_aenc_free(audio->enc_id); audio->audrec = NULL; audio->opened = 0; mutex_unlock(&audio->lock); return 0; }
static int audqcelp_in_open(struct inode *inode, struct file *file) { struct audio_in *audio = &the_audio_qcelp_in; int rc; int encid; MM_DBG("\n"); 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->buffer_size = (FRAME_SIZE - 8); audio->enc_type = ENC_TYPE_V13K; audio->cfg.cdma_rate = CDMA_RATE_FULL; audio->cfg.min_bit_rate = CDMA_RATE_FULL; audio->cfg.max_bit_rate = CDMA_RATE_FULL; audio->source = INTERNAL_CODEC_TX_SOURCE_MIX_MASK; audio->rec_mode = VOC_REC_UPLINK; 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_qcelp_adsp_ops, audio); if (rc) { audpreproc_aenc_free(audio->enc_id); goto done; } audio->stopped = 0; audio->source = 0; audqcelp_in_flush(audio); audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS; rc = auddev_register_evt_listner(audio->device_events, AUDDEV_CLNT_ENC, audio->enc_id, qcelp_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; 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 audqcelp_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"); 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; } rc = audqcelp_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; } break; } case AUDIO_STOP: { rc = audqcelp_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); audqcelp_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_QCELP_ENC_CONFIG: { if (copy_to_user((void *) arg, &audio->cfg, sizeof(audio->cfg))) rc = -EFAULT; break; } case AUDIO_SET_QCELP_ENC_CONFIG: { struct msm_audio_qcelp_enc_config cfg; if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) { rc = -EFAULT; break; } MM_DBG("0X%8x, 0x%8x, 0x%8x\n", cfg.min_bit_rate, \ cfg.max_bit_rate, cfg.cdma_rate); if (cfg.min_bit_rate > CDMA_RATE_FULL || \ cfg.min_bit_rate < CDMA_RATE_EIGHTH) { MM_ERR("invalid min bitrate\n"); rc = -EFAULT; break; } if (cfg.max_bit_rate > CDMA_RATE_FULL || \ cfg.max_bit_rate < CDMA_RATE_EIGHTH) { MM_ERR("invalid max bitrate\n"); rc = -EFAULT; break; } /* Recording Does not support Erase and Blank */ if (cfg.cdma_rate > CDMA_RATE_FULL || cfg.cdma_rate < CDMA_RATE_EIGHTH) { MM_ERR("invalid qcelp cdma rate\n"); rc = -EFAULT; break; } memcpy(&audio->cfg, &cfg, sizeof(cfg)); 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 audqcelp_in_open(struct inode *inode, struct file *file) { struct audio_in *audio = &the_audio_qcelp_in; int rc; int encid; MM_DBG("\n"); mutex_lock(&audio->lock); if (audio->opened) { rc = -EBUSY; goto done; } 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_V13K | audio->mode; audio->cfg.cdma_rate = CDMA_RATE_FULL; audio->cfg.min_bit_rate = CDMA_RATE_FULL; audio->cfg.max_bit_rate = CDMA_RATE_FULL; audio->source = INTERNAL_CODEC_TX_SOURCE_MIX_MASK; audio->rec_mode = VOC_REC_UPLINK; 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_qcelp_adsp_ops, audio); if (rc) { audpreproc_aenc_free(audio->enc_id); goto done; } audio->stopped = 0; audio->source = 0; #ifdef CONFIG_SH_AUDIO_DRIVER audio->readbreak = 0; #endif /* CONFIG_SH_AUDIO_DRIVER */ audqcelp_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, qcelp_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; 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; }