lkml.org 
[lkml]   [2012]   [Feb]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: [PATCH 2/4] i.MX DMA: Add support for 2D transfers.
    From
    Date
    On Fri, 2012-02-10 at 15:31 +0100, Javier Martin wrote:
    > DMAC present in i.MX2 and i.MX1 chips have two
    > 2D configuration slots that any DMA channel can
    > use to make 2D DMA transfers.
    >
    > Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
    > ---
    > arch/arm/mach-imx/dma-v1.c | 86 +++++++++++++++++++++++++++++++
    > arch/arm/mach-imx/include/mach/dma-v1.h | 7 +++
    > 2 files changed, 93 insertions(+), 0 deletions(-)
    >
    > diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c
    > index 42afc29..7401138 100644
    > --- a/arch/arm/mach-imx/dma-v1.c
    > +++ b/arch/arm/mach-imx/dma-v1.c
    > @@ -121,6 +121,9 @@ struct imx_dma_channel {
    >
    > int in_use;
    >
    > + bool enabled_2d;
    > + int slot_2d;
    > +
    > u32 ccr_from_device;
    > u32 ccr_to_device;
    >
    > @@ -129,6 +132,13 @@ struct imx_dma_channel {
    > int hw_chaining;
    > };
    >
    > +struct imx_dma_2d_config {
    > + u16 xsr;
    > + u16 ysr;
    > + u16 wsr;
    > + int count;
    > +};
    > +
    > static void __iomem *imx_dmav1_baseaddr;
    >
    > static void imx_dmav1_writel(unsigned val, unsigned offset)
    > @@ -143,6 +153,9 @@ static unsigned imx_dmav1_readl(unsigned offset)
    >
    > static struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
    >
    > +static struct imx_dma_2d_config imx_dma_2d_slots[IMX_DMA_2D_SLOTS];
    > +static spinlock_t lock_2d;
    > +
    > static struct clk *dma_clk;
    >
    > static int imx_dma_hw_chain(struct imx_dma_channel *imxdma)
    > @@ -369,6 +382,11 @@ imx_dma_config_channel(int channel, unsigned int config_port,
    > imxdma->ccr_from_device = config_port | (config_mem << 2) | dreq;
    > imxdma->ccr_to_device = config_mem | (config_port << 2) | dreq;
    >
    > + if (imxdma->enabled_2d && (imxdma->slot_2d == IMX_DMA_2D_SLOT_B)) {
    > + imxdma->ccr_from_device |= CCR_MSEL_B;
    > + imxdma->ccr_to_device |= CCR_MSEL_B;
    > + }
    > +
    > imx_dmav1_writel(dmareq, DMA_RSSR(channel));
    >
    > return 0;
    > @@ -382,6 +400,63 @@ void imx_dma_config_burstlen(int channel, unsigned int burstlen)
    > EXPORT_SYMBOL(imx_dma_config_burstlen);
    >
    > /**
    > + * imx_dma_config_2d - prepare i.MX DMA channel for a 2D transfer.
    > + * @channel: i.MX DMA channel number
    > + * @x: x-size of the 2D window.
    > + * @y: number of rows that make up the 2D window.
    > + * @w: display size of the 2D window
    > + */
    > +int imx_dma_config_2d(int channel, unsigned int x, unsigned int y,
    > + unsigned int w)
    > +{
    > + struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
    > + int slot = -1;
    > + int i;
    > +
    > + spin_lock(&lock_2d);
    > + /* If the channel already owns a slot, free it first */
    > + if (imxdma->enabled_2d) {
    > + imx_dma_2d_slots[imxdma->slot_2d].count--;
    > + imxdma->enabled_2d = false;
    > + }
    > + /* Try to get free 2D slot */
    > + for (i = 0; i < IMX_DMA_2D_SLOTS; i++) {
    > + if ((imx_dma_2d_slots[i].count > 0) &&
    > + ((imx_dma_2d_slots[i].xsr != x) ||
    > + (imx_dma_2d_slots[i].ysr != y) ||
    > + (imx_dma_2d_slots[i].wsr != w)))
    > + continue;
    > + slot = i;
    > + break;
    > + }
    > + if (slot < 0)
    > + return -EBUSY;
    > +
    > + imx_dma_2d_slots[slot].xsr = x;
    > + imx_dma_2d_slots[slot].ysr = y;
    > + imx_dma_2d_slots[slot].wsr = w;
    > + imx_dma_2d_slots[slot].count++;
    > +
    > + spin_unlock(&lock_2d);
    > +
    > + imxdma->slot_2d = slot;
    > + imxdma->enabled_2d = true;
    > +
    > + if (slot == IMX_DMA_2D_SLOT_A) {
    > + imx_dmav1_writel(x, DMA_XSRA);
    > + imx_dmav1_writel(y, DMA_YSRA);
    > + imx_dmav1_writel(w, DMA_WSRA);
    > + } else {
    > + imx_dmav1_writel(x, DMA_XSRB);
    > + imx_dmav1_writel(y, DMA_YSRB);
    > + imx_dmav1_writel(w, DMA_WSRB);
    > + }
    > +
    > + return 0;
    > +}
    > +EXPORT_SYMBOL(imx_dma_config_2d);
    why EXPORT?? This should be done using the interleaved API
    > +
    > +/**
    > * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification
    > * handlers
    > * @channel: i.MX DMA channel number
    > @@ -732,6 +807,13 @@ void imx_dma_free(int channel)
    > return;
    > }
    >
    > + spin_lock(&lock_2d);
    > + if (imxdma->enabled_2d) {
    > + imx_dma_2d_slots[imxdma->slot_2d].count--;
    > + imxdma->enabled_2d = false;
    > + }
    > + spin_unlock(&lock_2d);
    > +
    > local_irq_save(flags);
    > /* Disable interrupts */
    > imx_dma_disable(channel);
    > @@ -840,6 +922,10 @@ static int __init imx_dma_init(void)
    > imx_dma_channels[i].dma_num = i;
    > }
    >
    > + for (i = 0; i < IMX_DMA_2D_SLOTS; i++)
    > + imx_dma_2d_slots[i].count = 0;
    > + spin_lock_init(&lock_2d);
    > +
    > return ret;
    > }
    >
    > diff --git a/arch/arm/mach-imx/include/mach/dma-v1.h b/arch/arm/mach-imx/include/mach/dma-v1.h
    > index ac6fd71..bab9183 100644
    > --- a/arch/arm/mach-imx/include/mach/dma-v1.h
    > +++ b/arch/arm/mach-imx/include/mach/dma-v1.h
    > @@ -30,6 +30,10 @@
    > #include <mach/dma.h>
    >
    > #define IMX_DMA_CHANNELS 16
    > +#define IMX_DMA_2D_SLOTS 2
    > +
    > +#define IMX_DMA_2D_SLOT_A 0
    > +#define IMX_DMA_2D_SLOT_B 1
    >
    > #define DMA_MODE_READ 0
    > #define DMA_MODE_WRITE 1
    > @@ -64,6 +68,9 @@ void
    > imx_dma_config_burstlen(int channel, unsigned int burstlen);
    >
    > int
    > +imx_dma_config_2d(int channel, unsigned int x, unsigned int y, unsigned int w);
    > +
    > +int
    > imx_dma_setup_single(int channel, dma_addr_t dma_address,
    > unsigned int dma_length, unsigned int dev_addr,
    > unsigned int dmamode);


    --
    ~Vinod



    \
     
     \ /
      Last update: 2012-02-22 14:21    [W:0.061 / U:0.124 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site