Re: [PATCH 01/14] davinci: vpfe: add dm3xx IPIPEIF hardware support module

2012-09-21 Thread Prabhakar Lad
Hi Laurent,

Thanks for the review.

On Thu, Sep 20, 2012 at 3:31 AM, Laurent Pinchart
laurent.pinch...@ideasonboard.com wrote:
 Hi Prabhakar,

 Thanks for the patch.

 On Friday 14 September 2012 18:16:31 Prabhakar Lad wrote:
 From: Manjunath Hadli manjunath.ha...@ti.com

 add support for dm3xx IPIPEIF hardware setup. This is the
 lowest software layer for the dm3x vpfe driver which directly
 accesses hardware. Add support for features like default
 pixel correction, dark frame substraction and hardware setup.

 Signed-off-by: Manjunath Hadli manjunath.ha...@ti.com
 Signed-off-by: Lad, Prabhakar prabhakar@ti.com
 ---
  drivers/media/platform/davinci/dm3xx_ipipeif.c |  318 +
  drivers/media/platform/davinci/dm3xx_ipipeif.h |  262 +++
  include/linux/dm3xx_ipipeif.h  |   62 +


  3 files changed, 642 insertions(+), 0 deletions(-)
  create mode 100644 drivers/media/platform/davinci/dm3xx_ipipeif.c
  create mode 100644 drivers/media/platform/davinci/dm3xx_ipipeif.h
  create mode 100644 include/linux/dm3xx_ipipeif.h

 diff --git a/drivers/media/platform/davinci/dm3xx_ipipeif.c
 b/drivers/media/platform/davinci/dm3xx_ipipeif.c new file mode 100644
 index 000..7961a74
 --- /dev/null
 +++ b/drivers/media/platform/davinci/dm3xx_ipipeif.c

 [snip]

 +#include linux/io.h
 +#include linux/module.h
 +#include linux/kernel.h
 +#include linux/uaccess.h
 +#include linux/v4l2-mediabus.h
 +#include linux/platform_device.h

 Just a side note, I usually sort headers alphabetically, but feel free to use
 whatever convention you like.

Ok I'll sort to.

 +#include dm3xx_ipipeif.h
 +
 +static void *__iomem ipipeif_base_addr;

 That's not good. You shouldn't have global constants like that. The value
 should instead be stored in your device structure, that you will need to pass
 around to all functions.

Ok.

 +static inline u32 regr_if(u32 offset)
 +{
 + return readl(ipipeif_base_addr + offset);
 +}
 +
 +static inline void regw_if(u32 val, u32 offset)
 +{
 + writel(val, ipipeif_base_addr + offset);
 +}

 Maybe ipipeif_read() and ipipeif_write() ?

 +void ipipeif_set_enable()
 +{
 + regw_if(1, IPIPEIF_ENABLE);
 +}

 Please define constants in a header file for register values, masks and shifts
 instead of hardcoding the raw numbers.

Ok.

 [snip]

 +static int __devinit dm3xx_ipipeif_probe(struct platform_device *pdev)
 +{
 + static resource_size_t  res_len;
 + struct resource *res;
 + int status;
 +
 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 + if (!res)
 + return -ENOENT;
 +
 + res_len = resource_size(res);
 +
 + res = request_mem_region(res-start, res_len, res-name);
 + if (!res)
 + return -EBUSY;
 +
 + ipipeif_base_addr = ioremap_nocache(res-start, res_len);
 + if (!ipipeif_base_addr) {
 + status = -EBUSY;
 + goto fail;
 + }
 + return 0;
 +
 +fail:
 + release_mem_region(res-start, res_len);
 +
 + return status;
 +}
 +
 +static int dm3xx_ipipeif_remove(struct platform_device *pdev)
 +{
 + struct resource *res;
 +
 + iounmap(ipipeif_base_addr);
 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 + if (res)
 + release_mem_region(res-start, resource_size(res));
 + return 0;
 +}
 +
 +static struct platform_driver dm3xx_ipipeif_driver = {
 + .driver = {
 + .name   = dm3xx_ipipeif,
 + .owner = THIS_MODULE,
 + },
 + .remove = __devexit_p(dm3xx_ipipeif_remove),
 + .probe = dm3xx_ipipeif_probe,
 +};
 +
 +static int dm3xx_ipipeif_init(void)
 +{
 + return platform_driver_register(dm3xx_ipipeif_driver);
 +}
 +
 +static void dm3xx_ipipeif_exit(void)
 +{
 + platform_driver_unregister(dm3xx_ipipeif_driver);
 +}
 +
 +module_init(dm3xx_ipipeif_init);
 +module_exit(dm3xx_ipipeif_exit);

 I'm not sure to like this. You're registering a module for a device that
 essentially sits there without doing anything, except providing functions that
 can be called by other modules.

 I somehow feel that the way the code is split amongst the different layers
 isn't optimal. Could you briefly explain the rationale behind the current
 architecture ?

 (BTW, please use the module_platform_driver() macro instead of
 module_init/module_exit)

As discussed over the IRC, I am working on new design, hopefully
you will be happy this time :)

 [snip]

 diff --git a/include/linux/dm3xx_ipipeif.h b/include/linux/dm3xx_ipipeif.h
 new file mode 100644
 index 000..1c1a830
 --- /dev/null
 +++ b/include/linux/dm3xx_ipipeif.h

 [snip]

 +#include media/davinci/vpfe_types.h
 +#include media/davinci/vpfe.h

 This header file defines part of the userspace API, but includes media/
 headers that are not exported to userspace.

 Header files should be split between 3 directories:

 - Definitions required by platform data used to go to media/ but the new
 include/linux/platform_data/ directory might 

Re: [PATCH 01/14] davinci: vpfe: add dm3xx IPIPEIF hardware support module

2012-09-19 Thread Laurent Pinchart
Hi Prabhakar,

Thanks for the patch.

On Friday 14 September 2012 18:16:31 Prabhakar Lad wrote:
 From: Manjunath Hadli manjunath.ha...@ti.com
 
 add support for dm3xx IPIPEIF hardware setup. This is the
 lowest software layer for the dm3x vpfe driver which directly
 accesses hardware. Add support for features like default
 pixel correction, dark frame substraction and hardware setup.
 
 Signed-off-by: Manjunath Hadli manjunath.ha...@ti.com
 Signed-off-by: Lad, Prabhakar prabhakar@ti.com
 ---
  drivers/media/platform/davinci/dm3xx_ipipeif.c |  318 +
  drivers/media/platform/davinci/dm3xx_ipipeif.h |  262 +++
  include/linux/dm3xx_ipipeif.h  |   62 +


  3 files changed, 642 insertions(+), 0 deletions(-)
  create mode 100644 drivers/media/platform/davinci/dm3xx_ipipeif.c
  create mode 100644 drivers/media/platform/davinci/dm3xx_ipipeif.h
  create mode 100644 include/linux/dm3xx_ipipeif.h
 
 diff --git a/drivers/media/platform/davinci/dm3xx_ipipeif.c
 b/drivers/media/platform/davinci/dm3xx_ipipeif.c new file mode 100644
 index 000..7961a74
 --- /dev/null
 +++ b/drivers/media/platform/davinci/dm3xx_ipipeif.c

[snip]

 +#include linux/io.h
 +#include linux/module.h
 +#include linux/kernel.h
 +#include linux/uaccess.h
 +#include linux/v4l2-mediabus.h
 +#include linux/platform_device.h

Just a side note, I usually sort headers alphabetically, but feel free to use 
whatever convention you like.

 +#include dm3xx_ipipeif.h
 +
 +static void *__iomem ipipeif_base_addr;

That's not good. You shouldn't have global constants like that. The value 
should instead be stored in your device structure, that you will need to pass 
around to all functions.

 +static inline u32 regr_if(u32 offset)
 +{
 + return readl(ipipeif_base_addr + offset);
 +}
 +
 +static inline void regw_if(u32 val, u32 offset)
 +{
 + writel(val, ipipeif_base_addr + offset);
 +}

Maybe ipipeif_read() and ipipeif_write() ?

 +void ipipeif_set_enable()
 +{
 + regw_if(1, IPIPEIF_ENABLE);
 +}

Please define constants in a header file for register values, masks and shifts 
instead of hardcoding the raw numbers.

[snip]

 +static int __devinit dm3xx_ipipeif_probe(struct platform_device *pdev)
 +{
 + static resource_size_t  res_len;
 + struct resource *res;
 + int status;
 +
 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 + if (!res)
 + return -ENOENT;
 +
 + res_len = resource_size(res);
 +
 + res = request_mem_region(res-start, res_len, res-name);
 + if (!res)
 + return -EBUSY;
 +
 + ipipeif_base_addr = ioremap_nocache(res-start, res_len);
 + if (!ipipeif_base_addr) {
 + status = -EBUSY;
 + goto fail;
 + }
 + return 0;
 +
 +fail:
 + release_mem_region(res-start, res_len);
 +
 + return status;
 +}
 +
 +static int dm3xx_ipipeif_remove(struct platform_device *pdev)
 +{
 + struct resource *res;
 +
 + iounmap(ipipeif_base_addr);
 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 + if (res)
 + release_mem_region(res-start, resource_size(res));
 + return 0;
 +}
 +
 +static struct platform_driver dm3xx_ipipeif_driver = {
 + .driver = {
 + .name   = dm3xx_ipipeif,
 + .owner = THIS_MODULE,
 + },
 + .remove = __devexit_p(dm3xx_ipipeif_remove),
 + .probe = dm3xx_ipipeif_probe,
 +};
 +
 +static int dm3xx_ipipeif_init(void)
 +{
 + return platform_driver_register(dm3xx_ipipeif_driver);
 +}
 +
 +static void dm3xx_ipipeif_exit(void)
 +{
 + platform_driver_unregister(dm3xx_ipipeif_driver);
 +}
 +
 +module_init(dm3xx_ipipeif_init);
 +module_exit(dm3xx_ipipeif_exit);

I'm not sure to like this. You're registering a module for a device that 
essentially sits there without doing anything, except providing functions that 
can be called by other modules.

I somehow feel that the way the code is split amongst the different layers 
isn't optimal. Could you briefly explain the rationale behind the current 
architecture ?

(BTW, please use the module_platform_driver() macro instead of 
module_init/module_exit)

[snip]

 diff --git a/include/linux/dm3xx_ipipeif.h b/include/linux/dm3xx_ipipeif.h
 new file mode 100644
 index 000..1c1a830
 --- /dev/null
 +++ b/include/linux/dm3xx_ipipeif.h

[snip]

 +#include media/davinci/vpfe_types.h
 +#include media/davinci/vpfe.h

This header file defines part of the userspace API, but includes media/ 
headers that are not exported to userspace.

Header files should be split between 3 directories:

- Definitions required by platform data used to go to media/ but the new 
include/linux/platform_data/ directory might be preferred nowadays. I have no 
strong opinion on this, as other headers are already in media/ you can 
probably keep using it for now.

- Definitions requires by userspace should go to include/linux/

- The rest should go to drivers/media/platform/davinci/.

-- 

[PATCH 01/14] davinci: vpfe: add dm3xx IPIPEIF hardware support module

2012-09-14 Thread Prabhakar Lad
From: Manjunath Hadli manjunath.ha...@ti.com

add support for dm3xx IPIPEIF hardware setup. This is the
lowest software layer for the dm3x vpfe driver which directly
accesses hardware. Add support for features like default
pixel correction, dark frame substraction and hardware setup.

Signed-off-by: Manjunath Hadli manjunath.ha...@ti.com
Signed-off-by: Lad, Prabhakar prabhakar@ti.com
---
 drivers/media/platform/davinci/dm3xx_ipipeif.c |  318 
 drivers/media/platform/davinci/dm3xx_ipipeif.h |  262 +++
 include/linux/dm3xx_ipipeif.h  |   62 +
 3 files changed, 642 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/platform/davinci/dm3xx_ipipeif.c
 create mode 100644 drivers/media/platform/davinci/dm3xx_ipipeif.h
 create mode 100644 include/linux/dm3xx_ipipeif.h

diff --git a/drivers/media/platform/davinci/dm3xx_ipipeif.c 
b/drivers/media/platform/davinci/dm3xx_ipipeif.c
new file mode 100644
index 000..7961a74
--- /dev/null
+++ b/drivers/media/platform/davinci/dm3xx_ipipeif.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contributors:
+ *  Manjunath Hadli manjunath.ha...@ti.com
+ *  Prabhakar Lad prabhakar@ti.com
+ */
+
+#include linux/io.h
+#include linux/module.h
+#include linux/kernel.h
+#include linux/uaccess.h
+#include linux/v4l2-mediabus.h
+#include linux/platform_device.h
+
+#include dm3xx_ipipeif.h
+
+static void *__iomem ipipeif_base_addr;
+
+static inline u32 regr_if(u32 offset)
+{
+   return readl(ipipeif_base_addr + offset);
+}
+
+static inline void regw_if(u32 val, u32 offset)
+{
+   writel(val, ipipeif_base_addr + offset);
+}
+
+void ipipeif_set_enable()
+{
+   regw_if(1, IPIPEIF_ENABLE);
+}
+
+u32 ipipeif_get_enable(void)
+{
+   return regr_if(IPIPEIF_ENABLE);
+}
+
+int ipipeif_set_address(struct ipipeif *params, unsigned int address)
+{
+   u32 val;
+
+   if (params-source == 0)
+   return -EINVAL;
+
+   val = (params-adofs  5)  IPIPEIF_ADOFS_LSB_MASK;
+   regw_if(val, IPIPEIF_ADOFS);
+
+   /* lower sixteen bit */
+   val = (address  IPIPEIF_ADDRL_SHIFT)  IPIPEIF_ADDRL_MASK;
+   regw_if(val, IPIPEIF_ADDRL);
+
+   /* upper next seven bit */
+   val = (address  IPIPEIF_ADDRU_SHIFT)  IPIPEIF_ADDRU_MASK;
+   regw_if(val, IPIPEIF_ADDRU);
+
+   return 0;
+}
+
+static void ipipeif_config_dpc(struct ipipeif_dpc *dpc)
+{
+   u32 val = 0;
+
+   if (dpc-en) {
+   val = (dpc-en  1)  IPIPEIF_DPC2_EN_SHIFT;
+   val |= dpc-thr  IPIPEIF_DPC2_THR_MASK;
+   }
+
+   regw_if(val, IPIPEIF_DPC2);
+}
+
+#define RD_DATA_15_2   0x7
+
+/*
+ * ipipeif_hw_setup() - This function sets up IPIPEIF
+ */
+int ipipeif_hw_setup(struct ipipeif *params, int device_type)
+{
+   enum v4l2_mbus_pixelcode isif_port_if;
+   unsigned int val;
+
+   if (params == NULL)
+   return -EINVAL;
+
+   /* Enable clock to IPIPEIF and IPIPE */
+   if (device_type == DM365)
+   vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
+
+   /* Combine all the fields to make CFG1 register of IPIPEIF */
+   val = params-mode  ONESHOT_SHIFT;
+   val |= params-source  INPSRC_SHIFT;
+   val |= params-clock_select  CLKSEL_SHIFT;
+   val |= params-avg_filter  AVGFILT_SHIFT;
+   val |= params-decimation  DECIM_SHIFT;
+
+   if (device_type == DM355) {
+   val |= params-var.if_base.ialaw  IALAW_SHIFT;
+   val |= params-var.if_base.pack_mode  PACK8IN_SHIFT;
+   val |= params-var.if_base.clk_div  CLKDIV_SHIFT;
+   val |= params-var.if_base.data_shift  DATASFT_SHIFT;
+   } else {
+   /* DM365 IPIPE 5.1 */
+   val |= params-var.if_5_1.pack_mode  PACK8IN_SHIFT;
+   val |= params-var.if_5_1.source1  INPSRC1_SHIFT;
+   if (params-source != IPIPEIF_SDRAM_YUV)
+   val |= params-var.if_5_1.data_shift  DATASFT_SHIFT;
+   else
+   val = ~(RD_DATA_15_2  DATASFT_SHIFT);
+   }
+   regw_if(val, IPIPEIF_CFG1);
+
+   switch (params-source) {
+   case IPIPEIF_CCDC:
+   regw_if(params-gain, IPIPEIF_GAIN);
+   break;
+   case IPIPEIF_SDRAM_RAW:
+