Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
0
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;
}