All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic
@ 2012-12-15  9:57 Albert Wang
  2012-12-15  9:57 ` [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable Albert Wang
                   ` (15 more replies)
  0 siblings, 16 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang

The following patches series will add soc_camera support on marvell-ccic

Patch set V3 - Change log:
	- correct and enhance the implementation of some functions
	- replace most of preprocessor instruction with runtime detect
	- use devm_clk_get and devm_gpio_request which were missed in previous version
	- change code format in some funcions: replace if-else with switch
	- change some confused variable names
	- remove unnecessary functions: buf_init, buf_cleanup ...
	- remove unnecessary keyword: inline, extern ...
	- remove unnecessary include header file name
	- remove duplicated and unused code
	- remove unnecessary initialization of ret variable
	- [PATCH 09/15] change description

Patch set V2 - Change log:
	- remove register definition patch
	- split big patch to some small patches
	- split mcam-core.c to mcam-core.c and mcam-core-standard.c
	- add mcam-core-soc.c for soc camera support
	- split 3 frame buffers support patch into 2 patches

Patch set V1:
Log:
	- add mmp register definition
	- add soc_camera support on mcam core and mmp driver
	- add 3 frames buffers support in DMA_CONTIG mode

Thanks
Albert Wang

--
Albert Wang (7):
  [media] marvell-ccic: add get_mcam function for marvell-ccic driver
  [media] marvell-ccic: split mcam-core into 2 parts for soc_camera
    support
  [media] marvell-ccic: add soc_camera support in mcam core
  [media] marvell-ccic: add soc_camera support in mmp driver
  [media] marvell-ccic: add dma burst mode support in marvell-ccic
    driver
  [media] marvell-ccic: use unsigned int type replace int type
  [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode

Libin Yang (8):
  [media] marvell-ccic: use internal variable replace global frame
    stats variable:w
  [media] marvell-ccic: add MIPI support for marvell-ccic driver
  [media] marvell-ccic: add clock tree support for marvell-ccic driver
  [media] marvell-ccic: reset ccic phy when stop streaming for
    stability
  [media] marvell-ccic: refine mcam_set_contig_buffer function
  [media] marvell-ccic: add new formats support for marvell-ccic driver
  [media] marvell-ccic: add SOF / EOF pair check for marvell-ccic
    driver
  [media] marvell-ccic: switch to resource managed allocation and
    request

 drivers/media/platform/Makefile                    |    4 +-
 drivers/media/platform/marvell-ccic/Kconfig        |   22 +
 drivers/media/platform/marvell-ccic/Makefile       |    6 +-
 .../media/platform/marvell-ccic/mcam-core-soc.c    |  416 +++++++
 .../media/platform/marvell-ccic/mcam-core-soc.h    |   19 +
 .../platform/marvell-ccic/mcam-core-standard.c     |  820 +++++++++++++
 .../platform/marvell-ccic/mcam-core-standard.h     |   26 +
 drivers/media/platform/marvell-ccic/mcam-core.c    | 1276 +++++---------------
 drivers/media/platform/marvell-ccic/mcam-core.h    |  155 ++-
 drivers/media/platform/marvell-ccic/mmp-driver.c   |  347 ++++--
 include/media/mmp-camera.h                         |   21 +
 11 files changed, 2071 insertions(+), 1041 deletions(-)
 create mode 100644 drivers/media/platform/marvell-ccic/mcam-core-soc.c
 create mode 100644 drivers/media/platform/marvell-ccic/mcam-core-soc.h
 create mode 100644 drivers/media/platform/marvell-ccic/mcam-core-standard.c
 create mode 100644 drivers/media/platform/marvell-ccic/mcam-core-standard.h

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 15:36   ` Jonathan Corbet
  2013-01-01 14:56   ` Guennadi Liakhovetski
  2012-12-15  9:57 ` [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver Albert Wang
                   ` (14 subsequent siblings)
  15 siblings, 2 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Libin Yang, Albert Wang

From: Libin Yang <lbyang@marvell.com>

This patch replaces the global frame stats variables by using
internal variables in mcam_camera structure.

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.c |   30 ++++++++++-------------
 drivers/media/platform/marvell-ccic/mcam-core.h |    9 +++++++
 2 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index ce2b7b4..7012913f 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -30,13 +30,6 @@
 
 #include "mcam-core.h"
 
-/*
- * Basic frame stats - to be deleted shortly
- */
-static int frames;
-static int singles;
-static int delivered;
-
 #ifdef MCAM_MODE_VMALLOC
 /*
  * Internal DMA buffer management.  Since the controller cannot do S/G I/O,
@@ -367,10 +360,10 @@ static void mcam_frame_tasklet(unsigned long data)
 		if (!test_bit(bufno, &cam->flags))
 			continue;
 		if (list_empty(&cam->buffers)) {
-			singles++;
+			cam->frame_state.singles++;
 			break;  /* Leave it valid, hope for better later */
 		}
-		delivered++;
+		cam->frame_state.delivered++;
 		clear_bit(bufno, &cam->flags);
 		buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
 				queue);
@@ -452,7 +445,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 		mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
 				vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 		set_bit(CF_SINGLE_BUFFER, &cam->flags);
-		singles++;
+		cam->frame_state.singles++;
 		return;
 	}
 	/*
@@ -485,7 +478,7 @@ static void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
 	struct mcam_vb_buffer *buf = cam->vb_bufs[frame];
 
 	if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) {
-		delivered++;
+		cam->frame_state.delivered++;
 		mcam_buffer_done(cam, frame, &buf->vb_buf);
 	}
 	mcam_set_contig_buffer(cam, frame);
@@ -578,13 +571,13 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
 	 */
 	} else {
 		set_bit(CF_SG_RESTART, &cam->flags);
-		singles++;
+		cam->frame_state.singles++;
 		cam->vb_bufs[0] = NULL;
 	}
 	/*
 	 * Now we can give the completed frame back to user space.
 	 */
-	delivered++;
+	cam->frame_state.delivered++;
 	mcam_buffer_done(cam, frame, &buf->vb_buf);
 }
 
@@ -1545,7 +1538,9 @@ static int mcam_v4l_open(struct file *filp)
 
 	filp->private_data = cam;
 
-	frames = singles = delivered = 0;
+	cam->frame_state.frames = 0;
+	cam->frame_state.singles = 0;
+	cam->frame_state.delivered = 0;
 	mutex_lock(&cam->s_mutex);
 	if (cam->users == 0) {
 		ret = mcam_setup_vb2(cam);
@@ -1566,8 +1561,9 @@ static int mcam_v4l_release(struct file *filp)
 {
 	struct mcam_camera *cam = filp->private_data;
 
-	cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames,
-			singles, delivered);
+	cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n",
+			cam->frame_state.frames, cam->frame_state.singles,
+			cam->frame_state.delivered);
 	mutex_lock(&cam->s_mutex);
 	(cam->users)--;
 	if (cam->users == 0) {
@@ -1660,7 +1656,7 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame)
 	clear_bit(CF_DMA_ACTIVE, &cam->flags);
 	cam->next_buf = frame;
 	cam->buf_seq[frame] = ++(cam->sequence);
-	frames++;
+	cam->frame_state.frames++;
 	/*
 	 * "This should never happen"
 	 */
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index bd6acba..5e802c6 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -73,6 +73,14 @@ static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode)
 	}
 }
 
+/*
+ * Basic frame states
+ */
+struct mcam_frame_state {
+	unsigned int frames;
+	unsigned int singles;
+	unsigned int delivered;
+};
 
 /*
  * A description of one of our devices.
@@ -108,6 +116,7 @@ struct mcam_camera {
 	unsigned long flags;		/* Buffer status, mainly (dev_lock) */
 	int users;			/* How many open FDs */
 
+	struct mcam_frame_state frame_state;	/* Frame state counter */
 	/*
 	 * Subsystem structures.
 	 */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
  2012-12-15  9:57 ` [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 15:54   ` Jonathan Corbet
  2013-01-01 15:28   ` Guennadi Liakhovetski
  2012-12-15  9:57 ` [PATCH V3 03/15] [media] marvell-ccic: add clock tree " Albert Wang
                   ` (13 subsequent siblings)
  15 siblings, 2 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Libin Yang, Albert Wang

From: Libin Yang <lbyang@marvell.com>

This patch adds the MIPI support for marvell-ccic.
Board driver should determine whether using MIPI or not.

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.c  |   70 ++++++++++++++++++++
 drivers/media/platform/marvell-ccic/mcam-core.h  |   24 ++++++-
 drivers/media/platform/marvell-ccic/mmp-driver.c |   75 +++++++++++++++++++++-
 include/media/mmp-camera.h                       |   10 +++
 4 files changed, 177 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 7012913f..f6ae06d 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -253,6 +254,50 @@ static void mcam_ctlr_stop(struct mcam_camera *cam)
 	mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
 }
 
+static int mcam_config_mipi(struct mcam_camera *mcam, int enable)
+{
+	if (mcam->bus_type == V4L2_MBUS_CSI2 && enable) {
+		/* Using MIPI mode and enable MIPI */
+		cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x, DPHY6=0x%x\n",
+			mcam->dphy[0], mcam->dphy[1], mcam->dphy[2]);
+		mcam_reg_write(mcam, REG_CSI2_DPHY3, mcam->dphy[0]);
+		mcam_reg_write(mcam, REG_CSI2_DPHY6, mcam->dphy[2]);
+		mcam_reg_write(mcam, REG_CSI2_DPHY5, mcam->dphy[1]);
+
+		if (mcam->mipi_enabled == 0) {
+			/*
+			 * 0x41 actives 1 lane
+			 * 0x43 actives 2 lanes
+			 * 0x47 actives 4 lanes
+			 * There is no 3 lanes case
+			 */
+			switch (mcam->lane) {
+			case 1:
+				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x41);
+				break;
+			case 2:
+				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x43);
+				break;
+			case 4:
+				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x47);
+				break;
+			default:
+				cam_err(mcam, "camera: lane number set err");
+				return -EINVAL;
+			}
+			mcam->mipi_enabled = 1;
+		}
+	} else {
+		/* Using Parallel mode or disable MIPI */
+		mcam_reg_write(mcam, REG_CSI2_DPHY3, 0x0);
+		mcam_reg_write(mcam, REG_CSI2_DPHY6, 0x0);
+		mcam_reg_write(mcam, REG_CSI2_DPHY5, 0x0);
+		mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x0);
+		mcam->mipi_enabled = 0;
+	}
+	return 0;
+}
+
 /* ------------------------------------------------------------------- */
 
 #ifdef MCAM_MODE_VMALLOC
@@ -656,6 +701,15 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
 	 */
 	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
 			C0_SIFM_MASK);
+
+	/*
+	 * This field controls the generation of EOF(DVP only)
+	 */
+	if (cam->bus_type != V4L2_MBUS_CSI2) {
+		mcam_reg_set_bit(cam, REG_CTRL0,
+				C0_EOF_VSYNC | C0_VEDGE_CTRL);
+		mcam_reg_write(cam, REG_CTRL3, 0x4);
+	}
 }
 
 
@@ -886,6 +940,16 @@ static int mcam_read_setup(struct mcam_camera *cam)
 	spin_lock_irqsave(&cam->dev_lock, flags);
 	clear_bit(CF_DMA_ACTIVE, &cam->flags);
 	mcam_reset_buffers(cam);
+	/*
+	 * Update CSI2_DPHY value
+	 */
+	if (cam->calc_dphy)
+		cam->calc_dphy(cam);
+	cam_dbg(cam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n",
+			cam->dphy[0], cam->dphy[1], cam->dphy[2]);
+	ret = mcam_config_mipi(cam, 1);
+	if (ret < 0)
+		return ret;
 	mcam_ctlr_irq_enable(cam);
 	cam->state = S_STREAMING;
 	if (!test_bit(CF_SG_RESTART, &cam->flags))
@@ -1551,6 +1615,11 @@ static int mcam_v4l_open(struct file *filp)
 		mcam_set_config_needed(cam, 1);
 	}
 	(cam->users)++;
+	cam->pll1 = devm_clk_get(cam->dev, "pll1");
+	if (IS_ERR(cam->pll1)) {
+		cam_err(cam, "Could not get pll1 clock\n");
+		ret = PTR_ERR(cam->pll1);
+	}
 out:
 	mutex_unlock(&cam->s_mutex);
 	return ret;
@@ -1569,6 +1638,7 @@ static int mcam_v4l_release(struct file *filp)
 	if (cam->users == 0) {
 		mcam_ctlr_stop_dma(cam);
 		mcam_cleanup_vb2(cam);
+		mcam_config_mipi(cam, 0);
 		mcam_ctlr_power_down(cam);
 		if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read)
 			mcam_free_dma_bufs(cam);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 5e802c6..ca63010 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -101,11 +101,21 @@ struct mcam_camera {
 	short int clock_speed;	/* Sensor clock speed, default 30 */
 	short int use_smbus;	/* SMBUS or straight I2c? */
 	enum mcam_buffer_mode buffer_mode;
+
+	enum v4l2_mbus_type bus_type;
+	/* MIPI support */
+	int *dphy;
+	int mipi_enabled;
+	int lane;			/* lane number */
+
+	struct clk *pll1;
+
 	/*
 	 * Callbacks from the core to the platform code.
 	 */
 	void (*plat_power_up) (struct mcam_camera *cam);
 	void (*plat_power_down) (struct mcam_camera *cam);
+	void (*calc_dphy)(struct mcam_camera *cam);
 
 	/*
 	 * Everything below here is private to the mcam core and
@@ -218,6 +228,15 @@ int mccic_resume(struct mcam_camera *cam);
 #define REG_Y0BAR	0x00
 #define REG_Y1BAR	0x04
 #define REG_Y2BAR	0x08
+
+/*
+ * register definitions for MIPI support
+ */
+#define REG_CSI2_CTRL0	0x100
+#define REG_CSI2_DPHY3	0x12c
+#define REG_CSI2_DPHY5	0x134
+#define REG_CSI2_DPHY6	0x138
+
 /* ... */
 
 #define REG_IMGPITCH	0x24	/* Image pitch register */
@@ -292,7 +311,9 @@ int mccic_resume(struct mcam_camera *cam);
 #define	  C0_DOWNSCALE	  0x08000000	/* Enable downscaler */
 #define	  C0_SIFM_MASK	  0xc0000000	/* SIF mode bits */
 #define	  C0_SIF_HVSYNC	  0x00000000	/* Use H/VSYNC */
-#define	  CO_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
+#define	  C0_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
+#define	  C0_EOF_VSYNC	  0x00400000	/* Generate EOF by VSYNC */
+#define	  C0_VEDGE_CTRL   0x00800000	/* Detect falling edge of VSYNC */
 
 /* Bits below C1_444ALPHA are not present in Cafe */
 #define REG_CTRL1	0x40	/* Control 1 */
@@ -308,6 +329,7 @@ int mccic_resume(struct mcam_camera *cam);
 #define	  C1_TWOBUFS	  0x08000000	/* Use only two DMA buffers */
 #define	  C1_PWRDWN	  0x10000000	/* Power down */
 
+#define REG_CTRL3	0x1ec	/* CCIC parallel mode */
 #define REG_CLKCTRL	0x88	/* Clock control */
 #define	  CLK_DIV_MASK	  0x0000ffff	/* Upper bits RW "reserved" */
 
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index c4c17fe..603fa0a 100755
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/pm.h>
+#include <linux/clk.h>
 
 #include "mcam-core.h"
 
@@ -152,6 +153,69 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
 	gpio_set_value(pdata->sensor_reset_gpio, 0);
 }
 
+/*
+ * calc the dphy register values
+ * There are three dphy registers being used.
+ * dphy[0] can be set with a default value
+ * or be calculated dynamically
+ */
+void mmpcam_calc_dphy(struct mcam_camera *mcam)
+{
+	struct mmp_camera *cam = mcam_to_cam(mcam);
+	struct mmp_camera_platform_data *pdata = cam->pdev->dev.platform_data;
+	struct device *dev = &cam->pdev->dev;
+	unsigned long tx_clk_esc;
+
+	/*
+	 * If dphy[0] is calculated dynamically,
+	 * pdata->lane_clk should be already set
+	 * either in the board driver statically
+	 * or in the sensor driver dynamically.
+	 */
+	switch (pdata->dphy3_algo) {
+	case 1:
+		/*
+		 * dphy3_algo == 1
+		 * Calculate CSI2_DPHY3 algo for PXA910
+		 */
+		pdata->dphy[0] = ((1 + pdata->lane_clk * 80 / 1000) & 0xff) << 8
+			| (1 + pdata->lane_clk * 35 / 1000);
+		break;
+	case 2:
+		/*
+		 * dphy3_algo == 2
+		 * Calculate CSI2_DPHY3 algo for PXA2128
+		 */
+		pdata->dphy[0] =
+			((2 + pdata->lane_clk * 110 / 1000) & 0xff) << 8
+			| (1 + pdata->lane_clk * 35 / 1000);
+		break;
+	default:
+		/*
+		 * dphy3_algo == 0
+		 * Use default CSI2_DPHY3 value for PXA688/PXA988
+		 */
+		dev_dbg(dev, "camera: use the default CSI2_DPHY3 value\n");
+	}
+
+	/*
+	 * pll1 will never be changed, it is a fixed value
+	 */
+
+	if (IS_ERR(mcam->pll1))
+		return;
+
+	tx_clk_esc = clk_get_rate(mcam->pll1) / 1000000 / 12;
+
+	/*
+	 * Update dphy6 according to current tx_clk_esc
+	 */
+	pdata->dphy[2] = ((534 * tx_clk_esc / 2000 - 1) & 0xff) << 8
+			| ((38 * tx_clk_esc / 1000 - 1) & 0xff);
+
+	dev_dbg(dev, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n",
+		pdata->dphy[0], pdata->dphy[1], pdata->dphy[2]);
+}
 
 static irqreturn_t mmpcam_irq(int irq, void *data)
 {
@@ -174,6 +238,10 @@ static int mmpcam_probe(struct platform_device *pdev)
 	struct mmp_camera_platform_data *pdata;
 	int ret;
 
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -ENODEV;
+
 	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
 	if (cam == NULL)
 		return -ENOMEM;
@@ -183,8 +251,14 @@ static int mmpcam_probe(struct platform_device *pdev)
 	mcam = &cam->mcam;
 	mcam->plat_power_up = mmpcam_power_up;
 	mcam->plat_power_down = mmpcam_power_down;
+	mcam->calc_dphy = mmpcam_calc_dphy;
+	mcam->pll1 = NULL;
 	mcam->dev = &pdev->dev;
 	mcam->use_smbus = 0;
+	mcam->bus_type = pdata->bus_type;
+	mcam->dphy = pdata->dphy;
+	mcam->mipi_enabled = 0;
+	mcam->lane = pdata->lane;
 	mcam->chip_id = V4L2_IDENT_ARMADA610;
 	mcam->buffer_mode = B_DMA_sg;
 	spin_lock_init(&mcam->dev_lock);
@@ -223,7 +297,6 @@ static int mmpcam_probe(struct platform_device *pdev)
 	 * Find the i2c adapter.  This assumes, of course, that the
 	 * i2c bus is already up and functioning.
 	 */
-	pdata = pdev->dev.platform_data;
 	mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
 	if (mcam->i2c_adapter == NULL) {
 		ret = -ENODEV;
diff --git a/include/media/mmp-camera.h b/include/media/mmp-camera.h
index 7611963..813efe2 100755
--- a/include/media/mmp-camera.h
+++ b/include/media/mmp-camera.h
@@ -1,3 +1,4 @@
+#include <media/v4l2-mediabus.h>
 /*
  * Information for the Marvell Armada MMP camera
  */
@@ -6,4 +7,13 @@ struct mmp_camera_platform_data {
 	struct platform_device *i2c_device;
 	int sensor_power_gpio;
 	int sensor_reset_gpio;
+	enum v4l2_mbus_type bus_type;
+	/*
+	 * MIPI support
+	 */
+	int dphy[3];		/* DPHY: CSI2_DPHY3, CSI2_DPHY5, CSI2_DPHY6 */
+	int dphy3_algo;		/* Exist 2 algos for calculate CSI2_DPHY3 */
+	int mipi_enabled;	/* MIPI enabled flag */
+	int lane;		/* ccic used lane number; 0 means DVP mode */
+	int lane_clk;
 };
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
  2012-12-15  9:57 ` [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable Albert Wang
  2012-12-15  9:57 ` [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 16:03   ` Jonathan Corbet
  2013-01-01 16:05   ` Guennadi Liakhovetski
  2012-12-15  9:57 ` [PATCH V3 04/15] [media] marvell-ccic: reset ccic phy when stop streaming for stability Albert Wang
                   ` (12 subsequent siblings)
  15 siblings, 2 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Libin Yang, Albert Wang

From: Libin Yang <lbyang@marvell.com>

This patch adds the clock tree support for marvell-ccic.

Each board may require different clk enabling sequence.
Developer need add the clk_name in correct sequence in board driver
to use this feature.

Signed-off-by: Libin Yang <lbyang@marvell.com>
Signed-off-by: Albert Wang <twang13@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.h  |    4 ++
 drivers/media/platform/marvell-ccic/mmp-driver.c |   57 +++++++++++++++++++++-
 include/media/mmp-camera.h                       |    5 ++
 3 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index ca63010..86e634e 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -88,6 +88,7 @@ struct mcam_frame_state {
  *          the dev_lock spinlock; they are marked as such by comments.
  *          dev_lock is also required for access to device registers.
  */
+#define NR_MCAM_CLK 4
 struct mcam_camera {
 	/*
 	 * These fields should be set by the platform code prior to
@@ -109,6 +110,9 @@ struct mcam_camera {
 	int lane;			/* lane number */
 
 	struct clk *pll1;
+	/* clock tree support */
+	struct clk *clk[NR_MCAM_CLK];
+	int clk_num;
 
 	/*
 	 * Callbacks from the core to the platform code.
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 603fa0a..2c4dce3 100755
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -104,6 +104,23 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev)
 #define REG_CCIC_DCGCR		0x28	/* CCIC dyn clock gate ctrl reg */
 #define REG_CCIC_CRCR		0x50	/* CCIC clk reset ctrl reg	*/
 
+static void mcam_clk_set(struct mcam_camera *mcam, int on)
+{
+	unsigned int i;
+
+	if (on) {
+		for (i = 0; i < mcam->clk_num; i++) {
+			if (mcam->clk[i])
+				clk_enable(mcam->clk[i]);
+		}
+	} else {
+		for (i = mcam->clk_num; i > 0; i--) {
+			if (mcam->clk[i - 1])
+				clk_disable(mcam->clk[i - 1]);
+		}
+	}
+}
+
 /*
  * Power control.
  */
@@ -134,6 +151,8 @@ static void mmpcam_power_up(struct mcam_camera *mcam)
 	mdelay(5);
 	gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
 	mdelay(5);
+
+	mcam_clk_set(mcam, 1);
 }
 
 static void mmpcam_power_down(struct mcam_camera *mcam)
@@ -151,6 +170,8 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
 	pdata = cam->pdev->dev.platform_data;
 	gpio_set_value(pdata->sensor_power_gpio, 0);
 	gpio_set_value(pdata->sensor_reset_gpio, 0);
+
+	mcam_clk_set(mcam, 0);
 }
 
 /*
@@ -202,7 +223,7 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
 	 * pll1 will never be changed, it is a fixed value
 	 */
 
-	if (IS_ERR(mcam->pll1))
+	if (IS_ERR_OR_NULL(mcam->pll1))
 		return;
 
 	tx_clk_esc = clk_get_rate(mcam->pll1) / 1000000 / 12;
@@ -229,6 +250,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
 	return IRQ_RETVAL(handled);
 }
 
+static void mcam_init_clk(struct mcam_camera *mcam,
+			struct mmp_camera_platform_data *pdata, int init)
+{
+	unsigned int i;
+
+	if (NR_MCAM_CLK < pdata->clk_num) {
+		dev_err(mcam->dev, "Too many mcam clocks defined\n");
+		mcam->clk_num = 0;
+		return;
+	}
+
+	if (init) {
+		for (i = 0; i < pdata->clk_num; i++) {
+			if (pdata->clk_name[i] != NULL) {
+				mcam->clk[i] = devm_clk_get(mcam->dev,
+						pdata->clk_name[i]);
+				if (IS_ERR(mcam->clk[i])) {
+					dev_err(mcam->dev,
+						"Could not get clk: %s\n",
+						pdata->clk_name[i]);
+					mcam->clk_num = 0;
+					return;
+				}
+			}
+		}
+		mcam->clk_num = pdata->clk_num;
+	} else
+		mcam->clk_num = 0;
+}
 
 static int mmpcam_probe(struct platform_device *pdev)
 {
@@ -293,6 +343,8 @@ static int mmpcam_probe(struct platform_device *pdev)
 		ret = -ENODEV;
 		goto out_unmap1;
 	}
+
+	mcam_init_clk(mcam, pdata, 1);
 	/*
 	 * Find the i2c adapter.  This assumes, of course, that the
 	 * i2c bus is already up and functioning.
@@ -320,6 +372,7 @@ static int mmpcam_probe(struct platform_device *pdev)
 		goto out_gpio;
 	}
 	gpio_direction_output(pdata->sensor_reset_gpio, 0);
+
 	/*
 	 * Power the device up and hand it off to the core.
 	 */
@@ -352,6 +405,7 @@ out_gpio2:
 out_gpio:
 	gpio_free(pdata->sensor_power_gpio);
 out_unmap2:
+	mcam_init_clk(mcam, pdata, 0);
 	iounmap(cam->power_regs);
 out_unmap1:
 	iounmap(mcam->regs);
@@ -375,6 +429,7 @@ static int mmpcam_remove(struct mmp_camera *cam)
 	gpio_free(pdata->sensor_power_gpio);
 	iounmap(cam->power_regs);
 	iounmap(mcam->regs);
+	mcam_init_clk(mcam, pdata, 0);
 	kfree(cam);
 	return 0;
 }
diff --git a/include/media/mmp-camera.h b/include/media/mmp-camera.h
index 813efe2..c339d43 100755
--- a/include/media/mmp-camera.h
+++ b/include/media/mmp-camera.h
@@ -16,4 +16,9 @@ struct mmp_camera_platform_data {
 	int mipi_enabled;	/* MIPI enabled flag */
 	int lane;		/* ccic used lane number; 0 means DVP mode */
 	int lane_clk;
+	/*
+	 * clock tree support
+	 */
+	char *clk_name[4];
+	int clk_num;
 };
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 04/15] [media] marvell-ccic: reset ccic phy when stop streaming for stability
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (2 preceding siblings ...)
  2012-12-15  9:57 ` [PATCH V3 03/15] [media] marvell-ccic: add clock tree " Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 16:04   ` Jonathan Corbet
  2013-01-01 16:13   ` Guennadi Liakhovetski
  2012-12-15  9:57 ` [PATCH V3 05/15] [media] marvell-ccic: refine mcam_set_contig_buffer function Albert Wang
                   ` (11 subsequent siblings)
  15 siblings, 2 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Libin Yang, Albert Wang

From: Libin Yang <lbyang@marvell.com>

This patch adds the reset ccic phy operation when stop streaming.

Without reset ccic phy, the next start streaming may be unstable.

Also need add CCIC2 definition when PXA688/PXA2128 support dual ccics.

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.c  |    6 ++++++
 drivers/media/platform/marvell-ccic/mcam-core.h  |    2 ++
 drivers/media/platform/marvell-ccic/mmp-driver.c |   25 ++++++++++++++++++++++
 3 files changed, 33 insertions(+)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index f6ae06d..19e91c5 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1058,6 +1058,12 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
 		return -EINVAL;
 	mcam_ctlr_stop_dma(cam);
 	/*
+	 * Reset the CCIC PHY after stopping streaming,
+	 * otherwise, the CCIC may be unstable.
+	 */
+	if (cam->ctlr_reset)
+		cam->ctlr_reset(cam);
+	/*
 	 * VB2 reclaims the buffers, so we need to forget
 	 * about them.
 	 */
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 86e634e..7c42cbe 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -103,6 +103,7 @@ struct mcam_camera {
 	short int use_smbus;	/* SMBUS or straight I2c? */
 	enum mcam_buffer_mode buffer_mode;
 
+	int ccic_id;
 	enum v4l2_mbus_type bus_type;
 	/* MIPI support */
 	int *dphy;
@@ -120,6 +121,7 @@ struct mcam_camera {
 	void (*plat_power_up) (struct mcam_camera *cam);
 	void (*plat_power_down) (struct mcam_camera *cam);
 	void (*calc_dphy)(struct mcam_camera *cam);
+	void (*ctlr_reset)(struct mcam_camera *cam);
 
 	/*
 	 * Everything below here is private to the mcam core and
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 2c4dce3..fec7cd8 100755
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -103,6 +103,7 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev)
 #define CPU_SUBSYS_PMU_BASE	0xd4282800
 #define REG_CCIC_DCGCR		0x28	/* CCIC dyn clock gate ctrl reg */
 #define REG_CCIC_CRCR		0x50	/* CCIC clk reset ctrl reg	*/
+#define REG_CCIC2_CRCR		0xf4	/* CCIC2 clk reset ctrl reg	*/
 
 static void mcam_clk_set(struct mcam_camera *mcam, int on)
 {
@@ -174,6 +175,28 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
 	mcam_clk_set(mcam, 0);
 }
 
+void mcam_ctlr_reset(struct mcam_camera *mcam)
+{
+	unsigned long val;
+	struct mmp_camera *cam = mcam_to_cam(mcam);
+
+	if (mcam->ccic_id) {
+		/*
+		 * Using CCIC2
+		 */
+		val = ioread32(cam->power_regs + REG_CCIC2_CRCR);
+		iowrite32(val & ~0x2, cam->power_regs + REG_CCIC2_CRCR);
+		iowrite32(val | 0x2, cam->power_regs + REG_CCIC2_CRCR);
+	} else {
+		/*
+		 * Using CCIC1
+		 */
+		val = ioread32(cam->power_regs + REG_CCIC_CRCR);
+		iowrite32(val & ~0x2, cam->power_regs + REG_CCIC_CRCR);
+		iowrite32(val | 0x2, cam->power_regs + REG_CCIC_CRCR);
+	}
+}
+
 /*
  * calc the dphy register values
  * There are three dphy registers being used.
@@ -301,10 +324,12 @@ static int mmpcam_probe(struct platform_device *pdev)
 	mcam = &cam->mcam;
 	mcam->plat_power_up = mmpcam_power_up;
 	mcam->plat_power_down = mmpcam_power_down;
+	mcam->ctlr_reset = mcam_ctlr_reset;
 	mcam->calc_dphy = mmpcam_calc_dphy;
 	mcam->pll1 = NULL;
 	mcam->dev = &pdev->dev;
 	mcam->use_smbus = 0;
+	mcam->ccic_id = pdev->id;
 	mcam->bus_type = pdata->bus_type;
 	mcam->dphy = pdata->dphy;
 	mcam->mipi_enabled = 0;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 05/15] [media] marvell-ccic: refine mcam_set_contig_buffer function
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (3 preceding siblings ...)
  2012-12-15  9:57 ` [PATCH V3 04/15] [media] marvell-ccic: reset ccic phy when stop streaming for stability Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 16:06   ` Jonathan Corbet
  2012-12-15  9:57 ` [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver Albert Wang
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Libin Yang, Albert Wang

From: Libin Yang <lbyang@marvell.com>

This patch refines mcam_set_contig_buffer() in mcam core

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/media/platform/marvell-ccic/mcam-core.c |   21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 19e91c5..3cc1d0c 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -486,22 +486,21 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 	 */
 	if (list_empty(&cam->buffers)) {
 		buf = cam->vb_bufs[frame ^ 0x1];
-		cam->vb_bufs[frame] = buf;
-		mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-				vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 		set_bit(CF_SINGLE_BUFFER, &cam->flags);
 		cam->frame_state.singles++;
-		return;
+	} else {
+		/*
+		 * OK, we have a buffer we can use.
+		 */
+		buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
+					queue);
+		list_del_init(&buf->queue);
+		clear_bit(CF_SINGLE_BUFFER, &cam->flags);
 	}
-	/*
-	 * OK, we have a buffer we can use.
-	 */
-	buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
-	list_del_init(&buf->queue);
+
+	cam->vb_bufs[frame] = buf;
 	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
 			vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
-	cam->vb_bufs[frame] = buf;
-	clear_bit(CF_SINGLE_BUFFER, &cam->flags);
 }
 
 /*
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (4 preceding siblings ...)
  2012-12-15  9:57 ` [PATCH V3 05/15] [media] marvell-ccic: refine mcam_set_contig_buffer function Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 16:16   ` Jonathan Corbet
  2013-01-01 16:56   ` Guennadi Liakhovetski
  2012-12-15  9:57 ` [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check " Albert Wang
                   ` (9 subsequent siblings)
  15 siblings, 2 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Libin Yang, Albert Wang

From: Libin Yang <lbyang@marvell.com>

This patch adds the new formats support for marvell-ccic.

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.c |  175 ++++++++++++++++++-----
 drivers/media/platform/marvell-ccic/mcam-core.h |    6 +
 2 files changed, 149 insertions(+), 32 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 3cc1d0c..a679917 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -111,6 +111,30 @@ static struct mcam_format_struct {
 		.bpp		= 2,
 	},
 	{
+		.desc		= "UYVY 4:2:2",
+		.pixelformat	= V4L2_PIX_FMT_UYVY,
+		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "YUV 4:2:2 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YUV422P,
+		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "YUV 4:2:0 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YUV420,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_1_5X8,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "YVU 4:2:0 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YVU420,
+		.mbus_code	= V4L2_MBUS_FMT_YVYU8_1_5X8,
+		.bpp		= 2,
+	},
+	{
 		.desc		= "RGB 444",
 		.pixelformat	= V4L2_PIX_FMT_RGB444,
 		.mbus_code	= V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
@@ -169,6 +193,12 @@ struct mcam_dma_desc {
 	u32 segment_len;
 };
 
+struct yuv_pointer_t {
+	dma_addr_t y;
+	dma_addr_t u;
+	dma_addr_t v;
+};
+
 /*
  * Our buffer type for working with videobuf2.  Note that the vb2
  * developers have decreed that struct vb2_buffer must be at the
@@ -180,6 +210,7 @@ struct mcam_vb_buffer {
 	struct mcam_dma_desc *dma_desc;	/* Descriptor virtual address */
 	dma_addr_t dma_desc_pa;		/* Descriptor physical address */
 	int dma_desc_nent;		/* Number of mapped descriptors */
+	struct yuv_pointer_t yuv_p;
 };
 
 static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
@@ -470,6 +501,18 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
 /*
  * DMA-contiguous code.
  */
+
+static bool mcam_fmt_is_planar(__u32 pfmt)
+{
+	switch (pfmt) {
+	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		return true;
+	}
+	return false;
+}
+
 /*
  * Set up a contiguous buffer for the given frame.  Here also is where
  * the underrun strategy is set: if there is no buffer available, reuse
@@ -481,6 +524,8 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
 static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 {
 	struct mcam_vb_buffer *buf;
+	struct v4l2_pix_format *fmt = &cam->pix_format;
+
 	/*
 	 * If there are no available buffers, go into single mode
 	 */
@@ -499,8 +544,13 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 	}
 
 	cam->vb_bufs[frame] = buf;
-	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-			vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
+	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y);
+	if (mcam_fmt_is_planar(fmt->pixelformat)) {
+		mcam_reg_write(cam, frame == 0 ?
+					REG_U0BAR : REG_U1BAR, buf->yuv_p.u);
+		mcam_reg_write(cam, frame == 0 ?
+					REG_V0BAR : REG_V1BAR, buf->yuv_p.v);
+	}
 }
 
 /*
@@ -658,49 +708,85 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
  */
 static void mcam_ctlr_image(struct mcam_camera *cam)
 {
-	int imgsz;
 	struct v4l2_pix_format *fmt = &cam->pix_format;
+	u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
+
+	cam_dbg(cam, "camera: bytesperline = %d; height = %d\n",
+		fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
+	imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
+	imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
+
+	switch (fmt->pixelformat) {
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_UYVY:
+		widthy = fmt->width * 2;
+		widthuv = 0;
+		break;
+	case V4L2_PIX_FMT_JPEG:
+		imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
+		widthy = fmt->bytesperline;
+		widthuv = 0;
+		break;
+	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		imgsz_w = (fmt->bytesperline * 4 / 3) & IMGSZ_H_MASK;
+		widthy = fmt->width;
+		widthuv = fmt->width / 2;
+		break;
+	default:
+		widthy = fmt->bytesperline;
+		widthuv = 0;
+	}
+
+	mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
+			IMGP_YP_MASK | IMGP_UVP_MASK);
+	mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w);
+	mcam_reg_write(cam, REG_IMGOFFSET, 0x0);
 
-	imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
-		(fmt->bytesperline & IMGSZ_H_MASK);
-	mcam_reg_write(cam, REG_IMGSIZE, imgsz);
-	mcam_reg_write(cam, REG_IMGOFFSET, 0);
-	/* YPITCH just drops the last two bits */
-	mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
-			IMGP_YP_MASK);
 	/*
 	 * Tell the controller about the image format we are using.
 	 */
-	switch (cam->pix_format.pixelformat) {
+	switch (fmt->pixelformat) {
+	case V4L2_PIX_FMT_YUV422P:
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
+		break;
 	case V4L2_PIX_FMT_YUYV:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
-			    C0_DF_MASK);
-	    break;
-
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_JPEG:
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
+		break;
 	case V4L2_PIX_FMT_RGB444:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
-			    C0_DF_MASK);
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
 		/* Alpha value? */
-	    break;
-
+		break;
 	case V4L2_PIX_FMT_RGB565:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
-			    C0_DF_MASK);
-	    break;
-
+		mcam_reg_write_mask(cam, REG_CTRL0,
+			C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
+		break;
 	default:
-	    cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
-	    break;
+		cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat);
+		break;
 	}
+
 	/*
 	 * Make sure it knows we want to use hsync/vsync.
 	 */
-	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
-			C0_SIFM_MASK);
-
+	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
 	/*
 	 * This field controls the generation of EOF(DVP only)
 	 */
@@ -711,7 +797,6 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
 	}
 }
 
-
 /*
  * Configure the controller for operation; caller holds the
  * device mutex.
@@ -984,11 +1069,37 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
 {
 	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
 	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+	struct v4l2_pix_format *fmt = &cam->pix_format;
 	unsigned long flags;
 	int start;
+	dma_addr_t dma_handle;
+	u32 pixel_count = fmt->width * fmt->height;
 
 	spin_lock_irqsave(&cam->dev_lock, flags);
+	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
+	BUG_ON(!dma_handle);
 	start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
+
+	switch (cam->pix_format.pixelformat) {
+	case V4L2_PIX_FMT_YUV422P:
+		mvb->yuv_p.y = dma_handle;
+		mvb->yuv_p.u = mvb->yuv_p.y + pixel_count;
+		mvb->yuv_p.v = mvb->yuv_p.u + pixel_count / 2;
+		break;
+	case V4L2_PIX_FMT_YUV420:
+		mvb->yuv_p.y = dma_handle;
+		mvb->yuv_p.u = mvb->yuv_p.y + pixel_count;
+		mvb->yuv_p.v = mvb->yuv_p.u + pixel_count / 4;
+		break;
+	case V4L2_PIX_FMT_YVU420:
+		mvb->yuv_p.y = dma_handle;
+		mvb->yuv_p.v = mvb->yuv_p.y + pixel_count;
+		mvb->yuv_p.u = mvb->yuv_p.v + pixel_count / 4;
+		break;
+	default:
+		mvb->yuv_p.y = dma_handle;
+	}
+
 	list_add(&mvb->queue, &cam->buffers);
 	if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags))
 		mcam_sg_restart(cam);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 7c42cbe..7db638f 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -234,6 +234,12 @@ int mccic_resume(struct mcam_camera *cam);
 #define REG_Y0BAR	0x00
 #define REG_Y1BAR	0x04
 #define REG_Y2BAR	0x08
+#define REG_U0BAR	0x0c
+#define REG_U1BAR	0x10
+#define REG_U2BAR	0x14
+#define REG_V0BAR	0x18
+#define REG_V1BAR	0x1C
+#define REG_V2BAR	0x20
 
 /*
  * register definitions for MIPI support
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check for marvell-ccic driver
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (5 preceding siblings ...)
  2012-12-15  9:57 ` [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 16:19   ` Jonathan Corbet
  2013-01-02  7:48   ` Guennadi Liakhovetski
  2012-12-15  9:57 ` [PATCH V3 08/15] [media] marvell-ccic: switch to resource managed allocation and request Albert Wang
                   ` (8 subsequent siblings)
  15 siblings, 2 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Libin Yang, Albert Wang

From: Libin Yang <lbyang@marvell.com>

This patch adds the SOFx/EOFx pair check for marvell-ccic.

When switching format, the last EOF may not arrive when stop streamning.
And the EOF will be detected in the next start streaming.

Must ensure clear the obsolete frame flags before every really start streaming.

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.c |   30 ++++++++++++++++++++---
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index a679917..c3c8873 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -94,6 +94,9 @@ MODULE_PARM_DESC(buffer_mode,
 #define CF_CONFIG_NEEDED 4	/* Must configure hardware */
 #define CF_SINGLE_BUFFER 5	/* Running with a single buffer */
 #define CF_SG_RESTART	 6	/* SG restart needed */
+#define CF_FRAME_SOF0	 7	/* Frame 0 started */
+#define CF_FRAME_SOF1	 8
+#define CF_FRAME_SOF2	 9
 
 #define sensor_call(cam, o, f, args...) \
 	v4l2_subdev_call(cam->sensor, o, f, ##args)
@@ -251,8 +254,10 @@ static void mcam_reset_buffers(struct mcam_camera *cam)
 	int i;
 
 	cam->next_buf = -1;
-	for (i = 0; i < cam->nbufs; i++)
+	for (i = 0; i < cam->nbufs; i++) {
 		clear_bit(i, &cam->flags);
+		clear_bit(CF_FRAME_SOF0 + i, &cam->flags);
+	}
 }
 
 static inline int mcam_needs_config(struct mcam_camera *cam)
@@ -1134,6 +1139,7 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
 static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+	unsigned int frame;
 
 	if (cam->state != S_IDLE) {
 		INIT_LIST_HEAD(&cam->buffers);
@@ -1151,6 +1157,14 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 		cam->state = S_BUFWAIT;
 		return 0;
 	}
+
+	/*
+	 * Ensure clear the obsolete frame flags
+	 * before every really start streaming
+	 */
+	for (frame = 0; frame < cam->nbufs; frame++)
+		clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
+
 	return mcam_read_setup(cam);
 }
 
@@ -1875,9 +1889,11 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 	 * each time.
 	 */
 	for (frame = 0; frame < cam->nbufs; frame++)
-		if (irqs & (IRQ_EOF0 << frame)) {
+		if (irqs & (IRQ_EOF0 << frame) &&
+			test_bit(CF_FRAME_SOF0 + frame, &cam->flags)) {
 			mcam_frame_complete(cam, frame);
 			handled = 1;
+			clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
 			if (cam->buffer_mode == B_DMA_sg)
 				break;
 		}
@@ -1886,9 +1902,15 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 	 * code assumes that we won't get multiple frame interrupts
 	 * at once; may want to rethink that.
 	 */
-	if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) {
+	for (frame = 0; frame < cam->nbufs; frame++) {
+		if (irqs & (IRQ_SOF0 << frame)) {
+			set_bit(CF_FRAME_SOF0 + frame, &cam->flags);
+			handled = IRQ_HANDLED;
+		}
+	}
+
+	if (handled == IRQ_HANDLED) {
 		set_bit(CF_DMA_ACTIVE, &cam->flags);
-		handled = 1;
 		if (cam->buffer_mode == B_DMA_sg)
 			mcam_ctlr_stop(cam);
 	}
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 08/15] [media] marvell-ccic: switch to resource managed allocation and request
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (6 preceding siblings ...)
  2012-12-15  9:57 ` [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check " Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 16:20   ` Jonathan Corbet
  2013-01-02  8:00   ` Guennadi Liakhovetski
  2012-12-15  9:57 ` [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-ccic driver Albert Wang
                   ` (7 subsequent siblings)
  15 siblings, 2 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Libin Yang, Albert Wang

From: Libin Yang <lbyang@marvell.com>

This patch switchs to resource managed allocation and request in mmp-driver.
It can remove free resource operations.

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 drivers/media/platform/marvell-ccic/mmp-driver.c |   56 ++++++++--------------
 1 file changed, 20 insertions(+), 36 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index fec7cd8..40c243e 100755
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -315,7 +315,7 @@ static int mmpcam_probe(struct platform_device *pdev)
 	if (!pdata)
 		return -ENODEV;
 
-	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
+	cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL);
 	if (cam == NULL)
 		return -ENOMEM;
 	cam->pdev = pdev;
@@ -343,14 +343,12 @@ static int mmpcam_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
 		dev_err(&pdev->dev, "no iomem resource!\n");
-		ret = -ENODEV;
-		goto out_free;
+		return -ENODEV;
 	}
-	mcam->regs = ioremap(res->start, resource_size(res));
+	mcam->regs = devm_request_and_ioremap(&pdev->dev, res);
 	if (mcam->regs == NULL) {
 		dev_err(&pdev->dev, "MMIO ioremap fail\n");
-		ret = -ENODEV;
-		goto out_free;
+		return -ENODEV;
 	}
 	/*
 	 * Power/clock memory is elsewhere; get it too.  Perhaps this
@@ -359,14 +357,12 @@ static int mmpcam_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (res == NULL) {
 		dev_err(&pdev->dev, "no power resource!\n");
-		ret = -ENODEV;
-		goto out_unmap1;
+		return -ENODEV;
 	}
-	cam->power_regs = ioremap(res->start, resource_size(res));
+	cam->power_regs = devm_request_and_ioremap(&pdev->dev, res);
 	if (cam->power_regs == NULL) {
 		dev_err(&pdev->dev, "power MMIO ioremap fail\n");
-		ret = -ENODEV;
-		goto out_unmap1;
+		return -ENODEV;
 	}
 
 	mcam_init_clk(mcam, pdata, 1);
@@ -376,25 +372,27 @@ static int mmpcam_probe(struct platform_device *pdev)
 	 */
 	mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
 	if (mcam->i2c_adapter == NULL) {
-		ret = -ENODEV;
 		dev_err(&pdev->dev, "No i2c adapter\n");
-		goto out_unmap2;
+		ret = -ENODEV;
+		goto out_uninit_clk;
 	}
 	/*
 	 * Sensor GPIO pins.
 	 */
-	ret = gpio_request(pdata->sensor_power_gpio, "cam-power");
+	ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio,
+					"cam-power");
 	if (ret) {
 		dev_err(&pdev->dev, "Can't get sensor power gpio %d",
 				pdata->sensor_power_gpio);
-		goto out_unmap2;
+		goto out_uninit_clk;
 	}
 	gpio_direction_output(pdata->sensor_power_gpio, 0);
-	ret = gpio_request(pdata->sensor_reset_gpio, "cam-reset");
+	ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio,
+					"cam-reset");
 	if (ret) {
 		dev_err(&pdev->dev, "Can't get sensor reset gpio %d",
 				pdata->sensor_reset_gpio);
-		goto out_gpio;
+		goto out_uninit_clk;
 	}
 	gpio_direction_output(pdata->sensor_reset_gpio, 0);
 
@@ -404,7 +402,7 @@ static int mmpcam_probe(struct platform_device *pdev)
 	mmpcam_power_up(mcam);
 	ret = mccic_register(mcam);
 	if (ret)
-		goto out_gpio2;
+		goto out_power_down;
 	/*
 	 * Finally, set up our IRQ now that the core is ready to
 	 * deal with it.
@@ -415,8 +413,8 @@ static int mmpcam_probe(struct platform_device *pdev)
 		goto out_unregister;
 	}
 	cam->irq = res->start;
-	ret = request_irq(cam->irq, mmpcam_irq, IRQF_SHARED,
-			"mmp-camera", mcam);
+	ret = devm_request_irq(&pdev->dev, cam->irq, mmpcam_irq, IRQF_SHARED,
+					"mmp-camera", mcam);
 	if (ret == 0) {
 		mmpcam_add_device(cam);
 		return 0;
@@ -424,18 +422,10 @@ static int mmpcam_probe(struct platform_device *pdev)
 
 out_unregister:
 	mccic_shutdown(mcam);
-out_gpio2:
+out_power_down:
 	mmpcam_power_down(mcam);
-	gpio_free(pdata->sensor_reset_gpio);
-out_gpio:
-	gpio_free(pdata->sensor_power_gpio);
-out_unmap2:
+out_uninit_clk:
 	mcam_init_clk(mcam, pdata, 0);
-	iounmap(cam->power_regs);
-out_unmap1:
-	iounmap(mcam->regs);
-out_free:
-	kfree(cam);
 	return ret;
 }
 
@@ -446,16 +436,10 @@ static int mmpcam_remove(struct mmp_camera *cam)
 	struct mmp_camera_platform_data *pdata;
 
 	mmpcam_remove_device(cam);
-	free_irq(cam->irq, mcam);
 	mccic_shutdown(mcam);
 	mmpcam_power_down(mcam);
 	pdata = cam->pdev->dev.platform_data;
-	gpio_free(pdata->sensor_reset_gpio);
-	gpio_free(pdata->sensor_power_gpio);
-	iounmap(cam->power_regs);
-	iounmap(mcam->regs);
 	mcam_init_clk(mcam, pdata, 0);
-	kfree(cam);
 	return 0;
 }
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-ccic driver
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (7 preceding siblings ...)
  2012-12-15  9:57 ` [PATCH V3 08/15] [media] marvell-ccic: switch to resource managed allocation and request Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 16:24   ` Jonathan Corbet
  2012-12-15  9:57 ` [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support Albert Wang
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang, Libin Yang

This patch adds get_mcam() inline function which is prepared for
adding soc_camera support in marvell-ccic driver

Signed-off-by: Libin Yang <lbyang@marvell.com>
Signed-off-by: Albert Wang <twang13@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.c |   27 ++++++++++++++---------
 drivers/media/platform/marvell-ccic/mcam-core.h |    5 +++++
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index c3c8873..9b5a5e9 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1057,7 +1057,7 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
 		unsigned int *num_planes, unsigned int sizes[],
 		void *alloc_ctxs[])
 {
-	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+	struct mcam_camera *cam = get_mcam(vq);
 	int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
 
 	sizes[0] = cam->pix_format.sizeimage;
@@ -1073,14 +1073,17 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
 static void mcam_vb_buf_queue(struct vb2_buffer *vb)
 {
 	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
-	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+	struct mcam_camera *cam = get_mcam(vb->vb2_queue);
 	struct v4l2_pix_format *fmt = &cam->pix_format;
 	unsigned long flags;
 	int start;
 	dma_addr_t dma_handle;
+	unsigned long size;
 	u32 pixel_count = fmt->width * fmt->height;
 
 	spin_lock_irqsave(&cam->dev_lock, flags);
+	size = vb2_plane_size(vb, 0);
+	vb2_set_plane_payload(vb, 0, size);
 	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
 	BUG_ON(!dma_handle);
 	start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
@@ -1121,14 +1124,14 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
  */
 static void mcam_vb_wait_prepare(struct vb2_queue *vq)
 {
-	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+	struct mcam_camera *cam = get_mcam(vq);
 
 	mutex_unlock(&cam->s_mutex);
 }
 
 static void mcam_vb_wait_finish(struct vb2_queue *vq)
 {
-	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+	struct mcam_camera *cam = get_mcam(vq);
 
 	mutex_lock(&cam->s_mutex);
 }
@@ -1138,9 +1141,12 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
  */
 static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
-	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+	struct mcam_camera *cam = get_mcam(vq);
 	unsigned int frame;
 
+	if (count < 2)
+		return -EINVAL;
+
 	if (cam->state != S_IDLE) {
 		INIT_LIST_HEAD(&cam->buffers);
 		return -EINVAL;
@@ -1170,7 +1176,7 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 static int mcam_vb_stop_streaming(struct vb2_queue *vq)
 {
-	struct mcam_camera *cam = vb2_get_drv_priv(vq);
+	struct mcam_camera *cam = get_mcam(vq);
 	unsigned long flags;
 
 	if (cam->state == S_BUFWAIT) {
@@ -1181,6 +1187,7 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
 	if (cam->state != S_STREAMING)
 		return -EINVAL;
 	mcam_ctlr_stop_dma(cam);
+	cam->state = S_IDLE;
 	/*
 	 * Reset the CCIC PHY after stopping streaming,
 	 * otherwise, the CCIC may be unstable.
@@ -1216,7 +1223,7 @@ static const struct vb2_ops mcam_vb2_ops = {
 static int mcam_vb_sg_buf_init(struct vb2_buffer *vb)
 {
 	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
-	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+	struct mcam_camera *cam = get_mcam(vb->vb2_queue);
 	int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1;
 
 	mvb->dma_desc = dma_alloc_coherent(cam->dev,
@@ -1232,7 +1239,7 @@ static int mcam_vb_sg_buf_init(struct vb2_buffer *vb)
 static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
 {
 	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
-	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+	struct mcam_camera *cam = get_mcam(vb->vb2_queue);
 	struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0);
 	struct mcam_dma_desc *desc = mvb->dma_desc;
 	struct scatterlist *sg;
@@ -1252,7 +1259,7 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
 
 static int mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
 {
-	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+	struct mcam_camera *cam = get_mcam(vb->vb2_queue);
 	struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0);
 
 	dma_unmap_sg(cam->dev, sgd->sglist, sgd->num_pages, DMA_FROM_DEVICE);
@@ -1261,7 +1268,7 @@ static int mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
 
 static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
 {
-	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+	struct mcam_camera *cam = get_mcam(vb->vb2_queue);
 	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
 	int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1;
 
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 7db638f..3ea25ed 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -216,6 +216,11 @@ static inline void mcam_reg_set_bit(struct mcam_camera *cam,
 	mcam_reg_write_mask(cam, reg, val, val);
 }
 
+static inline struct mcam_camera *get_mcam(struct vb2_queue *vq)
+{
+	return vb2_get_drv_priv(vq);
+}
+
 /*
  * Functions for use by platform code.
  */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (8 preceding siblings ...)
  2012-12-15  9:57 ` [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-ccic driver Albert Wang
@ 2012-12-15  9:57 ` Albert Wang
  2012-12-16 16:37   ` Jonathan Corbet
  2012-12-15  9:58 ` [PATCH V3 11/15] [media] marvell-ccic: add soc_camera support in mcam core Albert Wang
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:57 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang, Libin Yang

This patch splits mcam-core into 2 parts to prepare for soc_camera support.

The first part remains in mcam-core.c. This part includes the HW operations
and vb2 callback functions.

The second part is moved to mcam-core-standard.c. This part is relevant with
the implementation of using V4L2.

Signed-off-by: Libin Yang <lbyang@marvell.com>
Signed-off-by: Albert Wang <twang13@marvell.com>
---
 drivers/media/platform/marvell-ccic/Makefile       |    4 +-
 .../platform/marvell-ccic/mcam-core-standard.c     |  820 +++++++++++++++++
 .../platform/marvell-ccic/mcam-core-standard.h     |   26 +
 drivers/media/platform/marvell-ccic/mcam-core.c    |  944 +-------------------
 drivers/media/platform/marvell-ccic/mcam-core.h    |   54 ++
 5 files changed, 939 insertions(+), 909 deletions(-)
 create mode 100644 drivers/media/platform/marvell-ccic/mcam-core-standard.c
 create mode 100644 drivers/media/platform/marvell-ccic/mcam-core-standard.h

diff --git a/drivers/media/platform/marvell-ccic/Makefile b/drivers/media/platform/marvell-ccic/Makefile
index 05a792c..595ebdf 100755
--- a/drivers/media/platform/marvell-ccic/Makefile
+++ b/drivers/media/platform/marvell-ccic/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
 cafe_ccic-y := cafe-driver.o mcam-core.o
 
-obj-$(CONFIG_VIDEO_MMP_CAMERA) += mmp_camera.o
-mmp_camera-y := mmp-driver.o mcam-core.o
+obj-$(CONFIG_VIDEO_MMP_CAMERA) += mmp_camera_standard.o
+mmp_camera_standard-y := mmp-driver.o mcam-core.o mcam-core-standard.o
 
diff --git a/drivers/media/platform/marvell-ccic/mcam-core-standard.c b/drivers/media/platform/marvell-ccic/mcam-core-standard.c
new file mode 100644
index 0000000..5e0d8f1
--- /dev/null
+++ b/drivers/media/platform/marvell-ccic/mcam-core-standard.c
@@ -0,0 +1,820 @@
+/*
+ * The Marvell camera core.	 This device appears in a number of settings,
+ * so it needs platform-specific support outside of the core.
+ *
+ * Copyright 2011 Jonathan Corbet corbet@lwn.net
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/ov7670.h>
+#include <linux/clk.h>
+#include <media/videobuf2-vmalloc.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-dma-sg.h>
+
+#include "mcam-core.h"
+#include "mcam-core-standard.h"
+
+static const enum v4l2_mbus_pixelcode mcam_def_mbus_code =
+					V4L2_MBUS_FMT_YUYV8_2X8;
+
+static struct mcam_format_struct {
+	__u8 *desc;
+	__u32 pixelformat;
+	int bpp;   /* Bytes per pixel */
+	enum v4l2_mbus_pixelcode mbus_code;
+} mcam_formats[] = {
+	{
+		.desc		= "YUYV 4:2:2",
+		.pixelformat	= V4L2_PIX_FMT_YUYV,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "UYVY 4:2:2",
+		.pixelformat	= V4L2_PIX_FMT_UYVY,
+		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "YUV 4:2:2 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YUV422P,
+		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "YUV 4:2:0 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YUV420,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_1_5X8,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "YVU 4:2:0 PLANAR",
+		.pixelformat	= V4L2_PIX_FMT_YVU420,
+		.mbus_code	= V4L2_MBUS_FMT_YVYU8_1_5X8,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "RGB 444",
+		.pixelformat	= V4L2_PIX_FMT_RGB444,
+		.mbus_code	= V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "RGB 565",
+		.pixelformat	= V4L2_PIX_FMT_RGB565,
+		.mbus_code	= V4L2_MBUS_FMT_RGB565_2X8_LE,
+		.bpp		= 2,
+	},
+	{
+		.desc		= "Raw RGB Bayer",
+		.pixelformat	= V4L2_PIX_FMT_SBGGR8,
+		.mbus_code	= V4L2_MBUS_FMT_SBGGR8_1X8,
+		.bpp		= 1
+	},
+};
+#define N_MCAM_FMTS ARRAY_SIZE(mcam_formats)
+
+static struct mcam_format_struct *mcam_find_format(u32 pixelformat)
+{
+	unsigned i;
+
+	for (i = 0; i < N_MCAM_FMTS; i++)
+		if (mcam_formats[i].pixelformat == pixelformat)
+			return mcam_formats + i;
+	/* Not found? Then return the first format. */
+	return mcam_formats;
+}
+
+static void mcam_ctlr_init(struct mcam_camera *cam)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cam->dev_lock, flags);
+	/*
+	 * Make sure it's not powered down.
+	 */
+	mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
+	/*
+	 * Turn off the enable bit.  It sure should be off anyway,
+	 * but it's good to be sure.
+	 */
+	mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
+	/*
+	 * Clock the sensor appropriately.  Controller clock should
+	 * be 48MHz, sensor "typical" value is half that.
+	 */
+	mcam_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK);
+	spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
+/*
+ * We have found the sensor on the i2c.  Let's try to have a
+ * conversation.
+ */
+static int mcam_cam_init(struct mcam_camera *cam)
+{
+	struct v4l2_dbg_chip_ident chip;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	if (cam->state != S_NOTREADY)
+		cam_warn(cam, "Cam init with device in funky state %d",
+				cam->state);
+	ret = __mcam_cam_reset(cam);
+	if (ret)
+		goto out;
+	chip.ident = V4L2_IDENT_NONE;
+	chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
+	chip.match.addr = cam->sensor_addr;
+	ret = sensor_call(cam, core, g_chip_ident, &chip);
+	if (ret)
+		goto out;
+	cam->sensor_type = chip.ident;
+	if (cam->sensor_type != V4L2_IDENT_OV7670) {
+		cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type);
+		ret = -EINVAL;
+		goto out;
+	}
+/* Get/set parameters? */
+	ret = 0;
+	cam->state = S_IDLE;
+out:
+	mcam_ctlr_power_down(cam);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_setup_vb2(struct mcam_camera *cam)
+{
+	struct vb2_queue *vq = &cam->vb_queue;
+
+	memset(vq, 0, sizeof(*vq));
+	vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	vq->drv_priv = cam;
+	INIT_LIST_HEAD(&cam->buffers);
+	switch (cam->buffer_mode) {
+	case B_DMA_contig:
+#ifdef MCAM_MODE_DMA_CONTIG
+		vq->ops = &mcam_vb2_ops;
+		vq->mem_ops = &vb2_dma_contig_memops;
+		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
+		vq->io_modes = VB2_MMAP | VB2_USERPTR;
+		cam->dma_setup = mcam_ctlr_dma_contig;
+		cam->frame_complete = mcam_dma_contig_done;
+#endif
+		break;
+	case B_DMA_sg:
+#ifdef MCAM_MODE_DMA_SG
+		vq->ops = &mcam_vb2_sg_ops;
+		vq->mem_ops = &vb2_dma_sg_memops;
+		vq->io_modes = VB2_MMAP | VB2_USERPTR;
+		cam->dma_setup = mcam_ctlr_dma_sg;
+		cam->frame_complete = mcam_dma_sg_done;
+#endif
+		break;
+	case B_vmalloc:
+#ifdef MCAM_MODE_VMALLOC
+		tasklet_init(&cam->s_tasklet, mcam_frame_tasklet,
+				(unsigned long) cam);
+		vq->ops = &mcam_vb2_ops;
+		vq->mem_ops = &vb2_vmalloc_memops;
+		vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
+		vq->io_modes = VB2_MMAP;
+		cam->dma_setup = mcam_ctlr_dma_vmalloc;
+		cam->frame_complete = mcam_vmalloc_done;
+#endif
+		break;
+	}
+	return vb2_queue_init(vq);
+}
+
+static void mcam_cleanup_vb2(struct mcam_camera *cam)
+{
+	vb2_queue_release(&cam->vb_queue);
+#ifdef MCAM_MODE_DMA_CONTIG
+	if (cam->buffer_mode == B_DMA_contig)
+		vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
+#endif
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * The long list of V4L2 ioctl() operations.
+ */
+static int mcam_vidioc_streamon(struct file *filp, void *priv,
+		enum v4l2_buf_type type)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_streamon(&cam->vb_queue, type);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_streamoff(struct file *filp, void *priv,
+		enum v4l2_buf_type type)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_streamoff(&cam->vb_queue, type);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_reqbufs(struct file *filp, void *priv,
+		struct v4l2_requestbuffers *req)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_reqbufs(&cam->vb_queue, req);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_querybuf(struct file *filp, void *priv,
+		struct v4l2_buffer *buf)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_querybuf(&cam->vb_queue, buf);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_qbuf(struct file *filp, void *priv,
+		struct v4l2_buffer *buf)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_qbuf(&cam->vb_queue, buf);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_dqbuf(struct file *filp, void *priv,
+		struct v4l2_buffer *buf)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_queryctrl(struct file *filp, void *priv,
+		struct v4l2_queryctrl *qc)
+{
+	struct mcam_camera *cam = priv;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = sensor_call(cam, core, queryctrl, qc);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_g_ctrl(struct file *filp, void *priv,
+		struct v4l2_control *ctrl)
+{
+	struct mcam_camera *cam = priv;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = sensor_call(cam, core, g_ctrl, ctrl);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_s_ctrl(struct file *filp, void *priv,
+		struct v4l2_control *ctrl)
+{
+	struct mcam_camera *cam = priv;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = sensor_call(cam, core, s_ctrl, ctrl);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_querycap(struct file *file, void *priv,
+		struct v4l2_capability *cap)
+{
+	strcpy(cap->driver, "marvell_ccic");
+	strcpy(cap->card, "marvell_ccic");
+	cap->version = 1;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	return 0;
+}
+
+static int mcam_vidioc_enum_fmt_vid_cap(struct file *filp,
+		void *priv, struct v4l2_fmtdesc *fmt)
+{
+	if (fmt->index >= N_MCAM_FMTS)
+		return -EINVAL;
+	strlcpy(fmt->description, mcam_formats[fmt->index].desc,
+			sizeof(fmt->description));
+	fmt->pixelformat = mcam_formats[fmt->index].pixelformat;
+	return 0;
+}
+
+static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
+		struct v4l2_format *fmt)
+{
+	struct mcam_camera *cam = priv;
+	struct mcam_format_struct *f;
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	int ret;
+
+	f = mcam_find_format(pix->pixelformat);
+	pix->pixelformat = f->pixelformat;
+	v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code);
+	mutex_lock(&cam->s_mutex);
+	ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
+	mutex_unlock(&cam->s_mutex);
+	v4l2_fill_pix_format(pix, &mbus_fmt);
+	pix->bytesperline = pix->width * f->bpp;
+	pix->sizeimage = pix->height * pix->bytesperline;
+	return ret;
+}
+
+static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
+		struct v4l2_format *fmt)
+{
+	struct mcam_camera *cam = priv;
+	struct mcam_format_struct *f;
+	int ret;
+
+	/*
+	 * Can't do anything if the device is not idle
+	 * Also can't if there are streaming buffers in place.
+	 */
+	if (cam->state != S_IDLE || cam->vb_queue.num_buffers > 0)
+		return -EBUSY;
+
+	f = mcam_find_format(fmt->fmt.pix.pixelformat);
+
+	/*
+	 * See if the formatting works in principle.
+	 */
+	ret = mcam_vidioc_try_fmt_vid_cap(filp, priv, fmt);
+	if (ret)
+		return ret;
+	/*
+	 * Now we start to change things for real, so let's do it
+	 * under lock.
+	 */
+	mutex_lock(&cam->s_mutex);
+	cam->pix_format = fmt->fmt.pix;
+	cam->mbus_code = f->mbus_code;
+
+	/*
+	 * Make sure we have appropriate DMA buffers.
+	 */
+	if (cam->buffer_mode == B_vmalloc) {
+		ret = mcam_check_dma_buffers(cam);
+		if (ret)
+			goto out;
+	}
+	mcam_set_config_needed(cam, 1);
+out:
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+/*
+ * Return our stored notion of how the camera is/should be configured.
+ * The V4l2 spec wants us to be smarter, and actually get this from
+ * the camera (and not mess with it at open time).	Someday.
+ */
+static int mcam_vidioc_g_fmt_vid_cap(struct file *filp, void *priv,
+		struct v4l2_format *f)
+{
+	struct mcam_camera *cam = priv;
+
+	f->fmt.pix = cam->pix_format;
+	return 0;
+}
+
+/*
+ * We only have one input - the sensor - so minimize the nonsense here.
+ */
+static int mcam_vidioc_enum_input(struct file *filp, void *priv,
+		struct v4l2_input *input)
+{
+	if (input->index != 0)
+		return -EINVAL;
+
+	input->type = V4L2_INPUT_TYPE_CAMERA;
+	input->std = V4L2_STD_ALL; /* Not sure what should go here */
+	strcpy(input->name, "Camera");
+	return 0;
+}
+
+static int mcam_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int mcam_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	if (i != 0)
+		return -EINVAL;
+	return 0;
+}
+
+/* from vivi.c */
+static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
+{
+	return 0;
+}
+
+/*
+ * G/S_PARM.  Most of this is done by the sensor, but we are
+ * the level which controls the number of read buffers.
+ */
+static int mcam_vidioc_g_parm(struct file *filp, void *priv,
+		struct v4l2_streamparm *parms)
+{
+	struct mcam_camera *cam = priv;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = sensor_call(cam, video, g_parm, parms);
+	mutex_unlock(&cam->s_mutex);
+	parms->parm.capture.readbuffers = mcam_n_dma_bufs;
+	return ret;
+}
+
+static int mcam_vidioc_s_parm(struct file *filp, void *priv,
+		struct v4l2_streamparm *parms)
+{
+	struct mcam_camera *cam = priv;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = sensor_call(cam, video, s_parm, parms);
+	mutex_unlock(&cam->s_mutex);
+	parms->parm.capture.readbuffers = mcam_n_dma_bufs;
+	return ret;
+}
+
+static int mcam_vidioc_g_chip_ident(struct file *file, void *priv,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	struct mcam_camera *cam = priv;
+
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (v4l2_chip_match_host(&chip->match)) {
+		chip->ident = cam->chip_id;
+		return 0;
+	}
+	return sensor_call(cam, core, g_chip_ident, chip);
+}
+
+static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv,
+		struct v4l2_frmsizeenum *sizes)
+{
+	struct mcam_camera *cam = priv;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = sensor_call(cam, video, enum_framesizes, sizes);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_vidioc_enum_frameintervals(struct file *filp, void *priv,
+		struct v4l2_frmivalenum *interval)
+{
+	struct mcam_camera *cam = priv;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = sensor_call(cam, video, enum_frameintervals, interval);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mcam_vidioc_g_register(struct file *file, void *priv,
+		struct v4l2_dbg_register *reg)
+{
+	struct mcam_camera *cam = priv;
+
+	if (v4l2_chip_match_host(&reg->match)) {
+		reg->val = mcam_reg_read(cam, reg->reg);
+		reg->size = 4;
+		return 0;
+	}
+	return sensor_call(cam, core, g_register, reg);
+}
+
+static int mcam_vidioc_s_register(struct file *file, void *priv,
+		struct v4l2_dbg_register *reg)
+{
+	struct mcam_camera *cam = priv;
+
+	if (v4l2_chip_match_host(&reg->match)) {
+		mcam_reg_write(cam, reg->reg, reg->val);
+		return 0;
+	}
+	return sensor_call(cam, core, s_register, reg);
+}
+#endif
+
+static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = {
+	.vidioc_querycap	= mcam_vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap = mcam_vidioc_enum_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap	= mcam_vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap	= mcam_vidioc_s_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap	= mcam_vidioc_g_fmt_vid_cap,
+	.vidioc_enum_input	= mcam_vidioc_enum_input,
+	.vidioc_g_input		= mcam_vidioc_g_input,
+	.vidioc_s_input		= mcam_vidioc_s_input,
+	.vidioc_s_std		= mcam_vidioc_s_std,
+	.vidioc_reqbufs		= mcam_vidioc_reqbufs,
+	.vidioc_querybuf	= mcam_vidioc_querybuf,
+	.vidioc_qbuf		= mcam_vidioc_qbuf,
+	.vidioc_dqbuf		= mcam_vidioc_dqbuf,
+	.vidioc_streamon	= mcam_vidioc_streamon,
+	.vidioc_streamoff	= mcam_vidioc_streamoff,
+	.vidioc_queryctrl	= mcam_vidioc_queryctrl,
+	.vidioc_g_ctrl		= mcam_vidioc_g_ctrl,
+	.vidioc_s_ctrl		= mcam_vidioc_s_ctrl,
+	.vidioc_g_parm		= mcam_vidioc_g_parm,
+	.vidioc_s_parm		= mcam_vidioc_s_parm,
+	.vidioc_enum_framesizes = mcam_vidioc_enum_framesizes,
+	.vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals,
+	.vidioc_g_chip_ident	= mcam_vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register	= mcam_vidioc_g_register,
+	.vidioc_s_register	= mcam_vidioc_s_register,
+#endif
+};
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Our various file operations.
+ */
+static int mcam_v4l_open(struct file *filp)
+{
+	struct mcam_camera *cam = video_drvdata(filp);
+	int ret = 0;
+
+	filp->private_data = cam;
+
+	cam->frame_state.frames = 0;
+	cam->frame_state.singles = 0;
+	cam->frame_state.delivered = 0;
+	mutex_lock(&cam->s_mutex);
+	if (cam->users == 0) {
+		ret = mcam_setup_vb2(cam);
+		if (ret)
+			goto out;
+		mcam_ctlr_power_up(cam);
+		__mcam_cam_reset(cam);
+		mcam_set_config_needed(cam, 1);
+	}
+	(cam->users)++;
+	cam->pll1 = devm_clk_get(cam->dev, "pll1");
+	if (IS_ERR(cam->pll1)) {
+		cam_err(cam, "Could not get pll1 clock\n");
+		ret = PTR_ERR(cam->pll1);
+	}
+out:
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_v4l_release(struct file *filp)
+{
+	struct mcam_camera *cam = filp->private_data;
+
+	cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n",
+			cam->frame_state.frames, cam->frame_state.singles,
+			cam->frame_state.delivered);
+	mutex_lock(&cam->s_mutex);
+	(cam->users)--;
+	if (cam->users == 0) {
+		mcam_ctlr_stop_dma(cam);
+		mcam_cleanup_vb2(cam);
+		mcam_config_mipi(cam, 0);
+		mcam_ctlr_power_down(cam);
+		if (cam->buffer_mode == B_vmalloc && mcam_alloc_bufs_at_read)
+			mcam_free_dma_bufs(cam);
+	}
+	mutex_unlock(&cam->s_mutex);
+	return 0;
+}
+
+static ssize_t mcam_v4l_read(struct file *filp,
+		char __user *buffer, size_t len, loff_t *pos)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_read(&cam->vb_queue, buffer, len, pos,
+			filp->f_flags & O_NONBLOCK);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static unsigned int mcam_v4l_poll(struct file *filp,
+		struct poll_table_struct *pt)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_poll(&cam->vb_queue, filp, pt);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static int mcam_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct mcam_camera *cam = filp->private_data;
+	int ret;
+
+	mutex_lock(&cam->s_mutex);
+	ret = vb2_mmap(&cam->vb_queue, vma);
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+}
+
+static const struct v4l2_file_operations mcam_v4l_fops = {
+	.owner = THIS_MODULE,
+	.open = mcam_v4l_open,
+	.release = mcam_v4l_release,
+	.read = mcam_v4l_read,
+	.poll = mcam_v4l_poll,
+	.mmap = mcam_v4l_mmap,
+	.unlocked_ioctl = video_ioctl2,
+};
+
+/*
+ * This template device holds all of those v4l2 methods; we
+ * clone it for specific real devices.
+ */
+static struct video_device mcam_v4l_template = {
+	.name = "mcam",
+	.tvnorms = V4L2_STD_NTSC_M,
+	.current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
+
+	.fops = &mcam_v4l_fops,
+	.ioctl_ops = &mcam_v4l_ioctl_ops,
+	.release = video_device_release_empty,
+};
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Registration and such.
+ */
+static struct ov7670_config sensor_cfg = {
+	/*
+	 * Exclude QCIF mode, because it only captures a tiny portion
+	 * of the sensor FOV
+	 */
+	.min_width = 320,
+	.min_height = 240,
+};
+
+int mccic_register(struct mcam_camera *cam)
+{
+	struct i2c_board_info ov7670_info = {
+		.type = "ov7670",
+		.addr = 0x42 >> 1,
+		.platform_data = &sensor_cfg,
+	};
+	int ret;
+
+	/*
+	 * Validate the requested buffer mode.
+	 */
+	if (mcam_buffer_mode >= 0)
+		cam->buffer_mode = mcam_buffer_mode;
+	if (cam->buffer_mode == B_DMA_sg &&
+			cam->chip_id == V4L2_IDENT_CAFE) {
+		cam_err(cam, "marvell-cam: Cafe can't do S/G I/O, "
+				"attempting vmalloc mode instead\n");
+		cam->buffer_mode = B_vmalloc;
+	}
+	if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
+		cam_err(cam, "marvell-cam: buffer mode %d unsupported\n",
+				cam->buffer_mode);
+		return -EINVAL;
+	}
+	/*
+	 * Register with V4L
+	 */
+	ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
+	if (ret)
+		return ret;
+
+	mutex_init(&cam->s_mutex);
+	cam->state = S_NOTREADY;
+	mcam_set_config_needed(cam, 1);
+	cam->pix_format = mcam_def_pix_format;
+	cam->mbus_code = mcam_def_mbus_code;
+	INIT_LIST_HEAD(&cam->buffers);
+	mcam_ctlr_init(cam);
+
+	/*
+	 * Try to find the sensor.
+	 */
+	sensor_cfg.clock_speed = cam->clock_speed;
+	sensor_cfg.use_smbus = cam->use_smbus;
+	cam->sensor_addr = ov7670_info.addr;
+	cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev,
+			cam->i2c_adapter, &ov7670_info, NULL);
+	if (cam->sensor == NULL) {
+		ret = -ENODEV;
+		goto out_unregister;
+	}
+
+	ret = mcam_cam_init(cam);
+	if (ret)
+		goto out_unregister;
+	/*
+	 * Get the v4l2 setup done.
+	 */
+	mutex_lock(&cam->s_mutex);
+	cam->vdev = mcam_v4l_template;
+	cam->vdev.debug = 0;
+	cam->vdev.v4l2_dev = &cam->v4l2_dev;
+	ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
+	if (ret)
+		goto out;
+	video_set_drvdata(&cam->vdev, cam);
+
+	/*
+	 * If so requested, try to get our DMA buffers now.
+	 */
+	if (cam->buffer_mode == B_vmalloc && !mcam_alloc_bufs_at_read) {
+		if (mcam_alloc_dma_bufs(cam, 1))
+			cam_warn(cam, "Unable to alloc DMA buffers at load"
+					 " will try again later\n");
+	}
+
+out:
+	mutex_unlock(&cam->s_mutex);
+	return ret;
+out_unregister:
+	v4l2_device_unregister(&cam->v4l2_dev);
+	return ret;
+}
+
+void mccic_shutdown(struct mcam_camera *cam)
+{
+	/*
+	 * If we have no users (and we really, really should have no
+	 * users) the device will already be powered down.  Trying to
+	 * take it down again will wedge the machine, which is frowned
+	 * upon.
+	 */
+	if (cam->users > 0) {
+		cam_warn(cam, "Removing a device with users!\n");
+		mcam_ctlr_power_down(cam);
+	}
+	vb2_queue_release(&cam->vb_queue);
+	if (cam->buffer_mode == B_vmalloc)
+		mcam_free_dma_bufs(cam);
+	video_unregister_device(&cam->vdev);
+	v4l2_device_unregister(&cam->v4l2_dev);
+}
diff --git a/drivers/media/platform/marvell-ccic/mcam-core-standard.h b/drivers/media/platform/marvell-ccic/mcam-core-standard.h
new file mode 100644
index 0000000..154ea4f
--- /dev/null
+++ b/drivers/media/platform/marvell-ccic/mcam-core-standard.h
@@ -0,0 +1,26 @@
+/*
+ * Marvell camera core structures.
+ *
+ * Copyright 2011 Jonathan Corbet corbet@lwn.net
+ */
+extern bool mcam_alloc_bufs_at_read;
+extern int mcam_n_dma_bufs;
+extern int mcam_buffer_mode;
+extern const struct vb2_ops mcam_vb2_sg_ops;
+extern const struct vb2_ops mcam_vb2_ops;
+
+void mcam_ctlr_stop_dma(struct mcam_camera *cam);
+int mcam_config_mipi(struct mcam_camera *mcam, int enable);
+void mcam_ctlr_power_up(struct mcam_camera *cam);
+void mcam_ctlr_power_down(struct mcam_camera *cam);
+void mcam_free_dma_bufs(struct mcam_camera *cam);
+void mcam_ctlr_dma_sg(struct mcam_camera *cam);
+void mcam_dma_sg_done(struct mcam_camera *cam, int frame);
+int mcam_check_dma_buffers(struct mcam_camera *cam);
+void mcam_set_config_needed(struct mcam_camera *cam, int needed);
+int __mcam_cam_reset(struct mcam_camera *cam);
+int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime);
+void mcam_ctlr_dma_contig(struct mcam_camera *cam);
+void mcam_dma_contig_done(struct mcam_camera *cam, int frame);
+void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam);
+void mcam_vmalloc_done(struct mcam_camera *cam, int frame);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 9b5a5e9..dccc573 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -45,30 +45,30 @@
  * sense.
  */
 
-static bool alloc_bufs_at_read;
-module_param(alloc_bufs_at_read, bool, 0444);
-MODULE_PARM_DESC(alloc_bufs_at_read,
+bool mcam_alloc_bufs_at_read;
+module_param(mcam_alloc_bufs_at_read, bool, 0444);
+MODULE_PARM_DESC(mcam_alloc_bufs_at_read,
 		"Non-zero value causes DMA buffers to be allocated when the "
 		"video capture device is read, rather than at module load "
 		"time.  This saves memory, but decreases the chances of "
 		"successfully getting those buffers.  This parameter is "
 		"only used in the vmalloc buffer mode");
 
-static int n_dma_bufs = 3;
-module_param(n_dma_bufs, uint, 0644);
-MODULE_PARM_DESC(n_dma_bufs,
+unsigned int mcam_n_dma_bufs = 3;
+module_param(mcam_n_dma_bufs, uint, 0644);
+MODULE_PARM_DESC(mcam_n_dma_bufs,
 		"The number of DMA buffers to allocate.  Can be either two "
 		"(saves memory, makes timing tighter) or three.");
 
-static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2;  /* Worst case */
+static unsigned int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2;  /* Worst case */
 module_param(dma_buf_size, uint, 0444);
 MODULE_PARM_DESC(dma_buf_size,
 		"The size of the allocated DMA buffers.  If actual operating "
 		"parameters require larger buffers, an attempt to reallocate "
 		"will be made.");
 #else /* MCAM_MODE_VMALLOC */
-static const bool alloc_bufs_at_read = 0;
-static const int n_dma_bufs = 3;  /* Used by S/G_PARM */
+const bool mcam_alloc_bufs_at_read;
+const unsigned int mcam_n_dma_bufs = 3;  /* Used by S/G_PARM */
 #endif /* MCAM_MODE_VMALLOC */
 
 static bool flip;
@@ -77,9 +77,9 @@ MODULE_PARM_DESC(flip,
 		"If set, the sensor will be instructed to flip the image "
 		"vertically.");
 
-static int buffer_mode = -1;
-module_param(buffer_mode, int, 0444);
-MODULE_PARM_DESC(buffer_mode,
+int mcam_buffer_mode = -1;
+module_param(mcam_buffer_mode, int, 0444);
+MODULE_PARM_DESC(mcam_buffer_mode,
 		"Set the buffer mode to be used; default is to go with what "
 		"the platform driver asks for.  Set to 0 for vmalloc, 1 for "
 		"DMA contiguous.");
@@ -98,124 +98,6 @@ MODULE_PARM_DESC(buffer_mode,
 #define CF_FRAME_SOF1	 8
 #define CF_FRAME_SOF2	 9
 
-#define sensor_call(cam, o, f, args...) \
-	v4l2_subdev_call(cam->sensor, o, f, ##args)
-
-static struct mcam_format_struct {
-	__u8 *desc;
-	__u32 pixelformat;
-	int bpp;   /* Bytes per pixel */
-	enum v4l2_mbus_pixelcode mbus_code;
-} mcam_formats[] = {
-	{
-		.desc		= "YUYV 4:2:2",
-		.pixelformat	= V4L2_PIX_FMT_YUYV,
-		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
-		.bpp		= 2,
-	},
-	{
-		.desc		= "UYVY 4:2:2",
-		.pixelformat	= V4L2_PIX_FMT_UYVY,
-		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
-		.bpp		= 2,
-	},
-	{
-		.desc		= "YUV 4:2:2 PLANAR",
-		.pixelformat	= V4L2_PIX_FMT_YUV422P,
-		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
-		.bpp		= 2,
-	},
-	{
-		.desc		= "YUV 4:2:0 PLANAR",
-		.pixelformat	= V4L2_PIX_FMT_YUV420,
-		.mbus_code	= V4L2_MBUS_FMT_YUYV8_1_5X8,
-		.bpp		= 2,
-	},
-	{
-		.desc		= "YVU 4:2:0 PLANAR",
-		.pixelformat	= V4L2_PIX_FMT_YVU420,
-		.mbus_code	= V4L2_MBUS_FMT_YVYU8_1_5X8,
-		.bpp		= 2,
-	},
-	{
-		.desc		= "RGB 444",
-		.pixelformat	= V4L2_PIX_FMT_RGB444,
-		.mbus_code	= V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
-		.bpp		= 2,
-	},
-	{
-		.desc		= "RGB 565",
-		.pixelformat	= V4L2_PIX_FMT_RGB565,
-		.mbus_code	= V4L2_MBUS_FMT_RGB565_2X8_LE,
-		.bpp		= 2,
-	},
-	{
-		.desc		= "Raw RGB Bayer",
-		.pixelformat	= V4L2_PIX_FMT_SBGGR8,
-		.mbus_code	= V4L2_MBUS_FMT_SBGGR8_1X8,
-		.bpp		= 1
-	},
-};
-#define N_MCAM_FMTS ARRAY_SIZE(mcam_formats)
-
-static struct mcam_format_struct *mcam_find_format(u32 pixelformat)
-{
-	unsigned i;
-
-	for (i = 0; i < N_MCAM_FMTS; i++)
-		if (mcam_formats[i].pixelformat == pixelformat)
-			return mcam_formats + i;
-	/* Not found? Then return the first format. */
-	return mcam_formats;
-}
-
-/*
- * The default format we use until somebody says otherwise.
- */
-static const struct v4l2_pix_format mcam_def_pix_format = {
-	.width		= VGA_WIDTH,
-	.height		= VGA_HEIGHT,
-	.pixelformat	= V4L2_PIX_FMT_YUYV,
-	.field		= V4L2_FIELD_NONE,
-	.bytesperline	= VGA_WIDTH*2,
-	.sizeimage	= VGA_WIDTH*VGA_HEIGHT*2,
-};
-
-static const enum v4l2_mbus_pixelcode mcam_def_mbus_code =
-					V4L2_MBUS_FMT_YUYV8_2X8;
-
-
-/*
- * The two-word DMA descriptor format used by the Armada 610 and like.  There
- * Is a three-word format as well (set C1_DESC_3WORD) where the third
- * word is a pointer to the next descriptor, but we don't use it.  Two-word
- * descriptors have to be contiguous in memory.
- */
-struct mcam_dma_desc {
-	u32 dma_addr;
-	u32 segment_len;
-};
-
-struct yuv_pointer_t {
-	dma_addr_t y;
-	dma_addr_t u;
-	dma_addr_t v;
-};
-
-/*
- * Our buffer type for working with videobuf2.  Note that the vb2
- * developers have decreed that struct vb2_buffer must be at the
- * beginning of this structure.
- */
-struct mcam_vb_buffer {
-	struct vb2_buffer vb_buf;
-	struct list_head queue;
-	struct mcam_dma_desc *dma_desc;	/* Descriptor virtual address */
-	dma_addr_t dma_desc_pa;		/* Descriptor physical address */
-	int dma_desc_nent;		/* Number of mapped descriptors */
-	struct yuv_pointer_t yuv_p;
-};
-
 static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
 {
 	return container_of(vb, struct mcam_vb_buffer, vb_buf);
@@ -233,19 +115,6 @@ static void mcam_buffer_done(struct mcam_camera *cam, int frame,
 	vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE);
 }
 
-
-
-/*
- * Debugging and related.
- */
-#define cam_err(cam, fmt, arg...) \
-	dev_err((cam)->dev, fmt, ##arg);
-#define cam_warn(cam, fmt, arg...) \
-	dev_warn((cam)->dev, fmt, ##arg);
-#define cam_dbg(cam, fmt, arg...) \
-	dev_dbg((cam)->dev, fmt, ##arg);
-
-
 /*
  * Flag manipulation helpers
  */
@@ -265,7 +134,7 @@ static inline int mcam_needs_config(struct mcam_camera *cam)
 	return test_bit(CF_CONFIG_NEEDED, &cam->flags);
 }
 
-static void mcam_set_config_needed(struct mcam_camera *cam, int needed)
+void mcam_set_config_needed(struct mcam_camera *cam, int needed)
 {
 	if (needed)
 		set_bit(CF_CONFIG_NEEDED, &cam->flags);
@@ -290,7 +159,7 @@ static void mcam_ctlr_stop(struct mcam_camera *cam)
 	mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
 }
 
-static int mcam_config_mipi(struct mcam_camera *mcam, int enable)
+int mcam_config_mipi(struct mcam_camera *mcam, int enable)
 {
 	if (mcam->bus_type == V4L2_MBUS_CSI2 && enable) {
 		/* Using MIPI mode and enable MIPI */
@@ -344,7 +213,7 @@ static int mcam_config_mipi(struct mcam_camera *mcam, int enable)
 /*
  * Allocate in-kernel DMA buffers for vmalloc mode.
  */
-static int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
+int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
 {
 	int i;
 
@@ -353,11 +222,11 @@ static int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
 		cam->dma_buf_size = dma_buf_size;
 	else
 		cam->dma_buf_size = cam->pix_format.sizeimage;
-	if (n_dma_bufs > 3)
-		n_dma_bufs = 3;
+	if (mcam_n_dma_bufs > 3)
+		mcam_n_dma_bufs = 3;
 
 	cam->nbufs = 0;
-	for (i = 0; i < n_dma_bufs; i++) {
+	for (i = 0; i < mcam_n_dma_bufs; i++) {
 		cam->dma_bufs[i] = dma_alloc_coherent(cam->dev,
 				cam->dma_buf_size, cam->dma_handles + i,
 				GFP_KERNEL);
@@ -378,14 +247,14 @@ static int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
 		return -ENOMEM;
 
 	case 2:
-		if (n_dma_bufs > 2)
+		if (mcam_n_dma_bufs > 2)
 			cam_warn(cam, "Will limp along with only 2 buffers\n");
 		break;
 	}
 	return 0;
 }
 
-static void mcam_free_dma_bufs(struct mcam_camera *cam)
+void mcam_free_dma_bufs(struct mcam_camera *cam)
 {
 	int i;
 
@@ -401,7 +270,7 @@ static void mcam_free_dma_bufs(struct mcam_camera *cam)
 /*
  * Set up DMA buffers when operating in vmalloc mode
  */
-static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam)
+void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam)
 {
 	/*
 	 * Store the first two Y buffers (we aren't supporting
@@ -465,7 +334,7 @@ static void mcam_frame_tasklet(unsigned long data)
 /*
  * Make sure our allocated buffers are up to the task.
  */
-static int mcam_check_dma_buffers(struct mcam_camera *cam)
+int mcam_check_dma_buffers(struct mcam_camera *cam)
 {
 	if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage)
 			mcam_free_dma_bufs(cam);
@@ -474,24 +343,24 @@ static int mcam_check_dma_buffers(struct mcam_camera *cam)
 	return 0;
 }
 
-static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
+void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
 {
 	tasklet_schedule(&cam->s_tasklet);
 }
 
 #else /* MCAM_MODE_VMALLOC */
 
-static inline int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
+int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
 {
 	return 0;
 }
 
-static inline void mcam_free_dma_bufs(struct mcam_camera *cam)
+void mcam_free_dma_bufs(struct mcam_camera *cam)
 {
 	return;
 }
 
-static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
+int mcam_check_dma_buffers(struct mcam_camera *cam)
 {
 	return 0;
 }
@@ -561,7 +430,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 /*
  * Initial B_DMA_contig setup.
  */
-static void mcam_ctlr_dma_contig(struct mcam_camera *cam)
+void mcam_ctlr_dma_contig(struct mcam_camera *cam)
 {
 	mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
 	cam->nbufs = 2;
@@ -572,7 +441,7 @@ static void mcam_ctlr_dma_contig(struct mcam_camera *cam)
 /*
  * Frame completion handling.
  */
-static void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
+void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
 {
 	struct mcam_vb_buffer *buf = cam->vb_bufs[frame];
 
@@ -618,7 +487,7 @@ static void mcam_sg_next_buffer(struct mcam_camera *cam)
 /*
  * Initial B_DMA_sg setup
  */
-static void mcam_ctlr_dma_sg(struct mcam_camera *cam)
+void mcam_ctlr_dma_sg(struct mcam_camera *cam)
 {
 	/*
 	 * The list-empty condition can hit us at resume time
@@ -648,7 +517,7 @@ static void mcam_ctlr_dma_sg(struct mcam_camera *cam)
  * safely change the DMA descriptor array here and restart things
  * (assuming there's another buffer waiting to go).
  */
-static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
+void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
 {
 	struct mcam_vb_buffer *buf = cam->vb_bufs[0];
 
@@ -711,7 +580,7 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
 /*
  * Image format setup
  */
-static void mcam_ctlr_image(struct mcam_camera *cam)
+void mcam_ctlr_image(struct mcam_camera *cam)
 {
 	struct v4l2_pix_format *fmt = &cam->pix_format;
 	u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
@@ -834,36 +703,11 @@ static void mcam_ctlr_irq_disable(struct mcam_camera *cam)
 	mcam_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS);
 }
 
-
-
-static void mcam_ctlr_init(struct mcam_camera *cam)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cam->dev_lock, flags);
-	/*
-	 * Make sure it's not powered down.
-	 */
-	mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
-	/*
-	 * Turn off the enable bit.  It sure should be off anyway,
-	 * but it's good to be sure.
-	 */
-	mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
-	/*
-	 * Clock the sensor appropriately.  Controller clock should
-	 * be 48MHz, sensor "typical" value is half that.
-	 */
-	mcam_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK);
-	spin_unlock_irqrestore(&cam->dev_lock, flags);
-}
-
-
 /*
  * Stop the controller, and don't return until we're really sure that no
  * further DMA is going on.
  */
-static void mcam_ctlr_stop_dma(struct mcam_camera *cam)
+void mcam_ctlr_stop_dma(struct mcam_camera *cam)
 {
 	unsigned long flags;
 
@@ -896,7 +740,7 @@ static void mcam_ctlr_stop_dma(struct mcam_camera *cam)
 /*
  * Power up and down.
  */
-static void mcam_ctlr_power_up(struct mcam_camera *cam)
+void mcam_ctlr_power_up(struct mcam_camera *cam)
 {
 	unsigned long flags;
 
@@ -907,7 +751,7 @@ static void mcam_ctlr_power_up(struct mcam_camera *cam)
 	msleep(5); /* Just to be sure */
 }
 
-static void mcam_ctlr_power_down(struct mcam_camera *cam)
+void mcam_ctlr_power_down(struct mcam_camera *cam)
 {
 	unsigned long flags;
 
@@ -927,49 +771,12 @@ static void mcam_ctlr_power_down(struct mcam_camera *cam)
  * Communications with the sensor.
  */
 
-static int __mcam_cam_reset(struct mcam_camera *cam)
+int __mcam_cam_reset(struct mcam_camera *cam)
 {
 	return sensor_call(cam, core, reset, 0);
 }
 
 /*
- * We have found the sensor on the i2c.  Let's try to have a
- * conversation.
- */
-static int mcam_cam_init(struct mcam_camera *cam)
-{
-	struct v4l2_dbg_chip_ident chip;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	if (cam->state != S_NOTREADY)
-		cam_warn(cam, "Cam init with device in funky state %d",
-				cam->state);
-	ret = __mcam_cam_reset(cam);
-	if (ret)
-		goto out;
-	chip.ident = V4L2_IDENT_NONE;
-	chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
-	chip.match.addr = cam->sensor_addr;
-	ret = sensor_call(cam, core, g_chip_ident, &chip);
-	if (ret)
-		goto out;
-	cam->sensor_type = chip.ident;
-	if (cam->sensor_type != V4L2_IDENT_OV7670) {
-		cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type);
-		ret = -EINVAL;
-		goto out;
-	}
-/* Get/set parameters? */
-	ret = 0;
-	cam->state = S_IDLE;
-out:
-	mcam_ctlr_power_down(cam);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-/*
  * Configure the sensor to match the parameters we have.  Caller should
  * hold s_mutex
  */
@@ -1205,7 +1012,7 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
 }
 
 
-static const struct vb2_ops mcam_vb2_ops = {
+const struct vb2_ops mcam_vb2_ops = {
 	.queue_setup		= mcam_vb_queue_setup,
 	.buf_queue		= mcam_vb_buf_queue,
 	.start_streaming	= mcam_vb_start_streaming,
@@ -1277,7 +1084,7 @@ static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
 }
 
 
-static const struct vb2_ops mcam_vb2_sg_ops = {
+const struct vb2_ops mcam_vb2_sg_ops = {
 	.queue_setup		= mcam_vb_queue_setup,
 	.buf_init		= mcam_vb_sg_buf_init,
 	.buf_prepare		= mcam_vb_sg_buf_prepare,
@@ -1292,564 +1099,6 @@ static const struct vb2_ops mcam_vb2_sg_ops = {
 
 #endif /* MCAM_MODE_DMA_SG */
 
-static int mcam_setup_vb2(struct mcam_camera *cam)
-{
-	struct vb2_queue *vq = &cam->vb_queue;
-
-	memset(vq, 0, sizeof(*vq));
-	vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	vq->drv_priv = cam;
-	INIT_LIST_HEAD(&cam->buffers);
-	switch (cam->buffer_mode) {
-	case B_DMA_contig:
-#ifdef MCAM_MODE_DMA_CONTIG
-		vq->ops = &mcam_vb2_ops;
-		vq->mem_ops = &vb2_dma_contig_memops;
-		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
-		vq->io_modes = VB2_MMAP | VB2_USERPTR;
-		cam->dma_setup = mcam_ctlr_dma_contig;
-		cam->frame_complete = mcam_dma_contig_done;
-#endif
-		break;
-	case B_DMA_sg:
-#ifdef MCAM_MODE_DMA_SG
-		vq->ops = &mcam_vb2_sg_ops;
-		vq->mem_ops = &vb2_dma_sg_memops;
-		vq->io_modes = VB2_MMAP | VB2_USERPTR;
-		cam->dma_setup = mcam_ctlr_dma_sg;
-		cam->frame_complete = mcam_dma_sg_done;
-#endif
-		break;
-	case B_vmalloc:
-#ifdef MCAM_MODE_VMALLOC
-		tasklet_init(&cam->s_tasklet, mcam_frame_tasklet,
-				(unsigned long) cam);
-		vq->ops = &mcam_vb2_ops;
-		vq->mem_ops = &vb2_vmalloc_memops;
-		vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
-		vq->io_modes = VB2_MMAP;
-		cam->dma_setup = mcam_ctlr_dma_vmalloc;
-		cam->frame_complete = mcam_vmalloc_done;
-#endif
-		break;
-	}
-	return vb2_queue_init(vq);
-}
-
-static void mcam_cleanup_vb2(struct mcam_camera *cam)
-{
-	vb2_queue_release(&cam->vb_queue);
-#ifdef MCAM_MODE_DMA_CONTIG
-	if (cam->buffer_mode == B_DMA_contig)
-		vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
-#endif
-}
-
-
-/* ---------------------------------------------------------------------- */
-/*
- * The long list of V4L2 ioctl() operations.
- */
-
-static int mcam_vidioc_streamon(struct file *filp, void *priv,
-		enum v4l2_buf_type type)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_streamon(&cam->vb_queue, type);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-static int mcam_vidioc_streamoff(struct file *filp, void *priv,
-		enum v4l2_buf_type type)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_streamoff(&cam->vb_queue, type);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-static int mcam_vidioc_reqbufs(struct file *filp, void *priv,
-		struct v4l2_requestbuffers *req)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_reqbufs(&cam->vb_queue, req);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-static int mcam_vidioc_querybuf(struct file *filp, void *priv,
-		struct v4l2_buffer *buf)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_querybuf(&cam->vb_queue, buf);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-static int mcam_vidioc_qbuf(struct file *filp, void *priv,
-		struct v4l2_buffer *buf)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_qbuf(&cam->vb_queue, buf);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-static int mcam_vidioc_dqbuf(struct file *filp, void *priv,
-		struct v4l2_buffer *buf)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-
-static int mcam_vidioc_queryctrl(struct file *filp, void *priv,
-		struct v4l2_queryctrl *qc)
-{
-	struct mcam_camera *cam = priv;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = sensor_call(cam, core, queryctrl, qc);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-static int mcam_vidioc_g_ctrl(struct file *filp, void *priv,
-		struct v4l2_control *ctrl)
-{
-	struct mcam_camera *cam = priv;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = sensor_call(cam, core, g_ctrl, ctrl);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-static int mcam_vidioc_s_ctrl(struct file *filp, void *priv,
-		struct v4l2_control *ctrl)
-{
-	struct mcam_camera *cam = priv;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = sensor_call(cam, core, s_ctrl, ctrl);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-static int mcam_vidioc_querycap(struct file *file, void *priv,
-		struct v4l2_capability *cap)
-{
-	strcpy(cap->driver, "marvell_ccic");
-	strcpy(cap->card, "marvell_ccic");
-	cap->version = 1;
-	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-		V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-	return 0;
-}
-
-
-static int mcam_vidioc_enum_fmt_vid_cap(struct file *filp,
-		void *priv, struct v4l2_fmtdesc *fmt)
-{
-	if (fmt->index >= N_MCAM_FMTS)
-		return -EINVAL;
-	strlcpy(fmt->description, mcam_formats[fmt->index].desc,
-			sizeof(fmt->description));
-	fmt->pixelformat = mcam_formats[fmt->index].pixelformat;
-	return 0;
-}
-
-static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
-		struct v4l2_format *fmt)
-{
-	struct mcam_camera *cam = priv;
-	struct mcam_format_struct *f;
-	struct v4l2_pix_format *pix = &fmt->fmt.pix;
-	struct v4l2_mbus_framefmt mbus_fmt;
-	int ret;
-
-	f = mcam_find_format(pix->pixelformat);
-	pix->pixelformat = f->pixelformat;
-	v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code);
-	mutex_lock(&cam->s_mutex);
-	ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
-	mutex_unlock(&cam->s_mutex);
-	v4l2_fill_pix_format(pix, &mbus_fmt);
-	pix->bytesperline = pix->width * f->bpp;
-	pix->sizeimage = pix->height * pix->bytesperline;
-	return ret;
-}
-
-static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
-		struct v4l2_format *fmt)
-{
-	struct mcam_camera *cam = priv;
-	struct mcam_format_struct *f;
-	int ret;
-
-	/*
-	 * Can't do anything if the device is not idle
-	 * Also can't if there are streaming buffers in place.
-	 */
-	if (cam->state != S_IDLE || cam->vb_queue.num_buffers > 0)
-		return -EBUSY;
-
-	f = mcam_find_format(fmt->fmt.pix.pixelformat);
-
-	/*
-	 * See if the formatting works in principle.
-	 */
-	ret = mcam_vidioc_try_fmt_vid_cap(filp, priv, fmt);
-	if (ret)
-		return ret;
-	/*
-	 * Now we start to change things for real, so let's do it
-	 * under lock.
-	 */
-	mutex_lock(&cam->s_mutex);
-	cam->pix_format = fmt->fmt.pix;
-	cam->mbus_code = f->mbus_code;
-
-	/*
-	 * Make sure we have appropriate DMA buffers.
-	 */
-	if (cam->buffer_mode == B_vmalloc) {
-		ret = mcam_check_dma_buffers(cam);
-		if (ret)
-			goto out;
-	}
-	mcam_set_config_needed(cam, 1);
-out:
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-/*
- * Return our stored notion of how the camera is/should be configured.
- * The V4l2 spec wants us to be smarter, and actually get this from
- * the camera (and not mess with it at open time).  Someday.
- */
-static int mcam_vidioc_g_fmt_vid_cap(struct file *filp, void *priv,
-		struct v4l2_format *f)
-{
-	struct mcam_camera *cam = priv;
-
-	f->fmt.pix = cam->pix_format;
-	return 0;
-}
-
-/*
- * We only have one input - the sensor - so minimize the nonsense here.
- */
-static int mcam_vidioc_enum_input(struct file *filp, void *priv,
-		struct v4l2_input *input)
-{
-	if (input->index != 0)
-		return -EINVAL;
-
-	input->type = V4L2_INPUT_TYPE_CAMERA;
-	input->std = V4L2_STD_ALL; /* Not sure what should go here */
-	strcpy(input->name, "Camera");
-	return 0;
-}
-
-static int mcam_vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-	*i = 0;
-	return 0;
-}
-
-static int mcam_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
-	if (i != 0)
-		return -EINVAL;
-	return 0;
-}
-
-/* from vivi.c */
-static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
-{
-	return 0;
-}
-
-/*
- * G/S_PARM.  Most of this is done by the sensor, but we are
- * the level which controls the number of read buffers.
- */
-static int mcam_vidioc_g_parm(struct file *filp, void *priv,
-		struct v4l2_streamparm *parms)
-{
-	struct mcam_camera *cam = priv;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = sensor_call(cam, video, g_parm, parms);
-	mutex_unlock(&cam->s_mutex);
-	parms->parm.capture.readbuffers = n_dma_bufs;
-	return ret;
-}
-
-static int mcam_vidioc_s_parm(struct file *filp, void *priv,
-		struct v4l2_streamparm *parms)
-{
-	struct mcam_camera *cam = priv;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = sensor_call(cam, video, s_parm, parms);
-	mutex_unlock(&cam->s_mutex);
-	parms->parm.capture.readbuffers = n_dma_bufs;
-	return ret;
-}
-
-static int mcam_vidioc_g_chip_ident(struct file *file, void *priv,
-		struct v4l2_dbg_chip_ident *chip)
-{
-	struct mcam_camera *cam = priv;
-
-	chip->ident = V4L2_IDENT_NONE;
-	chip->revision = 0;
-	if (v4l2_chip_match_host(&chip->match)) {
-		chip->ident = cam->chip_id;
-		return 0;
-	}
-	return sensor_call(cam, core, g_chip_ident, chip);
-}
-
-static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv,
-		struct v4l2_frmsizeenum *sizes)
-{
-	struct mcam_camera *cam = priv;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = sensor_call(cam, video, enum_framesizes, sizes);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-static int mcam_vidioc_enum_frameintervals(struct file *filp, void *priv,
-		struct v4l2_frmivalenum *interval)
-{
-	struct mcam_camera *cam = priv;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = sensor_call(cam, video, enum_frameintervals, interval);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int mcam_vidioc_g_register(struct file *file, void *priv,
-		struct v4l2_dbg_register *reg)
-{
-	struct mcam_camera *cam = priv;
-
-	if (v4l2_chip_match_host(&reg->match)) {
-		reg->val = mcam_reg_read(cam, reg->reg);
-		reg->size = 4;
-		return 0;
-	}
-	return sensor_call(cam, core, g_register, reg);
-}
-
-static int mcam_vidioc_s_register(struct file *file, void *priv,
-		struct v4l2_dbg_register *reg)
-{
-	struct mcam_camera *cam = priv;
-
-	if (v4l2_chip_match_host(&reg->match)) {
-		mcam_reg_write(cam, reg->reg, reg->val);
-		return 0;
-	}
-	return sensor_call(cam, core, s_register, reg);
-}
-#endif
-
-static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = {
-	.vidioc_querycap	= mcam_vidioc_querycap,
-	.vidioc_enum_fmt_vid_cap = mcam_vidioc_enum_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap	= mcam_vidioc_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap	= mcam_vidioc_s_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap	= mcam_vidioc_g_fmt_vid_cap,
-	.vidioc_enum_input	= mcam_vidioc_enum_input,
-	.vidioc_g_input		= mcam_vidioc_g_input,
-	.vidioc_s_input		= mcam_vidioc_s_input,
-	.vidioc_s_std		= mcam_vidioc_s_std,
-	.vidioc_reqbufs		= mcam_vidioc_reqbufs,
-	.vidioc_querybuf	= mcam_vidioc_querybuf,
-	.vidioc_qbuf		= mcam_vidioc_qbuf,
-	.vidioc_dqbuf		= mcam_vidioc_dqbuf,
-	.vidioc_streamon	= mcam_vidioc_streamon,
-	.vidioc_streamoff	= mcam_vidioc_streamoff,
-	.vidioc_queryctrl	= mcam_vidioc_queryctrl,
-	.vidioc_g_ctrl		= mcam_vidioc_g_ctrl,
-	.vidioc_s_ctrl		= mcam_vidioc_s_ctrl,
-	.vidioc_g_parm		= mcam_vidioc_g_parm,
-	.vidioc_s_parm		= mcam_vidioc_s_parm,
-	.vidioc_enum_framesizes = mcam_vidioc_enum_framesizes,
-	.vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals,
-	.vidioc_g_chip_ident	= mcam_vidioc_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-	.vidioc_g_register	= mcam_vidioc_g_register,
-	.vidioc_s_register	= mcam_vidioc_s_register,
-#endif
-};
-
-/* ---------------------------------------------------------------------- */
-/*
- * Our various file operations.
- */
-static int mcam_v4l_open(struct file *filp)
-{
-	struct mcam_camera *cam = video_drvdata(filp);
-	int ret = 0;
-
-	filp->private_data = cam;
-
-	cam->frame_state.frames = 0;
-	cam->frame_state.singles = 0;
-	cam->frame_state.delivered = 0;
-	mutex_lock(&cam->s_mutex);
-	if (cam->users == 0) {
-		ret = mcam_setup_vb2(cam);
-		if (ret)
-			goto out;
-		mcam_ctlr_power_up(cam);
-		__mcam_cam_reset(cam);
-		mcam_set_config_needed(cam, 1);
-	}
-	(cam->users)++;
-	cam->pll1 = devm_clk_get(cam->dev, "pll1");
-	if (IS_ERR(cam->pll1)) {
-		cam_err(cam, "Could not get pll1 clock\n");
-		ret = PTR_ERR(cam->pll1);
-	}
-out:
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-static int mcam_v4l_release(struct file *filp)
-{
-	struct mcam_camera *cam = filp->private_data;
-
-	cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n",
-			cam->frame_state.frames, cam->frame_state.singles,
-			cam->frame_state.delivered);
-	mutex_lock(&cam->s_mutex);
-	(cam->users)--;
-	if (cam->users == 0) {
-		mcam_ctlr_stop_dma(cam);
-		mcam_cleanup_vb2(cam);
-		mcam_config_mipi(cam, 0);
-		mcam_ctlr_power_down(cam);
-		if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read)
-			mcam_free_dma_bufs(cam);
-	}
-	mutex_unlock(&cam->s_mutex);
-	return 0;
-}
-
-static ssize_t mcam_v4l_read(struct file *filp,
-		char __user *buffer, size_t len, loff_t *pos)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_read(&cam->vb_queue, buffer, len, pos,
-			filp->f_flags & O_NONBLOCK);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-
-static unsigned int mcam_v4l_poll(struct file *filp,
-		struct poll_table_struct *pt)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_poll(&cam->vb_queue, filp, pt);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-static int mcam_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	struct mcam_camera *cam = filp->private_data;
-	int ret;
-
-	mutex_lock(&cam->s_mutex);
-	ret = vb2_mmap(&cam->vb_queue, vma);
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-}
-
-
-
-static const struct v4l2_file_operations mcam_v4l_fops = {
-	.owner = THIS_MODULE,
-	.open = mcam_v4l_open,
-	.release = mcam_v4l_release,
-	.read = mcam_v4l_read,
-	.poll = mcam_v4l_poll,
-	.mmap = mcam_v4l_mmap,
-	.unlocked_ioctl = video_ioctl2,
-};
-
-
-/*
- * This template device holds all of those v4l2 methods; we
- * clone it for specific real devices.
- */
-static struct video_device mcam_v4l_template = {
-	.name = "mcam",
-	.tvnorms = V4L2_STD_NTSC_M,
-	.current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
-
-	.fops = &mcam_v4l_fops,
-	.ioctl_ops = &mcam_v4l_ioctl_ops,
-	.release = video_device_release_empty,
-};
-
 /* ---------------------------------------------------------------------- */
 /*
  * Interrupt handler stuff
@@ -1924,125 +1173,6 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 	return handled;
 }
 
-/* ---------------------------------------------------------------------- */
-/*
- * Registration and such.
- */
-static struct ov7670_config sensor_cfg = {
-	/*
-	 * Exclude QCIF mode, because it only captures a tiny portion
-	 * of the sensor FOV
-	 */
-	.min_width = 320,
-	.min_height = 240,
-};
-
-
-int mccic_register(struct mcam_camera *cam)
-{
-	struct i2c_board_info ov7670_info = {
-		.type = "ov7670",
-		.addr = 0x42 >> 1,
-		.platform_data = &sensor_cfg,
-	};
-	int ret;
-
-	/*
-	 * Validate the requested buffer mode.
-	 */
-	if (buffer_mode >= 0)
-		cam->buffer_mode = buffer_mode;
-	if (cam->buffer_mode == B_DMA_sg &&
-			cam->chip_id == V4L2_IDENT_CAFE) {
-		printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, "
-			"attempting vmalloc mode instead\n");
-		cam->buffer_mode = B_vmalloc;
-	}
-	if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
-		printk(KERN_ERR "marvell-cam: buffer mode %d unsupported\n",
-				cam->buffer_mode);
-		return -EINVAL;
-	}
-	/*
-	 * Register with V4L
-	 */
-	ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
-	if (ret)
-		return ret;
-
-	mutex_init(&cam->s_mutex);
-	cam->state = S_NOTREADY;
-	mcam_set_config_needed(cam, 1);
-	cam->pix_format = mcam_def_pix_format;
-	cam->mbus_code = mcam_def_mbus_code;
-	INIT_LIST_HEAD(&cam->buffers);
-	mcam_ctlr_init(cam);
-
-	/*
-	 * Try to find the sensor.
-	 */
-	sensor_cfg.clock_speed = cam->clock_speed;
-	sensor_cfg.use_smbus = cam->use_smbus;
-	cam->sensor_addr = ov7670_info.addr;
-	cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev,
-			cam->i2c_adapter, &ov7670_info, NULL);
-	if (cam->sensor == NULL) {
-		ret = -ENODEV;
-		goto out_unregister;
-	}
-
-	ret = mcam_cam_init(cam);
-	if (ret)
-		goto out_unregister;
-	/*
-	 * Get the v4l2 setup done.
-	 */
-	mutex_lock(&cam->s_mutex);
-	cam->vdev = mcam_v4l_template;
-	cam->vdev.debug = 0;
-	cam->vdev.v4l2_dev = &cam->v4l2_dev;
-	ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
-	if (ret)
-		goto out;
-	video_set_drvdata(&cam->vdev, cam);
-
-	/*
-	 * If so requested, try to get our DMA buffers now.
-	 */
-	if (cam->buffer_mode == B_vmalloc && !alloc_bufs_at_read) {
-		if (mcam_alloc_dma_bufs(cam, 1))
-			cam_warn(cam, "Unable to alloc DMA buffers at load"
-					" will try again later.");
-	}
-
-out:
-	mutex_unlock(&cam->s_mutex);
-	return ret;
-out_unregister:
-	v4l2_device_unregister(&cam->v4l2_dev);
-	return ret;
-}
-
-
-void mccic_shutdown(struct mcam_camera *cam)
-{
-	/*
-	 * If we have no users (and we really, really should have no
-	 * users) the device will already be powered down.  Trying to
-	 * take it down again will wedge the machine, which is frowned
-	 * upon.
-	 */
-	if (cam->users > 0) {
-		cam_warn(cam, "Removing a device with users!\n");
-		mcam_ctlr_power_down(cam);
-	}
-	vb2_queue_release(&cam->vb_queue);
-	if (cam->buffer_mode == B_vmalloc)
-		mcam_free_dma_bufs(cam);
-	video_unregister_device(&cam->vdev);
-	v4l2_device_unregister(&cam->v4l2_dev);
-}
-
 /*
  * Power management
  */
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 3ea25ed..4670c49 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -32,6 +32,18 @@
 #error One of the videobuf buffer modes must be selected in the config
 #endif
 
+#define sensor_call(cam, o, f, args...) \
+	v4l2_subdev_call(cam->sensor, o, f, ##args)
+
+/*
+ * Debugging and related.
+ */
+#define cam_err(cam, fmt, arg...) \
+	dev_err((cam)->dev, fmt, ##arg);
+#define cam_warn(cam, fmt, arg...) \
+	dev_warn((cam)->dev, fmt, ##arg);
+#define cam_dbg(cam, fmt, arg...) \
+	dev_dbg((cam)->dev, fmt, ##arg);
 
 enum mcam_state {
 	S_NOTREADY,	/* Not yet initialized */
@@ -174,6 +186,36 @@ struct mcam_camera {
 	struct mutex s_mutex; /* Access to this structure */
 };
 
+/*
+ * The two-word DMA descriptor format used by the Armada 610 and like.  There
+ * Is a three-word format as well (set C1_DESC_3WORD) where the third
+ * word is a pointer to the next descriptor, but we don't use it.  Two-word
+ * descriptors have to be contiguous in memory.
+ */
+struct mcam_dma_desc {
+	u32 dma_addr;
+	u32 segment_len;
+};
+
+struct yuv_pointer_t {
+	dma_addr_t y;
+	dma_addr_t u;
+	dma_addr_t v;
+};
+
+/*
+ * Our buffer type for working with videobuf2.  Note that the vb2
+ * developers have decreed that struct vb2_buffer must be at the
+ * beginning of this structure.
+ */
+struct mcam_vb_buffer {
+	struct vb2_buffer vb_buf;
+	struct list_head queue;
+	struct mcam_dma_desc *dma_desc;	/* Descriptor virtual address */
+	dma_addr_t dma_desc_pa;		/* Descriptor physical address */
+	int dma_desc_nent;		/* Number of mapped descriptors */
+	struct yuv_pointer_t yuv_p;
+};
 
 /*
  * Register I/O functions.  These are here because the platform code
@@ -367,4 +409,16 @@ int mccic_resume(struct mcam_camera *cam);
 #define VGA_WIDTH	640
 #define VGA_HEIGHT	480
 
+/*
+ * The default format we use until somebody says otherwise.
+ */
+static const struct v4l2_pix_format mcam_def_pix_format = {
+	.width		= VGA_WIDTH,
+	.height		= VGA_HEIGHT,
+	.pixelformat	= V4L2_PIX_FMT_YUYV,
+	.field		= V4L2_FIELD_NONE,
+	.bytesperline	= VGA_WIDTH*2,
+	.sizeimage	= VGA_WIDTH*VGA_HEIGHT*2,
+};
+
 #endif /* _MCAM_CORE_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 11/15] [media] marvell-ccic: add soc_camera support in mcam core
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (9 preceding siblings ...)
  2012-12-15  9:57 ` [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support Albert Wang
@ 2012-12-15  9:58 ` Albert Wang
  2012-12-15  9:58 ` [PATCH V3 12/15] [media] marvell-ccic: add soc_camera support in mmp driver Albert Wang
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:58 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang, Libin Yang

This patch adds the soc_camera support in mcam core.

It creates the file mcam-core-soc.c and mcam-core-soc.h
to support soc_camera in mcam core.

To use the soc_camera feature, platform driver, such as mmp-driver.c,
should also be modified.

Signed-off-by: Libin Yang <lbyang@marvell.com>
Signed-off-by: Albert Wang <twang13@marvell.com>
---
 drivers/media/platform/marvell-ccic/Makefile       |    2 +
 .../media/platform/marvell-ccic/mcam-core-soc.c    |  416 ++++++++++++++++++++
 .../media/platform/marvell-ccic/mcam-core-soc.h    |   19 +
 drivers/media/platform/marvell-ccic/mcam-core.c    |    2 +-
 drivers/media/platform/marvell-ccic/mcam-core.h    |   31 ++
 include/media/mmp-camera.h                         |    3 +
 6 files changed, 472 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/platform/marvell-ccic/mcam-core-soc.c
 create mode 100644 drivers/media/platform/marvell-ccic/mcam-core-soc.h

diff --git a/drivers/media/platform/marvell-ccic/Makefile b/drivers/media/platform/marvell-ccic/Makefile
index 595ebdf..b3e87d4 100755
--- a/drivers/media/platform/marvell-ccic/Makefile
+++ b/drivers/media/platform/marvell-ccic/Makefile
@@ -4,3 +4,5 @@ cafe_ccic-y := cafe-driver.o mcam-core.o
 obj-$(CONFIG_VIDEO_MMP_CAMERA) += mmp_camera_standard.o
 mmp_camera_standard-y := mmp-driver.o mcam-core.o mcam-core-standard.o
 
+obj-$(CONFIG_VIDEO_MMP_SOC_CAMERA) += mmp_camera_soc.o
+mmp_camera_soc-y := mmp-driver.o mcam-core.o mcam-core-soc.o
diff --git a/drivers/media/platform/marvell-ccic/mcam-core-soc.c b/drivers/media/platform/marvell-ccic/mcam-core-soc.c
new file mode 100644
index 0000000..9016dc6
--- /dev/null
+++ b/drivers/media/platform/marvell-ccic/mcam-core-soc.c
@@ -0,0 +1,416 @@
+/*
+ * The Marvell camera soc core.	 This device appears in a number of settings,
+ * so it needs platform-specific support outside of the core.
+ *
+ * Copyright (C) 2009-2012 Marvell International Ltd.
+ *
+ * Author: Libin Yang <lbyang@marvell.com>
+ *         Albert Wang <twang13@marvell.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+#include <linux/clk.h>
+
+#include "mcam-core.h"
+#include "mcam-core-soc.h"
+
+static const enum v4l2_mbus_pixelcode mcam_def_mbus_code =
+					V4L2_MBUS_FMT_YUYV8_2X8;
+
+static const struct soc_mbus_pixelfmt mcam_formats[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_UYVY,
+		.name = "YUV422PACKED",
+		.bits_per_sample = 8,
+		.packing = SOC_MBUS_PACKING_2X8_PADLO,
+		.order = SOC_MBUS_ORDER_LE,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV422P,
+		.name = "YUV422PLANAR",
+		.bits_per_sample = 8,
+		.packing = SOC_MBUS_PACKING_2X8_PADLO,
+		.order = SOC_MBUS_ORDER_LE,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.name = "YUV420PLANAR",
+		.bits_per_sample = 12,
+		.packing = SOC_MBUS_PACKING_NONE,
+		.order = SOC_MBUS_ORDER_LE,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YVU420,
+		.name = "YVU420PLANAR",
+		.bits_per_sample = 12,
+		.packing = SOC_MBUS_PACKING_NONE,
+		.order = SOC_MBUS_ORDER_LE,
+	},
+};
+
+static int mcam_camera_add_device(struct soc_camera_device *icd)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	int ret;
+
+	if (mcam->icd)
+		return -EBUSY;
+
+	mcam->frame_complete = mcam_dma_contig_done;
+	mcam->frame_state.frames = 0;
+	mcam->frame_state.singles = 0;
+	mcam->frame_state.delivered = 0;
+
+	mcam->pll1 = devm_clk_get(mcam->dev, "pll1");
+	if (IS_ERR(mcam->pll1)) {
+		cam_err(mcam, "Could not get pll1 clock\n");
+		return PTR_ERR(mcam->pll1);
+	}
+
+	mcam->flags = 0;
+	mcam->icd = icd;
+	mcam->state = S_IDLE;
+	mcam->dma_setup = mcam_ctlr_dma_contig;
+	mcam_ctlr_power_up(mcam);
+	mcam_ctlr_stop(mcam);
+	mcam_set_config_needed(mcam, 1);
+	mcam_reg_write(mcam, REG_CTRL1,
+				   C1_RESERVED | C1_DMAPOSTED);
+	mcam_reg_write(mcam, REG_CLKCTRL,
+		(mcam->mclk_src << 29) | mcam->mclk_div);
+	cam_dbg(mcam, "camera: set sensor mclk = %dMHz\n", mcam->mclk_min);
+	/*
+	 * Need sleep 1ms to wait for CCIC stable
+	 * This is a workround for OV5640 MIPI
+	 * TODO: Fix me in the future
+	 */
+	usleep_range(1000, 2000);
+
+	/*
+	 * Mask all interrupts.
+	 */
+	mcam_reg_write(mcam, REG_IRQMASK, 0);
+	ret = sensor_call(mcam, core, init, 0);
+	/*
+	 * When sensor_call return -ENOIOCTLCMD,
+	 * means No ioctl command
+	 */
+	if ((ret < 0) && (ret != -ENOIOCTLCMD) && (ret != -ENODEV)) {
+		dev_err(icd->parent,
+			"camera: Failed to initialize subdev: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void mcam_camera_remove_device(struct soc_camera_device *icd)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+
+	BUG_ON(icd != mcam->icd);
+	cam_dbg(mcam, "Release %d frames, %d singles, %d delivered\n",
+		mcam->frame_state.frames, mcam->frame_state.singles,
+		mcam->frame_state.delivered);
+	mcam_config_mipi(mcam, 0);
+	mcam_ctlr_power_down(mcam);
+	mcam->icd = NULL;
+}
+
+static int mcam_camera_set_fmt(struct soc_camera_device *icd,
+			struct v4l2_format *f)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	const struct soc_camera_format_xlate *xlate = NULL;
+	struct v4l2_mbus_framefmt mf;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	int ret;
+
+	cam_dbg(mcam, "camera: set_fmt: %c, width = %u, height = %u\n",
+		pix->pixelformat, pix->width, pix->height);
+	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+	if (!xlate) {
+		cam_err(mcam, "camera: format: %c not found\n",
+			pix->pixelformat);
+		return -EINVAL;
+	}
+
+	mf.width = pix->width;
+	mf.height = pix->height;
+	mf.field = V4L2_FIELD_NONE;
+	mf.colorspace = pix->colorspace;
+	mf.code = xlate->code;
+
+	ret = sensor_call(mcam, video, s_mbus_fmt, &mf);
+	if (ret < 0) {
+		cam_err(mcam, "camera: set_fmt failed %d\n", __LINE__);
+		return ret;
+	}
+
+	if (mf.code != xlate->code) {
+		cam_err(mcam, "camera: wrong code %s %d\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	pix->width = mf.width;
+	pix->height = mf.height;
+	pix->field = mf.field;
+	pix->colorspace = mf.colorspace;
+	mcam->pix_format.sizeimage = pix->sizeimage;
+	icd->current_fmt = xlate;
+
+	memcpy(&(mcam->pix_format), pix, sizeof(struct v4l2_pix_format));
+	mcam_ctlr_image(mcam);
+	mcam_set_config_needed(mcam, 1);
+
+	return ret;
+}
+
+static int mcam_camera_try_fmt(struct soc_camera_device *icd,
+			struct v4l2_format *f)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	const struct soc_camera_format_xlate *xlate;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_mbus_framefmt mf;
+	__u32 pixfmt = pix->pixelformat;
+	int ret;
+
+	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+	if (!xlate) {
+		/* using default fmt and try again*/
+		/* to be verified */
+		memcpy(pix, &mcam_def_pix_format,
+			sizeof(struct v4l2_pix_format));
+	}
+
+	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+	if (!xlate) {
+		/* it seems something really bad happens */
+		cam_err(mcam, "camera: format: %c not found\n",
+			pix->pixelformat);
+		return -EINVAL;
+	}
+
+	if (pix->bytesperline < 0)
+		return pix->bytesperline;
+
+	/*
+	 * limit to sensor capabilities
+	 */
+	mf.width = pix->width;
+	mf.height = pix->height;
+	mf.field = V4L2_FIELD_NONE;
+	mf.colorspace = pix->colorspace;
+	mf.code = xlate->code;
+
+	ret = sensor_call(mcam, video, try_mbus_fmt, &mf);
+	if (ret < 0)
+		return ret;
+
+	pix->width = mf.width;
+	pix->height = mf.height;
+	pix->colorspace = mf.colorspace;
+
+	switch (mf.field) {
+	case V4L2_FIELD_ANY:
+	case V4L2_FIELD_NONE:
+		pix->field = V4L2_FIELD_NONE;
+		break;
+	default:
+		cam_warn(mcam, "cam: Field type %d unsupported.\n", mf.field);
+		pix->field = V4L2_FIELD_NONE;
+		break;
+	}
+
+	return ret;
+}
+
+static int mcam_camera_init_videobuf(struct vb2_queue *q,
+			struct soc_camera_device *icd)
+{
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_USERPTR | VB2_MMAP;
+	q->drv_priv = icd;
+	q->ops = &mcam_vb2_ops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct mcam_vb_buffer);
+
+	return vb2_queue_init(q);
+}
+
+static unsigned int mcam_camera_poll(struct file *file, poll_table *pt)
+{
+	struct soc_camera_device *icd = file->private_data;
+
+	return vb2_poll(&icd->vb2_vidq, file, pt);
+}
+
+static int mcam_camera_querycap(struct soc_camera_host *ici,
+			struct v4l2_capability *cap)
+{
+	struct mcam_camera *mcam = ici->priv;
+
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	strcpy(cap->card, mcam->card_name);
+	strcpy(cap->driver, "marvell_ccic");
+
+	return 0;
+}
+
+static int mcam_camera_set_bus_param(struct soc_camera_device *icd)
+{
+	return 0;
+}
+
+static int mcam_camera_get_formats(struct soc_camera_device *icd, u32 idx,
+			struct soc_camera_format_xlate	*xlate)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	enum v4l2_mbus_pixelcode code;
+	const struct soc_mbus_pixelfmt *fmt;
+	int formats = 0, ret, i;
+
+	ret = sensor_call(mcam, video, enum_mbus_fmt, idx, &code);
+	if (ret < 0)
+		/*
+		 * No more formats
+		 */
+		return 0;
+
+	fmt = soc_mbus_get_fmtdesc(code);
+	if (!fmt) {
+		cam_err(mcam, "camera: Invalid format #%u: %d\n", idx, code);
+		return 0;
+	}
+
+	switch (code) {
+	/*
+	 * Refer to mbus_fmt struct
+	 */
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		/*
+		 * Add support for YUV420 and YUV422P
+		 */
+		formats = ARRAY_SIZE(mcam_formats);
+		if (xlate) {
+			for (i = 0; i < ARRAY_SIZE(mcam_formats); i++) {
+				xlate->host_fmt = &mcam_formats[i];
+				xlate->code = code;
+				xlate++;
+			}
+		}
+		return formats;
+	case V4L2_MBUS_FMT_JPEG_1X8:
+		if (xlate)
+			cam_dbg(mcam, "camera: Providing format: %s\n",
+				fmt->name);
+		break;
+	default:
+		/*
+		 * camera controller can not support
+		 * this format, which might supported by the sensor
+		 */
+		cam_warn(mcam, "camera: Not support fmt: %s\n", fmt->name);
+		return 0;
+	}
+
+	formats++;
+	if (xlate) {
+		xlate->host_fmt = fmt;
+		xlate->code = code;
+		xlate++;
+	}
+
+	return formats;
+}
+
+struct soc_camera_host_ops mcam_soc_camera_host_ops = {
+	.owner		= THIS_MODULE,
+	.add		= mcam_camera_add_device,
+	.remove		= mcam_camera_remove_device,
+	.set_fmt	= mcam_camera_set_fmt,
+	.try_fmt	= mcam_camera_try_fmt,
+	.init_videobuf2	= mcam_camera_init_videobuf,
+	.poll		= mcam_camera_poll,
+	.querycap	= mcam_camera_querycap,
+	.set_bus_param	= mcam_camera_set_bus_param,
+	.get_formats	= mcam_camera_get_formats,
+};
+
+int mcam_soc_camera_host_register(struct mcam_camera *mcam)
+{
+	mcam->soc_host.drv_name = "mmp-camera";
+	mcam->soc_host.ops = &mcam_soc_camera_host_ops;
+	mcam->soc_host.priv = mcam;
+	mcam->soc_host.v4l2_dev.dev = mcam->dev;
+	mcam->soc_host.nr = mcam->ccic_id;
+	return soc_camera_host_register(&mcam->soc_host);
+}
+
+int mccic_register(struct mcam_camera *cam)
+{
+	int ret;
+
+	cam->buffer_mode = B_DMA_contig;
+	/*
+	 * Validate the requested buffer mode.
+	 */
+	if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
+		cam_err(cam, "marvell-cam: buffer mode %d unsupported\n",
+				cam->buffer_mode);
+		return -EINVAL;
+	}
+
+	cam->vb_alloc_ctx =
+		vb2_dma_contig_init_ctx(cam->dev);
+	if (IS_ERR(cam->vb_alloc_ctx))
+		return PTR_ERR(cam->vb_alloc_ctx);
+
+	mutex_init(&cam->s_mutex);
+	cam->state = S_NOTREADY;
+	mcam_set_config_needed(cam, 1);
+	cam->pix_format = mcam_def_pix_format;
+	cam->mbus_code = mcam_def_mbus_code;
+	INIT_LIST_HEAD(&cam->buffers);
+
+	ret = mcam_soc_camera_host_register(cam);
+	if (ret) {
+		vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
+		cam->vb_alloc_ctx = NULL;
+	}
+	return ret;
+}
+
+void mccic_shutdown(struct mcam_camera *cam)
+{
+	struct soc_camera_host *soc_host = &cam->soc_host;
+	/*
+	 * If we have no users (and we really, really should have no
+	 * users) the device will already be powered down.  Trying to
+	 * take it down again will wedge the machine, which is frowned
+	 * upon.
+	 */
+	if (cam->users > 0) {
+		cam_warn(cam, "Removing a device with users!\n");
+		mcam_ctlr_power_down(cam);
+	}
+	vb2_queue_release(&cam->vb_queue);
+	soc_camera_host_unregister(soc_host);
+	vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
+	cam->vb_alloc_ctx = NULL;
+}
diff --git a/drivers/media/platform/marvell-ccic/mcam-core-soc.h b/drivers/media/platform/marvell-ccic/mcam-core-soc.h
new file mode 100644
index 0000000..fbdaa5d
--- /dev/null
+++ b/drivers/media/platform/marvell-ccic/mcam-core-soc.h
@@ -0,0 +1,19 @@
+/*
+ * Marvell camera core structures.
+ *
+ * Copyright (C) 2009-2012 Marvell International Ltd.
+ *
+ * Author: Libin Yang <lbyang@marvell.com>
+ *         Albert Wang <twang13@marvell.com>
+ *
+ */
+extern const struct vb2_ops mcam_vb2_ops;
+
+void mcam_ctlr_power_up(struct mcam_camera *cam);
+void mcam_ctlr_power_down(struct mcam_camera *cam);
+void mcam_dma_contig_done(struct mcam_camera *cam, int frame);
+void mcam_ctlr_stop(struct mcam_camera *cam);
+int mcam_config_mipi(struct mcam_camera *mcam, int enable);
+void mcam_ctlr_image(struct mcam_camera *cam);
+void mcam_set_config_needed(struct mcam_camera *cam, int needed);
+void mcam_ctlr_dma_contig(struct mcam_camera *cam);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index dccc573..97b40db 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -154,7 +154,7 @@ static void mcam_ctlr_start(struct mcam_camera *cam)
 	mcam_reg_set_bit(cam, REG_CTRL0, C0_ENABLE);
 }
 
-static void mcam_ctlr_stop(struct mcam_camera *cam)
+void mcam_ctlr_stop(struct mcam_camera *cam)
 {
 	mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
 }
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 4670c49..57442e0 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -10,6 +10,8 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf2-core.h>
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 
 /*
  * Create our own symbols for the supported buffer modes, but, for now,
@@ -32,8 +34,13 @@
 #error One of the videobuf buffer modes must be selected in the config
 #endif
 
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+#define sensor_call(cam, o, f, args...) \
+	v4l2_subdev_call(soc_camera_to_subdev(cam->icd), o, f, ##args)
+#else
 #define sensor_call(cam, o, f, args...) \
 	v4l2_subdev_call(cam->sensor, o, f, ##args)
+#endif
 
 /*
  * Debugging and related.
@@ -102,6 +109,10 @@ struct mcam_frame_state {
  */
 #define NR_MCAM_CLK 4
 struct mcam_camera {
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+	struct soc_camera_host soc_host;
+	struct soc_camera_device *icd;
+#endif
 	/*
 	 * These fields should be set by the platform code prior to
 	 * calling mcam_register().
@@ -115,6 +126,11 @@ struct mcam_camera {
 	short int use_smbus;	/* SMBUS or straight I2c? */
 	enum mcam_buffer_mode buffer_mode;
 
+	int mclk_min;
+	int mclk_src;
+	int mclk_div;
+	char *card_name;
+
 	int ccic_id;
 	enum v4l2_mbus_type bus_type;
 	/* MIPI support */
@@ -258,10 +274,20 @@ static inline void mcam_reg_set_bit(struct mcam_camera *cam,
 	mcam_reg_write_mask(cam, reg, val, val);
 }
 
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+static inline struct mcam_camera *get_mcam(struct vb2_queue *vq)
+{
+	struct soc_camera_device *icd = container_of(vq,
+					struct soc_camera_device, vb2_vidq);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	return ici->priv;
+}
+#else
 static inline struct mcam_camera *get_mcam(struct vb2_queue *vq)
 {
 	return vb2_get_drv_priv(vq);
 }
+#endif
 
 /*
  * Functions for use by platform code.
@@ -273,6 +299,9 @@ void mccic_shutdown(struct mcam_camera *cam);
 void mccic_suspend(struct mcam_camera *cam);
 int mccic_resume(struct mcam_camera *cam);
 #endif
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+int mcam_soc_camera_host_register(struct mcam_camera *mcam);
+#endif
 
 /*
  * Register definitions for the m88alp01 camera interface.  Offsets in bytes
@@ -377,6 +406,7 @@ int mccic_resume(struct mcam_camera *cam);
 /* Bits below C1_444ALPHA are not present in Cafe */
 #define REG_CTRL1	0x40	/* Control 1 */
 #define	  C1_CLKGATE	  0x00000001	/* Sensor clock gate */
+#define   C1_RESERVED	  0x0000003c	/* Reserved and shouldn't be changed */
 #define   C1_DESC_ENA	  0x00000100	/* DMA descriptor enable */
 #define   C1_DESC_3WORD   0x00000200	/* Three-word descriptors used */
 #define	  C1_444ALPHA	  0x00f00000	/* Alpha field in RGB444 */
@@ -387,6 +417,7 @@ int mccic_resume(struct mcam_camera *cam);
 #define	  C1_DMAB_MASK	  0x06000000
 #define	  C1_TWOBUFS	  0x08000000	/* Use only two DMA buffers */
 #define	  C1_PWRDWN	  0x10000000	/* Power down */
+#define   C1_DMAPOSTED	  0x40000000	/* DMA Posted Select */
 
 #define REG_CTRL3	0x1ec	/* CCIC parallel mode */
 #define REG_CLKCTRL	0x88	/* Clock control */
diff --git a/include/media/mmp-camera.h b/include/media/mmp-camera.h
index c339d43..9968031 100755
--- a/include/media/mmp-camera.h
+++ b/include/media/mmp-camera.h
@@ -8,6 +8,9 @@ struct mmp_camera_platform_data {
 	int sensor_power_gpio;
 	int sensor_reset_gpio;
 	enum v4l2_mbus_type bus_type;
+	int mclk_min;
+	int mclk_src;
+	int mclk_div;
 	/*
 	 * MIPI support
 	 */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 12/15] [media] marvell-ccic: add soc_camera support in mmp driver
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (10 preceding siblings ...)
  2012-12-15  9:58 ` [PATCH V3 11/15] [media] marvell-ccic: add soc_camera support in mcam core Albert Wang
@ 2012-12-15  9:58 ` Albert Wang
  2012-12-16 16:46   ` Jonathan Corbet
  2012-12-15  9:58 ` [PATCH V3 13/15] [media] marvell-ccic: add dma burst mode support in marvell-ccic driver Albert Wang
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:58 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang, Libin Yang

This patch adds the soc_camera support in the platform driver: mmp-driver.c.
Specified board driver also should be modified to support soc_camera by passing
some platform datas to platform driver.

Currently the soc_camera mode in mmp driver only supports B_DMA_contig mode.

Signed-off-by: Libin Yang <lbyang@marvell.com>
Signed-off-by: Albert Wang <twang13@marvell.com>
---
 drivers/media/platform/Makefile                  |    4 +-
 drivers/media/platform/marvell-ccic/Kconfig      |   22 ++++
 drivers/media/platform/marvell-ccic/mmp-driver.c |  147 ++++++++++++++--------
 include/media/mmp-camera.h                       |    2 +
 4 files changed, 120 insertions(+), 55 deletions(-)

diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index baaa550..95c1ce5 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -11,8 +11,6 @@ obj-$(CONFIG_VIDEO_TIMBERDALE)	+= timblogiw.o
 obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
 
 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
-obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/
-obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/
 
 obj-$(CONFIG_VIDEO_OMAP2)		+= omap2cam.o
 obj-$(CONFIG_VIDEO_OMAP3)	+= omap3isp/
@@ -43,6 +41,8 @@ obj-$(CONFIG_VIDEO_SH_VOU)		+= sh_vou.o
 
 obj-$(CONFIG_SOC_CAMERA)		+= soc_camera/
 
+obj-$(CONFIG_VIDEO_MARVELL_CCIC) 	+= marvell-ccic/
+
 obj-y	+= davinci/
 
 obj-$(CONFIG_ARCH_OMAP)	+= omap/
diff --git a/drivers/media/platform/marvell-ccic/Kconfig b/drivers/media/platform/marvell-ccic/Kconfig
index bf739e3..910c068 100755
--- a/drivers/media/platform/marvell-ccic/Kconfig
+++ b/drivers/media/platform/marvell-ccic/Kconfig
@@ -1,23 +1,45 @@
+config VIDEO_MARVELL_CCIC
+       tristate
+config VIDEO_MRVL_SOC_CAMERA
+       bool
+
 config VIDEO_CAFE_CCIC
 	tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support"
 	depends on PCI && I2C && VIDEO_V4L2
 	select VIDEO_OV7670
 	select VIDEOBUF2_VMALLOC
 	select VIDEOBUF2_DMA_CONTIG
+	select VIDEO_MARVELL_CCIC
 	---help---
 	  This is a video4linux2 driver for the Marvell 88ALP01 integrated
 	  CMOS camera controller.  This is the controller found on first-
 	  generation OLPC systems.
 
+choice
+	prompt "Camera support on Marvell MMP"
+	depends on ARCH_MMP && VIDEO_V4L2
+	optional
 config VIDEO_MMP_CAMERA
 	tristate "Marvell Armada 610 integrated camera controller support"
 	depends on ARCH_MMP && I2C && VIDEO_V4L2
 	select VIDEO_OV7670
 	select I2C_GPIO
 	select VIDEOBUF2_DMA_SG
+	select VIDEO_MARVELL_CCIC
 	---help---
 	  This is a Video4Linux2 driver for the integrated camera
 	  controller found on Marvell Armada 610 application
 	  processors (and likely beyond).  This is the controller found
 	  in OLPC XO 1.75 systems.
 
+config VIDEO_MMP_SOC_CAMERA
+	bool "Marvell MMP camera driver based on SOC_CAMERA"
+	depends on VIDEO_DEV && SOC_CAMERA && ARCH_MMP && VIDEO_V4L2
+	select VIDEOBUF2_DMA_CONTIG
+	select VIDEO_MARVELL_CCIC
+	select VIDEO_MRVL_SOC_CAMERA
+	---help---
+	  This is a Video4Linux2 driver for the Marvell Mobile Soc
+	  PXA910/PXA688/PXA2128/PXA988 CCIC
+	  (CMOS Camera Interface Controller)
+endchoice
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 40c243e..cd850f4 100755
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -28,6 +28,10 @@
 #include <linux/list.h>
 #include <linux/pm.h>
 #include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 
 #include "mcam-core.h"
 
@@ -40,6 +44,8 @@ struct mmp_camera {
 	struct platform_device *pdev;
 	struct mcam_camera mcam;
 	struct list_head devlist;
+	/* will change here */
+	struct clk *clk[3];	/* CCIC_GATE, CCIC_RST, CCIC_DBG clocks */
 	int irq;
 };
 
@@ -144,15 +150,17 @@ static void mmpcam_power_up(struct mcam_camera *mcam)
  * Provide power to the sensor.
  */
 	mcam_reg_write(mcam, REG_CLKCTRL, 0x60000002);
-	pdata = cam->pdev->dev.platform_data;
-	gpio_set_value(pdata->sensor_power_gpio, 1);
-	mdelay(5);
+	if (mcam->chip_id == V4L2_IDENT_ARMADA610) {
+		pdata = cam->pdev->dev.platform_data;
+		gpio_set_value(pdata->sensor_power_gpio, 1);
+		mdelay(5);
+		/* reset is active low */
+		gpio_set_value(pdata->sensor_reset_gpio, 0);
+		mdelay(5);
+		gpio_set_value(pdata->sensor_reset_gpio, 1);
+		mdelay(5);
+	}
 	mcam_reg_clear_bit(mcam, REG_CTRL1, 0x10000000);
-	gpio_set_value(pdata->sensor_reset_gpio, 0); /* reset is active low */
-	mdelay(5);
-	gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
-	mdelay(5);
-
 	mcam_clk_set(mcam, 1);
 }
 
@@ -165,13 +173,14 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
  */
 	iowrite32(0, cam->power_regs + REG_CCIC_DCGCR);
 	iowrite32(0, cam->power_regs + REG_CCIC_CRCR);
-/*
- * Shut down the sensor.
- */
-	pdata = cam->pdev->dev.platform_data;
-	gpio_set_value(pdata->sensor_power_gpio, 0);
-	gpio_set_value(pdata->sensor_reset_gpio, 0);
-
+	if (mcam->chip_id == V4L2_IDENT_ARMADA610) {
+		/*
+		 * Shut down the sensor.
+		 */
+		pdata = cam->pdev->dev.platform_data;
+		gpio_set_value(pdata->sensor_power_gpio, 0);
+		gpio_set_value(pdata->sensor_reset_gpio, 0);
+	}
 	mcam_clk_set(mcam, 0);
 }
 
@@ -303,6 +312,52 @@ static void mcam_init_clk(struct mcam_camera *mcam,
 		mcam->clk_num = 0;
 }
 
+static int mmp_probe(struct mcam_camera *mcam, struct platform_device *pdev)
+{
+	struct mmp_camera_platform_data *pdata;
+	int ret;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -ENODEV;
+
+	/*
+	 * Find the i2c adapter.  This assumes, of course, that the
+	 * i2c bus is already up and functioning.
+	 * soc-camera manages i2c interface in sensor side
+	 */
+	mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
+	if (mcam->i2c_adapter == NULL) {
+		dev_err(&pdev->dev, "No i2c adapter\n");
+		return -ENODEV;
+	}
+	/*
+	 * Sensor GPIO pins.
+	 */
+	ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio,
+				"cam-power");
+	if (ret) {
+		dev_err(&pdev->dev, "Can't get sensor power gpio %d",
+				pdata->sensor_power_gpio);
+		return ret;
+	}
+	gpio_direction_output(pdata->sensor_power_gpio, 0);
+	ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio,
+				"cam-reset");
+	if (ret) {
+		dev_err(&pdev->dev, "Can't get sensor reset gpio %d",
+				pdata->sensor_reset_gpio);
+		return ret;
+	}
+	gpio_direction_output(pdata->sensor_reset_gpio, 0);
+
+	/*
+	 * Power the device up and hand it off to the core.
+	 */
+	mmpcam_power_up(mcam);
+	return ret;
+}
+
 static int mmpcam_probe(struct platform_device *pdev)
 {
 	struct mmp_camera *cam;
@@ -322,6 +377,7 @@ static int mmpcam_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&cam->devlist);
 
 	mcam = &cam->mcam;
+	spin_lock_init(&mcam->dev_lock);
 	mcam->plat_power_up = mmpcam_power_up;
 	mcam->plat_power_down = mmpcam_power_down;
 	mcam->ctlr_reset = mcam_ctlr_reset;
@@ -329,14 +385,23 @@ static int mmpcam_probe(struct platform_device *pdev)
 	mcam->pll1 = NULL;
 	mcam->dev = &pdev->dev;
 	mcam->use_smbus = 0;
+	mcam->card_name = pdata->name;
+	mcam->mclk_min = pdata->mclk_min;
+	mcam->mclk_src = pdata->mclk_src;
+	mcam->mclk_div = pdata->mclk_div;
+	if (pdata->chip_id != V4L2_IDENT_NONE)
+		mcam->chip_id = pdata->chip_id;
+	else
+		mcam->chip_id = V4L2_IDENT_ARMADA610;
+	/* set B_DMA_sg as default */
+	mcam->buffer_mode = B_DMA_sg;
 	mcam->ccic_id = pdev->id;
 	mcam->bus_type = pdata->bus_type;
 	mcam->dphy = pdata->dphy;
 	mcam->mipi_enabled = 0;
 	mcam->lane = pdata->lane;
-	mcam->chip_id = V4L2_IDENT_ARMADA610;
-	mcam->buffer_mode = B_DMA_sg;
-	spin_lock_init(&mcam->dev_lock);
+	INIT_LIST_HEAD(&mcam->buffers);
+
 	/*
 	 * Get our I/O memory.
 	 */
@@ -366,40 +431,13 @@ static int mmpcam_probe(struct platform_device *pdev)
 	}
 
 	mcam_init_clk(mcam, pdata, 1);
-	/*
-	 * Find the i2c adapter.  This assumes, of course, that the
-	 * i2c bus is already up and functioning.
-	 */
-	mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
-	if (mcam->i2c_adapter == NULL) {
-		dev_err(&pdev->dev, "No i2c adapter\n");
-		ret = -ENODEV;
-		goto out_uninit_clk;
-	}
-	/*
-	 * Sensor GPIO pins.
-	 */
-	ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio,
-					"cam-power");
-	if (ret) {
-		dev_err(&pdev->dev, "Can't get sensor power gpio %d",
-				pdata->sensor_power_gpio);
-		goto out_uninit_clk;
-	}
-	gpio_direction_output(pdata->sensor_power_gpio, 0);
-	ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio,
-					"cam-reset");
-	if (ret) {
-		dev_err(&pdev->dev, "Can't get sensor reset gpio %d",
-				pdata->sensor_reset_gpio);
-		goto out_uninit_clk;
+
+	if (mcam->chip_id == V4L2_IDENT_ARMADA610) {
+		ret = mmp_probe(mcam, pdev);
+		if (ret)
+			goto out_uninit_clk;
 	}
-	gpio_direction_output(pdata->sensor_reset_gpio, 0);
 
-	/*
-	 * Power the device up and hand it off to the core.
-	 */
-	mmpcam_power_up(mcam);
 	ret = mccic_register(mcam);
 	if (ret)
 		goto out_power_down;
@@ -415,6 +453,9 @@ static int mmpcam_probe(struct platform_device *pdev)
 	cam->irq = res->start;
 	ret = devm_request_irq(&pdev->dev, cam->irq, mmpcam_irq, IRQF_SHARED,
 					"mmp-camera", mcam);
+	if (ret)
+		goto out_unregister;
+
 	if (ret == 0) {
 		mmpcam_add_device(cam);
 		return 0;
@@ -423,7 +464,8 @@ static int mmpcam_probe(struct platform_device *pdev)
 out_unregister:
 	mccic_shutdown(mcam);
 out_power_down:
-	mmpcam_power_down(mcam);
+	if (mcam->chip_id == V4L2_IDENT_ARMADA610)
+		mmpcam_power_down(mcam);
 out_uninit_clk:
 	mcam_init_clk(mcam, pdata, 0);
 	return ret;
@@ -433,12 +475,11 @@ out_uninit_clk:
 static int mmpcam_remove(struct mmp_camera *cam)
 {
 	struct mcam_camera *mcam = &cam->mcam;
-	struct mmp_camera_platform_data *pdata;
+	struct mmp_camera_platform_data *pdata = cam->pdev->dev.platform_data;
 
 	mmpcam_remove_device(cam);
 	mccic_shutdown(mcam);
 	mmpcam_power_down(mcam);
-	pdata = cam->pdev->dev.platform_data;
 	mcam_init_clk(mcam, pdata, 0);
 	return 0;
 }
diff --git a/include/media/mmp-camera.h b/include/media/mmp-camera.h
index 9968031..ec4f21f 100755
--- a/include/media/mmp-camera.h
+++ b/include/media/mmp-camera.h
@@ -7,10 +7,12 @@ struct mmp_camera_platform_data {
 	struct platform_device *i2c_device;
 	int sensor_power_gpio;
 	int sensor_reset_gpio;
+	char name[16];
 	enum v4l2_mbus_type bus_type;
 	int mclk_min;
 	int mclk_src;
 	int mclk_div;
+	int chip_id;
 	/*
 	 * MIPI support
 	 */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 13/15] [media] marvell-ccic: add dma burst mode support in marvell-ccic driver
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (11 preceding siblings ...)
  2012-12-15  9:58 ` [PATCH V3 12/15] [media] marvell-ccic: add soc_camera support in mmp driver Albert Wang
@ 2012-12-15  9:58 ` Albert Wang
  2012-12-16 16:49   ` Jonathan Corbet
  2012-12-15  9:58 ` [PATCH V3 14/15] [media] marvell-ccic: use unsigned int type replace int type Albert Wang
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:58 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang, Libin Yang

This patch adds the dma burst size config support for marvell-ccic.
Developer can set the dma burst size in specified board driver.

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 .../media/platform/marvell-ccic/mcam-core-soc.c    |    2 +-
 drivers/media/platform/marvell-ccic/mcam-core.h    |    7 ++++---
 drivers/media/platform/marvell-ccic/mmp-driver.c   |   11 +++++++++++
 include/media/mmp-camera.h                         |    1 +
 4 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core-soc.c b/drivers/media/platform/marvell-ccic/mcam-core-soc.c
index 9016dc6..5b1dcfe 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core-soc.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core-soc.c
@@ -83,7 +83,7 @@ static int mcam_camera_add_device(struct soc_camera_device *icd)
 	mcam_ctlr_stop(mcam);
 	mcam_set_config_needed(mcam, 1);
 	mcam_reg_write(mcam, REG_CTRL1,
-				   C1_RESERVED | C1_DMAPOSTED);
+			mcam->burst |  C1_RESERVED | C1_DMAPOSTED);
 	mcam_reg_write(mcam, REG_CLKCTRL,
 		(mcam->mclk_src << 29) | mcam->mclk_div);
 	cam_dbg(mcam, "camera: set sensor mclk = %dMHz\n", mcam->mclk_min);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 57442e0..e1025f2 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -126,6 +126,7 @@ struct mcam_camera {
 	short int use_smbus;	/* SMBUS or straight I2c? */
 	enum mcam_buffer_mode buffer_mode;
 
+	int burst;
 	int mclk_min;
 	int mclk_src;
 	int mclk_div;
@@ -411,9 +412,9 @@ int mcam_soc_camera_host_register(struct mcam_camera *mcam);
 #define   C1_DESC_3WORD   0x00000200	/* Three-word descriptors used */
 #define	  C1_444ALPHA	  0x00f00000	/* Alpha field in RGB444 */
 #define	  C1_ALPHA_SHFT	  20
-#define	  C1_DMAB32	  0x00000000	/* 32-byte DMA burst */
-#define	  C1_DMAB16	  0x02000000	/* 16-byte DMA burst */
-#define	  C1_DMAB64	  0x04000000	/* 64-byte DMA burst */
+#define	  C1_DMAB64	  0x00000000	/* 64-byte DMA burst */
+#define	  C1_DMAB128	  0x02000000	/* 128-byte DMA burst */
+#define	  C1_DMAB256	  0x04000000	/* 256-byte DMA burst */
 #define	  C1_DMAB_MASK	  0x06000000
 #define	  C1_TWOBUFS	  0x08000000	/* Use only two DMA buffers */
 #define	  C1_PWRDWN	  0x10000000	/* Power down */
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index cd850f4..3469f02 100755
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -400,6 +400,17 @@ static int mmpcam_probe(struct platform_device *pdev)
 	mcam->dphy = pdata->dphy;
 	mcam->mipi_enabled = 0;
 	mcam->lane = pdata->lane;
+	switch (pdata->dma_burst) {
+	case 128:
+		mcam->burst = C1_DMAB128;
+		break;
+	case 256:
+		mcam->burst = C1_DMAB256;
+		break;
+	default:
+		mcam->burst = C1_DMAB64;
+		break;
+	}
 	INIT_LIST_HEAD(&mcam->buffers);
 
 	/*
diff --git a/include/media/mmp-camera.h b/include/media/mmp-camera.h
index ec4f21f..4da0df7 100755
--- a/include/media/mmp-camera.h
+++ b/include/media/mmp-camera.h
@@ -13,6 +13,7 @@ struct mmp_camera_platform_data {
 	int mclk_src;
 	int mclk_div;
 	int chip_id;
+	int dma_burst;
 	/*
 	 * MIPI support
 	 */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 14/15] [media] marvell-ccic: use unsigned int type replace int type
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (12 preceding siblings ...)
  2012-12-15  9:58 ` [PATCH V3 13/15] [media] marvell-ccic: add dma burst mode support in marvell-ccic driver Albert Wang
@ 2012-12-15  9:58 ` Albert Wang
  2012-12-16 16:50   ` Jonathan Corbet
  2012-12-15  9:58 ` [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode Albert Wang
  2012-12-16 16:57 ` [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Jonathan Corbet
  15 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:58 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang, Libin Yang

This patch use unsigned int type replace int type in marvell-ccic.

These variables: frame number, buf number, irq... should be unsigned.

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 .../media/platform/marvell-ccic/mcam-core-soc.h    |    2 +-
 .../platform/marvell-ccic/mcam-core-standard.h     |   10 ++++-----
 drivers/media/platform/marvell-ccic/mcam-core.c    |   22 ++++++++++----------
 drivers/media/platform/marvell-ccic/mcam-core.h    |    2 +-
 drivers/media/platform/marvell-ccic/mmp-driver.c   |    2 +-
 5 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core-soc.h b/drivers/media/platform/marvell-ccic/mcam-core-soc.h
index fbdaa5d..cb1504a 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core-soc.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core-soc.h
@@ -11,7 +11,7 @@ extern const struct vb2_ops mcam_vb2_ops;
 
 void mcam_ctlr_power_up(struct mcam_camera *cam);
 void mcam_ctlr_power_down(struct mcam_camera *cam);
-void mcam_dma_contig_done(struct mcam_camera *cam, int frame);
+void mcam_dma_contig_done(struct mcam_camera *cam, unsigned int frame);
 void mcam_ctlr_stop(struct mcam_camera *cam);
 int mcam_config_mipi(struct mcam_camera *mcam, int enable);
 void mcam_ctlr_image(struct mcam_camera *cam);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core-standard.h b/drivers/media/platform/marvell-ccic/mcam-core-standard.h
index 154ea4f..363ae43 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core-standard.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core-standard.h
@@ -4,8 +4,8 @@
  * Copyright 2011 Jonathan Corbet corbet@lwn.net
  */
 extern bool mcam_alloc_bufs_at_read;
-extern int mcam_n_dma_bufs;
-extern int mcam_buffer_mode;
+extern unsigned int mcam_n_dma_bufs;
+extern unsigned int mcam_buffer_mode;
 extern const struct vb2_ops mcam_vb2_sg_ops;
 extern const struct vb2_ops mcam_vb2_ops;
 
@@ -15,12 +15,12 @@ void mcam_ctlr_power_up(struct mcam_camera *cam);
 void mcam_ctlr_power_down(struct mcam_camera *cam);
 void mcam_free_dma_bufs(struct mcam_camera *cam);
 void mcam_ctlr_dma_sg(struct mcam_camera *cam);
-void mcam_dma_sg_done(struct mcam_camera *cam, int frame);
+void mcam_dma_sg_done(struct mcam_camera *cam, unsigned int frame);
 int mcam_check_dma_buffers(struct mcam_camera *cam);
 void mcam_set_config_needed(struct mcam_camera *cam, int needed);
 int __mcam_cam_reset(struct mcam_camera *cam);
 int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime);
 void mcam_ctlr_dma_contig(struct mcam_camera *cam);
-void mcam_dma_contig_done(struct mcam_camera *cam, int frame);
+void mcam_dma_contig_done(struct mcam_camera *cam, unsigned int frame);
 void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam);
-void mcam_vmalloc_done(struct mcam_camera *cam, int frame);
+void mcam_vmalloc_done(struct mcam_camera *cam, unsigned int frame);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 97b40db..2a4d481 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -106,7 +106,7 @@ static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
 /*
  * Hand a completed buffer back to user space.
  */
-static void mcam_buffer_done(struct mcam_camera *cam, int frame,
+static void mcam_buffer_done(struct mcam_camera *cam, unsigned int frame,
 		struct vb2_buffer *vbuf)
 {
 	vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage;
@@ -120,7 +120,7 @@ static void mcam_buffer_done(struct mcam_camera *cam, int frame,
  */
 static void mcam_reset_buffers(struct mcam_camera *cam)
 {
-	int i;
+	unsigned int i;
 
 	cam->next_buf = -1;
 	for (i = 0; i < cam->nbufs; i++) {
@@ -215,7 +215,7 @@ int mcam_config_mipi(struct mcam_camera *mcam, int enable)
  */
 int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
 {
-	int i;
+	unsigned int i;
 
 	mcam_set_config_needed(cam, 1);
 	if (loadtime)
@@ -256,7 +256,7 @@ int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
 
 void mcam_free_dma_bufs(struct mcam_camera *cam)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < cam->nbufs; i++) {
 		dma_free_coherent(cam->dev, cam->dma_buf_size,
@@ -295,7 +295,7 @@ void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam)
 static void mcam_frame_tasklet(unsigned long data)
 {
 	struct mcam_camera *cam = (struct mcam_camera *) data;
-	int i;
+	unsigned int i;
 	unsigned long flags;
 	struct mcam_vb_buffer *buf;
 
@@ -343,7 +343,7 @@ int mcam_check_dma_buffers(struct mcam_camera *cam)
 	return 0;
 }
 
-void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
+void mcam_vmalloc_done(struct mcam_camera *cam, unsigned int frame)
 {
 	tasklet_schedule(&cam->s_tasklet);
 }
@@ -395,7 +395,7 @@ static bool mcam_fmt_is_planar(__u32 pfmt)
  * space.  In this way, we always have a buffer to DMA to and don't
  * have to try to play games stopping and restarting the controller.
  */
-static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
+static void mcam_set_contig_buffer(struct mcam_camera *cam, unsigned int frame)
 {
 	struct mcam_vb_buffer *buf;
 	struct v4l2_pix_format *fmt = &cam->pix_format;
@@ -441,7 +441,7 @@ void mcam_ctlr_dma_contig(struct mcam_camera *cam)
 /*
  * Frame completion handling.
  */
-void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
+void mcam_dma_contig_done(struct mcam_camera *cam, unsigned int frame)
 {
 	struct mcam_vb_buffer *buf = cam->vb_bufs[frame];
 
@@ -517,7 +517,7 @@ void mcam_ctlr_dma_sg(struct mcam_camera *cam)
  * safely change the DMA descriptor array here and restart things
  * (assuming there's another buffer waiting to go).
  */
-void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
+void mcam_dma_sg_done(struct mcam_camera *cam, unsigned int frame)
 {
 	struct mcam_vb_buffer *buf = cam->vb_bufs[0];
 
@@ -865,7 +865,7 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
 		void *alloc_ctxs[])
 {
 	struct mcam_camera *cam = get_mcam(vq);
-	int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
+	unsigned int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
 
 	sizes[0] = cam->pix_format.sizeimage;
 	*num_planes = 1; /* Someday we have to support planar formats... */
@@ -1103,7 +1103,7 @@ const struct vb2_ops mcam_vb2_sg_ops = {
 /*
  * Interrupt handler stuff
  */
-static void mcam_frame_complete(struct mcam_camera *cam, int frame)
+static void mcam_frame_complete(struct mcam_camera *cam, unsigned int frame)
 {
 	/*
 	 * Basic frame housekeeping.
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index e1025f2..765d47c 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -192,7 +192,7 @@ struct mcam_camera {
 
 	/* Mode-specific ops, set at open time */
 	void (*dma_setup)(struct mcam_camera *cam);
-	void (*frame_complete)(struct mcam_camera *cam, int frame);
+	void (*frame_complete)(struct mcam_camera *cam, unsigned int frame);
 
 	/* Current operating parameters */
 	u32 sensor_type;		/* Currently ov7670 only */
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 3469f02..8a87e3e 100755
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -46,7 +46,7 @@ struct mmp_camera {
 	struct list_head devlist;
 	/* will change here */
 	struct clk *clk[3];	/* CCIC_GATE, CCIC_RST, CCIC_DBG clocks */
-	int irq;
+	unsigned int irq;
 };
 
 static inline struct mmp_camera *mcam_to_cam(struct mcam_camera *mcam)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (13 preceding siblings ...)
  2012-12-15  9:58 ` [PATCH V3 14/15] [media] marvell-ccic: use unsigned int type replace int type Albert Wang
@ 2012-12-15  9:58 ` Albert Wang
  2012-12-16 16:56   ` Jonathan Corbet
  2012-12-16 16:57 ` [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Jonathan Corbet
  15 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-15  9:58 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang, Libin Yang

This patch adds support of 3 frame buffers in DMA-contiguous mode.

In current DMA_CONTIG mode, only 2 frame buffers can be supported.
Actually, Marvell CCIC can support at most 3 frame buffers.

Currently 2 frame buffers mode will be used by default.
To use 3 frame buffers mode, can do:
  define MAX_FRAME_BUFS 3
in mcam-core.h

Signed-off-by: Albert Wang <twang13@marvell.com>
Signed-off-by: Libin Yang <lbyang@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.c |   59 +++++++++++++++++------
 drivers/media/platform/marvell-ccic/mcam-core.h |   11 +++++
 2 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 2a4d481..d7f124d 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -400,13 +400,32 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, unsigned int frame)
 	struct mcam_vb_buffer *buf;
 	struct v4l2_pix_format *fmt = &cam->pix_format;
 
-	/*
-	 * If there are no available buffers, go into single mode
-	 */
 	if (list_empty(&cam->buffers)) {
-		buf = cam->vb_bufs[frame ^ 0x1];
-		set_bit(CF_SINGLE_BUFFER, &cam->flags);
-		cam->frame_state.singles++;
+		/*
+		 * If there are no available buffers
+		 * go into single buffer mode
+		 *
+		 * If CCIC use Two Buffers mode
+		 * will use another remaining frame buffer
+		 * frame 0 -> buf 1
+		 * frame 1 -> buf 0
+		 *
+		 * If CCIC use Three Buffers mode
+		 * will use the 2rd remaining frame buffer
+		 * frame 0 -> buf 2
+		 * frame 1 -> buf 0
+		 * frame 2 -> buf 1
+		 */
+		buf = cam->vb_bufs[(frame + (MAX_FRAME_BUFS - 1))
+						% MAX_FRAME_BUFS];
+		if (cam->frame_state.usebufs == 0)
+			cam->frame_state.usebufs++;
+		else {
+			set_bit(CF_SINGLE_BUFFER, &cam->flags);
+			cam->frame_state.singles++;
+			if (cam->frame_state.usebufs < 2)
+				cam->frame_state.usebufs++;
+		}
 	} else {
 		/*
 		 * OK, we have a buffer we can use.
@@ -415,15 +434,15 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, unsigned int frame)
 					queue);
 		list_del_init(&buf->queue);
 		clear_bit(CF_SINGLE_BUFFER, &cam->flags);
+		if (cam->frame_state.usebufs != (3 - MAX_FRAME_BUFS))
+			cam->frame_state.usebufs--;
 	}
 
 	cam->vb_bufs[frame] = buf;
-	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y);
+	mcam_reg_write(cam, REG_Y0BAR + (frame << 2), buf->yuv_p.y);
 	if (mcam_fmt_is_planar(fmt->pixelformat)) {
-		mcam_reg_write(cam, frame == 0 ?
-					REG_U0BAR : REG_U1BAR, buf->yuv_p.u);
-		mcam_reg_write(cam, frame == 0 ?
-					REG_V0BAR : REG_V1BAR, buf->yuv_p.v);
+		mcam_reg_write(cam, REG_U0BAR + (frame << 2), buf->yuv_p.u);
+		mcam_reg_write(cam, REG_V0BAR + (frame << 2), buf->yuv_p.v);
 	}
 }
 
@@ -432,10 +451,14 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, unsigned int frame)
  */
 void mcam_ctlr_dma_contig(struct mcam_camera *cam)
 {
-	mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
-	cam->nbufs = 2;
-	mcam_set_contig_buffer(cam, 0);
-	mcam_set_contig_buffer(cam, 1);
+	unsigned int frame;
+
+	cam->nbufs = MAX_FRAME_BUFS;
+	for (frame = 0; frame < cam->nbufs; frame++)
+		mcam_set_contig_buffer(cam, frame);
+
+	if (cam->nbufs == 2)
+		mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
 }
 
 /*
@@ -978,6 +1001,12 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
 	for (frame = 0; frame < cam->nbufs; frame++)
 		clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
 
+	/*
+	 *  If CCIC use Two Buffers mode, init usebufs == 1
+	 *  If CCIC use Three Buffers mode, init usebufs == 0
+	 */
+	cam->frame_state.usebufs = 3 - MAX_FRAME_BUFS;
+
 	return mcam_read_setup(cam);
 }
 
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 765d47c..9bf31c8 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -62,6 +62,13 @@ enum mcam_state {
 #define MAX_DMA_BUFS 3
 
 /*
+ * CCIC can support at most 3 frame buffers in DMA_CONTIG buffer mode
+ * 2 - Use Two Buffers mode
+ * 3 - Use Three Buffers mode
+ */
+#define MAX_FRAME_BUFS 2 /* Current marvell-ccic used Two Buffers mode */
+
+/*
  * Different platforms work best with different buffer modes, so we
  * let the platform pick.
  */
@@ -99,6 +106,10 @@ struct mcam_frame_state {
 	unsigned int frames;
 	unsigned int singles;
 	unsigned int delivered;
+	/*
+	 * Only usebufs == 2 can enter single buffer mode
+	 */
+	unsigned int usebufs;
 };
 
 /*
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable
  2012-12-15  9:57 ` [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable Albert Wang
@ 2012-12-16 15:36   ` Jonathan Corbet
  2012-12-27 20:07     ` Mauro Carvalho Chehab
  2013-01-01 14:56   ` Guennadi Liakhovetski
  1 sibling, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 15:36 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:50 +0800
Albert Wang <twang13@marvell.com> wrote:

> This patch replaces the global frame stats variables by using
> internal variables in mcam_camera structure.

This one seems fine.  Someday it might be nice to have proper stats
rather than my debugging hack, complete with a nice sysfs interface and
all that.  

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver Albert Wang
@ 2012-12-16 15:54   ` Jonathan Corbet
  2012-12-16 21:45     ` Albert Wang
  2013-01-01 15:28   ` Guennadi Liakhovetski
  1 sibling, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 15:54 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:51 +0800
Albert Wang <twang13@marvell.com> wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the MIPI support for marvell-ccic.
> Board driver should determine whether using MIPI or not.

There are limits to how deeply I can review this, since I know little about
the MIPI mode and don't have any hardware that uses it.  So I'm assuming
that it all works :)  My comments are on a different level.

> +static int mcam_config_mipi(struct mcam_camera *mcam, int enable)
> +{
> +	if (mcam->bus_type == V4L2_MBUS_CSI2 && enable) {
> +		/* Using MIPI mode and enable MIPI */
> +		cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x, DPHY6=0x%x\n",
> +			mcam->dphy[0], mcam->dphy[1], mcam->dphy[2]);
> +		mcam_reg_write(mcam, REG_CSI2_DPHY3, mcam->dphy[0]);
> +		mcam_reg_write(mcam, REG_CSI2_DPHY6, mcam->dphy[2]);
> +		mcam_reg_write(mcam, REG_CSI2_DPHY5, mcam->dphy[1]);

Is there a reason you're writing them in something other than direct
increasing order?  If so, a comment saying why might help somebody in ghe future.

> +		if (mcam->mipi_enabled == 0) {
> +			/*
> +			 * 0x41 actives 1 lane
> +			 * 0x43 actives 2 lanes
> +			 * 0x47 actives 4 lanes
> +			 * There is no 3 lanes case
> +			 */
> +			switch (mcam->lane) {
> +			case 1:
> +				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x41);
> +				break;
> +			case 2:
> +				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x43);
> +				break;
> +			case 4:
> +				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x47);
> +				break;

Can we have defined symbols rather than magic constants here?

> @@ -656,6 +701,15 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
>  	 */
>  	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
>  			C0_SIFM_MASK);
> +
> +	/*
> +	 * This field controls the generation of EOF(DVP only)
> +	 */
> +	if (cam->bus_type != V4L2_MBUS_CSI2) {
> +		mcam_reg_set_bit(cam, REG_CTRL0,
> +				C0_EOF_VSYNC | C0_VEDGE_CTRL);
> +		mcam_reg_write(cam, REG_CTRL3, 0x4);

Again, how about a symbol, or at least an explanation of what 0x4 means?

> +	}
>  }
>  
[...]
> @@ -1551,6 +1615,11 @@ static int mcam_v4l_open(struct file *filp)
>  		mcam_set_config_needed(cam, 1);
>  	}
>  	(cam->users)++;
> +	cam->pll1 = devm_clk_get(cam->dev, "pll1");
> +	if (IS_ERR(cam->pll1)) {
> +		cam_err(cam, "Could not get pll1 clock\n");
> +		ret = PTR_ERR(cam->pll1);
> +	}

This looks like it gets the clock in all cases?  Is that right?

>  #define REG_IMGPITCH	0x24	/* Image pitch register */
> @@ -292,7 +311,9 @@ int mccic_resume(struct mcam_camera *cam);
>  #define	  C0_DOWNSCALE	  0x08000000	/* Enable downscaler */
>  #define	  C0_SIFM_MASK	  0xc0000000	/* SIF mode bits */
>  #define	  C0_SIF_HVSYNC	  0x00000000	/* Use H/VSYNC */
> -#define	  CO_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
> +#define	  C0_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
> +#define	  C0_EOF_VSYNC	  0x00400000	/* Generate EOF by VSYNC */
> +#define	  C0_VEDGE_CTRL   0x00800000	/* Detect falling edge of VSYNC */

Being the retentive sort of guy I am, I try to keep definitions like these
in numerical order.  Any chance you could humor me and maintain that?

>  /* Bits below C1_444ALPHA are not present in Cafe */
>  #define REG_CTRL1	0x40	/* Control 1 */
> @@ -308,6 +329,7 @@ int mccic_resume(struct mcam_camera *cam);
>  #define	  C1_TWOBUFS	  0x08000000	/* Use only two DMA buffers */
>  #define	  C1_PWRDWN	  0x10000000	/* Power down */
>  
> +#define REG_CTRL3	0x1ec	/* CCIC parallel mode */
>  #define REG_CLKCTRL	0x88	/* Clock control */
>  #define	  CLK_DIV_MASK	  0x0000ffff	/* Upper bits RW "reserved" */

Here, too, I'd rather keep them in order if possible.

> +/*
> + * calc the dphy register values
> + * There are three dphy registers being used.
> + * dphy[0] can be set with a default value
> + * or be calculated dynamically
> + */
> +void mmpcam_calc_dphy(struct mcam_camera *mcam)
> +{
> +	struct mmp_camera *cam = mcam_to_cam(mcam);
> +	struct mmp_camera_platform_data *pdata = cam->pdev->dev.platform_data;
> +	struct device *dev = &cam->pdev->dev;
> +	unsigned long tx_clk_esc;
> +
> +	/*
> +	 * If dphy[0] is calculated dynamically,
> +	 * pdata->lane_clk should be already set
> +	 * either in the board driver statically
> +	 * or in the sensor driver dynamically.
> +	 */
> +	switch (pdata->dphy3_algo) {
> +	case 1:
> +		/*
> +		 * dphy3_algo == 1
> +		 * Calculate CSI2_DPHY3 algo for PXA910
> +		 */
> +		pdata->dphy[0] = ((1 + pdata->lane_clk * 80 / 1000) & 0xff) << 8
> +			| (1 + pdata->lane_clk * 35 / 1000);
> +		break;

What are the chances of getting a comment or some other reference so that a
naive reader like me has a chance of understanding what this calculation
does?  Where do all those constants come from?

> +	case 2:
> +		/*
> +		 * dphy3_algo == 2
> +		 * Calculate CSI2_DPHY3 algo for PXA2128
> +		 */
> +		pdata->dphy[0] =
> +			((2 + pdata->lane_clk * 110 / 1000) & 0xff) << 8
> +			| (1 + pdata->lane_clk * 35 / 1000);
> +		break;
> +	default:
> +		/*
> +		 * dphy3_algo == 0
> +		 * Use default CSI2_DPHY3 value for PXA688/PXA988
> +		 */
> +		dev_dbg(dev, "camera: use the default CSI2_DPHY3 value\n");
> +	}
> +
> +	/*
> +	 * pll1 will never be changed, it is a fixed value
> +	 */
> +
> +	if (IS_ERR(mcam->pll1))
> +		return;
> +
> +	tx_clk_esc = clk_get_rate(mcam->pll1) / 1000000 / 12;

Being who I am (see "retentive" above) I'll always parenthesize an
expression like this to make the intended order of operations explicit.

Mostly low-level comments, it's looking pretty good.

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 03/15] [media] marvell-ccic: add clock tree " Albert Wang
@ 2012-12-16 16:03   ` Jonathan Corbet
  2012-12-16 21:51     ` Albert Wang
  2013-01-01 16:05   ` Guennadi Liakhovetski
  1 sibling, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:03 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:52 +0800
Albert Wang <twang13@marvell.com> wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the clock tree support for marvell-ccic.
> 
> Each board may require different clk enabling sequence.
> Developer need add the clk_name in correct sequence in board driver
> to use this feature.
> 
> +static void mcam_clk_set(struct mcam_camera *mcam, int on)
> +{
> +	unsigned int i;
> +
> +	if (on) {
> +		for (i = 0; i < mcam->clk_num; i++) {
> +			if (mcam->clk[i])
> +				clk_enable(mcam->clk[i]);
> +		}
> +	} else {
> +		for (i = mcam->clk_num; i > 0; i--) {
> +			if (mcam->clk[i - 1])
> +				clk_disable(mcam->clk[i - 1]);
> +		}
> +	}
> +}

A couple of minor comments:

 - This function is always called with a constant value for "on".  It would
   be easier to read (and less prone to unfortunate brace errors) if it
   were just two functions: mcam_clk_enable() and mcam_clk_disable().

 - I'd write the second for loop as:

	for (i = mcal->clk_num - 1; i >= 0; i==) {

   just to match the values used in the other direction and avoid the
   subscript arithmetic.

> +static void mcam_init_clk(struct mcam_camera *mcam,
> +			struct mmp_camera_platform_data *pdata, int init)

So why does an "init" function have an "init" parameter?  Again, I think
this would be far better split into two functions.  Among other things,
that would help to reduce the deep nesting below.

> +{
> +	unsigned int i;
> +
> +	if (NR_MCAM_CLK < pdata->clk_num) {
> +		dev_err(mcam->dev, "Too many mcam clocks defined\n");
> +		mcam->clk_num = 0;
> +		return;
> +	}
> +
> +	if (init) {
> +		for (i = 0; i < pdata->clk_num; i++) {
> +			if (pdata->clk_name[i] != NULL) {
> +				mcam->clk[i] = devm_clk_get(mcam->dev,
> +						pdata->clk_name[i]);
> +				if (IS_ERR(mcam->clk[i])) {
> +					dev_err(mcam->dev,
> +						"Could not get clk: %s\n",
> +						pdata->clk_name[i]);
> +					mcam->clk_num = 0;
> +					return;
> +				}
> +			}
> +		}
> +		mcam->clk_num = pdata->clk_num;
> +	} else
> +		mcam->clk_num = 0;
> +}

Again, minor comments, but I do think the code would be improved by
splitting those functions.  Meanwhile:

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 04/15] [media] marvell-ccic: reset ccic phy when stop streaming for stability
  2012-12-15  9:57 ` [PATCH V3 04/15] [media] marvell-ccic: reset ccic phy when stop streaming for stability Albert Wang
@ 2012-12-16 16:04   ` Jonathan Corbet
  2013-01-01 16:13   ` Guennadi Liakhovetski
  1 sibling, 0 replies; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:04 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:53 +0800
Albert Wang <twang13@marvell.com> wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the reset ccic phy operation when stop streaming.
> 
> Without reset ccic phy, the next start streaming may be unstable.
> 
> Also need add CCIC2 definition when PXA688/PXA2128 support dual ccics.
> 
As with all of these, I've not been able to test it, but it looks OK to
me.

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 05/15] [media] marvell-ccic: refine mcam_set_contig_buffer function
  2012-12-15  9:57 ` [PATCH V3 05/15] [media] marvell-ccic: refine mcam_set_contig_buffer function Albert Wang
@ 2012-12-16 16:06   ` Jonathan Corbet
  2012-12-16 21:54     ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:06 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:54 +0800
Albert Wang <twang13@marvell.com> wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch refines mcam_set_contig_buffer() in mcam core

It might be nice if the changelog said *why* this was being done -
don't worry about insulting my ugly code :)  But no biggie...

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver Albert Wang
@ 2012-12-16 16:16   ` Jonathan Corbet
  2012-12-16 21:58     ` Albert Wang
  2013-01-01 16:56   ` Guennadi Liakhovetski
  1 sibling, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:16 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:55 +0800
Albert Wang <twang13@marvell.com> wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the new formats support for marvell-ccic.

Once again, just one second-order comment:

> +static bool mcam_fmt_is_planar(__u32 pfmt)
> +{
> +	switch (pfmt) {
> +	case V4L2_PIX_FMT_YUV422P:
> +	case V4L2_PIX_FMT_YUV420:
> +	case V4L2_PIX_FMT_YVU420:
> +		return true;
> +	}
> +	return false;
> +}

This seems like the kind of thing that would be useful in a number of
places; I'd be tempted to push it up a level and make it available to all
V4L2 drivers.  Of course, that means making it work for *all* formats,
which would be a pain.  

But, then, I can see some potential future pain if somebody adds a new
format and forgets to tweak this function here.  Rather than adding a new
switch, could you put a "planar" flag into struct mcam_format_struct
instead?  That would help to keep all this information together.

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check " Albert Wang
@ 2012-12-16 16:19   ` Jonathan Corbet
  2012-12-16 22:00     ` Albert Wang
  2013-01-02  7:48   ` Guennadi Liakhovetski
  1 sibling, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:19 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:56 +0800
Albert Wang <twang13@marvell.com> wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the SOFx/EOFx pair check for marvell-ccic.
> 
> When switching format, the last EOF may not arrive when stop streamning.
> And the EOF will be detected in the next start streaming.
> 
> Must ensure clear the obsolete frame flags before every really start streaming.

"obsolete" doesn't quite read right; it suggests that the flags only
apply to older hardware.  I'd suggest "left over" or some such (in the
code comment too).  Otherwise seems fine.

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 08/15] [media] marvell-ccic: switch to resource managed allocation and request
  2012-12-15  9:57 ` [PATCH V3 08/15] [media] marvell-ccic: switch to resource managed allocation and request Albert Wang
@ 2012-12-16 16:20   ` Jonathan Corbet
  2013-01-02  8:00   ` Guennadi Liakhovetski
  1 sibling, 0 replies; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:20 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:57 +0800
Albert Wang <twang13@marvell.com> wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch switchs to resource managed allocation and request in mmp-driver.
> It can remove free resource operations.

But that takes away half the challenge of getting all this stuff
right! :)

Acked-by: Jonathan Corbet <corbet@lwn.net>


jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-ccic driver Albert Wang
@ 2012-12-16 16:24   ` Jonathan Corbet
  2012-12-16 22:04     ` Albert Wang
  2013-01-02  8:16     ` Guennadi Liakhovetski
  0 siblings, 2 replies; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:24 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:58 +0800
Albert Wang <twang13@marvell.com> wrote:

> This patch adds get_mcam() inline function which is prepared for
> adding soc_camera support in marvell-ccic driver

Time for a bikeshed moment: "get" generally is understood to mean
incrementing a reference count in kernel code.  Can it have a name like
vbq_to_mcam() instead?

Also:

> @@ -1073,14 +1073,17 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
>  static void mcam_vb_buf_queue(struct vb2_buffer *vb)
>  {
>  	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
> -	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
> +	struct mcam_camera *cam = get_mcam(vb->vb2_queue);
>  	struct v4l2_pix_format *fmt = &cam->pix_format;
>  	unsigned long flags;
>  	int start;
>  	dma_addr_t dma_handle;
> +	unsigned long size;
>  	u32 pixel_count = fmt->width * fmt->height;
>  
>  	spin_lock_irqsave(&cam->dev_lock, flags);
> +	size = vb2_plane_size(vb, 0);
> +	vb2_set_plane_payload(vb, 0, size);
>  	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
>  	BUG_ON(!dma_handle);
>  	start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);

There is an unrelated change here that belongs in a separate patch.

> @@ -1138,9 +1141,12 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
>   */
>  static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
>  {
> -	struct mcam_camera *cam = vb2_get_drv_priv(vq);
> +	struct mcam_camera *cam = get_mcam(vq);
>  	unsigned int frame;
>  
> +	if (count < 2)
> +		return -EINVAL;
> +

Here too - unrelated change.

>  	if (cam->state != S_IDLE) {
>  		INIT_LIST_HEAD(&cam->buffers);
>  		return -EINVAL;
> @@ -1170,7 +1176,7 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
>  
>  static int mcam_vb_stop_streaming(struct vb2_queue *vq)
>  {
> -	struct mcam_camera *cam = vb2_get_drv_priv(vq);
> +	struct mcam_camera *cam = get_mcam(vq);
>  	unsigned long flags;
>  
>  	if (cam->state == S_BUFWAIT) {
> @@ -1181,6 +1187,7 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
>  	if (cam->state != S_STREAMING)
>  		return -EINVAL;
>  	mcam_ctlr_stop_dma(cam);
> +	cam->state = S_IDLE;

...and also here ...

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2012-12-15  9:57 ` [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support Albert Wang
@ 2012-12-16 16:37   ` Jonathan Corbet
  2012-12-16 22:12     ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:37 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:57:59 +0800
Albert Wang <twang13@marvell.com> wrote:

> This patch splits mcam-core into 2 parts to prepare for soc_camera support.
> 
> The first part remains in mcam-core.c. This part includes the HW operations
> and vb2 callback functions.
> 
> The second part is moved to mcam-core-standard.c. This part is relevant with
> the implementation of using V4L2.

OK, I'll confess I'm still not 100% sold on this part.  Can I repeat
the questions I raised before?

 - Is the soc_camera mode necessary?  Is there something you're trying
   to do that can't be done without it?  Or, at least, does it add
   sufficient benefit to be worth this work?  It would be nice if the
   reasoning behind this change were put into the changelog.

 - If the soc_camera change is deemed to be worthwhile, is there
   anything preventing you from doing it 100% so it's the only mode
   used?

The split as you've done it here is an improvement over what came
before, but it still results in a lot of duplicated code; it also adds
a *lot* of symbols to the global namespace.  If this is really the only
way then we'll find a way to make it work, but I'd like to be sure that
we can't do something better.

Thanks,

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 12/15] [media] marvell-ccic: add soc_camera support in mmp driver
  2012-12-15  9:58 ` [PATCH V3 12/15] [media] marvell-ccic: add soc_camera support in mmp driver Albert Wang
@ 2012-12-16 16:46   ` Jonathan Corbet
  2012-12-16 22:19     ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:46 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:58:01 +0800
Albert Wang <twang13@marvell.com> wrote:

> This patch adds the soc_camera support in the platform driver: mmp-driver.c.
> Specified board driver also should be modified to support soc_camera by passing
> some platform datas to platform driver.
> 
> Currently the soc_camera mode in mmp driver only supports B_DMA_contig mode.

You do intend to add the other modes (or SG, at least) in the future?

> --- a/drivers/media/platform/marvell-ccic/Kconfig
> +++ b/drivers/media/platform/marvell-ccic/Kconfig
> @@ -1,23 +1,45 @@
> +config VIDEO_MARVELL_CCIC
> +       tristate
> +config VIDEO_MRVL_SOC_CAMERA
> +       bool

If Linus sees this you'll get an unpleasant reminder that vowels are not
actually in short supply; I'd suggest spelling out "MARVELL".

> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
> index 40c243e..cd850f4 100755
> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
> @@ -28,6 +28,10 @@
>  #include <linux/list.h>
>  #include <linux/pm.h>
>  #include <linux/clk.h>
> +#include <linux/regulator/consumer.h>
> +#include <media/videobuf2-dma-contig.h>
> +#include <media/soc_camera.h>
> +#include <media/soc_mediabus.h>
>  
>  #include "mcam-core.h"
>  
> @@ -40,6 +44,8 @@ struct mmp_camera {
>  	struct platform_device *pdev;
>  	struct mcam_camera mcam;
>  	struct list_head devlist;
> +	/* will change here */
> +	struct clk *clk[3];	/* CCIC_GATE, CCIC_RST, CCIC_DBG clocks */

What does that comment mean?

>  	int irq;
>  };
>  
> @@ -144,15 +150,17 @@ static void mmpcam_power_up(struct mcam_camera *mcam)
>   * Provide power to the sensor.
>   */
>  	mcam_reg_write(mcam, REG_CLKCTRL, 0x60000002);
> -	pdata = cam->pdev->dev.platform_data;
> -	gpio_set_value(pdata->sensor_power_gpio, 1);
> -	mdelay(5);
> +	if (mcam->chip_id == V4L2_IDENT_ARMADA610) {

I'm seeing a lot of these tests being added to the code.  I can imagine
more in the future as new chipsets are supported in the driver.  Maybe it's
time to add a structure to hide chipset-specific low-level operations?  It
would make the code a lot cleaner.

Actually, things like mmpcam_power_up() were meant to be exactly that.  Can
we just define a different version of this function for different chipsets?

> +		pdata = cam->pdev->dev.platform_data;
> +		gpio_set_value(pdata->sensor_power_gpio, 1);
> +		mdelay(5);
> +		/* reset is active low */
> +		gpio_set_value(pdata->sensor_reset_gpio, 0);
> +		mdelay(5);
> +		gpio_set_value(pdata->sensor_reset_gpio, 1);
> +		mdelay(5);
> +	}
>  	mcam_reg_clear_bit(mcam, REG_CTRL1, 0x10000000);
> -	gpio_set_value(pdata->sensor_reset_gpio, 0); /* reset is active low */
> -	mdelay(5);
> -	gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
> -	mdelay(5);
> -
>  	mcam_clk_set(mcam, 1);
>  }
>  
> @@ -165,13 +173,14 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
>   */
>  	iowrite32(0, cam->power_regs + REG_CCIC_DCGCR);
>  	iowrite32(0, cam->power_regs + REG_CCIC_CRCR);
> -/*
> - * Shut down the sensor.
> - */
> -	pdata = cam->pdev->dev.platform_data;
> -	gpio_set_value(pdata->sensor_power_gpio, 0);
> -	gpio_set_value(pdata->sensor_reset_gpio, 0);
> -
> +	if (mcam->chip_id == V4L2_IDENT_ARMADA610) {

Same comment applies here.

> +		/*
> +		 * Shut down the sensor.
> +		 */
> +		pdata = cam->pdev->dev.platform_data;
> +		gpio_set_value(pdata->sensor_power_gpio, 0);
> +		gpio_set_value(pdata->sensor_reset_gpio, 0);
> +	}
>  	mcam_clk_set(mcam, 0);

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 13/15] [media] marvell-ccic: add dma burst mode support in marvell-ccic driver
  2012-12-15  9:58 ` [PATCH V3 13/15] [media] marvell-ccic: add dma burst mode support in marvell-ccic driver Albert Wang
@ 2012-12-16 16:49   ` Jonathan Corbet
  2012-12-16 22:22     ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:49 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:58:02 +0800
Albert Wang <twang13@marvell.com> wrote:

> This patch adds the dma burst size config support for marvell-ccic.
> Developer can set the dma burst size in specified board driver.

> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
> index 57442e0..e1025f2 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
> @@ -126,6 +126,7 @@ struct mcam_camera {
>  	short int use_smbus;	/* SMBUS or straight I2c? */
>  	enum mcam_buffer_mode buffer_mode;
>  
> +	int burst;

That's a register flag value, seems it should be unsigned (says the guy who
is admittedly sloppy about such things).

>  	int mclk_min;
>  	int mclk_src;
>  	int mclk_div;
> @@ -411,9 +412,9 @@ int mcam_soc_camera_host_register(struct mcam_camera *mcam);
>  #define   C1_DESC_3WORD   0x00000200	/* Three-word descriptors used */
>  #define	  C1_444ALPHA	  0x00f00000	/* Alpha field in RGB444 */
>  #define	  C1_ALPHA_SHFT	  20
> -#define	  C1_DMAB32	  0x00000000	/* 32-byte DMA burst */
> -#define	  C1_DMAB16	  0x02000000	/* 16-byte DMA burst */
> -#define	  C1_DMAB64	  0x04000000	/* 64-byte DMA burst */
> +#define	  C1_DMAB64	  0x00000000	/* 64-byte DMA burst */
> +#define	  C1_DMAB128	  0x02000000	/* 128-byte DMA burst */
> +#define	  C1_DMAB256	  0x04000000	/* 256-byte DMA burst */

Interesting, did I just get those wrong somehow?  Or might they have been
different in the Cafe days?  

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 14/15] [media] marvell-ccic: use unsigned int type replace int type
  2012-12-15  9:58 ` [PATCH V3 14/15] [media] marvell-ccic: use unsigned int type replace int type Albert Wang
@ 2012-12-16 16:50   ` Jonathan Corbet
  0 siblings, 0 replies; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:50 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:58:03 +0800
Albert Wang <twang13@marvell.com> wrote:

> This patch use unsigned int type replace int type in marvell-ccic.
> 
> These variables: frame number, buf number, irq... should be unsigned.

Acked-by: Jonathan Corbet <corbet@lwn.net>

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode
  2012-12-15  9:58 ` [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode Albert Wang
@ 2012-12-16 16:56   ` Jonathan Corbet
  2012-12-16 22:34     ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:56 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sat, 15 Dec 2012 17:58:04 +0800
Albert Wang <twang13@marvell.com> wrote:

> This patch adds support of 3 frame buffers in DMA-contiguous mode.
> 
> In current DMA_CONTIG mode, only 2 frame buffers can be supported.
> Actually, Marvell CCIC can support at most 3 frame buffers.
> 
> Currently 2 frame buffers mode will be used by default.
> To use 3 frame buffers mode, can do:
>   define MAX_FRAME_BUFS 3
> in mcam-core.h

Now that the code supports three buffers properly, is there any reason not
to use that mode by default?

Did you test that it works properly if allocation of the third buffer fails?

Otherwise looks OK except for one thing:

> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
> index 765d47c..9bf31c8 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
> @@ -62,6 +62,13 @@ enum mcam_state {
>  #define MAX_DMA_BUFS 3
>  
>  /*
> + * CCIC can support at most 3 frame buffers in DMA_CONTIG buffer mode
> + * 2 - Use Two Buffers mode
> + * 3 - Use Three Buffers mode
> + */
> +#define MAX_FRAME_BUFS 2 /* Current marvell-ccic used Two Buffers mode */
> +
> +/*
>   * Different platforms work best with different buffer modes, so we
>   * let the platform pick.
>   */
> @@ -99,6 +106,10 @@ struct mcam_frame_state {
>  	unsigned int frames;
>  	unsigned int singles;
>  	unsigned int delivered;
> +	/*
> +	 * Only usebufs == 2 can enter single buffer mode
> +	 */
> +	unsigned int usebufs;
>  };

What is the purpose of the "usebufs" field?  The code maintains it in
various places, but I don't see anywhere that actually uses that value for
anything.

Thanks,

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic
  2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
                   ` (14 preceding siblings ...)
  2012-12-15  9:58 ` [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode Albert Wang
@ 2012-12-16 16:57 ` Jonathan Corbet
  2012-12-16 22:34   ` Albert Wang
  15 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 16:57 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media

On Sat, 15 Dec 2012 17:57:49 +0800
Albert Wang <twang13@marvell.com> wrote:

> The following patches series will add soc_camera support on marvell-ccic

Overall, this patch set has come a long way - great work!

As I commented on the specific patches, I still have some concerns
about the soc_camera part of it.  There's various quibbles with the
rest, but mostly not much that's serious.  I think this work is getting
close to being ready.

Thanks,

jon


Jonathan Corbet / LWN.net / corbet@lwn.net

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver
  2012-12-16 15:54   ` Jonathan Corbet
@ 2012-12-16 21:45     ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-16 21:45 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Sunday, 16 December, 2012 23:55
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic
>driver
>
>On Sat, 15 Dec 2012 17:57:51 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the MIPI support for marvell-ccic.
>> Board driver should determine whether using MIPI or not.
>
>There are limits to how deeply I can review this, since I know little about
>the MIPI mode and don't have any hardware that uses it.  So I'm assuming
>that it all works :)  My comments are on a different level.
>
>> +static int mcam_config_mipi(struct mcam_camera *mcam, int enable)
>> +{
>> +	if (mcam->bus_type == V4L2_MBUS_CSI2 && enable) {
>> +		/* Using MIPI mode and enable MIPI */
>> +		cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x,
>DPHY6=0x%x\n",
>> +			mcam->dphy[0], mcam->dphy[1], mcam->dphy[2]);
>> +		mcam_reg_write(mcam, REG_CSI2_DPHY3, mcam->dphy[0]);
>> +		mcam_reg_write(mcam, REG_CSI2_DPHY6, mcam->dphy[2]);
>> +		mcam_reg_write(mcam, REG_CSI2_DPHY5, mcam->dphy[1]);
>
>Is there a reason you're writing them in something other than direct
>increasing order?  If so, a comment saying why might help somebody in ghe future.
>
[Albert Wang] Oh, actually there is no strict sequence to write these MIPI registers.
We can change it with direct increasing order, also we can add some comments for describing the definition. :)

>> +		if (mcam->mipi_enabled == 0) {
>> +			/*
>> +			 * 0x41 actives 1 lane
>> +			 * 0x43 actives 2 lanes
>> +			 * 0x47 actives 4 lanes
>> +			 * There is no 3 lanes case
>> +			 */
>> +			switch (mcam->lane) {
>> +			case 1:
>> +				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x41);
>> +				break;
>> +			case 2:
>> +				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x43);
>> +				break;
>> +			case 4:
>> +				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x47);
>> +				break;
>
>Can we have defined symbols rather than magic constants here?
>
[Albert Wang] Sure, we can do it in the next version.

>> @@ -656,6 +701,15 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
>>  	 */
>>  	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
>>  			C0_SIFM_MASK);
>> +
>> +	/*
>> +	 * This field controls the generation of EOF(DVP only)
>> +	 */
>> +	if (cam->bus_type != V4L2_MBUS_CSI2) {
>> +		mcam_reg_set_bit(cam, REG_CTRL0,
>> +				C0_EOF_VSYNC | C0_VEDGE_CTRL);
>> +		mcam_reg_write(cam, REG_CTRL3, 0x4);
>
>Again, how about a symbol, or at least an explanation of what 0x4 means?
>
[Albert Wang] OK, will do it.

>> +	}
>>  }
>>
>[...]
>> @@ -1551,6 +1615,11 @@ static int mcam_v4l_open(struct file *filp)
>>  		mcam_set_config_needed(cam, 1);
>>  	}
>>  	(cam->users)++;
>> +	cam->pll1 = devm_clk_get(cam->dev, "pll1");
>> +	if (IS_ERR(cam->pll1)) {
>> +		cam_err(cam, "Could not get pll1 clock\n");
>> +		ret = PTR_ERR(cam->pll1);
>> +	}
>
>This looks like it gets the clock in all cases?  Is that right?
>
[Albert Wang] Em, we need it in MIPI mode, it looks we should limit the usage in the MIPI mode.
We will update it.

>>  #define REG_IMGPITCH	0x24	/* Image pitch register */
>> @@ -292,7 +311,9 @@ int mccic_resume(struct mcam_camera *cam);
>>  #define	  C0_DOWNSCALE	  0x08000000	/* Enable downscaler */
>>  #define	  C0_SIFM_MASK	  0xc0000000	/* SIF mode bits */
>>  #define	  C0_SIF_HVSYNC	  0x00000000	/* Use H/VSYNC */
>> -#define	  CO_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
>> +#define	  C0_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
>> +#define	  C0_EOF_VSYNC	  0x00400000	/* Generate EOF by VSYNC */
>> +#define	  C0_VEDGE_CTRL   0x00800000	/* Detect falling edge of
>VSYNC */
>
>Being the retentive sort of guy I am, I try to keep definitions like these
>in numerical order.  Any chance you could humor me and maintain that?
>
[Albert Wang] OK, we will update it and keep it with numerical order.
BTW, there is a typo in CO_SOF_NOSYNC
 
>>  /* Bits below C1_444ALPHA are not present in Cafe */
>>  #define REG_CTRL1	0x40	/* Control 1 */
>> @@ -308,6 +329,7 @@ int mccic_resume(struct mcam_camera *cam);
>>  #define	  C1_TWOBUFS	  0x08000000	/* Use only two DMA buffers */
>>  #define	  C1_PWRDWN	  0x10000000	/* Power down */
>>
>> +#define REG_CTRL3	0x1ec	/* CCIC parallel mode */
>>  #define REG_CLKCTRL	0x88	/* Clock control */
>>  #define	  CLK_DIV_MASK	  0x0000ffff	/* Upper bits RW "reserved" */
>
>Here, too, I'd rather keep them in order if possible.
>
[Albert Wang] OK, we will change it.

>> +/*
>> + * calc the dphy register values
>> + * There are three dphy registers being used.
>> + * dphy[0] can be set with a default value
>> + * or be calculated dynamically
>> + */
>> +void mmpcam_calc_dphy(struct mcam_camera *mcam)
>> +{
>> +	struct mmp_camera *cam = mcam_to_cam(mcam);
>> +	struct mmp_camera_platform_data *pdata = cam->pdev->dev.platform_data;
>> +	struct device *dev = &cam->pdev->dev;
>> +	unsigned long tx_clk_esc;
>> +
>> +	/*
>> +	 * If dphy[0] is calculated dynamically,
>> +	 * pdata->lane_clk should be already set
>> +	 * either in the board driver statically
>> +	 * or in the sensor driver dynamically.
>> +	 */
>> +	switch (pdata->dphy3_algo) {
>> +	case 1:
>> +		/*
>> +		 * dphy3_algo == 1
>> +		 * Calculate CSI2_DPHY3 algo for PXA910
>> +		 */
>> +		pdata->dphy[0] = ((1 + pdata->lane_clk * 80 / 1000) & 0xff) << 8
>> +			| (1 + pdata->lane_clk * 35 / 1000);
>> +		break;
>
>What are the chances of getting a comment or some other reference so that a
>naive reader like me has a chance of understanding what this calculation
>does?  Where do all those constants come from?
>
[Albert Wang] The calculation is based on MIPI CSI2 spec, it looks it's very difficult to describe it in some sentences.
But, anyway we will try to do it.

>> +	case 2:
>> +		/*
>> +		 * dphy3_algo == 2
>> +		 * Calculate CSI2_DPHY3 algo for PXA2128
>> +		 */
>> +		pdata->dphy[0] =
>> +			((2 + pdata->lane_clk * 110 / 1000) & 0xff) << 8
>> +			| (1 + pdata->lane_clk * 35 / 1000);
>> +		break;
>> +	default:
>> +		/*
>> +		 * dphy3_algo == 0
>> +		 * Use default CSI2_DPHY3 value for PXA688/PXA988
>> +		 */
>> +		dev_dbg(dev, "camera: use the default CSI2_DPHY3 value\n");
>> +	}
>> +
>> +	/*
>> +	 * pll1 will never be changed, it is a fixed value
>> +	 */
>> +
>> +	if (IS_ERR(mcam->pll1))
>> +		return;
>> +
>> +	tx_clk_esc = clk_get_rate(mcam->pll1) / 1000000 / 12;
>
>Being who I am (see "retentive" above) I'll always parenthesize an
>expression like this to make the intended order of operations explicit.
>
[Albert Wang] Yes, an expression with parenthesis is more explicit.
>Mostly low-level comments, it's looking pretty good.
>
>jon
 

Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2012-12-16 16:03   ` Jonathan Corbet
@ 2012-12-16 21:51     ` Albert Wang
  2013-01-03 17:37       ` Nicolas THERY
  0 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-16 21:51 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:03
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-
>ccic driver
>
>On Sat, 15 Dec 2012 17:57:52 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the clock tree support for marvell-ccic.
>>
>> Each board may require different clk enabling sequence.
>> Developer need add the clk_name in correct sequence in board driver
>> to use this feature.
>>
>> +static void mcam_clk_set(struct mcam_camera *mcam, int on)
>> +{
>> +	unsigned int i;
>> +
>> +	if (on) {
>> +		for (i = 0; i < mcam->clk_num; i++) {
>> +			if (mcam->clk[i])
>> +				clk_enable(mcam->clk[i]);
>> +		}
>> +	} else {
>> +		for (i = mcam->clk_num; i > 0; i--) {
>> +			if (mcam->clk[i - 1])
>> +				clk_disable(mcam->clk[i - 1]);
>> +		}
>> +	}
>> +}
>
>A couple of minor comments:
>
> - This function is always called with a constant value for "on".  It would
>   be easier to read (and less prone to unfortunate brace errors) if it
>   were just two functions: mcam_clk_enable() and mcam_clk_disable().
>
[Albert Wang] OK, that's fine to split it to 2 functions. :)

> - I'd write the second for loop as:
>
>	for (i = mcal->clk_num - 1; i >= 0; i==) {
>
>   just to match the values used in the other direction and avoid the
>   subscript arithmetic.
>
[Albert Wang] Yes, we can improve it. :)

>> +static void mcam_init_clk(struct mcam_camera *mcam,
>> +			struct mmp_camera_platform_data *pdata, int init)
>
>So why does an "init" function have an "init" parameter?  Again, I think
>this would be far better split into two functions.  Among other things,
>that would help to reduce the deep nesting below.
>
[Albert Wang] Yes, the parameter name is confused.
And we will split this function too. :)

>> +{
>> +	unsigned int i;
>> +
>> +	if (NR_MCAM_CLK < pdata->clk_num) {
>> +		dev_err(mcam->dev, "Too many mcam clocks defined\n");
>> +		mcam->clk_num = 0;
>> +		return;
>> +	}
>> +
>> +	if (init) {
>> +		for (i = 0; i < pdata->clk_num; i++) {
>> +			if (pdata->clk_name[i] != NULL) {
>> +				mcam->clk[i] = devm_clk_get(mcam->dev,
>> +						pdata->clk_name[i]);
>> +				if (IS_ERR(mcam->clk[i])) {
>> +					dev_err(mcam->dev,
>> +						"Could not get clk: %s\n",
>> +						pdata->clk_name[i]);
>> +					mcam->clk_num = 0;
>> +					return;
>> +				}
>> +			}
>> +		}
>> +		mcam->clk_num = pdata->clk_num;
>> +	} else
>> +		mcam->clk_num = 0;
>> +}
>
>Again, minor comments, but I do think the code would be improved by
>splitting those functions.  Meanwhile:
>
>Acked-by: Jonathan Corbet <corbet@lwn.net>
>
>jon

 
Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 05/15] [media] marvell-ccic: refine mcam_set_contig_buffer function
  2012-12-16 16:06   ` Jonathan Corbet
@ 2012-12-16 21:54     ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-16 21:54 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:07
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 05/15] [media] marvell-ccic: refine mcam_set_contig_buffer
>function
>
>On Sat, 15 Dec 2012 17:57:54 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch refines mcam_set_contig_buffer() in mcam core
>
>It might be nice if the changelog said *why* this was being done -
[Albert Wang] We just want to reduce some redundancy code. :)

>don't worry about insulting my ugly code :)  But no biggie...
>
>Acked-by: Jonathan Corbet <corbet@lwn.net>
>
>jon



Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver
  2012-12-16 16:16   ` Jonathan Corbet
@ 2012-12-16 21:58     ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-16 21:58 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan



>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:17
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for
>marvell-ccic driver
>
>On Sat, 15 Dec 2012 17:57:55 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the new formats support for marvell-ccic.
>
>Once again, just one second-order comment:
>
>> +static bool mcam_fmt_is_planar(__u32 pfmt)
>> +{
>> +	switch (pfmt) {
>> +	case V4L2_PIX_FMT_YUV422P:
>> +	case V4L2_PIX_FMT_YUV420:
>> +	case V4L2_PIX_FMT_YVU420:
>> +		return true;
>> +	}
>> +	return false;
>> +}
>
>This seems like the kind of thing that would be useful in a number of
>places; I'd be tempted to push it up a level and make it available to all
>V4L2 drivers.  Of course, that means making it work for *all* formats,
>which would be a pain.
>
>But, then, I can see some potential future pain if somebody adds a new
>format and forgets to tweak this function here.  Rather than adding a new
>switch, could you put a "planar" flag into struct mcam_format_struct
>instead?  That would help to keep all this information together.
>
[Albert Wang] Yes, it looks make sense, we will think about it in next version.

>jon


Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check for marvell-ccic driver
  2012-12-16 16:19   ` Jonathan Corbet
@ 2012-12-16 22:00     ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-16 22:00 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:19
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check for
>marvell-ccic driver
>
>On Sat, 15 Dec 2012 17:57:56 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the SOFx/EOFx pair check for marvell-ccic.
>>
>> When switching format, the last EOF may not arrive when stop streamning.
>> And the EOF will be detected in the next start streaming.
>>
>> Must ensure clear the obsolete frame flags before every really start streaming.
>
>"obsolete" doesn't quite read right; it suggests that the flags only
>apply to older hardware.  I'd suggest "left over" or some such (in the
>code comment too).  Otherwise seems fine.
>
[Albert Wang] OK, we will change the "bad" word. :)

>Acked-by: Jonathan Corbet <corbet@lwn.net>
>
>jon


Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-ccic driver
  2012-12-16 16:24   ` Jonathan Corbet
@ 2012-12-16 22:04     ` Albert Wang
  2013-01-02  8:16     ` Guennadi Liakhovetski
  1 sibling, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-16 22:04 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:25
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-
>ccic driver
>
>On Sat, 15 Dec 2012 17:57:58 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> This patch adds get_mcam() inline function which is prepared for
>> adding soc_camera support in marvell-ccic driver
>
>Time for a bikeshed moment: "get" generally is understood to mean
>incrementing a reference count in kernel code.  Can it have a name like
>vbq_to_mcam() instead?
>
[Albert Wang] Sure. It looks your name is more professional. :)

>Also:
>
>> @@ -1073,14 +1073,17 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
>>  static void mcam_vb_buf_queue(struct vb2_buffer *vb)
>>  {
>>  	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
>> -	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
>> +	struct mcam_camera *cam = get_mcam(vb->vb2_queue);
>>  	struct v4l2_pix_format *fmt = &cam->pix_format;
>>  	unsigned long flags;
>>  	int start;
>>  	dma_addr_t dma_handle;
>> +	unsigned long size;
>>  	u32 pixel_count = fmt->width * fmt->height;
>>
>>  	spin_lock_irqsave(&cam->dev_lock, flags);
>> +	size = vb2_plane_size(vb, 0);
>> +	vb2_set_plane_payload(vb, 0, size);
>>  	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
>>  	BUG_ON(!dma_handle);
>>  	start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
>
>There is an unrelated change here that belongs in a separate patch.
>
[Albert Wang] OK

>> @@ -1138,9 +1141,12 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
>>   */
>>  static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
>>  {
>> -	struct mcam_camera *cam = vb2_get_drv_priv(vq);
>> +	struct mcam_camera *cam = get_mcam(vq);
>>  	unsigned int frame;
>>
>> +	if (count < 2)
>> +		return -EINVAL;
>> +
>
>Here too - unrelated change.
>
[Albert Wang] Em, it looks we should add a new patch to contain these changes. :)

>>  	if (cam->state != S_IDLE) {
>>  		INIT_LIST_HEAD(&cam->buffers);
>>  		return -EINVAL;
>> @@ -1170,7 +1176,7 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq,
>unsigned int count)
>>
>>  static int mcam_vb_stop_streaming(struct vb2_queue *vq)
>>  {
>> -	struct mcam_camera *cam = vb2_get_drv_priv(vq);
>> +	struct mcam_camera *cam = get_mcam(vq);
>>  	unsigned long flags;
>>
>>  	if (cam->state == S_BUFWAIT) {
>> @@ -1181,6 +1187,7 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
>>  	if (cam->state != S_STREAMING)
>>  		return -EINVAL;
>>  	mcam_ctlr_stop_dma(cam);
>> +	cam->state = S_IDLE;
>
>...and also here ...
>
>jon

 

Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2012-12-16 16:37   ` Jonathan Corbet
@ 2012-12-16 22:12     ` Albert Wang
  2012-12-17 15:28       ` Jonathan Corbet
  0 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-16 22:12 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:37
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for
>soc_camera support
>
>On Sat, 15 Dec 2012 17:57:59 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> This patch splits mcam-core into 2 parts to prepare for soc_camera support.
>>
>> The first part remains in mcam-core.c. This part includes the HW operations
>> and vb2 callback functions.
>>
>> The second part is moved to mcam-core-standard.c. This part is relevant with
>> the implementation of using V4L2.
>
>OK, I'll confess I'm still not 100% sold on this part.  Can I repeat
>the questions I raised before?
>
> - Is the soc_camera mode necessary?  Is there something you're trying
>   to do that can't be done without it?  Or, at least, does it add
>   sufficient benefit to be worth this work?  It would be nice if the
>   reasoning behind this change were put into the changelog.
>
[Albert Wang] We just want to add one more option for user. :)
And we split it to 2 parts because we want to keep the original mode.

> - If the soc_camera change is deemed to be worthwhile, is there
>   anything preventing you from doing it 100% so it's the only mode
>   used?
>
[Albert Wang] No, but current all Marvell platform have used the soc_camera in camera driver. :)
So we just hope the marvell-ccic can have this option. :)

>The split as you've done it here is an improvement over what came
>before, but it still results in a lot of duplicated code; it also adds
>a *lot* of symbols to the global namespace.  If this is really the only
>way then we'll find a way to make it work, but I'd like to be sure that
>we can't do something better.
>
>Thanks,
>
>jon



Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 12/15] [media] marvell-ccic: add soc_camera support in mmp driver
  2012-12-16 16:46   ` Jonathan Corbet
@ 2012-12-16 22:19     ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-16 22:19 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan



>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:46
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 12/15] [media] marvell-ccic: add soc_camera support in mmp
>driver
>
>On Sat, 15 Dec 2012 17:58:01 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> This patch adds the soc_camera support in the platform driver: mmp-driver.c.
>> Specified board driver also should be modified to support soc_camera by passing
>> some platform datas to platform driver.
>>
>> Currently the soc_camera mode in mmp driver only supports B_DMA_contig mode.
>
>You do intend to add the other modes (or SG, at least) in the future?
>
[Albert Wang] Yes, if need we can add the other modes in the future.

>> --- a/drivers/media/platform/marvell-ccic/Kconfig
>> +++ b/drivers/media/platform/marvell-ccic/Kconfig
>> @@ -1,23 +1,45 @@
>> +config VIDEO_MARVELL_CCIC
>> +       tristate
>> +config VIDEO_MRVL_SOC_CAMERA
>> +       bool
>
>If Linus sees this you'll get an unpleasant reminder that vowels are not
>actually in short supply; I'd suggest spelling out "MARVELL".
>
[Albert Wang] Sorry, we will change it.

>> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c
>b/drivers/media/platform/marvell-ccic/mmp-driver.c
>> index 40c243e..cd850f4 100755
>> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
>> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
>> @@ -28,6 +28,10 @@
>>  #include <linux/list.h>
>>  #include <linux/pm.h>
>>  #include <linux/clk.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <media/videobuf2-dma-contig.h>
>> +#include <media/soc_camera.h>
>> +#include <media/soc_mediabus.h>
>>
>>  #include "mcam-core.h"
>>
>> @@ -40,6 +44,8 @@ struct mmp_camera {
>>  	struct platform_device *pdev;
>>  	struct mcam_camera mcam;
>>  	struct list_head devlist;
>> +	/* will change here */
>> +	struct clk *clk[3];	/* CCIC_GATE, CCIC_RST, CCIC_DBG clocks */
>
>What does that comment mean?
>
[Albert Wang] It means there are 3 clk setting, gate_clk, rst_clk, dbg_clk.
Forgive me, the name of CCIC_DBG register is not good, but it's our actual register name. :(

>>  	int irq;
>>  };
>>
>> @@ -144,15 +150,17 @@ static void mmpcam_power_up(struct mcam_camera
>*mcam)
>>   * Provide power to the sensor.
>>   */
>>  	mcam_reg_write(mcam, REG_CLKCTRL, 0x60000002);
>> -	pdata = cam->pdev->dev.platform_data;
>> -	gpio_set_value(pdata->sensor_power_gpio, 1);
>> -	mdelay(5);
>> +	if (mcam->chip_id == V4L2_IDENT_ARMADA610) {
>
>I'm seeing a lot of these tests being added to the code.  I can imagine
>more in the future as new chipsets are supported in the driver.  Maybe it's
>time to add a structure to hide chipset-specific low-level operations?  It
>would make the code a lot cleaner.
>
[Albert Wang] OK, we will do it.

>Actually, things like mmpcam_power_up() were meant to be exactly that.  Can
>we just define a different version of this function for different chipsets?
>
[Albert Wang] Sure.

>> +		pdata = cam->pdev->dev.platform_data;
>> +		gpio_set_value(pdata->sensor_power_gpio, 1);
>> +		mdelay(5);
>> +		/* reset is active low */
>> +		gpio_set_value(pdata->sensor_reset_gpio, 0);
>> +		mdelay(5);
>> +		gpio_set_value(pdata->sensor_reset_gpio, 1);
>> +		mdelay(5);
>> +	}
>>  	mcam_reg_clear_bit(mcam, REG_CTRL1, 0x10000000);
>> -	gpio_set_value(pdata->sensor_reset_gpio, 0); /* reset is active low */
>> -	mdelay(5);
>> -	gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
>> -	mdelay(5);
>> -
>>  	mcam_clk_set(mcam, 1);
>>  }
>>
>> @@ -165,13 +173,14 @@ static void mmpcam_power_down(struct mcam_camera
>*mcam)
>>   */
>>  	iowrite32(0, cam->power_regs + REG_CCIC_DCGCR);
>>  	iowrite32(0, cam->power_regs + REG_CCIC_CRCR);
>> -/*
>> - * Shut down the sensor.
>> - */
>> -	pdata = cam->pdev->dev.platform_data;
>> -	gpio_set_value(pdata->sensor_power_gpio, 0);
>> -	gpio_set_value(pdata->sensor_reset_gpio, 0);
>> -
>> +	if (mcam->chip_id == V4L2_IDENT_ARMADA610) {
>
>Same comment applies here.
>
>> +		/*
>> +		 * Shut down the sensor.
>> +		 */
>> +		pdata = cam->pdev->dev.platform_data;
>> +		gpio_set_value(pdata->sensor_power_gpio, 0);
>> +		gpio_set_value(pdata->sensor_reset_gpio, 0);
>> +	}
>>  	mcam_clk_set(mcam, 0);
>
>jon


Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 13/15] [media] marvell-ccic: add dma burst mode support in marvell-ccic driver
  2012-12-16 16:49   ` Jonathan Corbet
@ 2012-12-16 22:22     ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-16 22:22 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan



>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:49
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 13/15] [media] marvell-ccic: add dma burst mode support in
>marvell-ccic driver
>
>On Sat, 15 Dec 2012 17:58:02 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> This patch adds the dma burst size config support for marvell-ccic.
>> Developer can set the dma burst size in specified board driver.
>
>> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h
>b/drivers/media/platform/marvell-ccic/mcam-core.h
>> index 57442e0..e1025f2 100755
>> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
>> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
>> @@ -126,6 +126,7 @@ struct mcam_camera {
>>  	short int use_smbus;	/* SMBUS or straight I2c? */
>>  	enum mcam_buffer_mode buffer_mode;
>>
>> +	int burst;
>
>That's a register flag value, seems it should be unsigned (says the guy who
>is admittedly sloppy about such things).
>
[Albert Wang] Yes, you are right.

>>  	int mclk_min;
>>  	int mclk_src;
>>  	int mclk_div;
>> @@ -411,9 +412,9 @@ int mcam_soc_camera_host_register(struct mcam_camera
>*mcam);
>>  #define   C1_DESC_3WORD   0x00000200	/* Three-word descriptors used */
>>  #define	  C1_444ALPHA	  0x00f00000	/* Alpha field in RGB444 */
>>  #define	  C1_ALPHA_SHFT	  20
>> -#define	  C1_DMAB32	  0x00000000	/* 32-byte DMA burst */
>> -#define	  C1_DMAB16	  0x02000000	/* 16-byte DMA burst */
>> -#define	  C1_DMAB64	  0x04000000	/* 64-byte DMA burst */
>> +#define	  C1_DMAB64	  0x00000000	/* 64-byte DMA burst */
>> +#define	  C1_DMAB128	  0x02000000	/* 128-byte DMA burst */
>> +#define	  C1_DMAB256	  0x04000000	/* 256-byte DMA burst */
>
>Interesting, did I just get those wrong somehow?  Or might they have been
>different in the Cafe days?
>
[Albert Wang] Yes, it looks the original definitions are wrong. We can't find them in all Marvell documents. :)
Just correct them.

>Acked-by: Jonathan Corbet <corbet@lwn.net>
>
>jon



Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode
  2012-12-16 16:56   ` Jonathan Corbet
@ 2012-12-16 22:34     ` Albert Wang
  2012-12-16 22:55       ` Jonathan Corbet
  0 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-16 22:34 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:56
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in
>DMA_CONTIG mode
>
>On Sat, 15 Dec 2012 17:58:04 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> This patch adds support of 3 frame buffers in DMA-contiguous mode.
>>
>> In current DMA_CONTIG mode, only 2 frame buffers can be supported.
>> Actually, Marvell CCIC can support at most 3 frame buffers.
>>
>> Currently 2 frame buffers mode will be used by default.
>> To use 3 frame buffers mode, can do:
>>   define MAX_FRAME_BUFS 3
>> in mcam-core.h
>
>Now that the code supports three buffers properly, is there any reason not
>to use that mode by default?
>
[Albert Wang] Because the original code use the two buffers mode, so we keep it. :)

>Did you test that it works properly if allocation of the third buffer fails?
>
[Albert Wang] Yes, we test it in our Marvell platforms.

>Otherwise looks OK except for one thing:
>
>> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h
>b/drivers/media/platform/marvell-ccic/mcam-core.h
>> index 765d47c..9bf31c8 100755
>> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
>> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
>> @@ -62,6 +62,13 @@ enum mcam_state {
>>  #define MAX_DMA_BUFS 3
>>
>>  /*
>> + * CCIC can support at most 3 frame buffers in DMA_CONTIG buffer mode
>> + * 2 - Use Two Buffers mode
>> + * 3 - Use Three Buffers mode
>> + */
>> +#define MAX_FRAME_BUFS 2 /* Current marvell-ccic used Two Buffers mode */
>> +
>> +/*
>>   * Different platforms work best with different buffer modes, so we
>>   * let the platform pick.
>>   */
>> @@ -99,6 +106,10 @@ struct mcam_frame_state {
>>  	unsigned int frames;
>>  	unsigned int singles;
>>  	unsigned int delivered;
>> +	/*
>> +	 * Only usebufs == 2 can enter single buffer mode
>> +	 */
>> +	unsigned int usebufs;
>>  };
>
>What is the purpose of the "usebufs" field?  The code maintains it in
>various places, but I don't see anywhere that actually uses that value for
>anything.
>
[Albert Wang] Two buffers mode doesn't need it.
But Three buffers mode need it indicates which conditions we need set the single buffer flag.
I used "tribufs" as the name in the previous version, but it looks it's a confused name when we merged
Two buffers mode and Three buffers mode with same code by removing #ifdef based on your comments months ago. :)
So we just changed the name with "usebufs".

>Thanks,
>
>jon


Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic
  2012-12-16 16:57 ` [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Jonathan Corbet
@ 2012-12-16 22:34   ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-16 22:34 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan

Thank you very much for taking your weekend time to review our patches! :)


Thanks
Albert Wang
86-21-61092656

>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 00:58
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org
>Subject: Re: [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-
>ccic
>
>On Sat, 15 Dec 2012 17:57:49 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> The following patches series will add soc_camera support on marvell-ccic
>
>Overall, this patch set has come a long way - great work!
>
>As I commented on the specific patches, I still have some concerns
>about the soc_camera part of it.  There's various quibbles with the
>rest, but mostly not much that's serious.  I think this work is getting
>close to being ready.
>
>Thanks,
>
>jon
>
>
>Jonathan Corbet / LWN.net / corbet@lwn.net

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode
  2012-12-16 22:34     ` Albert Wang
@ 2012-12-16 22:55       ` Jonathan Corbet
  2012-12-17  5:06         ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-16 22:55 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sun, 16 Dec 2012 14:34:31 -0800
Albert Wang <twang13@marvell.com> wrote:

> >What is the purpose of the "usebufs" field?  The code maintains it in
> >various places, but I don't see anywhere that actually uses that value for
> >anything.
> >  
> [Albert Wang] Two buffers mode doesn't need it.
> But Three buffers mode need it indicates which conditions we need set the single buffer flag.
> I used "tribufs" as the name in the previous version, but it looks it's a confused name when we merged
> Two buffers mode and Three buffers mode with same code by removing #ifdef based on your comments months ago. :)
> So we just changed the name with "usebufs".

OK, I misread the code a bit, sorry.  I do find the variable confusing
still, but it clearly does play a role.

I think that using three buffers by default would make sense.  I don't
think that increased overruns are an unbreakable ABI feature :)

Feel free to add my ack to this one.

Thanks,

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode
  2012-12-16 22:55       ` Jonathan Corbet
@ 2012-12-17  5:06         ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-17  5:06 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 06:55
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in
>DMA_CONTIG mode
>
>On Sun, 16 Dec 2012 14:34:31 -0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> >What is the purpose of the "usebufs" field?  The code maintains it in
>> >various places, but I don't see anywhere that actually uses that value for
>> >anything.
>> >
>> [Albert Wang] Two buffers mode doesn't need it.
>> But Three buffers mode need it indicates which conditions we need set the single
>buffer flag.
>> I used "tribufs" as the name in the previous version, but it looks it's a confused name
>when we merged
>> Two buffers mode and Three buffers mode with same code by removing #ifdef based
>on your comments months ago. :)
>> So we just changed the name with "usebufs".
>
>OK, I misread the code a bit, sorry.  I do find the variable confusing
>still, but it clearly does play a role.
>
>I think that using three buffers by default would make sense.  I don't
>think that increased overruns are an unbreakable ABI feature :)
>
[Albert Wang] OK, we can change the default to three buffers mode.

>Feel free to add my ack to this one.
>
>Thanks,
>
>jon


Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2012-12-16 22:12     ` Albert Wang
@ 2012-12-17 15:28       ` Jonathan Corbet
  2012-12-18  3:04         ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-17 15:28 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Sun, 16 Dec 2012 14:12:11 -0800
Albert Wang <twang13@marvell.com> wrote:

> > - Is the soc_camera mode necessary?  Is there something you're trying
> >   to do that can't be done without it?  Or, at least, does it add
> >   sufficient benefit to be worth this work?  It would be nice if the
> >   reasoning behind this change were put into the changelog.
> >  
> [Albert Wang] We just want to add one more option for user. :)
> And we split it to 2 parts because we want to keep the original mode.
> 
> > - If the soc_camera change is deemed to be worthwhile, is there
> >   anything preventing you from doing it 100% so it's the only mode
> >   used?
> >  
> [Albert Wang] No, but current all Marvell platform have used the soc_camera in camera driver. :)
> So we just hope the marvell-ccic can have this option. :)

OK, so this, I think, is the one remaining point of disagreement here;
unfortunately it's a biggish one.

Users, I believe, don't really care which underlying framework the driver
is using; they just want a camera implementing the V4L2 spec.  So, this
particular option does not have any real value for them.  But it has a
real cost in terms of duplicated code, added complexity, and namespace
pollution.  If you believe I'm wrong, please tell me why, but I think that
this option is not worth the cost.

The reason for the soc_camera conversion is because that's how your
drivers do it — not necessarily the strongest of reasons.  Of course, the
reason for keeping things as they are is because that's how the in-tree
drivers does it; not necessarily a whole lot stronger.

I'm not sold on the soc_camera conversion, but neither am I implacably
opposed to it.  But I *really* dislike the idea of having both, I don't
see that leading to good things in the long run.  So can I ask one more
time: if soc_camera is important to you, could you please just convert the
driver over 100% and drop the other mode entirely?  It seems that should
be easier than trying to support both, and it should certainly be easier
to maintain in the future.

I'm sorry to be obnoxious about this.

Meanwhile, the bulk of this last patch series seems good; most of them
have my acks, and I saw acks from Guennadi on some as well.  I would
recommend that you separate those out into a different series and submit
them for merging, presumably for 3.9.  That will give you a bit less code
to carry going forward as this last part gets worked out.

Thanks again for doing this work and persevering with it!

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2012-12-17 15:28       ` Jonathan Corbet
@ 2012-12-18  3:04         ` Albert Wang
  2012-12-18 19:15           ` Jonathan Corbet
  0 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2012-12-18  3:04 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Monday, 17 December, 2012 23:29
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for
>soc_camera support
>
>On Sun, 16 Dec 2012 14:12:11 -0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> > - Is the soc_camera mode necessary?  Is there something you're trying
>> >   to do that can't be done without it?  Or, at least, does it add
>> >   sufficient benefit to be worth this work?  It would be nice if the
>> >   reasoning behind this change were put into the changelog.
>> >
>> [Albert Wang] We just want to add one more option for user. :)
>> And we split it to 2 parts because we want to keep the original mode.
>>
>> > - If the soc_camera change is deemed to be worthwhile, is there
>> >   anything preventing you from doing it 100% so it's the only mode
>> >   used?
>> >
>> [Albert Wang] No, but current all Marvell platform have used the soc_camera in camera
>driver. :)
>> So we just hope the marvell-ccic can have this option. :)
>
>OK, so this, I think, is the one remaining point of disagreement here;
>unfortunately it's a biggish one.
>
>Users, I believe, don't really care which underlying framework the driver
>is using; they just want a camera implementing the V4L2 spec.  So, this
>particular option does not have any real value for them.  But it has a
>real cost in terms of duplicated code, added complexity, and namespace
>pollution.  If you believe I'm wrong, please tell me why, but I think that
>this option is not worth the cost.
>
>The reason for the soc_camera conversion is because that's how your
>drivers do it — not necessarily the strongest of reasons.  Of course, the
>reason for keeping things as they are is because that's how the in-tree
>drivers does it; not necessarily a whole lot stronger.
>
>I'm not sold on the soc_camera conversion, but neither am I implacably
>opposed to it.  But I *really* dislike the idea of having both, I don't
>see that leading to good things in the long run.  So can I ask one more
>time: if soc_camera is important to you, could you please just convert the
>driver over 100% and drop the other mode entirely?  It seems that should
>be easier than trying to support both, and it should certainly be easier
>to maintain in the future.
>
[Albert Wang] So if we add B_DMA_SG and B_VMALLOC support and OLPC XO 1.0 support in soc_camera mode.
Then we can just remove the original mode and only support soc_camera mode in marvell-ccic?

>I'm sorry to be obnoxious about this.
>
>Meanwhile, the bulk of this last patch series seems good; most of them
>have my acks, and I saw acks from Guennadi on some as well.  I would
>recommend that you separate those out into a different series and submit
>them for merging, presumably for 3.9.  That will give you a bit less code
>to carry going forward as this last part gets worked out.
>
>Thanks again for doing this work and persevering with it!
>
>jon


Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2012-12-18  3:04         ` Albert Wang
@ 2012-12-18 19:15           ` Jonathan Corbet
  2012-12-18 20:48             ` Albert Wang
  2013-01-31  8:29             ` Albert Wang
  0 siblings, 2 replies; 71+ messages in thread
From: Jonathan Corbet @ 2012-12-18 19:15 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

On Mon, 17 Dec 2012 19:04:26 -0800
Albert Wang <twang13@marvell.com> wrote:

> [Albert Wang] So if we add B_DMA_SG and B_VMALLOC support and OLPC XO 1.0 support in soc_camera mode.
> Then we can just remove the original mode and only support soc_camera mode in marvell-ccic?

That is the idea, yes.  Unless there is some real value to supporting both
modes (that I've not seen), I think it's far better to support just one of
them.  Trying to support duplicated modes just leads to pain in the long
run, in my experience.

I can offer to *try* to find time to help with XO 1.0 testing when the
time comes.

Thanks,

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2012-12-18 19:15           ` Jonathan Corbet
@ 2012-12-18 20:48             ` Albert Wang
  2013-01-31  8:29             ` Albert Wang
  1 sibling, 0 replies; 71+ messages in thread
From: Albert Wang @ 2012-12-18 20:48 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Wednesday, 19 December, 2012 03:15
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for
>soc_camera support
>
>On Mon, 17 Dec 2012 19:04:26 -0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> [Albert Wang] So if we add B_DMA_SG and B_VMALLOC support and OLPC XO 1.0
>support in soc_camera mode.
>> Then we can just remove the original mode and only support soc_camera mode in
>marvell-ccic?
>
>That is the idea, yes.  Unless there is some real value to supporting both
>modes (that I've not seen), I think it's far better to support just one of
>them.  Trying to support duplicated modes just leads to pain in the long
>run, in my experience.
>
[Albert Wang] OK, we will update and submit the remained patches except for the 3 patches related with soc_camera support as the first part.
Then we will submit the soc_camera support patches after we rework the patches and add B_DMA_SG and B_VMALLOC support and OLPC XO 1.0 support.

>I can offer to *try* to find time to help with XO 1.0 testing when the
>time comes.
>
[Albert Wang] Thank you very much! We were worried about how to get the OLPC XO 1.0 HW. That would be a great help! :)

>Thanks,
>
>jon


Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable
  2012-12-16 15:36   ` Jonathan Corbet
@ 2012-12-27 20:07     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 71+ messages in thread
From: Mauro Carvalho Chehab @ 2012-12-27 20:07 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: Albert Wang, g.liakhovetski, linux-media, Libin Yang

Em Sun, 16 Dec 2012 08:36:59 -0700
Jonathan Corbet <corbet@lwn.net> escreveu:

> On Sat, 15 Dec 2012 17:57:50 +0800
> Albert Wang <twang13@marvell.com> wrote:
> 
> > This patch replaces the global frame stats variables by using
> > internal variables in mcam_camera structure.
> 
> This one seems fine.  Someday it might be nice to have proper stats
> rather than my debugging hack, complete with a nice sysfs interface and
> all that.  
> 
> Acked-by: Jonathan Corbet <corbet@lwn.net>

While I understand that a v4 will popup, due to some comments done on
the other patches on this v3, this patch seems pretty much independent.
So, I'll just apply it right now, and tag the others as "changes_requested"
at patchwork.

Regards,
Mauro

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable
  2012-12-15  9:57 ` [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable Albert Wang
  2012-12-16 15:36   ` Jonathan Corbet
@ 2013-01-01 14:56   ` Guennadi Liakhovetski
  1 sibling, 0 replies; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-01 14:56 UTC (permalink / raw)
  To: Albert Wang; +Cc: corbet, linux-media, Libin Yang

On Sat, 15 Dec 2012, Albert Wang wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch replaces the global frame stats variables by using
> internal variables in mcam_camera structure.
> 
> Signed-off-by: Albert Wang <twang13@marvell.com>
> Signed-off-by: Libin Yang <lbyang@marvell.com>

Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>

Thanks
Guennadi

> ---
>  drivers/media/platform/marvell-ccic/mcam-core.c |   30 ++++++++++-------------
>  drivers/media/platform/marvell-ccic/mcam-core.h |    9 +++++++
>  2 files changed, 22 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
> index ce2b7b4..7012913f 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
> @@ -30,13 +30,6 @@
>  
>  #include "mcam-core.h"
>  
> -/*
> - * Basic frame stats - to be deleted shortly
> - */
> -static int frames;
> -static int singles;
> -static int delivered;
> -
>  #ifdef MCAM_MODE_VMALLOC
>  /*
>   * Internal DMA buffer management.  Since the controller cannot do S/G I/O,
> @@ -367,10 +360,10 @@ static void mcam_frame_tasklet(unsigned long data)
>  		if (!test_bit(bufno, &cam->flags))
>  			continue;
>  		if (list_empty(&cam->buffers)) {
> -			singles++;
> +			cam->frame_state.singles++;
>  			break;  /* Leave it valid, hope for better later */
>  		}
> -		delivered++;
> +		cam->frame_state.delivered++;
>  		clear_bit(bufno, &cam->flags);
>  		buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
>  				queue);
> @@ -452,7 +445,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
>  		mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
>  				vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
>  		set_bit(CF_SINGLE_BUFFER, &cam->flags);
> -		singles++;
> +		cam->frame_state.singles++;
>  		return;
>  	}
>  	/*
> @@ -485,7 +478,7 @@ static void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
>  	struct mcam_vb_buffer *buf = cam->vb_bufs[frame];
>  
>  	if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) {
> -		delivered++;
> +		cam->frame_state.delivered++;
>  		mcam_buffer_done(cam, frame, &buf->vb_buf);
>  	}
>  	mcam_set_contig_buffer(cam, frame);
> @@ -578,13 +571,13 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
>  	 */
>  	} else {
>  		set_bit(CF_SG_RESTART, &cam->flags);
> -		singles++;
> +		cam->frame_state.singles++;
>  		cam->vb_bufs[0] = NULL;
>  	}
>  	/*
>  	 * Now we can give the completed frame back to user space.
>  	 */
> -	delivered++;
> +	cam->frame_state.delivered++;
>  	mcam_buffer_done(cam, frame, &buf->vb_buf);
>  }
>  
> @@ -1545,7 +1538,9 @@ static int mcam_v4l_open(struct file *filp)
>  
>  	filp->private_data = cam;
>  
> -	frames = singles = delivered = 0;
> +	cam->frame_state.frames = 0;
> +	cam->frame_state.singles = 0;
> +	cam->frame_state.delivered = 0;
>  	mutex_lock(&cam->s_mutex);
>  	if (cam->users == 0) {
>  		ret = mcam_setup_vb2(cam);
> @@ -1566,8 +1561,9 @@ static int mcam_v4l_release(struct file *filp)
>  {
>  	struct mcam_camera *cam = filp->private_data;
>  
> -	cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames,
> -			singles, delivered);
> +	cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n",
> +			cam->frame_state.frames, cam->frame_state.singles,
> +			cam->frame_state.delivered);
>  	mutex_lock(&cam->s_mutex);
>  	(cam->users)--;
>  	if (cam->users == 0) {
> @@ -1660,7 +1656,7 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame)
>  	clear_bit(CF_DMA_ACTIVE, &cam->flags);
>  	cam->next_buf = frame;
>  	cam->buf_seq[frame] = ++(cam->sequence);
> -	frames++;
> +	cam->frame_state.frames++;
>  	/*
>  	 * "This should never happen"
>  	 */
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
> index bd6acba..5e802c6 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
> @@ -73,6 +73,14 @@ static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode)
>  	}
>  }
>  
> +/*
> + * Basic frame states
> + */
> +struct mcam_frame_state {
> +	unsigned int frames;
> +	unsigned int singles;
> +	unsigned int delivered;
> +};
>  
>  /*
>   * A description of one of our devices.
> @@ -108,6 +116,7 @@ struct mcam_camera {
>  	unsigned long flags;		/* Buffer status, mainly (dev_lock) */
>  	int users;			/* How many open FDs */
>  
> +	struct mcam_frame_state frame_state;	/* Frame state counter */
>  	/*
>  	 * Subsystem structures.
>  	 */
> -- 
> 1.7.9.5
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver Albert Wang
  2012-12-16 15:54   ` Jonathan Corbet
@ 2013-01-01 15:28   ` Guennadi Liakhovetski
  2013-01-01 19:31     ` Albert Wang
  1 sibling, 1 reply; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-01 15:28 UTC (permalink / raw)
  To: Albert Wang; +Cc: corbet, linux-media, Libin Yang

Hi Albert

Looks quite good to me, thanks for addressing my comments! Just a minor 
nitpick below:

On Sat, 15 Dec 2012, Albert Wang wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the MIPI support for marvell-ccic.
> Board driver should determine whether using MIPI or not.
> 
> Signed-off-by: Albert Wang <twang13@marvell.com>
> Signed-off-by: Libin Yang <lbyang@marvell.com>
> ---

A general request for future revisions: it would help if you could list changes 
since the last version here - after any Sob's and the "---" line.

>  drivers/media/platform/marvell-ccic/mcam-core.c  |   70 ++++++++++++++++++++
>  drivers/media/platform/marvell-ccic/mcam-core.h  |   24 ++++++-
>  drivers/media/platform/marvell-ccic/mmp-driver.c |   75 +++++++++++++++++++++-
>  include/media/mmp-camera.h                       |   10 +++
>  4 files changed, 177 insertions(+), 2 deletions(-)

[snip]

> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
> index c4c17fe..603fa0a 100755
> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c

[snip]

> @@ -183,8 +251,14 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	mcam = &cam->mcam;
>  	mcam->plat_power_up = mmpcam_power_up;
>  	mcam->plat_power_down = mmpcam_power_down;
> +	mcam->calc_dphy = mmpcam_calc_dphy;
> +	mcam->pll1 = NULL;

Strictly speaking this is not needed, it's allocated using kzalloc(). Kinda 
pointless to use kzalloc() and then explicitly initialise each field, 
including 0 / NULL...

>  	mcam->dev = &pdev->dev;
>  	mcam->use_smbus = 0;
> +	mcam->bus_type = pdata->bus_type;
> +	mcam->dphy = pdata->dphy;
> +	mcam->mipi_enabled = 0;

ditto

> +	mcam->lane = pdata->lane;
>  	mcam->chip_id = V4L2_IDENT_ARMADA610;
>  	mcam->buffer_mode = B_DMA_sg;
>  	spin_lock_init(&mcam->dev_lock);

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 03/15] [media] marvell-ccic: add clock tree " Albert Wang
  2012-12-16 16:03   ` Jonathan Corbet
@ 2013-01-01 16:05   ` Guennadi Liakhovetski
  2013-01-01 19:36     ` Albert Wang
  2013-01-04  5:42     ` Libin Yang
  1 sibling, 2 replies; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-01 16:05 UTC (permalink / raw)
  To: Albert Wang; +Cc: corbet, linux-media, Libin Yang

On Sat, 15 Dec 2012, Albert Wang wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the clock tree support for marvell-ccic.
> 
> Each board may require different clk enabling sequence.
> Developer need add the clk_name in correct sequence in board driver
> to use this feature.
> 
> Signed-off-by: Libin Yang <lbyang@marvell.com>
> Signed-off-by: Albert Wang <twang13@marvell.com>
> ---
>  drivers/media/platform/marvell-ccic/mcam-core.h  |    4 ++
>  drivers/media/platform/marvell-ccic/mmp-driver.c |   57 +++++++++++++++++++++-
>  include/media/mmp-camera.h                       |    5 ++
>  3 files changed, 65 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
> index ca63010..86e634e 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
> @@ -88,6 +88,7 @@ struct mcam_frame_state {
>   *          the dev_lock spinlock; they are marked as such by comments.
>   *          dev_lock is also required for access to device registers.
>   */
> +#define NR_MCAM_CLK 4
>  struct mcam_camera {
>  	/*
>  	 * These fields should be set by the platform code prior to
> @@ -109,6 +110,9 @@ struct mcam_camera {
>  	int lane;			/* lane number */
>  
>  	struct clk *pll1;
> +	/* clock tree support */
> +	struct clk *clk[NR_MCAM_CLK];
> +	int clk_num;
>  
>  	/*
>  	 * Callbacks from the core to the platform code.
> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
> index 603fa0a..2c4dce3 100755
> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
> @@ -104,6 +104,23 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev)
>  #define REG_CCIC_DCGCR		0x28	/* CCIC dyn clock gate ctrl reg */
>  #define REG_CCIC_CRCR		0x50	/* CCIC clk reset ctrl reg	*/
>  
> +static void mcam_clk_set(struct mcam_camera *mcam, int on)

Personally, I would also make two functions out of this - "on" and "off," 
but that's a matter of taste, perhaps.

> +{
> +	unsigned int i;
> +
> +	if (on) {
> +		for (i = 0; i < mcam->clk_num; i++) {
> +			if (mcam->clk[i])
> +				clk_enable(mcam->clk[i]);
> +		}
> +	} else {
> +		for (i = mcam->clk_num; i > 0; i--) {
> +			if (mcam->clk[i - 1])
> +				clk_disable(mcam->clk[i - 1]);
> +		}
> +	}
> +}
> +
>  /*
>   * Power control.
>   */
> @@ -134,6 +151,8 @@ static void mmpcam_power_up(struct mcam_camera *mcam)
>  	mdelay(5);
>  	gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
>  	mdelay(5);
> +
> +	mcam_clk_set(mcam, 1);
>  }
>  
>  static void mmpcam_power_down(struct mcam_camera *mcam)
> @@ -151,6 +170,8 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
>  	pdata = cam->pdev->dev.platform_data;
>  	gpio_set_value(pdata->sensor_power_gpio, 0);
>  	gpio_set_value(pdata->sensor_reset_gpio, 0);
> +
> +	mcam_clk_set(mcam, 0);
>  }
>  
>  /*
> @@ -202,7 +223,7 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
>  	 * pll1 will never be changed, it is a fixed value
>  	 */
>  
> -	if (IS_ERR(mcam->pll1))
> +	if (IS_ERR_OR_NULL(mcam->pll1))

Why are you changing this? If this really were needed, you should do this 
already in the previous patch, where you add these lines. But I don't 
think this is a good idea, don't think Russell would like this :-) NULL is 
a valid clock. Only a negative error is a failure. In fact, if you like, 
you could initialise .pll1 to ERR_PTR(-EINVAL) in your previous patch in 
mmpcam_probe().

>  		return;
>  
>  	tx_clk_esc = clk_get_rate(mcam->pll1) / 1000000 / 12;
> @@ -229,6 +250,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
>  	return IRQ_RETVAL(handled);
>  }
>  
> +static void mcam_init_clk(struct mcam_camera *mcam,
> +			struct mmp_camera_platform_data *pdata, int init)

I don't think this "int init" makes sense. Please, remove the parameter 
and you actually don't need the de-initialisation, no reason to set 
num_clk = 0 before freeing memory.

> +{
> +	unsigned int i;
> +
> +	if (NR_MCAM_CLK < pdata->clk_num) {
> +		dev_err(mcam->dev, "Too many mcam clocks defined\n");
> +		mcam->clk_num = 0;
> +		return;
> +	}
> +
> +	if (init) {
> +		for (i = 0; i < pdata->clk_num; i++) {
> +			if (pdata->clk_name[i] != NULL) {
> +				mcam->clk[i] = devm_clk_get(mcam->dev,
> +						pdata->clk_name[i]);

Sorry, no. Passing clock names in platform data doesn't look right to me. 
Clock names are a property of the consumer device, not of clock supplier. 
Also, your platform tells you to get clk_num clocks, you fail to get one 
of them, you don't continue trying the rest and just return with no error. 
This seems strange, usually a failure to get clocks, that the platform 
tells you to get, is fatal.

> +				if (IS_ERR(mcam->clk[i])) {
> +					dev_err(mcam->dev,
> +						"Could not get clk: %s\n",
> +						pdata->clk_name[i]);
> +					mcam->clk_num = 0;
> +					return;
> +				}
> +			}
> +		}
> +		mcam->clk_num = pdata->clk_num;
> +	} else
> +		mcam->clk_num = 0;
> +}
>  
>  static int mmpcam_probe(struct platform_device *pdev)
>  {

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 04/15] [media] marvell-ccic: reset ccic phy when stop streaming for stability
  2012-12-15  9:57 ` [PATCH V3 04/15] [media] marvell-ccic: reset ccic phy when stop streaming for stability Albert Wang
  2012-12-16 16:04   ` Jonathan Corbet
@ 2013-01-01 16:13   ` Guennadi Liakhovetski
  1 sibling, 0 replies; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-01 16:13 UTC (permalink / raw)
  To: Albert Wang; +Cc: corbet, linux-media, Libin Yang

On Sat, 15 Dec 2012, Albert Wang wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the reset ccic phy operation when stop streaming.
> 
> Without reset ccic phy, the next start streaming may be unstable.
> 
> Also need add CCIC2 definition when PXA688/PXA2128 support dual ccics.
> 
> Signed-off-by: Albert Wang <twang13@marvell.com>
> Signed-off-by: Libin Yang <lbyang@marvell.com>

Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>

Thanks
Guennadi

> ---
>  drivers/media/platform/marvell-ccic/mcam-core.c  |    6 ++++++
>  drivers/media/platform/marvell-ccic/mcam-core.h  |    2 ++
>  drivers/media/platform/marvell-ccic/mmp-driver.c |   25 ++++++++++++++++++++++
>  3 files changed, 33 insertions(+)
> 
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
> index f6ae06d..19e91c5 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
> @@ -1058,6 +1058,12 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
>  		return -EINVAL;
>  	mcam_ctlr_stop_dma(cam);
>  	/*
> +	 * Reset the CCIC PHY after stopping streaming,
> +	 * otherwise, the CCIC may be unstable.
> +	 */
> +	if (cam->ctlr_reset)
> +		cam->ctlr_reset(cam);
> +	/*
>  	 * VB2 reclaims the buffers, so we need to forget
>  	 * about them.
>  	 */
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
> index 86e634e..7c42cbe 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
> @@ -103,6 +103,7 @@ struct mcam_camera {
>  	short int use_smbus;	/* SMBUS or straight I2c? */
>  	enum mcam_buffer_mode buffer_mode;
>  
> +	int ccic_id;
>  	enum v4l2_mbus_type bus_type;
>  	/* MIPI support */
>  	int *dphy;
> @@ -120,6 +121,7 @@ struct mcam_camera {
>  	void (*plat_power_up) (struct mcam_camera *cam);
>  	void (*plat_power_down) (struct mcam_camera *cam);
>  	void (*calc_dphy)(struct mcam_camera *cam);
> +	void (*ctlr_reset)(struct mcam_camera *cam);
>  
>  	/*
>  	 * Everything below here is private to the mcam core and
> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
> index 2c4dce3..fec7cd8 100755
> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
> @@ -103,6 +103,7 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev)
>  #define CPU_SUBSYS_PMU_BASE	0xd4282800
>  #define REG_CCIC_DCGCR		0x28	/* CCIC dyn clock gate ctrl reg */
>  #define REG_CCIC_CRCR		0x50	/* CCIC clk reset ctrl reg	*/
> +#define REG_CCIC2_CRCR		0xf4	/* CCIC2 clk reset ctrl reg	*/
>  
>  static void mcam_clk_set(struct mcam_camera *mcam, int on)
>  {
> @@ -174,6 +175,28 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
>  	mcam_clk_set(mcam, 0);
>  }
>  
> +void mcam_ctlr_reset(struct mcam_camera *mcam)
> +{
> +	unsigned long val;
> +	struct mmp_camera *cam = mcam_to_cam(mcam);
> +
> +	if (mcam->ccic_id) {
> +		/*
> +		 * Using CCIC2
> +		 */
> +		val = ioread32(cam->power_regs + REG_CCIC2_CRCR);
> +		iowrite32(val & ~0x2, cam->power_regs + REG_CCIC2_CRCR);
> +		iowrite32(val | 0x2, cam->power_regs + REG_CCIC2_CRCR);
> +	} else {
> +		/*
> +		 * Using CCIC1
> +		 */
> +		val = ioread32(cam->power_regs + REG_CCIC_CRCR);
> +		iowrite32(val & ~0x2, cam->power_regs + REG_CCIC_CRCR);
> +		iowrite32(val | 0x2, cam->power_regs + REG_CCIC_CRCR);
> +	}
> +}
> +
>  /*
>   * calc the dphy register values
>   * There are three dphy registers being used.
> @@ -301,10 +324,12 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	mcam = &cam->mcam;
>  	mcam->plat_power_up = mmpcam_power_up;
>  	mcam->plat_power_down = mmpcam_power_down;
> +	mcam->ctlr_reset = mcam_ctlr_reset;
>  	mcam->calc_dphy = mmpcam_calc_dphy;
>  	mcam->pll1 = NULL;
>  	mcam->dev = &pdev->dev;
>  	mcam->use_smbus = 0;
> +	mcam->ccic_id = pdev->id;
>  	mcam->bus_type = pdata->bus_type;
>  	mcam->dphy = pdata->dphy;
>  	mcam->mipi_enabled = 0;
> -- 
> 1.7.9.5
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver Albert Wang
  2012-12-16 16:16   ` Jonathan Corbet
@ 2013-01-01 16:56   ` Guennadi Liakhovetski
  2013-01-01 19:42     ` Albert Wang
                       ` (2 more replies)
  1 sibling, 3 replies; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-01 16:56 UTC (permalink / raw)
  To: Albert Wang; +Cc: corbet, linux-media, Libin Yang

On Sat, 15 Dec 2012, Albert Wang wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the new formats support for marvell-ccic.
> 
> Signed-off-by: Albert Wang <twang13@marvell.com>
> Signed-off-by: Libin Yang <lbyang@marvell.com>
> ---
>  drivers/media/platform/marvell-ccic/mcam-core.c |  175 ++++++++++++++++++-----
>  drivers/media/platform/marvell-ccic/mcam-core.h |    6 +
>  2 files changed, 149 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
> index 3cc1d0c..a679917 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c

[snip]

> @@ -658,49 +708,85 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
>   */
>  static void mcam_ctlr_image(struct mcam_camera *cam)
>  {
> -	int imgsz;
>  	struct v4l2_pix_format *fmt = &cam->pix_format;
> +	u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
> +
> +	cam_dbg(cam, "camera: bytesperline = %d; height = %d\n",
> +		fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
> +	imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
> +	imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
> +
> +	switch (fmt->pixelformat) {
> +	case V4L2_PIX_FMT_YUYV:
> +	case V4L2_PIX_FMT_UYVY:
> +		widthy = fmt->width * 2;
> +		widthuv = 0;
> +		break;
> +	case V4L2_PIX_FMT_JPEG:
> +		imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
> +		widthy = fmt->bytesperline;
> +		widthuv = 0;
> +		break;
> +	case V4L2_PIX_FMT_YUV422P:
> +	case V4L2_PIX_FMT_YUV420:
> +	case V4L2_PIX_FMT_YVU420:
> +		imgsz_w = (fmt->bytesperline * 4 / 3) & IMGSZ_H_MASK;
> +		widthy = fmt->width;
> +		widthuv = fmt->width / 2;

I might be wrong, but the above doesn't look right to me. Firstly, YUV422P 
is a 4:2:2 format, whereas YUV420 and YVU420 are 4:2:0 formats, so, I 
would expect calculations for them to differ. Besides, bytesperline * 4 / 
3 doesn't look right for any of them. If this is what I think - total 
number of bytes per line, i.e., sizeimage / height, than shouldn't YAU422P 
have
+		imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
and the other two
+		imgsz_w = (fmt->bytesperline * 3 / 2) & IMGSZ_H_MASK;
? But maybe I'm wrong, please, double-check and confirm.

> +		break;
> +	default:
> +		widthy = fmt->bytesperline;
> +		widthuv = 0;
> +	}
> +
> +	mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
> +			IMGP_YP_MASK | IMGP_UVP_MASK);
> +	mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w);
> +	mcam_reg_write(cam, REG_IMGOFFSET, 0x0);
>  
> -	imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
> -		(fmt->bytesperline & IMGSZ_H_MASK);
> -	mcam_reg_write(cam, REG_IMGSIZE, imgsz);
> -	mcam_reg_write(cam, REG_IMGOFFSET, 0);
> -	/* YPITCH just drops the last two bits */
> -	mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
> -			IMGP_YP_MASK);
>  	/*
>  	 * Tell the controller about the image format we are using.
>  	 */
> -	switch (cam->pix_format.pixelformat) {
> +	switch (fmt->pixelformat) {
> +	case V4L2_PIX_FMT_YUV422P:
> +		mcam_reg_write_mask(cam, REG_CTRL0,
> +			C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK);
> +		break;
> +	case V4L2_PIX_FMT_YUV420:
> +	case V4L2_PIX_FMT_YVU420:
> +		mcam_reg_write_mask(cam, REG_CTRL0,
> +			C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
> +		break;
>  	case V4L2_PIX_FMT_YUYV:
> -	    mcam_reg_write_mask(cam, REG_CTRL0,
> -			    C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
> -			    C0_DF_MASK);
> -	    break;
> -
> +		mcam_reg_write_mask(cam, REG_CTRL0,
> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
> +		break;
> +	case V4L2_PIX_FMT_UYVY:
> +		mcam_reg_write_mask(cam, REG_CTRL0,
> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
> +		break;
> +	case V4L2_PIX_FMT_JPEG:
> +		mcam_reg_write_mask(cam, REG_CTRL0,
> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
> +		break;
>  	case V4L2_PIX_FMT_RGB444:
> -	    mcam_reg_write_mask(cam, REG_CTRL0,
> -			    C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
> -			    C0_DF_MASK);
> +		mcam_reg_write_mask(cam, REG_CTRL0,
> +			C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
>  		/* Alpha value? */
> -	    break;
> -
> +		break;
>  	case V4L2_PIX_FMT_RGB565:
> -	    mcam_reg_write_mask(cam, REG_CTRL0,
> -			    C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
> -			    C0_DF_MASK);
> -	    break;
> -
> +		mcam_reg_write_mask(cam, REG_CTRL0,
> +			C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
> +		break;
>  	default:
> -	    cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
> -	    break;
> +		cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat);
> +		break;
>  	}
> +
>  	/*
>  	 * Make sure it knows we want to use hsync/vsync.
>  	 */
> -	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
> -			C0_SIFM_MASK);
> -
> +	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
>  	/*
>  	 * This field controls the generation of EOF(DVP only)
>  	 */
> @@ -711,7 +797,6 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
>  	}
>  }
>  
> -
>  /*
>   * Configure the controller for operation; caller holds the
>   * device mutex.
> @@ -984,11 +1069,37 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
>  {
>  	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
>  	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
> +	struct v4l2_pix_format *fmt = &cam->pix_format;
>  	unsigned long flags;
>  	int start;
> +	dma_addr_t dma_handle;
> +	u32 pixel_count = fmt->width * fmt->height;
>  
>  	spin_lock_irqsave(&cam->dev_lock, flags);
> +	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
> +	BUG_ON(!dma_handle);
>  	start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
> +
> +	switch (cam->pix_format.pixelformat) {
> +	case V4L2_PIX_FMT_YUV422P:
> +		mvb->yuv_p.y = dma_handle;

The above line is common for all cases, perhaps just put it above switch?

> +		mvb->yuv_p.u = mvb->yuv_p.y + pixel_count;
> +		mvb->yuv_p.v = mvb->yuv_p.u + pixel_count / 2;
> +		break;
> +	case V4L2_PIX_FMT_YUV420:
> +		mvb->yuv_p.y = dma_handle;
> +		mvb->yuv_p.u = mvb->yuv_p.y + pixel_count;
> +		mvb->yuv_p.v = mvb->yuv_p.u + pixel_count / 4;
> +		break;
> +	case V4L2_PIX_FMT_YVU420:
> +		mvb->yuv_p.y = dma_handle;
> +		mvb->yuv_p.v = mvb->yuv_p.y + pixel_count;
> +		mvb->yuv_p.u = mvb->yuv_p.v + pixel_count / 4;
> +		break;
> +	default:
> +		mvb->yuv_p.y = dma_handle;
> +	}
> +
>  	list_add(&mvb->queue, &cam->buffers);
>  	if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags))
>  		mcam_sg_restart(cam);

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver
  2013-01-01 15:28   ` Guennadi Liakhovetski
@ 2013-01-01 19:31     ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2013-01-01 19:31 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: corbet, linux-media, Libin Yang

Hi, Guennadi

Happy New Year!

Thank you for your review!

>-----Original Message-----
>From: Guennadi Liakhovetski [mailto:g.liakhovetski@gmx.de]
>Sent: Tuesday, 01 January, 2013 23:28
>To: Albert Wang
>Cc: corbet@lwn.net; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic
>driver
>
>Hi Albert
>
>Looks quite good to me, thanks for addressing my comments! Just a minor
>nitpick below:
>
>On Sat, 15 Dec 2012, Albert Wang wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the MIPI support for marvell-ccic.
>> Board driver should determine whether using MIPI or not.
>>
>> Signed-off-by: Albert Wang <twang13@marvell.com>
>> Signed-off-by: Libin Yang <lbyang@marvell.com>
>> ---
>
>A general request for future revisions: it would help if you could list changes
>since the last version here - after any Sob's and the "---" line.
>
>>  drivers/media/platform/marvell-ccic/mcam-core.c  |   70 ++++++++++++++++++++
>>  drivers/media/platform/marvell-ccic/mcam-core.h  |   24 ++++++-
>>  drivers/media/platform/marvell-ccic/mmp-driver.c |   75 +++++++++++++++++++++-
>>  include/media/mmp-camera.h                       |   10 +++
>>  4 files changed, 177 insertions(+), 2 deletions(-)
>
>[snip]
>
>> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c
>b/drivers/media/platform/marvell-ccic/mmp-driver.c
>> index c4c17fe..603fa0a 100755
>> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
>> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
>
>[snip]
>
>> @@ -183,8 +251,14 @@ static int mmpcam_probe(struct platform_device *pdev)
>>  	mcam = &cam->mcam;
>>  	mcam->plat_power_up = mmpcam_power_up;
>>  	mcam->plat_power_down = mmpcam_power_down;
>> +	mcam->calc_dphy = mmpcam_calc_dphy;
>> +	mcam->pll1 = NULL;
>
>Strictly speaking this is not needed, it's allocated using kzalloc(). Kinda
>pointless to use kzalloc() and then explicitly initialise each field,
>including 0 / NULL...
>
[Albert Wang] OK, We will update it.

>>  	mcam->dev = &pdev->dev;
>>  	mcam->use_smbus = 0;
>> +	mcam->bus_type = pdata->bus_type;
>> +	mcam->dphy = pdata->dphy;
>> +	mcam->mipi_enabled = 0;
>
>ditto
>
>> +	mcam->lane = pdata->lane;
>>  	mcam->chip_id = V4L2_IDENT_ARMADA610;
>>  	mcam->buffer_mode = B_DMA_sg;
>>  	spin_lock_init(&mcam->dev_lock);
>
>Thanks
>Guennadi
>---
>Guennadi Liakhovetski, Ph.D.
>Freelance Open-Source Software Developer
>http://www.open-technology.de/

Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2013-01-01 16:05   ` Guennadi Liakhovetski
@ 2013-01-01 19:36     ` Albert Wang
  2013-01-04  5:42     ` Libin Yang
  1 sibling, 0 replies; 71+ messages in thread
From: Albert Wang @ 2013-01-01 19:36 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: corbet, linux-media, Libin Yang

Hi, Guennadi


>-----Original Message-----
>From: Guennadi Liakhovetski [mailto:g.liakhovetski@gmx.de]
>Sent: Wednesday, 02 January, 2013 00:06
>To: Albert Wang
>Cc: corbet@lwn.net; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-
>ccic driver
>
>On Sat, 15 Dec 2012, Albert Wang wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the clock tree support for marvell-ccic.
>>
>> Each board may require different clk enabling sequence.
>> Developer need add the clk_name in correct sequence in board driver
>> to use this feature.
>>
>> Signed-off-by: Libin Yang <lbyang@marvell.com>
>> Signed-off-by: Albert Wang <twang13@marvell.com>
>> ---
>>  drivers/media/platform/marvell-ccic/mcam-core.h  |    4 ++
>>  drivers/media/platform/marvell-ccic/mmp-driver.c |   57 +++++++++++++++++++++-
>>  include/media/mmp-camera.h                       |    5 ++
>>  3 files changed, 65 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h
>b/drivers/media/platform/marvell-ccic/mcam-core.h
>> index ca63010..86e634e 100755
>> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
>> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
>> @@ -88,6 +88,7 @@ struct mcam_frame_state {
>>   *          the dev_lock spinlock; they are marked as such by comments.
>>   *          dev_lock is also required for access to device registers.
>>   */
>> +#define NR_MCAM_CLK 4
>>  struct mcam_camera {
>>  	/*
>>  	 * These fields should be set by the platform code prior to
>> @@ -109,6 +110,9 @@ struct mcam_camera {
>>  	int lane;			/* lane number */
>>
>>  	struct clk *pll1;
>> +	/* clock tree support */
>> +	struct clk *clk[NR_MCAM_CLK];
>> +	int clk_num;
>>
>>  	/*
>>  	 * Callbacks from the core to the platform code.
>> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c
>b/drivers/media/platform/marvell-ccic/mmp-driver.c
>> index 603fa0a..2c4dce3 100755
>> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
>> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
>> @@ -104,6 +104,23 @@ static struct mmp_camera *mmpcam_find_device(struct
>platform_device *pdev)
>>  #define REG_CCIC_DCGCR		0x28	/* CCIC dyn clock gate ctrl reg */
>>  #define REG_CCIC_CRCR		0x50	/* CCIC clk reset ctrl reg	*/
>>
>> +static void mcam_clk_set(struct mcam_camera *mcam, int on)
>
>Personally, I would also make two functions out of this - "on" and "off,"
>but that's a matter of taste, perhaps.
>
[Albert Wang] That's we have planned to do in next version.

>> +{
>> +	unsigned int i;
>> +
>> +	if (on) {
>> +		for (i = 0; i < mcam->clk_num; i++) {
>> +			if (mcam->clk[i])
>> +				clk_enable(mcam->clk[i]);
>> +		}
>> +	} else {
>> +		for (i = mcam->clk_num; i > 0; i--) {
>> +			if (mcam->clk[i - 1])
>> +				clk_disable(mcam->clk[i - 1]);
>> +		}
>> +	}
>> +}
>> +
>>  /*
>>   * Power control.
>>   */
>> @@ -134,6 +151,8 @@ static void mmpcam_power_up(struct mcam_camera *mcam)
>>  	mdelay(5);
>>  	gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
>>  	mdelay(5);
>> +
>> +	mcam_clk_set(mcam, 1);
>>  }
>>
>>  static void mmpcam_power_down(struct mcam_camera *mcam)
>> @@ -151,6 +170,8 @@ static void mmpcam_power_down(struct mcam_camera
>*mcam)
>>  	pdata = cam->pdev->dev.platform_data;
>>  	gpio_set_value(pdata->sensor_power_gpio, 0);
>>  	gpio_set_value(pdata->sensor_reset_gpio, 0);
>> +
>> +	mcam_clk_set(mcam, 0);
>>  }
>>
>>  /*
>> @@ -202,7 +223,7 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
>>  	 * pll1 will never be changed, it is a fixed value
>>  	 */
>>
>> -	if (IS_ERR(mcam->pll1))
>> +	if (IS_ERR_OR_NULL(mcam->pll1))
>
>Why are you changing this? If this really were needed, you should do this
>already in the previous patch, where you add these lines. But I don't
>think this is a good idea, don't think Russell would like this :-) NULL is
>a valid clock. Only a negative error is a failure. In fact, if you like,
>you could initialise .pll1 to ERR_PTR(-EINVAL) in your previous patch in
>mmpcam_probe().
>
[Albert Wang] We will double check it if it's our mistake.
Thanks.

>>  		return;
>>
>>  	tx_clk_esc = clk_get_rate(mcam->pll1) / 1000000 / 12;
>> @@ -229,6 +250,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
>>  	return IRQ_RETVAL(handled);
>>  }
>>
>> +static void mcam_init_clk(struct mcam_camera *mcam,
>> +			struct mmp_camera_platform_data *pdata, int init)
>
>I don't think this "int init" makes sense. Please, remove the parameter
>and you actually don't need the de-initialisation, no reason to set
>num_clk = 0 before freeing memory.
>
[Albert Wang] OK, we will double check it.

>> +{
>> +	unsigned int i;
>> +
>> +	if (NR_MCAM_CLK < pdata->clk_num) {
>> +		dev_err(mcam->dev, "Too many mcam clocks defined\n");
>> +		mcam->clk_num = 0;
>> +		return;
>> +	}
>> +
>> +	if (init) {
>> +		for (i = 0; i < pdata->clk_num; i++) {
>> +			if (pdata->clk_name[i] != NULL) {
>> +				mcam->clk[i] = devm_clk_get(mcam->dev,
>> +						pdata->clk_name[i]);
>
>Sorry, no. Passing clock names in platform data doesn't look right to me.
>Clock names are a property of the consumer device, not of clock supplier.
>Also, your platform tells you to get clk_num clocks, you fail to get one
>of them, you don't continue trying the rest and just return with no error.
>This seems strange, usually a failure to get clocks, that the platform
>tells you to get, is fatal.
>
[Albert Wang] We will update it.

>> +				if (IS_ERR(mcam->clk[i])) {
>> +					dev_err(mcam->dev,
>> +						"Could not get clk: %s\n",
>> +						pdata->clk_name[i]);
>> +					mcam->clk_num = 0;
>> +					return;
>> +				}
>> +			}
>> +		}
>> +		mcam->clk_num = pdata->clk_num;
>> +	} else
>> +		mcam->clk_num = 0;
>> +}
>>
>>  static int mmpcam_probe(struct platform_device *pdev)
>>  {
>
>Thanks
>Guennadi
>---
>Guennadi Liakhovetski, Ph.D.
>Freelance Open-Source Software Developer
>http://www.open-technology.de/

Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver
  2013-01-01 16:56   ` Guennadi Liakhovetski
@ 2013-01-01 19:42     ` Albert Wang
  2013-01-01 20:03       ` Guennadi Liakhovetski
  2013-01-04  9:32     ` Libin Yang
  2013-01-10  7:53     ` Libin Yang
  2 siblings, 1 reply; 71+ messages in thread
From: Albert Wang @ 2013-01-01 19:42 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: corbet, linux-media, Libin Yang

Hi, Guennadi


>-----Original Message-----
>From: Guennadi Liakhovetski [mailto:g.liakhovetski@gmx.de]
>Sent: Wednesday, 02 January, 2013 00:56
>To: Albert Wang
>Cc: corbet@lwn.net; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for
>marvell-ccic driver
>
>On Sat, 15 Dec 2012, Albert Wang wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the new formats support for marvell-ccic.
>>
>> Signed-off-by: Albert Wang <twang13@marvell.com>
>> Signed-off-by: Libin Yang <lbyang@marvell.com>
>> ---
>>  drivers/media/platform/marvell-ccic/mcam-core.c |  175 ++++++++++++++++++-----
>>  drivers/media/platform/marvell-ccic/mcam-core.h |    6 +
>>  2 files changed, 149 insertions(+), 32 deletions(-)
>>
>> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c
>b/drivers/media/platform/marvell-ccic/mcam-core.c
>> index 3cc1d0c..a679917 100755
>> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
>> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
>
>[snip]
>
>> @@ -658,49 +708,85 @@ static inline void mcam_sg_restart(struct mcam_camera
>*cam)
>>   */
>>  static void mcam_ctlr_image(struct mcam_camera *cam)
>>  {
>> -	int imgsz;
>>  	struct v4l2_pix_format *fmt = &cam->pix_format;
>> +	u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
>> +
>> +	cam_dbg(cam, "camera: bytesperline = %d; height = %d\n",
>> +		fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
>> +	imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
>> +	imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
>> +
>> +	switch (fmt->pixelformat) {
>> +	case V4L2_PIX_FMT_YUYV:
>> +	case V4L2_PIX_FMT_UYVY:
>> +		widthy = fmt->width * 2;
>> +		widthuv = 0;
>> +		break;
>> +	case V4L2_PIX_FMT_JPEG:
>> +		imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
>> +		widthy = fmt->bytesperline;
>> +		widthuv = 0;
>> +		break;
>> +	case V4L2_PIX_FMT_YUV422P:
>> +	case V4L2_PIX_FMT_YUV420:
>> +	case V4L2_PIX_FMT_YVU420:
>> +		imgsz_w = (fmt->bytesperline * 4 / 3) & IMGSZ_H_MASK;
>> +		widthy = fmt->width;
>> +		widthuv = fmt->width / 2;
>
>I might be wrong, but the above doesn't look right to me. Firstly, YUV422P
>is a 4:2:2 format, whereas YUV420 and YVU420 are 4:2:0 formats, so, I
>would expect calculations for them to differ. Besides, bytesperline * 4 /
>3 doesn't look right for any of them. If this is what I think - total
>number of bytes per line, i.e., sizeimage / height, than shouldn't YAU422P
>have
>+		imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
>and the other two
>+		imgsz_w = (fmt->bytesperline * 3 / 2) & IMGSZ_H_MASK;
>? But maybe I'm wrong, please, double-check and confirm.
>
[Albert Wang] It looks they are both 12 bit planar format, they have same imgsz_w.
Anyway, we will double check it after back to office.

>> +		break;
>> +	default:
>> +		widthy = fmt->bytesperline;
>> +		widthuv = 0;
>> +	}
>> +
>> +	mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
>> +			IMGP_YP_MASK | IMGP_UVP_MASK);
>> +	mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w);
>> +	mcam_reg_write(cam, REG_IMGOFFSET, 0x0);
>>
>> -	imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
>> -		(fmt->bytesperline & IMGSZ_H_MASK);
>> -	mcam_reg_write(cam, REG_IMGSIZE, imgsz);
>> -	mcam_reg_write(cam, REG_IMGOFFSET, 0);
>> -	/* YPITCH just drops the last two bits */
>> -	mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
>> -			IMGP_YP_MASK);
>>  	/*
>>  	 * Tell the controller about the image format we are using.
>>  	 */
>> -	switch (cam->pix_format.pixelformat) {
>> +	switch (fmt->pixelformat) {
>> +	case V4L2_PIX_FMT_YUV422P:
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU,
>C0_DF_MASK);
>> +		break;
>> +	case V4L2_PIX_FMT_YUV420:
>> +	case V4L2_PIX_FMT_YVU420:
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU,
>C0_DF_MASK);
>> +		break;
>>  	case V4L2_PIX_FMT_YUYV:
>> -	    mcam_reg_write_mask(cam, REG_CTRL0,
>> -			    C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
>> -			    C0_DF_MASK);
>> -	    break;
>> -
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY,
>C0_DF_MASK);
>> +		break;
>> +	case V4L2_PIX_FMT_UYVY:
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV,
>C0_DF_MASK);
>> +		break;
>> +	case V4L2_PIX_FMT_JPEG:
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV,
>C0_DF_MASK);
>> +		break;
>>  	case V4L2_PIX_FMT_RGB444:
>> -	    mcam_reg_write_mask(cam, REG_CTRL0,
>> -			    C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
>> -			    C0_DF_MASK);
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB,
>C0_DF_MASK);
>>  		/* Alpha value? */
>> -	    break;
>> -
>> +		break;
>>  	case V4L2_PIX_FMT_RGB565:
>> -	    mcam_reg_write_mask(cam, REG_CTRL0,
>> -			    C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
>> -			    C0_DF_MASK);
>> -	    break;
>> -
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR,
>C0_DF_MASK);
>> +		break;
>>  	default:
>> -	    cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
>> -	    break;
>> +		cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat);
>> +		break;
>>  	}
>> +
>>  	/*
>>  	 * Make sure it knows we want to use hsync/vsync.
>>  	 */
>> -	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
>> -			C0_SIFM_MASK);
>> -
>> +	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
>>  	/*
>>  	 * This field controls the generation of EOF(DVP only)
>>  	 */
>> @@ -711,7 +797,6 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
>>  	}
>>  }
>>
>> -
>>  /*
>>   * Configure the controller for operation; caller holds the
>>   * device mutex.
>> @@ -984,11 +1069,37 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
>>  {
>>  	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
>>  	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
>> +	struct v4l2_pix_format *fmt = &cam->pix_format;
>>  	unsigned long flags;
>>  	int start;
>> +	dma_addr_t dma_handle;
>> +	u32 pixel_count = fmt->width * fmt->height;
>>
>>  	spin_lock_irqsave(&cam->dev_lock, flags);
>> +	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
>> +	BUG_ON(!dma_handle);
>>  	start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
>> +
>> +	switch (cam->pix_format.pixelformat) {
>> +	case V4L2_PIX_FMT_YUV422P:
>> +		mvb->yuv_p.y = dma_handle;
>
>The above line is common for all cases, perhaps just put it above switch?
>
[Albert Wang] OK, we can do that in next version.

>> +		mvb->yuv_p.u = mvb->yuv_p.y + pixel_count;
>> +		mvb->yuv_p.v = mvb->yuv_p.u + pixel_count / 2;
>> +		break;
>> +	case V4L2_PIX_FMT_YUV420:
>> +		mvb->yuv_p.y = dma_handle;
>> +		mvb->yuv_p.u = mvb->yuv_p.y + pixel_count;
>> +		mvb->yuv_p.v = mvb->yuv_p.u + pixel_count / 4;
>> +		break;
>> +	case V4L2_PIX_FMT_YVU420:
>> +		mvb->yuv_p.y = dma_handle;
>> +		mvb->yuv_p.v = mvb->yuv_p.y + pixel_count;
>> +		mvb->yuv_p.u = mvb->yuv_p.v + pixel_count / 4;
>> +		break;
>> +	default:
>> +		mvb->yuv_p.y = dma_handle;
>> +	}
>> +
>>  	list_add(&mvb->queue, &cam->buffers);
>>  	if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags))
>>  		mcam_sg_restart(cam);
>
>Thanks
>Guennadi
>---
>Guennadi Liakhovetski, Ph.D.
>Freelance Open-Source Software Developer
>http://www.open-technology.de/


Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver
  2013-01-01 19:42     ` Albert Wang
@ 2013-01-01 20:03       ` Guennadi Liakhovetski
  0 siblings, 0 replies; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-01 20:03 UTC (permalink / raw)
  To: Albert Wang; +Cc: corbet, linux-media, Libin Yang

Hi Albert

On Tue, 1 Jan 2013, Albert Wang wrote:

> >> +	case V4L2_PIX_FMT_YUV422P:
> >> +	case V4L2_PIX_FMT_YUV420:
> >> +	case V4L2_PIX_FMT_YVU420:
> >> +		imgsz_w = (fmt->bytesperline * 4 / 3) & IMGSZ_H_MASK;
> >> +		widthy = fmt->width;
> >> +		widthuv = fmt->width / 2;
> >
> >I might be wrong, but the above doesn't look right to me. Firstly, YUV422P
> >is a 4:2:2 format, whereas YUV420 and YVU420 are 4:2:0 formats, so, I
> >would expect calculations for them to differ. Besides, bytesperline * 4 /
> >3 doesn't look right for any of them. If this is what I think - total
> >number of bytes per line, i.e., sizeimage / height, than shouldn't YAU422P
> >have
> >+		imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
> >and the other two
> >+		imgsz_w = (fmt->bytesperline * 3 / 2) & IMGSZ_H_MASK;
> >? But maybe I'm wrong, please, double-check and confirm.
> >
> [Albert Wang] It looks they are both 12 bit planar format, they have same imgsz_w.
> Anyway, we will double check it after back to office.

_Both_ YUV420 and YVU420 - yes, but YUV422P is 16-bit.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check for marvell-ccic driver
  2012-12-15  9:57 ` [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check " Albert Wang
  2012-12-16 16:19   ` Jonathan Corbet
@ 2013-01-02  7:48   ` Guennadi Liakhovetski
  1 sibling, 0 replies; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-02  7:48 UTC (permalink / raw)
  To: Albert Wang; +Cc: corbet, linux-media, Libin Yang

On Sat, 15 Dec 2012, Albert Wang wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch adds the SOFx/EOFx pair check for marvell-ccic.
> 
> When switching format, the last EOF may not arrive when stop streamning.
> And the EOF will be detected in the next start streaming.
> 
> Must ensure clear the obsolete frame flags before every really start streaming.

Apart from the remark, that Jon has made:

Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>

Thanks
Guennadi

> 
> Signed-off-by: Albert Wang <twang13@marvell.com>
> Signed-off-by: Libin Yang <lbyang@marvell.com>
> ---
>  drivers/media/platform/marvell-ccic/mcam-core.c |   30 ++++++++++++++++++++---
>  1 file changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
> index a679917..c3c8873 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
> @@ -94,6 +94,9 @@ MODULE_PARM_DESC(buffer_mode,
>  #define CF_CONFIG_NEEDED 4	/* Must configure hardware */
>  #define CF_SINGLE_BUFFER 5	/* Running with a single buffer */
>  #define CF_SG_RESTART	 6	/* SG restart needed */
> +#define CF_FRAME_SOF0	 7	/* Frame 0 started */
> +#define CF_FRAME_SOF1	 8
> +#define CF_FRAME_SOF2	 9
>  
>  #define sensor_call(cam, o, f, args...) \
>  	v4l2_subdev_call(cam->sensor, o, f, ##args)
> @@ -251,8 +254,10 @@ static void mcam_reset_buffers(struct mcam_camera *cam)
>  	int i;
>  
>  	cam->next_buf = -1;
> -	for (i = 0; i < cam->nbufs; i++)
> +	for (i = 0; i < cam->nbufs; i++) {
>  		clear_bit(i, &cam->flags);
> +		clear_bit(CF_FRAME_SOF0 + i, &cam->flags);
> +	}
>  }
>  
>  static inline int mcam_needs_config(struct mcam_camera *cam)
> @@ -1134,6 +1139,7 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
>  static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
>  {
>  	struct mcam_camera *cam = vb2_get_drv_priv(vq);
> +	unsigned int frame;
>  
>  	if (cam->state != S_IDLE) {
>  		INIT_LIST_HEAD(&cam->buffers);
> @@ -1151,6 +1157,14 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
>  		cam->state = S_BUFWAIT;
>  		return 0;
>  	}
> +
> +	/*
> +	 * Ensure clear the obsolete frame flags
> +	 * before every really start streaming
> +	 */
> +	for (frame = 0; frame < cam->nbufs; frame++)
> +		clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
> +
>  	return mcam_read_setup(cam);
>  }
>  
> @@ -1875,9 +1889,11 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
>  	 * each time.
>  	 */
>  	for (frame = 0; frame < cam->nbufs; frame++)
> -		if (irqs & (IRQ_EOF0 << frame)) {
> +		if (irqs & (IRQ_EOF0 << frame) &&
> +			test_bit(CF_FRAME_SOF0 + frame, &cam->flags)) {
>  			mcam_frame_complete(cam, frame);
>  			handled = 1;
> +			clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
>  			if (cam->buffer_mode == B_DMA_sg)
>  				break;
>  		}
> @@ -1886,9 +1902,15 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
>  	 * code assumes that we won't get multiple frame interrupts
>  	 * at once; may want to rethink that.
>  	 */
> -	if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) {
> +	for (frame = 0; frame < cam->nbufs; frame++) {
> +		if (irqs & (IRQ_SOF0 << frame)) {
> +			set_bit(CF_FRAME_SOF0 + frame, &cam->flags);
> +			handled = IRQ_HANDLED;
> +		}
> +	}
> +
> +	if (handled == IRQ_HANDLED) {
>  		set_bit(CF_DMA_ACTIVE, &cam->flags);
> -		handled = 1;
>  		if (cam->buffer_mode == B_DMA_sg)
>  			mcam_ctlr_stop(cam);
>  	}
> -- 
> 1.7.9.5
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 08/15] [media] marvell-ccic: switch to resource managed allocation and request
  2012-12-15  9:57 ` [PATCH V3 08/15] [media] marvell-ccic: switch to resource managed allocation and request Albert Wang
  2012-12-16 16:20   ` Jonathan Corbet
@ 2013-01-02  8:00   ` Guennadi Liakhovetski
  1 sibling, 0 replies; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-02  8:00 UTC (permalink / raw)
  To: Albert Wang; +Cc: corbet, linux-media, Libin Yang

On Sat, 15 Dec 2012, Albert Wang wrote:

> From: Libin Yang <lbyang@marvell.com>
> 
> This patch switchs to resource managed allocation and request in mmp-driver.
> It can remove free resource operations.
> 
> Signed-off-by: Albert Wang <twang13@marvell.com>
> Signed-off-by: Libin Yang <lbyang@marvell.com>
> ---
>  drivers/media/platform/marvell-ccic/mmp-driver.c |   56 ++++++++--------------
>  1 file changed, 20 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
> index fec7cd8..40c243e 100755
> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
> @@ -315,7 +315,7 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	if (!pdata)
>  		return -ENODEV;
>  
> -	cam = kzalloc(sizeof(*cam), GFP_KERNEL);
> +	cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL);
>  	if (cam == NULL)
>  		return -ENOMEM;
>  	cam->pdev = pdev;
> @@ -343,14 +343,12 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	if (res == NULL) {
>  		dev_err(&pdev->dev, "no iomem resource!\n");
> -		ret = -ENODEV;
> -		goto out_free;
> +		return -ENODEV;
>  	}
> -	mcam->regs = ioremap(res->start, resource_size(res));
> +	mcam->regs = devm_request_and_ioremap(&pdev->dev, res);
>  	if (mcam->regs == NULL) {
>  		dev_err(&pdev->dev, "MMIO ioremap fail\n");
> -		ret = -ENODEV;
> -		goto out_free;
> +		return -ENODEV;
>  	}
>  	/*
>  	 * Power/clock memory is elsewhere; get it too.  Perhaps this
> @@ -359,14 +357,12 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>  	if (res == NULL) {
>  		dev_err(&pdev->dev, "no power resource!\n");
> -		ret = -ENODEV;
> -		goto out_unmap1;
> +		return -ENODEV;
>  	}
> -	cam->power_regs = ioremap(res->start, resource_size(res));
> +	cam->power_regs = devm_request_and_ioremap(&pdev->dev, res);
>  	if (cam->power_regs == NULL) {
>  		dev_err(&pdev->dev, "power MMIO ioremap fail\n");
> -		ret = -ENODEV;
> -		goto out_unmap1;
> +		return -ENODEV;
>  	}
>  
>  	mcam_init_clk(mcam, pdata, 1);
> @@ -376,25 +372,27 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	 */
>  	mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
>  	if (mcam->i2c_adapter == NULL) {
> -		ret = -ENODEV;
>  		dev_err(&pdev->dev, "No i2c adapter\n");
> -		goto out_unmap2;
> +		ret = -ENODEV;
> +		goto out_uninit_clk;

Looks good in principle, but it will become a bit simpler yet after you 
change your patch 03/15 to not use mcam_init_clk() for clock 
deinitialisation, but that's going to be just a minor modification.

Thanks
Guennadi

>  	}
>  	/*
>  	 * Sensor GPIO pins.
>  	 */
> -	ret = gpio_request(pdata->sensor_power_gpio, "cam-power");
> +	ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio,
> +					"cam-power");
>  	if (ret) {
>  		dev_err(&pdev->dev, "Can't get sensor power gpio %d",
>  				pdata->sensor_power_gpio);
> -		goto out_unmap2;
> +		goto out_uninit_clk;
>  	}
>  	gpio_direction_output(pdata->sensor_power_gpio, 0);
> -	ret = gpio_request(pdata->sensor_reset_gpio, "cam-reset");
> +	ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio,
> +					"cam-reset");
>  	if (ret) {
>  		dev_err(&pdev->dev, "Can't get sensor reset gpio %d",
>  				pdata->sensor_reset_gpio);
> -		goto out_gpio;
> +		goto out_uninit_clk;
>  	}
>  	gpio_direction_output(pdata->sensor_reset_gpio, 0);
>  
> @@ -404,7 +402,7 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	mmpcam_power_up(mcam);
>  	ret = mccic_register(mcam);
>  	if (ret)
> -		goto out_gpio2;
> +		goto out_power_down;
>  	/*
>  	 * Finally, set up our IRQ now that the core is ready to
>  	 * deal with it.
> @@ -415,8 +413,8 @@ static int mmpcam_probe(struct platform_device *pdev)
>  		goto out_unregister;
>  	}
>  	cam->irq = res->start;
> -	ret = request_irq(cam->irq, mmpcam_irq, IRQF_SHARED,
> -			"mmp-camera", mcam);
> +	ret = devm_request_irq(&pdev->dev, cam->irq, mmpcam_irq, IRQF_SHARED,
> +					"mmp-camera", mcam);
>  	if (ret == 0) {
>  		mmpcam_add_device(cam);
>  		return 0;
> @@ -424,18 +422,10 @@ static int mmpcam_probe(struct platform_device *pdev)
>  
>  out_unregister:
>  	mccic_shutdown(mcam);
> -out_gpio2:
> +out_power_down:
>  	mmpcam_power_down(mcam);
> -	gpio_free(pdata->sensor_reset_gpio);
> -out_gpio:
> -	gpio_free(pdata->sensor_power_gpio);
> -out_unmap2:
> +out_uninit_clk:
>  	mcam_init_clk(mcam, pdata, 0);
> -	iounmap(cam->power_regs);
> -out_unmap1:
> -	iounmap(mcam->regs);
> -out_free:
> -	kfree(cam);
>  	return ret;
>  }
>  
> @@ -446,16 +436,10 @@ static int mmpcam_remove(struct mmp_camera *cam)
>  	struct mmp_camera_platform_data *pdata;
>  
>  	mmpcam_remove_device(cam);
> -	free_irq(cam->irq, mcam);
>  	mccic_shutdown(mcam);
>  	mmpcam_power_down(mcam);
>  	pdata = cam->pdev->dev.platform_data;
> -	gpio_free(pdata->sensor_reset_gpio);
> -	gpio_free(pdata->sensor_power_gpio);
> -	iounmap(cam->power_regs);
> -	iounmap(mcam->regs);
>  	mcam_init_clk(mcam, pdata, 0);
> -	kfree(cam);
>  	return 0;
>  }
>  
> -- 
> 1.7.9.5
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-ccic driver
  2012-12-16 16:24   ` Jonathan Corbet
  2012-12-16 22:04     ` Albert Wang
@ 2013-01-02  8:16     ` Guennadi Liakhovetski
  1 sibling, 0 replies; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-02  8:16 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: Albert Wang, linux-media, Libin Yang

On Sun, 16 Dec 2012, Jonathan Corbet wrote:

> On Sat, 15 Dec 2012 17:57:58 +0800
> Albert Wang <twang13@marvell.com> wrote:
> 
> > This patch adds get_mcam() inline function which is prepared for
> > adding soc_camera support in marvell-ccic driver
> 
> Time for a bikeshed moment: "get" generally is understood to mean
> incrementing a reference count in kernel code.  Can it have a name like
> vbq_to_mcam() instead?
> 
> Also:
> 
> > @@ -1073,14 +1073,17 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
> >  static void mcam_vb_buf_queue(struct vb2_buffer *vb)
> >  {
> >  	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
> > -	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
> > +	struct mcam_camera *cam = get_mcam(vb->vb2_queue);
> >  	struct v4l2_pix_format *fmt = &cam->pix_format;
> >  	unsigned long flags;
> >  	int start;
> >  	dma_addr_t dma_handle;
> > +	unsigned long size;
> >  	u32 pixel_count = fmt->width * fmt->height;
> >  
> >  	spin_lock_irqsave(&cam->dev_lock, flags);
> > +	size = vb2_plane_size(vb, 0);
> > +	vb2_set_plane_payload(vb, 0, size);
> >  	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
> >  	BUG_ON(!dma_handle);
> >  	start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
> 
> There is an unrelated change here that belongs in a separate patch.

Right, agree.

Thanks
Guennadi

> > @@ -1138,9 +1141,12 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
> >   */
> >  static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
> >  {
> > -	struct mcam_camera *cam = vb2_get_drv_priv(vq);
> > +	struct mcam_camera *cam = get_mcam(vq);
> >  	unsigned int frame;
> >  
> > +	if (count < 2)
> > +		return -EINVAL;
> > +
> 
> Here too - unrelated change.
> 
> >  	if (cam->state != S_IDLE) {
> >  		INIT_LIST_HEAD(&cam->buffers);
> >  		return -EINVAL;
> > @@ -1170,7 +1176,7 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
> >  
> >  static int mcam_vb_stop_streaming(struct vb2_queue *vq)
> >  {
> > -	struct mcam_camera *cam = vb2_get_drv_priv(vq);
> > +	struct mcam_camera *cam = get_mcam(vq);
> >  	unsigned long flags;
> >  
> >  	if (cam->state == S_BUFWAIT) {
> > @@ -1181,6 +1187,7 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
> >  	if (cam->state != S_STREAMING)
> >  		return -EINVAL;
> >  	mcam_ctlr_stop_dma(cam);
> > +	cam->state = S_IDLE;
> 
> ...and also here ...
> 
> jon
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2012-12-16 21:51     ` Albert Wang
@ 2013-01-03 17:37       ` Nicolas THERY
  2013-01-03 19:27         ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Nicolas THERY @ 2013-01-03 17:37 UTC (permalink / raw)
  To: Albert Wang; +Cc: Jonathan Corbet, g.liakhovetski, linux-media, Libin Yang



On 2012-12-16 22:51, Albert Wang wrote:
[...]
>>>
>>> +static void mcam_clk_set(struct mcam_camera *mcam, int on)
>>> +{
>>> +	unsigned int i;
>>> +
>>> +	if (on) {
>>> +		for (i = 0; i < mcam->clk_num; i++) {
>>> +			if (mcam->clk[i])
>>> +				clk_enable(mcam->clk[i]);
>>> +		}
>>> +	} else {
>>> +		for (i = mcam->clk_num; i > 0; i--) {
>>> +			if (mcam->clk[i - 1])
>>> +				clk_disable(mcam->clk[i - 1]);
>>> +		}
>>> +	}
>>> +}
>>
>> A couple of minor comments:
>>
>> - This function is always called with a constant value for "on".  It would
>>   be easier to read (and less prone to unfortunate brace errors) if it
>>   were just two functions: mcam_clk_enable() and mcam_clk_disable().
>>
> [Albert Wang] OK, that's fine to split it to 2 functions. :)
> 
>> - I'd write the second for loop as:
>>
>> 	for (i = mcal->clk_num - 1; i >= 0; i==) {
>>
>>   just to match the values used in the other direction and avoid the
>>   subscript arithmetic.
>>
> [Albert Wang] Yes, we can improve it. :)

Bewar: i is unsigned so testing i >= 0 will loop forever.

[...]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2013-01-03 17:37       ` Nicolas THERY
@ 2013-01-03 19:27         ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2013-01-03 19:27 UTC (permalink / raw)
  To: Nicolas THERY; +Cc: Jonathan Corbet, g.liakhovetski, linux-media, Libin Yang

Hi, Nicolas

Thank you for your reminder. :)

Happy New Year!

>-----Original Message-----
>From: Nicolas THERY [mailto:nicolas.thery@st.com]
>Sent: Friday, 04 January, 2013 01:38
>To: Albert Wang
>Cc: Jonathan Corbet; g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-
>ccic driver
>
>
>
>On 2012-12-16 22:51, Albert Wang wrote:
>[...]
>>>>
>>>> +static void mcam_clk_set(struct mcam_camera *mcam, int on)
>>>> +{
>>>> +	unsigned int i;
>>>> +
>>>> +	if (on) {
>>>> +		for (i = 0; i < mcam->clk_num; i++) {
>>>> +			if (mcam->clk[i])
>>>> +				clk_enable(mcam->clk[i]);
>>>> +		}
>>>> +	} else {
>>>> +		for (i = mcam->clk_num; i > 0; i--) {
>>>> +			if (mcam->clk[i - 1])
>>>> +				clk_disable(mcam->clk[i - 1]);
>>>> +		}
>>>> +	}
>>>> +}
>>>
>>> A couple of minor comments:
>>>
>>> - This function is always called with a constant value for "on".  It would
>>>   be easier to read (and less prone to unfortunate brace errors) if it
>>>   were just two functions: mcam_clk_enable() and mcam_clk_disable().
>>>
>> [Albert Wang] OK, that's fine to split it to 2 functions. :)
>>
>>> - I'd write the second for loop as:
>>>
>>> 	for (i = mcal->clk_num - 1; i >= 0; i==) {
>>>
>>>   just to match the values used in the other direction and avoid the
>>>   subscript arithmetic.
>>>
>> [Albert Wang] Yes, we can improve it. :)
>
>Bewar: i is unsigned so testing i >= 0 will loop forever.
>
[Albert Wang] Yes, it looks my original code can work. :)
>[...]

Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2013-01-01 16:05   ` Guennadi Liakhovetski
  2013-01-01 19:36     ` Albert Wang
@ 2013-01-04  5:42     ` Libin Yang
  2013-01-04 10:25       ` Guennadi Liakhovetski
  1 sibling, 1 reply; 71+ messages in thread
From: Libin Yang @ 2013-01-04  5:42 UTC (permalink / raw)
  To: Guennadi Liakhovetski, Albert Wang; +Cc: corbet, linux-media

Hi Guennadi,

Thanks for your review. Please see my comments below.

>-----Original Message-----
>From: Guennadi Liakhovetski [mailto:g.liakhovetski@gmx.de]
>Sent: Wednesday, January 02, 2013 12:06 AM
>To: Albert Wang
>Cc: corbet@lwn.net; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for
>marvell-ccic driver
>
>On Sat, 15 Dec 2012, Albert Wang wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the clock tree support for marvell-ccic.
>>
>> Each board may require different clk enabling sequence.
>> Developer need add the clk_name in correct sequence in board driver
>> to use this feature.
>>
>> Signed-off-by: Libin Yang <lbyang@marvell.com>
>> Signed-off-by: Albert Wang <twang13@marvell.com>
>> ---
>>  drivers/media/platform/marvell-ccic/mcam-core.h  |    4 ++
>>  drivers/media/platform/marvell-ccic/mmp-driver.c |   57 +++++++++++++++++++++-
>>  include/media/mmp-camera.h                       |    5 ++
>>  3 files changed, 65 insertions(+), 1 deletion(-)
>>
[snip]

>> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c
>b/drivers/media/platform/marvell-ccic/mmp-driver.c
>> index 603fa0a..2c4dce3 100755
>> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
>> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
[snip]

>> +
>> +	mcam_clk_set(mcam, 0);
>>  }
>>
>>  /*
>> @@ -202,7 +223,7 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
>>  	 * pll1 will never be changed, it is a fixed value
>>  	 */
>>
>> -	if (IS_ERR(mcam->pll1))
>> +	if (IS_ERR_OR_NULL(mcam->pll1))
>
>Why are you changing this? If this really were needed, you should do this
>already in the previous patch, where you add these lines. But I don't
>think this is a good idea, don't think Russell would like this :-) NULL is
>a valid clock. Only a negative error is a failure. In fact, if you like,
>you could initialise .pll1 to ERR_PTR(-EINVAL) in your previous patch in
>mmpcam_probe().

In the below code, we will use platform related clk_get_rate() to get the rate. 
In the function we do not judge the clk is NULL or not. If we do not judge here, 
we need judge for NULL in the later, otherwise, error may happen. Or do you
think it is better that we should judge the pointer in the function clk_get_rate()?

>
>>  		return;
>>
>>  	tx_clk_esc = clk_get_rate(mcam->pll1) / 1000000 / 12;
>> @@ -229,6 +250,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
>>  	return IRQ_RETVAL(handled);
>>  }
>>
>> +static void mcam_init_clk(struct mcam_camera *mcam,
>> +			struct mmp_camera_platform_data *pdata, int init)
>
>I don't think this "int init" makes sense. Please, remove the parameter
>and you actually don't need the de-initialisation, no reason to set
>num_clk = 0 before freeing memory.

Yes, the init parameter is not good here, which make confusion.
The driver de-initiatives the clks because
I want to make sure the driver will never enable the clks after de-initialization.
After second consideration based on your suggestion, I will remove
de-initialization, because this scenario will never happen.

>
>> +{
>> +	unsigned int i;
>> +
>> +	if (NR_MCAM_CLK < pdata->clk_num) {
>> +		dev_err(mcam->dev, "Too many mcam clocks defined\n");
>> +		mcam->clk_num = 0;
>> +		return;
>> +	}
>> +
>> +	if (init) {
>> +		for (i = 0; i < pdata->clk_num; i++) {
>> +			if (pdata->clk_name[i] != NULL) {
>> +				mcam->clk[i] = devm_clk_get(mcam->dev,
>> +						pdata->clk_name[i]);
>
>Sorry, no. Passing clock names in platform data doesn't look right to me.
>Clock names are a property of the consumer device, not of clock supplier.
>Also, your platform tells you to get clk_num clocks, you fail to get one
>of them, you don't continue trying the rest and just return with no error.
>This seems strange, usually a failure to get clocks, that the platform
>tells you to get, is fatal.

I agree that after failing to get the clk, we should return error
instead of just returning. 

For the clock names, the clock names are different on different platforms.
So we need platform data passing the clock names. Do you have any suggestions?

>
>> +				if (IS_ERR(mcam->clk[i])) {
>> +					dev_err(mcam->dev,
>> +						"Could not get clk: %s\n",
>> +						pdata->clk_name[i]);
>> +					mcam->clk_num = 0;
>> +					return;
>> +				}
>> +			}
>> +		}
>> +		mcam->clk_num = pdata->clk_num;
>> +	} else
>> +		mcam->clk_num = 0;
>> +}
>>
>>  static int mmpcam_probe(struct platform_device *pdev)
>>  {
>
>Thanks
>Guennadi
>---
>Guennadi Liakhovetski, Ph.D.
>Freelance Open-Source Software Developer
>http://www.open-technology.de/

Regards,
Libin

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver
  2013-01-01 16:56   ` Guennadi Liakhovetski
  2013-01-01 19:42     ` Albert Wang
@ 2013-01-04  9:32     ` Libin Yang
  2013-01-10  7:53     ` Libin Yang
  2 siblings, 0 replies; 71+ messages in thread
From: Libin Yang @ 2013-01-04  9:32 UTC (permalink / raw)
  To: Guennadi Liakhovetski, Albert Wang; +Cc: corbet, linux-media

Hi Guennadi,

Please see my comments below.

>-----Original Message-----
>From: Guennadi Liakhovetski [mailto:g.liakhovetski@gmx.de]
>Sent: Wednesday, January 02, 2013 12:56 AM
>To: Albert Wang
>Cc: corbet@lwn.net; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for
>marvell-ccic driver
>
>On Sat, 15 Dec 2012, Albert Wang wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the new formats support for marvell-ccic.
>>
>> Signed-off-by: Albert Wang <twang13@marvell.com>
>> Signed-off-by: Libin Yang <lbyang@marvell.com>
>> ---
>>  drivers/media/platform/marvell-ccic/mcam-core.c |  175 ++++++++++++++++++-----
>>  drivers/media/platform/marvell-ccic/mcam-core.h |    6 +
>>  2 files changed, 149 insertions(+), 32 deletions(-)
>>
>> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c
>b/drivers/media/platform/marvell-ccic/mcam-core.c
>> index 3cc1d0c..a679917 100755
>> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
>> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
>
>[snip]
>
>> @@ -658,49 +708,85 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
>>   */
>>  static void mcam_ctlr_image(struct mcam_camera *cam)
>>  {
>> -	int imgsz;
>>  	struct v4l2_pix_format *fmt = &cam->pix_format;
>> +	u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
>> +
>> +	cam_dbg(cam, "camera: bytesperline = %d; height = %d\n",
>> +		fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
>> +	imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
>> +	imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
>> +
>> +	switch (fmt->pixelformat) {
>> +	case V4L2_PIX_FMT_YUYV:
>> +	case V4L2_PIX_FMT_UYVY:
>> +		widthy = fmt->width * 2;
>> +		widthuv = 0;
>> +		break;
>> +	case V4L2_PIX_FMT_JPEG:
>> +		imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
>> +		widthy = fmt->bytesperline;
>> +		widthuv = 0;
>> +		break;
>> +	case V4L2_PIX_FMT_YUV422P:
>> +	case V4L2_PIX_FMT_YUV420:
>> +	case V4L2_PIX_FMT_YVU420:
>> +		imgsz_w = (fmt->bytesperline * 4 / 3) & IMGSZ_H_MASK;
>> +		widthy = fmt->width;
>> +		widthuv = fmt->width / 2;
>
>I might be wrong, but the above doesn't look right to me. Firstly, YUV422P
>is a 4:2:2 format, whereas YUV420 and YVU420 are 4:2:0 formats, so, I
>would expect calculations for them to differ. Besides, bytesperline * 4 /
>3 doesn't look right for any of them. If this is what I think - total
>number of bytes per line, i.e., sizeimage / height, than shouldn't YAU422P
>have
>+		imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
>and the other two
>+		imgsz_w = (fmt->bytesperline * 3 / 2) & IMGSZ_H_MASK;
>? But maybe I'm wrong, please, double-check and confirm.
>

Basically, I agree with you. We are checking with our HW team how the value is calculated out. And we will update here as soon as we get the answer.

>> +		break;
>> +	default:
>> +		widthy = fmt->bytesperline;
>> +		widthuv = 0;
>> +	}
>> +
>> +	mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
>> +			IMGP_YP_MASK | IMGP_UVP_MASK);
>> +	mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w);
>> +	mcam_reg_write(cam, REG_IMGOFFSET, 0x0);
>>
>> -	imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
>> -		(fmt->bytesperline & IMGSZ_H_MASK);
>> -	mcam_reg_write(cam, REG_IMGSIZE, imgsz);
>> -	mcam_reg_write(cam, REG_IMGOFFSET, 0);
>> -	/* YPITCH just drops the last two bits */
>> -	mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
>> -			IMGP_YP_MASK);
>>  	/*
>>  	 * Tell the controller about the image format we are using.
>>  	 */
>> -	switch (cam->pix_format.pixelformat) {
>> +	switch (fmt->pixelformat) {
>> +	case V4L2_PIX_FMT_YUV422P:
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU,
>C0_DF_MASK);
>> +		break;
>> +	case V4L2_PIX_FMT_YUV420:
>> +	case V4L2_PIX_FMT_YVU420:
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
>> +		break;
>>  	case V4L2_PIX_FMT_YUYV:
>> -	    mcam_reg_write_mask(cam, REG_CTRL0,
>> -			    C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
>> -			    C0_DF_MASK);
>> -	    break;
>> -
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
>> +		break;
>> +	case V4L2_PIX_FMT_UYVY:
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
>> +		break;
>> +	case V4L2_PIX_FMT_JPEG:
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
>> +		break;
>>  	case V4L2_PIX_FMT_RGB444:
>> -	    mcam_reg_write_mask(cam, REG_CTRL0,
>> -			    C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
>> -			    C0_DF_MASK);
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
>>  		/* Alpha value? */
>> -	    break;
>> -
>> +		break;
>>  	case V4L2_PIX_FMT_RGB565:
>> -	    mcam_reg_write_mask(cam, REG_CTRL0,
>> -			    C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
>> -			    C0_DF_MASK);
>> -	    break;
>> -
>> +		mcam_reg_write_mask(cam, REG_CTRL0,
>> +			C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
>> +		break;
>>  	default:
>> -	    cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
>> -	    break;
>> +		cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat);
>> +		break;
>>  	}
>> +
>>  	/*
>>  	 * Make sure it knows we want to use hsync/vsync.
>>  	 */
>> -	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
>> -			C0_SIFM_MASK);
>> -
>> +	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
>>  	/*
>>  	 * This field controls the generation of EOF(DVP only)
>>  	 */
>> @@ -711,7 +797,6 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
>>  	}
>>  }
>>
>> -
>>  /*
>>   * Configure the controller for operation; caller holds the
>>   * device mutex.
>> @@ -984,11 +1069,37 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
>>  {
>>  	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
>>  	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
>> +	struct v4l2_pix_format *fmt = &cam->pix_format;
>>  	unsigned long flags;
>>  	int start;
>> +	dma_addr_t dma_handle;
>> +	u32 pixel_count = fmt->width * fmt->height;
>>
>>  	spin_lock_irqsave(&cam->dev_lock, flags);
>> +	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
>> +	BUG_ON(!dma_handle);
>>  	start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
>> +
>> +	switch (cam->pix_format.pixelformat) {
>> +	case V4L2_PIX_FMT_YUV422P:
>> +		mvb->yuv_p.y = dma_handle;
>
>The above line is common for all cases, perhaps just put it above switch?
>
>> +		mvb->yuv_p.u = mvb->yuv_p.y + pixel_count;
>> +		mvb->yuv_p.v = mvb->yuv_p.u + pixel_count / 2;
>> +		break;
>> +	case V4L2_PIX_FMT_YUV420:
>> +		mvb->yuv_p.y = dma_handle;
>> +		mvb->yuv_p.u = mvb->yuv_p.y + pixel_count;
>> +		mvb->yuv_p.v = mvb->yuv_p.u + pixel_count / 4;
>> +		break;
>> +	case V4L2_PIX_FMT_YVU420:
>> +		mvb->yuv_p.y = dma_handle;
>> +		mvb->yuv_p.v = mvb->yuv_p.y + pixel_count;
>> +		mvb->yuv_p.u = mvb->yuv_p.v + pixel_count / 4;
>> +		break;
>> +	default:
>> +		mvb->yuv_p.y = dma_handle;
>> +	}
>> +
>>  	list_add(&mvb->queue, &cam->buffers);
>>  	if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags))
>>  		mcam_sg_restart(cam);
>
>Thanks
>Guennadi
>---
>Guennadi Liakhovetski, Ph.D.
>Freelance Open-Source Software Developer
>http://www.open-technology.de/

Regards,
Libin

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2013-01-04  5:42     ` Libin Yang
@ 2013-01-04 10:25       ` Guennadi Liakhovetski
  2013-01-05  3:12         ` Libin Yang
  0 siblings, 1 reply; 71+ messages in thread
From: Guennadi Liakhovetski @ 2013-01-04 10:25 UTC (permalink / raw)
  To: Libin Yang; +Cc: Albert Wang, corbet, linux-media

Hi Libin

On Thu, 3 Jan 2013, Libin Yang wrote:

> Hi Guennadi,
> 
> Thanks for your review. Please see my comments below.
> 
> >-----Original Message-----
> >From: Guennadi Liakhovetski [mailto:g.liakhovetski@gmx.de]
> >Sent: Wednesday, January 02, 2013 12:06 AM
> >To: Albert Wang
> >Cc: corbet@lwn.net; linux-media@vger.kernel.org; Libin Yang
> >Subject: Re: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for
> >marvell-ccic driver
> >
> >On Sat, 15 Dec 2012, Albert Wang wrote:
> >
> >> From: Libin Yang <lbyang@marvell.com>
> >>
> >> This patch adds the clock tree support for marvell-ccic.
> >>
> >> Each board may require different clk enabling sequence.
> >> Developer need add the clk_name in correct sequence in board driver
> >> to use this feature.
> >>
> >> Signed-off-by: Libin Yang <lbyang@marvell.com>
> >> Signed-off-by: Albert Wang <twang13@marvell.com>
> >> ---
> >>  drivers/media/platform/marvell-ccic/mcam-core.h  |    4 ++
> >>  drivers/media/platform/marvell-ccic/mmp-driver.c |   57 +++++++++++++++++++++-
> >>  include/media/mmp-camera.h                       |    5 ++
> >>  3 files changed, 65 insertions(+), 1 deletion(-)
> >>
> [snip]
> 
> >> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c
> >b/drivers/media/platform/marvell-ccic/mmp-driver.c
> >> index 603fa0a..2c4dce3 100755
> >> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
> >> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
> [snip]
> 
> >> +
> >> +	mcam_clk_set(mcam, 0);
> >>  }
> >>
> >>  /*
> >> @@ -202,7 +223,7 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
> >>  	 * pll1 will never be changed, it is a fixed value
> >>  	 */
> >>
> >> -	if (IS_ERR(mcam->pll1))
> >> +	if (IS_ERR_OR_NULL(mcam->pll1))
> >
> >Why are you changing this? If this really were needed, you should do this
> >already in the previous patch, where you add these lines. But I don't
> >think this is a good idea, don't think Russell would like this :-) NULL is
> >a valid clock. Only a negative error is a failure. In fact, if you like,
> >you could initialise .pll1 to ERR_PTR(-EINVAL) in your previous patch in
> >mmpcam_probe().
> 
> In the below code, we will use platform related clk_get_rate() to get the rate. 
> In the function we do not judge the clk is NULL or not. If we do not judge here, 
> we need judge for NULL in the later, otherwise, error may happen. Or do you
> think it is better that we should judge the pointer in the function clk_get_rate()?

I think, there is a problem here. Firstly, if you really want to check for 
"clock API not supported" or a similar type of condition by checking 
get_clk() return value for NULL, you should do this immediately in the 
patch, where you add this code: in "[PATCH V3 02/15] [media] marvell-ccic: 
add MIPI support for marvell-ccic driver." Secondly, it's probably ok to 
check this to say - no clock, co reason to try to use it, in which case 
you skip calculating your ->dphy[2] value, and it remains == 0, 
presumably, is this what you want to have? But, I think, there's a bigger 
problem in your patch #02/15: you don't check for mcam->dphy != NULL. So, 
I think, this has to be fixed in that patch, not here.

[snip]

> >> +{
> >> +	unsigned int i;
> >> +
> >> +	if (NR_MCAM_CLK < pdata->clk_num) {
> >> +		dev_err(mcam->dev, "Too many mcam clocks defined\n");
> >> +		mcam->clk_num = 0;
> >> +		return;
> >> +	}
> >> +
> >> +	if (init) {
> >> +		for (i = 0; i < pdata->clk_num; i++) {
> >> +			if (pdata->clk_name[i] != NULL) {
> >> +				mcam->clk[i] = devm_clk_get(mcam->dev,
> >> +						pdata->clk_name[i]);
> >
> >Sorry, no. Passing clock names in platform data doesn't look right to me.
> >Clock names are a property of the consumer device, not of clock supplier.
> >Also, your platform tells you to get clk_num clocks, you fail to get one
> >of them, you don't continue trying the rest and just return with no error.
> >This seems strange, usually a failure to get clocks, that the platform
> >tells you to get, is fatal.
> 
> I agree that after failing to get the clk, we should return error
> instead of just returning. 
> 
> For the clock names, the clock names are different on different platforms.
> So we need platform data passing the clock names. Do you have any suggestions?

I think you should use the same names on all platforms. As I said, those 
are names of _consumer_ clocks, not of supplier. And the consumer on all 
platforms is the same - your camera unit. If you cannot remove existing 
clock entries for compatibility reasons you, probably, can just add clock 
lookup entries for them. In the _very_ worst case, maybe make a table of 
clock names and, depending on the SoC type use one of them, but that's 
really also not very apropriate, not sure, whether that would be accepted.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for marvell-ccic driver
  2013-01-04 10:25       ` Guennadi Liakhovetski
@ 2013-01-05  3:12         ` Libin Yang
  0 siblings, 0 replies; 71+ messages in thread
From: Libin Yang @ 2013-01-05  3:12 UTC (permalink / raw)
  To: Guennadi Liakhovetski; +Cc: Albert Wang, corbet, linux-media

Hi Guennadi,

Please see my comments below.

>-----Original Message-----
>From: Guennadi Liakhovetski [mailto:g.liakhovetski@gmx.de]
>Sent: Friday, January 04, 2013 6:25 PM
>To: Libin Yang
>Cc: Albert Wang; corbet@lwn.net; linux-media@vger.kernel.org
>Subject: RE: [PATCH V3 03/15] [media] marvell-ccic: add clock tree support for
>marvell-ccic driver
>
>Hi Libin
>
>On Thu, 3 Jan 2013, Libin Yang wrote:
>
>> Hi Guennadi,
>>
>> Thanks for your review. Please see my comments below.
>>

[snip]

>> >>  /*
>> >> @@ -202,7 +223,7 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
>> >>  	 * pll1 will never be changed, it is a fixed value
>> >>  	 */
>> >>
>> >> -	if (IS_ERR(mcam->pll1))
>> >> +	if (IS_ERR_OR_NULL(mcam->pll1))
>> >
>> >Why are you changing this? If this really were needed, you should do this
>> >already in the previous patch, where you add these lines. But I don't
>> >think this is a good idea, don't think Russell would like this :-) NULL is
>> >a valid clock. Only a negative error is a failure. In fact, if you like,
>> >you could initialise .pll1 to ERR_PTR(-EINVAL) in your previous patch in
>> >mmpcam_probe().
>>
>> In the below code, we will use platform related clk_get_rate() to get the rate.
>> In the function we do not judge the clk is NULL or not. If we do not judge here,
>> we need judge for NULL in the later, otherwise, error may happen. Or do you
>> think it is better that we should judge the pointer in the function clk_get_rate()?
>
>I think, there is a problem here. Firstly, if you really want to check for
>"clock API not supported" or a similar type of condition by checking
>get_clk() return value for NULL, you should do this immediately in the
>patch, where you add this code: in "[PATCH V3 02/15] [media] marvell-ccic:
>add MIPI support for marvell-ccic driver." Secondly, it's probably ok to
>check this to say - no clock, co reason to try to use it, in which case
>you skip calculating your ->dphy[2] value, and it remains == 0,
>presumably, is this what you want to have? But, I think, there's a bigger
>problem in your patch #02/15: you don't check for mcam->dphy != NULL. So,
>I think, this has to be fixed in that patch, not here.

Your understanding is right. We will try to use the default value if the pll1
is not available. So we just return if pll1 is error or NULL. And mostly the
default value should work. And this reminds me that there is a little issue:
we should not return fail in the mcam_v4l_open() function when failing
to get the pll1 clk because we can also use the default values.

What I plan to code in the next version is:
1. Remove the judgement of (IS_ERR(cam->pll1)) in the open function when
get the clk.
2. Still use IS_ERR_OR_NULL(mcam->pll1), so that we can use the default
vaule if pll1 is not available.

What do you think of it?

mcam->dphy != NULL may be a critical issue. Thanks for digging out this bug.
We will fix it in the next version.

>
>[snip]
>
>> >> +{
>> >> +	unsigned int i;
>> >> +
>> >> +	if (NR_MCAM_CLK < pdata->clk_num) {
>> >> +		dev_err(mcam->dev, "Too many mcam clocks defined\n");
>> >> +		mcam->clk_num = 0;
>> >> +		return;
>> >> +	}
>> >> +
>> >> +	if (init) {
>> >> +		for (i = 0; i < pdata->clk_num; i++) {
>> >> +			if (pdata->clk_name[i] != NULL) {
>> >> +				mcam->clk[i] = devm_clk_get(mcam->dev,
>> >> +						pdata->clk_name[i]);
>> >
>> >Sorry, no. Passing clock names in platform data doesn't look right to me.
>> >Clock names are a property of the consumer device, not of clock supplier.
>> >Also, your platform tells you to get clk_num clocks, you fail to get one
>> >of them, you don't continue trying the rest and just return with no error.
>> >This seems strange, usually a failure to get clocks, that the platform
>> >tells you to get, is fatal.
>>
>> I agree that after failing to get the clk, we should return error
>> instead of just returning.
>>
>> For the clock names, the clock names are different on different platforms.
>> So we need platform data passing the clock names. Do you have any suggestions?
>
>I think you should use the same names on all platforms. As I said, those
>are names of _consumer_ clocks, not of supplier. And the consumer on all
>platforms is the same - your camera unit. If you cannot remove existing
>clock entries for compatibility reasons you, probably, can just add clock
>lookup entries for them. In the _very_ worst case, maybe make a table of
>clock names and, depending on the SoC type use one of them, but that's
>really also not very apropriate, not sure, whether that would be accepted.

OK, I see. I will use the names directly in the camera driver without 
getting them from the platform data.

>
>Thanks
>Guennadi
>---
>Guennadi Liakhovetski, Ph.D.
>Freelance Open-Source Software Developer
>http://www.open-technology.de/

Regards,
Libin

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver
  2013-01-01 16:56   ` Guennadi Liakhovetski
  2013-01-01 19:42     ` Albert Wang
  2013-01-04  9:32     ` Libin Yang
@ 2013-01-10  7:53     ` Libin Yang
  2 siblings, 0 replies; 71+ messages in thread
From: Libin Yang @ 2013-01-10  7:53 UTC (permalink / raw)
  To: Guennadi Liakhovetski, Albert Wang; +Cc: corbet, linux-media

Hi Guennadi,

Below is the update for widthy, widthuv and imgsz_w setting.

>-----Original Message-----
>From: Guennadi Liakhovetski [mailto:g.liakhovetski@gmx.de]
>Sent: Wednesday, January 02, 2013 12:56 AM
>To: Albert Wang
>Cc: corbet@lwn.net; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 06/15] [media] marvell-ccic: add new formats support for
>marvell-ccic driver
>
>On Sat, 15 Dec 2012, Albert Wang wrote:
>
>> From: Libin Yang <lbyang@marvell.com>
>>
>> This patch adds the new formats support for marvell-ccic.
>>
>> Signed-off-by: Albert Wang <twang13@marvell.com>
>> Signed-off-by: Libin Yang <lbyang@marvell.com>
>> ---
>>  drivers/media/platform/marvell-ccic/mcam-core.c |  175 ++++++++++++++++++-----
>>  drivers/media/platform/marvell-ccic/mcam-core.h |    6 +
>>  2 files changed, 149 insertions(+), 32 deletions(-)
>>
>> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c
>b/drivers/media/platform/marvell-ccic/mcam-core.c
>> index 3cc1d0c..a679917 100755
>> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
>> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
>
>[snip]
>
>> @@ -658,49 +708,85 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
>>   */
>>  static void mcam_ctlr_image(struct mcam_camera *cam)
>>  {
>> -	int imgsz;
>>  	struct v4l2_pix_format *fmt = &cam->pix_format;
>> +	u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
>> +
>> +	cam_dbg(cam, "camera: bytesperline = %d; height = %d\n",
>> +		fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
>> +	imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
>> +	imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
>> +
>> +	switch (fmt->pixelformat) {
>> +	case V4L2_PIX_FMT_YUYV:
>> +	case V4L2_PIX_FMT_UYVY:
>> +		widthy = fmt->width * 2;
>> +		widthuv = 0;
>> +		break;
>> +	case V4L2_PIX_FMT_JPEG:
>> +		imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
>> +		widthy = fmt->bytesperline;
>> +		widthuv = 0;
>> +		break;
>> +	case V4L2_PIX_FMT_YUV422P:
>> +	case V4L2_PIX_FMT_YUV420:
>> +	case V4L2_PIX_FMT_YVU420:
>> +		imgsz_w = (fmt->bytesperline * 4 / 3) & IMGSZ_H_MASK;
>> +		widthy = fmt->width;
>> +		widthuv = fmt->width / 2;
>
>I might be wrong, but the above doesn't look right to me. Firstly, YUV422P
>is a 4:2:2 format, whereas YUV420 and YVU420 are 4:2:0 formats, so, I
>would expect calculations for them to differ. Besides, bytesperline * 4 /
>3 doesn't look right for any of them. If this is what I think - total
>number of bytes per line, i.e., sizeimage / height, than shouldn't YAU422P
>have
>+		imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
>and the other two
>+		imgsz_w = (fmt->bytesperline * 3 / 2) & IMGSZ_H_MASK;
>? But maybe I'm wrong, please, double-check and confirm.
>

First of all, the setting bytesperline in this file is wrong. It should be
like the setting in the mcam-core-soc.c in the later patch. It's my fault
missing modifying the bytesperline when adding the new formats.
Besides the bytesperline in mcam-core-soc.c is a little wrong.
I will update it in the new version of patch.

For imgsz_w setting, this is for the CCIC input data format, which is from
sensor, while 'switch (fmt->pixelformat)' is CCIC output data format.
It seems a little confusing using fmt->pixelformat here. Using
mcam_formats->mbus_code seems more reasonable. Anyway, 
each fmt->pixelformat must have one mcam_formats->mbus_code
correspondingly. 

Although, our spec says it supports YUV420 input. Our HW team told me
we only use YUV422 and the length is width * 2. So it seems some 
mbus_code is wrong set here.
It seems in this case such format will be never used as we can see
ov7670 does not support yuv420.

Regards,
Libin

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2012-12-18 19:15           ` Jonathan Corbet
  2012-12-18 20:48             ` Albert Wang
@ 2013-01-31  8:29             ` Albert Wang
  2013-02-05  3:14               ` Jonathan Corbet
  1 sibling, 1 reply; 71+ messages in thread
From: Albert Wang @ 2013-01-31  8:29 UTC (permalink / raw)
  To: Albert Wang, Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan

As you know, we are working on adding B_DMA_SG support on soc_camera mode.

We found there is some code we can't understand in irq handler:
>>>>>>
if (handled == IRQ_HANDLED) {
	set_bit(CF_DMA_ACTIVE, &cam->flags);
	if (cam->buffer_mode == B_DMA_sg)
		mcam_ctlr_stop(cam);
}
<<<<<<

The question is why we need stop ccic in irq handler when buffer mode is B_DMA_sg?
>>>
	if (cam->buffer_mode == B_DMA_sg)
		mcam_ctlr_stop(cam);
<<<

Currently we tested B_DMA_sg mode on our platform, and this buffer mode can work only if we comment these 2 lines.

Could you please help us take a look if you have time?

Thank you very much for your help! :)


Thanks
Albert Wang
86-21-61092656

>-----Original Message-----
>From: Albert Wang
>Sent: Wednesday, 19 December, 2012 04:48
>To: 'Jonathan Corbet'
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: RE: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for
>soc_camera support
>
>Hi, Jonathan
>
>
>>-----Original Message-----
>>From: Jonathan Corbet [mailto:corbet@lwn.net]
>>Sent: Wednesday, 19 December, 2012 03:15
>>To: Albert Wang
>>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>>Subject: Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for
>>soc_camera support
>>
>>On Mon, 17 Dec 2012 19:04:26 -0800
>>Albert Wang <twang13@marvell.com> wrote:
>>
>>> [Albert Wang] So if we add B_DMA_SG and B_VMALLOC support and OLPC XO 1.0
>>support in soc_camera mode.
>>> Then we can just remove the original mode and only support soc_camera mode in
>>marvell-ccic?
>>
>>That is the idea, yes.  Unless there is some real value to supporting both
>>modes (that I've not seen), I think it's far better to support just one of
>>them.  Trying to support duplicated modes just leads to pain in the long
>>run, in my experience.
>>
>[Albert Wang] OK, we will update and submit the remained patches except for the 3
>patches related with soc_camera support as the first part.
>Then we will submit the soc_camera support patches after we rework the patches and add
>B_DMA_SG and B_VMALLOC support and OLPC XO 1.0 support.
>
>>I can offer to *try* to find time to help with XO 1.0 testing when the
>>time comes.
>>
>[Albert Wang] Thank you very much! We were worried about how to get the OLPC XO 1.0
>HW. That would be a great help! :)
>
>>Thanks,
>>
>>jon
>
>
>Thanks
>Albert Wang
>86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2013-01-31  8:29             ` Albert Wang
@ 2013-02-05  3:14               ` Jonathan Corbet
  2013-02-06  3:21                 ` Albert Wang
  0 siblings, 1 reply; 71+ messages in thread
From: Jonathan Corbet @ 2013-02-05  3:14 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media, Libin Yang

My apologies for the slow response...I'm running far behind.

On Thu, 31 Jan 2013 00:29:13 -0800
Albert Wang <twang13@marvell.com> wrote:

> As you know, we are working on adding B_DMA_SG support on soc_camera mode.
> 
> We found there is some code we can't understand in irq handler:
> >>>>>>  
> if (handled == IRQ_HANDLED) {
> 	set_bit(CF_DMA_ACTIVE, &cam->flags);
> 	if (cam->buffer_mode == B_DMA_sg)
> 		mcam_ctlr_stop(cam);
> }
> <<<<<<
> 
> The question is why we need stop ccic in irq handler when buffer mode is B_DMA_sg?

That's actually intended to be addressed by this comment in the DMA setup
code:

/*
 * Frame completion with S/G is trickier.  We can't muck with
 * a descriptor chain on the fly, since the controller buffers it
 * internally.  So we have to actually stop and restart; Marvell
 * says this is the way to do it.
 *

...and, indeed, at the time, I was told by somebody at Marvell that I
needed to stop the controller before I could store a new descriptor into
the chain.  I don't see how it could work otherwise, really?

I'd be happy to see this code go, it always felt a bit hacky.  But the
controller buffers the descriptor chain deep inside its unreachable guts,
so one has to mess with it carefully.

Thanks,

jon

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support
  2013-02-05  3:14               ` Jonathan Corbet
@ 2013-02-06  3:21                 ` Albert Wang
  0 siblings, 0 replies; 71+ messages in thread
From: Albert Wang @ 2013-02-06  3:21 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

Hi, Jonathan

Thanks a lot for explaining it. :)


>-----Original Message-----
>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Tuesday, 05 February, 2013 11:14
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org; Libin Yang
>Subject: Re: [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for
>soc_camera support
>
>My apologies for the slow response...I'm running far behind.
>
>On Thu, 31 Jan 2013 00:29:13 -0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> As you know, we are working on adding B_DMA_SG support on soc_camera mode.
>>
>> We found there is some code we can't understand in irq handler:
>> >>>>>>
>> if (handled == IRQ_HANDLED) {
>> 	set_bit(CF_DMA_ACTIVE, &cam->flags);
>> 	if (cam->buffer_mode == B_DMA_sg)
>> 		mcam_ctlr_stop(cam);
>> }
>> <<<<<<
>>
>> The question is why we need stop ccic in irq handler when buffer mode is B_DMA_sg?
>
>That's actually intended to be addressed by this comment in the DMA setup
>code:
>
>/*
> * Frame completion with S/G is trickier.  We can't muck with
> * a descriptor chain on the fly, since the controller buffers it
> * internally.  So we have to actually stop and restart; Marvell
> * says this is the way to do it.
> *
>
>...and, indeed, at the time, I was told by somebody at Marvell that I
>needed to stop the controller before I could store a new descriptor into
>the chain.  I don't see how it could work otherwise, really?
>
[Albert Wang] Em.., maybe I guess there was some flaw in old version.
We indeed can work on current platform without the code.

>I'd be happy to see this code go, it always felt a bit hacky.  But the
>controller buffers the descriptor chain deep inside its unreachable guts,
>so one has to mess with it carefully.
>
[Albert Wang] I suppose your platform should work with the original code.
So how do you think this time we will keep the original code in the patches?
If there is something wrong with it when you test the patches on your platform, maybe we can try to change it. :


>Thanks,
>
>jon

Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 71+ messages in thread

end of thread, other threads:[~2013-02-06  3:26 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-15  9:57 [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Albert Wang
2012-12-15  9:57 ` [PATCH V3 01/15] [media] marvell-ccic: use internal variable replace global frame stats variable Albert Wang
2012-12-16 15:36   ` Jonathan Corbet
2012-12-27 20:07     ` Mauro Carvalho Chehab
2013-01-01 14:56   ` Guennadi Liakhovetski
2012-12-15  9:57 ` [PATCH V3 02/15] [media] marvell-ccic: add MIPI support for marvell-ccic driver Albert Wang
2012-12-16 15:54   ` Jonathan Corbet
2012-12-16 21:45     ` Albert Wang
2013-01-01 15:28   ` Guennadi Liakhovetski
2013-01-01 19:31     ` Albert Wang
2012-12-15  9:57 ` [PATCH V3 03/15] [media] marvell-ccic: add clock tree " Albert Wang
2012-12-16 16:03   ` Jonathan Corbet
2012-12-16 21:51     ` Albert Wang
2013-01-03 17:37       ` Nicolas THERY
2013-01-03 19:27         ` Albert Wang
2013-01-01 16:05   ` Guennadi Liakhovetski
2013-01-01 19:36     ` Albert Wang
2013-01-04  5:42     ` Libin Yang
2013-01-04 10:25       ` Guennadi Liakhovetski
2013-01-05  3:12         ` Libin Yang
2012-12-15  9:57 ` [PATCH V3 04/15] [media] marvell-ccic: reset ccic phy when stop streaming for stability Albert Wang
2012-12-16 16:04   ` Jonathan Corbet
2013-01-01 16:13   ` Guennadi Liakhovetski
2012-12-15  9:57 ` [PATCH V3 05/15] [media] marvell-ccic: refine mcam_set_contig_buffer function Albert Wang
2012-12-16 16:06   ` Jonathan Corbet
2012-12-16 21:54     ` Albert Wang
2012-12-15  9:57 ` [PATCH V3 06/15] [media] marvell-ccic: add new formats support for marvell-ccic driver Albert Wang
2012-12-16 16:16   ` Jonathan Corbet
2012-12-16 21:58     ` Albert Wang
2013-01-01 16:56   ` Guennadi Liakhovetski
2013-01-01 19:42     ` Albert Wang
2013-01-01 20:03       ` Guennadi Liakhovetski
2013-01-04  9:32     ` Libin Yang
2013-01-10  7:53     ` Libin Yang
2012-12-15  9:57 ` [PATCH V3 07/15] [media] marvell-ccic: add SOF / EOF pair check " Albert Wang
2012-12-16 16:19   ` Jonathan Corbet
2012-12-16 22:00     ` Albert Wang
2013-01-02  7:48   ` Guennadi Liakhovetski
2012-12-15  9:57 ` [PATCH V3 08/15] [media] marvell-ccic: switch to resource managed allocation and request Albert Wang
2012-12-16 16:20   ` Jonathan Corbet
2013-01-02  8:00   ` Guennadi Liakhovetski
2012-12-15  9:57 ` [PATCH V3 09/15] [media] marvell-ccic: add get_mcam function for marvell-ccic driver Albert Wang
2012-12-16 16:24   ` Jonathan Corbet
2012-12-16 22:04     ` Albert Wang
2013-01-02  8:16     ` Guennadi Liakhovetski
2012-12-15  9:57 ` [PATCH V3 10/15] [media] marvell-ccic: split mcam-core into 2 parts for soc_camera support Albert Wang
2012-12-16 16:37   ` Jonathan Corbet
2012-12-16 22:12     ` Albert Wang
2012-12-17 15:28       ` Jonathan Corbet
2012-12-18  3:04         ` Albert Wang
2012-12-18 19:15           ` Jonathan Corbet
2012-12-18 20:48             ` Albert Wang
2013-01-31  8:29             ` Albert Wang
2013-02-05  3:14               ` Jonathan Corbet
2013-02-06  3:21                 ` Albert Wang
2012-12-15  9:58 ` [PATCH V3 11/15] [media] marvell-ccic: add soc_camera support in mcam core Albert Wang
2012-12-15  9:58 ` [PATCH V3 12/15] [media] marvell-ccic: add soc_camera support in mmp driver Albert Wang
2012-12-16 16:46   ` Jonathan Corbet
2012-12-16 22:19     ` Albert Wang
2012-12-15  9:58 ` [PATCH V3 13/15] [media] marvell-ccic: add dma burst mode support in marvell-ccic driver Albert Wang
2012-12-16 16:49   ` Jonathan Corbet
2012-12-16 22:22     ` Albert Wang
2012-12-15  9:58 ` [PATCH V3 14/15] [media] marvell-ccic: use unsigned int type replace int type Albert Wang
2012-12-16 16:50   ` Jonathan Corbet
2012-12-15  9:58 ` [PATCH V3 15/15] [media] marvell-ccic: add 3 frame buffers support in DMA_CONTIG mode Albert Wang
2012-12-16 16:56   ` Jonathan Corbet
2012-12-16 22:34     ` Albert Wang
2012-12-16 22:55       ` Jonathan Corbet
2012-12-17  5:06         ` Albert Wang
2012-12-16 16:57 ` [PATCH V3 00/15] [media] marvell-ccic: add soc camera support on marvell-ccic Jonathan Corbet
2012-12-16 22:34   ` Albert Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.