[media] media: omap3isp: hist: Move histogram DMA to DMA engine
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Sat, 21 Feb 2015 20:59:54 +0000 (17:59 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Thu, 2 Apr 2015 19:37:13 +0000 (16:37 -0300)
Replace the custom OMAP DMA API usage by DMA engine. Feature-wise the
driver has lost the ability to get notified of DMA transfers failure
through the completion handler, as the DMA engine API doesn't expose
that status information.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/platform/omap3isp/isph3a_aewb.c
drivers/media/platform/omap3isp/isph3a_af.c
drivers/media/platform/omap3isp/isphist.c
drivers/media/platform/omap3isp/ispstat.c
drivers/media/platform/omap3isp/ispstat.h

index b208c5417146e081facc8675f345f221e346f567..ccaf92f39236c9d43a3ccd549b1e7a98492c0a03 100644 (file)
@@ -297,7 +297,6 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
 
        aewb->ops = &h3a_aewb_ops;
        aewb->priv = aewb_cfg;
-       aewb->dma_ch = -1;
        aewb->event_type = V4L2_EVENT_OMAP3ISP_AEWB;
        aewb->isp = isp;
 
index 8a83e195f3e30443dc914a4d10dc12edc90f02a9..92937f7eeceff799c8ba79f4dd59b2579ab97203 100644 (file)
@@ -360,7 +360,6 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
 
        af->ops = &h3a_af_ops;
        af->priv = af_cfg;
-       af->dma_ch = -1;
        af->event_type = V4L2_EVENT_OMAP3ISP_AF;
        af->isp = isp;
 
index ce822c34c843a7d9c92c020ccd9d19526ac32af1..738b946ddb37ad511c87101974dac0fb141c1f5f 100644 (file)
  */
 
 #include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/omap-dmaengine.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
-#include <linux/device.h>
 
 #include "isp.h"
 #include "ispreg.h"
 #include "isphist.h"
 
-#define OMAP24XX_DMA_NO_DEVICE         0
-
 #define HIST_CONFIG_DMA        1
 
-#define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0)
-
 /*
  * hist_reset_mem - clear Histogram memory before start stats engine.
  */
@@ -62,20 +60,6 @@ static void hist_reset_mem(struct ispstat *hist)
        hist->wait_acc_frames = conf->num_acc_frames;
 }
 
-static void hist_dma_config(struct ispstat *hist)
-{
-       struct isp_device *isp = hist->isp;
-
-       hist->dma_config.data_type = OMAP_DMA_DATA_TYPE_S32;
-       hist->dma_config.sync_mode = OMAP_DMA_SYNC_ELEMENT;
-       hist->dma_config.frame_count = 1;
-       hist->dma_config.src_amode = OMAP_DMA_AMODE_CONSTANT;
-       hist->dma_config.src_start = isp->mmio_base_phys[OMAP3_ISP_IOMEM_HIST]
-                                  + ISPHIST_DATA;
-       hist->dma_config.dst_amode = OMAP_DMA_AMODE_POST_INC;
-       hist->dma_config.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
-}
-
 /*
  * hist_setup_regs - Helper function to update Histogram registers.
  */
@@ -176,17 +160,12 @@ static int hist_busy(struct ispstat *hist)
                                                & ISPHIST_PCR_BUSY;
 }
 
-static void hist_dma_cb(int lch, u16 ch_status, void *data)
+static void hist_dma_cb(void *data)
 {
        struct ispstat *hist = data;
 
-       if (ch_status & ~OMAP_DMA_BLOCK_IRQ) {
-               dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n",
-                       ch_status);
-               omap_stop_dma(lch);
-               hist_reset_mem(hist);
-               atomic_set(&hist->buf_err, 1);
-       }
+       /* FIXME: The DMA engine API can't report transfer errors :-/ */
+
        isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
                    ISPHIST_CNT_CLEAR);
 
@@ -198,24 +177,58 @@ static void hist_dma_cb(int lch, u16 ch_status, void *data)
 static int hist_buf_dma(struct ispstat *hist)
 {
        dma_addr_t dma_addr = hist->active_buf->dma_addr;
+       struct dma_async_tx_descriptor *tx;
+       struct dma_slave_config cfg;
+       dma_cookie_t cookie;
+       int ret;
 
        if (unlikely(!dma_addr)) {
                dev_dbg(hist->isp->dev, "hist: invalid DMA buffer address\n");
-               hist_reset_mem(hist);
-               return STAT_NO_BUF;
+               goto error;
        }
 
        isp_reg_writel(hist->isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
        isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
                    ISPHIST_CNT_CLEAR);
        omap3isp_flush(hist->isp);
-       hist->dma_config.dst_start = dma_addr;
-       hist->dma_config.elem_count = hist->buf_size / sizeof(u32);
-       omap_set_dma_params(hist->dma_ch, &hist->dma_config);
 
-       omap_start_dma(hist->dma_ch);
+       memset(&cfg, 0, sizeof(cfg));
+       cfg.src_addr = hist->isp->mmio_base_phys[OMAP3_ISP_IOMEM_HIST]
+                    + ISPHIST_DATA;
+       cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       cfg.src_maxburst = hist->buf_size / 4;
+
+       ret = dmaengine_slave_config(hist->dma_ch, &cfg);
+       if (ret < 0) {
+               dev_dbg(hist->isp->dev,
+                       "hist: DMA slave configuration failed\n");
+               goto error;
+       }
+
+       tx = dmaengine_prep_slave_single(hist->dma_ch, dma_addr,
+                                        hist->buf_size, DMA_DEV_TO_MEM,
+                                        DMA_CTRL_ACK);
+       if (tx == NULL) {
+               dev_dbg(hist->isp->dev,
+                       "hist: DMA slave preparation failed\n");
+               goto error;
+       }
+
+       tx->callback = hist_dma_cb;
+       tx->callback_param = hist;
+       cookie = tx->tx_submit(tx);
+       if (dma_submit_error(cookie)) {
+               dev_dbg(hist->isp->dev, "hist: DMA submission failed\n");
+               goto error;
+       }
+
+       dma_async_issue_pending(hist->dma_ch);
 
        return STAT_BUF_WAITING_DMA;
+
+error:
+       hist_reset_mem(hist);
+       return STAT_NO_BUF;
 }
 
 static int hist_buf_pio(struct ispstat *hist)
@@ -272,7 +285,7 @@ static int hist_buf_process(struct ispstat *hist)
        if (--(hist->wait_acc_frames))
                return STAT_NO_BUF;
 
-       if (HIST_USING_DMA(hist))
+       if (hist->dma_ch)
                ret = hist_buf_dma(hist);
        else
                ret = hist_buf_pio(hist);
@@ -473,18 +486,28 @@ int omap3isp_hist_init(struct isp_device *isp)
 
        hist->isp = isp;
 
-       if (HIST_CONFIG_DMA)
-               ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST",
-                                      hist_dma_cb, hist, &hist->dma_ch);
-       if (ret) {
-               if (HIST_CONFIG_DMA)
-                       dev_warn(isp->dev, "hist: DMA request channel failed. "
-                                          "Using PIO only.\n");
-               hist->dma_ch = -1;
-       } else {
-               dev_dbg(isp->dev, "hist: DMA channel = %d\n", hist->dma_ch);
-               hist_dma_config(hist);
-               omap_enable_dma_irq(hist->dma_ch, OMAP_DMA_BLOCK_IRQ);
+       if (HIST_CONFIG_DMA) {
+               struct platform_device *pdev = to_platform_device(isp->dev);
+               struct resource *res;
+               unsigned int sig = 0;
+               dma_cap_mask_t mask;
+
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+
+               res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+                                                  "hist");
+               if (res)
+                       sig = res->start;
+
+               hist->dma_ch = dma_request_slave_channel_compat(mask,
+                               omap_dma_filter_fn, &sig, isp->dev, "hist");
+               if (!hist->dma_ch)
+                       dev_warn(isp->dev,
+                                "hist: DMA channel request failed, using PIO\n");
+               else
+                       dev_dbg(isp->dev, "hist: using DMA channel %s\n",
+                               dma_chan_name(hist->dma_ch));
        }
 
        hist->ops = &hist_ops;
@@ -493,8 +516,8 @@ int omap3isp_hist_init(struct isp_device *isp)
 
        ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
        if (ret) {
-               if (HIST_USING_DMA(hist))
-                       omap_free_dma(hist->dma_ch);
+               if (hist->dma_ch)
+                       dma_release_channel(hist->dma_ch);
        }
 
        return ret;
@@ -505,7 +528,10 @@ int omap3isp_hist_init(struct isp_device *isp)
  */
 void omap3isp_hist_cleanup(struct isp_device *isp)
 {
-       if (HIST_USING_DMA(&isp->isp_hist))
-               omap_free_dma(isp->isp_hist.dma_ch);
-       omap3isp_stat_cleanup(&isp->isp_hist);
+       struct ispstat *hist = &isp->isp_hist;
+
+       if (hist->dma_ch)
+               dma_release_channel(hist->dma_ch);
+
+       omap3isp_stat_cleanup(hist);
 }
index a94e8340508f703efea86f51232578e30912f496..20434e83e801c1bae242509e666321b63e2437c5 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "isp.h"
 
-#define ISP_STAT_USES_DMAENGINE(stat)  ((stat)->dma_ch >= 0)
+#define ISP_STAT_USES_DMAENGINE(stat)  ((stat)->dma_ch != NULL)
 
 /*
  * MAGIC_SIZE must always be the greatest common divisor of
index b32b29677e2c48f3fc3bd4dbe9d9208452ee1cf5..b79380d83fcfacb1f8e1ff43f5964b10db1df1b7 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/types.h>
 #include <linux/omap3isp.h>
-#include <linux/omap-dma.h>
 #include <media/v4l2-event.h>
 
 #include "isp.h"
@@ -33,6 +32,7 @@
 #define STAT_NO_BUF            1       /* An error has occurred */
 #define STAT_BUF_WAITING_DMA   2       /* Histogram only: DMA is running */
 
+struct dma_chan;
 struct ispstat;
 
 struct ispstat_buffer {
@@ -96,7 +96,6 @@ struct ispstat {
        u8 inc_config;
        atomic_t buf_err;
        enum ispstat_state_t state;     /* enabling/disabling state */
-       struct omap_dma_channel_params dma_config;
        struct isp_device *isp;
        void *priv;             /* pointer to priv config struct */
        void *recover_priv;     /* pointer to recover priv configuration */
@@ -110,7 +109,7 @@ struct ispstat {
        u32 frame_number;
        u32 buf_size;
        u32 buf_alloc_size;
-       int dma_ch;
+       struct dma_chan *dma_ch;
        unsigned long event_type;
        struct ispstat_buffer *buf;
        struct ispstat_buffer *active_buf;