Lines Matching +full:double +full:- +full:buffering

1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/dma-mapping.h>
68 writel(value, priv->ai_reg_base + reg); in n64audio_write_reg()
73 writel(value, priv->mi_reg_base + reg); in n64mi_write_reg()
78 return readl(priv->mi_reg_base + reg); in n64mi_read_reg()
83 struct snd_pcm_runtime *runtime = priv->chan.substream->runtime; in n64audio_push()
87 spin_lock_irqsave(&priv->chan.lock, flags); in n64audio_push()
89 count = priv->chan.writesize; in n64audio_push()
91 memcpy(priv->ring_base + priv->chan.nextpos, in n64audio_push()
92 runtime->dma_area + priv->chan.nextpos, count); in n64audio_push()
95 * The hw registers are double-buffered, and the IRQ fires essentially in n64audio_push()
99 n64audio_write_reg(priv, AI_ADDR_REG, priv->ring_base_dma + priv->chan.nextpos); in n64audio_push()
103 priv->chan.nextpos += count; in n64audio_push()
104 priv->chan.nextpos %= priv->chan.bufsize; in n64audio_push()
106 runtime->delay = runtime->period_size; in n64audio_push()
108 spin_unlock_irqrestore(&priv->chan.lock, flags); in n64audio_push()
123 if (priv->chan.substream && snd_pcm_running(priv->chan.substream)) { in n64audio_isr()
124 spin_lock_irqsave(&priv->chan.lock, flags); in n64audio_isr()
126 priv->chan.pos = priv->chan.nextpos; in n64audio_isr()
128 spin_unlock_irqrestore(&priv->chan.lock, flags); in n64audio_isr()
130 snd_pcm_period_elapsed(priv->chan.substream); in n64audio_isr()
131 if (priv->chan.substream && snd_pcm_running(priv->chan.substream)) in n64audio_isr()
153 // 3 periods lets the double-buffering hw read one buffer behind safely
171 if (is_power_of_2(c->min)) { in hw_rule_period_size()
172 c->min += 2; in hw_rule_period_size()
175 if (is_power_of_2(c->max)) { in hw_rule_period_size()
176 c->max -= 2; in hw_rule_period_size()
180 c->empty = 1; in hw_rule_period_size()
181 return -EINVAL; in hw_rule_period_size()
189 struct snd_pcm_runtime *runtime = substream->runtime; in n64audio_pcm_open()
192 runtime->hw = n64audio_pcm_hw; in n64audio_pcm_open()
202 hw_rule_period_size, NULL, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); in n64audio_pcm_open()
211 struct snd_pcm_runtime *runtime = substream->runtime; in n64audio_pcm_prepare()
212 struct n64audio *priv = substream->pcm->private_data; in n64audio_pcm_prepare()
215 rate = ((2 * AI_NTSC_DACRATE / runtime->rate) + 1) / 2 - 1; in n64audio_pcm_prepare()
222 n64audio_write_reg(priv, AI_BITCLOCK_REG, rate - 1); in n64audio_pcm_prepare()
224 spin_lock_irq(&priv->chan.lock); in n64audio_pcm_prepare()
226 /* Setup the pseudo-dma transfer pointers. */ in n64audio_pcm_prepare()
227 priv->chan.pos = 0; in n64audio_pcm_prepare()
228 priv->chan.nextpos = 0; in n64audio_pcm_prepare()
229 priv->chan.substream = substream; in n64audio_pcm_prepare()
230 priv->chan.writesize = snd_pcm_lib_period_bytes(substream); in n64audio_pcm_prepare()
231 priv->chan.bufsize = snd_pcm_lib_buffer_bytes(substream); in n64audio_pcm_prepare()
233 spin_unlock_irq(&priv->chan.lock); in n64audio_pcm_prepare()
240 struct n64audio *priv = substream->pcm->private_data; in n64audio_pcm_trigger()
244 n64audio_push(substream->pcm->private_data); in n64audio_pcm_trigger()
253 return -EINVAL; in n64audio_pcm_trigger()
260 struct n64audio *priv = substream->pcm->private_data; in n64audio_pcm_pointer()
262 return bytes_to_frames(substream->runtime, in n64audio_pcm_pointer()
263 priv->chan.pos); in n64audio_pcm_pointer()
268 struct n64audio *priv = substream->pcm->private_data; in n64audio_pcm_close()
270 priv->chan.substream = NULL; in n64audio_pcm_close()
284 * The target device is embedded and RAM-constrained. We save RAM
295 err = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, in n64audio_probe()
301 priv = card->private_data; in n64audio_probe()
303 spin_lock_init(&priv->chan.lock); in n64audio_probe()
305 priv->card = card; in n64audio_probe()
307 priv->ring_base = dma_alloc_coherent(card->dev, 32 * 1024, &priv->ring_base_dma, in n64audio_probe()
309 if (!priv->ring_base) { in n64audio_probe()
310 err = -ENOMEM; in n64audio_probe()
314 priv->mi_reg_base = devm_platform_ioremap_resource(pdev, 0); in n64audio_probe()
315 if (IS_ERR(priv->mi_reg_base)) { in n64audio_probe()
316 err = PTR_ERR(priv->mi_reg_base); in n64audio_probe()
320 priv->ai_reg_base = devm_platform_ioremap_resource(pdev, 1); in n64audio_probe()
321 if (IS_ERR(priv->ai_reg_base)) { in n64audio_probe()
322 err = PTR_ERR(priv->ai_reg_base); in n64audio_probe()
330 pcm->private_data = priv; in n64audio_probe()
331 strscpy(pcm->name, "N64 Audio"); in n64audio_probe()
334 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, card->dev, 0, 0); in n64audio_probe()
336 strscpy(card->driver, "N64 Audio"); in n64audio_probe()
337 strscpy(card->shortname, "N64 Audio"); in n64audio_probe()
338 strscpy(card->longname, "N64 Audio"); in n64audio_probe()
342 err = -EINVAL; in n64audio_probe()
345 if (devm_request_irq(&pdev->dev, irq, n64audio_isr, in n64audio_probe()
347 err = -EBUSY; in n64audio_probe()
358 dma_free_coherent(card->dev, 32 * 1024, priv->ring_base, priv->ring_base_dma); in n64audio_probe()