msm: camera: Add support for low power configuration in camera
Camera may run in a low power background mode. Configure the sensor
to run at lowest clock and vfe to request minimum bandwidth.
Change-Id: Idf6e5fb069c5a3cdbbbddb760614fee4510d81dc
Signed-off-by: Nishant Pandit <npandit@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index bc1eded..3955e77 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -356,6 +356,26 @@
},
};
+static struct msm_bus_vectors cam_low_power_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1451520,
+ .ib = 3870720,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
static struct msm_bus_paths cam_bus_client_config[] = {
{
@@ -386,6 +406,10 @@
ARRAY_SIZE(cam_dual_vectors),
cam_dual_vectors,
},
+ {
+ ARRAY_SIZE(cam_low_power_vectors),
+ cam_low_power_vectors,
+ },
};
static struct msm_bus_scale_pdata cam_bus_client_pdata = {
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 9f70ac2..ae496f9 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -634,6 +634,7 @@
S_DEFAULT,
S_LIVESHOT,
S_DUAL,
+ S_LOW_POWER,
S_EXIT
};
diff --git a/drivers/media/video/msm/io/msm_io_8960.c b/drivers/media/video/msm/io/msm_io_8960.c
index 808cc32..ab3ea5d 100644
--- a/drivers/media/video/msm/io/msm_io_8960.c
+++ b/drivers/media/video/msm/io/msm_io_8960.c
@@ -103,6 +103,14 @@
} else
CDBG("%s: Bus Client NOT Registered!!!\n", __func__);
break;
+ case S_LOW_POWER:
+ if (bus_perf_client) {
+ rc = msm_bus_scale_client_update_request(
+ bus_perf_client, 7);
+ CDBG("%s: S_LOW_POWER rc = %d\n", __func__, rc);
+ } else
+ CDBG("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
case S_DEFAULT:
break;
default:
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 3c8563b..3d14de5 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -533,6 +533,17 @@
}
break;
+ case MSM_CAM_IOCTL_AXI_LOW_POWER_MODE:
+ if (p_mctl->axi_sdev) {
+ v4l2_set_subdev_hostdata(p_mctl->axi_sdev, p_mctl);
+ rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+ VIDIOC_MSM_AXI_LOW_POWER_MODE,
+ (void __user *)arg);
+ } else {
+ rc = 0;
+ }
+ break;
+
default:
/* ISP config*/
D("%s:%d: go to default. Calling msm_isp_config\n",
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 999783e..ddadf0b 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -102,11 +102,12 @@
int32_t msm_sensor_write_init_settings(struct msm_sensor_ctrl_t *s_ctrl)
{
- int32_t rc;
- rc = msm_sensor_write_all_conf_array(
- s_ctrl->sensor_i2c_client,
- s_ctrl->msm_sensor_reg->init_settings,
- s_ctrl->msm_sensor_reg->init_size);
+ int32_t rc = 0;
+ if (s_ctrl->msm_sensor_reg->init_settings)
+ rc = msm_sensor_write_all_conf_array(
+ s_ctrl->sensor_i2c_client,
+ s_ctrl->msm_sensor_reg->init_settings,
+ s_ctrl->msm_sensor_reg->init_size);
return rc;
}
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index 281349f..1788779 100755
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -5758,6 +5758,7 @@
if (axi_ctrl->share_ctrl->axi_ref_cnt > 1)
return rc;
axi_ctrl->share_ctrl->dual_enabled = dual_enabled;
+ axi_ctrl->share_ctrl->lp_mode = 0;
spin_lock_init(&axi_ctrl->tasklet_lock);
INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
@@ -5916,6 +5917,23 @@
vfe32_ctrl->share_ctrl->vfebase);
}
+int msm_axi_set_low_power_mode(struct v4l2_subdev *sd, void *arg)
+{
+ uint8_t lp_mode = 0;
+ int rc = 0;
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ if (copy_from_user(&lp_mode,
+ (void __user *)(arg),
+ sizeof(uint8_t))) {
+ rc = -EFAULT;
+ return rc;
+ }
+ axi_ctrl->share_ctrl->lp_mode = lp_mode;
+ if (lp_mode)
+ axi_ctrl->share_ctrl->dual_enabled = 0;
+ return rc;
+}
+
void axi_abort(struct axi_ctrl_t *axi_ctrl)
{
uint8_t axi_busy_flag = true;
@@ -6144,9 +6162,14 @@
switch (vfe_params.cmd_type) {
case AXI_CMD_PREVIEW:
- if (!axi_ctrl->share_ctrl->dual_enabled)
+ if (axi_ctrl->share_ctrl->lp_mode)
msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ pmctl->sdata->pdata->cam_bus_scale_table,
+ S_LOW_POWER);
+ else if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table,
+ S_PREVIEW);
break;
case AXI_CMD_CAPTURE:
case AXI_CMD_RAW_CAPTURE:
@@ -6160,9 +6183,14 @@
pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
return;
case AXI_CMD_ZSL:
- if (!axi_ctrl->share_ctrl->dual_enabled)
+ if (axi_ctrl->share_ctrl->lp_mode)
msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
+ pmctl->sdata->pdata->cam_bus_scale_table,
+ S_LOW_POWER);
+ else if (!axi_ctrl->share_ctrl->dual_enabled)
+ msm_camio_bus_scale_cfg(
+ pmctl->sdata->pdata->cam_bus_scale_table,
+ S_ZSL);
break;
case AXI_CMD_LIVESHOT:
if (!axi_ctrl->share_ctrl->dual_enabled)
@@ -6978,6 +7006,9 @@
rc = msm_axi_subdev_init(sd, dual_enabled);
}
break;
+ case VIDIOC_MSM_AXI_LOW_POWER_MODE:
+ rc = msm_axi_set_low_power_mode(sd, arg);
+ break;
case VIDIOC_MSM_AXI_CFG:
rc = msm_axi_config(sd, arg);
break;
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/video/msm/vfe/msm_vfe32.h
index 1c1f441..0eae60cf 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.h
+++ b/drivers/media/video/msm/vfe/msm_vfe32.h
@@ -978,6 +978,7 @@
uint16_t cmd_type;
uint8_t vfe_reset_flag;
uint8_t dual_enabled;
+ uint8_t lp_mode;
uint8_t axi_ref_cnt;
uint16_t comp_output_mode;
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 18b641f..7241e90 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -243,8 +243,11 @@
#define MSM_CAM_IOCTL_V4L2_EVT_NATIVE_FRONT_CMD \
_IOWR(MSM_CAM_IOCTL_MAGIC, 69, struct msm_camera_v4l2_ioctl_t)
+#define MSM_CAM_IOCTL_AXI_LOW_POWER_MODE \
+ _IOWR(MSM_CAM_IOCTL_MAGIC, 70, uint8_t *)
+
#define MSM_CAM_IOCTL_INTF_MCTL_MAPPING_CFG \
- _IOR(MSM_CAM_IOCTL_MAGIC, 70, struct intf_mctl_mapping_cfg *)
+ _IOR(MSM_CAM_IOCTL_MAGIC, 71, struct intf_mctl_mapping_cfg *)
struct ioctl_native_cmd {
unsigned short mode;
@@ -2063,6 +2066,10 @@
#define VIDIOC_MSM_VFE_RELEASE \
_IO('V', BASE_VIDIOC_PRIVATE + 25)
+#define VIDIOC_MSM_AXI_LOW_POWER_MODE \
+ _IO('V', BASE_VIDIOC_PRIVATE + 26)
+
+
struct msm_camera_v4l2_ioctl_t {
uint32_t id;
uint32_t len;