Unverified Commit b6c508b4 authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Mark Brown
Browse files

ASoC: SOF: Intel: hda-dai: add DMIC support

parent a8338e76
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -237,6 +237,36 @@ static unsigned int generic_calc_stream_format(struct snd_sof_dev *sdev,
	return format_val;
}

static unsigned int dmic_calc_stream_format(struct snd_sof_dev *sdev,
					    struct snd_pcm_substream *substream,
					    struct snd_pcm_hw_params *params)
{
	unsigned int format_val;
	snd_pcm_format_t format;
	unsigned int channels;
	unsigned int width;

	channels = params_channels(params);
	format = params_format(params);
	width = params_physical_width(params);

	if (format == SNDRV_PCM_FORMAT_S16_LE) {
		format = SNDRV_PCM_FORMAT_S32_LE;
		channels /= 2;
		width = 32;
	}

	format_val = snd_hdac_calc_stream_format(params_rate(params), channels,
						 format,
						 width,
						 0);

	dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
		params_rate(params), channels, format);

	return format_val;
}

static struct hdac_ext_link *ssp_get_hlink(struct snd_sof_dev *sdev,
					   struct snd_pcm_substream *substream)
{
@@ -245,6 +275,14 @@ static struct hdac_ext_link *ssp_get_hlink(struct snd_sof_dev *sdev,
	return hdac_bus_eml_ssp_get_hlink(bus);
}

static struct hdac_ext_link *dmic_get_hlink(struct snd_sof_dev *sdev,
					    struct snd_pcm_substream *substream)
{
	struct hdac_bus *bus = sof_to_bus(sdev);

	return hdac_bus_eml_dmic_get_hlink(bus);
}

static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
				struct snd_pcm_substream *substream, int cmd)
{
@@ -402,6 +440,19 @@ static const struct hda_dai_widget_dma_ops ssp_ipc4_dma_ops = {
	.get_hlink = ssp_get_hlink,
};

static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops = {
	.get_hext_stream = hda_ipc4_get_hext_stream,
	.assign_hext_stream = hda_assign_hext_stream,
	.release_hext_stream = hda_release_hext_stream,
	.setup_hext_stream = hda_setup_hext_stream,
	.reset_hext_stream = hda_reset_hext_stream,
	.pre_trigger = hda_ipc4_pre_trigger,
	.trigger = hda_trigger,
	.post_trigger = hda_ipc4_post_trigger,
	.calc_stream_format = dmic_calc_stream_format,
	.get_hlink = dmic_get_hlink,
};

static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = {
	.get_hext_stream = hda_get_hext_stream,
	.assign_hext_stream = hda_assign_hext_stream,
@@ -523,6 +574,10 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg
			if (chip->hw_ip_version < SOF_INTEL_ACE_2_0)
				return NULL;
			return &ssp_ipc4_dma_ops;
		case SOF_DAI_INTEL_DMIC:
			if (chip->hw_ip_version < SOF_INTEL_ACE_2_0)
				return NULL;
			return &dmic_ipc4_dma_ops;
		default:
			break;
		}
+24 −0
Original line number Diff line number Diff line
@@ -422,6 +422,13 @@ static const struct snd_soc_dai_ops ssp_dai_ops = {
	.prepare = non_hda_dai_prepare,
};

static const struct snd_soc_dai_ops dmic_dai_ops = {
	.hw_params = non_hda_dai_hw_params,
	.hw_free = hda_dai_hw_free,
	.trigger = hda_dai_trigger,
	.prepare = non_hda_dai_prepare,
};

static int hda_dai_suspend(struct hdac_bus *bus)
{
	struct snd_soc_pcm_runtime *rtd;
@@ -491,9 +498,25 @@ static void ssp_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops
	}
}

static void dmic_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
{
	const struct sof_intel_dsp_desc *chip;
	int i;

	chip = get_chip_info(sdev->pdata);

	if (chip->hw_ip_version >= SOF_INTEL_ACE_2_0) {
		for (i = 0; i < ops->num_drv; i++) {
			if (strstr(ops->drv[i].name, "DMIC"))
				ops->drv[i].ops = &dmic_dai_ops;
		}
	}
}

#else

static inline void ssp_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) {}
static inline void dmic_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) {}

#endif /* CONFIG_SND_SOC_SOF_HDA_LINK */

@@ -511,6 +534,7 @@ void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
	}

	ssp_set_dai_drv_ops(sdev, ops);
	dmic_set_dai_drv_ops(sdev, ops);

	if (sdev->pdata->ipc_type == SOF_INTEL_IPC4 && !hda_use_tplg_nhlt) {
		struct sof_ipc4_fw_data *ipc4_data = sdev->private;