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__ */