0001
0002
0003
0004
0005
0006 #include <linux/kernel.h>
0007 #include <linux/delay.h>
0008 #include <linux/export.h>
0009 #include <linux/clocksource.h>
0010 #include <sound/core.h>
0011 #include <sound/pcm.h>
0012 #include <sound/hdaudio.h>
0013 #include <sound/hda_register.h>
0014 #include "trace.h"
0015
0016
0017
0018
0019
0020
0021 int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
0022 struct snd_pcm_substream *substream)
0023 {
0024 struct snd_pcm_runtime *runtime = substream->runtime;
0025 unsigned int channels = runtime->channels,
0026 rate = runtime->rate,
0027 bits_per_sample = runtime->sample_bits,
0028 max_sdo_lines, value, sdo_line;
0029
0030
0031 max_sdo_lines = snd_hdac_chip_readl(bus, GCAP) & AZX_GCAP_NSDO;
0032
0033
0034 for (sdo_line = max_sdo_lines; sdo_line > 0; sdo_line >>= 1) {
0035 if (rate > 48000)
0036 value = (channels * bits_per_sample *
0037 (rate / 48000)) / sdo_line;
0038 else
0039 value = (channels * bits_per_sample) / sdo_line;
0040
0041 if (value >= bus->sdo_limit)
0042 break;
0043 }
0044
0045
0046 return sdo_line >> 1;
0047 }
0048 EXPORT_SYMBOL_GPL(snd_hdac_get_stream_stripe_ctl);
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
0061 int idx, int direction, int tag)
0062 {
0063 azx_dev->bus = bus;
0064
0065 azx_dev->sd_addr = bus->remap_addr + (0x20 * idx + 0x80);
0066
0067 azx_dev->sd_int_sta_mask = 1 << idx;
0068 azx_dev->index = idx;
0069 azx_dev->direction = direction;
0070 azx_dev->stream_tag = tag;
0071 snd_hdac_dsp_lock_init(azx_dev);
0072 list_add_tail(&azx_dev->list, &bus->stream_list);
0073 }
0074 EXPORT_SYMBOL_GPL(snd_hdac_stream_init);
0075
0076
0077
0078
0079
0080
0081
0082
0083 void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
0084 {
0085 struct hdac_bus *bus = azx_dev->bus;
0086 int stripe_ctl;
0087
0088 trace_snd_hdac_stream_start(bus, azx_dev);
0089
0090 azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK);
0091 if (!fresh_start)
0092 azx_dev->start_wallclk -= azx_dev->period_wallclk;
0093
0094
0095 snd_hdac_chip_updatel(bus, INTCTL,
0096 1 << azx_dev->index,
0097 1 << azx_dev->index);
0098
0099 if (azx_dev->stripe) {
0100 if (azx_dev->substream)
0101 stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream);
0102 else
0103 stripe_ctl = 0;
0104 snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK,
0105 stripe_ctl);
0106 }
0107
0108 snd_hdac_stream_updateb(azx_dev, SD_CTL,
0109 0, SD_CTL_DMA_START | SD_INT_MASK);
0110 azx_dev->running = true;
0111 }
0112 EXPORT_SYMBOL_GPL(snd_hdac_stream_start);
0113
0114
0115
0116
0117
0118 void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
0119 {
0120 snd_hdac_stream_updateb(azx_dev, SD_CTL,
0121 SD_CTL_DMA_START | SD_INT_MASK, 0);
0122 snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
0123 if (azx_dev->stripe)
0124 snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
0125 azx_dev->running = false;
0126 }
0127 EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
0128
0129
0130
0131
0132
0133
0134
0135 void snd_hdac_stream_stop(struct hdac_stream *azx_dev)
0136 {
0137 trace_snd_hdac_stream_stop(azx_dev->bus, azx_dev);
0138
0139 snd_hdac_stream_clear(azx_dev);
0140
0141 snd_hdac_chip_updatel(azx_dev->bus, INTCTL, 1 << azx_dev->index, 0);
0142 }
0143 EXPORT_SYMBOL_GPL(snd_hdac_stream_stop);
0144
0145
0146
0147
0148
0149 void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus)
0150 {
0151 struct hdac_stream *stream;
0152
0153 if (bus->chip_init) {
0154 list_for_each_entry(stream, &bus->stream_list, list)
0155 snd_hdac_stream_stop(stream);
0156 snd_hdac_bus_stop_chip(bus);
0157 }
0158 }
0159 EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip);
0160
0161
0162
0163
0164
0165 void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
0166 {
0167 unsigned char val;
0168 int timeout;
0169 int dma_run_state;
0170
0171 snd_hdac_stream_clear(azx_dev);
0172
0173 dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START;
0174
0175 snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
0176 udelay(3);
0177 timeout = 300;
0178 do {
0179 val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
0180 SD_CTL_STREAM_RESET;
0181 if (val)
0182 break;
0183 } while (--timeout);
0184
0185 if (azx_dev->bus->dma_stop_delay && dma_run_state)
0186 udelay(azx_dev->bus->dma_stop_delay);
0187
0188 val &= ~SD_CTL_STREAM_RESET;
0189 snd_hdac_stream_writeb(azx_dev, SD_CTL, val);
0190 udelay(3);
0191
0192 timeout = 300;
0193
0194 do {
0195 val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
0196 SD_CTL_STREAM_RESET;
0197 if (!val)
0198 break;
0199 } while (--timeout);
0200
0201
0202 if (azx_dev->posbuf)
0203 *azx_dev->posbuf = 0;
0204 }
0205 EXPORT_SYMBOL_GPL(snd_hdac_stream_reset);
0206
0207
0208
0209
0210
0211 int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
0212 {
0213 struct hdac_bus *bus = azx_dev->bus;
0214 struct snd_pcm_runtime *runtime;
0215 unsigned int val;
0216
0217 if (azx_dev->substream)
0218 runtime = azx_dev->substream->runtime;
0219 else
0220 runtime = NULL;
0221
0222 snd_hdac_stream_clear(azx_dev);
0223
0224 val = snd_hdac_stream_readl(azx_dev, SD_CTL);
0225 val = (val & ~SD_CTL_STREAM_TAG_MASK) |
0226 (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT);
0227 if (!bus->snoop)
0228 val |= SD_CTL_TRAFFIC_PRIO;
0229 snd_hdac_stream_writel(azx_dev, SD_CTL, val);
0230
0231
0232 snd_hdac_stream_writel(azx_dev, SD_CBL, azx_dev->bufsize);
0233
0234
0235
0236 snd_hdac_stream_writew(azx_dev, SD_FORMAT, azx_dev->format_val);
0237
0238
0239 snd_hdac_stream_writew(azx_dev, SD_LVI, azx_dev->frags - 1);
0240
0241
0242
0243 snd_hdac_stream_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
0244
0245 snd_hdac_stream_writel(azx_dev, SD_BDLPU,
0246 upper_32_bits(azx_dev->bdl.addr));
0247
0248
0249 if (bus->use_posbuf && bus->posbuf.addr) {
0250 if (!(snd_hdac_chip_readl(bus, DPLBASE) & AZX_DPLBASE_ENABLE))
0251 snd_hdac_chip_writel(bus, DPLBASE,
0252 (u32)bus->posbuf.addr | AZX_DPLBASE_ENABLE);
0253 }
0254
0255
0256 snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK);
0257
0258 azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1;
0259
0260
0261
0262
0263
0264 if (runtime && runtime->period_size > 64)
0265 azx_dev->delay_negative_threshold =
0266 -frames_to_bytes(runtime, 64);
0267 else
0268 azx_dev->delay_negative_threshold = 0;
0269
0270
0271 if (runtime)
0272 azx_dev->period_wallclk = (((runtime->period_size * 24000) /
0273 runtime->rate) * 1000);
0274
0275 return 0;
0276 }
0277 EXPORT_SYMBOL_GPL(snd_hdac_stream_setup);
0278
0279
0280
0281
0282
0283 void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev)
0284 {
0285 snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0);
0286 snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0);
0287 snd_hdac_stream_writel(azx_dev, SD_CTL, 0);
0288 azx_dev->bufsize = 0;
0289 azx_dev->period_bytes = 0;
0290 azx_dev->format_val = 0;
0291 }
0292 EXPORT_SYMBOL_GPL(snd_hdac_stream_cleanup);
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
0306 struct snd_pcm_substream *substream)
0307 {
0308 struct hdac_stream *azx_dev;
0309 struct hdac_stream *res = NULL;
0310
0311
0312 int key = (substream->pcm->device << 16) | (substream->number << 2) |
0313 (substream->stream + 1);
0314
0315 spin_lock_irq(&bus->reg_lock);
0316 list_for_each_entry(azx_dev, &bus->stream_list, list) {
0317 if (azx_dev->direction != substream->stream)
0318 continue;
0319 if (azx_dev->opened)
0320 continue;
0321 if (azx_dev->assigned_key == key) {
0322 res = azx_dev;
0323 break;
0324 }
0325 if (!res || bus->reverse_assign)
0326 res = azx_dev;
0327 }
0328 if (res) {
0329 res->opened = 1;
0330 res->running = 0;
0331 res->assigned_key = key;
0332 res->substream = substream;
0333 }
0334 spin_unlock_irq(&bus->reg_lock);
0335 return res;
0336 }
0337 EXPORT_SYMBOL_GPL(snd_hdac_stream_assign);
0338
0339
0340
0341
0342
0343
0344
0345 void snd_hdac_stream_release(struct hdac_stream *azx_dev)
0346 {
0347 struct hdac_bus *bus = azx_dev->bus;
0348
0349 spin_lock_irq(&bus->reg_lock);
0350 azx_dev->opened = 0;
0351 azx_dev->running = 0;
0352 azx_dev->substream = NULL;
0353 spin_unlock_irq(&bus->reg_lock);
0354 }
0355 EXPORT_SYMBOL_GPL(snd_hdac_stream_release);
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365 struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus,
0366 int dir, int stream_tag)
0367 {
0368 struct hdac_stream *s;
0369
0370 list_for_each_entry(s, &bus->stream_list, list) {
0371 if (s->direction == dir && s->stream_tag == stream_tag)
0372 return s;
0373 }
0374
0375 return NULL;
0376 }
0377 EXPORT_SYMBOL_GPL(snd_hdac_get_stream);
0378
0379
0380
0381
0382 static int setup_bdle(struct hdac_bus *bus,
0383 struct snd_dma_buffer *dmab,
0384 struct hdac_stream *azx_dev, __le32 **bdlp,
0385 int ofs, int size, int with_ioc)
0386 {
0387 __le32 *bdl = *bdlp;
0388
0389 while (size > 0) {
0390 dma_addr_t addr;
0391 int chunk;
0392
0393 if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES)
0394 return -EINVAL;
0395
0396 addr = snd_sgbuf_get_addr(dmab, ofs);
0397
0398 bdl[0] = cpu_to_le32((u32)addr);
0399 bdl[1] = cpu_to_le32(upper_32_bits(addr));
0400
0401 chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size);
0402
0403 if (bus->align_bdle_4k) {
0404 u32 remain = 0x1000 - (ofs & 0xfff);
0405
0406 if (chunk > remain)
0407 chunk = remain;
0408 }
0409 bdl[2] = cpu_to_le32(chunk);
0410
0411
0412
0413 size -= chunk;
0414 bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01);
0415 bdl += 4;
0416 azx_dev->frags++;
0417 ofs += chunk;
0418 }
0419 *bdlp = bdl;
0420 return ofs;
0421 }
0422
0423
0424
0425
0426
0427
0428
0429
0430 int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
0431 {
0432 struct hdac_bus *bus = azx_dev->bus;
0433 struct snd_pcm_substream *substream = azx_dev->substream;
0434 struct snd_pcm_runtime *runtime = substream->runtime;
0435 __le32 *bdl;
0436 int i, ofs, periods, period_bytes;
0437 int pos_adj, pos_align;
0438
0439
0440 snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0);
0441 snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0);
0442
0443 period_bytes = azx_dev->period_bytes;
0444 periods = azx_dev->bufsize / period_bytes;
0445
0446
0447 bdl = (__le32 *)azx_dev->bdl.area;
0448 ofs = 0;
0449 azx_dev->frags = 0;
0450
0451 pos_adj = bus->bdl_pos_adj;
0452 if (!azx_dev->no_period_wakeup && pos_adj > 0) {
0453 pos_align = pos_adj;
0454 pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000);
0455 if (!pos_adj)
0456 pos_adj = pos_align;
0457 else
0458 pos_adj = roundup(pos_adj, pos_align);
0459 pos_adj = frames_to_bytes(runtime, pos_adj);
0460 if (pos_adj >= period_bytes) {
0461 dev_warn(bus->dev, "Too big adjustment %d\n",
0462 pos_adj);
0463 pos_adj = 0;
0464 } else {
0465 ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
0466 azx_dev,
0467 &bdl, ofs, pos_adj, true);
0468 if (ofs < 0)
0469 goto error;
0470 }
0471 } else
0472 pos_adj = 0;
0473
0474 for (i = 0; i < periods; i++) {
0475 if (i == periods - 1 && pos_adj)
0476 ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
0477 azx_dev, &bdl, ofs,
0478 period_bytes - pos_adj, 0);
0479 else
0480 ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
0481 azx_dev, &bdl, ofs,
0482 period_bytes,
0483 !azx_dev->no_period_wakeup);
0484 if (ofs < 0)
0485 goto error;
0486 }
0487 return 0;
0488
0489 error:
0490 dev_err(bus->dev, "Too many BDL entries: buffer=%d, period=%d\n",
0491 azx_dev->bufsize, period_bytes);
0492 return -EINVAL;
0493 }
0494 EXPORT_SYMBOL_GPL(snd_hdac_stream_setup_periods);
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504 int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
0505 unsigned int format_val)
0506 {
0507
0508 unsigned int bufsize, period_bytes;
0509 struct snd_pcm_substream *substream = azx_dev->substream;
0510 struct snd_pcm_runtime *runtime;
0511 int err;
0512
0513 if (!substream)
0514 return -EINVAL;
0515 runtime = substream->runtime;
0516 bufsize = snd_pcm_lib_buffer_bytes(substream);
0517 period_bytes = snd_pcm_lib_period_bytes(substream);
0518
0519 if (bufsize != azx_dev->bufsize ||
0520 period_bytes != azx_dev->period_bytes ||
0521 format_val != azx_dev->format_val ||
0522 runtime->no_period_wakeup != azx_dev->no_period_wakeup) {
0523 azx_dev->bufsize = bufsize;
0524 azx_dev->period_bytes = period_bytes;
0525 azx_dev->format_val = format_val;
0526 azx_dev->no_period_wakeup = runtime->no_period_wakeup;
0527 err = snd_hdac_stream_setup_periods(azx_dev);
0528 if (err < 0)
0529 return err;
0530 }
0531 return 0;
0532 }
0533 EXPORT_SYMBOL_GPL(snd_hdac_stream_set_params);
0534
0535 static u64 azx_cc_read(const struct cyclecounter *cc)
0536 {
0537 struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc);
0538
0539 return snd_hdac_chip_readl(azx_dev->bus, WALLCLK);
0540 }
0541
0542 static void azx_timecounter_init(struct hdac_stream *azx_dev,
0543 bool force, u64 last)
0544 {
0545 struct timecounter *tc = &azx_dev->tc;
0546 struct cyclecounter *cc = &azx_dev->cc;
0547 u64 nsec;
0548
0549 cc->read = azx_cc_read;
0550 cc->mask = CLOCKSOURCE_MASK(32);
0551
0552
0553
0554
0555
0556 clocks_calc_mult_shift(&cc->mult, &cc->shift, 24000000,
0557 NSEC_PER_SEC, 178);
0558
0559 nsec = 0;
0560 timecounter_init(tc, cc, nsec);
0561 if (force) {
0562
0563
0564
0565
0566 tc->cycle_last = last;
0567 }
0568 }
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580 void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
0581 unsigned int streams)
0582 {
0583 struct hdac_bus *bus = azx_dev->bus;
0584 struct snd_pcm_runtime *runtime = azx_dev->substream->runtime;
0585 struct hdac_stream *s;
0586 bool inited = false;
0587 u64 cycle_last = 0;
0588 int i = 0;
0589
0590 list_for_each_entry(s, &bus->stream_list, list) {
0591 if (streams & (1 << i)) {
0592 azx_timecounter_init(s, inited, cycle_last);
0593 if (!inited) {
0594 inited = true;
0595 cycle_last = s->tc.cycle_last;
0596 }
0597 }
0598 i++;
0599 }
0600
0601 snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
0602 runtime->trigger_tstamp_latched = true;
0603 }
0604 EXPORT_SYMBOL_GPL(snd_hdac_stream_timecounter_init);
0605
0606
0607
0608
0609
0610
0611
0612
0613 void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set,
0614 unsigned int streams, unsigned int reg)
0615 {
0616 struct hdac_bus *bus = azx_dev->bus;
0617 unsigned int val;
0618
0619 if (!reg)
0620 reg = AZX_REG_SSYNC;
0621 val = _snd_hdac_chip_readl(bus, reg);
0622 if (set)
0623 val |= streams;
0624 else
0625 val &= ~streams;
0626 _snd_hdac_chip_writel(bus, reg, val);
0627 }
0628 EXPORT_SYMBOL_GPL(snd_hdac_stream_sync_trigger);
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639 void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
0640 unsigned int streams)
0641 {
0642 struct hdac_bus *bus = azx_dev->bus;
0643 int i, nwait, timeout;
0644 struct hdac_stream *s;
0645
0646 for (timeout = 5000; timeout; timeout--) {
0647 nwait = 0;
0648 i = 0;
0649 list_for_each_entry(s, &bus->stream_list, list) {
0650 if (!(streams & (1 << i++)))
0651 continue;
0652
0653 if (start) {
0654
0655 if (!(snd_hdac_stream_readb(s, SD_STS) &
0656 SD_STS_FIFO_READY))
0657 nwait++;
0658 } else {
0659
0660 if (snd_hdac_stream_readb(s, SD_CTL) &
0661 SD_CTL_DMA_START) {
0662 nwait++;
0663
0664
0665
0666
0667 if (timeout == 1)
0668 snd_hdac_stream_reset(s);
0669 }
0670 }
0671 }
0672 if (!nwait)
0673 break;
0674 cpu_relax();
0675 }
0676 }
0677 EXPORT_SYMBOL_GPL(snd_hdac_stream_sync);
0678
0679 #ifdef CONFIG_SND_HDA_DSP_LOADER
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690 int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
0691 unsigned int byte_size, struct snd_dma_buffer *bufp)
0692 {
0693 struct hdac_bus *bus = azx_dev->bus;
0694 __le32 *bdl;
0695 int err;
0696
0697 snd_hdac_dsp_lock(azx_dev);
0698 spin_lock_irq(&bus->reg_lock);
0699 if (azx_dev->running || azx_dev->locked) {
0700 spin_unlock_irq(&bus->reg_lock);
0701 err = -EBUSY;
0702 goto unlock;
0703 }
0704 azx_dev->locked = true;
0705 spin_unlock_irq(&bus->reg_lock);
0706
0707 err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev,
0708 byte_size, bufp);
0709 if (err < 0)
0710 goto err_alloc;
0711
0712 azx_dev->substream = NULL;
0713 azx_dev->bufsize = byte_size;
0714 azx_dev->period_bytes = byte_size;
0715 azx_dev->format_val = format;
0716
0717 snd_hdac_stream_reset(azx_dev);
0718
0719
0720 snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0);
0721 snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0);
0722
0723 azx_dev->frags = 0;
0724 bdl = (__le32 *)azx_dev->bdl.area;
0725 err = setup_bdle(bus, bufp, azx_dev, &bdl, 0, byte_size, 0);
0726 if (err < 0)
0727 goto error;
0728
0729 snd_hdac_stream_setup(azx_dev);
0730 snd_hdac_dsp_unlock(azx_dev);
0731 return azx_dev->stream_tag;
0732
0733 error:
0734 snd_dma_free_pages(bufp);
0735 err_alloc:
0736 spin_lock_irq(&bus->reg_lock);
0737 azx_dev->locked = false;
0738 spin_unlock_irq(&bus->reg_lock);
0739 unlock:
0740 snd_hdac_dsp_unlock(azx_dev);
0741 return err;
0742 }
0743 EXPORT_SYMBOL_GPL(snd_hdac_dsp_prepare);
0744
0745
0746
0747
0748
0749
0750 void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start)
0751 {
0752 if (start)
0753 snd_hdac_stream_start(azx_dev, true);
0754 else
0755 snd_hdac_stream_stop(azx_dev);
0756 }
0757 EXPORT_SYMBOL_GPL(snd_hdac_dsp_trigger);
0758
0759
0760
0761
0762
0763
0764 void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev,
0765 struct snd_dma_buffer *dmab)
0766 {
0767 struct hdac_bus *bus = azx_dev->bus;
0768
0769 if (!dmab->area || !azx_dev->locked)
0770 return;
0771
0772 snd_hdac_dsp_lock(azx_dev);
0773
0774 snd_hdac_stream_writel(azx_dev, SD_BDLPL, 0);
0775 snd_hdac_stream_writel(azx_dev, SD_BDLPU, 0);
0776 snd_hdac_stream_writel(azx_dev, SD_CTL, 0);
0777 azx_dev->bufsize = 0;
0778 azx_dev->period_bytes = 0;
0779 azx_dev->format_val = 0;
0780
0781 snd_dma_free_pages(dmab);
0782 dmab->area = NULL;
0783
0784 spin_lock_irq(&bus->reg_lock);
0785 azx_dev->locked = false;
0786 spin_unlock_irq(&bus->reg_lock);
0787 snd_hdac_dsp_unlock(azx_dev);
0788 }
0789 EXPORT_SYMBOL_GPL(snd_hdac_dsp_cleanup);
0790 #endif