From d6c2b71e753a46bc72743d09000ca4589da51251 Mon Sep 17 00:00:00 2001
From: Valentine Barshak <valentine.barshak@cogentembedded.com>
Date: Tue, 6 Nov 2018 16:02:21 +0300
Subject: [PATCH 029/122] media: soc_camera: rcar_vin: Add R-Car M3N support

This adds R8A77965 SoC support.

Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
---
 drivers/media/platform/soc_camera/rcar_vin.c | 98 ++++++++++++++++++++++++----
 1 file changed, 86 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 77c8d6b..228bbf3 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -200,6 +200,7 @@ static int ifmd4_init = true;
 enum chip_id {
 	RCAR_GEN3,
 	RCAR_V3M,
+	RCAR_M3N,
 	RCAR_M3,
 	RCAR_H3,
 	RCAR_GEN2,
@@ -375,6 +376,69 @@ static const struct vin_gen3_ifmd vin_m3_vc_ifmd[] = {
 	},
 };
 
+static const struct vin_gen3_ifmd vin_m3n_vc_ifmd[] = {
+	{ 0x0000,
+		{
+			{RCAR_CSI40, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH1},
+		}
+	},
+	{ 0x0001,
+		{
+			{RCAR_CSI20, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH1},
+		}
+	},
+	{ 0x0002,
+		{
+			{RCAR_CSI40, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH1},
+		}
+	},
+	{ 0x0003,
+		{
+			{RCAR_CSI40, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH2},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH3},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH2},
+			{RCAR_CSI40, RCAR_VIRTUAL_CH3},
+		}
+	},
+	{ 0x0004,
+		{
+			{RCAR_CSI20, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH2},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH3},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH0},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH1},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH2},
+			{RCAR_CSI20, RCAR_VIRTUAL_CH3},
+		}
+	},
+};
+
 static const struct vin_gen3_ifmd vin_v3_vc_ifmd[] = {
 	{ 0x0000,
 		{
@@ -913,7 +977,7 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
 	struct rcar_vin_cam *cam = icd->host_priv;
 
 	if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-		priv->chip == RCAR_V3M) {
+	    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) {
 		if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) {
 			dev_err(icd->parent, "Scaling rate parameter error\n");
 			return -EINVAL;
@@ -1022,7 +1086,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
 	switch (icd->current_fmt->host_fmt->fourcc) {
 	case V4L2_PIX_FMT_NV12:
 		if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-			priv->chip == RCAR_V3M) {
+		    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) {
 			iowrite32(ALIGN((cam->out_width * cam->out_height),
 					 0x80), priv->base + VNUVAOF_REG);
 			dmr = VNDMR_DTMD_YCSEP_YCBCR420;
@@ -1058,7 +1122,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
 		break;
 	case V4L2_PIX_FMT_XBGR32:
 		if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 &&
-			priv->chip != RCAR_V3M &&
+		    priv->chip != RCAR_M3N && priv->chip != RCAR_V3M &&
 		    priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 &&
 		    priv->chip != RCAR_E1)
 			goto e_format;
@@ -1067,7 +1131,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
 		break;
 	case V4L2_PIX_FMT_ABGR32:
 		if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 &&
-			priv->chip != RCAR_V3M)
+		    priv->chip != RCAR_M3N && priv->chip != RCAR_V3M)
 			goto e_format;
 
 		dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB;
@@ -1088,7 +1152,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
 		vnmc |= VNMC_BPS;
 
 	if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-		priv->chip == RCAR_V3M) {
+	    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) {
 		if (priv->pdata_flags & RCAR_VIN_CSI2)
 			vnmc &= ~VNMC_DPINE;
 		else
@@ -1459,7 +1523,7 @@ static int rcar_vin_add_device(struct soc_camera_device *icd)
 	pm_runtime_get_sync(ici->v4l2_dev.dev);
 
 	if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-		priv->chip == RCAR_V3M) {
+	    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) {
 		struct v4l2_subdev *csi2_sd = find_csi2(priv);
 		struct v4l2_subdev *deser_sd = find_deser(priv);
 		int ret = 0;
@@ -1722,7 +1786,7 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd)
 	}
 
 	if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-		priv->chip == RCAR_V3M) {
+	    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) {
 		if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) &&
 		    (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) &&
 		    (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12)
@@ -1880,7 +1944,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
 		return ret;
 
 	if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-		priv->chip == RCAR_V3M) {
+	    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) {
 		if (cfg.type == V4L2_MBUS_CSI2)
 			vnmc &= ~VNMC_DPINE;
 		else
@@ -1888,7 +1952,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
 	}
 
 	if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-		priv->chip == RCAR_V3M)
+	    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M)
 		val = VNDMR2_FTEV;
 	else
 		val = VNDMR2_FTEV | VNDMR2_VLV(1);
@@ -2486,7 +2550,7 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd,
 		return ret;
 
 	if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-		priv->chip == RCAR_V3M) {
+	    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) {
 		/* Adjust max scaling size for Gen3 */
 		if (pix->width > 4096)
 			pix->width = priv->max_width;
@@ -2666,6 +2730,7 @@ static struct soc_camera_host_ops rcar_vin_host_ops = {
 #ifdef CONFIG_OF
 static const struct of_device_id rcar_vin_of_table[] = {
 	{ .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M },
+	{ .compatible = "renesas,vin-r8a77965", .data = (void *)RCAR_M3N },
 	{ .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 },
 	{ .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 },
 	{ .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
@@ -2989,7 +3054,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
 	}
 
 	if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-		priv->chip == RCAR_V3M) {
+	    priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) {
 		priv->max_width = 4096;
 		priv->max_height = 4096;
 	} else {
@@ -2998,7 +3063,8 @@ static int rcar_vin_probe(struct platform_device *pdev)
 	}
 
 	if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
-	    priv->chip == RCAR_V3M) && !of_property_read_string(np, "csi,select", &str)) {
+	     priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) &&
+	    !of_property_read_string(np, "csi,select", &str)) {
 		u32 ifmd;
 		bool match_flag = false;
 		const struct vin_gen3_ifmd *gen3_ifmd_table = NULL;
@@ -3076,6 +3142,10 @@ static int rcar_vin_probe(struct platform_device *pdev)
 			gen3_ifmd_table = vin_m3_vc_ifmd;
 			ifmd = VNCSI_IFMD_DES1;
 			break;
+		case RCAR_M3N:
+			gen3_ifmd_table = vin_m3n_vc_ifmd;
+			ifmd = VNCSI_IFMD_DES1;
+			break;
 		case RCAR_V3M:
 			gen3_ifmd_table = vin_v3_vc_ifmd;
 			break;
@@ -3242,6 +3312,10 @@ static int rcar_vin_resume(struct device *dev)
 		gen3_ifmd_table = vin_m3_vc_ifmd;
 		ifmd = VNCSI_IFMD_DES1;
 		break;
+	case RCAR_M3N:
+		gen3_ifmd_table = vin_m3n_vc_ifmd;
+		ifmd = VNCSI_IFMD_DES1;
+		break;
 	case RCAR_V3M:
 		gen3_ifmd_table = vin_v3_vc_ifmd;
 		break;
-- 
2.7.4

