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