[PATCH 5/28] [OMAPZOOM] OMAP: CAM: ISP: Core Fixes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Sergio Aguirre <saaguirre@xxxxxx>

OMAP: CAM: ISP: Core Fixes

This patch Adds the following changes:
 - Removes useless headers
 - Add DMA cache flush for fixing green line problem on streaming
 - Aligns color effects handling with CDP release
 - Removes IRQ registers saving/restore on context save/restore
 - Removes isp_open and isp_close, and adds isp_release_resources
   instead.
 - Fixes V4L2 control handling operation, now responds properly when
   calling vidioc_g_ctrl IOCTL with V4L2_CTRL_FLAG_NEXT_CTRL flag.
 - Simplify isp_stop code.
 - Boundary checking fixes.
 - Removes IOCTL declares from isp header.
 - Add resizer output boundaries.
 - Corrected ISPCCDC_BLKCMP_GR_CY_SHIFT value.

Signed-off-by: Mohit Jalori <mjalori@xxxxxx>
Signed-off-by: Dominic Curran <dcurran@xxxxxx>
Signed-off-by: Vaibhav Hiremat <hvaibhav@xxxxxx>
Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxx>
Signed-off-by: Sergio Aguirre <saaguirre@xxxxxx>
---
 drivers/media/video/isp/isp.c    |  245 ++++++++++++++++++++++++---------------
 drivers/media/video/isp/isp.h    |   22 ---
 drivers/media/video/isp/ispreg.h |    4
 3 files changed, 161 insertions(+), 110 deletions(-)

Index: omapkernel/drivers/media/video/isp/isp.c
===================================================================
--- omapkernel.orig/drivers/media/video/isp/isp.c       2008-10-14 12:12:13.000000000 -0500
+++ omapkernel/drivers/media/video/isp/isp.c    2008-10-14 12:16:12.000000000 -0500
@@ -30,12 +30,11 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
 #include <asm/irq.h>
 #include <linux/bitops.h>
 #include <linux/scatterlist.h>
 #include <asm/mach-types.h>
-#include <mach/clock.h>
-#include <mach/io.h>
 #include <linux/device.h>
 #include <linux/videodev2.h>

@@ -108,7 +107,7 @@
                        .type = V4L2_CTRL_TYPE_INTEGER,
                        .name = "Color Effects",
                        .minimum = PREV_DEFAULT_COLOR,
-                       .maximum = PREV_SEPIA_COLOR,
+                       .maximum = PREV_BW_COLOR,
                        .step = 1,
                        .default_value = PREV_DEFAULT_COLOR,
                },
@@ -219,8 +218,6 @@
 /* Structure for saving/restoring ISP module registers */
 static struct isp_reg isp_reg_list[] = {
        {ISP_SYSCONFIG, 0},
-       {ISP_IRQ0ENABLE, 0},
-       {ISP_IRQ1ENABLE, 0},
        {ISP_TCTRL_GRESET_LENGTH, 0},
        {ISP_TCTRL_PSTRB_REPLAY, 0},
        {ISP_CTRL, 0},
@@ -277,26 +274,39 @@
        return i;
 }

-/**
- * isp_open - Reserve ISP submodules for operation
- **/
-void isp_open(void)
+static int find_next_vctrl(int id)
 {
-       ispccdc_request();
-       isppreview_request();
-       ispresizer_request();
-       return;
+       int i;
+       u32 best = (u32)-1;
+
+       for (i = 0; i < ARRAY_SIZE(video_control); i++) {
+               if (video_control[i].qc.id > id
+                   && (best == (u32)-1
+                       || video_control[i].qc.id
+                       < video_control[best].qc.id)) {
+                       best = i;
+               }
+       }
+
+       if (best == (u32)-1)
+               return -EINVAL;
+
+       return best;
 }
-EXPORT_SYMBOL(isp_set_pipeline);

 /**
- * isp_close - Free ISP submodules
+ * isp_release_resources - Free ISP submodules
  **/
-void isp_close(void)
+void isp_release_resources(void)
 {
-       ispccdc_free();
-       isppreview_free();
-       ispresizer_free();
+       if (ispmodule_obj.isp_pipeline & OMAP_ISP_CCDC)
+               ispccdc_free();
+
+       if (ispmodule_obj.isp_pipeline & OMAP_ISP_PREVIEW)
+               isppreview_free();
+
+       if (ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER)
+               ispresizer_free();
        return;
 }
 EXPORT_SYMBOL(omapisp_unset_callback);
@@ -1075,7 +1085,7 @@

        return;
 }
-EXPORT_SYMBOL(isp_open);
+EXPORT_SYMBOL(isp_set_pipeline);

 /**
  * omapisp_unset_callback - Unsets all the callbacks associated with ISP module
@@ -1099,7 +1109,6 @@
        }
        omap_writel(omap_readl(ISP_IRQ0STATUS) | ISP_INT_CLR, ISP_IRQ0STATUS);
 }
-EXPORT_SYMBOL(isp_close);

 /**
  * isp_start - Starts ISP submodule
@@ -1122,53 +1131,29 @@
  **/
 void isp_stop()
 {
-       int timeout;
+       int timeout = 0;

        spin_lock(&isp_obj.isp_temp_buf_lock);
        ispmodule_obj.isp_temp_state = ISP_FREE_RUNNING;
        spin_unlock(&isp_obj.isp_temp_buf_lock);
-       omapisp_unset_callback();
-
-       if ((ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER) &&
-                                               is_ispresizer_enabled()) {
-               ispresizer_enable(0);
-               timeout = 0;
-               while (ispresizer_busy() && (timeout < 20)) {
-                       timeout++;
-                       mdelay(10);
-               }
-       }
-
-       if ((ispmodule_obj.isp_pipeline & OMAP_ISP_PREVIEW) &&
-                                               is_isppreview_enabled()) {
-               isppreview_enable(0);
-               timeout = 0;
-               while (isppreview_busy() && (timeout < 20)) {
-                       timeout++;
-                       mdelay(10);
-               }
-       }

-       if (ispmodule_obj.isp_pipeline & OMAP_ISP_CCDC) {
-               ispccdc_enable_lsc(0);
-               ispccdc_enable(0);
-               timeout = 0;
-               while (ispccdc_busy() && (timeout < 20)) {
-                       timeout++;
-                       mdelay(10);
+       omapisp_unset_callback();
+       ispccdc_enable_lsc(0);
+       ispccdc_enable(0);
+       isppreview_enable(0);
+       ispresizer_enable(0);
+       isp_save_ctx();
+       omap_writel(omap_readl(ISP_SYSCONFIG) |
+               ISP_SYSCONFIG_SOFTRESET, ISP_SYSCONFIG);
+       while (!(omap_readl(ISP_SYSSTATUS) & 0x1)) {
+               timeout++;
+               if (timeout >= 10) {
+                       printk(KERN_ALERT "isp.c: cannot reset ISP\n");
+                       return;
                }
+               msleep(1);
        }
-       if (ispccdc_busy() || isppreview_busy() || ispresizer_busy()) {
-               isp_save_ctx();
-               omap_writel(omap_readl(ISP_SYSCONFIG) |
-                       ISP_SYSCONFIG_SOFTRESET, ISP_SYSCONFIG);
-               timeout = 0;
-               while ((!(omap_readl(ISP_SYSSTATUS) & 0x1)) && timeout < 20) {
-                       timeout++;
-                       mdelay(1);
-               }
        isp_restore_ctx();
-       }
 }

 /**
@@ -1196,15 +1181,20 @@
 void isp_calc_pipeline(struct v4l2_pix_format *pix_input,
                                        struct v4l2_pix_format *pix_output)
 {
-       ispmodule_obj.isp_pipeline = OMAP_ISP_CCDC;
+       isp_release_resources();
        if ((pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10) &&
                (pix_output->pixelformat != V4L2_PIX_FMT_SGRBG10)) {
-               ispmodule_obj.isp_pipeline |= (OMAP_ISP_PREVIEW |
-                                                       OMAP_ISP_RESIZER);
+                       ispmodule_obj.isp_pipeline = OMAP_ISP_CCDC |
+                                       OMAP_ISP_PREVIEW | OMAP_ISP_RESIZER;
+                       ispccdc_request();
+                       isppreview_request();
+                       ispresizer_request();
                ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP);
                isppreview_config_datapath(PRV_RAW_CCDC, PREVIEW_RSZ);
                ispresizer_config_datapath(RSZ_OTFLY_YUV);
        } else {
+               ispmodule_obj.isp_pipeline = OMAP_ISP_CCDC;
+               ispccdc_request();
                if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10)
                        ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_MEM);
                else
@@ -1301,22 +1291,24 @@
                break;
        case PREV_DONE:
                if (is_isppreview_enabled()) {
-                       if (ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER) {
-                               if (!ispmodule_obj.applyCrop && (ispmodule_obj.
-                                                       isp_temp_state ==
-                                                       ISP_BUF_INIT))
-                                       ispresizer_enable(1);
-                               if (ispmodule_obj.applyCrop &&
-                                                       !ispresizer_busy()) {
-                                       ispresizer_enable(0);
-                                       ispresizer_applycrop();
-                                       ispmodule_obj.applyCrop = 0;
-                               }
+               if (ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER) {
+                       spin_lock(&isp_obj.isp_temp_buf_lock);
+                       if (!ispmodule_obj.applyCrop &&
+                                       (ispmodule_obj.isp_temp_state ==
+                                       ISP_BUF_INIT))
+                               ispresizer_enable(1);
+                       spin_unlock(&isp_obj.isp_temp_buf_lock);
+                       if (ispmodule_obj.applyCrop &&
+                               !ispresizer_busy()) {
+                               ispresizer_enable(0);
+                               ispresizer_applycrop();
+                               ispmodule_obj.applyCrop = 0;
                        }
                        isppreview_config_shadow_registers();
                        isph3a_update_wb();
-                       if (ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER)
-                               return;
+               }
+               if (ispmodule_obj.isp_pipeline & OMAP_ISP_RESIZER)
+                       return;
                }
                break;
        case RESZ_DONE:
@@ -1339,7 +1331,7 @@
                spin_unlock(&isp_obj.isp_temp_buf_lock);
                return;
        default:
-               break;
+               return;
        }

        spin_lock_irqsave(&ispsg.lock, flags);
@@ -1374,6 +1366,29 @@
 EXPORT_SYMBOL(isp_stop);

 /**
+ * isp_vbq_sync - Walks the pages table and flushes the cache for
+ *                each page.
+ **/
+int isp_vbq_sync(struct videobuf_buffer *vb)
+{
+       struct videobuf_dmabuf *vdma;
+       u32 sg_element_addr;
+       int i;
+
+       vdma = videobuf_to_dma(vb);
+
+       for (i = 0; i < vdma->sglen; i++) {
+               sg_element_addr = sg_dma_address(vdma->sglist + i);
+               /* Page align address */
+               sg_element_addr &= ~(PAGE_SIZE-1);
+
+               dma_sync_single_for_cpu(NULL, sg_element_addr,
+                               PAGE_SIZE, DMA_FROM_DEVICE);
+       }
+       return 0;
+}
+
+/**
  * isp_sgdma_process - Sets operations and config for specified SG DMA
  * @sgdma: SG-DMA function to work on.
  * @irq: Flag to specify if an IRQ is associated with the DMA completion.
@@ -1397,23 +1412,42 @@
                                ispccdc_enable(1);
                                isp_start();
                                *dma_notify = 0;
-                               ispmodule_obj.isp_temp_state = ISP_BUF_TRAN;
+                               spin_lock(&isp_obj.isp_temp_buf_lock);
+                               if (ispmodule_obj.isp_pipeline
+                                       & OMAP_ISP_RESIZER) {
+                                       ispmodule_obj.isp_temp_state =
+                                               ISP_BUF_INIT;
+                               } else
+                                       ispmodule_obj.isp_temp_state =
+                                               ISP_BUF_TRAN;
+                               spin_unlock(&isp_obj.isp_temp_buf_lock);
                        } else {
+                               spin_lock(&isp_obj.isp_temp_buf_lock);
                                if (ispmodule_obj.isp_temp_state ==
                                                        ISP_FREE_RUNNING) {
                                        isp_set_sgdma_callback(sgdma_state,
                                                                func_ptr);
                                        isp_set_buf(sgdma_state);
-                                       ispccdc_enable(1);
-                                       ispmodule_obj.isp_temp_state =
-                                                               ISP_BUF_TRAN;
+                                       /* Non startup case */
+                                       if (ispmodule_obj.isp_pipeline
+                                       & OMAP_ISP_RESIZER) {
+                                               ispmodule_obj.isp_temp_state =
+                                                       ISP_BUF_INIT;
+                                       } else {
+                                               ispmodule_obj.isp_temp_state =
+                                                       ISP_BUF_TRAN;
+                                               ispccdc_enable(1);
+                                       }
                                }
+                               spin_unlock(&isp_obj.isp_temp_buf_lock);
                        }
                } else {
                        isp_set_sgdma_callback(sgdma_state, func_ptr);
                        isp_set_buf(sgdma_state);
-                       ispccdc_enable(1);
-                       ispmodule_obj.isp_temp_state = ISP_BUF_INIT;
+                       /* Non startup case */
+                       if (!(ispmodule_obj.isp_pipeline
+                               & OMAP_ISP_RESIZER))
+                               ispccdc_enable(1);

                        if (*dma_notify) {
                                isp_start();
@@ -1423,6 +1457,7 @@
        } else {
                spin_lock(&isp_obj.isp_temp_buf_lock);
                isp_CCDC_VD01_disable();
+               ispresizer_enable(0);
                ispmodule_obj.isp_temp_state = ISP_FREE_RUNNING;
                spin_unlock(&isp_obj.isp_temp_buf_lock);
        }
@@ -1453,6 +1488,7 @@

        if ((sglen < 0) || ((sglen > 0) & !sglist))
                return -EINVAL;
+       isp_vbq_sync(vb);

        spin_lock_irqsave(&ispsg.lock, flags);

@@ -1531,9 +1567,12 @@
 {
        int i;

-       i = find_vctrl(a->id);
-       if (i == -EINVAL)
-               a->flags = V4L2_CTRL_FLAG_DISABLED;
+       if (a->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+               a->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
+               i = find_next_vctrl(a->id);
+       } else {
+               i = find_vctrl(a->id);
+       }

        if (i < 0)
                return -EINVAL;
@@ -1604,7 +1643,7 @@
                        isppreview_update_contrast(&new_value);
                break;
        case V4L2_CID_PRIVATE_ISP_COLOR_FX:
-               if (new_value > PREV_SEPIA_COLOR)
+               if (new_value > PREV_BW_COLOR)
                        rval = -EINVAL;
                else
                        isppreview_set_color(&new_value);
@@ -1897,6 +1936,15 @@
                                        struct v4l2_pix_format *pix_output)
 {
        int rval = 0;
+
+       if (pix_output->width <= ISPRSZ_MIN_OUTPUT ||
+               pix_output->height <= ISPRSZ_MIN_OUTPUT)
+               return -EINVAL;
+
+       if (pix_output->width >= ISPRSZ_MAX_OUTPUT ||
+               pix_output->height > ISPRSZ_MAX_OUTPUT)
+               return -EINVAL;
+
        ispmodule_obj.ccdc_input_width = pix_input->width;
        ispmodule_obj.ccdc_input_height = pix_input->height;
        ispmodule_obj.resizer_output_width = pix_output->width;
@@ -1907,6 +1955,12 @@
                                        ispmodule_obj.ccdc_input_height,
                                        &ispmodule_obj.ccdc_output_width,
                                        &ispmodule_obj.ccdc_output_height);
+               if (rval) {
+                       printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
+                                       " supported\n", pix_input->width,
+                                       pix_input->height);
+                       return rval;
+               }
                pix_output->width = ispmodule_obj.ccdc_output_width;
                pix_output->height = ispmodule_obj.ccdc_output_height;
        }
@@ -1920,6 +1974,12 @@
                                        ispmodule_obj.preview_input_height,
                                        &ispmodule_obj.preview_output_width,
                                        &ispmodule_obj.preview_output_height);
+               if (rval) {
+                       printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
+                                       " supported\n", pix_input->width,
+                                       pix_input->height);
+                       return rval;
+               }
                pix_output->width = ispmodule_obj.preview_output_width;
                pix_output->height = ispmodule_obj.preview_output_height;
        }
@@ -1933,6 +1993,12 @@
                                        &ispmodule_obj.resizer_input_height,
                                        &ispmodule_obj.resizer_output_width,
                                        &ispmodule_obj.resizer_output_height);
+               if (rval) {
+                       printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
+                                       " supported\n", pix_input->width,
+                                       pix_input->height);
+                       return rval;
+               }
                pix_output->width = ispmodule_obj.resizer_output_width;
                pix_output->height = ispmodule_obj.resizer_output_height;
        }
@@ -2096,11 +2162,14 @@
                if (--isp_obj.ref_count == 0) {
                        isp_save_ctx();
                        off_mode = 1;
-
+                       isp_release_resources();
+                       ispmodule_obj.isp_pipeline = 0;
                        clk_disable(isp_obj.cam_ick);
                        clk_disable(isp_obj.cam_mclk);
                        clk_put(isp_obj.cam_ick);
                        clk_put(isp_obj.cam_mclk);
+                       memset(&ispcroprect, 0, sizeof(ispcroprect));
+                       memset(&cur_rect, 0, sizeof(cur_rect));
                }
        mutex_unlock(&(isp_obj.isp_mutex));
        DPRINTK_ISPCTRL("isp_put: new %d\n", isp_obj.ref_count);
Index: omapkernel/drivers/media/video/isp/isp.h
===================================================================
--- omapkernel.orig/drivers/media/video/isp/isp.h       2008-10-14 12:12:13.000000000 -0500
+++ omapkernel/drivers/media/video/isp/isp.h    2008-10-14 12:15:43.000000000 -0500
@@ -36,24 +36,6 @@
 /* Our ISP specific controls */
 #define V4L2_CID_PRIVATE_ISP_COLOR_FX          (V4L2_CID_PRIVATE_BASE + 0)

-/* ISP Private IOCTLs */
-#define VIDIOC_PRIVATE_ISP_CCDC_CFG    \
-       _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct ispccdc_update_config)
-#define VIDIOC_PRIVATE_ISP_PRV_CFG \
-       _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct ispprv_update_config)
-#define VIDIOC_PRIVATE_ISP_AEWB_CFG \
-       _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct isph3a_aewb_config)
-#define VIDIOC_PRIVATE_ISP_AEWB_REQ \
-       _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct isph3a_aewb_data)
-#define VIDIOC_PRIVATE_ISP_HIST_CFG \
-       _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct isp_hist_config)
-#define VIDIOC_PRIVATE_ISP_HIST_REQ \
-       _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct isp_hist_data)
-#define VIDIOC_PRIVATE_ISP_AF_CFG \
-       _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct af_configuration)
-#define VIDIOC_PRIVATE_ISP_AF_REQ \
-       _IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct isp_af_data)
-
 #define ISP_TOK_TERM           0xFFFFFFFF      /*
                                                 * terminating token for ISP
                                                 * modules reg list
@@ -231,9 +213,7 @@
        char idle_mode;
 };

-void isp_open(void);
-
-void isp_close(void);
+void isp_release_resources(void);

 void isp_start(void);

Index: omapkernel/drivers/media/video/isp/ispreg.h
===================================================================
--- omapkernel.orig/drivers/media/video/isp/ispreg.h    2008-10-14 12:12:13.000000000 -0500
+++ omapkernel/drivers/media/video/isp/ispreg.h 2008-10-14 12:15:43.000000000 -0500
@@ -408,6 +408,8 @@

 #define ISPPRV_MAXOUTPUT_WIDTH         1280
 #define ISPPRV_MAXOUTPUT_WIDTH_ES2     3300
+#define ISPRSZ_MIN_OUTPUT              64
+#define ISPRSZ_MAX_OUTPUT              3312

 /* Resizer module register offset */
 #define ISPRSZ_PID                     0x480BD000
@@ -867,7 +869,7 @@

 #define ISPCCDC_BLKCMP_B_MG_SHIFT              0
 #define ISPCCDC_BLKCMP_GB_G_SHIFT              8
-#define ISPCCDC_BLKCMP_GR_CY_SHIFT             6
+#define ISPCCDC_BLKCMP_GR_CY_SHIFT             16
 #define ISPCCDC_BLKCMP_R_YE_SHIFT              24

 #define ISPCCDC_FPC_FPNUM_SHIFT                        0
--
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

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux