/* * Not used with ping/pong */ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) { struct davinci_runtime_data *prtd = substream->runtime->private_data; struct snd_pcm_runtime *runtime = substream->runtime; unsigned int period_size; unsigned int dma_offset; dma_addr_t dma_pos; dma_addr_t src, dst; unsigned short src_bidx, dst_bidx; unsigned short src_cidx, dst_cidx; unsigned int data_type; unsigned short acnt; unsigned int count; unsigned int fifo_level; period_size = snd_pcm_lib_period_bytes(substream); dma_offset = prtd->period * period_size; dma_pos = runtime->dma_addr + dma_offset; fifo_level = prtd->params->fifo_level; pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d " "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos, period_size); data_type = prtd->params->data_type; count = period_size / data_type; if (fifo_level) count /= fifo_level; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { src = dma_pos; dst = prtd->params->dma_addr; src_bidx = data_type; dst_bidx = 0; src_cidx = data_type * fifo_level; dst_cidx = 0; } else { src = prtd->params->dma_addr; dst = dma_pos; src_bidx = 0; dst_bidx = data_type; src_cidx = 0; dst_cidx = data_type * fifo_level; } acnt = prtd->params->acnt; edma_set_src(prtd->asp_link[0], src, INCR, W8BIT); edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT); edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx); edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx); if (!fifo_level) edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0, ASYNC); else edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level, count, fifo_level, ABSYNC); }
static int edma_memtomemcpy(int count, unsigned long src_addr, unsigned long trgt_addr, int dma_ch) { int result = 0; struct edmacc_param param_set; edma_set_src(dma_ch, src_addr, INCR, W256BIT); edma_set_dest(dma_ch, trgt_addr, INCR, W256BIT); edma_set_src_index(dma_ch, 1, 1); edma_set_dest_index(dma_ch, 1, 1); /* A Sync Transfer Mode */ edma_set_transfer_params(dma_ch, count, 1, 1, 1, ASYNC); //one block of one frame of one array of count bytes /* Enable the Interrupts on Channel 1 */ edma_read_slot(dma_ch, ¶m_set); param_set.opt |= ITCINTEN; param_set.opt |= TCINTEN; param_set.opt |= EDMA_TCC(EDMA_CHAN_SLOT(dma_ch)); edma_write_slot(dma_ch, ¶m_set); irqraised1 = 0u; dma_comp.done = 0; result = edma_start(dma_ch); if (result != 0) { printk("%s: edma copy failed \n", DEVICE_NAME); } wait_for_completion(&dma_comp); /* Check the status of the completed transfer */ if (irqraised1 < 0) { printk("%s: edma copy: Event Miss Occured!!!\n", DEVICE_NAME); edma_stop(dma_ch); result = -EAGAIN; } return result; }
/* * Only used with ping/pong. * This is called after runtime->dma_addr, period_bytes and data_type are valid */ static int ping_pong_dma_setup(struct snd_pcm_substream *substream) { unsigned short ram_src_cidx, ram_dst_cidx; struct snd_pcm_runtime *runtime = substream->runtime; struct davinci_runtime_data *prtd = runtime->private_data; struct snd_dma_buffer *iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data; struct davinci_pcm_dma_params *params = prtd->params; unsigned int data_type = params->data_type; unsigned int acnt = params->acnt; /* divide by 2 for ping/pong */ unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1; unsigned int fifo_level = prtd->params->fifo_level; unsigned int count; if ((data_type == 0) || (data_type > 4)) { printk(KERN_ERR "%s: data_type=%i\n", __func__, data_type); return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_addr_t asp_src_pong = iram_dma->addr + ping_size; ram_src_cidx = ping_size; ram_dst_cidx = -ping_size; edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT); edma_set_src_index(prtd->asp_link[0], data_type, data_type * fifo_level); edma_set_src_index(prtd->asp_link[1], data_type, data_type * fifo_level); edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT); } else { dma_addr_t asp_dst_pong = iram_dma->addr + ping_size; ram_src_cidx = -ping_size; ram_dst_cidx = ping_size; edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT); edma_set_dest_index(prtd->asp_link[0], data_type, data_type * fifo_level); edma_set_dest_index(prtd->asp_link[1], data_type, data_type * fifo_level); edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT); } if (!fifo_level) { count = ping_size / data_type; edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0, ASYNC); edma_set_transfer_params(prtd->asp_link[1], acnt, count, 1, 0, ASYNC); } else { count = ping_size / (data_type * fifo_level); edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level, count, fifo_level, ABSYNC); edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level, count, fifo_level, ABSYNC); } edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx); edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx); edma_set_transfer_params(prtd->ram_link, ping_size, 2, runtime->periods, 2, ASYNC); /* init master params */ edma_read_slot(prtd->asp_link[0], &prtd->asp_params); edma_read_slot(prtd->ram_link, &prtd->ram_params); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { struct edmacc_param p_ram; /* Copy entire iram buffer before playback started */ prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1); /* 0 dst_bidx */ prtd->ram_params.src_dst_bidx = (ping_size << 1); /* 0 dst_cidx */ prtd->ram_params.src_dst_cidx = (ping_size << 1); prtd->ram_params.ccnt = 1; /* Skip 1st period */ edma_read_slot(prtd->ram_link, &p_ram); p_ram.src += (ping_size << 1); p_ram.ccnt -= 1; edma_write_slot(prtd->ram_link2, &p_ram); /* * When 1st started, ram -> iram dma channel will fill the * entire iram. Then, whenever a ping/pong asp buffer finishes, * 1/2 iram will be filled. */ prtd->ram_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->ram_link2) << 5; } return 0; }
static int edma_config(void) { // use AB mode, one_dma = 8KB/16bit static int acnt = 4096*2; static int bcnt = 1; static int ccnt = 1; int result = 0; unsigned int BRCnt = 0; int srcbidx = 0; int desbidx = 0; int srccidx = 0; int descidx = 0; struct edmacc_param param_set; printk("Initializing dma transfer...\n"); // set dest memory fpga_buf = dma_alloc_coherent (NULL, MAX_DMA_TRANSFER_IN_BYTES, &dmaphysdest, 0); if (!fpga_buf) { printk ("dma_alloc_coherent failed for physdest\n"); return -ENOMEM; } /* Set B count reload as B count. */ BRCnt = bcnt; /* Setting up the SRC/DES Index */ srcbidx = 0; desbidx = acnt; /* A Sync Transfer Mode */ srccidx = 0; descidx = acnt; // gpmc channel result = edma_alloc_channel (52, callback1, NULL, 0); if (result < 0) { printk ("edma_alloc_channel failed, error:%d", result); return result; } dma_ch = result; edma_set_src (dma_ch, (unsigned long)(gpmc_membase), INCR, W16BIT); edma_set_dest (dma_ch, (unsigned long)(dmaphysdest), INCR, W16BIT); edma_set_src_index (dma_ch, srcbidx, srccidx); // use fifo, set zero edma_set_dest_index (dma_ch, desbidx, descidx); // A mode // A Sync Transfer Mode edma_set_transfer_params (dma_ch, acnt, bcnt, ccnt, BRCnt, ASYNC); /* Enable the Interrupts on Channel 1 */ edma_read_slot (dma_ch, ¶m_set); param_set.opt |= (1 << ITCINTEN_SHIFT); param_set.opt |= (1 << TCINTEN_SHIFT); param_set.opt |= EDMA_TCC(EDMA_CHAN_SLOT(dma_ch)); edma_write_slot (dma_ch, ¶m_set); return 0; }
int logi_dma_copy(struct drvr_mem* mem_dev, unsigned long trgt_addr, unsigned long src_addr, int count) { int result = 0; #ifdef USE_DMA_ENGINE struct dma_chan *chan; struct dma_device *dev; struct dma_async_tx_descriptor *tx; unsigned long flags; chan = mem_dev->dma.chan; dev = chan->device; flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; tx = dev->device_prep_dma_memcpy(chan, trgt_addr, src_addr, count, flags); if (!tx) { DBG_LOG("device_prep_dma_memcpy failed\n"); return -ENODEV; } irqraised1 = 0u; dma_comp.done = 0; /* set the callback and submit the transaction */ tx->callback = dma_callback; tx->callback_param = mem_dev; cookie = dmaengine_submit(tx); dma_async_issue_pending(chan); #else struct edmacc_param param_set; int dma_ch = mem_dev->dma.dma_chan; edma_set_src(dma_ch, src_addr, INCR, W256BIT); edma_set_dest(dma_ch, trgt_addr, INCR, W256BIT); edma_set_src_index(dma_ch, 1, 1); edma_set_dest_index(dma_ch, 1, 1); /* A Sync Transfer Mode */ edma_set_transfer_params(dma_ch, count, 1, 1, 1, ASYNC);//one block of one frame of one array of count bytes /* Enable the Interrupts on Channel 1 */ edma_read_slot(dma_ch, ¶m_set); param_set.opt |= ITCINTEN; param_set.opt |= TCINTEN; param_set.opt |= EDMA_TCC(EDMA_CHAN_SLOT(dma_ch)); edma_write_slot(dma_ch, ¶m_set); irqraised1 = 0u; dma_comp.done = 0; result = edma_start(dma_ch); if (result != 0) { DBG_LOG("edma copy failed\n"); return result; } #endif /* USE_DMA_ENGINE */ wait_for_completion(&dma_comp); /* Check the status of the completed transfer */ if (irqraised1 < 0) { DBG_LOG("edma copy: Event Miss Occured!!!\n"); #ifdef USE_DMA_ENGINE dmaengine_terminate_all(chan); #else edma_stop(dma_ch); #endif /* USE_DMA_ENGINE */ result = -EAGAIN; } return result; }
static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) { struct davinci_spi *davinci_spi; int int_status = 0; int count, temp_count; u8 conv = 1; u8 tmp; u32 data1_reg_val; struct davinci_spi_dma *davinci_spi_dma; int word_len, data_type, ret; unsigned long tx_reg, rx_reg; struct davinci_spi_platform_data *pdata; struct device *sdev; davinci_spi = spi_master_get_devdata(spi->master); pdata = davinci_spi->pdata; sdev = davinci_spi->bitbang.master->dev.parent; davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select]; tx_reg = (unsigned long)davinci_spi->pbase + SPIDAT1; rx_reg = (unsigned long)davinci_spi->pbase + SPIBUF; davinci_spi->tx = t->tx_buf; davinci_spi->rx = t->rx_buf; /* convert len to words based on bits_per_word */ conv = davinci_spi->slave[spi->chip_select].bytes_per_word; davinci_spi->count = t->len / conv; INIT_COMPLETION(davinci_spi->done); init_completion(&davinci_spi_dma->dma_rx_completion); init_completion(&davinci_spi_dma->dma_tx_completion); word_len = conv * 8; if (word_len <= 8) data_type = DAVINCI_DMA_DATA_TYPE_S8; else if (word_len <= 16) data_type = DAVINCI_DMA_DATA_TYPE_S16; else if (word_len <= 32) data_type = DAVINCI_DMA_DATA_TYPE_S32; else return -EINVAL; ret = davinci_spi_bufs_prep(spi, davinci_spi); if (ret) return ret; /* Put delay val if required */ iowrite32(0 | (pdata->c2tdelay << SPI_C2TDELAY_SHIFT) | (pdata->t2cdelay << SPI_T2CDELAY_SHIFT), davinci_spi->base + SPIDELAY); count = davinci_spi->count; /* the number of elements */ data1_reg_val = pdata->cs_hold << SPIDAT1_CSHOLD_SHIFT; /* CS default = 0xFF */ tmp = ~(0x1 << spi->chip_select); clear_io_bits(davinci_spi->base + SPIDEF, ~tmp); data1_reg_val |= tmp << SPIDAT1_CSNR_SHIFT; /* disable all interrupts for dma transfers */ clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL); /* Disable SPI to write configuration bits in SPIDAT */ clear_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); /* Enable SPI */ set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); while ((ioread32(davinci_spi->base + SPIBUF) & SPIBUF_RXEMPTY_MASK) == 0) cpu_relax(); if (t->tx_buf) { t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf, count, DMA_TO_DEVICE); if (dma_mapping_error(&spi->dev, t->tx_dma)) { dev_dbg(sdev, "Unable to DMA map a %d bytes" " TX buffer\n", count); return -ENOMEM; } temp_count = count; } else { /* We need TX clocking for RX transaction */ t->tx_dma = dma_map_single(&spi->dev, (void *)davinci_spi->tmp_buf, count + 1, DMA_TO_DEVICE); if (dma_mapping_error(&spi->dev, t->tx_dma)) { dev_dbg(sdev, "Unable to DMA map a %d bytes" " TX tmp buffer\n", count); return -ENOMEM; } temp_count = count + 1; } edma_set_transfer_params(davinci_spi_dma->dma_tx_channel, data_type, temp_count, 1, 0, ASYNC); edma_set_dest(davinci_spi_dma->dma_tx_channel, tx_reg, INCR, W8BIT); edma_set_src(davinci_spi_dma->dma_tx_channel, t->tx_dma, INCR, W8BIT); edma_set_src_index(davinci_spi_dma->dma_tx_channel, data_type, 0); edma_set_dest_index(davinci_spi_dma->dma_tx_channel, 0, 0); if (t->rx_buf) { /* initiate transaction */ iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); t->rx_dma = dma_map_single(&spi->dev, (void *)t->rx_buf, count, DMA_FROM_DEVICE); if (dma_mapping_error(&spi->dev, t->rx_dma)) { dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n", count); if (t->tx_buf != NULL) dma_unmap_single(NULL, t->tx_dma, count, DMA_TO_DEVICE); return -ENOMEM; } edma_set_transfer_params(davinci_spi_dma->dma_rx_channel, data_type, count, 1, 0, ASYNC); edma_set_src(davinci_spi_dma->dma_rx_channel, rx_reg, INCR, W8BIT); edma_set_dest(davinci_spi_dma->dma_rx_channel, t->rx_dma, INCR, W8BIT); edma_set_src_index(davinci_spi_dma->dma_rx_channel, 0, 0); edma_set_dest_index(davinci_spi_dma->dma_rx_channel, data_type, 0); } if ((t->tx_buf) || (t->rx_buf)) edma_start(davinci_spi_dma->dma_tx_channel); if (t->rx_buf) edma_start(davinci_spi_dma->dma_rx_channel); if ((t->rx_buf) || (t->tx_buf)) davinci_spi_set_dma_req(spi, 1); if (t->tx_buf) wait_for_completion_interruptible( &davinci_spi_dma->dma_tx_completion); if (t->rx_buf) wait_for_completion_interruptible( &davinci_spi_dma->dma_rx_completion); dma_unmap_single(NULL, t->tx_dma, temp_count, DMA_TO_DEVICE); if (t->rx_buf) dma_unmap_single(NULL, t->rx_dma, count, DMA_FROM_DEVICE); /* * Check for bit error, desync error,parity error,timeout error and * receive overflow errors */ int_status = ioread32(davinci_spi->base + SPIFLG); ret = davinci_spi_check_error(davinci_spi, int_status); if (ret != 0) return ret; /* SPI Framework maintains the count only in bytes so convert back */ davinci_spi->count *= conv; return t->len; }