static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct msm_audio *prtd = runtime->private_data; struct audmgr_config cfg; int rc; prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream); prtd->pcm_count = snd_pcm_lib_period_bytes(substream); prtd->pcm_irq_pos = 0; prtd->pcm_buf_pos = 0; /* rate and channels are sent to audio driver */ prtd->samp_rate = convert_samp_rate(runtime->rate); prtd->samp_rate_index = convert_dsp_samp_index(runtime->rate); prtd->channel_mode = (runtime->channels - 1); prtd->buffer_size = prtd->channel_mode ? STEREO_DATA_SIZE : \ MONO_DATA_SIZE; if (prtd->enabled == 1) return 0; prtd->type = AUDREC_CMD_TYPE_0_INDEX_WAV; cfg.tx_rate = convert_samp_rate(runtime->rate); cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE; cfg.def_method = RPC_AUD_DEF_METHOD_RECORD; cfg.codec = RPC_AUD_DEF_CODEC_PCM; cfg.snd_method = RPC_SND_METHOD_MIDI; rc = audmgr_enable(&prtd->audmgr, &cfg); if (rc < 0) return rc; if (msm_adsp_enable(prtd->audpre)) { audmgr_disable(&prtd->audmgr); return -ENODEV; } if (msm_adsp_enable(prtd->audrec)) { msm_adsp_disable(prtd->audpre); audmgr_disable(&prtd->audmgr); return -ENODEV; } prtd->enabled = 1; alsa_rec_dsp_enable(prtd, 1); return 0; }
static long audio_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct audio_in *audio = file->private_data; int rc; if (cmd == AUDIO_GET_STATS) { struct msm_audio_stats stats; memset(&stats, 0, sizeof(stats)); stats.byte_count = atomic_read(&audio->in_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_in_enable(audio); break; case AUDIO_STOP: rc = audio_in_disable(audio); 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); audio_flush(audio); mutex_unlock(&audio->read_lock); } case AUDIO_SET_CONFIG: { struct msm_audio_config cfg; /* The below code is to make mutual exclusive between * AUDIO_SET_CONFIG and AUDIO_SET_STREAM_CONFIG. * Allow any one IOCTL. */ if (audio->buffer_cfg_ioctl == AUDIO_SET_STREAM_CONFIG) { rc = -EINVAL; break; } if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) { rc = -EFAULT; break; } if (cfg.channel_count == 1) { cfg.channel_count = AUDREC_CMD_STEREO_MODE_MONO; } else if (cfg.channel_count == 2) { cfg.channel_count = AUDREC_CMD_STEREO_MODE_STEREO; } else { rc = -EINVAL; break; } if (cfg.type == 0) { cfg.type = AUDREC_CMD_TYPE_0_INDEX_WAV; } else if (cfg.type == 1) { cfg.type = AUDREC_CMD_TYPE_0_INDEX_AAC; } else { rc = -EINVAL; break; } audio->samp_rate = convert_samp_rate(cfg.sample_rate); audio->samp_rate_index = convert_dsp_samp_index(cfg.sample_rate); audio->channel_mode = cfg.channel_count; audio->buffer_size = audio->channel_mode ? STEREO_DATA_SIZE : MONO_DATA_SIZE; audio->type = cfg.type; audio->buffer_cfg_ioctl = AUDIO_SET_CONFIG; rc = 0; break; } case AUDIO_GET_CONFIG: { struct msm_audio_config cfg; cfg.buffer_size = audio->buffer_size; cfg.buffer_count = FRAME_NUM; cfg.sample_rate = convert_samp_index(audio->samp_rate); if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO) cfg.channel_count = 1; else cfg.channel_count = 2; if (audio->type == AUDREC_CMD_TYPE_0_INDEX_WAV) cfg.type = 0; else cfg.type = 1; cfg.unused[0] = 0; cfg.unused[1] = 0; cfg.unused[2] = 0; if (copy_to_user((void *) arg, &cfg, sizeof(cfg))) rc = -EFAULT; else rc = 0; break; } case AUDIO_GET_STREAM_CONFIG: { struct msm_audio_stream_config cfg; cfg.buffer_size = audio->buffer_size; cfg.buffer_count = FRAME_NUM; if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) rc = -EFAULT; else rc = 0; break; } case AUDIO_SET_STREAM_CONFIG: { struct msm_audio_stream_config cfg; /* The below code is to make mutual exclusive between * AUDIO_SET_CONFIG and AUDIO_SET_STREAM_CONFIG. * Allow any one IOCTL. */ if (audio->buffer_cfg_ioctl == AUDIO_SET_CONFIG) { rc = -EINVAL; break; } if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { rc = -EFAULT; break; } else rc = 0; audio->buffer_size = cfg.buffer_size; /* The IOCTL is only of AAC, set the encoder as AAC */ audio->type = 1; audio->buffer_cfg_ioctl = AUDIO_SET_STREAM_CONFIG; break; } case AUDIO_GET_AAC_ENC_CONFIG: { struct msm_audio_aac_enc_config cfg; if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO) cfg.channels = 1; else cfg.channels = 2; cfg.sample_rate = convert_samp_index(audio->samp_rate); cfg.bit_rate = audio->bit_rate; cfg.stream_format = AUDIO_AAC_FORMAT_RAW; if (copy_to_user((void *)arg, &cfg, sizeof(cfg))) rc = -EFAULT; else rc = 0; break; } case AUDIO_SET_AAC_ENC_CONFIG: { struct msm_audio_aac_enc_config cfg; unsigned int record_quality; if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) { rc = -EFAULT; break; } if (cfg.stream_format != AUDIO_AAC_FORMAT_RAW) { MM_ERR("unsupported AAC format\n"); rc = -EINVAL; break; } record_quality = bitrate_to_record_quality(cfg.sample_rate, cfg.channels, cfg.bit_rate); /* Range of Record Quality Supported by DSP, Q12 format */ if ((record_quality < 0x800) || (record_quality > 0x4000)) { MM_ERR("Unsupported bit rate \n"); rc = -EINVAL; break; } if (cfg.channels == 1) { cfg.channels = AUDREC_CMD_STEREO_MODE_MONO; } else if (cfg.channels == 2) { cfg.channels = AUDREC_CMD_STEREO_MODE_STEREO; } else { rc = -EINVAL; break; } audio->samp_rate = convert_samp_rate(cfg.sample_rate); audio->samp_rate_index = convert_dsp_samp_index(cfg.sample_rate); audio->channel_mode = cfg.channels; audio->bit_rate = cfg.bit_rate; audio->record_quality = record_quality; MM_DBG(" Record Quality = 0x%8x \n", audio->record_quality); rc = 0; break; } default: rc = -EINVAL; } mutex_unlock(&audio->lock); return rc; }
static long audpcm_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); if (copy_to_user((void *) arg, &stats, sizeof(stats))) return -EFAULT; return 0; } mutex_lock(&audio->lock); switch (cmd) { case AUDIO_START: { rc = audpcm_in_enable(audio); audio->stopped = 0; break; } case AUDIO_STOP: rc = audpcm_in_disable(audio); 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); audpcm_in_flush(audio); mutex_unlock(&audio->read_lock); } 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_STEREO_MODE_MONO; } else if (cfg.channel_count == 2) { cfg.channel_count = AUDREC_CMD_STEREO_MODE_STEREO; } else { rc = -EINVAL; break; } audio->samp_rate = convert_samp_rate(cfg.sample_rate); audio->samp_rate_index = convert_dsp_samp_index(cfg.sample_rate); audio->channel_mode = cfg.channel_count; audio->buffer_size = audio->channel_mode ? STEREO_DATA_SIZE : MONO_DATA_SIZE; break; } case AUDIO_GET_CONFIG: { struct msm_audio_config cfg; cfg.buffer_size = audio->buffer_size; cfg.buffer_count = FRAME_NUM; cfg.sample_rate = convert_samp_index(audio->samp_rate); if (audio->channel_mode == AUDREC_CMD_STEREO_MODE_MONO) cfg.channel_count = 1; else cfg.channel_count = 2; cfg.type = 0; cfg.unused[0] = 0; cfg.unused[1] = 0; cfg.unused[2] = 0; if (copy_to_user((void *) arg, &cfg, sizeof(cfg))) rc = -EFAULT; break; } default: rc = -EINVAL; } mutex_unlock(&audio->lock); return rc; }