Merge "ARM: dts: msm: Enable early camera on msm8996 auto"

This commit is contained in:
Linux Build Service Account 2017-08-21 00:19:47 -07:00 committed by Gerrit - the friendly Code Review server
commit 42be98d03f
7 changed files with 668 additions and 4 deletions

View file

@ -0,0 +1,110 @@
* Qualcomm Technologies Inc MSM BA
[Root level node]
==================
Required properties:
- compatible: Must be "qcom,early-cam".
[Subnode]
==========
- qcom,early-cam-input-profile-#: Defines child nodes for the profiles supported
by early camera driver. Each profile should have properties
"mmagic-supply", "gdscr-supply", "vfe0-vdd-supply",
"qcom,cam-vreg-name", "clocks", "clock-names",
"qcom,clock-rates".
Required properties:
- mmagic-supply : should contain mmagic regulator used for mmagic clocks.
- gdscr-supply : should contain gdsr regulator used for cci clocks.
- vfe0-vdd-supply: phandle to vfe0 regulator.
- qcom,cam-vreg-name : name of the voltage regulators required for the device.
- clocks: List of clock handles. The parent clocks of the input clocks to the
devices in this power domain are set to oscclk before power gating
and restored back after powering on a domain. This is required for
all domains which are powered on and off and not required for unused
domains.
- clock-names: name of the clock used by the driver.
- qcom,clock-rates: clock rate in Hz.
Example:
qcom,early-cam {
cell-index = <0>;
compatible = "qcom,early-cam";
status = "ok";
mmagic-supply = <&gdsc_mmagic_camss>;
gdscr-supply = <&gdsc_camss_top>;
vfe0-vdd-supply = <&gdsc_vfe0>;
qcom,cam-vreg-name = "mmagic", "gdscr", "vfe0-vdd";
clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>,
<&clock_mmss clk_camss_top_ahb_clk>,
<&clock_mmss clk_cci_clk_src>,
<&clock_mmss clk_camss_cci_ahb_clk>,
<&clock_mmss clk_camss_cci_clk>,
<&clock_mmss clk_camss_ahb_clk>,
<&clock_mmss clk_mmagic_camss_axi_clk>,
<&clock_mmss clk_camss_vfe_ahb_clk>,
<&clock_mmss clk_camss_vfe0_ahb_clk>,
<&clock_mmss clk_camss_vfe_axi_clk>,
<&clock_mmss clk_camss_vfe0_stream_clk>,
<&clock_mmss clk_smmu_vfe_axi_clk>,
<&clock_mmss clk_smmu_vfe_ahb_clk>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
<&clock_mmss clk_vfe0_clk_src>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
<&clock_mmss clk_camss_csi2_ahb_clk>,
<&clock_mmss clk_camss_csi2_clk>,
<&clock_mmss clk_camss_csi2phy_clk>,
<&clock_mmss clk_csi2phytimer_clk_src>,
<&clock_mmss clk_camss_csi2phytimer_clk>,
<&clock_mmss clk_camss_csi2rdi_clk>,
<&clock_mmss clk_camss_ispif_ahb_clk>,
<&clock_mmss clk_camss_vfe0_clk>;
clock-names =
"mmss_mmagic_ahb_clk",
"camss_top_ahb_clk",
"cci_clk_src",
"camss_cci_ahb_clk",
"camss_cci_clk",
"camss_ahb_clk",
"mmagic_camss_axi_clk",
"camss_vfe_ahb_clk",
"camss_vfe0_ahb_clk",
"camss_vfe_axi_clk",
"camss_vfe0_stream_clk",
"smmu_vfe_axi_clk",
"smmu_vfe_ahb_clk",
"camss_csi_vfe0_clk",
"vfe0_clk_src",
"camss_csi_vfe0_clk",
"camss_csi2_ahb_clk",
"camss_csi2_clk",
"camss_csi2phy_clk",
"csi2phytimer_clk_src",
"camss_csi2phytimer_clk",
"camss_csi2rdi_clk",
"camss_ispif_ahb_clk",
"clk_camss_vfe0_clk";
qcom,clock-rates = <19200000
19200000
19200000
19200000
19200000
19200000
0
0
0
320000000
0
0
0
0
19200000
0
0
200000000
200000000
200000000
200000000
200000000
0
};

View file

@ -858,6 +858,90 @@
};
&soc {
qcom,early-cam {
cell-index = <0>;
compatible = "qcom,early-cam";
status = "ok";
mmagic-supply = <&gdsc_mmagic_camss>;
gdscr-supply = <&gdsc_camss_top>;
vfe0-vdd-supply = <&gdsc_vfe0>;
qcom,cam-vreg-name = "mmagic", "gdscr", "vfe0-vdd";
clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>,
<&clock_mmss clk_camss_top_ahb_clk>,
<&clock_mmss clk_cci_clk_src>,
<&clock_mmss clk_camss_cci_ahb_clk>,
<&clock_mmss clk_camss_cci_clk>,
<&clock_mmss clk_camss_ahb_clk>,
<&clock_mmss clk_mmagic_camss_axi_clk>,
<&clock_mmss clk_camss_vfe_ahb_clk>,
<&clock_mmss clk_camss_vfe0_ahb_clk>,
<&clock_mmss clk_camss_vfe_axi_clk>,
<&clock_mmss clk_camss_vfe0_stream_clk>,
<&clock_mmss clk_smmu_vfe_axi_clk>,
<&clock_mmss clk_smmu_vfe_ahb_clk>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
<&clock_mmss clk_vfe0_clk_src>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
<&clock_mmss clk_camss_csi2_ahb_clk>,
<&clock_mmss clk_camss_csi2_clk>,
<&clock_mmss clk_camss_csi2phy_clk>,
<&clock_mmss clk_csi2phytimer_clk_src>,
<&clock_mmss clk_camss_csi2phytimer_clk>,
<&clock_mmss clk_camss_csi2rdi_clk>,
<&clock_mmss clk_camss_ispif_ahb_clk>,
<&clock_mmss clk_camss_vfe0_clk>;
clock-names =
"mmss_mmagic_ahb_clk",
"camss_top_ahb_clk",
"cci_clk_src",
"camss_cci_ahb_clk",
"camss_cci_clk",
"camss_ahb_clk",
"mmagic_camss_axi_clk",
"camss_vfe_ahb_clk",
"camss_vfe0_ahb_clk",
"camss_vfe_axi_clk",
"camss_vfe0_stream_clk",
"smmu_vfe_axi_clk",
"smmu_vfe_ahb_clk",
"camss_csi_vfe0_clk",
"vfe0_clk_src",
"camss_csi_vfe0_clk",
"camss_csi2_ahb_clk",
"camss_csi2_clk",
"camss_csi2phy_clk",
"csi2phytimer_clk_src",
"camss_csi2phytimer_clk",
"camss_csi2rdi_clk",
"camss_ispif_ahb_clk",
"clk_camss_vfe0_clk";
qcom,clock-rates = <19200000
19200000
19200000
19200000
19200000
19200000
0
0
0
320000000
0
0
0
0
19200000
0
0
200000000
200000000
200000000
200000000
200000000
0
100000000>;
};
qcom,ntn_avb {
compatible = "qcom,ntn_avb";
@ -1457,11 +1541,21 @@
};
};
&vfe_smmu {
qcom,no-smr-check;
};
/ {
reserved-memory {
lk_mem: lk_pool@91600000 {
reg = <0x0 0x91600000 0x0 0x600000>;
lk_mem: lk_pool@0x91600000 {
no-map;
reg = <0 0x91600000 0 0x00600000>;
label = "lk_pool";
};
early_camera_mem: early_camera_mem@b3fff000 {
reg = <0 0xb3fff000 0 0x800000>;
label = "early_camera_mem";
};
};
};

View file

@ -623,6 +623,90 @@
};
&soc {
qcom,early-cam {
cell-index = <0>;
compatible = "qcom,early-cam";
status = "ok";
mmagic-supply = <&gdsc_mmagic_camss>;
gdscr-supply = <&gdsc_camss_top>;
vfe0-vdd-supply = <&gdsc_vfe0>;
qcom,cam-vreg-name = "mmagic", "gdscr", "vfe0-vdd";
clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>,
<&clock_mmss clk_camss_top_ahb_clk>,
<&clock_mmss clk_cci_clk_src>,
<&clock_mmss clk_camss_cci_ahb_clk>,
<&clock_mmss clk_camss_cci_clk>,
<&clock_mmss clk_camss_ahb_clk>,
<&clock_mmss clk_mmagic_camss_axi_clk>,
<&clock_mmss clk_camss_vfe_ahb_clk>,
<&clock_mmss clk_camss_vfe0_ahb_clk>,
<&clock_mmss clk_camss_vfe_axi_clk>,
<&clock_mmss clk_camss_vfe0_stream_clk>,
<&clock_mmss clk_smmu_vfe_axi_clk>,
<&clock_mmss clk_smmu_vfe_ahb_clk>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
<&clock_mmss clk_vfe0_clk_src>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
<&clock_mmss clk_camss_csi2_ahb_clk>,
<&clock_mmss clk_camss_csi2_clk>,
<&clock_mmss clk_camss_csi2phy_clk>,
<&clock_mmss clk_csi2phytimer_clk_src>,
<&clock_mmss clk_camss_csi2phytimer_clk>,
<&clock_mmss clk_camss_csi2rdi_clk>,
<&clock_mmss clk_camss_ispif_ahb_clk>,
<&clock_mmss clk_camss_vfe0_clk>;
clock-names =
"mmss_mmagic_ahb_clk",
"camss_top_ahb_clk",
"cci_clk_src",
"camss_cci_ahb_clk",
"camss_cci_clk",
"camss_ahb_clk",
"mmagic_camss_axi_clk",
"camss_vfe_ahb_clk",
"camss_vfe0_ahb_clk",
"camss_vfe_axi_clk",
"camss_vfe0_stream_clk",
"smmu_vfe_axi_clk",
"smmu_vfe_ahb_clk",
"camss_csi_vfe0_clk",
"vfe0_clk_src",
"camss_csi_vfe0_clk",
"camss_csi2_ahb_clk",
"camss_csi2_clk",
"camss_csi2phy_clk",
"csi2phytimer_clk_src",
"camss_csi2phytimer_clk",
"camss_csi2rdi_clk",
"camss_ispif_ahb_clk",
"clk_camss_vfe0_clk";
qcom,clock-rates = <19200000
19200000
19200000
19200000
19200000
19200000
0
0
0
320000000
0
0
0
0
19200000
0
0
200000000
200000000
200000000
200000000
200000000
0
100000000>;
};
ntn1: ntn_avb@1 { /* Neutrno device on RC1*/
compatible = "qcom,ntn_avb";
@ -1231,12 +1315,22 @@
/delete-property/ qcom,spkr-sd-n-gpio;
};
&vfe_smmu {
qcom,no-smr-check;
};
/ {
reserved-memory {
lk_mem: lk_pool@91600000 {
reg = <0x0 0x91600000 0x0 0x600000>;
lk_mem: lk_pool@0x91600000 {
no-map;
reg = <0 0x91600000 0 0x00600000>;
label = "lk_pool";
};
early_camera_mem: early_camera_mem@b3fff000 {
reg = <0 0xb3fff000 0 0x800000>;
label = "early_camera_mem";
};
};
};

View file

@ -2,3 +2,4 @@ ccflags-y += -Idrivers/media/platform/msm/ais
ccflags-y += -Idrivers/media/platform/msm/ais/common
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/io
obj-$(CONFIG_MSM_AIS) += msm_cci.o
obj-$(CONFIG_MSM_AIS) += msm_early_cam.o

View file

@ -0,0 +1,279 @@
/* Copyright (c) 2017, 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.
*/
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include "msm_sd.h"
#include "msm_early_cam.h"
#include "msm_cam_cci_hwreg.h"
#include "msm_camera_io_util.h"
#include "msm_camera_dt_util.h"
#include "cam_hw_ops.h"
#undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#undef EARLY_CAM_DBG
#ifdef MSM_EARLY_CAM_DEBUG
#define EARLY_CAM_DBG(fmt, args...) pr_err(fmt, ##args)
#else
#define EARLY_CAM_DBG(fmt, args...) pr_debug(fmt, ##args)
#endif
#define MSM_EARLY_CAM_DRV_NAME "msm_early_cam"
static struct platform_driver msm_early_camera_driver;
static struct early_cam_device *new_early_cam_dev;
int msm_early_cam_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_CCI,
CAM_AHB_SUSPEND_VOTE);
if (rc < 0) {
pr_err("%s: failed to vote OFF AHB_CLIENT_CCI %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;
}
pr_debug("Turned OFF camera clocks\n");
return 0;
}
static int msm_early_cam_probe(struct platform_device *pdev)
{
int rc = 0;
CDBG("%s: pdev %pK device id = %d\n", __func__, pdev, pdev->id);
/* Vote for Early camera if enabled */
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_CCI,
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;
}
new_early_cam_dev = kzalloc(sizeof(struct early_cam_device),
GFP_KERNEL);
if (!new_early_cam_dev)
return -ENOMEM;
if (pdev->dev.of_node)
of_property_read_u32((&pdev->dev)->of_node,
"cell-index", &pdev->id);
rc = msm_camera_get_clk_info_and_rates(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__);
kfree(new_early_cam_dev);
return -EFAULT;
}
new_early_cam_dev->ref_count = 0;
new_early_cam_dev->pdev = pdev;
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;
goto early_cam_release_mem;
}
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;
goto early_cam_invalid_vreg_data;
}
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;
goto early_cam_release_mem;
}
platform_set_drvdata(pdev, new_early_cam_dev);
return 0;
early_cam_invalid_vreg_data:
kfree(new_early_cam_dev->early_cam_vreg);
early_cam_release_mem:
kfree(new_early_cam_dev);
new_early_cam_dev = NULL;
return rc;
}
static int msm_early_cam_exit(struct platform_device *pdev)
{
return 0;
}
static int __init msm_early_cam_init_module(void)
{
return platform_driver_register(&msm_early_camera_driver);
}
static void __exit msm_early_cam_exit_module(void)
{
kfree(new_early_cam_dev);
platform_driver_unregister(&msm_early_camera_driver);
}
static const struct of_device_id msm_early_camera_match_table[] = {
{ .compatible = "qcom,early-cam" },
{},
};
static struct platform_driver msm_early_camera_driver = {
.probe = msm_early_cam_probe,
.remove = msm_early_cam_exit,
.driver = {
.name = MSM_EARLY_CAM_DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = msm_early_camera_match_table,
},
};
MODULE_DEVICE_TABLE(of, msm_early_camera_match_table);
module_init(msm_early_cam_init_module);
module_exit(msm_early_cam_exit_module);
MODULE_DESCRIPTION("MSM early camera driver");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,53 @@
/* Copyright (c) 2012-2017, 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_EARLY_CAM_H
#define MSM_EARLY_CAM_H
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <media/v4l2-subdev.h>
#include <linux/workqueue.h>
#include <media/ais/msm_ais_sensor.h>
#include <soc/qcom/ais.h>
#include "msm_sd.h"
#include "cam_soc_api.h"
#define NUM_MASTERS 2
#define NUM_QUEUES 2
#define TRUE 1
#define FALSE 0
enum msm_early_cam_state_t {
STATE_DISABLED,
STATE_ENABLED,
};
struct early_cam_device {
struct platform_device *pdev;
uint8_t ref_count;
enum msm_early_cam_state_t early_cam_state;
size_t num_clk;
size_t num_clk_cases;
struct clk **early_cam_clk;
uint32_t **early_cam_clk_rates;
struct msm_cam_clk_info *early_cam_clk_info;
struct camera_vreg_t *early_cam_vreg;
struct regulator *early_cam_reg_ptr[MAX_REGULATOR];
int32_t regulator_count;
};
int msm_early_cam_disable_clocks(void);
#endif

View file

@ -16,11 +16,17 @@
#include "msm_sensor_driver.h"
#include "msm_sensor.h"
#include "msm_sd.h"
#include "msm_camera_io_util.h"
#include "msm_early_cam.h"
/* Logging macro */
#undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#define EARLY_CAMERA_SIGNAL_DONE 0xa5a5a5a5
#define EARLY_CAMERA_SIGNAL_DISABLED 0
static bool early_camera_clock_off;
static struct msm_sensor_init_t *s_init;
static int msm_sensor_wait_for_probe_done(struct msm_sensor_init_t *s_init)
@ -42,10 +48,14 @@ static int msm_sensor_wait_for_probe_done(struct msm_sensor_init_t *s_init)
return rc;
}
#define MMSS_A_VFE_0_SPARE 0xC84
/* Static function definition */
int32_t msm_sensor_driver_cmd(struct msm_sensor_init_t *s_init, void *arg)
{
int32_t rc = 0;
u32 val = 0;
void __iomem *base;
struct sensor_init_cfg_data *cfg = (struct sensor_init_cfg_data *)arg;
/* Validate input parameters */
@ -68,6 +78,28 @@ int32_t msm_sensor_driver_cmd(struct msm_sensor_init_t *s_init, void *arg)
break;
case CFG_SINIT_PROBE_DONE:
if (early_camera_clock_off == false) {
base = ioremap(0x00A10000, 0x1000);
val = msm_camera_io_r_mb(base + MMSS_A_VFE_0_SPARE);
while (val != EARLY_CAMERA_SIGNAL_DONE) {
if (val == EARLY_CAMERA_SIGNAL_DISABLED)
break;
msleep(1000);
val = msm_camera_io_r_mb(
base + MMSS_A_VFE_0_SPARE);
pr_err("Waiting for signal from LK val = %u\n",
val);
}
rc = msm_early_cam_disable_clocks();
if (rc < 0) {
pr_err("Failed to disable early camera :%d\n",
rc);
} else {
early_camera_clock_off = true;
pr_debug("Voted OFF early camera clocks\n");
}
}
s_init->module_init_status = 1;
wake_up(&s_init->state_wait);
break;
@ -99,6 +131,7 @@ static int __init msm_sensor_init_module(void)
mutex_init(&s_init->imutex);
init_waitqueue_head(&s_init->state_wait);
early_camera_clock_off = false;
return ret;
}