690 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Support for Digigram Lola PCI-e boards4 *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 818#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 again114 */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 entry303 */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 interrupt325 * only when the whole fragment is processed326 */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 entries339 */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 channels399 * (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 streaming426 */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 several529 * streams. On stop or if only one stream do as quick as possible530 */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 else541 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}690