예제 #1
0
파일: soc-compress.c 프로젝트: mdamt/linux
static int soc_compr_set_params(struct snd_compr_stream *cstream,
					struct snd_compr_params *params)
{
	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
	struct snd_soc_platform *platform = rtd->platform;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	int ret = 0;

	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

	/* first we call set_params for the platform driver
	 * this should configure the soc side
	 * if the machine has compressed ops then we call that as well
	 * expectation is that platform and machine will configure everything
	 * for this compress path, like configuring pcm port for codec
	 */
	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
		ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
		if (ret < 0)
			goto err;
	}

	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
		ret = platform->driver->compr_ops->set_params(cstream, params);
		if (ret < 0)
			goto err;
	}

	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
		ret = rtd->dai_link->compr_ops->set_params(cstream);
		if (ret < 0)
			goto err;
	}

	if (cstream->direction == SND_COMPRESS_PLAYBACK)
		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
					SND_SOC_DAPM_STREAM_START);
	else
		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
					SND_SOC_DAPM_STREAM_START);

	/* cancel any delayed stream shutdown that is pending */
	rtd->pop_wait = 0;
	mutex_unlock(&rtd->pcm_mutex);

	cancel_delayed_work_sync(&rtd->delayed_work);

	return ret;

err:
	mutex_unlock(&rtd->pcm_mutex);
	return ret;
}
예제 #2
0
static int soc_compr_free(struct snd_compr_stream *cstream)
{
    struct snd_soc_pcm_runtime *rtd = cstream->private_data;
    struct snd_soc_platform *platform = rtd->platform;
    struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    struct snd_soc_dai *codec_dai = rtd->codec_dai;
    int stream;

    mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

    if (cstream->direction == SND_COMPRESS_PLAYBACK)
        stream = SNDRV_PCM_STREAM_PLAYBACK;
    else
        stream = SNDRV_PCM_STREAM_CAPTURE;

    snd_soc_runtime_deactivate(rtd, stream);

    snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);

    if (!cpu_dai->active)
        cpu_dai->rate = 0;

    if (!codec_dai->active)
        codec_dai->rate = 0;


    if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
        rtd->dai_link->compr_ops->shutdown(cstream);

    if (platform->driver->compr_ops && platform->driver->compr_ops->free)
        platform->driver->compr_ops->free(cstream);

    if (cstream->direction == SND_COMPRESS_PLAYBACK) {
        if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
            snd_soc_dapm_stream_event(rtd,
                                      SNDRV_PCM_STREAM_PLAYBACK,
                                      SND_SOC_DAPM_STREAM_STOP);
        } else {
            rtd->pop_wait = 1;
            queue_delayed_work(system_power_efficient_wq,
                               &rtd->delayed_work,
                               msecs_to_jiffies(rtd->pmdown_time));
        }
    } else {
        /* capture streams can be powered down now */
        snd_soc_dapm_stream_event(rtd,
                                  SNDRV_PCM_STREAM_CAPTURE,
                                  SND_SOC_DAPM_STREAM_STOP);
    }

    mutex_unlock(&rtd->pcm_mutex);
    return 0;
}
예제 #3
0
static int soc_compr_set_params(struct snd_compr_stream *cstream,
					struct snd_compr_params *params)
{
	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
	struct snd_soc_platform *platform = rtd->platform;
	int ret = 0;

	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

	/* first we call set_params for the platform driver
	 * this should configure the soc side
	 * if the machine has compressed ops then we call that as well
	 * expectation is that platform and machine will configure everything
	 * for this compress path, like configuring pcm port for codec
	 */
	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
		ret = platform->driver->compr_ops->set_params(cstream, params);
		if (ret < 0)
			goto out;
	}

	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
		ret = rtd->dai_link->compr_ops->set_params(cstream);
		if (ret < 0)
			goto out;
	}

	snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
				SND_SOC_DAPM_STREAM_START);

out:
	mutex_unlock(&rtd->pcm_mutex);
	return ret;
}
예제 #4
0
파일: soc-pcm.c 프로젝트: CSCLOG/beaglebone
/*
 * Called by ALSA when a PCM substream is closed. Private data can be
 * freed here. The cpu DAI, codec DAI, machine and platform are also
 * shutdown.
 */
static int soc_pcm_close(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_platform *platform = rtd->platform;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_codec *codec = rtd->codec;

	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		cpu_dai->playback_active--;
		codec_dai->playback_active--;
	} else {
		cpu_dai->capture_active--;
		codec_dai->capture_active--;
	}

	cpu_dai->active--;
	codec_dai->active--;
	codec->active--;

	if (!cpu_dai->active && !codec_dai->active)
		rtd->rate = 0;

	/* Muting the DAC suppresses artifacts caused during digital
	 * shutdown, for example from stopping clocks.
	 */
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		snd_soc_dai_digital_mute(codec_dai, 1);

	if (cpu_dai->driver->ops->shutdown)
		cpu_dai->driver->ops->shutdown(substream, cpu_dai);

	if (codec_dai->driver->ops->shutdown)
		codec_dai->driver->ops->shutdown(substream, codec_dai);

	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
		rtd->dai_link->ops->shutdown(substream);

	if (platform->driver->ops && platform->driver->ops->close)
		platform->driver->ops->close(substream);
	cpu_dai->runtime = NULL;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/* start delayed pop wq here for playback streams */
		codec_dai->pop_wait = 1;
		schedule_delayed_work(&rtd->delayed_work,
			msecs_to_jiffies(rtd->pmdown_time));
	} else {
		/* capture streams can be powered down now */
		snd_soc_dapm_stream_event(rtd,
			codec_dai->driver->capture.stream_name,
			SND_SOC_DAPM_STREAM_STOP);
	}

	mutex_unlock(&rtd->pcm_mutex);
	return 0;
}
예제 #5
0
/* pay attention: application should lock the route set period. */
static int bb_control_put(struct snd_kcontrol *kcontrol,
		struct snd_ctl_elem_value *ucontrol)
{
	unsigned short reg;
	struct snd_soc_codec *codec = wm9713_dai[WM9713_DAI_PCM_VOICE].codec;

	if (bb_enable == 1 && ucontrol->value.integer.value[0] == 0)
		printk(KERN_INFO "Disable BB!!\n");

	if (bb_enable == 0 && ucontrol->value.integer.value[0] == 1) {
		printk(KERN_INFO "Enable BB!!\n");

		snd_soc_dapm_stream_event(codec, "Voice Playback",
			SND_SOC_DAPM_STREAM_START);
		snd_soc_dapm_stream_event(codec, "Voice Capture",
			SND_SOC_DAPM_STREAM_START);
		/*enable VRA mode*/
		codec->write(codec, AC97_EXTENDED_STATUS, 0x1);
		codec->write(codec, AC97_PCM_LR_ADC_RATE, 0x1F40);
		codec->write(codec, AC97_EXTENDED_MID,
			codec->read(codec, AC97_EXTENDED_MID)&0xffc3);
		codec->write(codec, AC97_EXTENDED_MSTATUS,
			codec->read(codec, AC97_EXTENDED_MSTATUS)&0xf9f5);
		codec->write(codec, AC97_POWERDOWN, 0);
		codec->write(codec, AC97_HANDSET_RATE, 0x0f80);
		schedule_timeout_interruptible(msecs_to_jiffies(10));
		codec->write(codec, AC97_CENTER_LFE_MASTER, 0xa8b3);
		reg = codec->read(codec, AC97_GPIO_CFG);
		reg |= (0x1<<1);
		reg |= (0x1<<3);
		reg |= (0x1<<4);
		reg &= ~(0x1<<5);
		codec->write(codec, AC97_GPIO_CFG, reg);
		schedule_timeout_interruptible(msecs_to_jiffies(10));
	}
	bb_enable = ucontrol->value.integer.value[0];
	return 0;
}
예제 #6
0
파일: zoom2.c 프로젝트: kapoloclubs/diana
static int zoom2_set_capture_state(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	int ret;

	if (zoom2_capture_state == ucontrol->value.integer.value[0])
		return 0;

	if (ucontrol->value.integer.value[0]) {
		ret = snd_soc_dapm_stream_event(g_rtd, 1, "Capture",
			SND_SOC_DAPM_STREAM_START);
	} else {
	       ret = snd_soc_dapm_stream_event(g_rtd, 1, "Capture",
			SND_SOC_DAPM_STREAM_STOP);
	}

	if (ret != 0) {
		printk(KERN_ERR "failed to set capture state\n");
		return 0;
	}

	zoom2_capture_state = ucontrol->value.integer.value[0];
	return 1;
}
예제 #7
0
/*
 * Power down the audio subsystem pmdown_time msecs after close is called.
 * This is to ensure there are no pops or clicks in between any music tracks
 * due to DAPM power cycling.
 */
static void close_delayed_work(struct work_struct *work)
{
	struct snd_soc_pcm_runtime *rtd =
			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
	struct snd_soc_dai *codec_dai = rtd->codec_dai;

	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

	dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
		 codec_dai->driver->playback.stream_name,
		 codec_dai->playback_active ? "active" : "inactive",
		 rtd->pop_wait ? "yes" : "no");

	/* are we waiting on this codec DAI stream */
	if (rtd->pop_wait == 1) {
		rtd->pop_wait = 0;
		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
					  SND_SOC_DAPM_STREAM_STOP);
	}

	mutex_unlock(&rtd->pcm_mutex);
}
예제 #8
0
static int soc_compr_set_params(struct snd_compr_stream *cstream,
					struct snd_compr_params *params)
{
	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
	struct snd_soc_platform *platform = rtd->platform;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	int ret = 0;

	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
		ret = platform->driver->compr_ops->set_params(cstream, params);
		if (ret < 0)
			goto err;
	}

	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
		ret = rtd->dai_link->compr_ops->set_params(cstream);
		if (ret < 0)
			goto err;
	}

	snd_soc_dapm_stream_event(rtd,
				codec_dai->driver->playback.stream_name,
				SND_SOC_DAPM_STREAM_START);

	
	codec_dai->pop_wait = 0;
	mutex_unlock(&rtd->pcm_mutex);

	cancel_delayed_work_sync(&rtd->delayed_work);

	return ret;

err:
	mutex_unlock(&rtd->pcm_mutex);
	return ret;
}
예제 #9
0
/*
 * Called by ALSA when the PCM substream is prepared, can set format, sample
 * rate, etc.  This function is non atomic and can be called multiple times,
 * it can refer to the runtime info.
 */
static int soc_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_platform *platform = rtd->platform;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	int ret = 0;

	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

	if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
		ret = rtd->dai_link->ops->prepare(substream);
		if (ret < 0) {
			pr_err("asoc: machine prepare error: %d\n", ret);
			goto out;
		}
	}

	if (platform->driver->ops && platform->driver->ops->prepare) {
		ret = platform->driver->ops->prepare(substream);
		if (ret < 0) {
			dev_err(platform->dev, "platform prepare error: %d\n",
				ret);
			goto out;
		}
	}

	if (codec_dai->driver->ops->prepare) {
		ret = codec_dai->driver->ops->prepare(substream, codec_dai);
		if (ret < 0) {
			dev_err(codec_dai->dev, "DAI prepare error: %d\n",
				ret);
			goto out;
		}
	}

	if (cpu_dai->driver->ops->prepare) {
		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
		if (ret < 0) {
			dev_err(cpu_dai->dev, "DAI prepare error: %d\n",
				ret);
			goto out;
		}
	}

	/* cancel any delayed stream shutdown that is pending */
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
	    codec_dai->pop_wait) {
		codec_dai->pop_wait = 0;
		cancel_delayed_work(&rtd->delayed_work);
	}

	snd_soc_dapm_stream_event(rtd, substream->stream, codec_dai,
				  SND_SOC_DAPM_STREAM_START);

	snd_soc_dai_digital_mute(codec_dai, 0);

out:
	mutex_unlock(&rtd->pcm_mutex);
	return ret;
}
예제 #10
0
파일: zoom2.c 프로젝트: kapoloclubs/diana
static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_codec *codec = rtd->codec;
	unsigned short reg;
	int     ret = 0;

	/* Enable voice interface */
	reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF);
	reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
	codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);

	/* hifi state */

	ret = snd_soc_dapm_stream_event(rtd,
			1,
			"Capture",
			SND_SOC_DAPM_STREAM_START);

	/* voice state */
	/* this is not dynamic, so ignore dir */
	ret = snd_soc_dapm_stream_event(rtd,
			1,
			"TWL4030 Voice",
			SND_SOC_DAPM_STREAM_START);

		/* Enable voice digital filters */
	snd_soc_update_bits(codec, TWL4030_REG_OPTION,
			TWL4030_ARXL1_VRX_EN, 0x10);

	ret = snd_soc_dapm_stream_event(rtd,
			1,
			"TWL4030 Voice",
			SND_SOC_DAPM_STREAM_START);

	/* reinit defaults */

	snd_soc_update_bits(codec, 1, 1, 0);
	snd_soc_update_bits(codec, 17, 63, 50);
	snd_soc_update_bits(codec, 16, 63, 50);

	snd_soc_update_bits(codec, 19, 63, 45);
	snd_soc_update_bits(codec, 18, 63, 45);

	snd_soc_update_bits(codec, 17, 192, 128);
	snd_soc_update_bits(codec, 16, 192, 128);
	snd_soc_update_bits(codec, 19, 192, 128);
	snd_soc_update_bits(codec, 18, 192, 128);

	snd_soc_update_bits(codec, 25, 248, 0);
	snd_soc_update_bits(codec, 26, 248, 0);

	snd_soc_update_bits(codec, 27, 248, 32);
	snd_soc_update_bits(codec, 28, 248, 32);

	snd_soc_update_bits(codec, 25, 2, 0);
	snd_soc_update_bits(codec, 26, 2, 0);
	snd_soc_update_bits(codec, 27, 2, 2);
	snd_soc_update_bits(codec, 28, 2, 2);

	snd_soc_update_bits(codec, 20, 63, 36);

	snd_soc_update_bits(codec, 68, 2, 0);

	snd_soc_update_bits(codec, 37, 48, 16);
	snd_soc_update_bits(codec, 37, 48, 16);

	snd_soc_update_bits(codec, 38, 48, 16);

	snd_soc_update_bits(codec, 35, 15, 5);

	snd_soc_update_bits(codec, 39, 48, 16);
	snd_soc_update_bits(codec, 40, 48, 16);

	snd_soc_update_bits(codec, 33, 48, 16);

	snd_soc_update_bits(codec, 10, 31, 23);
	snd_soc_update_bits(codec, 11, 31, 23);
	snd_soc_update_bits(codec, 12, 31, 23);
	snd_soc_update_bits(codec, 13, 31, 23);

	snd_soc_update_bits(codec, 72, 63, 27);

	snd_soc_update_bits(codec, 7, 4, 0);

	snd_soc_update_bits(codec, 36, 28, 12);

	snd_soc_update_bits(codec, 69, 32, 0);
	snd_soc_update_bits(codec, 69, 2, 0);

	return 0;
}
예제 #11
0
/*
 * Called by ALSA when a PCM substream is closed. Private data can be
 * freed here. The cpu DAI, codec DAI, machine and platform are also
 * shutdown.
 */
static int soc_pcm_close(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_platform *platform = rtd->platform;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_codec *codec = rtd->codec;

	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		cpu_dai->playback_active--;
		codec_dai->playback_active--;
	} else {
		cpu_dai->capture_active--;
		codec_dai->capture_active--;
	}

	cpu_dai->active--;
	codec_dai->active--;
	codec->active--;

	/* clear the corresponding DAIs rate when inactive */
	if (!cpu_dai->active)
		cpu_dai->rate = 0;

	if (!codec_dai->active)
		codec_dai->rate = 0;

	/* Muting the DAC suppresses artifacts caused during digital
	 * shutdown, for example from stopping clocks.
	 */
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
				&& !codec_dai->playback_active)
		snd_soc_dai_digital_mute(codec_dai, 1);

	if (cpu_dai->driver->ops->shutdown)
		cpu_dai->driver->ops->shutdown(substream, cpu_dai);

	if (codec_dai->driver->ops->shutdown
				&& !codec_dai->playback_active)
		codec_dai->driver->ops->shutdown(substream, codec_dai);

	if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
		rtd->dai_link->ops->shutdown(substream);

	if (platform->driver->ops && platform->driver->ops->close)
		platform->driver->ops->close(substream);
	cpu_dai->runtime = NULL;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
		!codec_dai->playback_active) {
		if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
		    rtd->dai_link->ignore_pmdown_time) {
			/* powered down playback stream now */
			snd_soc_dapm_stream_event(rtd,
					  SNDRV_PCM_STREAM_PLAYBACK,
					  codec_dai,
					  SND_SOC_DAPM_STREAM_STOP);
		} else {
			/* start delayed pop wq here for playback streams */
			codec_dai->pop_wait = 1;
			queue_delayed_work(system_power_efficient_wq,
					   &rtd->delayed_work,
					   msecs_to_jiffies(rtd->pmdown_time));
		}
	} else {
		/* capture streams can be powered down now */
		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
				  codec_dai, SND_SOC_DAPM_STREAM_STOP);
	}

	mutex_unlock(&rtd->pcm_mutex);

	pm_runtime_put(platform->dev);
	pm_runtime_put(codec_dai->dev);
	pm_runtime_put(cpu_dai->dev);

	return 0;
}