msm: camera: Lens rolloff changes for MSM8960.

MSM8960v1 has mesh based lens rolloff while MSM8960v2 has
PCA based lens rolloff. Also starting from MSM8960v2 and
newer chipsets have double buffered lens rolloff. So adding
the run-time lens rolloff update, new config for PCA lens
rolloff and run-time selection of Mesh or PCA lens rolloff.

Signed-off-by: Ujwal Patel <ujwalp@codeaurora.org>
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 3f89965..ff281f2 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -77,8 +77,8 @@
 		{VFE_CMD_BLACK_LEVEL_CFG, V32_BLACK_LEVEL_LEN,
 		V32_BLACK_LEVEL_OFF,
 		0xFF},
-/*10*/  {VFE_CMD_ROLL_OFF_CFG, V32_ROLL_OFF_CFG_LEN, V32_ROLL_OFF_CFG_OFF,
-		0xFF},
+/*10*/  {VFE_CMD_MESH_ROLL_OFF_CFG, V32_MESH_ROLL_OFF_CFG_LEN,
+		V32_MESH_ROLL_OFF_CFG_OFF, 0xFF},
 		{VFE_CMD_DEMUX_CFG, V32_DEMUX_LEN, V32_DEMUX_OFF, 0xFF},
 		{VFE_CMD_FOV_CFG, V32_FOV_LEN, V32_FOV_OFF, 0xFF},
 		{VFE_CMD_MAIN_SCALER_CFG, V32_MAIN_SCALER_LEN,
@@ -866,6 +866,7 @@
 static void vfe32_update(void)
 {
 	unsigned long flags;
+	uint32_t value = 0;
 	if (vfe32_ctrl->update_linear) {
 		if (!msm_io_r(vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1))
 			msm_io_w(1,
@@ -875,6 +876,16 @@
 				vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1);
 		vfe32_ctrl->update_linear = false;
 	}
+
+	if (vfe32_ctrl->update_rolloff) {
+		value = msm_io_r(vfe32_ctrl->vfebase +
+			V33_PCA_ROLL_OFF_CFG_OFF1);
+		value ^= V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK;
+		msm_io_w(value, vfe32_ctrl->vfebase +
+			V33_PCA_ROLL_OFF_CFG_OFF1);
+		vfe32_ctrl->update_rolloff = false;
+	}
+
 	spin_lock_irqsave(&vfe32_ctrl->update_ack_lock, flags);
 	vfe32_ctrl->update_ack_pending = TRUE;
 	spin_unlock_irqrestore(&vfe32_ctrl->update_ack_lock, flags);
@@ -1099,6 +1110,7 @@
 	uint32_t *cmdp = NULL;
 	uint32_t *cmdp_local = NULL;
 	uint32_t snapshot_cnt = 0;
+	uint32_t temp1 = 0, temp2 = 0;
 
 	CDBG("vfe32_proc_general: cmdID = %s, length = %d\n",
 		vfe32_general_cmd[cmd->id], cmd->length);
@@ -1354,7 +1366,8 @@
 	case VFE_CMD_BLACK_LEVEL_CFG:
 		rc = -EFAULT;
 		goto proc_general_done;
-	case VFE_CMD_ROLL_OFF_CFG: {
+
+	case VFE_CMD_MESH_ROLL_OFF_CFG: {
 		cmdp = kmalloc(cmd->length, GFP_ATOMIC);
 		if (!cmdp) {
 			rc = -ENOMEM;
@@ -1369,19 +1382,19 @@
 		msm_io_memcpy(vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
 		cmdp_local, 16);
 		cmdp_local += 4;
-		vfe32_program_dmi_cfg(ROLLOFF_RAM);
+		vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
 		/* for loop for extrcting init table. */
-		for (i = 0 ; i < (VFE32_ROLL_OFF_INIT_TABLE_SIZE * 2) ; i++) {
+		for (i = 0; i < (V32_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2); i++) {
 			msm_io_w(*cmdp_local ,
 			vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
 			cmdp_local++;
 		}
 		CDBG("done writing init table\n");
 		/* by default, always starts with offset 0. */
-		msm_io_w(LENS_ROLL_OFF_DELTA_TABLE_OFFSET,
+		msm_io_w(V32_MESH_ROLL_OFF_DELTA_TABLE_OFFSET,
 		vfe32_ctrl->vfebase + VFE_DMI_ADDR);
 		/* for loop for extracting delta table. */
-		for (i = 0 ; i < (VFE32_ROLL_OFF_DELTA_TABLE_SIZE * 2) ; i++) {
+		for (i = 0; i < (V32_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2); i++) {
 			msm_io_w(*cmdp_local,
 			vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
 			cmdp_local++;
@@ -1792,7 +1805,114 @@
 			cmdp, (vfe32_cmd[cmd->id].length));
 		break;
 
-	default: {
+	case VFE_CMD_PCA_ROLL_OFF_CFG:
+		cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+		if (!cmdp) {
+			rc = -ENOMEM;
+			goto proc_general_done;
+		}
+		if (copy_from_user(cmdp,
+			(void __user *)(cmd->value) , cmd->length)) {
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+
+		cmdp_local = cmdp;
+
+		temp1 = *cmdp_local;
+		cmdp_local++;
+
+		msm_io_memcpy(vfe32_ctrl->vfebase + V33_PCA_ROLL_OFF_CFG_OFF1,
+			cmdp_local, V33_PCA_ROLL_OFF_CFG_LEN1);
+		cmdp_local += 4;
+		msm_io_memcpy(vfe32_ctrl->vfebase + V33_PCA_ROLL_OFF_CFG_OFF2,
+			cmdp_local, V33_PCA_ROLL_OFF_CFG_LEN2);
+
+		CDBG("%s: start writing RollOff Ram0 table\n", __func__);
+		vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+		msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
+			msm_io_w(*cmdp_local,
+				vfe32_ctrl->vfebase + VFE33_DMI_DATA_HI);
+			cmdp_local++;
+			msm_io_w(*cmdp_local,
+				vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+			cmdp_local++;
+		}
+		CDBG("%s: end writing RollOff Ram0 table\n", __func__);
+
+		CDBG("%s: start writing RollOff Ram1 table\n", __func__);
+		vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
+		msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
+			cmdp_local++;
+			msm_io_w(*cmdp_local,
+				vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+			cmdp_local++;
+		}
+		CDBG("%s: end writing RollOff Ram1 table\n", __func__);
+
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		break;
+
+	case VFE_CMD_PCA_ROLL_OFF_UPDATE:
+		cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+		if (!cmdp) {
+			rc = -ENOMEM;
+			goto proc_general_done;
+		}
+		if (copy_from_user(cmdp,
+			(void __user *)(cmd->value), cmd->length)) {
+			rc = -EFAULT;
+			goto proc_general_done;
+		}
+
+		cmdp_local = cmdp;
+
+		temp1 = *cmdp_local;
+		cmdp_local += 8;
+
+		temp2 = msm_io_r(vfe32_ctrl->vfebase +
+			V33_PCA_ROLL_OFF_CFG_OFF1)
+			& V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK;
+
+		CDBG("%s: start writing RollOff Ram0 table\n", __func__);
+		if (temp2)
+			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+		else
+			vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1);
+
+		msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
+			msm_io_w(*cmdp_local,
+				vfe32_ctrl->vfebase + VFE33_DMI_DATA_HI);
+			cmdp_local++;
+			msm_io_w(*cmdp_local,
+				vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+			cmdp_local++;
+		}
+		CDBG("%s: end writing RollOff Ram0 table\n", __func__);
+
+		CDBG("%s: start writing RollOff Ram1 table\n", __func__);
+		if (temp2)
+			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
+		else
+			vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1);
+
+		msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+		for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
+			cmdp_local++;
+			msm_io_w(*cmdp_local,
+				vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+			cmdp_local++;
+		}
+		CDBG("%s: end writing RollOff Ram1 table\n", __func__);
+
+		vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+		vfe32_ctrl->update_rolloff = true;
+		break;
+
+	default:
 		if (cmd->length != vfe32_cmd[cmd->id].length)
 			return -EINVAL;
 
@@ -1805,8 +1925,7 @@
 		CHECKED_COPY_FROM_USER(cmdp);
 		msm_io_memcpy(vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
 			cmdp, (vfe32_cmd[cmd->id].length));
-	}
-	break;
+		break;
 
 	}
 
@@ -2916,6 +3035,7 @@
 	vfe32_ctrl->vfemem = vfemem;
 	vfe32_ctrl->vfeio  = vfeio;
 	vfe32_ctrl->update_linear = false;
+	vfe32_ctrl->update_rolloff = false;
 	return 0;
 
 cmd_init_failed3:
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 820c5a4..2015a03 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -150,17 +150,15 @@
 #define VFE_REG_UPDATE_TRIGGER           1
 #define VFE_PM_BUF_MAX_CNT_MASK          0xFF
 #define VFE_DMI_CFG_DEFAULT              0x00000100
-#define LENS_ROLL_OFF_DELTA_TABLE_OFFSET 32
 #define VFE_AE_PINGPONG_STATUS_BIT       0x80
 #define VFE_AF_PINGPONG_STATUS_BIT       0x100
 #define VFE_AWB_PINGPONG_STATUS_BIT      0x200
 
-
 enum VFE32_DMI_RAM_SEL {
 	NO_MEM_SELECTED          = 0,
 	BLACK_LUT_RAM_BANK0      = 0x1,
 	BLACK_LUT_RAM_BANK1      = 0x2,
-	ROLLOFF_RAM              = 0x3,
+	ROLLOFF_RAM0_BANK0       = 0x3,
 	DEMOSAIC_LUT_RAM_BANK0   = 0x4,
 	DEMOSAIC_LUT_RAM_BANK1   = 0x5,
 	STATS_BHIST_RAM0         = 0x6,
@@ -175,7 +173,10 @@
 	RGBLUT_CHX_BANK1         = 0xf,
 	STATS_IHIST_RAM          = 0x10,
 	LUMA_ADAPT_LUT_RAM_BANK0 = 0x11,
-	LUMA_ADAPT_LUT_RAM_BANK1 = 0x12
+	LUMA_ADAPT_LUT_RAM_BANK1 = 0x12,
+	ROLLOFF_RAM1_BANK0       = 0x13,
+	ROLLOFF_RAM0_BANK1       = 0x14,
+	ROLLOFF_RAM1_BANK1       = 0x15,
 };
 
 enum  VFE_STATE {
@@ -247,8 +248,18 @@
 #define V32_BLACK_LEVEL_OFF 0x00000264
 #define V32_BLACK_LEVEL_LEN 16
 
-#define V32_ROLL_OFF_CFG_OFF 0x00000274
-#define V32_ROLL_OFF_CFG_LEN 16
+#define V32_MESH_ROLL_OFF_CFG_OFF             0x00000274
+#define V32_MESH_ROLL_OFF_CFG_LEN             16
+#define V32_MESH_ROLL_OFF_INIT_TABLE_SIZE     13
+#define V32_MESH_ROLL_OFF_DELTA_TABLE_SIZE    208
+#define V32_MESH_ROLL_OFF_DELTA_TABLE_OFFSET  32
+
+#define V33_PCA_ROLL_OFF_CFG_LEN1             16
+#define V33_PCA_ROLL_OFF_CFG_OFF1             0x00000274
+#define V33_PCA_ROLL_OFF_CFG_LEN2             12
+#define V33_PCA_ROLL_OFF_CFG_OFF2             0x000007A8
+#define V33_PCA_ROLL_OFF_TABLE_SIZE           (17 + (13*4))
+#define V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK    0x00010000
 
 #define V32_COLOR_COR_OFF 0x00000388
 #define V32_COLOR_COR_LEN 52
@@ -468,12 +479,6 @@
 	VFE_YUV_INTERPOLATED
 };
 
-
-/* 13*1  */
-#define VFE32_ROLL_OFF_INIT_TABLE_SIZE  13
-/* 13*16 */
-#define VFE32_ROLL_OFF_DELTA_TABLE_SIZE 208
-
 #define VFE32_GAMMA_NUM_ENTRIES  64
 
 #define VFE32_LA_TABLE_LENGTH    64
@@ -852,6 +857,9 @@
 #define VFE_BUS_IO_FORMAT_CFG		0x000006F8
 #define VFE_PIXEL_IF_CFG                0x000006FC
 
+#define VFE33_DMI_DATA_HI               0x000005A0
+#define VFE33_DMI_DATA_LO               0x000005A4
+
 #define VFE32_OUTPUT_MODE_PT (0x1 << 0)
 #define VFE32_OUTPUT_MODE_S (0x1 << 1)
 #define VFE32_OUTPUT_MODE_V (0x1 << 2)
@@ -889,6 +897,7 @@
 	int8_t update_ack_pending;
 	enum vfe_recording_state recording_state;
 	int8_t update_linear;
+	int8_t update_rolloff;
 
 	spinlock_t  tasklet_lock;
 	struct list_head tasklet_q;
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 75f975a..d57c4fb 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -53,7 +53,7 @@
 #define VFE_CMD_CAMIF_CFG                               7
 #define VFE_CMD_AXI_INPUT_CFG                           8
 #define VFE_CMD_BLACK_LEVEL_CFG                         9
-#define VFE_CMD_ROLL_OFF_CFG                            10
+#define VFE_CMD_MESH_ROLL_OFF_CFG                       10
 #define VFE_CMD_DEMUX_CFG                               11
 #define VFE_CMD_FOV_CFG                                 12
 #define VFE_CMD_MAIN_SCALER_CFG                         13
@@ -163,5 +163,7 @@
 #define VFE_CMD_CLF_CFG                                 117
 #define VFE_CMD_CLF_LUMA_UPDATE                         118
 #define VFE_CMD_CLF_CHROMA_UPDATE                       119
+#define VFE_CMD_PCA_ROLL_OFF_CFG                        120
+#define VFE_CMD_PCA_ROLL_OFF_UPDATE                     121
 
 #endif /* __MSM_ISP_H__ */