.. | .. |
---|
| 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); |
---|
.. | .. |
---|
94 | 143 | EXPORT_SYMBOL_GPL(snd_hdac_stream_stop); |
---|
95 | 144 | |
---|
96 | 145 | /** |
---|
| 146 | + * snd_hdac_stop_streams - stop all streams |
---|
| 147 | + * @bus: HD-audio core bus |
---|
| 148 | + */ |
---|
| 149 | +void snd_hdac_stop_streams(struct hdac_bus *bus) |
---|
| 150 | +{ |
---|
| 151 | + struct hdac_stream *stream; |
---|
| 152 | + |
---|
| 153 | + list_for_each_entry(stream, &bus->stream_list, list) |
---|
| 154 | + snd_hdac_stream_stop(stream); |
---|
| 155 | +} |
---|
| 156 | +EXPORT_SYMBOL_GPL(snd_hdac_stop_streams); |
---|
| 157 | + |
---|
| 158 | +/** |
---|
| 159 | + * snd_hdac_stop_streams_and_chip - stop all streams and chip if running |
---|
| 160 | + * @bus: HD-audio core bus |
---|
| 161 | + */ |
---|
| 162 | +void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus) |
---|
| 163 | +{ |
---|
| 164 | + |
---|
| 165 | + if (bus->chip_init) { |
---|
| 166 | + snd_hdac_stop_streams(bus); |
---|
| 167 | + snd_hdac_bus_stop_chip(bus); |
---|
| 168 | + } |
---|
| 169 | +} |
---|
| 170 | +EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip); |
---|
| 171 | + |
---|
| 172 | +/** |
---|
97 | 173 | * snd_hdac_stream_reset - reset a stream |
---|
98 | 174 | * @azx_dev: HD-audio core stream to reset |
---|
99 | 175 | */ |
---|
.. | .. |
---|
101 | 177 | { |
---|
102 | 178 | unsigned char val; |
---|
103 | 179 | int timeout; |
---|
| 180 | + int dma_run_state; |
---|
104 | 181 | |
---|
105 | 182 | snd_hdac_stream_clear(azx_dev); |
---|
| 183 | + |
---|
| 184 | + dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START; |
---|
106 | 185 | |
---|
107 | 186 | snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET); |
---|
108 | 187 | udelay(3); |
---|
.. | .. |
---|
113 | 192 | if (val) |
---|
114 | 193 | break; |
---|
115 | 194 | } while (--timeout); |
---|
| 195 | + |
---|
| 196 | + if (azx_dev->bus->dma_stop_delay && dma_run_state) |
---|
| 197 | + udelay(azx_dev->bus->dma_stop_delay); |
---|
| 198 | + |
---|
116 | 199 | val &= ~SD_CTL_STREAM_RESET; |
---|
117 | 200 | snd_hdac_stream_writeb(azx_dev, SD_CTL, val); |
---|
118 | 201 | udelay(3); |
---|
.. | .. |
---|
183 | 266 | /* set the interrupt enable bits in the descriptor control register */ |
---|
184 | 267 | snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK); |
---|
185 | 268 | |
---|
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; |
---|
| 269 | + azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; |
---|
191 | 270 | |
---|
192 | 271 | /* when LPIB delay correction gives a small negative value, |
---|
193 | 272 | * we ignore it; currently set the threshold statically to |
---|
.. | .. |
---|
244 | 323 | int key = (substream->pcm->device << 16) | (substream->number << 2) | |
---|
245 | 324 | (substream->stream + 1); |
---|
246 | 325 | |
---|
| 326 | + spin_lock_irq(&bus->reg_lock); |
---|
247 | 327 | list_for_each_entry(azx_dev, &bus->stream_list, list) { |
---|
248 | 328 | if (azx_dev->direction != substream->stream) |
---|
249 | 329 | continue; |
---|
.. | .. |
---|
257 | 337 | res = azx_dev; |
---|
258 | 338 | } |
---|
259 | 339 | if (res) { |
---|
260 | | - spin_lock_irq(&bus->reg_lock); |
---|
261 | 340 | res->opened = 1; |
---|
262 | 341 | res->running = 0; |
---|
263 | 342 | res->assigned_key = key; |
---|
264 | 343 | res->substream = substream; |
---|
265 | | - spin_unlock_irq(&bus->reg_lock); |
---|
266 | 344 | } |
---|
| 345 | + spin_unlock_irq(&bus->reg_lock); |
---|
267 | 346 | return res; |
---|
268 | 347 | } |
---|
269 | 348 | EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); |
---|
.. | .. |
---|
545 | 624 | /** |
---|
546 | 625 | * snd_hdac_stream_sync_trigger - turn on/off stream sync register |
---|
547 | 626 | * @azx_dev: HD-audio core stream (master stream) |
---|
| 627 | + * @set: true = set, false = clear |
---|
548 | 628 | * @streams: bit flags of streams to sync |
---|
| 629 | + * @reg: the stream sync register address |
---|
549 | 630 | */ |
---|
550 | 631 | void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, |
---|
551 | 632 | unsigned int streams, unsigned int reg) |
---|
.. | .. |
---|
584 | 665 | nwait = 0; |
---|
585 | 666 | i = 0; |
---|
586 | 667 | 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++; |
---|
| 668 | + if (!(streams & (1 << i++))) |
---|
| 669 | + continue; |
---|
| 670 | + |
---|
| 671 | + if (start) { |
---|
| 672 | + /* check FIFO gets ready */ |
---|
| 673 | + if (!(snd_hdac_stream_readb(s, SD_STS) & |
---|
| 674 | + SD_STS_FIFO_READY)) |
---|
| 675 | + nwait++; |
---|
| 676 | + } else { |
---|
| 677 | + /* check RUN bit is cleared */ |
---|
| 678 | + if (snd_hdac_stream_readb(s, SD_CTL) & |
---|
| 679 | + SD_CTL_DMA_START) { |
---|
| 680 | + nwait++; |
---|
| 681 | + /* |
---|
| 682 | + * Perform stream reset if DMA RUN |
---|
| 683 | + * bit not cleared within given timeout |
---|
| 684 | + */ |
---|
| 685 | + if (timeout == 1) |
---|
| 686 | + snd_hdac_stream_reset(s); |
---|
598 | 687 | } |
---|
599 | 688 | } |
---|
600 | | - i++; |
---|
601 | 689 | } |
---|
602 | 690 | if (!nwait) |
---|
603 | 691 | break; |
---|
.. | .. |
---|
634 | 722 | azx_dev->locked = true; |
---|
635 | 723 | spin_unlock_irq(&bus->reg_lock); |
---|
636 | 724 | |
---|
637 | | - err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG, |
---|
638 | | - byte_size, bufp); |
---|
| 725 | + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, |
---|
| 726 | + byte_size, bufp); |
---|
639 | 727 | if (err < 0) |
---|
640 | 728 | goto err_alloc; |
---|
641 | 729 | |
---|
.. | .. |
---|
661 | 749 | return azx_dev->stream_tag; |
---|
662 | 750 | |
---|
663 | 751 | error: |
---|
664 | | - bus->io_ops->dma_free_pages(bus, bufp); |
---|
| 752 | + snd_dma_free_pages(bufp); |
---|
665 | 753 | err_alloc: |
---|
666 | 754 | spin_lock_irq(&bus->reg_lock); |
---|
667 | 755 | azx_dev->locked = false; |
---|
.. | .. |
---|
708 | 796 | azx_dev->period_bytes = 0; |
---|
709 | 797 | azx_dev->format_val = 0; |
---|
710 | 798 | |
---|
711 | | - bus->io_ops->dma_free_pages(bus, dmab); |
---|
| 799 | + snd_dma_free_pages(dmab); |
---|
712 | 800 | dmab->area = NULL; |
---|
713 | 801 | |
---|
714 | 802 | spin_lock_irq(&bus->reg_lock); |
---|