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:
parent
04b6b652ac
commit
a211778552
18 changed files with 565 additions and 29 deletions
|
@ -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/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
5
drivers/media/platform/msm/ais/msm_ais_mgr/Makefile
Normal file
5
drivers/media/platform/msm/ais/msm_ais_mgr/Makefile
Normal 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
|
147
drivers/media/platform/msm/ais/msm_ais_mgr/msm_ais_mgr.c
Normal file
147
drivers/media/platform/msm/ais/msm_ais_mgr/msm_ais_mgr.c
Normal 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");
|
31
drivers/media/platform/msm/ais/msm_ais_mgr/msm_ais_mngr.h
Normal file
31
drivers/media/platform/msm/ais/msm_ais_mgr/msm_ais_mngr.h
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
28
include/uapi/media/ais/msm_ais_mgr.h
Normal file
28
include/uapi/media/ais/msm_ais_mgr.h
Normal 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__ */
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue