cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pcm.c (32039B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2//
      3// Copyright(c) 2021-2022 Intel Corporation. All rights reserved.
      4//
      5// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
      6//          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
      7//
      8
      9#include <linux/debugfs.h>
     10#include <linux/device.h>
     11#include <sound/hda_register.h>
     12#include <sound/hdaudio_ext.h>
     13#include <sound/pcm_params.h>
     14#include <sound/soc-acpi.h>
     15#include <sound/soc-acpi-intel-match.h>
     16#include <sound/soc-component.h>
     17#include "avs.h"
     18#include "path.h"
     19#include "topology.h"
     20
     21struct avs_dma_data {
     22	struct avs_tplg_path_template *template;
     23	struct avs_path *path;
     24	/*
     25	 * link stream is stored within substream's runtime
     26	 * private_data to fulfill the needs of codec BE path
     27	 *
     28	 * host stream assigned
     29	 */
     30	struct hdac_ext_stream *host_stream;
     31};
     32
     33static struct avs_tplg_path_template *
     34avs_dai_find_path_template(struct snd_soc_dai *dai, bool is_fe, int direction)
     35{
     36	struct snd_soc_dapm_widget *dw;
     37	struct snd_soc_dapm_path *dp;
     38	enum snd_soc_dapm_direction dir;
     39
     40	if (direction == SNDRV_PCM_STREAM_CAPTURE) {
     41		dw = dai->capture_widget;
     42		dir = is_fe ? SND_SOC_DAPM_DIR_OUT : SND_SOC_DAPM_DIR_IN;
     43	} else {
     44		dw = dai->playback_widget;
     45		dir = is_fe ? SND_SOC_DAPM_DIR_IN : SND_SOC_DAPM_DIR_OUT;
     46	}
     47
     48	dp = list_first_entry_or_null(&dw->edges[dir], typeof(*dp), list_node[dir]);
     49	if (!dp)
     50		return NULL;
     51
     52	/* Get the other widget, with actual path template data */
     53	dw = (dp->source == dw) ? dp->sink : dp->source;
     54
     55	return dw->priv;
     56}
     57
     58static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, bool is_fe)
     59{
     60	struct avs_tplg_path_template *template;
     61	struct avs_dma_data *data;
     62
     63	template = avs_dai_find_path_template(dai, is_fe, substream->stream);
     64	if (!template) {
     65		dev_err(dai->dev, "no %s path for dai %s, invalid tplg?\n",
     66			snd_pcm_stream_str(substream), dai->name);
     67		return -EINVAL;
     68	}
     69
     70	data = kzalloc(sizeof(*data), GFP_KERNEL);
     71	if (!data)
     72		return -ENOMEM;
     73
     74	data->template = template;
     75	snd_soc_dai_set_dma_data(dai, substream, data);
     76
     77	return 0;
     78}
     79
     80static int avs_dai_hw_params(struct snd_pcm_substream *substream,
     81			     struct snd_pcm_hw_params *fe_hw_params,
     82			     struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai,
     83			     int dma_id)
     84{
     85	struct avs_dma_data *data;
     86	struct avs_path *path;
     87	struct avs_dev *adev = to_avs_dev(dai->dev);
     88	int ret;
     89
     90	data = snd_soc_dai_get_dma_data(dai, substream);
     91
     92	dev_dbg(dai->dev, "%s FE hw_params str %p rtd %p",
     93		__func__, substream, substream->runtime);
     94	dev_dbg(dai->dev, "rate %d chn %d vbd %d bd %d\n",
     95		params_rate(fe_hw_params), params_channels(fe_hw_params),
     96		params_width(fe_hw_params), params_physical_width(fe_hw_params));
     97
     98	dev_dbg(dai->dev, "%s BE hw_params str %p rtd %p",
     99		__func__, substream, substream->runtime);
    100	dev_dbg(dai->dev, "rate %d chn %d vbd %d bd %d\n",
    101		params_rate(be_hw_params), params_channels(be_hw_params),
    102		params_width(be_hw_params), params_physical_width(be_hw_params));
    103
    104	path = avs_path_create(adev, dma_id, data->template, fe_hw_params, be_hw_params);
    105	if (IS_ERR(path)) {
    106		ret = PTR_ERR(path);
    107		dev_err(dai->dev, "create path failed: %d\n", ret);
    108		return ret;
    109	}
    110
    111	data->path = path;
    112	return 0;
    113}
    114
    115static int avs_dai_be_hw_params(struct snd_pcm_substream *substream,
    116				struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai,
    117				int dma_id)
    118{
    119	struct snd_pcm_hw_params *fe_hw_params = NULL;
    120	struct snd_soc_pcm_runtime *fe, *be;
    121	struct snd_soc_dpcm *dpcm;
    122
    123	be = asoc_substream_to_rtd(substream);
    124	for_each_dpcm_fe(be, substream->stream, dpcm) {
    125		fe = dpcm->fe;
    126		fe_hw_params = &fe->dpcm[substream->stream].hw_params;
    127	}
    128
    129	return avs_dai_hw_params(substream, fe_hw_params, be_hw_params, dai, dma_id);
    130}
    131
    132static int avs_dai_prepare(struct avs_dev *adev, struct snd_pcm_substream *substream,
    133			   struct snd_soc_dai *dai)
    134{
    135	struct avs_dma_data *data;
    136	int ret;
    137
    138	data = snd_soc_dai_get_dma_data(dai, substream);
    139	if (!data->path)
    140		return 0;
    141
    142	ret = avs_path_reset(data->path);
    143	if (ret < 0) {
    144		dev_err(dai->dev, "reset path failed: %d\n", ret);
    145		return ret;
    146	}
    147
    148	ret = avs_path_pause(data->path);
    149	if (ret < 0)
    150		dev_err(dai->dev, "pause path failed: %d\n", ret);
    151	return ret;
    152}
    153
    154static int avs_dai_nonhda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    155{
    156	return avs_dai_startup(substream, dai, false);
    157}
    158
    159static void avs_dai_nonhda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    160{
    161	struct avs_dma_data *data;
    162
    163	data = snd_soc_dai_get_dma_data(dai, substream);
    164
    165	snd_soc_dai_set_dma_data(dai, substream, NULL);
    166	kfree(data);
    167}
    168
    169static int avs_dai_nonhda_be_hw_params(struct snd_pcm_substream *substream,
    170				       struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
    171{
    172	struct avs_dma_data *data;
    173
    174	data = snd_soc_dai_get_dma_data(dai, substream);
    175	if (data->path)
    176		return 0;
    177
    178	/* Actual port-id comes from topology. */
    179	return avs_dai_be_hw_params(substream, hw_params, dai, 0);
    180}
    181
    182static int avs_dai_nonhda_be_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    183{
    184	struct avs_dma_data *data;
    185
    186	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
    187
    188	data = snd_soc_dai_get_dma_data(dai, substream);
    189	if (data->path) {
    190		avs_path_free(data->path);
    191		data->path = NULL;
    192	}
    193
    194	return 0;
    195}
    196
    197static int avs_dai_nonhda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    198{
    199	return avs_dai_prepare(to_avs_dev(dai->dev), substream, dai);
    200}
    201
    202static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cmd,
    203				     struct snd_soc_dai *dai)
    204{
    205	struct avs_dma_data *data;
    206	int ret = 0;
    207
    208	data = snd_soc_dai_get_dma_data(dai, substream);
    209
    210	switch (cmd) {
    211	case SNDRV_PCM_TRIGGER_START:
    212	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    213		ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
    214		if (ret < 0)
    215			dev_err(dai->dev, "run BE path failed: %d\n", ret);
    216		break;
    217
    218	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    219	case SNDRV_PCM_TRIGGER_STOP:
    220		ret = avs_path_pause(data->path);
    221		if (ret < 0)
    222			dev_err(dai->dev, "pause BE path failed: %d\n", ret);
    223
    224		if (cmd == SNDRV_PCM_TRIGGER_STOP) {
    225			ret = avs_path_reset(data->path);
    226			if (ret < 0)
    227				dev_err(dai->dev, "reset BE path failed: %d\n", ret);
    228		}
    229		break;
    230
    231	default:
    232		ret = -EINVAL;
    233		break;
    234	}
    235
    236	return ret;
    237}
    238
    239static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = {
    240	.startup = avs_dai_nonhda_be_startup,
    241	.shutdown = avs_dai_nonhda_be_shutdown,
    242	.hw_params = avs_dai_nonhda_be_hw_params,
    243	.hw_free = avs_dai_nonhda_be_hw_free,
    244	.prepare = avs_dai_nonhda_be_prepare,
    245	.trigger = avs_dai_nonhda_be_trigger,
    246};
    247
    248static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    249{
    250	return avs_dai_startup(substream, dai, false);
    251}
    252
    253static void avs_dai_hda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    254{
    255	return avs_dai_nonhda_be_shutdown(substream, dai);
    256}
    257
    258static int avs_dai_hda_be_hw_params(struct snd_pcm_substream *substream,
    259				    struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
    260{
    261	struct avs_dma_data *data;
    262	struct hdac_ext_stream *link_stream;
    263
    264	data = snd_soc_dai_get_dma_data(dai, substream);
    265	if (data->path)
    266		return 0;
    267
    268	link_stream = substream->runtime->private_data;
    269
    270	return avs_dai_be_hw_params(substream, hw_params, dai,
    271				    hdac_stream(link_stream)->stream_tag - 1);
    272}
    273
    274static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    275{
    276	struct avs_dma_data *data;
    277	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
    278	struct hdac_ext_stream *link_stream;
    279	struct hdac_ext_link *link;
    280	struct hda_codec *codec;
    281
    282	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
    283
    284	data = snd_soc_dai_get_dma_data(dai, substream);
    285	if (!data->path)
    286		return 0;
    287
    288	link_stream = substream->runtime->private_data;
    289	link_stream->link_prepared = false;
    290	avs_path_free(data->path);
    291	data->path = NULL;
    292
    293	/* clear link <-> stream mapping */
    294	codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev);
    295	link = snd_hdac_ext_bus_link_at(&codec->bus->core, codec->core.addr);
    296	if (!link)
    297		return -EINVAL;
    298
    299	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    300		snd_hdac_ext_link_clear_stream_id(link, hdac_stream(link_stream)->stream_tag);
    301
    302	return 0;
    303}
    304
    305static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    306{
    307	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
    308	struct snd_pcm_runtime *runtime = substream->runtime;
    309	struct hdac_ext_stream *link_stream = runtime->private_data;
    310	struct hdac_ext_link *link;
    311	struct hda_codec *codec;
    312	struct hdac_bus *bus;
    313	unsigned int format_val;
    314	int ret;
    315
    316	if (link_stream->link_prepared)
    317		return 0;
    318
    319	codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev);
    320	bus = &codec->bus->core;
    321	format_val = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format,
    322						 runtime->sample_bits, 0);
    323
    324	snd_hdac_ext_stream_decouple(bus, link_stream, true);
    325	snd_hdac_ext_link_stream_reset(link_stream);
    326	snd_hdac_ext_link_stream_setup(link_stream, format_val);
    327
    328	link = snd_hdac_ext_bus_link_at(bus, codec->core.addr);
    329	if (!link)
    330		return -EINVAL;
    331
    332	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    333		snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_stream)->stream_tag);
    334
    335	ret = avs_dai_prepare(to_avs_dev(dai->dev), substream, dai);
    336	if (ret)
    337		return ret;
    338
    339	link_stream->link_prepared = true;
    340	return 0;
    341}
    342
    343static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd,
    344				  struct snd_soc_dai *dai)
    345{
    346	struct hdac_ext_stream *link_stream;
    347	struct avs_dma_data *data;
    348	int ret = 0;
    349
    350	dev_dbg(dai->dev, "entry %s cmd=%d\n", __func__, cmd);
    351
    352	data = snd_soc_dai_get_dma_data(dai, substream);
    353	link_stream = substream->runtime->private_data;
    354
    355	switch (cmd) {
    356	case SNDRV_PCM_TRIGGER_START:
    357	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    358		snd_hdac_ext_link_stream_start(link_stream);
    359
    360		ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
    361		if (ret < 0)
    362			dev_err(dai->dev, "run BE path failed: %d\n", ret);
    363		break;
    364
    365	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    366	case SNDRV_PCM_TRIGGER_STOP:
    367		ret = avs_path_pause(data->path);
    368		if (ret < 0)
    369			dev_err(dai->dev, "pause BE path failed: %d\n", ret);
    370
    371		snd_hdac_ext_link_stream_clear(link_stream);
    372
    373		if (cmd == SNDRV_PCM_TRIGGER_STOP) {
    374			ret = avs_path_reset(data->path);
    375			if (ret < 0)
    376				dev_err(dai->dev, "reset BE path failed: %d\n", ret);
    377		}
    378		break;
    379
    380	default:
    381		ret = -EINVAL;
    382		break;
    383	}
    384
    385	return ret;
    386}
    387
    388static const struct snd_soc_dai_ops avs_dai_hda_be_ops = {
    389	.startup = avs_dai_hda_be_startup,
    390	.shutdown = avs_dai_hda_be_shutdown,
    391	.hw_params = avs_dai_hda_be_hw_params,
    392	.hw_free = avs_dai_hda_be_hw_free,
    393	.prepare = avs_dai_hda_be_prepare,
    394	.trigger = avs_dai_hda_be_trigger,
    395};
    396
    397static const unsigned int rates[] = {
    398	8000, 11025, 12000, 16000,
    399	22050, 24000, 32000, 44100,
    400	48000, 64000, 88200, 96000,
    401	128000, 176400, 192000,
    402};
    403
    404static const struct snd_pcm_hw_constraint_list hw_rates = {
    405	.count = ARRAY_SIZE(rates),
    406	.list = rates,
    407	.mask = 0,
    408};
    409
    410static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    411{
    412	struct snd_pcm_runtime *runtime = substream->runtime;
    413	struct avs_dma_data *data;
    414	struct avs_dev *adev = to_avs_dev(dai->dev);
    415	struct hdac_bus *bus = &adev->base.core;
    416	struct hdac_ext_stream *host_stream;
    417	int ret;
    418
    419	ret = avs_dai_startup(substream, dai, true);
    420	if (ret)
    421		return ret;
    422
    423	data = snd_soc_dai_get_dma_data(dai, substream);
    424
    425	host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST);
    426	if (!host_stream) {
    427		kfree(data);
    428		return -EBUSY;
    429	}
    430
    431	data->host_stream = host_stream;
    432	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
    433	/* avoid wrap-around with wall-clock */
    434	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
    435	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates);
    436	snd_pcm_set_sync(substream);
    437
    438	dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p",
    439		__func__, hdac_stream(host_stream)->stream_tag, substream);
    440
    441	return 0;
    442}
    443
    444static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    445{
    446	struct avs_dma_data *data;
    447
    448	data = snd_soc_dai_get_dma_data(dai, substream);
    449
    450	snd_soc_dai_set_dma_data(dai, substream, NULL);
    451	snd_hdac_ext_stream_release(data->host_stream, HDAC_EXT_STREAM_TYPE_HOST);
    452	kfree(data);
    453}
    454
    455static int avs_dai_fe_hw_params(struct snd_pcm_substream *substream,
    456				struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
    457{
    458	struct snd_pcm_hw_params *be_hw_params = NULL;
    459	struct snd_soc_pcm_runtime *fe, *be;
    460	struct snd_soc_dpcm *dpcm;
    461	struct avs_dma_data *data;
    462	struct hdac_ext_stream *host_stream;
    463	int ret;
    464
    465	data = snd_soc_dai_get_dma_data(dai, substream);
    466	if (data->path)
    467		return 0;
    468
    469	host_stream = data->host_stream;
    470
    471	hdac_stream(host_stream)->bufsize = 0;
    472	hdac_stream(host_stream)->period_bytes = 0;
    473	hdac_stream(host_stream)->format_val = 0;
    474
    475	fe = asoc_substream_to_rtd(substream);
    476	for_each_dpcm_be(fe, substream->stream, dpcm) {
    477		be = dpcm->be;
    478		be_hw_params = &be->dpcm[substream->stream].hw_params;
    479	}
    480
    481	ret = avs_dai_hw_params(substream, hw_params, be_hw_params, dai,
    482				hdac_stream(host_stream)->stream_tag - 1);
    483	if (ret)
    484		goto create_err;
    485
    486	ret = avs_path_bind(data->path);
    487	if (ret < 0) {
    488		dev_err(dai->dev, "bind FE <-> BE failed: %d\n", ret);
    489		goto bind_err;
    490	}
    491
    492	return 0;
    493
    494bind_err:
    495	avs_path_free(data->path);
    496	data->path = NULL;
    497create_err:
    498	snd_pcm_lib_free_pages(substream);
    499	return ret;
    500}
    501
    502static int avs_dai_fe_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    503{
    504	struct avs_dma_data *data;
    505	struct hdac_ext_stream *host_stream;
    506	int ret;
    507
    508	dev_dbg(dai->dev, "%s fe HW_FREE str %p rtd %p",
    509		__func__, substream, substream->runtime);
    510
    511	data = snd_soc_dai_get_dma_data(dai, substream);
    512	if (!data->path)
    513		return 0;
    514
    515	host_stream = data->host_stream;
    516
    517	ret = avs_path_unbind(data->path);
    518	if (ret < 0)
    519		dev_err(dai->dev, "unbind FE <-> BE failed: %d\n", ret);
    520
    521	avs_path_free(data->path);
    522	data->path = NULL;
    523	snd_hdac_stream_cleanup(hdac_stream(host_stream));
    524	hdac_stream(host_stream)->prepared = false;
    525
    526	ret = snd_pcm_lib_free_pages(substream);
    527	if (ret < 0)
    528		dev_dbg(dai->dev, "Failed to free pages!\n");
    529
    530	return ret;
    531}
    532
    533static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
    534{
    535	struct snd_pcm_runtime *runtime = substream->runtime;
    536	struct avs_dma_data *data;
    537	struct avs_dev *adev = to_avs_dev(dai->dev);
    538	struct hdac_ext_stream *host_stream;
    539	struct hdac_bus *bus;
    540	unsigned int format_val;
    541	int ret;
    542
    543	data = snd_soc_dai_get_dma_data(dai, substream);
    544	host_stream = data->host_stream;
    545
    546	if (hdac_stream(host_stream)->prepared)
    547		return 0;
    548
    549	bus = hdac_stream(host_stream)->bus;
    550	snd_hdac_ext_stream_decouple(bus, data->host_stream, true);
    551	snd_hdac_stream_reset(hdac_stream(host_stream));
    552
    553	format_val = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format,
    554						 runtime->sample_bits, 0);
    555
    556	ret = snd_hdac_stream_set_params(hdac_stream(host_stream), format_val);
    557	if (ret < 0)
    558		return ret;
    559
    560	ret = snd_hdac_stream_setup(hdac_stream(host_stream));
    561	if (ret < 0)
    562		return ret;
    563
    564	ret = avs_dai_prepare(adev, substream, dai);
    565	if (ret)
    566		return ret;
    567
    568	hdac_stream(host_stream)->prepared = true;
    569	return 0;
    570}
    571
    572static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
    573{
    574	struct avs_dma_data *data;
    575	struct hdac_ext_stream *host_stream;
    576	struct hdac_bus *bus;
    577	unsigned long flags;
    578	int ret = 0;
    579
    580	data = snd_soc_dai_get_dma_data(dai, substream);
    581	host_stream = data->host_stream;
    582	bus = hdac_stream(host_stream)->bus;
    583
    584	switch (cmd) {
    585	case SNDRV_PCM_TRIGGER_START:
    586	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    587		spin_lock_irqsave(&bus->reg_lock, flags);
    588		snd_hdac_stream_start(hdac_stream(host_stream), true);
    589		spin_unlock_irqrestore(&bus->reg_lock, flags);
    590
    591		ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
    592		if (ret < 0)
    593			dev_err(dai->dev, "run FE path failed: %d\n", ret);
    594		break;
    595
    596	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    597	case SNDRV_PCM_TRIGGER_STOP:
    598		ret = avs_path_pause(data->path);
    599		if (ret < 0)
    600			dev_err(dai->dev, "pause FE path failed: %d\n", ret);
    601
    602		spin_lock_irqsave(&bus->reg_lock, flags);
    603		snd_hdac_stream_stop(hdac_stream(host_stream));
    604		spin_unlock_irqrestore(&bus->reg_lock, flags);
    605
    606		if (cmd == SNDRV_PCM_TRIGGER_STOP) {
    607			ret = avs_path_reset(data->path);
    608			if (ret < 0)
    609				dev_err(dai->dev, "reset FE path failed: %d\n", ret);
    610		}
    611		break;
    612
    613	default:
    614		ret = -EINVAL;
    615		break;
    616	}
    617
    618	return ret;
    619}
    620
    621const struct snd_soc_dai_ops avs_dai_fe_ops = {
    622	.startup = avs_dai_fe_startup,
    623	.shutdown = avs_dai_fe_shutdown,
    624	.hw_params = avs_dai_fe_hw_params,
    625	.hw_free = avs_dai_fe_hw_free,
    626	.prepare = avs_dai_fe_prepare,
    627	.trigger = avs_dai_fe_trigger,
    628};
    629
    630static ssize_t topology_name_read(struct file *file, char __user *user_buf, size_t count,
    631				  loff_t *ppos)
    632{
    633	struct snd_soc_component *component = file->private_data;
    634	struct snd_soc_card *card = component->card;
    635	struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev);
    636	char buf[64];
    637	size_t len;
    638
    639	len = snprintf(buf, sizeof(buf), "%s/%s\n", component->driver->topology_name_prefix,
    640		       mach->tplg_filename);
    641
    642	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    643}
    644
    645static const struct file_operations topology_name_fops = {
    646	.open = simple_open,
    647	.read = topology_name_read,
    648	.llseek = default_llseek,
    649};
    650
    651static int avs_component_load_libraries(struct avs_soc_component *acomp)
    652{
    653	struct avs_tplg *tplg = acomp->tplg;
    654	struct avs_dev *adev = to_avs_dev(acomp->base.dev);
    655	int ret;
    656
    657	if (!tplg->num_libs)
    658		return 0;
    659
    660	/* Parent device may be asleep and library loading involves IPCs. */
    661	ret = pm_runtime_resume_and_get(adev->dev);
    662	if (ret < 0)
    663		return ret;
    664
    665	avs_hda_clock_gating_enable(adev, false);
    666	avs_hda_l1sen_enable(adev, false);
    667
    668	ret = avs_dsp_load_libraries(adev, tplg->libs, tplg->num_libs);
    669
    670	avs_hda_l1sen_enable(adev, true);
    671	avs_hda_clock_gating_enable(adev, true);
    672
    673	if (!ret)
    674		ret = avs_module_info_init(adev, false);
    675
    676	pm_runtime_mark_last_busy(adev->dev);
    677	pm_runtime_put_autosuspend(adev->dev);
    678
    679	return ret;
    680}
    681
    682static int avs_component_probe(struct snd_soc_component *component)
    683{
    684	struct snd_soc_card *card = component->card;
    685	struct snd_soc_acpi_mach *mach;
    686	struct avs_soc_component *acomp;
    687	struct avs_dev *adev;
    688	char *filename;
    689	int ret;
    690
    691	dev_dbg(card->dev, "probing %s card %s\n", component->name, card->name);
    692	mach = dev_get_platdata(card->dev);
    693	acomp = to_avs_soc_component(component);
    694	adev = to_avs_dev(component->dev);
    695
    696	acomp->tplg = avs_tplg_new(component);
    697	if (!acomp->tplg)
    698		return -ENOMEM;
    699
    700	if (!mach->tplg_filename)
    701		goto finalize;
    702
    703	/* Load specified topology and create debugfs for it. */
    704	filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix,
    705			     mach->tplg_filename);
    706	if (!filename)
    707		return -ENOMEM;
    708
    709	ret = avs_load_topology(component, filename);
    710	kfree(filename);
    711	if (ret < 0)
    712		return ret;
    713
    714	ret = avs_component_load_libraries(acomp);
    715	if (ret < 0) {
    716		dev_err(card->dev, "libraries loading failed: %d\n", ret);
    717		goto err_load_libs;
    718	}
    719
    720finalize:
    721	debugfs_create_file("topology_name", 0444, component->debugfs_root, component,
    722			    &topology_name_fops);
    723
    724	mutex_lock(&adev->comp_list_mutex);
    725	list_add_tail(&acomp->node, &adev->comp_list);
    726	mutex_unlock(&adev->comp_list_mutex);
    727
    728	return 0;
    729
    730err_load_libs:
    731	avs_remove_topology(component);
    732	return ret;
    733}
    734
    735static void avs_component_remove(struct snd_soc_component *component)
    736{
    737	struct avs_soc_component *acomp = to_avs_soc_component(component);
    738	struct snd_soc_acpi_mach *mach;
    739	struct avs_dev *adev = to_avs_dev(component->dev);
    740	int ret;
    741
    742	mach = dev_get_platdata(component->card->dev);
    743
    744	mutex_lock(&adev->comp_list_mutex);
    745	list_del(&acomp->node);
    746	mutex_unlock(&adev->comp_list_mutex);
    747
    748	if (mach->tplg_filename) {
    749		ret = avs_remove_topology(component);
    750		if (ret < 0)
    751			dev_err(component->dev, "unload topology failed: %d\n", ret);
    752	}
    753}
    754
    755static int avs_component_open(struct snd_soc_component *component,
    756			      struct snd_pcm_substream *substream)
    757{
    758	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
    759	struct snd_pcm_hardware hwparams;
    760
    761	/* only FE DAI links are handled here */
    762	if (rtd->dai_link->no_pcm)
    763		return 0;
    764
    765	hwparams.info = SNDRV_PCM_INFO_MMAP |
    766			SNDRV_PCM_INFO_MMAP_VALID |
    767			SNDRV_PCM_INFO_INTERLEAVED |
    768			SNDRV_PCM_INFO_PAUSE |
    769			SNDRV_PCM_INFO_NO_PERIOD_WAKEUP;
    770
    771	hwparams.formats = SNDRV_PCM_FMTBIT_S16_LE |
    772			   SNDRV_PCM_FMTBIT_S24_LE |
    773			   SNDRV_PCM_FMTBIT_S32_LE;
    774	hwparams.period_bytes_min = 128;
    775	hwparams.period_bytes_max = AZX_MAX_BUF_SIZE / 2;
    776	hwparams.periods_min = 2;
    777	hwparams.periods_max = AZX_MAX_FRAG;
    778	hwparams.buffer_bytes_max = AZX_MAX_BUF_SIZE;
    779	hwparams.fifo_size = 0;
    780
    781	return snd_soc_set_runtime_hwparams(substream, &hwparams);
    782}
    783
    784static unsigned int avs_hda_stream_dpib_read(struct hdac_ext_stream *stream)
    785{
    786	return readl(hdac_stream(stream)->bus->remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
    787		     (AZX_REG_VS_SDXDPIB_XINTERVAL * hdac_stream(stream)->index));
    788}
    789
    790static snd_pcm_uframes_t
    791avs_component_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream)
    792{
    793	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
    794	struct avs_dma_data *data;
    795	struct hdac_ext_stream *host_stream;
    796	unsigned int pos;
    797
    798	data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
    799	if (!data->host_stream)
    800		return 0;
    801
    802	host_stream = data->host_stream;
    803	pos = avs_hda_stream_dpib_read(host_stream);
    804
    805	if (pos >= hdac_stream(host_stream)->bufsize)
    806		pos = 0;
    807
    808	return bytes_to_frames(substream->runtime, pos);
    809}
    810
    811static int avs_component_mmap(struct snd_soc_component *component,
    812			      struct snd_pcm_substream *substream,
    813			      struct vm_area_struct *vma)
    814{
    815	return snd_pcm_lib_default_mmap(substream, vma);
    816}
    817
    818#define MAX_PREALLOC_SIZE	(32 * 1024 * 1024)
    819
    820static int avs_component_construct(struct snd_soc_component *component,
    821				   struct snd_soc_pcm_runtime *rtd)
    822{
    823	struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
    824	struct snd_pcm *pcm = rtd->pcm;
    825
    826	if (dai->driver->playback.channels_min)
    827		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
    828					   SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
    829					   MAX_PREALLOC_SIZE);
    830
    831	if (dai->driver->capture.channels_min)
    832		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
    833					   SNDRV_DMA_TYPE_DEV_SG, component->dev, 0,
    834					   MAX_PREALLOC_SIZE);
    835
    836	return 0;
    837}
    838
    839static const struct snd_soc_component_driver avs_component_driver = {
    840	.name			= "avs-pcm",
    841	.probe			= avs_component_probe,
    842	.remove			= avs_component_remove,
    843	.open			= avs_component_open,
    844	.pointer		= avs_component_pointer,
    845	.mmap			= avs_component_mmap,
    846	.pcm_construct		= avs_component_construct,
    847	.module_get_upon_open	= 1, /* increment refcount when a pcm is opened */
    848	.topology_name_prefix	= "intel/avs",
    849	.non_legacy_dai_naming	= true,
    850};
    851
    852static int avs_soc_component_register(struct device *dev, const char *name,
    853				      const struct snd_soc_component_driver *drv,
    854				      struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais)
    855{
    856	struct avs_soc_component *acomp;
    857	int ret;
    858
    859	acomp = devm_kzalloc(dev, sizeof(*acomp), GFP_KERNEL);
    860	if (!acomp)
    861		return -ENOMEM;
    862
    863	ret = snd_soc_component_initialize(&acomp->base, drv, dev);
    864	if (ret < 0)
    865		return ret;
    866
    867	/* force name change after ASoC is done with its init */
    868	acomp->base.name = name;
    869	INIT_LIST_HEAD(&acomp->node);
    870
    871	return snd_soc_add_component(&acomp->base, cpu_dais, num_cpu_dais);
    872}
    873
    874static struct snd_soc_dai_driver dmic_cpu_dais[] = {
    875{
    876	.name = "DMIC Pin",
    877	.ops = &avs_dai_nonhda_be_ops,
    878	.capture = {
    879		.stream_name	= "DMIC Rx",
    880		.channels_min	= 1,
    881		.channels_max	= 4,
    882		.rates		= SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000,
    883		.formats	= SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
    884	},
    885},
    886{
    887	.name = "DMIC WoV Pin",
    888	.ops = &avs_dai_nonhda_be_ops,
    889	.capture = {
    890		.stream_name	= "DMIC WoV Rx",
    891		.channels_min	= 1,
    892		.channels_max	= 4,
    893		.rates		= SNDRV_PCM_RATE_16000,
    894		.formats	= SNDRV_PCM_FMTBIT_S16_LE,
    895	},
    896},
    897};
    898
    899int avs_dmic_platform_register(struct avs_dev *adev, const char *name)
    900{
    901	return avs_soc_component_register(adev->dev, name, &avs_component_driver, dmic_cpu_dais,
    902					  ARRAY_SIZE(dmic_cpu_dais));
    903}
    904
    905static const struct snd_soc_dai_driver i2s_dai_template = {
    906	.ops = &avs_dai_nonhda_be_ops,
    907	.playback = {
    908		.channels_min	= 1,
    909		.channels_max	= 8,
    910		.rates		= SNDRV_PCM_RATE_8000_192000 |
    911				  SNDRV_PCM_RATE_KNOT,
    912		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
    913				  SNDRV_PCM_FMTBIT_S24_LE |
    914				  SNDRV_PCM_FMTBIT_S32_LE,
    915	},
    916	.capture = {
    917		.channels_min	= 1,
    918		.channels_max	= 8,
    919		.rates		= SNDRV_PCM_RATE_8000_192000 |
    920				  SNDRV_PCM_RATE_KNOT,
    921		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
    922				  SNDRV_PCM_FMTBIT_S24_LE |
    923				  SNDRV_PCM_FMTBIT_S32_LE,
    924	},
    925};
    926
    927int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned long port_mask,
    928			      unsigned long *tdms)
    929{
    930	struct snd_soc_dai_driver *cpus, *dai;
    931	size_t ssp_count, cpu_count;
    932	int i, j;
    933
    934	ssp_count = adev->hw_cfg.i2s_caps.ctrl_count;
    935	cpu_count = hweight_long(port_mask);
    936	if (tdms)
    937		for_each_set_bit(i, &port_mask, ssp_count)
    938			cpu_count += hweight_long(tdms[i]);
    939
    940	cpus = devm_kzalloc(adev->dev, sizeof(*cpus) * cpu_count, GFP_KERNEL);
    941	if (!cpus)
    942		return -ENOMEM;
    943
    944	dai = cpus;
    945	for_each_set_bit(i, &port_mask, ssp_count) {
    946		memcpy(dai, &i2s_dai_template, sizeof(*dai));
    947
    948		dai->name =
    949			devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d Pin", i);
    950		dai->playback.stream_name =
    951			devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Tx", i);
    952		dai->capture.stream_name =
    953			devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d Rx", i);
    954
    955		if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
    956			return -ENOMEM;
    957		dai++;
    958	}
    959
    960	if (!tdms)
    961		goto plat_register;
    962
    963	for_each_set_bit(i, &port_mask, ssp_count) {
    964		for_each_set_bit(j, &tdms[i], ssp_count) {
    965			memcpy(dai, &i2s_dai_template, sizeof(*dai));
    966
    967			dai->name =
    968				devm_kasprintf(adev->dev, GFP_KERNEL, "SSP%d:%d Pin", i, j);
    969			dai->playback.stream_name =
    970				devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Tx", i, j);
    971			dai->capture.stream_name =
    972				devm_kasprintf(adev->dev, GFP_KERNEL, "ssp%d:%d Rx", i, j);
    973
    974			if (!dai->name || !dai->playback.stream_name || !dai->capture.stream_name)
    975				return -ENOMEM;
    976			dai++;
    977		}
    978	}
    979
    980plat_register:
    981	return avs_soc_component_register(adev->dev, name, &avs_component_driver, cpus, cpu_count);
    982}
    983
    984/* HD-Audio CPU DAI template */
    985static const struct snd_soc_dai_driver hda_cpu_dai = {
    986	.ops = &avs_dai_hda_be_ops,
    987	.playback = {
    988		.channels_min	= 1,
    989		.channels_max	= 8,
    990		.rates		= SNDRV_PCM_RATE_8000_192000,
    991		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
    992				  SNDRV_PCM_FMTBIT_S24_LE |
    993				  SNDRV_PCM_FMTBIT_S32_LE,
    994	},
    995	.capture = {
    996		.channels_min	= 1,
    997		.channels_max	= 8,
    998		.rates		= SNDRV_PCM_RATE_8000_192000,
    999		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
   1000				  SNDRV_PCM_FMTBIT_S24_LE |
   1001				  SNDRV_PCM_FMTBIT_S32_LE,
   1002	},
   1003};
   1004
   1005static void avs_component_hda_unregister_dais(struct snd_soc_component *component)
   1006{
   1007	struct snd_soc_acpi_mach *mach;
   1008	struct snd_soc_dai *dai, *save;
   1009	struct hda_codec *codec;
   1010	char name[32];
   1011
   1012	mach = dev_get_platdata(component->card->dev);
   1013	codec = mach->pdata;
   1014	sprintf(name, "%s-cpu", dev_name(&codec->core.dev));
   1015
   1016	for_each_component_dais_safe(component, dai, save) {
   1017		if (!strstr(dai->driver->name, name))
   1018			continue;
   1019
   1020		if (dai->playback_widget)
   1021			snd_soc_dapm_free_widget(dai->playback_widget);
   1022		if (dai->capture_widget)
   1023			snd_soc_dapm_free_widget(dai->capture_widget);
   1024		snd_soc_unregister_dai(dai);
   1025	}
   1026}
   1027
   1028static int avs_component_hda_probe(struct snd_soc_component *component)
   1029{
   1030	struct snd_soc_dapm_context *dapm;
   1031	struct snd_soc_dai_driver *dais;
   1032	struct snd_soc_acpi_mach *mach;
   1033	struct hda_codec *codec;
   1034	struct hda_pcm *pcm;
   1035	const char *cname;
   1036	int pcm_count = 0, ret, i;
   1037
   1038	mach = dev_get_platdata(component->card->dev);
   1039	if (!mach)
   1040		return -EINVAL;
   1041
   1042	codec = mach->pdata;
   1043	if (list_empty(&codec->pcm_list_head))
   1044		return -EINVAL;
   1045	list_for_each_entry(pcm, &codec->pcm_list_head, list)
   1046		pcm_count++;
   1047
   1048	dais = devm_kcalloc(component->dev, pcm_count, sizeof(*dais),
   1049			    GFP_KERNEL);
   1050	if (!dais)
   1051		return -ENOMEM;
   1052
   1053	cname = dev_name(&codec->core.dev);
   1054	dapm = snd_soc_component_get_dapm(component);
   1055	pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list);
   1056
   1057	for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) {
   1058		struct snd_soc_dai *dai;
   1059
   1060		memcpy(&dais[i], &hda_cpu_dai, sizeof(*dais));
   1061		dais[i].id = i;
   1062		dais[i].name = devm_kasprintf(component->dev, GFP_KERNEL,
   1063					      "%s-cpu%d", cname, i);
   1064		if (!dais[i].name) {
   1065			ret = -ENOMEM;
   1066			goto exit;
   1067		}
   1068
   1069		if (pcm->stream[0].substreams) {
   1070			dais[i].playback.stream_name =
   1071				devm_kasprintf(component->dev, GFP_KERNEL,
   1072					       "%s-cpu%d Tx", cname, i);
   1073			if (!dais[i].playback.stream_name) {
   1074				ret = -ENOMEM;
   1075				goto exit;
   1076			}
   1077		}
   1078
   1079		if (pcm->stream[1].substreams) {
   1080			dais[i].capture.stream_name =
   1081				devm_kasprintf(component->dev, GFP_KERNEL,
   1082					       "%s-cpu%d Rx", cname, i);
   1083			if (!dais[i].capture.stream_name) {
   1084				ret = -ENOMEM;
   1085				goto exit;
   1086			}
   1087		}
   1088
   1089		dai = snd_soc_register_dai(component, &dais[i], false);
   1090		if (!dai) {
   1091			dev_err(component->dev, "register dai for %s failed\n",
   1092				pcm->name);
   1093			ret = -EINVAL;
   1094			goto exit;
   1095		}
   1096
   1097		ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
   1098		if (ret < 0) {
   1099			dev_err(component->dev, "create widgets failed: %d\n",
   1100				ret);
   1101			goto exit;
   1102		}
   1103	}
   1104
   1105	ret = avs_component_probe(component);
   1106exit:
   1107	if (ret)
   1108		avs_component_hda_unregister_dais(component);
   1109
   1110	return ret;
   1111}
   1112
   1113static void avs_component_hda_remove(struct snd_soc_component *component)
   1114{
   1115	avs_component_hda_unregister_dais(component);
   1116	avs_component_remove(component);
   1117}
   1118
   1119static int avs_component_hda_open(struct snd_soc_component *component,
   1120				  struct snd_pcm_substream *substream)
   1121{
   1122	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
   1123	struct hdac_ext_stream *link_stream;
   1124	struct hda_codec *codec;
   1125
   1126	/* only BE DAI links are handled here */
   1127	if (!rtd->dai_link->no_pcm)
   1128		return avs_component_open(component, substream);
   1129
   1130	codec = dev_to_hda_codec(asoc_rtd_to_codec(rtd, 0)->dev);
   1131	link_stream = snd_hdac_ext_stream_assign(&codec->bus->core, substream,
   1132					     HDAC_EXT_STREAM_TYPE_LINK);
   1133	if (!link_stream)
   1134		return -EBUSY;
   1135
   1136	substream->runtime->private_data = link_stream;
   1137	return 0;
   1138}
   1139
   1140static int avs_component_hda_close(struct snd_soc_component *component,
   1141				   struct snd_pcm_substream *substream)
   1142{
   1143	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
   1144	struct hdac_ext_stream *link_stream;
   1145
   1146	/* only BE DAI links are handled here */
   1147	if (!rtd->dai_link->no_pcm)
   1148		return 0;
   1149
   1150	link_stream = substream->runtime->private_data;
   1151	snd_hdac_ext_stream_release(link_stream, HDAC_EXT_STREAM_TYPE_LINK);
   1152	substream->runtime->private_data = NULL;
   1153
   1154	return 0;
   1155}
   1156
   1157static const struct snd_soc_component_driver avs_hda_component_driver = {
   1158	.name			= "avs-hda-pcm",
   1159	.probe			= avs_component_hda_probe,
   1160	.remove			= avs_component_hda_remove,
   1161	.open			= avs_component_hda_open,
   1162	.close			= avs_component_hda_close,
   1163	.pointer		= avs_component_pointer,
   1164	.mmap			= avs_component_mmap,
   1165	.pcm_construct		= avs_component_construct,
   1166	/*
   1167	 * hda platform component's probe() is dependent on
   1168	 * codec->pcm_list_head, it needs to be initialized after codec
   1169	 * component. remove_order is here for completeness sake
   1170	 */
   1171	.probe_order		= SND_SOC_COMP_ORDER_LATE,
   1172	.remove_order		= SND_SOC_COMP_ORDER_EARLY,
   1173	.module_get_upon_open	= 1,
   1174	.topology_name_prefix	= "intel/avs",
   1175	.non_legacy_dai_naming	= true,
   1176};
   1177
   1178int avs_hda_platform_register(struct avs_dev *adev, const char *name)
   1179{
   1180	return avs_soc_component_register(adev->dev, name,
   1181					  &avs_hda_component_driver, NULL, 0);
   1182}