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

lola_pcm.c (18058B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Support for Digigram Lola PCI-e boards
      4 *
      5 *  Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/init.h>
     10#include <linux/dma-mapping.h>
     11#include <linux/pci.h>
     12#include <linux/delay.h>
     13#include <sound/core.h>
     14#include <sound/pcm.h>
     15#include "lola.h"
     16
     17#define LOLA_MAX_BDL_ENTRIES	8
     18#define LOLA_MAX_BUF_SIZE	(1024*1024*1024)
     19#define LOLA_BDL_ENTRY_SIZE	(16 * 16)
     20
     21static struct lola_pcm *lola_get_pcm(struct snd_pcm_substream *substream)
     22{
     23	struct lola *chip = snd_pcm_substream_chip(substream);
     24	return &chip->pcm[substream->stream];
     25}
     26
     27static struct lola_stream *lola_get_stream(struct snd_pcm_substream *substream)
     28{
     29	struct lola_pcm *pcm = lola_get_pcm(substream);
     30	unsigned int idx = substream->number;
     31	return &pcm->streams[idx];
     32}
     33
     34static unsigned int lola_get_lrc(struct lola *chip)
     35{
     36	return lola_readl(chip, BAR1, LRC);
     37}
     38
     39static unsigned int lola_get_tstamp(struct lola *chip, bool quick_no_sync)
     40{
     41	unsigned int tstamp = lola_get_lrc(chip) >> 8;
     42	if (chip->granularity) {
     43		unsigned int wait_banks = quick_no_sync ? 0 : 8;
     44		tstamp += (wait_banks + 1) * chip->granularity - 1;
     45		tstamp -= tstamp % chip->granularity;
     46	}
     47	return tstamp << 8;
     48}
     49
     50/* clear any pending interrupt status */
     51static void lola_stream_clear_pending_irq(struct lola *chip,
     52					  struct lola_stream *str)
     53{
     54	unsigned int val = lola_dsd_read(chip, str->dsd, STS);
     55	val &= LOLA_DSD_STS_DESE | LOLA_DSD_STS_BCIS;
     56	if (val)
     57		lola_dsd_write(chip, str->dsd, STS, val);
     58}
     59
     60static void lola_stream_start(struct lola *chip, struct lola_stream *str,
     61			      unsigned int tstamp)
     62{
     63	lola_stream_clear_pending_irq(chip, str);
     64	lola_dsd_write(chip, str->dsd, CTL,
     65		       LOLA_DSD_CTL_SRUN |
     66		       LOLA_DSD_CTL_IOCE |
     67		       LOLA_DSD_CTL_DEIE |
     68		       LOLA_DSD_CTL_VLRCV |
     69		       tstamp);
     70}
     71
     72static void lola_stream_stop(struct lola *chip, struct lola_stream *str,
     73			     unsigned int tstamp)
     74{
     75	lola_dsd_write(chip, str->dsd, CTL,
     76		       LOLA_DSD_CTL_IOCE |
     77		       LOLA_DSD_CTL_DEIE |
     78		       LOLA_DSD_CTL_VLRCV |
     79		       tstamp);
     80	lola_stream_clear_pending_irq(chip, str);
     81}
     82
     83static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
     84{
     85	unsigned long end_time = jiffies + msecs_to_jiffies(200);
     86	while (time_before(jiffies, end_time)) {
     87		unsigned int val;
     88		val = lola_dsd_read(chip, str->dsd, CTL);
     89		if (!(val & LOLA_DSD_CTL_SRST))
     90			return;
     91		msleep(1);
     92	}
     93	dev_warn(chip->card->dev, "SRST not clear (stream %d)\n", str->dsd);
     94}
     95
     96static int lola_stream_wait_for_fifo(struct lola *chip,
     97				     struct lola_stream *str,
     98				     bool ready)
     99{
    100	unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0;
    101	unsigned long end_time = jiffies + msecs_to_jiffies(200);
    102	while (time_before(jiffies, end_time)) {
    103		unsigned int reg = lola_dsd_read(chip, str->dsd, STS);
    104		if ((reg & LOLA_DSD_STS_FIFORDY) == val)
    105			return 0;
    106		msleep(1);
    107	}
    108	dev_warn(chip->card->dev, "FIFO not ready (stream %d)\n", str->dsd);
    109	return -EIO;
    110}
    111
    112/* sync for FIFO ready/empty for all linked streams;
    113 * clear paused flag when FIFO gets ready again
    114 */
    115static int lola_sync_wait_for_fifo(struct lola *chip,
    116				   struct snd_pcm_substream *substream,
    117				   bool ready)
    118{
    119	unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0;
    120	unsigned long end_time = jiffies + msecs_to_jiffies(200);
    121	struct snd_pcm_substream *s;
    122	int pending = 0;
    123
    124	while (time_before(jiffies, end_time)) {
    125		pending = 0;
    126		snd_pcm_group_for_each_entry(s, substream) {
    127			struct lola_stream *str;
    128			if (s->pcm->card != substream->pcm->card)
    129				continue;
    130			str = lola_get_stream(s);
    131			if (str->prepared && str->paused) {
    132				unsigned int reg;
    133				reg = lola_dsd_read(chip, str->dsd, STS);
    134				if ((reg & LOLA_DSD_STS_FIFORDY) != val) {
    135					pending = str->dsd + 1;
    136					break;
    137				}
    138				if (ready)
    139					str->paused = 0;
    140			}
    141		}
    142		if (!pending)
    143			return 0;
    144		msleep(1);
    145	}
    146	dev_warn(chip->card->dev, "FIFO not ready (pending %d)\n", pending - 1);
    147	return -EIO;
    148}
    149
    150/* finish pause - prepare for a new resume */
    151static void lola_sync_pause(struct lola *chip,
    152			    struct snd_pcm_substream *substream)
    153{
    154	struct snd_pcm_substream *s;
    155
    156	lola_sync_wait_for_fifo(chip, substream, false);
    157	snd_pcm_group_for_each_entry(s, substream) {
    158		struct lola_stream *str;
    159		if (s->pcm->card != substream->pcm->card)
    160			continue;
    161		str = lola_get_stream(s);
    162		if (str->paused && str->prepared)
    163			lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRUN |
    164				       LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
    165	}
    166	lola_sync_wait_for_fifo(chip, substream, true);
    167}
    168
    169static void lola_stream_reset(struct lola *chip, struct lola_stream *str)
    170{
    171	if (str->prepared) {
    172		if (str->paused)
    173			lola_sync_pause(chip, str->substream);
    174		str->prepared = 0;
    175		lola_dsd_write(chip, str->dsd, CTL,
    176			       LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
    177		lola_stream_wait_for_fifo(chip, str, false);
    178		lola_stream_clear_pending_irq(chip, str);
    179		lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST);
    180		lola_dsd_write(chip, str->dsd, LVI, 0);
    181		lola_dsd_write(chip, str->dsd, BDPU, 0);
    182		lola_dsd_write(chip, str->dsd, BDPL, 0);
    183		wait_for_srst_clear(chip, str);
    184	}
    185}
    186
    187static const struct snd_pcm_hardware lola_pcm_hw = {
    188	.info =			(SNDRV_PCM_INFO_MMAP |
    189				 SNDRV_PCM_INFO_INTERLEAVED |
    190				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
    191				 SNDRV_PCM_INFO_MMAP_VALID |
    192				 SNDRV_PCM_INFO_PAUSE),
    193	.formats =		(SNDRV_PCM_FMTBIT_S16_LE |
    194				 SNDRV_PCM_FMTBIT_S24_LE |
    195				 SNDRV_PCM_FMTBIT_S32_LE |
    196				 SNDRV_PCM_FMTBIT_FLOAT_LE),
    197	.rates =		SNDRV_PCM_RATE_8000_192000,
    198	.rate_min =		8000,
    199	.rate_max =		192000,
    200	.channels_min =		1,
    201	.channels_max =		2,
    202	.buffer_bytes_max =	LOLA_MAX_BUF_SIZE,
    203	.period_bytes_min =	128,
    204	.period_bytes_max =	LOLA_MAX_BUF_SIZE / 2,
    205	.periods_min =		2,
    206	.periods_max =		LOLA_MAX_BDL_ENTRIES,
    207	.fifo_size =		0,
    208};
    209
    210static int lola_pcm_open(struct snd_pcm_substream *substream)
    211{
    212	struct lola *chip = snd_pcm_substream_chip(substream);
    213	struct lola_pcm *pcm = lola_get_pcm(substream);
    214	struct lola_stream *str = lola_get_stream(substream);
    215	struct snd_pcm_runtime *runtime = substream->runtime;
    216
    217	mutex_lock(&chip->open_mutex);
    218	if (str->opened) {
    219		mutex_unlock(&chip->open_mutex);
    220		return -EBUSY;
    221	}
    222	str->substream = substream;
    223	str->master = NULL;
    224	str->opened = 1;
    225	runtime->hw = lola_pcm_hw;
    226	runtime->hw.channels_max = pcm->num_streams - str->index;
    227	if (chip->sample_rate) {
    228		/* sample rate is locked */
    229		runtime->hw.rate_min = chip->sample_rate;
    230		runtime->hw.rate_max = chip->sample_rate;
    231	} else {
    232		runtime->hw.rate_min = chip->sample_rate_min;
    233		runtime->hw.rate_max = chip->sample_rate_max;
    234	}
    235	chip->ref_count_rate++;
    236	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
    237	/* period size = multiple of chip->granularity (8, 16 or 32 frames)*/
    238	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
    239				   chip->granularity);
    240	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
    241				   chip->granularity);
    242	mutex_unlock(&chip->open_mutex);
    243	return 0;
    244}
    245
    246static void lola_cleanup_slave_streams(struct lola_pcm *pcm,
    247				       struct lola_stream *str)
    248{
    249	int i;
    250	for (i = str->index + 1; i < pcm->num_streams; i++) {
    251		struct lola_stream *s = &pcm->streams[i];
    252		if (s->master != str)
    253			break;
    254		s->master = NULL;
    255		s->opened = 0;
    256	}
    257}
    258
    259static int lola_pcm_close(struct snd_pcm_substream *substream)
    260{
    261	struct lola *chip = snd_pcm_substream_chip(substream);
    262	struct lola_stream *str = lola_get_stream(substream);
    263
    264	mutex_lock(&chip->open_mutex);
    265	if (str->substream == substream) {
    266		str->substream = NULL;
    267		str->opened = 0;
    268	}
    269	if (--chip->ref_count_rate == 0) {
    270		/* release sample rate */
    271		chip->sample_rate = 0;
    272	}
    273	mutex_unlock(&chip->open_mutex);
    274	return 0;
    275}
    276
    277static int lola_pcm_hw_params(struct snd_pcm_substream *substream,
    278			      struct snd_pcm_hw_params *hw_params)
    279{
    280	struct lola_stream *str = lola_get_stream(substream);
    281
    282	str->bufsize = 0;
    283	str->period_bytes = 0;
    284	str->format_verb = 0;
    285	return 0;
    286}
    287
    288static int lola_pcm_hw_free(struct snd_pcm_substream *substream)
    289{
    290	struct lola *chip = snd_pcm_substream_chip(substream);
    291	struct lola_pcm *pcm = lola_get_pcm(substream);
    292	struct lola_stream *str = lola_get_stream(substream);
    293
    294	mutex_lock(&chip->open_mutex);
    295	lola_stream_reset(chip, str);
    296	lola_cleanup_slave_streams(pcm, str);
    297	mutex_unlock(&chip->open_mutex);
    298	return 0;
    299}
    300
    301/*
    302 * set up a BDL entry
    303 */
    304static int setup_bdle(struct snd_pcm_substream *substream,
    305		      struct lola_stream *str, __le32 **bdlp,
    306		      int ofs, int size)
    307{
    308	__le32 *bdl = *bdlp;
    309
    310	while (size > 0) {
    311		dma_addr_t addr;
    312		int chunk;
    313
    314		if (str->frags >= LOLA_MAX_BDL_ENTRIES)
    315			return -EINVAL;
    316
    317		addr = snd_pcm_sgbuf_get_addr(substream, ofs);
    318		/* program the address field of the BDL entry */
    319		bdl[0] = cpu_to_le32((u32)addr);
    320		bdl[1] = cpu_to_le32(upper_32_bits(addr));
    321		/* program the size field of the BDL entry */
    322		chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size);
    323		bdl[2] = cpu_to_le32(chunk);
    324		/* program the IOC to enable interrupt
    325		 * only when the whole fragment is processed
    326		 */
    327		size -= chunk;
    328		bdl[3] = size ? 0 : cpu_to_le32(0x01);
    329		bdl += 4;
    330		str->frags++;
    331		ofs += chunk;
    332	}
    333	*bdlp = bdl;
    334	return ofs;
    335}
    336
    337/*
    338 * set up BDL entries
    339 */
    340static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm,
    341			      struct snd_pcm_substream *substream,
    342			      struct lola_stream *str)
    343{
    344	__le32 *bdl;
    345	int i, ofs, periods, period_bytes;
    346
    347	period_bytes = str->period_bytes;
    348	periods = str->bufsize / period_bytes;
    349
    350	/* program the initial BDL entries */
    351	bdl = (__le32 *)(pcm->bdl->area + LOLA_BDL_ENTRY_SIZE * str->index);
    352	ofs = 0;
    353	str->frags = 0;
    354	for (i = 0; i < periods; i++) {
    355		ofs = setup_bdle(substream, str, &bdl, ofs, period_bytes);
    356		if (ofs < 0)
    357			goto error;
    358	}
    359	return 0;
    360
    361 error:
    362	dev_err(chip->card->dev, "Too many BDL entries: buffer=%d, period=%d\n",
    363		   str->bufsize, period_bytes);
    364	return -EINVAL;
    365}
    366
    367static unsigned int lola_get_format_verb(struct snd_pcm_substream *substream)
    368{
    369	unsigned int verb;
    370
    371	switch (substream->runtime->format) {
    372	case SNDRV_PCM_FORMAT_S16_LE:
    373		verb = 0x00000000;
    374		break;
    375	case SNDRV_PCM_FORMAT_S24_LE:
    376		verb = 0x00000200;
    377		break;
    378	case SNDRV_PCM_FORMAT_S32_LE:
    379		verb = 0x00000300;
    380		break;
    381	case SNDRV_PCM_FORMAT_FLOAT_LE:
    382		verb = 0x00001300;
    383		break;
    384	default:
    385		return 0;
    386	}
    387	verb |= substream->runtime->channels;
    388	return verb;
    389}
    390
    391static int lola_set_stream_config(struct lola *chip,
    392				  struct lola_stream *str,
    393				  int channels)
    394{
    395	int i, err;
    396	unsigned int verb, val;
    397
    398	/* set format info for all channels
    399	 * (with only one command for the first channel)
    400	 */
    401	err = lola_codec_read(chip, str->nid, LOLA_VERB_SET_STREAM_FORMAT,
    402			      str->format_verb, 0, &val, NULL);
    403	if (err < 0) {
    404		dev_err(chip->card->dev, "Cannot set stream format 0x%x\n",
    405		       str->format_verb);
    406		return err;
    407	}
    408
    409	/* update stream - channel config */
    410	for (i = 0; i < channels; i++) {
    411		verb = (str->index << 6) | i;
    412		err = lola_codec_read(chip, str[i].nid,
    413				      LOLA_VERB_SET_CHANNEL_STREAMID, 0, verb,
    414				      &val, NULL);
    415		if (err < 0) {
    416			dev_err(chip->card->dev,
    417				"Cannot set stream channel %d\n", i);
    418			return err;
    419		}
    420	}
    421	return 0;
    422}
    423
    424/*
    425 * set up the SD for streaming
    426 */
    427static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
    428				 struct lola_stream *str)
    429{
    430	dma_addr_t bdl;
    431
    432	if (str->prepared)
    433		return -EINVAL;
    434
    435	/* set up BDL */
    436	bdl = pcm->bdl->addr + LOLA_BDL_ENTRY_SIZE * str->index;
    437	lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl);
    438	lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl));
    439	/* program the stream LVI (last valid index) of the BDL */
    440	lola_dsd_write(chip, str->dsd, LVI, str->frags - 1);
    441	lola_stream_clear_pending_irq(chip, str);
    442
    443 	lola_dsd_write(chip, str->dsd, CTL,
    444		       LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE | LOLA_DSD_CTL_SRUN);
    445
    446	str->prepared = 1;
    447
    448	return lola_stream_wait_for_fifo(chip, str, true);
    449}
    450
    451static int lola_pcm_prepare(struct snd_pcm_substream *substream)
    452{
    453	struct lola *chip = snd_pcm_substream_chip(substream);
    454	struct lola_pcm *pcm = lola_get_pcm(substream);
    455	struct lola_stream *str = lola_get_stream(substream);
    456	struct snd_pcm_runtime *runtime = substream->runtime;
    457	unsigned int bufsize, period_bytes, format_verb;
    458	int i, err;
    459
    460	mutex_lock(&chip->open_mutex);
    461	lola_stream_reset(chip, str);
    462	lola_cleanup_slave_streams(pcm, str);
    463	if (str->index + runtime->channels > pcm->num_streams) {
    464		mutex_unlock(&chip->open_mutex);
    465		return -EINVAL;
    466	}
    467	for (i = 1; i < runtime->channels; i++) {
    468		str[i].master = str;
    469		str[i].opened = 1;
    470	}
    471	mutex_unlock(&chip->open_mutex);
    472
    473	bufsize = snd_pcm_lib_buffer_bytes(substream);
    474	period_bytes = snd_pcm_lib_period_bytes(substream);
    475	format_verb = lola_get_format_verb(substream);
    476
    477	str->bufsize = bufsize;
    478	str->period_bytes = period_bytes;
    479	str->format_verb = format_verb;
    480
    481	err = lola_setup_periods(chip, pcm, substream, str);
    482	if (err < 0)
    483		return err;
    484
    485	err = lola_set_sample_rate(chip, runtime->rate);
    486	if (err < 0)
    487		return err;
    488	chip->sample_rate = runtime->rate;	/* sample rate gets locked */
    489
    490	err = lola_set_stream_config(chip, str, runtime->channels);
    491	if (err < 0)
    492		return err;
    493
    494	err = lola_setup_controller(chip, pcm, str);
    495	if (err < 0) {
    496		lola_stream_reset(chip, str);
    497		return err;
    498	}
    499
    500	return 0;
    501}
    502
    503static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
    504{
    505	struct lola *chip = snd_pcm_substream_chip(substream);
    506	struct lola_stream *str;
    507	struct snd_pcm_substream *s;
    508	unsigned int start;
    509	unsigned int tstamp;
    510	bool sync_streams;
    511
    512	switch (cmd) {
    513	case SNDRV_PCM_TRIGGER_START:
    514	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    515	case SNDRV_PCM_TRIGGER_RESUME:
    516		start = 1;
    517		break;
    518	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    519	case SNDRV_PCM_TRIGGER_SUSPEND:
    520	case SNDRV_PCM_TRIGGER_STOP:
    521		start = 0;
    522		break;
    523	default:
    524		return -EINVAL;
    525	}
    526
    527	/*
    528	 * sample correct synchronization is only needed starting several
    529	 * streams. On stop or if only one stream do as quick as possible
    530	 */
    531	sync_streams = (start && snd_pcm_stream_linked(substream));
    532	tstamp = lola_get_tstamp(chip, !sync_streams);
    533	spin_lock(&chip->reg_lock);
    534	snd_pcm_group_for_each_entry(s, substream) {
    535		if (s->pcm->card != substream->pcm->card)
    536			continue;
    537		str = lola_get_stream(s);
    538		if (start)
    539			lola_stream_start(chip, str, tstamp);
    540		else
    541			lola_stream_stop(chip, str, tstamp);
    542		str->running = start;
    543		str->paused = !start;
    544		snd_pcm_trigger_done(s, substream);
    545	}
    546	spin_unlock(&chip->reg_lock);
    547	return 0;
    548}
    549
    550static snd_pcm_uframes_t lola_pcm_pointer(struct snd_pcm_substream *substream)
    551{
    552	struct lola *chip = snd_pcm_substream_chip(substream);
    553	struct lola_stream *str = lola_get_stream(substream);
    554	unsigned int pos = lola_dsd_read(chip, str->dsd, LPIB);
    555
    556	if (pos >= str->bufsize)
    557		pos = 0;
    558	return bytes_to_frames(substream->runtime, pos);
    559}
    560
    561void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits)
    562{
    563	int i;
    564	u8 num_streams = min_t(u8, pcm->num_streams, ARRAY_SIZE(pcm->streams));
    565
    566	for (i = 0; bits && i < num_streams; i++) {
    567		if (bits & (1 << i)) {
    568			struct lola_stream *str = &pcm->streams[i];
    569			if (str->substream && str->running)
    570				snd_pcm_period_elapsed(str->substream);
    571			bits &= ~(1 << i);
    572		}
    573	}
    574}
    575
    576static const struct snd_pcm_ops lola_pcm_ops = {
    577	.open = lola_pcm_open,
    578	.close = lola_pcm_close,
    579	.hw_params = lola_pcm_hw_params,
    580	.hw_free = lola_pcm_hw_free,
    581	.prepare = lola_pcm_prepare,
    582	.trigger = lola_pcm_trigger,
    583	.pointer = lola_pcm_pointer,
    584};
    585
    586int lola_create_pcm(struct lola *chip)
    587{
    588	struct snd_pcm *pcm;
    589	int i, err;
    590
    591	for (i = 0; i < 2; i++) {
    592		chip->pcm[i].bdl =
    593			snd_devm_alloc_pages(&chip->pci->dev, SNDRV_DMA_TYPE_DEV,
    594					     PAGE_SIZE);
    595		if (!chip->pcm[i].bdl)
    596			return -ENOMEM;
    597	}
    598
    599	err = snd_pcm_new(chip->card, "Digigram Lola", 0,
    600			  chip->pcm[SNDRV_PCM_STREAM_PLAYBACK].num_streams,
    601			  chip->pcm[SNDRV_PCM_STREAM_CAPTURE].num_streams,
    602			  &pcm);
    603	if (err < 0)
    604		return err;
    605	strscpy(pcm->name, "Digigram Lola", sizeof(pcm->name));
    606	pcm->private_data = chip;
    607	for (i = 0; i < 2; i++) {
    608		if (chip->pcm[i].num_streams)
    609			snd_pcm_set_ops(pcm, i, &lola_pcm_ops);
    610	}
    611	/* buffer pre-allocation */
    612	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
    613				       &chip->pci->dev,
    614				       1024 * 64, 32 * 1024 * 1024);
    615	return 0;
    616}
    617
    618/*
    619 */
    620
    621static int lola_init_stream(struct lola *chip, struct lola_stream *str,
    622			    int idx, int nid, int dir)
    623{
    624	unsigned int val;
    625	int err;
    626
    627	str->nid = nid;
    628	str->index = idx;
    629	str->dsd = idx;
    630	if (dir == PLAY)
    631		str->dsd += MAX_STREAM_IN_COUNT;
    632	err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
    633	if (err < 0) {
    634		dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid);
    635		return err;
    636	}
    637	if (dir == PLAY) {
    638		/* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) */
    639		if ((val & 0x00f00dff) != 0x00000010) {
    640			dev_err(chip->card->dev,
    641				"Invalid wcaps 0x%x for 0x%x\n",
    642			       val, nid);
    643			return -EINVAL;
    644		}
    645	} else {
    646		/* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1)
    647		 * (bug : ignore bit8: Conn list = 0/1)
    648		 */
    649		if ((val & 0x00f00cff) != 0x00100010) {
    650			dev_err(chip->card->dev,
    651				"Invalid wcaps 0x%x for 0x%x\n",
    652			       val, nid);
    653			return -EINVAL;
    654		}
    655		/* test bit9:DIGITAL and bit12:SRC_PRESENT*/
    656		if ((val & 0x00001200) == 0x00001200)
    657			chip->input_src_caps_mask |= (1 << idx);
    658	}
    659
    660	err = lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val);
    661	if (err < 0) {
    662		dev_err(chip->card->dev, "Can't read FORMATS 0x%x\n", nid);
    663		return err;
    664	}
    665	val &= 3;
    666	if (val == 3)
    667		str->can_float = true;
    668	if (!(val & 1)) {
    669		dev_err(chip->card->dev,
    670			"Invalid formats 0x%x for 0x%x", val, nid);
    671		return -EINVAL;
    672	}
    673	return 0;
    674}
    675
    676int lola_init_pcm(struct lola *chip, int dir, int *nidp)
    677{
    678	struct lola_pcm *pcm = &chip->pcm[dir];
    679	int i, nid, err;
    680
    681	nid = *nidp;
    682	for (i = 0; i < pcm->num_streams; i++, nid++) {
    683		err = lola_init_stream(chip, &pcm->streams[i], i, nid, dir);
    684		if (err < 0)
    685			return err;
    686	}
    687	*nidp = nid;
    688	return 0;
    689}