msm: gemini: Make GEMINI a v4l2 subdev.

This has been added to support the
inline JPEG feature. Here the VFE V4L2
subdev sends frames directly to the
Gemini driver. All camera modules like
Sensors, VFE, etc are V4L2 subdevs.

Change-Id: I572afe130ef4f2de441faf1104e688778e0e0ecb
Signed-off-by: Jignesh Mehta <jigneshm@codeaurora.org>
Signed-off-by: Ashwini Rao <ashwinik@codeaurora.org>
diff --git a/drivers/media/video/msm/gemini/Makefile b/drivers/media/video/msm/gemini/Makefile
index 3e2fc97..8a7cd93 100644
--- a/drivers/media/video/msm/gemini/Makefile
+++ b/drivers/media/video/msm/gemini/Makefile
@@ -1,2 +1,3 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+EXTRA_CFLAGS += -Idrivers/media/video/msm
 obj-$(CONFIG_MSM_GEMINI) += msm_gemini_dev.o msm_gemini_sync.o msm_gemini_core.o msm_gemini_hw.o msm_gemini_platform.o
diff --git a/drivers/media/video/msm/gemini/msm_gemini_dev.c b/drivers/media/video/msm/gemini/msm_gemini_dev.c
index 1156bb0..01d45ed 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_dev.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_dev.c
@@ -20,8 +20,11 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/uaccess.h>
-
 #include <media/msm_gemini.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "msm.h"
 #include "msm_gemini_sync.h"
 #include "msm_gemini_common.h"
 
@@ -66,8 +69,8 @@
 	int rc;
 	struct msm_gemini_device *pgmn_dev = filp->private_data;
 
-	GMN_DBG(KERN_INFO "%s:%d] cmd = %d\n", __func__, __LINE__,
-		_IOC_NR(cmd));
+	GMN_DBG("%s:%d] cmd=%d pgmn_dev=0x%x arg=0x%x\n", __func__,
+		__LINE__, _IOC_NR(cmd), (uint32_t)pgmn_dev, (uint32_t)arg);
 
 	rc = __msm_gemini_ioctl(pgmn_dev, cmd, arg);
 
@@ -84,21 +87,78 @@
 
 static struct class *msm_gemini_class;
 static dev_t msm_gemini_devno;
-static struct msm_gemini_device *msm_gemini_device_p;
+struct msm_gemini_device *msm_gemini_device_p;
+
+int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd)
+{
+	int rc;
+	struct msm_gemini_device *pgmn_dev =
+		(struct msm_gemini_device *)gemini_sd->host_priv;
+
+	GMN_DBG("%s:%d: gemini_sd=0x%x pgmn_dev=0x%x\n",
+		__func__, __LINE__, (uint32_t)gemini_sd, (uint32_t)pgmn_dev);
+	rc = __msm_gemini_open(pgmn_dev);
+	GMN_DBG("%s:%d: rc=%d\n",
+		__func__, __LINE__, rc);
+	return rc;
+}
+
+static long msm_gemini_subdev_ioctl(struct v4l2_subdev *sd,
+	unsigned int cmd, void *arg)
+{
+	long rc;
+	struct msm_gemini_device *pgmn_dev =
+		(struct msm_gemini_device *)sd->host_priv;
+
+	GMN_DBG("%s: cmd=%d\n", __func__, cmd);
+
+	GMN_DBG("%s: pgmn_dev 0x%x", __func__, (uint32_t)pgmn_dev);
+
+	GMN_DBG("%s: Calling __msm_gemini_ioctl\n", __func__);
+
+	rc = __msm_gemini_ioctl(pgmn_dev, cmd, (unsigned long)arg);
+	pr_debug("%s: X\n", __func__);
+	return rc;
+}
+
+void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd)
+{
+	int rc;
+	struct msm_gemini_device *pgmn_dev =
+		(struct msm_gemini_device *)gemini_sd->host_priv;
+	GMN_DBG("%s:pgmn_dev=0x%x", __func__, (uint32_t)pgmn_dev);
+	rc = __msm_gemini_release(pgmn_dev);
+	GMN_DBG("%s:rc=%d", __func__, rc);
+}
+
+static const struct v4l2_subdev_core_ops msm_gemini_subdev_core_ops = {
+	.ioctl = msm_gemini_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_gemini_subdev_ops = {
+	.core = &msm_gemini_subdev_core_ops,
+};
 
 static int msm_gemini_init(struct platform_device *pdev)
 {
 	int rc = -1;
 	struct device *dev;
 
-	GMN_DBG("%s:%d]\n", __func__, __LINE__);
-
+	GMN_DBG("%s:\n", __func__);
 	msm_gemini_device_p = __msm_gemini_init(pdev);
 	if (msm_gemini_device_p == NULL) {
 		GMN_PR_ERR("%s: initialization failed\n", __func__);
 		goto fail;
 	}
 
+	v4l2_subdev_init(&msm_gemini_device_p->subdev, &msm_gemini_subdev_ops);
+	v4l2_set_subdev_hostdata(&msm_gemini_device_p->subdev,
+		msm_gemini_device_p);
+	pr_debug("%s: msm_gemini_device_p 0x%x", __func__,
+			(uint32_t)msm_gemini_device_p);
+	GMN_DBG("%s:gemini: platform_set_drvdata\n", __func__);
+	platform_set_drvdata(pdev, &msm_gemini_device_p->subdev);
+
 	rc = alloc_chrdev_region(&msm_gemini_devno, 0, 1, MSM_GEMINI_NAME);
 	if (rc < 0) {
 		GMN_PR_ERR("%s: failed to allocate chrdev\n", __func__);
@@ -168,9 +228,7 @@
 
 static int __msm_gemini_probe(struct platform_device *pdev)
 {
-	int rc;
-	rc = msm_gemini_init(pdev);
-	return rc;
+	return msm_gemini_init(pdev);
 }
 
 static int __msm_gemini_remove(struct platform_device *pdev)
@@ -183,7 +241,7 @@
 	.probe  = __msm_gemini_probe,
 	.remove = __msm_gemini_remove,
 	.driver = {
-		.name = "msm_gemini",
+		.name = MSM_GEMINI_DRV_NAME,
 		.owner = THIS_MODULE,
 	},
 };
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.h b/drivers/media/video/msm/gemini/msm_gemini_sync.h
index 6c69a92..a47e766 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_sync.h
+++ b/drivers/media/video/msm/gemini/msm_gemini_sync.h
@@ -17,6 +17,8 @@
 #include <linux/list.h>
 #include <linux/cdev.h>
 #include <linux/platform_device.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
 #include "msm_gemini_core.h"
 
 struct msm_gemini_q {
@@ -63,6 +65,8 @@
 	/* input buf queue
 	 */
 	struct msm_gemini_q input_buf_q;
+
+	struct v4l2_subdev subdev;
 };
 
 int __msm_gemini_open(struct msm_gemini_device *pgmn_dev);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 7680559..40bc160 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -36,7 +36,7 @@
 #define MSM_V4L2_DIMENSION_SIZE 96
 #define MAX_DEV_NAME_LEN 50
 
-#define ERR_USER_COPY(to) pr_err("%s(%d): copy %s user\n", \
+#define ERR_USER_COPY(to) pr_debug("%s(%d): copy %s user\n", \
 				__func__, __LINE__, ((to) ? "to" : "from"))
 #define ERR_COPY_FROM_USER() ERR_USER_COPY(0)
 #define ERR_COPY_TO_USER() ERR_USER_COPY(1)
@@ -47,6 +47,7 @@
 #define MSM_ISPIF_DRV_NAME "msm_ispif"
 #define MSM_VFE_DRV_NAME "msm_vfe"
 #define MSM_VPE_DRV_NAME "msm_vpe"
+#define MSM_GEMINI_DRV_NAME "msm_gemini"
 
 /* msm queue management APIs*/
 
@@ -232,6 +233,7 @@
 	struct v4l2_subdev *csic_sdev; /*csid sub device*/
 	struct v4l2_subdev *ispif_sdev; /* ispif sub device */
 	struct v4l2_subdev *act_sdev; /* actuator sub device */
+	struct v4l2_subdev *gemini_sdev; /* gemini sub device */
 
 	struct pm_qos_request_list pm_qos_req_list;
 	struct msm_mctl_pp_info pp_info;
@@ -248,12 +250,13 @@
 
 	/*int (*isp_init)(struct msm_cam_v4l2_device *pcam);*/
 	int (*isp_open)(struct v4l2_subdev *sd, struct v4l2_subdev *sd_vpe,
-					struct msm_sync *sync);
+		struct v4l2_subdev *gemini_sdev, struct msm_sync *sync);
 	int (*isp_config)(struct msm_cam_media_controller *pmctl,
 		 unsigned int cmd, unsigned long arg);
 	int (*isp_notify)(struct v4l2_subdev *sd,
 		unsigned int notification, void *arg);
-	void (*isp_release)(struct msm_sync *psync);
+	void (*isp_release)(struct msm_sync *psync,
+		struct v4l2_subdev *gemini_sdev);
 	int (*isp_pp_cmd)(struct msm_cam_media_controller *pmctl,
 		 struct msm_mctl_pp_cmd, void *data);
 
@@ -462,7 +465,9 @@
 	struct msm_vfe_cfg_cmd *cfgcmd, void *data);
 int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
 	struct platform_device *pdev);
+int msm_gemini_subdev_init(struct v4l2_subdev *sd);
 void msm_vpe_subdev_release(struct platform_device *pdev);
+void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
 int msm_isp_subdev_ioctl_vpe(struct v4l2_subdev *isp_subdev,
 	struct msm_mctl_pp_cmd *cmd, void *data);
 int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index bb50d77..c9a9f1b 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -26,6 +26,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <media/msm_isp.h>
+#include <media/msm_gemini.h>
 
 #include "msm.h"
 
@@ -34,10 +35,6 @@
 #else
 #define D(fmt, args...) do {} while (0)
 #endif
-#define ERR_USER_COPY(to) pr_err("%s(%d): copy %s user\n", \
-				__func__, __LINE__, ((to) ? "to" : "from"))
-#define ERR_COPY_FROM_USER() ERR_USER_COPY(0)
-#define ERR_COPY_TO_USER() ERR_USER_COPY(1)
 
 #define MSM_FRAME_AXI_MAX_BUF 32
 
@@ -151,7 +148,7 @@
 
 	int vfe_id = vdata->evt_msg.msg_id;
 	if (!pcam) {
-		pr_err("%s pcam is null. return\n", __func__);
+		pr_debug("%s pcam is null. return\n", __func__);
 		msm_isp_sync_free(vdata);
 		return rc;
 	}
@@ -181,7 +178,7 @@
 		break;
 	case VFE_MSG_V32_CAPTURE:
 	case VFE_MSG_V2X_CAPTURE:
-		pr_err("%s Got V32_CAPTURE: getting buffer for id = %d",
+		pr_debug("%s Got V32_CAPTURE: getting buffer for id = %d",
 						__func__, vfe_id);
 		msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
 					image_mode, &free_buf);
@@ -413,7 +410,7 @@
 
 /* This function is called by open() function, so we need to init HW*/
 static int msm_isp_open(struct v4l2_subdev *sd,
-	struct v4l2_subdev *sd_vpe,
+	struct v4l2_subdev *sd_vpe, struct v4l2_subdev *gemini_sdev,
 	struct msm_sync *sync)
 {
 	/* init vfe and senor, register sync callbacks for init*/
@@ -439,7 +436,8 @@
 	return rc;
 }
 
-static void msm_isp_release(struct msm_sync *psync)
+static void msm_isp_release(struct msm_sync *psync,
+		struct v4l2_subdev *gemini_sdev)
 {
 	D("%s\n", __func__);
 	msm_vfe_subdev_release(psync->pdev);
@@ -447,7 +445,7 @@
 }
 
 static int msm_config_vfe(struct v4l2_subdev *sd,
-		struct msm_sync *sync, void __user *arg)
+	struct msm_sync *sync, void __user *arg)
 {
 	struct msm_vfe_cfg_cmd cfgcmd;
 	struct msm_pmem_region region[8];
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 13d1daf..54458d1 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -304,7 +304,7 @@
 		pr_err("%s: param is NULL", __func__);
 		return -EINVAL;
 	}
-	D("%s cmd = %d\n", __func__, _IOC_NR(cmd));
+	D("%s:%d: cmd %d\n", __func__, __LINE__, cmd);
 
 	/* ... call sensor, ISPIF or VEF subdev*/
 	switch (cmd) {
@@ -436,6 +436,8 @@
 			/* ISFIF config*/
 	default:
 		/* ISP config*/
+		D("%s:%d: go to default. Calling msm_isp_config\n",
+			__func__, __LINE__);
 		rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
 		break;
 	}
@@ -556,6 +558,34 @@
 	}
 
 	rc = 0;
+
+
+	/* register gemini subdev */
+	driver = driver_find(MSM_GEMINI_DRV_NAME, &platform_bus_type);
+	if (!driver) {
+		pr_err("%s:%d:Gemini: Failure: goto out\n",
+			__func__, __LINE__);
+		goto out;
+	}
+	pr_debug("%s:%d:Gemini: driver_find_device Gemini driver 0x%x\n",
+		__func__, __LINE__, (uint32_t)driver);
+	dev = driver_find_device(driver, NULL, NULL,
+				msm_mctl_subdev_match_core);
+	if (!dev) {
+		pr_err("%s:%d:Gemini: Failure goto out_put_driver\n",
+			__func__, __LINE__);
+		goto out_put_driver;
+	}
+	p_mctl->gemini_sdev = dev_get_drvdata(dev);
+	pr_debug("%s:%d:Gemini: After dev_get_drvdata gemini_sdev=0x%x\n",
+		__func__, __LINE__, (uint32_t)p_mctl->gemini_sdev);
+
+	if (p_mctl->gemini_sdev == NULL) {
+		pr_err("%s:%d:Gemini: Failure gemini_sdev is null\n",
+			__func__, __LINE__);
+		goto out_put_driver;
+	}
+	rc = 0;
 	return rc;
 out_put_driver:
 	put_driver(driver);
@@ -629,7 +659,9 @@
 		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_open)
 			rc = p_mctl->isp_sdev->isp_open(
 				p_mctl->isp_sdev->sd,
-				p_mctl->isp_sdev->sd_vpe, sync);
+				p_mctl->isp_sdev->sd_vpe,
+				p_mctl->gemini_sdev,
+				sync);
 		if (rc < 0) {
 			pr_err("%s: isp init failed: %d\n", __func__, rc);
 			goto msm_open_done;
@@ -691,7 +723,8 @@
 	}
 
 	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
-		p_mctl->isp_sdev->isp_release(&p_mctl->sync);
+		p_mctl->isp_sdev->isp_release(&p_mctl->sync,
+				p_mctl->gemini_sdev);
 
 	if (camdev->is_csid) {
 		v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index 0ba1c0f..54b4efb 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -36,13 +36,6 @@
 #define D(fmt, args...) do {} while (0)
 #endif
 
-
-#define ERR_USER_COPY(to) pr_err("%s(%d): copy %s user\n", \
-				__func__, __LINE__, ((to) ? "to" : "from"))
-#define ERR_COPY_FROM_USER() ERR_USER_COPY(0)
-#define ERR_COPY_TO_USER() ERR_USER_COPY(1)
-
-
 #define PAD_TO_WORD(a)	  (((a) + 3) & ~3)
 
 #define __CONTAINS(r, v, l, field) ({			   \