> -----Original Message----- > From: svenkatr@xxxxxxxxx [mailto:svenkatr@xxxxxxxxx] On Behalf Of Venkatraman S > Sent: Thursday, April 29, 2010 11:05 PM > To: linux-omap@xxxxxxxxxxxxxxx; linux-mmc@xxxxxxxxxxxxxxx; linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > Cc: Chikkature Rajashekar, Madhusudhan; Adrian Hunter; Tony Lindgren; Shilimkar, Santosh > Subject: [PATCH v8 1/2] sDMA: descriptor autoloading feature > > From d46f8a00728cc6c1fbdfce69435759c8cc49f25c Mon Sep 17 00:00:00 2001 > From: Venkatraman S <svenkatr@xxxxxx> > Date: Thu, 29 Apr 2010 22:34:04 +0530 > Subject: [PATCH 1/2] sDMA: descriptor autoloading feature > > Add sDMA driver support for descriptor autoloading feature. > Descriptor autoloading is OMAP sDMA v5 hardware capability that can > be exploited for scatter gather > scenarios, currently available in OMAP3630 and OMAP4430. > > The feature works as described below. > 1) A sDMA channel is programmed to be in 'linked list' mode. > 2) The client (sDMA user) provides a list of descriptors in a linked > list format. > 3) Each of the 'descriptor' (element in the linked list) contains an > updated set of DMA > configuration register values. > 4) Client starts DMA transfer. > 5) sDMA controller loads the first element to its register > configuration memory and executes the > transfer. > 6) After completion, loads the next element (in linked list) to > configuration memory and executes > the transfer, without MCU intervention. > 7) Interrupt is generated after all transfers are completed; this > can be configured to be done > differently. > > Configurations and additional features > 1) Fast mode & non-fast mode > Fast mode/non-fast decides on how the first transfer begins. > In non-fast mode, the first > element in the linked list is loaded only after completing the > transfer according to the > configurations already in the sDMA channel registers. In fast mode, > the loading of the first > element precedes the transfer. > > 2) Pause / resume of transfers > A transfer can be paused after a descriptor set has been loaded, > provided the 'pause > bit' is set in the linked list element. > An ongoing transfer cannot be paused. If the 'pause bit' is set, > transfer is not > started after loading the register set from memory. > Such a transfer can be resumed later. > > 3) Descriptor types > 3 possible configurations of descriptors (initialized as linked list elements) > are possible. Type 1 provides the maximum flexibility, which contains most > register definitions of a DMA logical channel. Fewer options are > present in type > 2. Type 3 can just modify source/destinations address of transfers. In all > transfers, unmodified registers settings are maintained for the next transfer. > > Patch provides options / API for > 1) Setting up a descriptor loading for DMA channel for sg type transfers > 2) configuration with linked list elements > 3) Starting / pause and resume of the said transfers, query state > 4) Clearing the sglist mode > > Signed-off-by: Venkatraman S <svenkatr@xxxxxx> > CC: Adrian Hunter <adrian.hunter@xxxxxxxxx> > CC: Madhusudhan C <madhu.cr@xxxxxx> > CC: Shilimkar Santosh <santosh.shilimkar@xxxxxx> > CC: Tony Lindgren <tony@xxxxxxxxxxx> > --- > Changes from v7: > * Added wmb() calls between descriptor data structure update and > start/resume of transfer > * Added proper commit log about the feature > > arch/arm/plat-omap/dma.c | 289 ++++++++++++++++++++++++++++++++- > arch/arm/plat-omap/include/plat/dma.h | 170 +++++++++++++++++++ > 2 files changed, 458 insertions(+), 1 deletions(-) > > diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c > index f6c9bdc..d8d4df8 100644 > --- a/arch/arm/plat-omap/dma.c > +++ b/arch/arm/plat-omap/dma.c > @@ -46,12 +46,40 @@ enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, > DMA_CH_STARTED, > enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; > #endif > > +/* CDP Register bitmaps */ > +#define DMA_LIST_CDP_DST_VALID (BIT(0)) > +#define DMA_LIST_CDP_SRC_VALID (BIT(2)) > +#define DMA_LIST_CDP_TYPE1 (BIT(4)) > +#define DMA_LIST_CDP_TYPE2 (BIT(5)) > +#define DMA_LIST_CDP_TYPE3 (BIT(4) | BIT(5)) > +#define DMA_LIST_CDP_PAUSEMODE (BIT(7)) > +#define DMA_LIST_CDP_LISTMODE (BIT(8)) > +#define DMA_LIST_CDP_FASTMODE (BIT(10)) > +/* CAPS register bitmaps */ > +#define DMA_CAPS_SGLIST_SUPPORT (BIT(20)) > + > +#define DMA_LIST_DESC_PAUSE (BIT(0)) > +#define DMA_LIST_DESC_SRC_VALID (BIT(24)) > +#define DMA_LIST_DESC_DST_VALID (BIT(26)) > +#define DMA_LIST_DESC_BLK_END (BIT(28)) > + > #define OMAP_DMA_ACTIVE 0x01 > #define OMAP2_DMA_CSR_CLEAR_MASK 0xffe > > #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) > +#define OMAP_DMA_INVALID_FRAME_COUNT (0xffff) > +#define OMAP_DMA_INVALID_ELEM_COUNT (0xffffff) > +#define OMAP_DMA_INVALID_DESCRIPTOR_POINTER (0xfffffffc) > > static int enable_1510_mode; > +static int dma_caps0_status; > + > +struct omap_dma_list_config_params { > + unsigned int num_elem; > + struct omap_dma_sglist_node *sghead; > + dma_addr_t sgheadphy; > + unsigned int pausenode; > +}; > > static struct omap_dma_global_context_registers { > u32 dma_irqenable_l0; > @@ -74,9 +102,10 @@ struct omap_dma_lch { > int next_linked_ch; > int state; > int chain_id; > - > int status; > + struct omap_dma_list_config_params list_config; > #endif > + > long flags; > }; > > @@ -214,6 +243,76 @@ static void clear_lch_regs(int lch) > __raw_writew(0, lch_base + i); > } > > +static inline void omap_dma_list_set_ntype(struct omap_dma_sglist_node *node, > + int value) > +{ > + node->num_of_elem |= ((value) << 29); > +} > + > +static void omap_set_dma_sglist_pausebit( > + struct omap_dma_list_config_params *lcfg, int nelem, int set) > +{ > + struct omap_dma_sglist_node *sgn = lcfg->sghead; > + > + if (nelem > 0 && nelem < lcfg->num_elem) { > + lcfg->pausenode = nelem; > + sgn += nelem; > + > + if (set) > + sgn->next_desc_add_ptr |= DMA_LIST_DESC_PAUSE; > + else > + sgn->next_desc_add_ptr &= ~(DMA_LIST_DESC_PAUSE); > + } > +} > + > +static int dma_sglist_set_phy_params(struct omap_dma_sglist_node *sghead, > + dma_addr_t phyaddr, int nelem) > +{ > + struct omap_dma_sglist_node *sgcurr, *sgprev; > + dma_addr_t elem_paddr = phyaddr; > + > + for (sgprev = sghead; > + sgprev < sghead + nelem; > + sgprev++) { > + > + sgcurr = sgprev + 1; > + sgprev->next = sgcurr; > + elem_paddr += (int)sizeof(*sgcurr); > + sgprev->next_desc_add_ptr = elem_paddr; > + > + switch (sgcurr->desc_type) { > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1: > + omap_dma_list_set_ntype(sgprev, 1); > + break; > + > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a: > + /* intentional no break */ > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b: > + omap_dma_list_set_ntype(sgprev, 2); > + break; > + > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a: > + /* intentional no break */ > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b: > + omap_dma_list_set_ntype(sgprev, 3); > + break; > + > + default: > + return -EINVAL; > + > + } Are we supporting all the descriptor types. I think only type2a is supported. In that case please add FIXME, or WARN message here. > + if (sgcurr->flags & OMAP_DMA_LIST_SRC_VALID) > + sgprev->num_of_elem |= DMA_LIST_DESC_SRC_VALID; > + if (sgcurr->flags & OMAP_DMA_LIST_DST_VALID) > + sgprev->num_of_elem |= DMA_LIST_DESC_DST_VALID; > + if (sgcurr->flags & OMAP_DMA_LIST_NOTIFY_BLOCK_END) > + sgprev->num_of_elem |= DMA_LIST_DESC_BLK_END; > + } > + sgprev--; > + sgprev->next_desc_add_ptr = OMAP_DMA_INVALID_DESCRIPTOR_POINTER; > + return 0; > +} > + > void omap_set_dma_priority(int lch, int dst_port, int priority) > { > unsigned long reg; > @@ -825,6 +924,7 @@ void omap_free_dma(int lch) > /* Make sure the DMA transfer is stopped. */ > dma_write(0, CCR(lch)); > omap_clear_dma(lch); > + omap_clear_dma_sglist_mode(lch); > } > > spin_lock_irqsave(&dma_chan_lock, flags); > @@ -1818,6 +1918,192 @@ int omap_get_dma_chain_src_pos(int chain_id) > EXPORT_SYMBOL(omap_get_dma_chain_src_pos); > #endif /* ifndef CONFIG_ARCH_OMAP1 */ > > +int omap_set_dma_sglist_mode(int lch, struct omap_dma_sglist_node *sgparams, > + dma_addr_t padd, int nelem, struct omap_dma_channel_params *chparams) > +{ > + struct omap_dma_list_config_params *lcfg; > + int l = DMA_LIST_CDP_LISTMODE; /* Enable Linked list mode in CDP */ > + > + if ((dma_caps0_status & DMA_CAPS_SGLIST_SUPPORT) == 0) { > + printk(KERN_ERR "omap DMA: sglist feature not supported\n"); > + return -EPERM; > + } > + if (dma_chan[lch].flags & OMAP_DMA_ACTIVE) { > + printk(KERN_ERR "omap DMA: configuring active DMA channel\n"); > + return -EPERM; > + } > + > + if (padd == 0) { > + printk(KERN_ERR "omap DMA: sglist invalid dma_addr\n"); > + return -EINVAL; > + } > + lcfg = &dma_chan[lch].list_config; > + > + lcfg->sghead = sgparams; > + lcfg->num_elem = nelem; > + lcfg->sgheadphy = padd; > + lcfg->pausenode = -1; > + > + > + if (NULL == chparams) Minute point really. Better readability "ch_params" > + l |= DMA_LIST_CDP_FASTMODE; > + else > + omap_set_dma_params(lch, chparams); > + > + dma_write(l, CDP(lch)); > + dma_write(0, CCDN(lch)); /* Reset List index numbering */ > + /* Initialize frame and element counters to invalid values */ > + dma_write(OMAP_DMA_INVALID_FRAME_COUNT, CCFN(lch)); > + dma_write(OMAP_DMA_INVALID_ELEM_COUNT, CCEN(lch)); > + > + return dma_sglist_set_phy_params(sgparams, lcfg->sgheadphy, nelem); > + > +} > +EXPORT_SYMBOL(omap_set_dma_sglist_mode); > + > +void omap_clear_dma_sglist_mode(int lch) > +{ > + /* Clear entire CDP which is related to sglist handling */ > + dma_write(0, CDP(lch)); > + dma_write(0, CCDN(lch)); > + /** > + * Put back the original enabled irqs, which > + * could have been overwritten by type 1 or type 2 > + * descriptors > + */ > + dma_write(dma_chan[lch].enabled_irqs, CICR(lch)); > + return; > +} > +EXPORT_SYMBOL(omap_clear_dma_sglist_mode); > + > +int omap_start_dma_sglist_transfers(int lch, int pauseafter) > +{ > + struct omap_dma_list_config_params *lcfg; > + struct omap_dma_sglist_node *sgn; > + unsigned int l, type_id; > + > + lcfg = &dma_chan[lch].list_config; > + sgn = lcfg->sghead; > + > + lcfg->pausenode = 0; > + omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1); > + > + /* Program the head descriptor's properties into CDP */ > + switch (lcfg->sghead->desc_type) { > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1: > + type_id = DMA_LIST_CDP_TYPE1; > + break; > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a: > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b: > + type_id = DMA_LIST_CDP_TYPE2; > + break; > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a: > + case OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b: > + type_id = DMA_LIST_CDP_TYPE3; > + break; > + default: > + return -EINVAL; > + } > + > + l = dma_read(CDP(lch)); > + l |= type_id; > + if (lcfg->sghead->flags & OMAP_DMA_LIST_SRC_VALID) > + l |= DMA_LIST_CDP_SRC_VALID; > + if (lcfg->sghead->flags & OMAP_DMA_LIST_DST_VALID) > + l |= DMA_LIST_CDP_DST_VALID; > + > + dma_write(l, CDP(lch)); > + dma_write((lcfg->sgheadphy), CNDP(lch)); > + /** > + * Barrier needed as writes to the > + * descriptor memory needs to be flushed > + * before it's used by DMA controller > + */ Little bit of re-wording if you can. Also you don't wanted the double ** /* * Memory barrier is needed because data may still be * in the write buffer. The barrier drains write buffers and * ensures that DMA sees correct descriptors */ > + wmb(); > + omap_start_dma(lch); > + > + return 0; > +} > +EXPORT_SYMBOL(omap_start_dma_sglist_transfers); > + > +int omap_resume_dma_sglist_transfers(int lch, int pauseafter) > +{ > + struct omap_dma_list_config_params *lcfg; > + struct omap_dma_sglist_node *sgn; > + int l, sys_cf; > + > + lcfg = &dma_chan[lch].list_config; > + sgn = lcfg->sghead; > + > + /* Maintain the pause state in descriptor */ > + omap_set_dma_sglist_pausebit(lcfg, lcfg->pausenode, 0); > + omap_set_dma_sglist_pausebit(lcfg, pauseafter, 1); > + > + /** > + * Barrier needed as writes to the > + * descriptor memory needs to be flushed > + * before it's used by DMA controller > + */ Description change if possible > + wmb(); > + > + /* Errata i557 - pausebit should be cleared in no standby mode */ This should have been > + sys_cf = dma_read(OCP_SYSCONFIG); > + l = sys_cf; > + /* Middle mode reg set no Standby */ > + l &= ~(BIT(12) | BIT(13)); > + dma_write(l, OCP_SYSCONFIG); > + > + /* Clear pause bit in CDP */ > + l = dma_read(CDP(lch)); > + l &= ~(DMA_LIST_CDP_PAUSEMODE); > + dma_write(l, CDP(lch)); > + > + omap_start_dma(lch); > + > + /* Errata i557 - put in the old value */ > + dma_write(sys_cf, OCP_SYSCONFIG); > + return 0; > +} > +EXPORT_SYMBOL(omap_resume_dma_sglist_transfers); > + > +void omap_release_dma_sglist(int lch) > +{ > + omap_clear_dma_sglist_mode(lch); > + omap_free_dma(lch); > + > + return; > +} > +EXPORT_SYMBOL(omap_release_dma_sglist); > + > +int omap_get_completed_sglist_nodes(int lch) > +{ > + int list_count; > + > + list_count = dma_read(CCDN(lch)); > + return list_count & 0xffff; /* only 16 LSB bits are valid */ > +} > +EXPORT_SYMBOL(omap_get_completed_sglist_nodes); > + > +int omap_dma_sglist_is_paused(int lch) > +{ > + int list_state; > + list_state = dma_read(CDP(lch)); > + return (list_state & DMA_LIST_CDP_PAUSEMODE) ? 1 : 0; > +} > +EXPORT_SYMBOL(omap_dma_sglist_is_paused); > + > +void omap_dma_set_sglist_fastmode(int lch, int fastmode) > +{ > + int l = dma_read(CDP(lch)); > + > + if (fastmode) > + l |= DMA_LIST_CDP_FASTMODE; > + else > + l &= ~(DMA_LIST_CDP_FASTMODE); > + dma_write(l, CDP(lch)); > +} > +EXPORT_SYMBOL(omap_dma_set_sglist_fastmode); > + > /*----------------------------------------------------------------------------*/ > > #ifdef CONFIG_ARCH_OMAP1 > @@ -2066,6 +2352,7 @@ static int __init omap_init_dma(void) > r = -ENOMEM; > goto out_free; > } > + dma_caps0_status = dma_read(CAPS_0); > } > > if (cpu_is_omap15xx()) { > diff --git a/arch/arm/plat-omap/include/plat/dma.h > b/arch/arm/plat-omap/include/plat/dma.h > index 02232ca..7490df9 100644 > --- a/arch/arm/plat-omap/include/plat/dma.h > +++ b/arch/arm/plat-omap/include/plat/dma.h > @@ -115,8 +115,12 @@ > #define OMAP1_DMA_COLOR_U(n) (0x40 * (n) + 0x22) > #define OMAP1_DMA_CCR2(n) (0x40 * (n) + 0x24) > #define OMAP1_DMA_LCH_CTRL(n) (0x40 * (n) + 0x2a) /* not on 15xx */ > +#define OMAP1_DMA_COLOR(n) 0 > #define OMAP1_DMA_CCEN(n) 0 > #define OMAP1_DMA_CCFN(n) 0 > +#define OMAP1_DMA_CDP(n) 0 > +#define OMAP1_DMA_CNDP(n) 0 > +#define OMAP1_DMA_CCDN(n) 0 > > /* Channel specific registers only on omap2 */ > #define OMAP_DMA4_CSSA(n) (0x60 * (n) + 0x9c) > @@ -135,6 +139,8 @@ > #define OMAP1_DMA_IRQSTATUS_L0 0 > #define OMAP1_DMA_IRQENABLE_L0 0 > #define OMAP1_DMA_OCP_SYSCONFIG 0 > +#define OMAP1_DMA_CAPS_0 0 > + > #define OMAP_DMA4_HW_ID 0 > #define OMAP_DMA4_CAPS_0_L 0 > #define OMAP_DMA4_CAPS_0_U 0 > @@ -463,6 +469,83 @@ struct omap_dma_channel_params { > #endif > }; > > +struct omap_dma_sglist_type1_params { > + u32 src_addr; > + u32 dst_addr; > + u16 cfn_fn; > + u16 cicr; > + u16 dst_elem_idx; > + u16 src_elem_idx; > + u32 dst_frame_idx_or_pkt_size; > + u32 src_frame_idx_or_pkt_size; > + u32 color; > + u32 csdp; > + u32 clnk_ctrl; > + u32 ccr; > +}; > + > +struct omap_dma_sglist_type2a_params { > + u32 src_addr; > + u32 dst_addr; > + u16 cfn_fn; > + u16 cicr; > + u16 dst_elem_idx; > + u16 src_elem_idx; > + u32 dst_frame_idx_or_pkt_size; > + u32 src_frame_idx_or_pkt_size; > +}; > + > +struct omap_dma_sglist_type2b_params { > + u32 src_or_dest_addr; > + u16 cfn_fn; > + u16 cicr; > + u16 dst_elem_idx; > + u16 src_elem_idx; > + u32 dst_frame_idx_or_pkt_size; > + u32 src_frame_idx_or_pkt_size; > +}; > + > +struct omap_dma_sglist_type3a_params { > + u32 src_addr; > + u32 dst_addr; > +}; > + > +struct omap_dma_sglist_type3b_params { > + u32 src_or_dest_addr; > +}; > + > +enum omap_dma_sglist_descriptor_select { > + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE1, > + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2a, > + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE2b, > + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3a, > + OMAP_DMA_SGLIST_DESCRIPTOR_TYPE3b, > +}; > + > +union omap_dma_sglist_node_type{ > + struct omap_dma_sglist_type1_params t1; > + struct omap_dma_sglist_type2a_params t2a; > + struct omap_dma_sglist_type2b_params t2b; > + struct omap_dma_sglist_type3a_params t3a; > + struct omap_dma_sglist_type3b_params t3b; > +}; > + > +struct omap_dma_sglist_node { > + > + /* Common elements for all descriptors */ > + dma_addr_t next_desc_add_ptr; > + u32 num_of_elem; > + /* Type specific elements */ > + union omap_dma_sglist_node_type sg_node; > + /* Control fields */ > + unsigned short flags; > + /* Fields that can be set in flags variable */ > + #define OMAP_DMA_LIST_SRC_VALID BIT(0) > + #define OMAP_DMA_LIST_DST_VALID BIT(1) > + #define OMAP_DMA_LIST_NOTIFY_BLOCK_END BIT(2) > + enum omap_dma_sglist_descriptor_select desc_type; > + struct omap_dma_sglist_node *next; > +}; > > extern void omap_set_dma_priority(int lch, int dst_port, int priority); > extern int omap_request_dma(int dev_id, const char *dev_name, > @@ -548,6 +631,93 @@ extern int omap_modify_dma_chain_params(int chain_id, > extern int omap_dma_chain_status(int chain_id); > #endif > > +/** > + * omap_set_dma_sglist_mode() Switch channel to scatter gather mode > + * @lch: Logical channel to switch to sglist mode > + * @sghead: Contains the descriptor elements to be executed > + * Should be allocated using dma_alloc_coherent > + * @padd: The dma address of sghead, as returned by dma_alloc_coherent > + * @nelem: Number of elements in sghead > + * @chparams: DMA channel transfer parameters. Can be NULL > + */ > +extern int omap_set_dma_sglist_mode(int lch, > + struct omap_dma_sglist_node *sghead, dma_addr_t padd, > + int nelem, struct omap_dma_channel_params *chparams); > + > +/** > + * omap_clear_dma_sglist_mode() Switch from scatter gather mode > + * to normal mode > + * @lch: The logical channel to be switched to normal mode > + * > + * Switches the requested logical channel to normal mode > + * from scatter gather mode > + */ > +extern void omap_clear_dma_sglist_mode(int lch); > + > +/** > + * omap_start_dma_sglist_transfers() Starts the sglist transfer > + * @lch: logical channel on which sglist transfer to be started > + * @pauseafter: index of the element on which to pause the transfer > + * set to -1 if no pause is needed till end of transfer > + * > + * Start the dma transfer in list mode > + * The index (in pauseafter) is absolute (from the head of the list) > + * User should have previously called omap_set_dma_sglist_mode() > + */ > +extern int omap_start_dma_sglist_transfers(int lch, int pauseafter); > + > +/** > + * omap_resume_dma_sglist_transfers() Resumes a previously paused > + * sglist transfer > + * @lch: The logical channel to be resumed > + * @pauseafter: The index of sglist to be paused again > + * set to -1 if no pause is needed till end of transfer > + * > + * Resume the previously paused transfer > + * The index (in pauseafter) is absolute (from the head of the list) > + */ > +extern int omap_resume_dma_sglist_transfers(int lch, int pauseafter); > + > +/** > + * omap_release_dma_sglist() Releases a previously requested > + * DMA channel which is in sglist mode > + * @lch: The logical channel to be released > + */ > +extern void omap_release_dma_sglist(int lch); > + > +/** > + * omap_get_completed_sglist_nodes() Returns a list of completed > + * sglist nodes > + * @lch: The logical on which the query is to be made > + * > + * Returns the number of completed elements in the linked list > + * The value is transient if the API is invoked for an ongoing transfer > + */ > +int omap_get_completed_sglist_nodes(int lch); > + > +/** > + * omap_dma_sglist_is_paused() Query is the logical channel in > + * sglist mode is paused or note > + * @lch: The logical on which the query is to be made > + * > + * Returns non zero if the linked list is currently in pause state > + */ > +int omap_dma_sglist_is_paused(int lch); > + > +/** > + * omap_dma_set_sglist_fastmode() Set the sglist transfer to fastmode > + * @lch: The logical channel which is to be changed to fastmode > + * @fastmode: Set or clear the fastmode status > + * 1 = set fastmode > + * 0 = clear fastmode > + * > + * In fastmode, DMA register settings are updated from the first element > + * of the linked list, before initiating the tranfer. > + * In non-fastmode, the first element is used only after completing the > + * transfer as already configured in the registers > + */ > +void omap_dma_set_sglist_fastmode(int lch, int fastmode); > + > #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_FB_OMAP) > #include <mach/lcd_dma.h> > #else > -- > 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html