Exemplo n.º 1
0
static int skl_pcm_prepare(struct snd_pcm_substream *substream,
		struct snd_soc_dai *dai)
{
	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
	struct skl *skl = get_skl_ctx(dai->dev);
	unsigned int format_val;
	int err;
	struct skl_module_cfg *mconfig;

	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);

	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);

	format_val = skl_get_format(substream, dai);
	dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n",
				hdac_stream(stream)->stream_tag, format_val);
	snd_hdac_stream_reset(hdac_stream(stream));

	/* In case of XRUN recovery, reset the FW pipe to clean state */
	if (mconfig && (substream->runtime->status->state ==
					SNDRV_PCM_STATE_XRUN))
		skl_reset_pipe(skl->skl_sst, mconfig->pipe);

	err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
	if (err < 0)
		return err;

	err = snd_hdac_stream_setup(hdac_stream(stream));
	if (err < 0)
		return err;

	hdac_stream(stream)->prepared = 1;

	return err;
}
Exemplo n.º 2
0
static int skl_be_prepare(struct snd_pcm_substream *substream,
		struct snd_soc_dai *dai)
{
	struct skl *skl = get_skl_ctx(dai->dev);
	struct skl_sst *ctx = skl->skl_sst;
	struct skl_module_cfg *mconfig;

	if (dai->playback_widget->power || dai->capture_widget->power)
		return 0;

	mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
	if (mconfig == NULL)
		return -EINVAL;

	return skl_dsp_set_dma_control(ctx, mconfig);
}
Exemplo n.º 3
0
static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
		struct snd_soc_dai *dai)
{
	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
	struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
	struct hdac_ext_stream *link_dev =
			snd_soc_dai_get_dma_data(dai, substream);
	unsigned int format_val = 0;
	struct skl_dma_params *dma_params;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct hdac_ext_link *link;
	struct skl *skl = get_skl_ctx(dai->dev);
	struct skl_module_cfg *mconfig = NULL;

	dma_params  = (struct skl_dma_params *)
			snd_soc_dai_get_dma_data(codec_dai, substream);
	if (dma_params)
		format_val = dma_params->format;
	dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d codec_dai_name=%s\n",
			hdac_stream(link_dev)->stream_tag, format_val, codec_dai->name);

	link = snd_hdac_ext_bus_get_link(ebus, rtd->codec->component.name);
	if (!link)
		return -EINVAL;

	snd_hdac_ext_link_stream_reset(link_dev);

	/* In case of XRUN recovery, reset the FW pipe to clean state */
	mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
	if (mconfig && (substream->runtime->status->state ==
					SNDRV_PCM_STATE_XRUN))
		skl_reset_pipe(skl->skl_sst, mconfig->pipe);

	snd_hdac_ext_link_stream_setup(link_dev, format_val);

	snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag);
	link_dev->link_prepared = 1;

	return 0;
}
Exemplo n.º 4
0
static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
			struct skl_module_cfg *mconfig,
			struct skl_cpr_cfg *cpr_mconfig)
{
	u32 dma_io_buf;
	struct skl_module_res *res;
	int res_idx = mconfig->res_idx;
	struct skl *skl = get_skl_ctx(ctx->dev);

	cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig);

	if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) {
		cpr_mconfig->cpr_feature_mask = 0;
		return;
	}

	if (skl->nr_modules) {
		res = &mconfig->module->resources[mconfig->res_idx];
		cpr_mconfig->gtw_cfg.dma_buffer_size = res->dma_buffer_size;
		goto skip_buf_size_calc;
	} else {
		res = &mconfig->module->resources[res_idx];
	}

	switch (mconfig->hw_conn_type) {
	case SKL_CONN_SOURCE:
		if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
			dma_io_buf =  res->ibs;
		else
			dma_io_buf =  res->obs;
		break;

	case SKL_CONN_SINK:
		if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
			dma_io_buf =  res->obs;
		else
			dma_io_buf =  res->ibs;
		break;

	default:
		dev_warn(ctx->dev, "wrong connection type: %d\n",
				mconfig->hw_conn_type);
		return;
	}

	cpr_mconfig->gtw_cfg.dma_buffer_size =
				mconfig->dma_buffer_size * dma_io_buf;

	/* fallback to 2ms default value */
	if (!cpr_mconfig->gtw_cfg.dma_buffer_size) {
		if (mconfig->hw_conn_type == SKL_CONN_SOURCE)
			cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->obs;
		else
			cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->ibs;
	}

skip_buf_size_calc:
	cpr_mconfig->cpr_feature_mask = 0;
	cpr_mconfig->gtw_cfg.config_length  = 0;

	skl_copy_copier_caps(mconfig, cpr_mconfig);
}
Exemplo n.º 5
0
static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
		struct snd_soc_dai *dai)
{
	struct skl *skl = get_skl_ctx(dai->dev);
	struct skl_sst *ctx = skl->skl_sst;
	struct skl_module_cfg *mconfig;
	struct hdac_ext_bus *ebus = get_bus_ctx(substream);
	struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
	struct snd_soc_dapm_widget *w;
	int ret;

	mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
	if (!mconfig)
		return -EIO;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		w = dai->playback_widget;
	else
		w = dai->capture_widget;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_RESUME:
		if (!w->ignore_suspend) {
			skl_pcm_prepare(substream, dai);
			/*
			 * enable DMA Resume enable bit for the stream, set the
			 * dpib & lpib position to resume before starting the
			 * DMA
			 */
			snd_hdac_ext_stream_drsm_enable(ebus, true,
						hdac_stream(stream)->index);
			snd_hdac_ext_stream_set_dpibr(ebus, stream,
							stream->dpib);
			snd_hdac_ext_stream_set_lpib(stream, stream->lpib);
		}

	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		/*
		 * Start HOST DMA and Start FE Pipe.This is to make sure that
		 * there are no underrun/overrun in the case when the FE
		 * pipeline is started but there is a delay in starting the
		 * DMA channel on the host.
		 */
		snd_hdac_ext_stream_decouple(ebus, stream, true);
		ret = skl_decoupled_trigger(substream, cmd);
		if (ret < 0)
			return ret;
		return skl_run_pipe(ctx, mconfig->pipe);
		break;

	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_STOP:
		/*
		 * Stop FE Pipe first and stop DMA. This is to make sure that
		 * there are no underrun/overrun in the case if there is a delay
		 * between the two operations.
		 */
		ret = skl_stop_pipe(ctx, mconfig->pipe);
		if (ret < 0)
			return ret;

		ret = skl_decoupled_trigger(substream, cmd);
		if ((cmd == SNDRV_PCM_TRIGGER_SUSPEND) && !w->ignore_suspend) {
			/* save the dpib and lpib positions */
			stream->dpib = readl(ebus->bus.remap_addr +
					AZX_REG_VS_SDXDPIB_XBASE +
					(AZX_REG_VS_SDXDPIB_XINTERVAL *
					hdac_stream(stream)->index));

			stream->lpib = snd_hdac_stream_get_pos_lpib(
							hdac_stream(stream));
			snd_hdac_ext_stream_decouple(ebus, stream, false);
		}
		break;

	default:
		return -EINVAL;
	}

	return 0;
}