Lines Matching +full:double +full:- +full:buffering
1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/dma-mapping.h>
67 writel(value, priv->ai_reg_base + reg); in n64audio_write_reg()
72 writel(value, priv->mi_reg_base + reg); in n64mi_write_reg()
77 return readl(priv->mi_reg_base + reg); in n64mi_read_reg()
82 struct snd_pcm_runtime *runtime = priv->chan.substream->runtime; in n64audio_push()
86 spin_lock_irqsave(&priv->chan.lock, flags); in n64audio_push()
88 count = priv->chan.writesize; in n64audio_push()
90 memcpy(priv->ring_base + priv->chan.nextpos, in n64audio_push()
91 runtime->dma_area + priv->chan.nextpos, count); in n64audio_push()
94 * The hw registers are double-buffered, and the IRQ fires essentially in n64audio_push()
98 n64audio_write_reg(priv, AI_ADDR_REG, priv->ring_base_dma + priv->chan.nextpos); in n64audio_push()
102 priv->chan.nextpos += count; in n64audio_push()
103 priv->chan.nextpos %= priv->chan.bufsize; in n64audio_push()
105 runtime->delay = runtime->period_size; in n64audio_push()
107 spin_unlock_irqrestore(&priv->chan.lock, flags); in n64audio_push()
122 if (priv->chan.substream && snd_pcm_running(priv->chan.substream)) { in n64audio_isr()
123 spin_lock_irqsave(&priv->chan.lock, flags); in n64audio_isr()
125 priv->chan.pos = priv->chan.nextpos; in n64audio_isr()
127 spin_unlock_irqrestore(&priv->chan.lock, flags); in n64audio_isr()
129 snd_pcm_period_elapsed(priv->chan.substream); in n64audio_isr()
130 if (priv->chan.substream && snd_pcm_running(priv->chan.substream)) in n64audio_isr()
152 // 3 periods lets the double-buffering hw read one buffer behind safely
170 if (is_power_of_2(c->min)) { in hw_rule_period_size()
171 c->min += 2; in hw_rule_period_size()
174 if (is_power_of_2(c->max)) { in hw_rule_period_size()
175 c->max -= 2; in hw_rule_period_size()
179 c->empty = 1; in hw_rule_period_size()
180 return -EINVAL; in hw_rule_period_size()
188 struct snd_pcm_runtime *runtime = substream->runtime; in n64audio_pcm_open()
191 runtime->hw = n64audio_pcm_hw; in n64audio_pcm_open()
201 hw_rule_period_size, NULL, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); in n64audio_pcm_open()
210 struct snd_pcm_runtime *runtime = substream->runtime; in n64audio_pcm_prepare()
211 struct n64audio *priv = substream->pcm->private_data; in n64audio_pcm_prepare()
214 rate = ((2 * AI_NTSC_DACRATE / runtime->rate) + 1) / 2 - 1; in n64audio_pcm_prepare()
221 n64audio_write_reg(priv, AI_BITCLOCK_REG, rate - 1); in n64audio_pcm_prepare()
223 spin_lock_irq(&priv->chan.lock); in n64audio_pcm_prepare()
225 /* Setup the pseudo-dma transfer pointers. */ in n64audio_pcm_prepare()
226 priv->chan.pos = 0; in n64audio_pcm_prepare()
227 priv->chan.nextpos = 0; in n64audio_pcm_prepare()
228 priv->chan.substream = substream; in n64audio_pcm_prepare()
229 priv->chan.writesize = snd_pcm_lib_period_bytes(substream); in n64audio_pcm_prepare()
230 priv->chan.bufsize = snd_pcm_lib_buffer_bytes(substream); in n64audio_pcm_prepare()
232 spin_unlock_irq(&priv->chan.lock); in n64audio_pcm_prepare()
239 struct n64audio *priv = substream->pcm->private_data; in n64audio_pcm_trigger()
243 n64audio_push(substream->pcm->private_data); in n64audio_pcm_trigger()
252 return -EINVAL; in n64audio_pcm_trigger()
259 struct n64audio *priv = substream->pcm->private_data; in n64audio_pcm_pointer()
261 return bytes_to_frames(substream->runtime, in n64audio_pcm_pointer()
262 priv->chan.pos); in n64audio_pcm_pointer()
267 struct n64audio *priv = substream->pcm->private_data; in n64audio_pcm_close()
269 priv->chan.substream = NULL; in n64audio_pcm_close()
283 * The target device is embedded and RAM-constrained. We save RAM
294 err = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, in n64audio_probe()
300 priv = card->private_data; in n64audio_probe()
302 spin_lock_init(&priv->chan.lock); in n64audio_probe()
304 priv->card = card; in n64audio_probe()
306 priv->ring_base = dma_alloc_coherent(card->dev, 32 * 1024, &priv->ring_base_dma, in n64audio_probe()
308 if (!priv->ring_base) { in n64audio_probe()
309 err = -ENOMEM; in n64audio_probe()
313 priv->mi_reg_base = devm_platform_ioremap_resource(pdev, 0); in n64audio_probe()
314 if (IS_ERR(priv->mi_reg_base)) { in n64audio_probe()
315 err = PTR_ERR(priv->mi_reg_base); in n64audio_probe()
319 priv->ai_reg_base = devm_platform_ioremap_resource(pdev, 1); in n64audio_probe()
320 if (IS_ERR(priv->ai_reg_base)) { in n64audio_probe()
321 err = PTR_ERR(priv->ai_reg_base); in n64audio_probe()
329 pcm->private_data = priv; in n64audio_probe()
330 strcpy(pcm->name, "N64 Audio"); in n64audio_probe()
333 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, card->dev, 0, 0); in n64audio_probe()
335 strcpy(card->driver, "N64 Audio"); in n64audio_probe()
336 strcpy(card->shortname, "N64 Audio"); in n64audio_probe()
337 strcpy(card->longname, "N64 Audio"); in n64audio_probe()
341 err = -EINVAL; in n64audio_probe()
344 if (devm_request_irq(&pdev->dev, irq, n64audio_isr, in n64audio_probe()
346 err = -EBUSY; in n64audio_probe()
357 dma_free_coherent(card->dev, 32 * 1024, priv->ring_base, priv->ring_base_dma); in n64audio_probe()