On Fri, 2012-04-20 at 14:38 +0530, Laxman Dewangan wrote:
+ * dma_transfer_mode: Different dma transfer mode.
+ * DMA_MODE_ONCE: Dma transfer the configured buffer once and at the end ofwhy do you need to define this? use the cyclic api to convey this
+ * transfer, dma stops automatically and generates interrupt
+ * if enabled. SW need to reprogram dma for next transfer.
+ * DMA_MODE_CYCLE: Dma keeps transferring the same buffer again and again
+ * until dma stopped explicitly by SW or another buffer configured.
+ * After transfer completes, dma again starts transfer from
+ * beginning of buffer without sw intervention. If any new
+ * address/size is configured during buffer transfer then
+ * dma start transfer with new configuration otherwise it
+ * will keep transferring with old configuration. It also
+ * generates the interrupt after buffer transfer completes.
+ * DMA_MODE_CYCLE_HALF_NOTIFY: In this mode dma keeps transferring the bufferisnt this a specifc example of cylci and frankly why should dmaengine
+ * into two folds. This is kind of ping-pong buffer where both
+ * buffer size should be same. Dma completes the one buffer,
+ * generates interrupt and keep transferring the next buffer
+ * whose address start just next to first buffer. At the end of
+ * second buffer transfer, dma again generates interrupt and
+ * keep transferring of the data from starting of first buffer.
+ * If sw wants to change the address/size of the buffer then
+ * it needs to change only when dma transferring the second
+ * half of buffer. In dma configuration, it only need to
+ * configure starting of first buffer and size of first buffer.
+ * Dma hw assumes that striating address of second buffer is just
+ * next to end of first buffer and size is same as the first
+ * buffer.
care about this. This one of the configurations you are passing for a
cyclic dma operation
+ */this seems questionable too...
+enum dma_transfer_mode {
+ DMA_MODE_NONE,
+ DMA_MODE_ONCE,
+ DMA_MODE_CYCLE,
+ DMA_MODE_CYCLE_HALF_NOTIFY,
+};
+
+/* List of memory allocated for that channel */
+struct tegra_dma_chan_mem_alloc {
+ struct list_head node;
+};
+ * The client's request for data transfer can be broken into multipletypo ^^^^^^^^^
+ * sub-transfer as per requestor details and hw support.
Will fix this, thanks for pointing. My spell check did not found it.+ * tegra_dma_desc: Tegra dma descriptors which manages the client requests.again ^^^^
+ * This de scripts keep track of transfer status, callbacks, transfer and
+what does the last arg mean?
+static dma_cookie_t tegra_dma_tx_submit(struct dma_async_tx_descriptor *tx);
+
+static int allocate_tegra_desc(struct tegra_dma_channel *tdc,
+ int ndma_desc, int nsg_req)
+ INIT_LIST_HEAD(&sg_req_list);why cant you simply allocate three structs you need?
+
+ /* Calculate total require size of memory and then allocate */
+ dma_desc_size = sizeof(struct tegra_dma_desc) * ndma_desc;
+ sg_req_size = sizeof(struct tegra_dma_sg_req) * nsg_req;
+ chan_mem_size = sizeof(struct tegra_dma_chan_mem_alloc);
+ total_size = chan_mem_size + dma_desc_size + sg_req_size;
+static int tegra_dma_slave_config(struct dma_chan *dc,private is deprecated, pls dont use that
+ struct dma_slave_config *sconfig)
+{
+ struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
+
+ if (!list_empty(&tdc->pending_sg_req)) {
+ dev_err(tdc2dev(tdc),
+ "dma requests are pending, cannot take new configuration");
+ return -EBUSY;
+ }
+
+ /* Slave specific configuration is must for channel configuration */
+ if (!dc->private) {
+you dont support DMA_MEM_TO_DEV?
+ apb_seq = APB_SEQ_WRAP_WORD_1;
+
+ switch (direction) {
+ case DMA_MEM_TO_DEV:
+ apb_ptr = tdc->dma_sconfig.dst_addr;
+ apb_seq |= get_bus_width(tdc->dma_sconfig.dst_addr_width);
+ csr |= CSR_DIR;
+ break;
+
+ case DMA_DEV_TO_MEM:
+ apb_ptr = tdc->dma_sconfig.src_addr;
+ apb_seq |= get_bus_width(tdc->dma_sconfig.src_addr_width);
+ break;
+ if (!period_len)i am not sure about this assignment here. Why should period length be
+ period_len = buf_len;
ZERO?
+I am assuming you are also putting this as a constraint in sound driver.
+ if (buf_len % period_len) {
+ dev_err(tdc2dev(tdc),
+ "buf_len %d should be multiple of period_len %d\n",
+ buf_len, period_len);
+ return NULL;
+ }
+not supported would be apt
+ half_buffer_notify = (buf_len == (2 * period_len)) ? true : false;
+ len = (half_buffer_notify) ? buf_len / 2 : period_len;
+ if ((len& 3) || (buf_addr& 3) ||
+ (len> tdc->tdma->chip_data.max_dma_count)) {
+ dev_err(tdc2dev(tdc),
+ "Dma length/memory address is not correct\n");
+#ifndef LINUX_TEGRA_DMA_Hwhy should this be global, clinet should pass them as defined in
+#define LINUX_TEGRA_DMA_H
+
+/*
+ * tegra_dma_burst_size: Burst size of dma.
+ * @TEGRA_DMA_AUTO: Based on transfer size, select the burst size.
+ * If it is multple of 32 bytes then burst size will be 32 bytes else
+ * If it is multiple of 16 bytes then burst size will be 16 bytes else
+ * If it is multiple of 4 bytes then burst size will be 4 bytes.
+ * @TEGRA_DMA_BURST_1: Burst size is 1 word/4 bytes.
+ * @TEGRA_DMA_BURST_4: Burst size is 4 word/16 bytes.
+ * @TEGRA_DMA_BURST_8: Burst size is 8 words/32 bytes.
+ */
+enum tegra_dma_burst_size {
+ TEGRA_DMA_AUTO,
+ TEGRA_DMA_BURST_1,
+ TEGRA_DMA_BURST_4,
+ TEGRA_DMA_BURST_8,
+};
dmaengine.h
+ * @dma_dev: required DMA master client device.pls remove
+ * @dm_req_id: Peripheral dma requestor ID.
+ */
+struct tegra_dma_slave {
+ struct device *client_dev;
+ enum tegra_dma_requestor dma_req_id;
+ enum tegra_dma_burst_size burst_size;
+};Please also update the driver to use the cookie helpers in
+
+#endif /* LINUX_TEGRA_DMA_H */
drivers/dma/dmaengine.h