static int auda2dp_in_release(struct inode *inode, struct file *file) { struct audio_a2dp_in *audio = file->private_data; mutex_lock(&audio->lock); /* 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); /*reset the sampling frequency information at audpreproc layer*/ audio->session_info.sampling_freq = 0; audpreproc_update_audrec_info(&audio->session_info); auda2dp_in_disable(audio); auda2dp_in_flush(audio); msm_adsp_put(audio->audrec); audpreproc_aenc_free(audio->enc_id); audio->audrec = NULL; audio->opened = 0; if (audio->data) { msm_subsystem_unmap_buffer(audio->msm_map); free_contiguous_memory_by_paddr(audio->phys); audio->data = NULL; } mutex_unlock(&audio->lock); return 0; }
static int auda2dp_in_release(struct inode *inode, struct file *file) { struct audio_a2dp_in *audio = file->private_data; mutex_lock(&audio->lock); /* 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); auda2dp_in_disable(audio); auda2dp_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 auda2dp_in_open(struct inode *inode, struct file *file) { struct audio_a2dp_in *audio = &the_audio_a2dp_in; int rc; int encid; mutex_lock(&audio->lock); if (audio->opened) { rc = -EBUSY; goto done; } audio->phys = allocate_contiguous_ebi_nomap(DMASZ, SZ_4K); if (audio->phys) { audio->msm_map = msm_subsystem_map_buffer( audio->phys, DMASZ, MSM_SUBSYSTEM_MAP_KADDR, NULL, 0); if (IS_ERR(audio->msm_map)) { MM_ERR("could not map the phys address to kernel" "space\n"); rc = -ENOMEM; free_contiguous_memory_by_paddr(audio->phys); goto done; } audio->data = (u8 *)audio->msm_map->vaddr; } else { MM_ERR("could not allocate DMA buffers\n"); rc = -ENOMEM; goto done; } 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/SBC_ENC_CONFIG, * but at least we need to have initial config */ audio->channel_mode = AUDREC_CMD_MODE_MONO; audio->buffer_size = FRAME_SIZE_SBC; audio->samp_rate = 48000; audio->enc_type = ENC_TYPE_SBC | audio->mode; audio->cfg.bit_allocation = AUDIO_SBC_BA_SNR; audio->cfg.mode = AUDIO_SBC_MODE_JSTEREO; audio->cfg.number_of_subbands = AUDIO_SBC_BANDS_8; audio->cfg.number_of_blocks = AUDIO_SBC_BLOCKS_16; audio->cfg.bit_rate = 320000; /* max 512kbps(mono), 320kbs(others) */ 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; auda2dp_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, a2dp_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; 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 auda2dp_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct audio_a2dp_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; /* Poll at 48KHz always */ 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 sample rate requested %d\n", freq, audio->samp_rate); 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; audio->session_info.sampling_freq = audio->samp_rate; audpreproc_update_audrec_info(&audio->session_info); rc = auda2dp_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; msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX, AUDDEV_CLNT_ENC); MM_DBG("msm_snddev_withdraw_freq\n"); } 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 = auda2dp_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; audio->abort = 0; 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); auda2dp_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 ((audio->enc_type == ENC_TYPE_SBC) && (cfg.buffer_size != FRAME_SIZE_SBC)) 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)); if (audio->enc_type == ENC_TYPE_SBC) cfg.buffer_size = FRAME_SIZE_SBC; else cfg.buffer_size = MONO_DATA_SIZE; cfg.buffer_count = FRAME_NUM; if (copy_to_user((void *) arg, &cfg, sizeof(cfg))) rc = -EFAULT; break; } case AUDIO_SET_SBC_ENC_CONFIG: { if (copy_from_user(&audio->cfg, (void *) arg, sizeof(audio->cfg))) { rc = -EFAULT; break; } audio->samp_rate = audio->cfg.sample_rate; audio->channel_mode = audio->cfg.channels; audio->enc_type = ENC_TYPE_SBC; break; } case AUDIO_SET_CONFIG: { struct msm_audio_config cfg; if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) { rc = -EFAULT; break; } if (cfg.channel_count == 1) { cfg.channel_count = AUDREC_CMD_MODE_MONO; audio->buffer_size = MONO_DATA_SIZE; } else if (cfg.channel_count == 2) { cfg.channel_count = AUDREC_CMD_MODE_STEREO; audio->buffer_size = STEREO_DATA_SIZE; } else { rc = -EINVAL; break; } audio->samp_rate = cfg.sample_rate; audio->channel_mode = cfg.channel_count; audio->enc_type = ENC_TYPE_WAV; break; } case AUDIO_GET_SBC_ENC_CONFIG: { struct msm_audio_sbc_enc_config cfg; memset(&cfg, 0, sizeof(cfg)); cfg.bit_allocation = audio->cfg.bit_allocation; cfg.mode = audio->cfg.mode; cfg.number_of_subbands = audio->cfg.number_of_subbands; cfg.number_of_blocks = audio->cfg.number_of_blocks; cfg.sample_rate = audio->samp_rate; cfg.channels = audio->channel_mode; cfg.bit_rate = audio->cfg.bit_rate; if (copy_to_user((void *) arg, &cfg, sizeof(cfg))) rc = -EFAULT; break; } case AUDIO_GET_CONFIG: { struct msm_audio_config cfg; memset(&cfg, 0, sizeof(cfg)); cfg.buffer_count = FRAME_NUM; cfg.sample_rate = audio->samp_rate; if (audio->channel_mode == AUDREC_CMD_MODE_MONO) { cfg.channel_count = 1; cfg.buffer_size = MONO_DATA_SIZE; } else { cfg.channel_count = 2; cfg.buffer_size = STEREO_DATA_SIZE; } cfg.type = ENC_TYPE_WAV; if (copy_to_user((void *) arg, &cfg, sizeof(cfg))) rc = -EFAULT; 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 auda2dp_in_open(struct inode *inode, struct file *file) { struct audio_a2dp_in *audio = &the_audio_a2dp_in; int rc; int encid; 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/SBC_ENC_CONFIG, * but at least we need to have initial config */ audio->channel_mode = AUDREC_CMD_MODE_MONO; audio->buffer_size = FRAME_SIZE_SBC; audio->samp_rate = 48000; audio->enc_type = ENC_TYPE_SBC | audio->mode; audio->cfg.bit_allocation = AUDIO_SBC_BA_SNR; audio->cfg.mode = AUDIO_SBC_MODE_JSTEREO; audio->cfg.number_of_subbands = AUDIO_SBC_BANDS_8; audio->cfg.number_of_blocks = AUDIO_SBC_BLOCKS_16; audio->cfg.bit_rate = 320000; /* max 512kbps(mono), 320kbs(others) */ 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; auda2dp_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, a2dp_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; }