msm: ais: Camera clock voting fixes for LA XO

AIS camera voting on VFE and ISPIF clocks cause XO shutdown failure.
So, add new AIS manager driver, to control AIS camera clock votes.
Also add a new method in early camera driver to turn on/off clocks
when it's needed.

Change-Id: I43090b51cb29ca9de62dfa191f77b7aa9dae8613
Signed-off-by: Rahul Sharma <sharah@codeaurora.org>
This commit is contained in:
Rahul Sharma 2018-01-04 12:27:55 +05:30 committed by Gerrit - the friendly Code Review server
parent 04b6b652ac
commit a211778552
18 changed files with 565 additions and 29 deletions

View file

@ -21,4 +21,5 @@ obj-$(CONFIG_MSM_AIS) += ispif/
obj-$(CONFIG_MSM_AIS_JPEG) += jpeg_10/
obj-$(CONFIG_MSM_AIS_JPEGDMA) += jpeg_dma/
obj-$(CONFIG_MSM_AIS) += msm_buf_mgr/
obj-$(CONFIG_MSM_AIS) += msm_ais_mgr/
obj-$(CONFIG_MSM_AIS_FD) += fd/

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -306,19 +306,12 @@ int msm_vfe47_init_hardware(struct vfe_device *vfe_dev)
vfe_dev->common_data->dual_vfe_res->vfe_base[vfe_dev->pdev->id] =
vfe_dev->vfe_base;
rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
MSM_ISP_MIN_AB, MSM_ISP_MIN_IB);
if (rc)
goto bw_enable_fail;
rc = msm_camera_enable_irq(vfe_dev->vfe_irq, 1);
if (rc < 0)
goto irq_enable_fail;
return rc;
irq_enable_fail:
msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id, 0, 0);
bw_enable_fail:
vfe_dev->common_data->dual_vfe_res->vfe_base[vfe_dev->pdev->id] = NULL;
if (cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SUSPEND_VOTE) < 0)
pr_err("%s: failed to remove vote for AHB\n", __func__);
@ -347,8 +340,6 @@ void msm_vfe47_release_hardware(struct vfe_device *vfe_dev)
vfe_dev->common_data->dual_vfe_res->vfe_base[vfe_dev->pdev->id] = NULL;
msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id, 0, 0);
if (vfe_dev->pdev->id == 0)
id = CAM_AHB_CLIENT_VFE0;
else

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -1106,9 +1106,11 @@ void msm_isp_calculate_bandwidth(
int bpp = 0;
if (stream_info->stream_src < RDI_INTF_0) {
stream_info->max_width = max(stream_info->max_width,
axi_data->src_info[VFE_PIX_0].width);
stream_info->bandwidth =
(axi_data->src_info[VFE_PIX_0].pixel_clock /
axi_data->src_info[VFE_PIX_0].width) *
(axi_data->src_info[VFE_PIX_0].pixel_clock *
axi_data->src_info[VFE_PIX_0].width) /
stream_info->max_width;
stream_info->bandwidth = (unsigned long)stream_info->bandwidth *
stream_info->format_factor / ISP_Q2;
@ -2272,8 +2274,7 @@ int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev,
total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
(total_bandwidth + vfe_dev->hw_info->min_ab),
(total_bandwidth + vfe_dev->hw_info->min_ib));
total_bandwidth, total_bandwidth);
if (rc < 0)
pr_err("%s: update failed\n", __func__);

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -2217,6 +2217,7 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
long rc = 0;
enum cam_ahb_clk_client id;
ISP_DBG("%s open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt);
@ -2291,6 +2292,17 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
cam_smmu_reg_client_page_fault_handler(
vfe_dev->buf_mgr->iommu_hdl,
msm_vfe_iommu_fault_handler, vfe_dev);
/* Disable vfe clks and allow device to go XO shutdown mode */
if (vfe_dev->pdev->id == 0)
id = CAM_AHB_CLIENT_VFE0;
else
id = CAM_AHB_CLIENT_VFE1;
if (cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SUSPEND_VOTE) < 0)
pr_err("%s: failed to remove vote for AHB\n", __func__);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_clks(vfe_dev, 0);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_regulators(vfe_dev, 0);
mutex_unlock(&vfe_dev->core_mutex);
mutex_unlock(&vfe_dev->realtime_mutex);
return 0;
@ -2313,11 +2325,22 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
long rc = 0;
int wm;
struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
enum cam_ahb_clk_client id;
ISP_DBG("%s E open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt);
mutex_lock(&vfe_dev->realtime_mutex);
mutex_lock(&vfe_dev->core_mutex);
/* Enable vfe clks to wake up from XO shutdown mode */
if (vfe_dev->pdev->id == 0)
id = CAM_AHB_CLIENT_VFE0;
else
id = CAM_AHB_CLIENT_VFE1;
if (cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SVS_VOTE) < 0)
pr_err("%s: failed to vote for AHB\n", __func__);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_clks(vfe_dev, 1);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_regulators(vfe_dev, 1);
if (!vfe_dev->vfe_open_cnt) {
pr_err("%s invalid state open cnt %d\n", __func__,
vfe_dev->vfe_open_cnt);

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -1437,13 +1437,6 @@ static int msm_ispif_init(struct ispif_device *ispif,
return -ENOMEM;
}
rc = cam_config_ahb_clk(NULL, 0,
CAM_AHB_CLIENT_ISPIF, CAM_AHB_SVS_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote for AHB\n", __func__);
return rc;
}
rc = msm_ispif_reset_hw(ispif);
if (rc)
goto error_ahb;
@ -1608,6 +1601,11 @@ static int ispif_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
rc = msm_camera_enable_irq(ispif->irq, 1);
if (rc)
goto irq_enable_fail;
/* Disable ispif clk and allow device to go XO shutdown */
msm_ispif_clk_ahb_enable(ispif, 0);
msm_ispif_set_regulators(ispif->ispif_vdd,
ispif->ispif_vdd_count, 0);
}
/* mem remap is done in init when the clock is on */
ispif->open_cnt++;
@ -1640,6 +1638,10 @@ static int ispif_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
}
ispif->open_cnt--;
if (ispif->open_cnt == 0) {
/* Enable ispif clk to wake up from XO shutdown mode */
msm_ispif_clk_ahb_enable(ispif, 1);
msm_ispif_set_regulators(ispif->ispif_vdd,
ispif->ispif_vdd_count, 1);
msm_ispif_release(ispif);
/* disable clocks and regulator on last close */
msm_ispif_clk_ahb_enable(ispif, 0);

View file

@ -0,0 +1,5 @@
ccflags-y += -Idrivers/media/platform/msm/ais
ccflags-y += -Idrivers/media/platform/msm/ais/common
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/io
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/cci
obj-$(CONFIG_MSM_AIS) += msm_ais_mgr.o

View file

@ -0,0 +1,147 @@
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) "CAM-BUFMGR %s:%d " fmt, __func__, __LINE__
#include <media/ais/msm_ais_mgr.h>
#include "msm_ais_mngr.h"
#include "msm_early_cam.h"
#undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
static struct msm_ais_mngr_device *msm_ais_mngr_dev;
static long msm_ais_hndl_ioctl(struct v4l2_subdev *sd, void *arg)
{
long rc = 0;
struct clk_mgr_cfg_data *pcdata = (struct clk_mgr_cfg_data *)arg;
struct msm_ais_mngr_device *clk_mngr_dev =
(struct msm_ais_mngr_device *)v4l2_get_subdevdata(sd);
if (WARN_ON(!clk_mngr_dev) || WARN_ON(!pcdata)) {
rc = -EINVAL;
return rc;
}
mutex_lock(&clk_mngr_dev->cont_mutex);
CDBG(pr_fmt("cfg_type = %d\n"), pcdata->cfg_type);
switch (pcdata->cfg_type) {
case AIS_CLK_ENABLE:
rc = msm_ais_enable_clocks();
break;
case AIS_CLK_DISABLE:
rc = msm_ais_disable_clocks();
break;
default:
pr_err("invalid cfg_type\n");
rc = -EINVAL;
}
mutex_unlock(&clk_mngr_dev->cont_mutex);
return rc;
}
static long msm_ais_mngr_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
int32_t rc = 0;
CDBG(pr_fmt("Enter\n"));
switch (cmd) {
case VIDIOC_MSM_AIS_CLK_CFG:
rc = msm_ais_hndl_ioctl(sd, arg);
if (rc)
pr_err("msm_ais_mngr_subdev_ioctl failed\n");
break;
default:
rc = -ENOIOCTLCMD;
}
CDBG(pr_fmt("Exit\n"));
return rc;
}
static struct v4l2_subdev_core_ops msm_ais_mngr_subdev_core_ops = {
.ioctl = msm_ais_mngr_subdev_ioctl,
};
static const struct v4l2_subdev_ops msm_ais_mngr_subdev_ops = {
.core = &msm_ais_mngr_subdev_core_ops,
};
static struct v4l2_file_operations msm_ais_v4l2_subdev_fops;
static long msm_clkmgr_subdev_do_ioctl(
struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
}
static long msm_ais_subdev_fops_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
return video_usercopy(file, cmd, arg, msm_clkmgr_subdev_do_ioctl);
}
static int32_t __init msm_ais_mngr_init(void)
{
int32_t rc = 0;
msm_ais_mngr_dev = kzalloc(sizeof(*msm_ais_mngr_dev),
GFP_KERNEL);
if (!msm_ais_mngr_dev)
return -ENOMEM;
/* Sub-dev */
v4l2_subdev_init(&msm_ais_mngr_dev->subdev.sd,
&msm_ais_mngr_subdev_ops);
msm_cam_copy_v4l2_subdev_fops(&msm_ais_v4l2_subdev_fops);
msm_ais_v4l2_subdev_fops.unlocked_ioctl = msm_ais_subdev_fops_ioctl;
snprintf(msm_ais_mngr_dev->subdev.sd.name,
ARRAY_SIZE(msm_ais_mngr_dev->subdev.sd.name), "msm_ais_mngr");
msm_ais_mngr_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
v4l2_set_subdevdata(&msm_ais_mngr_dev->subdev.sd, msm_ais_mngr_dev);
media_entity_init(&msm_ais_mngr_dev->subdev.sd.entity, 0, NULL, 0);
msm_ais_mngr_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
msm_ais_mngr_dev->subdev.sd.entity.group_id =
MSM_CAMERA_SUBDEV_AIS_MNGR;
msm_ais_mngr_dev->subdev.close_seq = MSM_SD_CLOSE_4TH_CATEGORY;
rc = msm_sd_register(&msm_ais_mngr_dev->subdev);
if (rc != 0) {
pr_err("msm_sd_register error = %d\n", rc);
kfree(msm_ais_mngr_dev);
return rc;
}
msm_ais_mngr_dev->subdev.sd.devnode->fops = &msm_ais_v4l2_subdev_fops;
mutex_init(&msm_ais_mngr_dev->cont_mutex);
return rc;
}
static void __exit msm_ais_mngr_exit(void)
{
msm_sd_unregister(&msm_ais_mngr_dev->subdev);
mutex_destroy(&msm_ais_mngr_dev->cont_mutex);
kfree(msm_ais_mngr_dev);
}
module_init(msm_ais_mngr_init);
module_exit(msm_ais_mngr_exit);
MODULE_DESCRIPTION("MSM AIS Manager");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,31 @@
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __MSM_CLK_GENERIC_MNGR_H__
#define __MSM_CLK_GENERIC_MNGR_H__
#include <linux/io.h>
#include <linux/of.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <media/v4l2-subdev.h>
#include <media/ais/msm_ais.h>
#include "msm.h"
#include "msm_sd.h"
struct msm_ais_mngr_device {
struct msm_sd_subdev subdev;
struct mutex cont_mutex;
};
#endif

View file

@ -1,5 +1,6 @@
ccflags-y += -Idrivers/media/platform/msm/ais
ccflags-y += -Idrivers/media/platform/msm/ais/common
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/io
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/cci
obj-$(CONFIG_MSM_AIS) += msm_cci.o
obj-$(CONFIG_MSM_AIS) += msm_early_cam.o

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -112,6 +112,199 @@ int msm_early_cam_disable_clocks(void)
pr_debug("Turned OFF camera clocks\n");
return 0;
}
int msm_ais_enable_clocks(void)
{
int rc = 0;
CDBG("%s:\n", __func__);
/* Vote ON for clocks */
if (new_early_cam_dev == NULL) {
rc = -EINVAL;
pr_err("%s: clock structure uninitialised %d\n", __func__,
rc);
return rc;
}
/* Vote for camera abh clocks */
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY,
CAM_AHB_SVS_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote for AHB\n", __func__);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSID,
CAM_AHB_SVS_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote for AHB\n", __func__);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_ISPIF,
CAM_AHB_SVS_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote for AHB\n", __func__);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_VFE0,
CAM_AHB_SVS_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote for AHB\n", __func__);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_VFE1,
CAM_AHB_SVS_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote for AHB\n", __func__);
return rc;
}
if (new_early_cam_dev->pdev->dev.of_node)
of_property_read_u32((&new_early_cam_dev->pdev->dev)->of_node,
"cell-index", &new_early_cam_dev->pdev->id);
rc = msm_camera_get_clk_info_and_rates(new_early_cam_dev->pdev,
&new_early_cam_dev->early_cam_clk_info,
&new_early_cam_dev->early_cam_clk,
&new_early_cam_dev->early_cam_clk_rates,
&new_early_cam_dev->num_clk_cases,
&new_early_cam_dev->num_clk);
if (rc < 0) {
pr_err("%s: msm_early_cam_get_clk_info() failed", __func__);
return -EFAULT;
}
rc = msm_camera_get_dt_vreg_data(
new_early_cam_dev->pdev->dev.of_node,
&(new_early_cam_dev->early_cam_vreg),
&(new_early_cam_dev->regulator_count));
if (rc < 0) {
pr_err("%s: msm_camera_get_dt_vreg_data fail\n", __func__);
rc = -EFAULT;
return rc;
}
if ((new_early_cam_dev->regulator_count < 0) ||
(new_early_cam_dev->regulator_count > MAX_REGULATOR)) {
pr_err("%s: invalid reg count = %d, max is %d\n", __func__,
new_early_cam_dev->regulator_count, MAX_REGULATOR);
rc = -EFAULT;
return rc;
}
rc = msm_camera_config_vreg(&new_early_cam_dev->pdev->dev,
new_early_cam_dev->early_cam_vreg,
new_early_cam_dev->regulator_count,
NULL,
0,
&new_early_cam_dev->early_cam_reg_ptr[0], 1);
if (rc < 0)
pr_err("%s:%d early_cam config_vreg failed\n", __func__,
__LINE__);
rc = msm_camera_enable_vreg(&new_early_cam_dev->pdev->dev,
new_early_cam_dev->early_cam_vreg,
new_early_cam_dev->regulator_count,
NULL,
0,
&new_early_cam_dev->early_cam_reg_ptr[0], 1);
if (rc < 0)
pr_err("%s:%d early_cam enable_vreg failed\n", __func__,
__LINE__);
rc = msm_camera_clk_enable(&new_early_cam_dev->pdev->dev,
new_early_cam_dev->early_cam_clk_info,
new_early_cam_dev->early_cam_clk,
new_early_cam_dev->num_clk, true);
if (rc < 0) {
pr_err("%s: clk enable failed %d\n", __func__, rc);
rc = 0;
return rc;
}
pr_debug("Turned ON camera clocks\n");
return 0;
}
int msm_ais_disable_clocks(void)
{
int rc = 0;
CDBG("%s:\n", __func__);
/* Vote OFF for clocks */
if (new_early_cam_dev == NULL) {
rc = -EINVAL;
pr_err("%s: clock structure uninitialised %d\n", __func__,
rc);
return rc;
}
if ((new_early_cam_dev->pdev == NULL) ||
(new_early_cam_dev->early_cam_clk_info == NULL) ||
(new_early_cam_dev->early_cam_clk == NULL) ||
(new_early_cam_dev->num_clk == 0)) {
rc = -EINVAL;
pr_err("%s: Clock details uninitialised %d\n", __func__,
rc);
return rc;
}
rc = msm_camera_clk_enable(&new_early_cam_dev->pdev->dev,
new_early_cam_dev->early_cam_clk_info,
new_early_cam_dev->early_cam_clk,
new_early_cam_dev->num_clk, false);
if (rc < 0) {
pr_err("%s: clk disable failed %d\n", __func__, rc);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY,
CAM_AHB_SUSPEND_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote OFF AHB_CLIENT_CSIPHY %d\n",
__func__, rc);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSID,
CAM_AHB_SUSPEND_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote OFF AHB_CLIENT_CSID %d\n",
__func__, rc);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_ISPIF,
CAM_AHB_SUSPEND_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote OFF AHB_CLIENT_ISPIF %d\n",
__func__, rc);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_VFE0,
CAM_AHB_SUSPEND_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote OFF AHB_CLIENT_VFE0 %d\n",
__func__, rc);
return rc;
}
rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_VFE1,
CAM_AHB_SUSPEND_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote OFF AHB_CLIENT_VFE0 %d\n",
__func__, rc);
return rc;
}
pr_debug("Turned OFF camera clocks\n");
return 0;
}
static int msm_early_cam_probe(struct platform_device *pdev)
{

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -20,6 +20,7 @@
#include <linux/workqueue.h>
#include <media/ais/msm_ais_sensor.h>
#include <soc/qcom/ais.h>
#include <media/ais/msm_ais.h>
#include "msm_sd.h"
#include "cam_soc_api.h"
@ -50,4 +51,6 @@ struct early_cam_device {
};
int msm_early_cam_disable_clocks(void);
int msm_ais_enable_clocks(void);
int msm_ais_disable_clocks(void);
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -1733,3 +1733,50 @@ int msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
return 0;
}
int msm_camera_cci_power_up(enum msm_camera_device_type_t device_type,
struct msm_camera_i2c_client *sensor_i2c_client)
{
int rc = 0;
CDBG("%s:%d\n", __func__, __LINE__);
if (!sensor_i2c_client) {
pr_err("failed sensor_i2c_client %pK\n",
sensor_i2c_client);
return -EINVAL;
}
if (device_type == MSM_CAMERA_PLATFORM_DEVICE) {
rc = sensor_i2c_client->i2c_func_tbl->i2c_util(
sensor_i2c_client, MSM_CCI_INIT);
if (rc < 0) {
pr_err("%s cci_init failed\n", __func__);
return rc;
}
}
CDBG("%s exit\n", __func__);
return rc;
}
int msm_camera_cci_power_down(enum msm_camera_device_type_t device_type,
struct msm_camera_i2c_client *sensor_i2c_client)
{
int rc = 0;
CDBG("%s:%d\n", __func__, __LINE__);
if (!sensor_i2c_client) {
pr_err("failed sensor_i2c_client %pK\n",
sensor_i2c_client);
return -EINVAL;
}
if (device_type == MSM_CAMERA_PLATFORM_DEVICE) {
rc = sensor_i2c_client->i2c_func_tbl->i2c_util(
sensor_i2c_client, MSM_CCI_RELEASE);
if (rc < 0) {
pr_err("%s MSM_CCI_RELEASE failed\n", __func__);
return rc;
}
}
CDBG("%s exit\n", __func__);
return rc;
}

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -68,4 +68,10 @@ int msm_cam_sensor_handle_reg_gpio(int seq_val,
int32_t msm_sensor_driver_get_gpio_data(
struct msm_camera_gpio_conf **gpio_conf,
struct device_node *of_node);
int msm_camera_cci_power_up(enum msm_camera_device_type_t device_type,
struct msm_camera_i2c_client *sensor_i2c_client);
int msm_camera_cci_power_down(enum msm_camera_device_type_t device_type,
struct msm_camera_i2c_client *sensor_i2c_client);
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -875,6 +875,30 @@ static int msm_sensor_config32(struct msm_sensor_ctrl_t *s_ctrl,
rc = -EFAULT;
}
break;
case CFG_CCI_POWER_UP:
if (s_ctrl->is_csid_tg_mode)
goto DONE;
rc = msm_camera_cci_power_up(s_ctrl->sensor_device_type,
s_ctrl->sensor_i2c_client);
if (rc < 0) {
pr_err("%s:%d failed rc %d\n", __func__,
__LINE__, rc);
break;
}
break;
case CFG_CCI_POWER_DOWN:
if (s_ctrl->is_csid_tg_mode)
goto DONE;
rc = msm_camera_cci_power_down(s_ctrl->sensor_device_type,
s_ctrl->sensor_i2c_client);
if (rc < 0) {
pr_err("%s:%d failed rc %d\n", __func__,
__LINE__, rc);
break;
}
break;
case CFG_SET_STOP_STREAM_SETTING: {
struct msm_camera_i2c_reg_setting32 stop_setting32;
struct msm_camera_i2c_reg_setting *stop_setting =
@ -1364,6 +1388,32 @@ int msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void *argp)
}
break;
case CFG_CCI_POWER_UP:
if (s_ctrl->is_csid_tg_mode)
goto DONE;
rc = msm_camera_cci_power_up(s_ctrl->sensor_device_type,
s_ctrl->sensor_i2c_client);
if (rc < 0) {
pr_err("%s:%d failed rc %d\n", __func__,
__LINE__, rc);
break;
}
break;
case CFG_CCI_POWER_DOWN:
if (s_ctrl->is_csid_tg_mode)
goto DONE;
rc = msm_camera_cci_power_down(s_ctrl->sensor_device_type,
s_ctrl->sensor_i2c_client);
if (rc < 0) {
pr_err("%s:%d failed rc %d\n", __func__,
__LINE__, rc);
break;
}
break;
case CFG_SET_STOP_STREAM_SETTING: {
struct msm_camera_i2c_reg_setting *stop_setting =
&s_ctrl->stop_setting;

View file

@ -4,3 +4,4 @@ header-y += msm_ais_isp.h
header-y += msm_ais_ispif.h
header-y += msm_ais_sensor.h
header-y += msm_ais_sensor_sdk.h
header-y += msm_ais_mgr.h

View file

@ -52,6 +52,7 @@
#define MSM_CAMERA_SUBDEV_IR_LED 18
#define MSM_CAMERA_SUBDEV_IR_CUT 19
#define MSM_CAMERA_SUBDEV_EXT 20
#define MSM_CAMERA_SUBDEV_AIS_MNGR 21
#define MSM_MAX_CAMERA_SENSORS 5

View file

@ -0,0 +1,28 @@
#ifndef __UAPI_MEDIA_MSM_AIS_MGR_H__
#define __UAPI_MEDIA_MSM_AIS_MGR_H__
#include <media/ais/msm_ais.h>
enum clk_mgr_cfg_type_t {
AIS_CLK_ENABLE,
AIS_CLK_DISABLE,
};
#define AIS_CLK_ENABLE AIS_CLK_ENABLE
#define AIS_CLK_DISABLE AIS_CLK_DISABLE
struct clk_mgr_cfg_data_ext {
enum clk_mgr_cfg_type_t cfg_type;
};
struct clk_mgr_cfg_data {
enum clk_mgr_cfg_type_t cfg_type;
};
#define VIDIOC_MSM_AIS_CLK_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE, struct clk_mgr_cfg_data)
#define VIDIOC_MSM_AIS_CLK_CFG_EXT \
_IOWR('V', BASE_VIDIOC_PRIVATE+1, struct clk_mgr_cfg_data_ext)
#endif /* __UAPI_MEDIA_MSM_AIS_MGR_H__ */

View file

@ -369,8 +369,13 @@ enum msm_sensor_cfg_type_t {
CFG_WRITE_I2C_ARRAY_ASYNC,
CFG_WRITE_I2C_ARRAY_SYNC,
CFG_WRITE_I2C_ARRAY_SYNC_BLOCK,
CFG_CCI_POWER_UP,
CFG_CCI_POWER_DOWN,
};
#define CFG_CCI_POWER_UP CFG_CCI_POWER_UP
#define CFG_CCI_POWER_DOWN CFG_CCI_POWER_DOWN
enum msm_actuator_cfg_type_t {
CFG_GET_ACTUATOR_INFO,
CFG_SET_ACTUATOR_INFO,