static inline snd_pcm_uframes_t snd_em8300_pcm_indirect_playback_pointer(struct snd_pcm_substream *substream, snd_em8300_pcm_indirect_t *rec, unsigned int ptr) { int bytes = ptr - rec->hw_io; if (bytes < 0) bytes += rec->hw_buffer_size; rec->hw_io = ptr; rec->hw_ready -= bytes; rec->sw_io += bytes; if (rec->sw_io >= rec->sw_buffer_size) rec->sw_io -= rec->sw_buffer_size; if (substream->ops->ack) substream->ops->ack(substream); return bytes_to_frames(substream->runtime, rec->sw_io); }
static snd_pcm_uframes_t at91_pcm_pointer( struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct at91_runtime_data *prtd = runtime->private_data; struct at91_pcm_dma_params *params = prtd->params; dma_addr_t ptr; snd_pcm_uframes_t x; ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr); x = bytes_to_frames(runtime, ptr - prtd->dma_buffer); if (x == runtime->buffer_size) x = 0; return x; }
/* pointer callback */ static snd_pcm_uframes_t snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; audio_info(" .. IN\n"); audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0, frames_to_bytes(runtime, runtime->status->hw_ptr), frames_to_bytes(runtime, runtime->control->appl_ptr), alsa_stream->pos); audio_info(" .. OUT\n"); return bytes_to_frames(runtime, alsa_stream->pos); }
static snd_pcm_uframes_t pxa3xx_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct pxa3xx_runtime_data *prtd = runtime->private_data; dma_addr_t ptr; snd_pcm_uframes_t x; ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch); x = bytes_to_frames(runtime, ptr - runtime->dma_addr); if (x == runtime->buffer_size) x = 0; return x; }
/* Called in atomic context with IRQ disabled */ static snd_pcm_uframes_t snd_ad1889_playback_pointer(struct snd_pcm_substream *ss) { size_t ptr = 0; struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); if (unlikely(!(chip->wave.reg & AD_DS_WSMC_WAEN))) return 0; ptr = ad1889_readl(chip, AD_DMA_WAVCA); ptr -= chip->wave.addr; snd_assert((ptr >= 0) && (ptr < chip->wave.size), return 0); return bytes_to_frames(ss->runtime, ptr); }
/* Called in atomic context with IRQ disabled */ static snd_pcm_uframes_t snd_ad1889_capture_pointer(struct snd_pcm_substream *ss) { size_t ptr = 0; struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); if (unlikely(!(chip->ramc.reg & AD_DS_RAMC_ADEN))) return 0; ptr = ad1889_readl(chip, AD_DMA_ADCCA); ptr -= chip->ramc.addr; snd_assert((ptr >= 0) && (ptr < chip->ramc.size), return 0); return bytes_to_frames(ss->runtime, ptr); }
static snd_pcm_uframes_t ath79_pcm_pointer(struct snd_pcm_substream *ss) { struct snd_pcm_runtime *runtime = ss->runtime; struct ath79_pcm_rt_priv *rtpriv; snd_pcm_uframes_t ret = 0; rtpriv = runtime->private_data; if(rtpriv->last_played == NULL) ret = 0; else ret = rtpriv->last_played->BufPtr - runtime->dma_addr; ret = bytes_to_frames(runtime, ret); return ret; }
static snd_pcm_uframes_t s3c_dma_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct s3c24xx_runtime_data *prtd = runtime->private_data; unsigned long res; dma_addr_t src, dst; pr_debug("Entered %s\n", __func__); spin_lock(&prtd->lock); s3c2410_dma_getposition(prtd->params->channel, &src, &dst); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) res = dst - prtd->dma_start; else res = src - prtd->dma_start; spin_unlock(&prtd->lock); pr_debug("Pointer %x %x\n", src, dst); /* we seem to be getting the odd error from the pcm library due * to out-of-bounds pointers. this is maybe due to the dma engine * not having loaded the new values for the channel before being * callled... (todo - fix ) */ /* To fix the pcm buffer underrun in case of high busy state ( ex. Starting broswer ) 2010.06.22*/ if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (res >= snd_pcm_lib_buffer_bytes(substream) * ANDROID_BUF_NUM) { if (res == snd_pcm_lib_buffer_bytes(substream) * ANDROID_BUF_NUM) res = 0; } } else { if (res >= snd_pcm_lib_buffer_bytes(substream)) { if (res == snd_pcm_lib_buffer_bytes(substream)) res = 0; } } return bytes_to_frames(substream->runtime, res); }
static snd_pcm_uframes_t atmel_abdac_pointer(struct snd_pcm_substream *substream) { struct atmel_abdac *dac = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t frames; unsigned long bytes; bytes = dw_dma_get_src_addr(dac->dma.chan); bytes -= runtime->dma_addr; frames = bytes_to_frames(runtime, bytes); if (frames >= runtime->buffer_size) frames -= runtime->buffer_size; return frames; }
static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(rtd->platform); struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); struct sst_hsw *hsw = pdata->hsw; snd_pcm_uframes_t offset; offset = bytes_to_frames(runtime, sst_hsw_get_dsp_position(hsw, pcm_data->stream)); dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", frames_to_bytes(runtime, (u32)offset)); return offset; }
static snd_pcm_uframes_t idma_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct idma_ctrl *prtd = runtime->private_data; dma_addr_t src; unsigned long res; spin_lock(&prtd->lock); idma_getpos(&src); res = src - prtd->start; spin_unlock(&prtd->lock); return bytes_to_frames(substream->runtime, res); }
/** * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation * @substream: PCM substream * * This function can be used as the PCM pointer callback for dmaengine based PCM * driver implementations. */ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) { struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); struct dma_tx_state state; enum dma_status status; unsigned int buf_size; unsigned int pos = 0; status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { buf_size = snd_pcm_lib_buffer_bytes(substream); if (state.residue > 0 && state.residue <= buf_size) pos = buf_size - state.residue; } return bytes_to_frames(substream->runtime, pos); }
static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct omap_runtime_data *prtd = runtime->private_data; dma_addr_t ptr; snd_pcm_uframes_t offset; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ptr = omap_get_dma_src_pos(prtd->dma_ch); else ptr = omap_get_dma_dst_pos(prtd->dma_ch); offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); if (offset >= runtime->buffer_size) offset = 0; return offset; }
/* pointer callback */ static snd_pcm_uframes_t snd_vortex_pcm_pointer(snd_pcm_substream_t * substream) { vortex_t *chip = snd_pcm_substream_chip(substream); stream_t *stream = (stream_t *) substream->runtime->private_data; int dma = stream->dma; snd_pcm_uframes_t current_ptr = 0; spin_lock(&chip->lock); if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) current_ptr = vortex_adbdma_getlinearpos(chip, dma); #ifndef CHIP_AU8810 else current_ptr = vortex_wtdma_getlinearpos(chip, dma); #endif //printk(KERN_INFO "vortex: pointer = 0x%x\n", current_ptr); spin_unlock(&chip->lock); return (bytes_to_frames(substream->runtime, current_ptr)); }
/* * report current pointer */ static snd_pcm_uframes_t snd_ps3_pcm_pointer( struct snd_pcm_substream *substream) { struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); size_t bytes; snd_pcm_uframes_t ret; spin_lock(&card->dma_lock); { bytes = (size_t)(card->dma_last_transfer_vaddr[SND_PS3_CH_L] - card->dma_start_vaddr[SND_PS3_CH_L]); } spin_unlock(&card->dma_lock); ret = bytes_to_frames(substream->runtime, bytes * 2); return ret; };
static snd_pcm_uframes_t cns3xxx_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct cns3xxx_runtime_data *prtd = runtime->private_data; dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? DMAC_READ_CHREGS (prtd->dma_ch, PL330_SA) : DMAC_READ_CHREGS (prtd->dma_ch, PL330_DA) ; snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); #ifdef __DEBUG_PATH // printk("%s=>%d\n", __FUNCTION__, __LINE__); #endif // static int dumponce = 1; // // if(dumponce) // { // int counter = 0; // unsigned char *pBuf = (unsigned char *)__bus_to_virt(runtime->dma_addr); // // if(*pBuf) { // printk("\n>>>>>>>>>> Dump Sound Buffer 11 <<<<<<<<<<<<\n"); // for(counter=0; counter<128; counter++) { // if((counter%16 == 0) && counter) // printk("\n"); // printk("%02X ", *(pBuf+counter)); // } // printk("\n"); // dumponce = 0; // } // } //printk ("%s:Transmitted %d frame [sa:%x;da:%x]\n",__FUNCTION__,(int)x,DMAC_READ_CHREGS(prtd->dma_ch,PL330_SA),DMAC_READ_CHREGS(prtd->dma_ch,PL330_DA)); if (x >= runtime->buffer_size) { //#ifdef CNS3XXX_AUDIO_DEBUG //printk ("Transmitted all the frames [%d in total]\n",(int)x); //#endif x = 0; } return x; }
static snd_pcm_uframes_t hi3630_srcup_normal_pointer(struct snd_pcm_substream *substream) { snd_pcm_uframes_t offset = 0; struct snd_pcm_runtime *runtime = substream->runtime; struct hi3630_srcup_runtime_data *prtd = substream->runtime->private_data; unsigned int period_cur = 0; unsigned int period_size = 0; spin_lock(&prtd->lock); period_cur = prtd->period_cur; period_size = prtd->period_size; spin_unlock(&prtd->lock); offset = bytes_to_frames(runtime, period_cur * period_size); if (offset >= runtime->buffer_size) offset = 0; return offset; }
static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct sst_byt_priv_data *pdata = snd_soc_platform_get_drvdata(rtd->platform); struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); struct sst_byt *byt = pdata->byt; snd_pcm_uframes_t offset; int pos; pos = sst_byt_get_dsp_position(byt, pcm_data->stream, snd_pcm_lib_buffer_bytes(substream)); offset = bytes_to_frames(runtime, pos); dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", frames_to_bytes(runtime, (u32)offset)); return offset; }
static snd_pcm_uframes_t mxs_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct mxs_runtime_data *prtd = runtime->private_data; struct mxs_dma_info dma_info; unsigned int offset; dma_addr_t pos; mxs_dma_get_info(prtd->params->dma_ch, &dma_info); pos = dma_info.buf_addr; offset = bytes_to_frames(runtime, pos - runtime->dma_addr); if (offset >= runtime->buffer_size) offset = 0; return offset; }
static snd_pcm_uframes_t atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream) { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t frames; unsigned long bytes; if (cpu_is_at32ap7000()) bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); else bytes = readl(chip->regs + ATMEL_PDC_RPR); bytes -= runtime->dma_addr; frames = bytes_to_frames(runtime, bytes); if (frames >= runtime->buffer_size) frames -= runtime->buffer_size; return frames; }
static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct sport_device *sport = runtime->private_data; unsigned int diff; snd_pcm_uframes_t frames; pr_debug("%s enter\n", __func__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { diff = sport_curr_offset_tx(sport); } else { diff = sport_curr_offset_rx(sport); } if (diff == snd_pcm_lib_buffer_bytes(substream)) diff = 0; frames = bytes_to_frames(substream->runtime, diff); return frames; }
static snd_pcm_uframes_t s5p_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct s5p_runtime_data *prtd = runtime->private_data; unsigned long res; dma_addr_t src, dst; spin_lock(&prtd->lock); if(s3c_pcm_pdat.lp_mode) s3ci2s_func->dma_getpos(&src, &dst); /* By Jung */ res = prtd->dma_pos - prtd->dma_start; spin_unlock(&prtd->lock); s3cdbg("Pointer %x %x\n", src, dst); /* we seem to be getting the odd error from the pcm library due * to out-of-bounds pointers. this is maybe due to the dma engine * not having loaded the new values for the channel before being * callled... (todo - fix ) */ /* By Jung */ if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (res >= snd_pcm_lib_buffer_bytes(substream) * ANDROID_BUF_NUM) { if (res == snd_pcm_lib_buffer_bytes(substream) * ANDROID_BUF_NUM) res = 0; } } else { if (res >= snd_pcm_lib_buffer_bytes(substream)) { if (res == snd_pcm_lib_buffer_bytes(substream)) res = 0; } } return bytes_to_frames(substream->runtime, res); }
/* * pointer callback simplly reads XXX_DMA_DT_CUR register as the current * position. when SG-buffer is implemented, the offset must be calculated * correctly... */ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream) { atiixp_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data; unsigned int curptr; int timeout = 1000; while (timeout--) { curptr = readl(chip->remap_addr + dma->ops->dt_cur); if (curptr < dma->buf_addr) continue; curptr -= dma->buf_addr; if (curptr >= dma->buf_bytes) continue; return bytes_to_frames(runtime, curptr); } snd_printd("atiixp: invalid DMA pointer read 0x%x (buf=%x)\n", readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr); return 0; }
/* * return the current pointer */ inline static snd_pcm_uframes_t snd_pmac_pcm_pointer(struct snd_pmac *chip, struct pmac_stream *rec, struct snd_pcm_substream *subs) { int count = 0; #if 1 /* hmm.. how can we get the current dma pointer?? */ int stat; volatile struct dbdma_cmd __iomem *cp = &rec->cmd.cmds[rec->cur_period]; stat = le16_to_cpu(cp->xfer_status); if (stat & (ACTIVE|DEAD)) { count = in_le16(&cp->res_count); if (count) count = rec->period_size - count; } #endif count += rec->cur_period * rec->period_size; /*printk(KERN_DEBUG "pointer=%d\n", count);*/ return bytes_to_frames(subs->runtime, count); }
static snd_pcm_uframes_t sun7i_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct sun7i_runtime_data *prtd = runtime->private_data; unsigned long res = 0; snd_pcm_uframes_t offset = 0; spin_lock(&prtd->lock); sw_dma_getposition(prtd->dma_hdl, (dma_addr_t*)&dmasrc, (dma_addr_t*)&dmadst); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE){ res = dmadst - prtd->dma_start; } else { offset = bytes_to_frames(runtime, dmasrc + prtd->dma_period - runtime->dma_addr); } spin_unlock(&prtd->lock); if(offset >= runtime->buffer_size) offset = 0; return offset; }
/* * pointer callback simplly reads XXX_DMA_DT_CUR register as the current * position. when SG-buffer is implemented, the offset must be calculated * correctly... */ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(struct snd_pcm_substream *substream) { struct atiixp *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct atiixp_dma *dma = runtime->private_data; unsigned int curptr; int timeout = 1000; while (timeout--) { curptr = readl(chip->remap_addr + dma->ops->dt_cur); if (curptr < dma->buf_addr) continue; curptr -= dma->buf_addr; if (curptr >= dma->buf_bytes) continue; return bytes_to_frames(runtime, curptr); } dev_dbg(chip->card->dev, "invalid DMA pointer read 0x%x (buf=%x)\n", readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr); return 0; }
static snd_pcm_uframes_t dma_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct runtime_data *prtd = runtime->private_data; unsigned long res; pr_debug("Entered %s\n", __func__); res = prtd->dma_pos - prtd->dma_start; pr_debug("Pointer offset: %lu\n", res); if (res >= snd_pcm_lib_buffer_bytes(substream)) { if (res == snd_pcm_lib_buffer_bytes(substream)) res = 0; } return bytes_to_frames(substream->runtime, res); }
static inline int queue_next_buffer(void *arg, int cur_offset) { struct snd_pcm_substream *substream = (struct snd_pcm_substream *)arg; struct snd_pcm_runtime *runtime = substream->runtime; struct pcm_runtime_data *prtd = substream->runtime->private_data; struct snd_pcm *pcm = substream->pcm; struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device]; int offset = cur_offset; int size, rtbuffersize; NvAudioFxBufferDescriptor abd; rtbuffersize = frames_to_bytes(runtime, runtime->buffer_size); memset(&abd, 0, sizeof(NvAudioFxBufferDescriptor)); size = TEGRA_DEFAULT_BUFFER_SIZE; if ((offset + size) > rtbuffersize) { size = rtbuffersize - offset; } abd.hMixBuffer = prtd->mixer_buffer; abd.Offset = offset; abd.Size = size; abd.Format.FormatTag = 1; abd.Format.SampleRate = runtime->rate; abd.Format.BitsPerSample = runtime->sample_bits; abd.Format.Channels = runtime->channels; abd.Format.ChannelMask = 0; abd.Format.ValidBitsPerSample = 0; ptscx->xrt_fxn.StreamAddBuffer( (NvAudioFxStreamHandle)prtd->stdoutpath->Stream, &abd); offset += size; if (offset >= rtbuffersize) offset =0; prtd->audiofx_frames += bytes_to_frames(runtime, size); return offset; }
static snd_pcm_uframes_t snd_cs5535audio_pcm_pointer(struct snd_pcm_substream *substream) { struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); u32 curdma; struct cs5535audio_dma *dma; dma = substream->runtime->private_data; curdma = dma->ops->read_dma_pntr(cs5535au); if (curdma < dma->buf_addr) { snd_printk(KERN_ERR "curdma=%x < %x bufaddr.\n", curdma, dma->buf_addr); return 0; } curdma -= dma->buf_addr; if (curdma >= dma->buf_bytes) { snd_printk(KERN_ERR "diff=%x >= %x buf_bytes.\n", curdma, dma->buf_bytes); return 0; } return bytes_to_frames(substream->runtime, curdma); }
static snd_pcm_uframes_t idma_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct idma_ctrl *prtd = runtime->private_data; dma_addr_t src; unsigned long res, flags; spin_lock_irqsave(&prtd->lock, flags); idma_getpos(&src, substream); res = src - prtd->start; spin_unlock_irqrestore(&prtd->lock, flags); if (res >= snd_pcm_lib_buffer_bytes(substream)) { if (res == snd_pcm_lib_buffer_bytes(substream)) res = 0; } return bytes_to_frames(substream->runtime, res); }