예제 #1
0
static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
				  struct snd_soc_dai *dai)
{
	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
	struct pm_qos_request *pm_qos_req = &mcpdm->pm_qos_req;
	int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
	int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
	int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
	int latency = mcpdm->latency[stream2];

	/* Prevent omap hardware from hitting off between FIFO fills */
	if (!latency || mcpdm->latency[stream1] < latency)
		latency = mcpdm->latency[stream1];

	if (pm_qos_request_active(pm_qos_req))
		pm_qos_update_request(pm_qos_req, latency);
	else if (latency)
		pm_qos_add_request(pm_qos_req, PM_QOS_CPU_DMA_LATENCY, latency);

	if (!omap_mcpdm_active(mcpdm)) {
		omap_mcpdm_start(mcpdm);
		omap_mcpdm_reg_dump(mcpdm);
	} else if (mcpdm->restart) {
		omap_mcpdm_stop(mcpdm);
		omap_mcpdm_start(mcpdm);
		mcpdm->restart = false;
		omap_mcpdm_reg_dump(mcpdm);
	}

	return 0;
}
예제 #2
0
static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
				  struct snd_soc_dai *dai)
{
	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
	int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
	int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
	int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;

	mutex_lock(&mcpdm->mutex);

	if (!dai->active) {
		if (omap_mcpdm_active(mcpdm)) {
			omap_mcpdm_stop(mcpdm);
			omap_mcpdm_close_streams(mcpdm);
			mcpdm->config[0].link_mask = 0;
			mcpdm->config[1].link_mask = 0;
		}
	}

	if (mcpdm->latency[stream2])
		pm_qos_update_request(&mcpdm->pm_qos_req,
				      mcpdm->latency[stream2]);
	else if (mcpdm->latency[stream1])
		pm_qos_remove_request(&mcpdm->pm_qos_req);

	mcpdm->latency[stream1] = 0;

	mutex_unlock(&mcpdm->mutex);
}
예제 #3
0
파일: omap-mcpdm.c 프로젝트: krzk/linux
static int omap_mcpdm_suspend(struct snd_soc_dai *dai)
{
	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);

	if (dai->active) {
		omap_mcpdm_stop(mcpdm);
		omap_mcpdm_close_streams(mcpdm);
	}

	mcpdm->pm_active_count = 0;
	while (pm_runtime_active(mcpdm->dev)) {
		pm_runtime_put_sync(mcpdm->dev);
		mcpdm->pm_active_count++;
	}

	return 0;
}
예제 #4
0
파일: omap-mcpdm.c 프로젝트: krzk/linux
static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
				  struct snd_soc_dai *dai)
{
	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);

	if (!omap_mcpdm_active(mcpdm)) {
		omap_mcpdm_start(mcpdm);
		omap_mcpdm_reg_dump(mcpdm);
	} else if (mcpdm->restart) {
		omap_mcpdm_stop(mcpdm);
		omap_mcpdm_start(mcpdm);
		mcpdm->restart = false;
		omap_mcpdm_reg_dump(mcpdm);
	}

	return 0;
}
예제 #5
0
파일: omap-mcpdm.c 프로젝트: krzk/linux
static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
				  struct snd_soc_dai *dai)
{
	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);

	mutex_lock(&mcpdm->mutex);

	if (!dai->active) {
		if (omap_mcpdm_active(mcpdm)) {
			omap_mcpdm_stop(mcpdm);
			omap_mcpdm_close_streams(mcpdm);
			mcpdm->config[0].link_mask = 0;
			mcpdm->config[1].link_mask = 0;
		}
	}

	mutex_unlock(&mcpdm->mutex);
}