| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * HD-audio stream operations |
|---|
| 3 | 4 | */ |
|---|
| .. | .. |
|---|
| 11 | 12 | #include <sound/hdaudio.h> |
|---|
| 12 | 13 | #include <sound/hda_register.h> |
|---|
| 13 | 14 | #include "trace.h" |
|---|
| 15 | + |
|---|
| 16 | +/** |
|---|
| 17 | + * snd_hdac_get_stream_stripe_ctl - get stripe control value |
|---|
| 18 | + * @bus: HD-audio core bus |
|---|
| 19 | + * @substream: PCM substream |
|---|
| 20 | + */ |
|---|
| 21 | +int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, |
|---|
| 22 | + struct snd_pcm_substream *substream) |
|---|
| 23 | +{ |
|---|
| 24 | + struct snd_pcm_runtime *runtime = substream->runtime; |
|---|
| 25 | + unsigned int channels = runtime->channels, |
|---|
| 26 | + rate = runtime->rate, |
|---|
| 27 | + bits_per_sample = runtime->sample_bits, |
|---|
| 28 | + max_sdo_lines, value, sdo_line; |
|---|
| 29 | + |
|---|
| 30 | + /* T_AZA_GCAP_NSDO is 1:2 bitfields in GCAP */ |
|---|
| 31 | + max_sdo_lines = snd_hdac_chip_readl(bus, GCAP) & AZX_GCAP_NSDO; |
|---|
| 32 | + |
|---|
| 33 | + /* following is from HD audio spec */ |
|---|
| 34 | + for (sdo_line = max_sdo_lines; sdo_line > 0; sdo_line >>= 1) { |
|---|
| 35 | + if (rate > 48000) |
|---|
| 36 | + value = (channels * bits_per_sample * |
|---|
| 37 | + (rate / 48000)) / sdo_line; |
|---|
| 38 | + else |
|---|
| 39 | + value = (channels * bits_per_sample) / sdo_line; |
|---|
| 40 | + |
|---|
| 41 | + if (value >= bus->sdo_limit) |
|---|
| 42 | + break; |
|---|
| 43 | + } |
|---|
| 44 | + |
|---|
| 45 | + /* stripe value: 0 for 1SDO, 1 for 2SDO, 2 for 4SDO lines */ |
|---|
| 46 | + return sdo_line >> 1; |
|---|
| 47 | +} |
|---|
| 48 | +EXPORT_SYMBOL_GPL(snd_hdac_get_stream_stripe_ctl); |
|---|
| 14 | 49 | |
|---|
| 15 | 50 | /** |
|---|
| 16 | 51 | * snd_hdac_stream_init - initialize each stream (aka device) |
|---|
| .. | .. |
|---|
| 48 | 83 | void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start) |
|---|
| 49 | 84 | { |
|---|
| 50 | 85 | struct hdac_bus *bus = azx_dev->bus; |
|---|
| 86 | + int stripe_ctl; |
|---|
| 51 | 87 | |
|---|
| 52 | 88 | trace_snd_hdac_stream_start(bus, azx_dev); |
|---|
| 53 | 89 | |
|---|
| .. | .. |
|---|
| 56 | 92 | azx_dev->start_wallclk -= azx_dev->period_wallclk; |
|---|
| 57 | 93 | |
|---|
| 58 | 94 | /* enable SIE */ |
|---|
| 59 | | - snd_hdac_chip_updatel(bus, INTCTL, 0, 1 << azx_dev->index); |
|---|
| 95 | + snd_hdac_chip_updatel(bus, INTCTL, |
|---|
| 96 | + 1 << azx_dev->index, |
|---|
| 97 | + 1 << azx_dev->index); |
|---|
| 98 | + /* set stripe control */ |
|---|
| 99 | + if (azx_dev->stripe) { |
|---|
| 100 | + if (azx_dev->substream) |
|---|
| 101 | + stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream); |
|---|
| 102 | + else |
|---|
| 103 | + stripe_ctl = 0; |
|---|
| 104 | + snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, |
|---|
| 105 | + stripe_ctl); |
|---|
| 106 | + } |
|---|
| 60 | 107 | /* set DMA start and interrupt mask */ |
|---|
| 61 | 108 | snd_hdac_stream_updateb(azx_dev, SD_CTL, |
|---|
| 62 | 109 | 0, SD_CTL_DMA_START | SD_INT_MASK); |
|---|
| .. | .. |
|---|
| 73 | 120 | snd_hdac_stream_updateb(azx_dev, SD_CTL, |
|---|
| 74 | 121 | SD_CTL_DMA_START | SD_INT_MASK, 0); |
|---|
| 75 | 122 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ |
|---|
| 123 | + if (azx_dev->stripe) |
|---|
| 124 | + snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0); |
|---|
| 76 | 125 | azx_dev->running = false; |
|---|
| 77 | 126 | } |
|---|
| 78 | 127 | EXPORT_SYMBOL_GPL(snd_hdac_stream_clear); |
|---|
| .. | .. |
|---|
| 101 | 150 | { |
|---|
| 102 | 151 | unsigned char val; |
|---|
| 103 | 152 | int timeout; |
|---|
| 153 | + int dma_run_state; |
|---|
| 104 | 154 | |
|---|
| 105 | 155 | snd_hdac_stream_clear(azx_dev); |
|---|
| 156 | + |
|---|
| 157 | + dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START; |
|---|
| 106 | 158 | |
|---|
| 107 | 159 | snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET); |
|---|
| 108 | 160 | udelay(3); |
|---|
| .. | .. |
|---|
| 113 | 165 | if (val) |
|---|
| 114 | 166 | break; |
|---|
| 115 | 167 | } while (--timeout); |
|---|
| 168 | + |
|---|
| 169 | + if (azx_dev->bus->dma_stop_delay && dma_run_state) |
|---|
| 170 | + udelay(azx_dev->bus->dma_stop_delay); |
|---|
| 171 | + |
|---|
| 116 | 172 | val &= ~SD_CTL_STREAM_RESET; |
|---|
| 117 | 173 | snd_hdac_stream_writeb(azx_dev, SD_CTL, val); |
|---|
| 118 | 174 | udelay(3); |
|---|
| .. | .. |
|---|
| 183 | 239 | /* set the interrupt enable bits in the descriptor control register */ |
|---|
| 184 | 240 | snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK); |
|---|
| 185 | 241 | |
|---|
| 186 | | - if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) |
|---|
| 187 | | - azx_dev->fifo_size = |
|---|
| 188 | | - snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; |
|---|
| 189 | | - else |
|---|
| 190 | | - azx_dev->fifo_size = 0; |
|---|
| 242 | + azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; |
|---|
| 191 | 243 | |
|---|
| 192 | 244 | /* when LPIB delay correction gives a small negative value, |
|---|
| 193 | 245 | * we ignore it; currently set the threshold statically to |
|---|
| .. | .. |
|---|
| 244 | 296 | int key = (substream->pcm->device << 16) | (substream->number << 2) | |
|---|
| 245 | 297 | (substream->stream + 1); |
|---|
| 246 | 298 | |
|---|
| 299 | + spin_lock_irq(&bus->reg_lock); |
|---|
| 247 | 300 | list_for_each_entry(azx_dev, &bus->stream_list, list) { |
|---|
| 248 | 301 | if (azx_dev->direction != substream->stream) |
|---|
| 249 | 302 | continue; |
|---|
| .. | .. |
|---|
| 257 | 310 | res = azx_dev; |
|---|
| 258 | 311 | } |
|---|
| 259 | 312 | if (res) { |
|---|
| 260 | | - spin_lock_irq(&bus->reg_lock); |
|---|
| 261 | 313 | res->opened = 1; |
|---|
| 262 | 314 | res->running = 0; |
|---|
| 263 | 315 | res->assigned_key = key; |
|---|
| 264 | 316 | res->substream = substream; |
|---|
| 265 | | - spin_unlock_irq(&bus->reg_lock); |
|---|
| 266 | 317 | } |
|---|
| 318 | + spin_unlock_irq(&bus->reg_lock); |
|---|
| 267 | 319 | return res; |
|---|
| 268 | 320 | } |
|---|
| 269 | 321 | EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); |
|---|
| .. | .. |
|---|
| 545 | 597 | /** |
|---|
| 546 | 598 | * snd_hdac_stream_sync_trigger - turn on/off stream sync register |
|---|
| 547 | 599 | * @azx_dev: HD-audio core stream (master stream) |
|---|
| 600 | + * @set: true = set, false = clear |
|---|
| 548 | 601 | * @streams: bit flags of streams to sync |
|---|
| 602 | + * @reg: the stream sync register address |
|---|
| 549 | 603 | */ |
|---|
| 550 | 604 | void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, |
|---|
| 551 | 605 | unsigned int streams, unsigned int reg) |
|---|
| .. | .. |
|---|
| 584 | 638 | nwait = 0; |
|---|
| 585 | 639 | i = 0; |
|---|
| 586 | 640 | list_for_each_entry(s, &bus->stream_list, list) { |
|---|
| 587 | | - if (streams & (1 << i)) { |
|---|
| 588 | | - if (start) { |
|---|
| 589 | | - /* check FIFO gets ready */ |
|---|
| 590 | | - if (!(snd_hdac_stream_readb(s, SD_STS) & |
|---|
| 591 | | - SD_STS_FIFO_READY)) |
|---|
| 592 | | - nwait++; |
|---|
| 593 | | - } else { |
|---|
| 594 | | - /* check RUN bit is cleared */ |
|---|
| 595 | | - if (snd_hdac_stream_readb(s, SD_CTL) & |
|---|
| 596 | | - SD_CTL_DMA_START) |
|---|
| 597 | | - nwait++; |
|---|
| 641 | + if (!(streams & (1 << i++))) |
|---|
| 642 | + continue; |
|---|
| 643 | + |
|---|
| 644 | + if (start) { |
|---|
| 645 | + /* check FIFO gets ready */ |
|---|
| 646 | + if (!(snd_hdac_stream_readb(s, SD_STS) & |
|---|
| 647 | + SD_STS_FIFO_READY)) |
|---|
| 648 | + nwait++; |
|---|
| 649 | + } else { |
|---|
| 650 | + /* check RUN bit is cleared */ |
|---|
| 651 | + if (snd_hdac_stream_readb(s, SD_CTL) & |
|---|
| 652 | + SD_CTL_DMA_START) { |
|---|
| 653 | + nwait++; |
|---|
| 654 | + /* |
|---|
| 655 | + * Perform stream reset if DMA RUN |
|---|
| 656 | + * bit not cleared within given timeout |
|---|
| 657 | + */ |
|---|
| 658 | + if (timeout == 1) |
|---|
| 659 | + snd_hdac_stream_reset(s); |
|---|
| 598 | 660 | } |
|---|
| 599 | 661 | } |
|---|
| 600 | | - i++; |
|---|
| 601 | 662 | } |
|---|
| 602 | 663 | if (!nwait) |
|---|
| 603 | 664 | break; |
|---|
| .. | .. |
|---|
| 634 | 695 | azx_dev->locked = true; |
|---|
| 635 | 696 | spin_unlock_irq(&bus->reg_lock); |
|---|
| 636 | 697 | |
|---|
| 637 | | - err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 638 | | - byte_size, bufp); |
|---|
| 698 | + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, |
|---|
| 699 | + byte_size, bufp); |
|---|
| 639 | 700 | if (err < 0) |
|---|
| 640 | 701 | goto err_alloc; |
|---|
| 641 | 702 | |
|---|
| .. | .. |
|---|
| 661 | 722 | return azx_dev->stream_tag; |
|---|
| 662 | 723 | |
|---|
| 663 | 724 | error: |
|---|
| 664 | | - bus->io_ops->dma_free_pages(bus, bufp); |
|---|
| 725 | + snd_dma_free_pages(bufp); |
|---|
| 665 | 726 | err_alloc: |
|---|
| 666 | 727 | spin_lock_irq(&bus->reg_lock); |
|---|
| 667 | 728 | azx_dev->locked = false; |
|---|
| .. | .. |
|---|
| 708 | 769 | azx_dev->period_bytes = 0; |
|---|
| 709 | 770 | azx_dev->format_val = 0; |
|---|
| 710 | 771 | |
|---|
| 711 | | - bus->io_ops->dma_free_pages(bus, dmab); |
|---|
| 772 | + snd_dma_free_pages(dmab); |
|---|
| 712 | 773 | dmab->area = NULL; |
|---|
| 713 | 774 | |
|---|
| 714 | 775 | spin_lock_irq(&bus->reg_lock); |
|---|