static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
{
	struct davinci_runtime_data *prtd = substream->runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
	int tcc = TCC_ANY;
	int ret;

	if (!dma_data)
		return -ENODEV;

	prtd->params = dma_data;

	/* Request master DMA channel */
	ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
				  davinci_pcm_dma_irq, substream,
				  &prtd->master_lch, &tcc, EVENTQ_0);
	if (ret)
		return ret;

	/* Request slave DMA channel */
	ret = davinci_request_dma(PARAM_ANY, "Link",
				  NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
	if (ret) {
		davinci_free_dma(prtd->master_lch);
		return ret;
	}

	/* Link slave DMA channel in loopback */
	davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);

	return 0;
}
Exemple #2
0
int DMA_demuxRun(DMA_DemuxPrm *pUserPrm )
{
    DMA_Obj *pObj;
    DMA_DemuxObj *pDemuxObj;
    DRV_DmaDemux *prm;

    DMA_DemuxPrm kernelPrm;

    int i, status;

    status = copy_from_user(&kernelPrm, pUserPrm, sizeof(kernelPrm));
    if (status < 0)
    {
        FUNCERR( "copy_from_user()\n");                    
        return status;
    }

    if (kernelPrm.chId >= DMA_DEV_MAX_CH)
    {
        FUNCERR( "Illegal parameter (chId = %d)\n", kernelPrm.chId );  
        return -1;
    }

    pObj = gDMA_dev.pObj[kernelPrm.chId];
    if (pObj==NULL)
    {
        FUNCERR( "Illegal parameter (chId = %d)\n", kernelPrm.chId );  
        return -1;
    }

    pDemuxObj = pObj->demuxObj;
    if (pDemuxObj==NULL)
    {
        FUNCERR( "Illegal parameter (chId = %d)\n", kernelPrm.chId );    
        return -1;
    }

    prm = &pDemuxObj->demuxPrm;

    memcpy(prm, &kernelPrm.prm, sizeof(pDemuxObj->demuxPrm));

    prm->srcPhysAddrList = pDemuxObj->srcPhysAddrList;
    prm->dstPhysAddrList = pDemuxObj->dstPhysAddrList;

    if (prm->numLines>pDemuxObj->maxLines)
    {
        FUNCERR( "Illegal parameter (chId = %d)\n", kernelPrm.chId );    
        return -1;
    }

    status = copy_from_user(prm->srcPhysAddrList, kernelPrm.prm.srcPhysAddrList, sizeof(unsigned long)*prm->numLines);
    if (status < 0)
    {
        FUNCERR( "copy_from_user() (chId = %d)\n", kernelPrm.chId );    
        return status;
    }

    status = copy_from_user(prm->dstPhysAddrList, kernelPrm.prm.dstPhysAddrList, sizeof(unsigned long)*prm->numLines);
    if (status < 0)
    {
        FUNCERR( "copy_from_user() (chId = %d)\n", kernelPrm.chId );      
        return status;
    }

    pDemuxObj->curLine = 0;

    for (i=0; i<DRV_DMA_MAX_DEMUX_PARAM; i++)
    {
        pDemuxObj->dmaParamDemux[i].a_b_cnt = (uint32_t)(1<<16)|prm->copyWidth;
    }

    for (i=0; i<DRV_DMA_MAX_DEMUX_PARAM; i+=1)
    {
        if (pDemuxObj->curLine<prm->numLines)
        {
            pDemuxObj->dmaParamDemux[i].src = (uint32_t) pDemuxObj->srcPhysAddrList[pDemuxObj->curLine];
            pDemuxObj->dmaParamDemux[i].dst = (uint32_t) pDemuxObj->dstPhysAddrList[pDemuxObj->curLine];
        }
        pDemuxObj->curLine++;
    }

    for (i=0; i<DRV_DMA_MAX_DEMUX_PARAM; i++)
    {
        davinci_set_dma_params(pDemuxObj->channelDemux[i], &pDemuxObj->dmaParamDemux[i]);    
    }

    for (i=1; i<DRV_DMA_MAX_DEMUX_PARAM; i++)
    {
        davinci_dma_link_lch(pDemuxObj->channelDemux[i-1], pDemuxObj->channelDemux[i]);
        davinci_get_dma_params(pDemuxObj->channelDemux[i-1], &pDemuxObj->dmaParamDemux[i-1]);      
    }

#ifdef DMA_DEBUG
    for (i=0; i<DRV_DMA_MAX_DEMUX_PARAM; i++)
    {
        DMA_dumpPARAM("Demux", pDemuxObj->channelDemux[i]);
    }  
#endif

#if 1
    davinci_start_dma(pDemuxObj->channelDemux[0]);

    wait_for_completion_interruptible(&pDemuxObj->dma_complete);

    INIT_COMPLETION(pDemuxObj->dma_complete);
#endif

    return 0;
}
Exemple #3
0
static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
					struct mmc_request *req)
{
	int sync_dev;
	unsigned char i, j;
	unsigned short acnt, bcnt, ccnt;
	unsigned int src_port, dst_port, temp_ccnt;
	enum address_mode mode_src, mode_dst;
	enum fifo_width fifo_width_src, fifo_width_dst;
	unsigned short src_bidx, dst_bidx;
	unsigned short src_cidx, dst_cidx;
	unsigned short bcntrld;
	enum sync_dimension sync_mode;
	edmacc_paramentry_regs temp;
	int edma_chan_num;
	struct mmc_data *data = host->data;
	struct scatterlist *sg = &data->sg[0];
	unsigned int count;
	int num_frames, frame;


	frame = data->blksz;
	count = sg_dma_len(sg);

	if ((data->blocks == 1) && (count > data->blksz))
		count = frame;

	if (count % 32 == 0) {
		acnt = 4;
		bcnt = 8;
		num_frames = count / 32;
	} else {
		acnt = count;
		bcnt = 1;
		num_frames = 1;
	}

	if (num_frames > MAX_C_CNT) {
		temp_ccnt = MAX_C_CNT;
		ccnt = temp_ccnt;
	} else {
		ccnt = num_frames;
		temp_ccnt = ccnt;
	}

	if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
		/*AB Sync Transfer */
		sync_dev = host->dma_tx_event;

		src_port = (unsigned int)sg_dma_address(sg);
		mode_src = INCR;
		fifo_width_src = W8BIT;	/* It's not cared as modeDsr is INCR */
		src_bidx = acnt;
		src_cidx = acnt * bcnt;
		dst_port = host->phys_base + DAVINCI_MMC_REG_DXR;
		mode_dst = INCR;
		fifo_width_dst = W8BIT;	/* It's not cared as modeDsr is INCR */
		dst_bidx = 0;
		dst_cidx = 0;
		bcntrld = 8;
		sync_mode = ABSYNC;
	} else {
		sync_dev = host->dma_rx_event;

		src_port = host->phys_base + DAVINCI_MMC_REG_DRR;
		mode_src = INCR;
		fifo_width_src = W8BIT;
		src_bidx = 0;
		src_cidx = 0;
		dst_port = (unsigned int)sg_dma_address(sg);
		mode_dst = INCR;
		fifo_width_dst = W8BIT;	/* It's not cared as modeDsr is INCR */
		dst_bidx = acnt;
		dst_cidx = acnt * bcnt;
		bcntrld = 8;
		sync_mode = ABSYNC;
	}

	davinci_set_dma_src_params(sync_dev, src_port, mode_src,
				   fifo_width_src);
	davinci_set_dma_dest_params(sync_dev, dst_port, mode_dst,
				    fifo_width_dst);
	davinci_set_dma_src_index(sync_dev, src_bidx, src_cidx);
	davinci_set_dma_dest_index(sync_dev, dst_bidx, dst_cidx);
	davinci_set_dma_transfer_params(sync_dev, acnt, bcnt, ccnt, bcntrld,
					sync_mode);

	davinci_get_dma_params(sync_dev, &temp);
	if (sync_dev == host->dma_tx_event) {
		if (host->option_write == 0) {
			host->option_write = temp.opt;
		} else {
			temp.opt = host->option_write;
			davinci_set_dma_params(sync_dev, &temp);
		}
	}
	if (sync_dev == host->dma_rx_event) {
		if (host->option_read == 0) {
			host->option_read = temp.opt;
		} else {
			temp.opt = host->option_read;
			davinci_set_dma_params(sync_dev, &temp);
		}
	}

	if (host->sg_len > 1) {
		davinci_get_dma_params(sync_dev, &temp);
		temp.opt &= ~TCINTEN;
		davinci_set_dma_params(sync_dev, &temp);

		for (i = 0; i < host->sg_len - 1; i++) {

			sg = &data->sg[i + 1];

			if (i != 0) {
				j = i - 1;
				davinci_get_dma_params(host->edma_ch_details.
						       chanel_num[j], &temp);
				temp.opt &= ~TCINTEN;
				davinci_set_dma_params(host->edma_ch_details.
						       chanel_num[j], &temp);
			}

			edma_chan_num = host->edma_ch_details.chanel_num[0];

			frame = data->blksz;
			count = sg_dma_len(sg);

			if ((data->blocks == 1) && (count > data->blksz))
				count = frame;

			ccnt = count / 32;

			if (sync_dev == host->dma_tx_event)
				temp.src = (unsigned int)sg_dma_address(sg);
			else
				temp.dst = (unsigned int)sg_dma_address(sg);

			temp.opt |= TCINTEN;

			temp.ccnt = (temp.ccnt & 0xFFFF0000) | (ccnt);

			davinci_set_dma_params(edma_chan_num, &temp);
			if (i != 0) {
				j = i - 1;
				davinci_dma_link_lch(host->edma_ch_details.
						     chanel_num[j],
						     edma_chan_num);
			}
		}
		davinci_dma_link_lch(sync_dev,
				     host->edma_ch_details.chanel_num[0]);
	}

	davinci_start_dma(sync_dev);
	return 0;
}