Merge tag 'MMI-U1UGS34.23-110-23-2' of https://github.com/MotorolaMobilityLLC/kernel-msm-5.4-techpack-camera into lineage-22.2

Fogos push for Android 14

* tag 'MMI-U1UGS34.23-110-23-2' of https://github.com/MotorolaMobilityLLC/kernel-msm-5.4-techpack-camera: (86 commits)
  fogo: fix tombstone when use secure camera
  fogo: Fix secure mode switch error (2/2)
  Bangkk: reset ois when read standby_flag fail
  fogos: Actuator noise reduction[2/2]
  fogor: Actuator noise reduction[2/2]
  bangkk: Powerup and initialize sensor early [3/4]
  bangkk: Fix flash request GPIO-24 failed
  bangkk: support dw9784 af drift
  bangkk: Open Camera preview will be black then camera error
  bangkk: open Camera preview may be black sometimes
  bangkk: dw9784 ois bring up
  bangkk: Secondary supply flash driver ic compatible
  Tundra: restore ois delete submit
  Tundra: add delay at check ois data_ready
  Revert "(CR): milanf: modify ois vsync irq processing flow"
  penang: Adjust actuator noise reduction
  penang: Adjust actuator noise reduction
  penang: Actuator noise reduction
  milanf: modify ois vsync irq processing flow
  camera: ois: avoid ois power down twice when download firmware failed
  ...

 Conflicts:
	techpack/camera/drivers/cam_sensor_module/cam_ois/cam_ois_core.c

Change-Id: I9aa733fcd4412059a267c7cb9408b05e91eba111
This commit is contained in:
Michael Bestas 2025-03-21 18:36:20 +02:00
commit 9ca541ecda
No known key found for this signature in database
45 changed files with 8194 additions and 76 deletions

View file

@ -8,3 +8,4 @@
#define CONFIG_SPECTRA_OPE 1
#define CONFIG_SPECTRA_TFE 1
#define CONFIG_SPECTRA_SENSOR 1

View file

@ -162,6 +162,9 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \
cam_sensor_module/cam_ois/cam_ois_dev.o \
cam_sensor_module/cam_ois/cam_ois_core.o \
cam_sensor_module/cam_ois/cam_ois_soc.o \
cam_sensor_module/cam_ois/cam_ois_dw9781.o \
cam_sensor_module/cam_ois/cam_ois_dw9784.o \
cam_sensor_module/cam_ois/cam_ois_aw86006.o \
cam_sensor_module/cam_sensor/cam_sensor_dev.o \
cam_sensor_module/cam_sensor/cam_sensor_core.o \
cam_sensor_module/cam_sensor/cam_sensor_soc.o \
@ -170,8 +173,15 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \
cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.o \
cam_sensor_module/cam_sensor_io/cam_sensor_spi.o \
cam_sensor_module/cam_sensor_utils/cam_sensor_util.o \
cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.o \
cam_sensor_module/cam_res_mgr/cam_res_mgr.o
ifneq (,$(filter $(CONFIG_AF_NOISE_ELIMINATION), y m))
camera-$(CONFIG_SPECTRA_SENSOR) += \
cam_sensor_module/cam_actuator/mot_actuator.o \
cam_sensor_module/cam_actuator/mot_actuator_policy.o
endif
camera-$(CONFIG_LEDS_QPNP_FLASH_V2) += \
cam_sensor_module/cam_flash/cam_flash_dev.o \
cam_sensor_module/cam_flash/cam_flash_core.o \

View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CAM_HW_MGR_INTF_H_
@ -26,6 +27,12 @@
/* Maximum reg dump cmd buffer entries in a context */
#define CAM_REG_DUMP_MAX_BUF_ENTRIES 10
/*
* This value should align with MAX requests supported by
* hw modules like ICP, IFE, JPEG etc.
*/
#define CAM_MAX_FLUSH_REQS 40
/**
* enum cam_context_dump_id -
* context dump type
@ -289,9 +296,9 @@ struct cam_hw_config_args {
struct cam_hw_flush_args {
void *ctxt_to_hw_map;
uint32_t num_req_pending;
void *flush_req_pending[20];
void *flush_req_pending[CAM_MAX_FLUSH_REQS];
uint32_t num_req_active;
void *flush_req_active[20];
void *flush_req_active[CAM_MAX_FLUSH_REQS];
enum flush_type_t flush_type;
uint32_t last_flush_req;
};

View file

@ -3350,7 +3350,7 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv,
prepare_args->priv = ctx_data->req_list[request_idx];
prepare_args->pf_data->packet = packet;
prepare_args->pf_data->req = ope_req;
CAM_INFO(CAM_REQ, "OPE req %x num_batch %d", ope_req, ope_req->num_batch);
CAM_DBG(CAM_REQ, "OPE req %x num_batch %d", ope_req, ope_req->num_batch);
ope_req->hang_data.packet = packet;
ktime_get_boottime_ts64(&ts);
ctx_data->last_req_time = (uint64_t)((ts.tv_sec * 1000000000) +

View file

@ -11,6 +11,15 @@
#include "cam_trace.h"
#include "cam_common_util.h"
#include "cam_packet_util.h"
#ifdef CONFIG_AF_NOISE_ELIMINATION
#include "mot_actuator_policy.h"
#include "mot_actuator.h"
#endif
#ifdef CONFIG_MOT_DONGWOON_OIS_AF_DRIFT
extern int cam_ois_get_init_info(void);
extern int cam_ois_write_af_drift(uint32_t dac);
#endif
int32_t cam_actuator_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@ -160,8 +169,17 @@ static int32_t cam_actuator_i2c_modes_util(
uint32_t i, size;
if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) {
rc = camera_io_dev_write(io_master_info,
&(i2c_list->i2c_settings));
// if meet cci fail, retry 5 times, each time dealy 1.5ms.
for (i = 0; i < 5; i++) {
rc = camera_io_dev_write(io_master_info,
&(i2c_list->i2c_settings));
if (rc >= 0)
break;
usleep_range(1000, 1500);
}
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to random write I2C settings: %d",
@ -251,6 +269,11 @@ int32_t cam_actuator_apply_settings(struct cam_actuator_ctrl_t *a_ctrl,
struct i2c_settings_list *i2c_list;
int32_t rc = 0;
#ifdef CONFIG_MOT_DONGWOON_OIS_AF_DRIFT
struct cam_sensor_i2c_reg_setting * i2c_reg = NULL;
uint32_t dac = 0;
#endif
if (a_ctrl == NULL || i2c_set == NULL) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
@ -260,7 +283,13 @@ int32_t cam_actuator_apply_settings(struct cam_actuator_ctrl_t *a_ctrl,
CAM_ERR(CAM_ACTUATOR, " Invalid settings");
return -EINVAL;
}
#ifdef CONFIG_AF_NOISE_ELIMINATION
/*Usually actuator initial setting will execute power down reset(PD), actuator can't respond
CCI access for a while after PD. Add lock to avoid access actuator while PD operation.*/
if (a_ctrl->is_multi_user_supported) {
mot_actuator_lock();
}
#endif
list_for_each_entry(i2c_list,
&(i2c_set->list_head), list) {
rc = cam_actuator_i2c_modes_util(
@ -274,9 +303,47 @@ int32_t cam_actuator_apply_settings(struct cam_actuator_ctrl_t *a_ctrl,
CAM_DBG(CAM_ACTUATOR,
"Success:request ID: %d",
i2c_set->request_id);
#ifdef CONFIG_MOT_DONGWOON_OIS_AF_DRIFT
if (a_ctrl->af_drift_supported == true &&
(cam_ois_get_init_info() == 1) &&
i2c_list != NULL) {
#define ADDR_ACTUATOR 0x18
#define REG_ACTUATOR 0x00
#define DATA_SHIFT 4
i2c_reg = &(i2c_list->i2c_settings);
if (i2c_reg != NULL &&
i2c_reg->reg_setting != NULL &&
a_ctrl->io_master_info.cci_client != NULL &&
a_ctrl->io_master_info.cci_client->sid == (ADDR_ACTUATOR >> 1) &&
i2c_reg->addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE &&
i2c_reg->data_type == CAMERA_SENSOR_I2C_TYPE_WORD &&
i2c_reg->reg_setting[0].reg_data != 0 &&
i2c_reg->reg_setting[0].reg_addr == REG_ACTUATOR)
{
dac = i2c_reg->reg_setting[0].reg_data >> DATA_SHIFT;
rc = cam_ois_write_af_drift(dac);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Failed to apply af drift settings: %d", rc);
rc = 0; // avoid broken actuator function
}
}
}
#endif
}
}
#ifdef CONFIG_AF_NOISE_ELIMINATION
/*Usually actuator initial setting will execute power down reset(PD), actuator can't respond
CCI access for a while after PD. Add lock to avoid access actuator while PD operation.*/
if (a_ctrl->is_multi_user_supported) {
mot_actuator_unlock();
}
#endif
return rc;
}
@ -593,6 +660,15 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
cam_mem_put_cpu_buf(cmd_desc[i].mem_handle);
}
#ifdef CONFIG_AF_NOISE_ELIMINATION
if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE &&
a_ctrl->is_multi_user_supported == true) {
/*exile vibrator when camera want to take control of actuator*/
mot_actuator_handle_exile();
mot_actuator_get(ACTUATOR_CLIENT_CAMERA);
}
#endif
if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE) {
rc = cam_actuator_power_up(a_ctrl);
if (rc < 0) {
@ -606,6 +682,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
rc = cam_actuator_apply_settings(a_ctrl,
&a_ctrl->i2c_data.init_settings);
if (rc < 0) {
delete_request(&a_ctrl->i2c_data.init_settings);
CAM_ERR(CAM_ACTUATOR, "Cannot apply Init settings");
goto end;
}
@ -902,6 +979,11 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl,
}
if (a_ctrl->cam_act_state == CAM_ACTUATOR_CONFIG) {
#ifdef CONFIG_AF_NOISE_ELIMINATION
if (a_ctrl->is_multi_user_supported == true) {
mot_actuator_put(ACTUATOR_CLIENT_CAMERA);
}
#endif
rc = cam_actuator_power_down(a_ctrl);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,

View file

@ -115,6 +115,12 @@ struct cam_actuator_ctrl_t {
struct cam_actuator_query_cap act_info;
struct actuator_intf_params bridge_intf;
uint32_t last_flush_req;
#ifdef CONFIG_AF_NOISE_ELIMINATION
bool is_multi_user_supported;
#endif
#ifdef CONFIG_MOT_DONGWOON_OIS_AF_DRIFT
bool af_drift_supported;
#endif
};
/**

View file

@ -34,6 +34,24 @@ int32_t cam_actuator_parse_dt(struct cam_actuator_ctrl_t *a_ctrl,
of_node = soc_info->dev->of_node;
#ifdef CONFIG_AF_NOISE_ELIMINATION
if (!of_property_read_bool(of_node, "multi-user-support")) {
a_ctrl->is_multi_user_supported = false;
} else {
a_ctrl->is_multi_user_supported = true;
}
CAM_DBG(CAM_ACTUATOR, "multi-user-support %d", a_ctrl->is_multi_user_supported);
#endif
#ifdef CONFIG_MOT_DONGWOON_OIS_AF_DRIFT
if (!of_property_read_bool(of_node, "af-drift-support")) {
a_ctrl->af_drift_supported = false;
} else {
a_ctrl->af_drift_supported = true;
}
CAM_DBG(CAM_ACTUATOR, "af-drift-support %d", a_ctrl->af_drift_supported);
#endif
if (a_ctrl->io_master_info.master_type == CCI_MASTER) {
rc = of_property_read_u32(of_node, "cci-master",
&(a_ctrl->cci_i2c_master));

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,36 @@
#ifndef __MOT_ACTUATOR_H__
#define __MOT_ACTUATOR_H__
#include <linux/ioctl.h>
#include <linux/videodev2.h>
#define MOT_ACTUATOR_NAME "mot_actuator"
#define MOT_ACTUATOR_READ \
_IOWR('X', BASE_VIDIOC_PRIVATE + 50, int)
#define MOT_ACTUATOR_READ32 \
_IOWR('X', BASE_VIDIOC_PRIVATE + 50, int)
#define MOT_ACTUATOR_WRITE \
_IOWR('X', BASE_VIDIOC_PRIVATE + 51, int)
#define MOT_ACTUATOR_WRITE32 \
_IOWR('X', BASE_VIDIOC_PRIVATE + 51, int)
#define MOT_ACTUATOR_INIT \
_IOWR('X', BASE_VIDIOC_PRIVATE + 52, int)
#define MOT_ACTUATOR_INIT32 \
_IOWR('X', BASE_VIDIOC_PRIVATE + 52, int)
#define MOT_ACTUATOR_RELEASE \
_IOWR('X', BASE_VIDIOC_PRIVATE + 53, int)
#define MOT_ACTUATOR_RELEASE32 \
_IOWR('X', BASE_VIDIOC_PRIVATE + 53, int)
#define MOT_ACTUATOR_EXIT \
_IOWR('X', BASE_VIDIOC_PRIVATE + 54, int)
#define MOT_ACTUATOR_EXIT32 \
_IOWR('X', BASE_VIDIOC_PRIVATE + 54, int)
void mot_actuator_handle_exile(void);
int mot_actuator_driver_init(void);
void mot_actuator_driver_exit(void);
#endif /*__MOT_ACTUATOR_H__*/

View file

@ -0,0 +1,113 @@
/*
* Copyright (C) 2020 Motorola Mobility LLC.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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/module.h>
#include <linux/types.h>
#include "cam_debug_util.h"
#include "mot_actuator_policy.h"
extern int mot_actuator_on_vibrate_start(void);
extern int mot_actuator_on_vibrate_stop(void);
static atomic_t mot_actuator_ref_count = ATOMIC_INIT(0);
static unsigned long mot_actuator_consumers = ATOMIC_INIT(0);
static struct mutex actuator_res_lock = __MUTEX_INITIALIZER(actuator_res_lock);
int mot_actuator_get(mot_actuator_client user)
{
if (user <= ACTUATOR_CLIENT_INVALID || user >= ACTUATOR_CLIENT_MAX) {
CAM_ERR(CAM_ACTUATOR, "INVALID CLIENT!!!");
return 0;
}
CAM_DBG(CAM_ACTUATOR, "Obtain actuator from: %d", user);
test_and_set_bit(user, &mot_actuator_consumers);
return atomic_add_return(1, &mot_actuator_ref_count);
}
EXPORT_SYMBOL(mot_actuator_get);
int mot_actuator_put(mot_actuator_client user)
{
unsigned long consumers = 0;
if (user <= ACTUATOR_CLIENT_INVALID || user >= ACTUATOR_CLIENT_MAX) {
CAM_ERR(CAM_ACTUATOR, "INVALID CLIENT!!!");
return 0;
}
CAM_DBG(CAM_ACTUATOR, "Release actuator from: %d", user);
test_and_clear_bit(user, &mot_actuator_consumers);
consumers = mot_actuator_get_consumers();
if (((consumers & CLINET_VIBRATOR_MASK) == CLINET_VIBRATOR_MASK) &&
(user != ACTUATOR_CLIENT_VIBRATOR)) {
//If only vibrator noise eliminator exists, move lens to required position
CAM_DBG(CAM_ACTUATOR, "Set actuator pos for vibrator");
mot_actuator_on_vibrate_start();
if ((mot_actuator_get_consumers() & CLINET_VIBRATOR_MASK) == 0) {
mot_actuator_on_vibrate_stop();
}
}
return atomic_sub_return(1, &mot_actuator_ref_count);
}
EXPORT_SYMBOL(mot_actuator_put);
int mot_actuator_get_ref_count(void)
{
return atomic_read(&mot_actuator_ref_count);
}
EXPORT_SYMBOL(mot_actuator_get_ref_count);
unsigned int mot_actuator_get_consumers(void)
{
return mot_actuator_consumers;
}
EXPORT_SYMBOL(mot_actuator_get_consumers);
void mot_actuator_lock(void)
{
mutex_lock(&actuator_res_lock);
}
EXPORT_SYMBOL(mot_actuator_lock);
void mot_actuator_unlock(void)
{
mutex_unlock(&actuator_res_lock);
}
EXPORT_SYMBOL(mot_actuator_unlock);
ssize_t mot_actuator_dump(char *buf)
{
int item_len = 0;
unsigned int consumers = mot_actuator_get_consumers();
item_len += sprintf(buf+item_len, "refCount: %d\n", mot_actuator_get_ref_count());
item_len += sprintf(buf+item_len, "Consumers (0x%x):\n", consumers);
if (consumers & CLINET_CAMERA_MASK) {
item_len += sprintf(buf+item_len, "camera");
}
if (consumers & CLINET_VIBRATOR_MASK) {
item_len += sprintf(buf+item_len, " vibrator");
}
item_len += sprintf(buf+item_len, "\n");
CAM_DBG(CAM_ACTUATOR, "ref cnt:%d, consumers:0x%x", mot_actuator_get_ref_count(), mot_actuator_get_consumers());
return item_len;
}
EXPORT_SYMBOL(mot_actuator_dump);

View file

@ -0,0 +1,20 @@
#ifndef __MOT_ACTUATOR_POLICY_H__
#define __MOT_ACTUATOR_POLICY_H__
typedef enum {
ACTUATOR_CLIENT_INVALID,
ACTUATOR_CLIENT_CAMERA,
ACTUATOR_CLIENT_VIBRATOR,
ACTUATOR_CLIENT_MAX
} mot_actuator_client;
#define CLINET_CAMERA_MASK (0x01 << ACTUATOR_CLIENT_CAMERA)
#define CLINET_VIBRATOR_MASK (0x01 << ACTUATOR_CLIENT_VIBRATOR)
int mot_actuator_get(mot_actuator_client user);
int mot_actuator_put(mot_actuator_client user);
void mot_actuator_lock(void);
void mot_actuator_unlock(void);
ssize_t mot_actuator_dump(char *buf);
unsigned int mot_actuator_get_consumers(void);
#endif /*__MOT_ACTUATOR_POLICY_H__*/

View file

@ -212,7 +212,7 @@ void cam_cci_dump_registers(struct cci_device *cci_dev,
uint32_t reg_offset = 0;
void __iomem *base = cci_dev->soc_info.reg_map[0].mem_base;
dump_en = cci_dev->dump_en;
dump_en = cci_dev->dump_en = 6;
if (!(dump_en & CAM_CCI_NACK_DUMP_EN) &&
!(dump_en & CAM_CCI_TIMEOUT_DUMP_EN)) {
CAM_DBG(CAM_CCI,

View file

@ -28,6 +28,8 @@ struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index)
return sub_device;
}
EXPORT_SYMBOL(cam_cci_get_subdev);
static long cam_cci_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{

View file

@ -37,6 +37,10 @@
/* Mask to enable skew calibration registers */
#define SKEW_CAL_MASK 0x2
#ifdef CONFIG_MOT_SECURE_CAMERA
#define QCOM_SCM_EBUSY_MAX_RETRY 5
#endif
static DEFINE_MUTEX(active_csiphy_cnt_mutex);
static int csiphy_dump;
@ -1097,6 +1101,10 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_control *cmd = (struct cam_control *)arg;
int32_t rc = 0;
#ifdef CONFIG_MOT_SECURE_CAMERA
int32_t retry_count = 0;
#endif
if (!csiphy_dev || !cmd) {
CAM_ERR(CAM_CSIPHY, "Invalid input args");
return -EINVAL;
@ -1293,7 +1301,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
cam_csiphy_update_lane(csiphy_dev, offset, false);
goto release_mutex;
}
#ifndef CONFIG_MOT_SECURE_CAMERA
if (csiphy_dev->csiphy_info[offset].secure_mode)
cam_csiphy_notify_secure_mode(
csiphy_dev,
@ -1301,6 +1309,28 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
csiphy_dev->csiphy_info[offset].secure_mode =
CAM_SECURE_MODE_NON_SECURE;
#else
retry_count = 0;
retry_a:
retry_count++;
if (csiphy_dev->csiphy_info[offset].secure_mode) {
rc = cam_csiphy_notify_secure_mode(
csiphy_dev,
CAM_SECURE_MODE_NON_SECURE, offset);
if (rc <0 && retry_count <= QCOM_SCM_EBUSY_MAX_RETRY) {
CAM_INFO(CAM_CSIPHY, "CAM_STOP_PHYDEV: scm call with count: %d,",retry_count);
goto retry_a;
} else if (rc <0 && retry_count > QCOM_SCM_EBUSY_MAX_RETRY){
CAM_INFO(CAM_CSIPHY, "CAM_STOP_PHYDEV: notify secure mode finally failed scm call with count: %d,",retry_count);
}
}
csiphy_dev->csiphy_info[offset].secure_mode =
CAM_SECURE_MODE_NON_SECURE;
#endif
csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask = 0x0;
@ -1356,6 +1386,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
goto release_mutex;
}
#ifndef CONFIG_MOT_SECURE_CAMERA
if (csiphy_dev->csiphy_info[offset].secure_mode)
cam_csiphy_notify_secure_mode(
csiphy_dev,
@ -1363,6 +1394,26 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
csiphy_dev->csiphy_info[offset].secure_mode =
CAM_SECURE_MODE_NON_SECURE;
#else
retry_count = 0;
retry_b:
retry_count++;
if (csiphy_dev->csiphy_info[offset].secure_mode) {
rc = cam_csiphy_notify_secure_mode(
csiphy_dev,
CAM_SECURE_MODE_NON_SECURE, offset);
if (rc <0 && retry_count <= QCOM_SCM_EBUSY_MAX_RETRY) {
CAM_INFO(CAM_CSIPHY, "CAM_RELEASE_PHYDEV: scm call with count: %d,",retry_count);
goto retry_b;
} else if (rc <0 && retry_count > QCOM_SCM_EBUSY_MAX_RETRY){
CAM_INFO(CAM_CSIPHY, "CAM_RELEASE_PHYDEV: notify secure mode finally failed scm call with count: %d,",retry_count);
}
}
csiphy_dev->csiphy_info[offset].secure_mode =
CAM_SECURE_MODE_NON_SECURE;
#endif
csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0;

View file

@ -376,12 +376,22 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = {
{
.lane_identifier = CPHY_LANE_0,
.csiphy_data_rate_regs = {
#ifdef CONFIG_CAM_CTLE_ENABLE
{0x144, 0xB2, 0x00,
CSIPHY_DEFAULT_PARAMS},
#else
{0x144, 0xA2, 0x00,
CSIPHY_DEFAULT_PARAMS},
#endif
{0x988, 0x05, 0x00,
CSIPHY_DEFAULT_PARAMS},
#ifdef CONFIG_CAM_CTLE_ENABLE
{0x980, 0x60, 0x00,
CSIPHY_DEFAULT_PARAMS},
#else
{0x980, 0x61, 0x00,
CSIPHY_DEFAULT_PARAMS},
#endif
{0x9B4, 0x08, 0x0A,
CSIPHY_DEFAULT_PARAMS},
},
@ -389,12 +399,22 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = {
{
.lane_identifier = CPHY_LANE_1,
.csiphy_data_rate_regs = {
#ifdef CONFIG_CAM_CTLE_ENABLE
{0x344, 0xB2, 0x00,
CSIPHY_DEFAULT_PARAMS},
#else
{0x344, 0xA2, 0x00,
CSIPHY_DEFAULT_PARAMS},
#endif
{0xA88, 0x05, 0x00,
CSIPHY_DEFAULT_PARAMS},
#ifdef CONFIG_CAM_CTLE_ENABLE
{0xA80, 0x60, 0x00,
CSIPHY_DEFAULT_PARAMS},
#else
{0xA80, 0x61, 0x00,
CSIPHY_DEFAULT_PARAMS},
#endif
{0xAB4, 0x08, 0x0A,
CSIPHY_DEFAULT_PARAMS},
},
@ -402,12 +422,22 @@ struct data_rate_settings_t data_rate_delta_table_1_2_3 = {
{
.lane_identifier = CPHY_LANE_2,
.csiphy_data_rate_regs = {
#ifdef CONFIG_CAM_CTLE_ENABLE
{0x544, 0xB2, 0x00,
CSIPHY_DEFAULT_PARAMS},
#else
{0x544, 0xA2, 0x00,
CSIPHY_DEFAULT_PARAMS},
#endif
{0xB88, 0x05, 0x00,
CSIPHY_DEFAULT_PARAMS},
#ifdef CONFIG_CAM_CTLE_ENABLE
{0xB80, 0x60, 0x00,
CSIPHY_DEFAULT_PARAMS},
#else
{0xB80, 0x61, 0x00,
CSIPHY_DEFAULT_PARAMS},
#endif
{0xBB4, 0x08, 0x0A,
CSIPHY_DEFAULT_PARAMS},
},

View file

@ -13,9 +13,58 @@
#include "cam_packet_util.h"
#include <linux/math64.h>
#ifdef CONFIG_CAMERA_FLASH_PWM
#include "cam_sensor_util.h"
#include "../cam_flash_pm6125_gpio/pm6125_flash_gpio.h"
#endif
static uint default_on_timer = 2;
module_param(default_on_timer, uint, 0644);
static int flash_initstate = 0;
static struct i2c_settings_list* i2c_flash_off = NULL;
static struct i2c_settings_list*
cam_flash_get_i2c_ptr(struct i2c_settings_list *pi2c_list)
{
struct i2c_settings_list *tmp;
struct cam_sensor_i2c_reg_array *i2c_reg_settings =
pi2c_list->i2c_settings.reg_setting;
uint32_t size = pi2c_list->i2c_settings.size;
int i = 0;
tmp = kzalloc(sizeof(struct i2c_settings_list), GFP_KERNEL);
if (tmp == NULL) {
CAM_WARN(CAM_FLASH, "kzalloc failed");
return NULL;
}
tmp->i2c_settings.reg_setting = (struct cam_sensor_i2c_reg_array *)
vzalloc(size * sizeof(struct cam_sensor_i2c_reg_array));
if (tmp->i2c_settings.reg_setting == NULL) {
kfree(tmp);
CAM_WARN(CAM_FLASH, "vzalloc failed");
return NULL;
}
tmp->i2c_settings.size = size;
tmp->op_code = pi2c_list->op_code;
tmp->i2c_settings.addr_type = pi2c_list->i2c_settings.addr_type;
tmp->i2c_settings.data_type = pi2c_list->i2c_settings.data_type;
for( i = 0; i < size ; i++ ) {
tmp->i2c_settings.reg_setting[i].reg_addr =
i2c_reg_settings[i].reg_addr;
tmp->i2c_settings.reg_setting[i].reg_data =
i2c_reg_settings[i].reg_data;
tmp->i2c_settings.reg_setting[i].data_mask =
i2c_reg_settings[i].data_mask;
tmp->i2c_settings.reg_setting[i].delay =
i2c_reg_settings[i].delay;
}
return tmp;
}
int cam_flash_led_prepare(struct led_trigger *trigger, int options,
int *max_current, bool is_wled)
{
@ -290,6 +339,7 @@ int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl,
int i = 0;
uint32_t cancel_req_id_found = 0;
struct i2c_settings_array *i2c_set = NULL;
struct i2c_settings_list *i2c_list = NULL;
if (!fctrl) {
CAM_ERR(CAM_FLASH, "Device data is NULL");
@ -310,6 +360,17 @@ int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl,
continue;
if (i2c_set->is_settings_valid == 1) {
list_for_each_entry(i2c_list,
&(i2c_set->list_head), list) {
rc = cam_sensor_util_i2c_apply_setting(
&(fctrl->io_master_info),
i2c_list);
if (rc) {
CAM_ERR(CAM_FLASH,
"Failed to apply settings: %d",
rc);
}
}
rc = delete_request(i2c_set);
if (rc < 0)
CAM_ERR(CAM_FLASH,
@ -462,6 +523,11 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
{
int rc = 0;
#ifdef CONFIG_CAMERA_FLASH_PWM
struct cam_hw_soc_info soc_info = flash_ctrl->soc_info;
struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private;
#endif
if (!flash_ctrl) {
CAM_ERR(CAM_FLASH, "Flash control Null");
return -EINVAL;
@ -480,6 +546,19 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
"cannot apply streamoff settings");
}
}
if(i2c_flash_off)
{
CAM_DBG(CAM_FLASH, "i2c Flash OFF Triggered");
cam_sensor_util_i2c_apply_setting(&(flash_ctrl->io_master_info),
i2c_flash_off);
}
#ifdef CONFIG_CAMERA_FLASH_PWM
CAM_ERR(CAM_SENSOR,"cam_flash_off");
cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 0);
cam_res_mgr_gpio_free(soc_info.dev, soc_private->flash_gpio_enable);
pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_SUSPEND, CAMERA_SENSOR_FLASH_OP_OFF, 0);
#endif
return 0;
}
@ -489,6 +568,11 @@ static int cam_flash_low(
{
int i = 0, rc = 0;
#ifdef CONFIG_CAMERA_FLASH_PWM
struct cam_hw_soc_info soc_info = flash_ctrl->soc_info;
struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private;
#endif
if (!flash_data) {
CAM_ERR(CAM_FLASH, "Flash Data Null");
return -EINVAL;
@ -505,6 +589,19 @@ static int cam_flash_low(
if (rc)
CAM_ERR(CAM_FLASH, "Fire Torch failed: %d", rc);
#ifdef CONFIG_CAMERA_FLASH_PWM
CAM_DBG(CAM_FLASH, "Flash low Triggered flash_data->led_current_ma[0] = %u", flash_data->led_current_ma[0]);
rc = cam_res_mgr_gpio_request(soc_info.dev, soc_private->flash_gpio_enable, 0, "CUSTOM_GPIO1");
if(rc) {
CAM_ERR(CAM_FLASH, "gpio %d request fails", soc_private->flash_gpio_enable);
return rc;
}
cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 0);
pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_ACTIVE, CAMERA_SENSOR_FLASH_OP_FIRELOW, FLASH_FIRE_LOW_MAXCURRENT);
usleep_range(5000,6000);
pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_ACTIVE, CAMERA_SENSOR_FLASH_OP_FIRELOW, flash_data->led_current_ma[0]);
#endif
return rc;
}
@ -514,6 +611,11 @@ static int cam_flash_high(
{
int i = 0, rc = 0;
#ifdef CONFIG_CAMERA_FLASH_PWM
struct cam_hw_soc_info soc_info = flash_ctrl->soc_info;
struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private;
#endif
if (!flash_data) {
CAM_ERR(CAM_FLASH, "Flash Data Null");
return -EINVAL;
@ -530,6 +632,17 @@ static int cam_flash_high(
if (rc)
CAM_ERR(CAM_FLASH, "Fire Flash Failed: %d", rc);
#ifdef CONFIG_CAMERA_FLASH_PWM
CAM_DBG(CAM_FLASH, "Flash high Triggered flash_data->led_current_ma[0] = %u", flash_data->led_current_ma[0]);
rc = cam_res_mgr_gpio_request(soc_info.dev, soc_private->flash_gpio_enable, 0, "CUSTOM_GPIO1");
if(rc) {
CAM_ERR(CAM_FLASH, "gpio %d request fails", soc_private->flash_gpio_enable);
return rc;
}
cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 1);
pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_ACTIVE, CAMERA_SENSOR_FLASH_OP_FIREHIGH, flash_data->led_current_ma[0]);
#endif
return rc;
}
@ -706,6 +819,8 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl,
CAM_DBG(CAM_FLASH, "req_id=%llu", req_id);
if (req_id == 0) {
/* NonRealTime Init settings*/
if (fctrl->apply_streamoff == true) {
fctrl->apply_streamoff = false;
i2c_set = &fctrl->i2c_data.streamoff_settings;
@ -722,6 +837,9 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl,
break;
}
} else if (fctrl->i2c_data.init_settings.is_settings_valid == true) {
if(flash_initstate)
goto config_setting;
list_for_each_entry(i2c_list,
&(fctrl->i2c_data.init_settings.list_head),
list) {
@ -743,8 +861,14 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl,
rc);
return rc;
}
if((NULL != i2c_list) && (NULL == i2c_flash_off)) {
i2c_flash_off = cam_flash_get_i2c_ptr(i2c_list);
}
}
flash_initstate = CAM_FLASH_STATE_CONFIG;
}
config_setting:
/* NonRealTime (Widget/RER/INIT_FIRE settings) */
if (fctrl->i2c_data.config_settings.is_settings_valid == true) {
list_for_each_entry(i2c_list,
@ -1258,7 +1382,12 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
CAM_DBG(CAM_FLASH, "settings already valid");
i2c_reg_settings->request_id = 0;
i2c_reg_settings->is_settings_valid = false;
goto update_req_mgr;
//goto update_req_mgr;
rc = delete_request(i2c_reg_settings);
if (rc) {
CAM_ERR(CAM_FLASH, "Error deleting req: %d", rc);
return rc;
}
}
i2c_reg_settings->is_settings_valid = true;
i2c_reg_settings->request_id =
@ -2009,6 +2138,18 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl)
}
}
if(i2c_flash_off != NULL)
{
if(i2c_flash_off->i2c_settings.reg_setting != NULL) {
vfree(i2c_flash_off->i2c_settings.reg_setting);
i2c_flash_off->i2c_settings.reg_setting = NULL;
}
kfree(i2c_flash_off);
i2c_flash_off = NULL;
flash_initstate = 0;
}
if (fctrl->bridge_intf.device_hdl != 1) {
rc = cam_destroy_device_hdl(fctrl->bridge_intf.device_hdl);
if (rc)
@ -2078,3 +2219,98 @@ int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply)
return rc;
}
#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE
static int cam_flash_construct_power_vio_setting(
struct cam_sensor_power_ctrl_t *power_info)
{
int rc = 0;
power_info->power_setting_size = 2;
power_info->power_setting =
kzalloc(sizeof(struct cam_sensor_power_setting) * 2,
GFP_KERNEL);
if (!power_info->power_setting)
return -ENOMEM;
power_info->power_setting[0].seq_type = SENSOR_VIO;
power_info->power_setting[0].seq_val = CAM_VIO;
power_info->power_setting[0].config_val = 1;
power_info->power_setting[0].delay = 2;
power_info->power_setting[1].seq_type = SENSOR_CUSTOM_REG2;
power_info->power_setting[1].seq_val = 0;
power_info->power_setting[1].config_val = 1;
power_info->power_setting[1].delay = 0;
power_info->power_down_setting_size = 2;
power_info->power_down_setting =
kzalloc(sizeof(struct cam_sensor_power_setting) * 2,
GFP_KERNEL);
if (!power_info->power_down_setting) {
rc = -ENOMEM;
goto free_power_settings;
}
power_info->power_down_setting[0].seq_type = SENSOR_CUSTOM_REG2;
power_info->power_down_setting[0].seq_val = 0;
power_info->power_down_setting[0].config_val = 0;
power_info->power_down_setting[1].seq_type = SENSOR_VIO;
power_info->power_down_setting[1].seq_val = CAM_VIO;
power_info->power_down_setting[1].config_val = 0;
return rc;
free_power_settings:
kfree(power_info->power_setting);
power_info->power_setting = NULL;
power_info->power_setting_size = 0;
return rc;
}
int cam_flash_fill_vreg_setting(struct cam_flash_ctrl *fctrl)
{
int rc = 0;
rc = cam_flash_construct_power_vio_setting(
&fctrl->power_info);
if (rc) {
CAM_ERR(CAM_FLASH, "Failed Flash Power VIO Setting: rc=%d\n", rc);
return rc;
}
rc = msm_camera_fill_vreg_params(&fctrl->soc_info,
fctrl->power_info.power_setting,
fctrl->power_info.power_setting_size);
if(rc)
{
CAM_ERR(CAM_FLASH, "Failed Flash Fill Power Up Params: rc=%d\n", rc);
return rc;
}
rc = msm_camera_fill_vreg_params(&fctrl->soc_info,
fctrl->power_info.power_down_setting,
fctrl->power_info.power_down_setting_size);
if(rc)
{
CAM_ERR(CAM_FLASH, "Failed Flash Fill Power Down Params: rc=%d\n", rc);
return rc;
}
return rc;
}
int cam_flash_fill_i2c_default_setting(struct cam_flash_ctrl *fctrl, uint32_t slave_addr)
{
int rc = 0;
struct cam_cmd_i2c_info i2c_info={0};
i2c_info.slave_addr = slave_addr;
i2c_info.i2c_freq_mode = I2C_STANDARD_MODE;
rc = cam_flash_slaveInfo_pkt_parser(
fctrl, (uint32_t *)&i2c_info, sizeof(struct cam_cmd_i2c_info));
if (rc < 0) {
CAM_ERR(CAM_FLASH,
"Failed parsing slave info: rc: %d",
rc);
}
return rc;
}
#endif

View file

@ -9,6 +9,9 @@
#include "cam_flash_core.h"
#include "cam_common_util.h"
#include "camera_main.h"
#ifdef CONFIG_CAMERA_FLASH_PWM
#include "pm6125_flash_gpio.h"
#endif
static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
void *arg, struct cam_flash_private_soc *soc_private)
@ -138,10 +141,17 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
}
case CAM_QUERY_CAP: {
struct cam_flash_query_cap_info flash_cap = {0};
#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE
uint32_t flash_iic_supplier[3];
uint32_t flashid=0;
#endif
CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP");
flash_cap.slot_info = fctrl->soc_info.index;
flash_cap.flash_type = soc_private->flash_type;
CAM_DBG(CAM_FLASH, "dts flash_type is %d, it should same with camx&chi flash_type", soc_private->flash_type);
#ifdef CONFIG_CAMERA_FLASH_PWM
CAM_DBG(CAM_FLASH, "get flash_enabel_gpio %d", soc_private->flash_gpio_enable);
#endif
for (i = 0; i < fctrl->flash_num_sources; i++) {
flash_cap.max_current_flash[i] =
soc_private->flash_max_current[i];
@ -152,7 +162,39 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
for (i = 0; i < fctrl->torch_num_sources; i++)
flash_cap.max_current_torch[i] =
soc_private->torch_max_current[i];
#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE
rc = of_property_read_u32_array(fctrl->of_node, "distinguish-flash-supplier",
flash_iic_supplier, 3);
if (!rc) {
CAM_DBG(CAM_FLASH, "Distinguish IIC Flash Supplier dev:0x%x addr:0x%x data:0x%x",
flash_iic_supplier[0],flash_iic_supplier[1],flash_iic_supplier[2]);
if (cam_flash_fill_vreg_setting(fctrl)){
CAM_ERR(CAM_FLASH, "Flash Fill Vreg Failed");
goto release_mutex;
}
if (cam_flash_fill_i2c_default_setting(fctrl, flash_iic_supplier[0])){
CAM_ERR(CAM_FLASH, "Failed Flash Fill I2C Setting rc =%d",rc);
goto release_mutex;
}
if (fctrl->func_tbl.power_ops(fctrl, true)){
CAM_ERR(CAM_FLASH, "Power Up Failed");
goto release_mutex;
}
rc = camera_io_dev_read(&(fctrl->io_master_info),
flash_iic_supplier[1],&flashid,
CAMERA_SENSOR_I2C_TYPE_BYTE,
CAMERA_SENSOR_I2C_TYPE_BYTE);
CAM_DBG(CAM_FLASH, "flashid=%d",flashid);
if ((!rc) && (flashid == flash_iic_supplier[2]))
flash_cap.flash_supplier = 1;
else
flash_cap.flash_supplier = 0;
if (fctrl->func_tbl.power_ops(fctrl, false)){
CAM_ERR(CAM_FLASH, "Power Down Failed");
goto release_mutex;
}
}
#endif
if (copy_to_user(u64_to_user_ptr(cmd->handle),
&flash_cap, sizeof(struct cam_flash_query_cap_info))) {
CAM_ERR(CAM_FLASH, "Failed Copy to User");
@ -440,6 +482,9 @@ static int cam_flash_component_bind(struct device *dev,
fctrl->soc_info.dev_name = pdev->name;
platform_set_drvdata(pdev, fctrl);
#ifdef CONFIG_CAMERA_FLASH_PWM
dev_set_drvdata(&pdev->dev, fctrl);
#endif
rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info);
if (rc) {
@ -482,8 +527,9 @@ static int cam_flash_component_bind(struct device *dev,
rc = cam_sensor_util_init_gpio_pin_tbl(soc_info,
&fctrl->power_info.gpio_num_info);
if ((rc < 0) || (!fctrl->power_info.gpio_num_info)) {
CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs");
return -EINVAL;
//CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs");
//return -EINVAL;
CAM_WARN(CAM_FLASH, "No/Error Flash GPIOs");
}
rc = cam_sensor_util_regulator_powerup(soc_info);
if (rc < 0) {
@ -539,6 +585,9 @@ static int cam_flash_component_bind(struct device *dev,
fctrl->flash_state = CAM_FLASH_STATE_INIT;
CAM_DBG(CAM_FLASH, "Component bound successfully");
#ifdef CONFIG_CAMERA_FLASH_PWM
pm6125_flash_control_create_device(&pdev->dev);
#endif
return rc;
free_cci_resource:
@ -561,6 +610,10 @@ static void cam_flash_component_unbind(struct device *dev,
struct cam_flash_ctrl *fctrl;
struct platform_device *pdev = to_platform_device(dev);
#ifdef CONFIG_CAMERA_FLASH_PWM
pm6125_flash_control_remove_device(&pdev->dev);
#endif
fctrl = platform_get_drvdata(pdev);
if (!fctrl) {
CAM_ERR(CAM_FLASH, "Flash device is NULL");
@ -573,6 +626,9 @@ static void cam_flash_component_unbind(struct device *dev,
cam_unregister_subdev(&(fctrl->v4l2_dev_str));
cam_flash_put_source_node_data(fctrl);
platform_set_drvdata(pdev, NULL);
#ifdef CONFIG_CAMERA_FLASH_PWM
dev_set_drvdata(&pdev->dev, NULL);
#endif
v4l2_set_subdevdata(&fctrl->v4l2_dev_str.sd, NULL);
kfree(fctrl);
CAM_INFO(CAM_FLASH, "Flash Sensor component unbind");

View file

@ -153,6 +153,9 @@ struct cam_flash_private_soc {
uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
bool is_wled_flash;
uint32_t flash_type;
#ifdef CONFIG_CAMERA_FLASH_PWM
uint32_t flash_gpio_enable;
#endif
};
struct cam_flash_func_tbl {
@ -239,7 +242,10 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
enum cam_flash_flush_type, uint64_t req_id);
void cam_flash_shutdown(struct cam_flash_ctrl *fctrl);
int cam_flash_release_dev(struct cam_flash_ctrl *fctrl);
#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE
int cam_flash_fill_i2c_default_setting(struct cam_flash_ctrl *fctrl, uint32_t slave_addr);
int cam_flash_fill_vreg_setting(struct cam_flash_ctrl *fctrl);
#endif
/**
* @brief : API to register FLASH hw to platform framework.
* @return struct platform_device pointer on on success, or ERR_PTR() on error.

View file

@ -70,6 +70,10 @@ static int32_t cam_get_source_node_info(
struct device_node *flash_src_node = NULL;
struct device_node *torch_src_node = NULL;
struct device_node *switch_src_node = NULL;
#ifdef CONFIG_CAMERA_FLASH_PWM
int16_t gpio_array_size = 0;
uint16_t *gpio_array = NULL;
#endif
soc_private->is_wled_flash =
of_property_read_bool(of_node, "wled-flash-support");
@ -79,7 +83,29 @@ static int32_t cam_get_source_node_info(
CAM_ERR(CAM_FLASH,
"flash-type read failed rc=%d", rc);
soc_private->flash_type = CAM_FLASH_TYPE_PMIC; // default to PMIC flash
#ifdef CONFIG_CAMERA_FLASH_PWM
} else if(soc_private->flash_type == CAM_FLASH_TYPE_GPIO) {
gpio_array_size = of_gpio_count(of_node);
if (gpio_array_size == 1){
gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL);
if (!gpio_array) {
CAM_ERR(CAM_FLASH, "flash gpio array alloc fail");
} else {
for (i = 0; i < gpio_array_size; i++) {
gpio_array[i] = of_get_gpio(of_node, i);
CAM_DBG(CAM_FLASH, "flash dts gpio_array[%d] = %d name is %s %s", i, gpio_array[i], of_node->name, of_node->full_name);
}
soc_private->flash_gpio_enable = gpio_array[0];
CAM_DBG(CAM_FLASH, "flash gpio enable %d",soc_private->flash_gpio_enable);
kfree(gpio_array);
}
} else {
CAM_ERR(CAM_FLASH, "flash should have two gpio, first is enable in flash dts, second control by flash pm6125");
}
}
#else
}
#endif
switch_src_node = of_parse_phandle(of_node, "switch-source", 0);
if (!switch_src_node) {

View file

@ -0,0 +1,302 @@
/*
*Copyright (C) 2021 Motorola Mobility LLC,
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License 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/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pwm.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <media/rc-core.h>
#include <linux/platform_device.h>
#include "pm6125_flash_gpio.h"
#ifdef CONFIG_CAMERA_FLASH_PWM
#include "cam_flash_dev.h"
#include "cam_flash_soc.h"
#include "cam_flash_core.h"
#include "cam_common_util.h"
#include "cam_res_mgr_api.h"
#endif
/*****************************************************************************
* Data Structure
*****************************************************************************/
struct pwm_device *pwm;
#ifdef CONFIG_CAMERA_FLASH_PWM
static unsigned int flashlight_enable = CAMERA_SENSOR_FLASH_STATUS_OFF;
static unsigned int flashlight_brightness = 0;
#endif/*****************************************************************************
* Function
*****************************************************************************/
void pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE s, enum camera_flash_opcode opcode, u64 flash_current){
struct pwm_state pstate;
int rc = 0;
u64 real_current = 0;
pwm_get_state(pwm, &pstate);
PM6125_FLASH_PRINT("[pm6125_flash_gpio]Status duty_cycle = %u, period = %u\n",
pstate.duty_cycle, pstate.period);
pstate.period = PM6125_PWM_PERIOD;
switch (s) {
case PM6125_FLASH_GPIO_STATE_ACTIVE:
switch (opcode)
{
case CAMERA_SENSOR_FLASH_OP_FIRELOW:
real_current = (flash_current > FLASH_FIRE_LOW_MAXCURRENT?FLASH_FIRE_LOW_MAXCURRENT:flash_current);
pstate.duty_cycle = PM6125_PWM_PERIOD * real_current / FLASH_FIRE_LOW_MAXCURRENT;
break;
case CAMERA_SENSOR_FLASH_OP_FIREHIGH:
real_current = (flash_current > FLASH_FIRE_HIGH_MAXCURRENT?FLASH_FIRE_HIGH_MAXCURRENT:flash_current);
pstate.duty_cycle = PM6125_PWM_PERIOD * real_current / FLASH_FIRE_HIGH_MAXCURRENT;
break;
default:
pstate.duty_cycle = PM6125_PWM_PERIOD;
break;
}
pstate.enabled = true;
rc = pwm_apply_state(pwm, &pstate);
PM6125_FLASH_PRINT("[pm6125_flash_gpio]Active duty_cycle = %u, period = %u, opcode = %u, real_current = %u\n",
pstate.duty_cycle, pstate.period, opcode, real_current);
break;
case PM6125_FLASH_GPIO_STATE_SUSPEND:
pstate.enabled = false;
rc = pwm_apply_state(pwm, &pstate);
PM6125_FLASH_PRINT("[pm6125_flash_gpio]Suspend");
break;
default:
PM6125_FLASH_PRINT("[pm6125_flash_gpio]Failed to control PWM use a err state!\n");
}
if(rc < 0) {
PM6125_FLASH_PRINT("[pm6125_flash_gpio]Apply PWM state fail, rc = %d", rc);
}
}
#ifdef CONFIG_CAMERA_FLASH_PWM
static ssize_t flashlight_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%u\n", flashlight_enable);
}
static ssize_t flashlight_enable_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct cam_flash_ctrl *fctrl = dev_get_drvdata(dev);
struct cam_flash_private_soc *soc_private = fctrl->soc_info.soc_private;
unsigned long state_to_set;
ssize_t ret = -EINVAL;
CAM_INFO(CAM_FLASH, "Flash Enable Command: %s", buf);
ret = kstrtoul(buf, 10, &state_to_set);
if (ret)
return ret;
if (CAMERA_SENSOR_FLASH_STATUS_OFF != state_to_set) {
// enable flash
if (CAMERA_SENSOR_FLASH_STATUS_OFF == flashlight_enable) {
ret = cam_res_mgr_gpio_request(
fctrl->soc_info.dev,
soc_private->flash_gpio_enable, 0,
"CUSTOM_GPIO1");
if (ret) {
CAM_ERR(CAM_FLASH, "gpio %d request fails",
soc_private->flash_gpio_enable);
return ret;
}
}
flashlight_enable = state_to_set;
cam_res_mgr_gpio_set_value(
soc_private->flash_gpio_enable,
flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH);
if (flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_LOW) {
pm6125_flash_gpio_select_state(
PM6125_FLASH_GPIO_STATE_ACTIVE,
CAMERA_SENSOR_FLASH_OP_FIRELOW,
FLASH_FIRE_LOW_MAXCURRENT);
usleep_range(5000, 6000);
}
pm6125_flash_gpio_select_state(
PM6125_FLASH_GPIO_STATE_ACTIVE,
flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH ?
CAMERA_SENSOR_FLASH_OP_FIREHIGH :
CAMERA_SENSOR_FLASH_OP_FIRELOW,
(u64)flashlight_brightness);
}
else {
// disable flash
if (CAMERA_SENSOR_FLASH_STATUS_OFF != flashlight_enable) {
cam_res_mgr_gpio_set_value(
soc_private->flash_gpio_enable, 0);
cam_res_mgr_gpio_free(fctrl->soc_info.dev,
soc_private->flash_gpio_enable);
}
flashlight_enable = CAMERA_SENSOR_FLASH_STATUS_OFF;
pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_SUSPEND,
CAMERA_SENSOR_FLASH_OP_OFF, 0);
}
return size;
}
static ssize_t flashlight_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%u\n", flashlight_brightness);
}
static ssize_t flashlight_brightness_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct cam_flash_ctrl *fctrl = dev_get_drvdata(dev);
struct cam_flash_private_soc *soc_private = fctrl->soc_info.soc_private;
unsigned long brightness_to_set;
ssize_t ret = -EINVAL;
CAM_INFO(CAM_FLASH, "Flash Brightness Command: %s", buf);
ret = kstrtoul(buf, 10, &brightness_to_set);
if (ret)
return ret;
flashlight_brightness = brightness_to_set;
switch (flashlight_enable)
{
case CAMERA_SENSOR_FLASH_STATUS_LOW: // CAMERA_SENSOR_FLASH_OP_FIRELOW
case CAMERA_SENSOR_FLASH_STATUS_HIGH: // CAMERA_SENSOR_FLASH_OP_FIREHIGH
CAM_INFO(CAM_FLASH, "Flash Mode %s: %d",
flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH ?
"High" :
"Low",
flashlight_brightness);
// disable first
cam_res_mgr_gpio_set_value(
soc_private->flash_gpio_enable, 0);
cam_res_mgr_gpio_free(fctrl->soc_info.dev,
soc_private->flash_gpio_enable);
pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_SUSPEND, CAMERA_SENSOR_FLASH_OP_OFF, 0);
// get handle
ret = cam_res_mgr_gpio_request(
fctrl->soc_info.dev,
soc_private->flash_gpio_enable, 0,
"CUSTOM_GPIO1");
if (ret) {
CAM_ERR(CAM_FLASH, "gpio %d request fails",
soc_private->flash_gpio_enable);
return ret;
}
cam_res_mgr_gpio_set_value(
soc_private->flash_gpio_enable,
flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH);
if (flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_LOW) {
pm6125_flash_gpio_select_state(
PM6125_FLASH_GPIO_STATE_ACTIVE,
CAMERA_SENSOR_FLASH_OP_FIRELOW,
FLASH_FIRE_LOW_MAXCURRENT);
usleep_range(5000, 6000);
}
pm6125_flash_gpio_select_state(
PM6125_FLASH_GPIO_STATE_ACTIVE,
flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH ?
CAMERA_SENSOR_FLASH_OP_FIREHIGH :
CAMERA_SENSOR_FLASH_OP_FIRELOW,
(u64)flashlight_brightness);
break;
default:
CAM_INFO(CAM_FLASH, "flashlight had not been enable yet.");
break;
}
return size;
}
static DEVICE_ATTR_RW(flashlight_enable);
static DEVICE_ATTR_RW(flashlight_brightness);
struct device_attribute *flashlight_attributes[] = {
&dev_attr_flashlight_enable,
&dev_attr_flashlight_brightness,
};
int pm6125_flash_control_create_device(struct device* dev)
{
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(flashlight_attributes); i++) {
ret = device_create_file(dev,
flashlight_attributes[i]);
if (ret) {
dev_err(dev, "failed: sysfs file %s\n",
flashlight_attributes[i]->attr.name);
pm6125_flash_control_remove_device(dev);
return ret;
}
}
return 0;
}
int pm6125_flash_control_remove_device(struct device* dev)
{
int i;
for (i = 0; i < ARRAY_SIZE(flashlight_attributes); i++) {
device_remove_file(dev, flashlight_attributes[i]);
}
return 0;
}
#endif
static int pm6125_flash_pwm_probe(struct platform_device *pdev)
{
int rc = 0;
pwm = devm_pwm_get(&pdev->dev, NULL);
if (IS_ERR(pwm))
return PTR_ERR(pwm);
return rc;
}
static const struct of_device_id gpio_of_match[] = {
{ .compatible = "qualcomm,pm6125_flash_gpio", },
{},
};
static struct platform_driver pm6125_flash_gpio_platform_driver = {
.probe = pm6125_flash_pwm_probe,
.driver = {
.name = "PM6125_FLASH_GPIO_DTS",
.of_match_table = gpio_of_match,
},
};
int pm6125_flash_gpio_init_module(void)
{
if (platform_driver_register(&pm6125_flash_gpio_platform_driver)) {
PM6125_FLASH_PRINT("[pm6125_flash_gpio]Failed to register pm6125_flash_gpio_platform_driver!\n");
return -1;
}
return 0;
}
void pm6125_flash_gpio_exit_module(void)
{
platform_driver_unregister(&pm6125_flash_gpio_platform_driver);
}
MODULE_AUTHOR("liyang <liyang14@huaqin.com>");
MODULE_DESCRIPTION("CONTROL PM6125 FLASH GPIO Driver");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,38 @@
#ifndef _PM6125_FLASH_GPIO_H_
#define _PM6125_FLASH_GPIO_H_
#include "../cam_sensor_utils/cam_sensor_cmn_header.h"
#define PM6125_FLASH_PRINT pr_info //printk
/* DTS state */
typedef enum {
PM6125_FLASH_GPIO_STATE_ACTIVE,
PM6125_FLASH_GPIO_STATE_SUSPEND,
PM6125_FLASH_GPIO_STATE_MAX, /* for array size */
} PM6125_FLASH_GPIO_STATE;
#ifdef CONFIG_CAMERA_FLASH_PWM
enum{
CAMERA_SENSOR_FLASH_STATUS_OFF,
CAMERA_SENSOR_FLASH_STATUS_LOW,
CAMERA_SENSOR_FLASH_STATUS_HIGH
};
#endif
#define PM6125_PWM_PERIOD 50000
#define FLASH_FIRE_HIGH_MAXCURRENT 1200
#define FLASH_FIRE_LOW_MAXCURRENT 150
/*****************************************************************************
* Function Prototype
*****************************************************************************/
extern void pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE s, enum camera_flash_opcode opcode, u64 flash_current);
#ifdef CONFIG_CAMERA_FLASH_PWM
extern int pm6125_flash_control_create_device(struct device* dev);
extern int pm6125_flash_control_remove_device(struct device* dev);
#endif
int pm6125_flash_gpio_init_module(void);
void pm6125_flash_gpio_exit_module(void);
#endif /* _PM6125_FLASH_GPIO_H_*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,224 @@
#ifndef AW86006_OIS_H
#define AW86006_OIS_H
/* Log Format */
#define AW_LOGI(format, ...) \
CAM_INFO(CAM_OIS, format, ##__VA_ARGS__)
#define AW_LOGD(format, ...) \
CAM_DBG(CAM_OIS, format, ##__VA_ARGS__)
#define AW_LOGE(format, ...) \
CAM_ERR(CAM_OIS, format, ##__VA_ARGS__)
/* I2c address */
#define AW_SHUTDOWN_I2C_ADDR (0xC2 >> 1) /* 0x61 */
#define AW_WAKEUP_I2C_ADDR (0xD2 >> 1) /* 0x69 */
/* Register detail */
#define REG_CHIPID (0x0000)
#define REG_OIS_ENABLE (0x0001)
#define REG_OIS_STATUS (0x0002)
#define REG_PACKING_RST (0x0003)
#define REG_DATA_READY (0x0004)
#define REG_SAMPLE_TIME (0x0005)
#define REG_PACK_DATA (0x0006)
#define REG_SPI_GYRO (0x0007)
#define REG_SPI_CFG (0x0008)
#define REG_AF_CODE_H (0x0009)
#define REG_AF_CODE_L (0x000A)
#define REG_AF_ARCT (0x000B)
#define REG_AF_CFG (0x000C)
#define REG_AF_BUSY (0x000D)
#define REG_VERSION (0x0010)
#define REG_STANDBY (0xFF11)
/* Flag */
#define OIS_ENABLE (0x01)
#define OIS_DISABLE (0x00)
#define OIS_ERROR (-1)
#define OIS_SUCCESS (0)
#define AW_IC_STANDBY (1)
#define AW_FLASH_WRITE_CONNECT
/* #define AW_SOC_FLASH_READ_FLAG */
/* Loop */
#define AW_STAY_ON_MOVE_LOOP (20)
#define AW_STAY_ON_BOOT_LOOP (20)
#define AW_ERROR_LOOP (3)
#define AW_FLASH_WRITE_ERROR_LOOP (2)
#define AW_FLASH_READ_ERROR_LOOP (2)
#define AW_FLASH_ERASE_ERROR_LOOP (2)
#define AW_JUMP_BOOT_LOOP (6)
#define AW_JUMP_MOVE_LOOP (6)
/* Addr or data size */
#define AW_SIZE_BYTE_0 (0)
#define AW_SIZE_BYTE_1 (1)
#define AW_SIZE_BYTE_2 (2)
#define AW_SIZE_BYTE_3 (3)
#define AW_SIZE_BYTE_4 (4)
#define AW_SIZE_BYTE_12 (12)
#define AW_SIZE_BYTE_20 (20)
#define AW_PROTOCOL_SIZE (14)
#define AW_DATA_SHIFT_0_BIT (0)
#define AW_DATA_SHIFT_8_BIT (8)
#define AW_DATA_SHIFT_16_BIT (16)
#define AW_DATA_SHIFT_24_BIT (24)
#define AW_I2C_WRITE_BYTE_ZERO (0x00)
/* Delay */
#define AW_RESET_DELAY (50) /* ms */
#define AW_JUMP_MOVE_DELAY (9) /* ms */
#define AW_JUMP_MOVE_DELAY_MAX (16) /* ms */
#define AW_JUMP_BOOT_DELAY (2) /* ms */
#define AW_JUMP_BOOT_DELAY_MAX (6) /* ms */
#define AW_SHUTDOWN_DELAY (2000) /* us */
/* Flash and firmware */
#define AW_FLASH_BASE_ADDR (0x01000000)
#define AW_FLASH_APP_ADDR (0x01002000)
#define AW_FLASH_MOVE_LENGTH (AW_FLASH_APP_ADDR - AW_FLASH_BASE_ADDR)
#define AW_FLASH_FULL_SIZE (0xB000)
#define AW_FLASH_TOP_ADDR (AW_FLASH_BASE_ADDR + AW_FLASH_FULL_SIZE)
#define AW_FLASH_ERASE_LEN (512)
#define AW_FLASH_WRITE_LEN (64)
#define AW_FLASH_READ_LEN (64)
#define AW_FW_INFO_LENGTH (64)
#define AW_FW_SHIFT_IDENTIFY (AW_FLASH_MOVE_LENGTH)
#define AW_FW_SHIFT_CHECKSUM (AW_FW_SHIFT_IDENTIFY + 8)
#define AW_FW_SHIFT_APP_CHECKSUM (AW_FW_SHIFT_CHECKSUM + 4)
#define AW_FW_SHIFT_CHECKSUM_ADDR (AW_FW_SHIFT_APP_CHECKSUM)
#define AW_FW_SHIFT_APP_LENGTH (AW_FW_SHIFT_APP_CHECKSUM + 4)
#define AW_FW_SHIFT_APP_VERSION (AW_FW_SHIFT_APP_LENGTH + 4)
#define AW_FW_SHIFT_APP_ID (AW_FW_SHIFT_APP_VERSION + 4)
#define AW_FW_SHIFT_MOVE_CHECKSUM (AW_FW_SHIFT_APP_ID + 4)
#define AW_FW_SHIFT_MOVE_VERSION (AW_FW_SHIFT_MOVE_CHECKSUM + 4)
#define AW_FW_SHIFT_MOVE_LENGTH (AW_FW_SHIFT_MOVE_VERSION + 4)
#define AW_FW_SHIFT_UPDATE_FLAG (AW_FW_SHIFT_MOVE_LENGTH + 8)
#define AW_ARRAY_SHIFT_UPDATE_FLAG (AW_FW_SHIFT_UPDATE_FLAG - AW_FLASH_MOVE_LENGTH)
/* gyro and hall test */
#define AW_GYROACCEL_DIFT_LIMIT 5000
#define CHECK_DIFF(x, y) ((x > 0) ? (x - y) : (-x - y))
/* SOC */
enum soc_status {
SOC_OK = 0,
SOC_ADDR_ERROR,
SOC_PBUF_ERROR,
SOC_HANK_ERROR,
SOC_JUMP_ERROR,
SOC_FLASH_ERROR,
SOC_SPACE_ERROR,
};
enum soc_module {
SOC_HANK = 0x01,
SOC_SRAM = 0x02,
SOC_FLASH = 0x03,
SOC_END = 0x04,
};
enum soc_enum {
SOC_VERSION = 0x01,
SOC_CTL = 0x00,
SOC_ACK = 0x01,
SOC_ADDR = 0x84,
SOC_READ_ADDR = 0x48,
SOC_ERASE_STRUCT_LEN = 6,
SOC_READ_STRUCT_LEN = 6,
SOC_PROTOCAL_HEAD = 9,
SOC_CONNECT_WRITE_LEN = 9,
SOC_ERASE_WRITE_LEN = 15,
SOC_READ_WRITE_LEN = 15,
SOC_ERASE_BLOCK_DELAY = 5,
SOC_WRITE_BLOCK_HEAD = 13,
SOC_WRITE_BLOCK_DELAY = 600, /* us */
SOC_READ_BLOCK_DELAY = 200, /* us */
SOC_CONNECT_DELAY = 100, /* us */
};
enum soc_flash_event {
SOC_FLASH_WRITE = 0x01,
SOC_FLASH_WRITE_ACK = 0x02,
SOC_FLASH_READ = 0x11,
SOC_FLASH_READ_ACK = 0x12,
SOC_FLASH_ERASE_BLOCK = 0x21,
SOC_FLASH_ERASE_BLOCK_ACK = 0x22,
SOC_FLASH_ERASE_CHIP = 0x23,
SOC_FLASH_ERASE_CHIP_ACK = 0x24,
};
enum soc_hank_event {
SOC_HANK_CONNECT = 0x01,
SOC_HANK_CONNECT_ACK = 0x02,
SOC_HANK_PROTICOL = 0x11,
SOC_HANK_PROTICOL_ACK = 0x12,
SOC_HANK_VERSION = 0x21,
SOC_HANK_VERSION_ACK = 0x22,
SOC_HANK_ID = 0x31,
SOC_HANK_ID_ACK = 0x32,
SOC_HANK_DATE = 0x33,
SOC_HANK_DATA_ACK = 0x34,
};
/* ISP */
enum isp_enum {
ISP_READ_VERSION_DELAY = 500, /* us */
ISP_VERS_CONNECT_ACK = 0x01,
ISP_VERSION_ACK_LEN = 5,
ISP_EVENT_OK = 0x01,
};
enum awrw_flag {
AW_SEQ_WRITE = 0,
AW_SEQ_READ = 1,
};
enum axis_info {
AXIS_X,
AXIS_Y,
AXIS_Z,
};
struct accelgyro_dift {
int16_t gyro_dift[3];
int16_t accel_dift[3];
};
/* Struct */
struct soc_protocol {
uint8_t checksum;
uint8_t protocol_ver;
uint8_t addr;
uint8_t module;
uint8_t event;
uint8_t len[2];
uint8_t ack;
uint8_t sum;
uint8_t reserved[3];
uint8_t ack_juge;
uint8_t *p_data;
};
struct aw86006_fw {
uint32_t checksum;
uint32_t app_checksum;
uint32_t app_length;
uint32_t app_version;
uint32_t app_id;
uint32_t move_checksum;
uint32_t move_version;
uint32_t move_length;
uint32_t update_flag;
uint32_t size;
uint8_t *data_p;
};
struct aw86006_info {
uint8_t already_update;
uint8_t checkinfo_fw[64];
uint8_t checkinfo_rd[64];
struct aw86006_fw fw;
};
#endif

View file

@ -10,6 +10,63 @@
#include "cam_debug_util.h"
#include "camera_main.h"
extern int aw86006_ois_init(struct cam_ois_ctrl_t *o_ctrl); /* awinic add */
extern int aw86006_ois_exit(struct cam_ois_ctrl_t *o_ctrl); /* awinic add */
static int cam_ois_clear_data_ready(struct cam_ois_ctrl_t *o_ctrl)
{
struct cam_sensor_i2c_reg_setting i2c_reg_setting = {NULL,1,CAMERA_SENSOR_I2C_TYPE_WORD,CAMERA_SENSOR_I2C_TYPE_WORD,0};
struct cam_sensor_i2c_reg_array i2c_write_settings = {0x70DA,0x0000,0,0};
int32_t rc = 0;
if (!o_ctrl) {
CAM_ERR(CAM_OIS, "Invalid Args");
return -EINVAL;
}
i2c_reg_setting.reg_setting = &(i2c_write_settings);
rc = camera_io_dev_write(&(o_ctrl->io_master_info), &(i2c_reg_setting));
if (rc < 0) {
CAM_ERR(CAM_OIS, "Failed in Applying i2c wrt settings");
}
CAM_DBG(CAM_OIS,"Clear data-ready success");
return rc;
}
#ifdef CONFIG_MOT_DONGWOON_OIS_AF_DRIFT
static struct cam_ois_ctrl_t * g_o_ctrl = NULL;
int cam_ois_write_af_drift(uint32_t dac)
{
struct cam_ois_ctrl_t *o_ctrl = g_o_ctrl;
struct cam_sensor_i2c_reg_setting i2c_reg_setting = {NULL, 1, CAMERA_SENSOR_I2C_TYPE_WORD, CAMERA_SENSOR_I2C_TYPE_WORD, 0};
struct cam_sensor_i2c_reg_array i2c_write_settings = {0x7070, dac, 0, 0};
int rc = 0;
if (!o_ctrl) {
CAM_ERR(CAM_OIS, "invalid args");
return -EINVAL;
}
if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) {
CAM_WARN(CAM_OIS, "Not in right state to write af drift: %d", o_ctrl->cam_ois_state);
return -EINVAL;
}
i2c_reg_setting.reg_setting = &(i2c_write_settings);
rc = camera_io_dev_write(&(o_ctrl->io_master_info), &(i2c_reg_setting));
if (rc < 0) {
CAM_ERR(CAM_OIS, "fail in applying i2c wrt settings");
return -EINVAL;
}
CAM_DBG(CAM_OIS,"write af-drift success 0x%x", dac);
return rc;
}
#endif
static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd,
struct v4l2_subdev_fh *fh)
{
@ -271,6 +328,255 @@ static int cam_ois_i2c_driver_remove(struct i2c_client *client)
return 0;
}
static irqreturn_t cam_aw86006_ois_vsync_irq_thread(int irq, void *data)
{
struct cam_ois_ctrl_t *o_ctrl = data;
int rc = -EINVAL, handled = IRQ_NONE, sample_cnt = 0, delay_time = 0;
uint64_t mono_time_ns;
struct timespec64 ts;
uint8_t *read_buff;
uint32_t k, read_len;
if (!o_ctrl) {
CAM_ERR(CAM_OIS, "Invalid Args");
return IRQ_NONE;
}
if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) {
CAM_WARN(CAM_OIS, "Not in right state to read Eis data: %d", o_ctrl->cam_ois_state);
return IRQ_NONE;
}
if (o_ctrl->is_video_mode == false ||
o_ctrl->is_need_eis_data == false) {
CAM_DBG(CAM_OIS, "No need to read Eis data: %d %d", o_ctrl->is_video_mode, o_ctrl->is_need_eis_data);
return IRQ_NONE;
}
if (!mutex_trylock(&o_ctrl->vsync_mutex)) {
CAM_WARN(CAM_OIS, "try to get mutex fail, skip this irq");
return IRQ_NONE;
}
ktime_get_boottime_ts64(&ts);
mono_time_ns = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec);
CAM_DBG(CAM_OIS, "aw86006 ois vsync sof mono timestamp is %lld", mono_time_ns);
o_ctrl->prev_timestamp = o_ctrl->curr_timestamp;
o_ctrl->curr_timestamp = mono_time_ns;
// when the first vsync arrived, return
if (o_ctrl->is_first_vsync) {
o_ctrl->is_first_vsync = 0;
rc = -EINVAL;
goto release_mutex;
}
memset(o_ctrl->ring_buff, 0, o_ctrl->ring_buff_size);
read_buff = o_ctrl->ring_buff;
for (k = 0; k < RING_BUFFER_LEN/READ_BYTE + 1; k++) {
if (k == RING_BUFFER_LEN/READ_BYTE)
read_len = RING_BUFFER_LEN%READ_BYTE;
else
read_len = READ_BYTE;
if (read_len == 0) {
CAM_WARN(CAM_OIS, "read length is 0, break loop read");
break;
}
rc = camera_io_dev_ois_read_seq(
&o_ctrl->io_master_info,
AW86006_PACKET_ADDR,
read_buff + k*READ_BYTE,
CAMERA_SENSOR_I2C_TYPE_WORD,
CAMERA_SENSOR_I2C_TYPE_BYTE,
read_len);
if (rc < 0) {
CAM_ERR(CAM_OIS, "failed to read ois data: %d", rc);
goto release_mutex;
}
}
sample_cnt = read_buff[0];
delay_time = read_buff[1];
CAM_DBG(CAM_OIS,"sample_cnt = %d, delay_time = %d (100 us)", sample_cnt, delay_time);
if (sample_cnt == 0 || sample_cnt > AW86006_MAX_SAMPLE) {
CAM_WARN(CAM_OIS,"sample_cnt %d is invalid, skip the data", sample_cnt);
rc = -EINVAL;
goto release_mutex;
}
release_mutex:
if (rc < 0) {
memset(o_ctrl->ring_buff, 0, o_ctrl->ring_buff_size);
handled = IRQ_NONE;
} else
handled = IRQ_HANDLED;
mutex_unlock(&(o_ctrl->vsync_mutex));
if (rc >= 0)
complete(&o_ctrl->ois_data_complete);
return handled;
}
static irqreturn_t cam_ois_vsync_irq_thread(int irq, void *data)
{
struct cam_ois_ctrl_t *o_ctrl = data;
int rc = 0, handled = IRQ_NONE, packet_cnt = 0, sample_cnt = 0;
uint64_t mono_time_ns;
struct timespec64 ts;
uint8_t *read_buff;
uint32_t k, read_len;
uint32_t data_ready = 0xFFFF;
int i = 0;
if (!o_ctrl) {
CAM_ERR(CAM_OIS, "Invalid Args");
return IRQ_NONE;
}
if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) {
CAM_WARN(CAM_OIS, "Not in right state to read OIS: %d", o_ctrl->cam_ois_state);
goto release_mutex;
}
if(o_ctrl->is_video_mode == false ||
o_ctrl->is_need_eis_data == false) {
CAM_WARN(CAM_OIS, "No need to read Eis data %d %d", o_ctrl->is_video_mode, o_ctrl->is_need_eis_data);
return IRQ_NONE;
}
if (!mutex_trylock(&o_ctrl->vsync_mutex)) {
CAM_ERR(CAM_OIS, "try lock fail, skip this irq");
return IRQ_NONE;
}
ktime_get_boottime_ts64(&ts);
mono_time_ns = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec);
CAM_DBG(CAM_OIS, "vsync sof mono timestamp is %lld", mono_time_ns);
o_ctrl->prev_timestamp = o_ctrl->curr_timestamp;
o_ctrl->curr_timestamp = mono_time_ns;
// when the first vsync arrived, clear data-ready, and return.
if (o_ctrl->is_first_vsync) {
o_ctrl->is_first_vsync = 0;
rc = cam_ois_clear_data_ready(o_ctrl);
udelay(1000);
goto release_mutex;
}
memset(o_ctrl->ois_data, 0, o_ctrl->ois_data_size);
read_buff = o_ctrl->ois_data;
for (i = 0; i < READ_COUNT; i++) {
rc = camera_io_dev_read(
&o_ctrl->io_master_info,
DATA_READY_ADDR,
&data_ready,
CAMERA_SENSOR_I2C_TYPE_WORD,
CAMERA_SENSOR_I2C_TYPE_WORD);
if (rc < 0) {
CAM_ERR(CAM_OIS, "failed to read OIS 0x70da reg rc: %d", rc);
goto release_mutex;
}
if (data_ready == DATA_READY) {
CAM_DBG(CAM_OIS, "data_ready == 0x0001 i = %d", i);
udelay(400);
break;
} else if (data_ready != DATA_READY && i < READ_COUNT - 1) {
CAM_ERR(CAM_OIS, "data_ready != 0x0001 i = %d", i);
udelay(1000);
} else {
CAM_ERR(CAM_OIS, "data_ready check fail i = %d", i);
goto release_mutex;
}
}
do {
if (packet_cnt > 0 && packet_cnt < MAX_PACKET)
read_buff += PACKET_BYTE;
// SM6375: CCI_VERSION_1_2_9 can only support read 0xE bytes data one time.
for (k = 0; k < PACKET_BYTE/READ_BYTE + 1; k++) {
if (k == PACKET_BYTE/READ_BYTE)
read_len = PACKET_BYTE%READ_BYTE;
else
read_len = READ_BYTE;
if (read_len == 0) {
CAM_WARN(CAM_OIS, "Read length is zero, break loop read");
break;
}
rc = camera_io_dev_ois_read_seq(
&o_ctrl->io_master_info,
PACKET_ADDR + k*READ_BYTE/2,
read_buff + k*READ_BYTE,
CAMERA_SENSOR_I2C_TYPE_WORD,
CAMERA_SENSOR_I2C_TYPE_WORD,
read_len);
if (rc < 0) {
CAM_ERR(CAM_OIS, "Failed: seq read I2C settings: %d", rc);
goto release_mutex;
}
if (k == 0 && packet_cnt == 0) {
sample_cnt = read_buff[1];
if (sample_cnt != 0) {
packet_cnt = (sample_cnt + 9)/10;
CAM_DBG(CAM_OIS,"sample data = 0x%x, packet_cnt = %d", sample_cnt, packet_cnt);
// we only need max 30 sample.
if (packet_cnt > MAX_PACKET || sample_cnt > MAX_SAMPLE) {
CAM_WARN(CAM_OIS,"Too many packet, skip this read");
rc = -EINVAL;
goto release_mutex;
}
} else {
CAM_WARN(CAM_OIS,"No-fatal: sample data is zero, break the loop read");
goto release_mutex;
}
}
}
if (sample_cnt > 10 && packet_cnt > 1) {
CAM_WARN(CAM_OIS,"more than 1 packet, clear data-ready and read next packet");
rc = cam_ois_clear_data_ready(o_ctrl);
udelay(1000);
if (rc < 0) {
CAM_ERR(CAM_OIS,"Write failed rc: %d", rc);
goto release_mutex;
}
}
packet_cnt--;
} while(packet_cnt > 0);
release_mutex:
if (rc < 0) {
memset(o_ctrl->ois_data, 0, o_ctrl->ois_data_size);
handled = IRQ_NONE;
} else
handled = IRQ_HANDLED;
mutex_unlock(&(o_ctrl->vsync_mutex));
complete(&o_ctrl->ois_data_complete);
return handled;
}
static int cam_ois_component_bind(struct device *dev,
struct device *master_dev, void *data)
{
@ -290,11 +596,21 @@ static int cam_ois_component_bind(struct device *dev,
o_ctrl->ois_device_type = MSM_CAMERA_PLATFORM_DEVICE;
o_ctrl->ring_buff_size = RING_BUFFER_LEN;
o_ctrl->ring_buff = kzalloc(o_ctrl->ring_buff_size, GFP_KERNEL);
if (!o_ctrl->ring_buff)
goto free_o_ctrl;
o_ctrl->ois_data_size = PACKET_BYTE*MAX_PACKET;
o_ctrl->ois_data = kzalloc(o_ctrl->ois_data_size, GFP_KERNEL);
if (!o_ctrl->ois_data)
goto free_ring_buff;
o_ctrl->io_master_info.master_type = CCI_MASTER;
o_ctrl->io_master_info.cci_client = kzalloc(
sizeof(struct cam_sensor_cci_client), GFP_KERNEL);
if (!o_ctrl->io_master_info.cci_client)
goto free_o_ctrl;
goto free_ois_data;
soc_private = kzalloc(sizeof(struct cam_ois_soc_private),
GFP_KERNEL);
@ -306,8 +622,12 @@ static int cam_ois_component_bind(struct device *dev,
soc_private->power_info.dev = &pdev->dev;
INIT_LIST_HEAD(&(o_ctrl->i2c_init_data.list_head));
INIT_LIST_HEAD(&(o_ctrl->i2c_preprog_data.list_head));
INIT_LIST_HEAD(&(o_ctrl->i2c_precoeff_data.list_head));
INIT_LIST_HEAD(&(o_ctrl->i2c_calib_data.list_head));
INIT_LIST_HEAD(&(o_ctrl->i2c_postcalib_data.list_head));
INIT_LIST_HEAD(&(o_ctrl->i2c_mode_data.list_head));
INIT_LIST_HEAD(&(o_ctrl->i2c_gyro_data.list_head));
mutex_init(&(o_ctrl->ois_mutex));
rc = cam_ois_driver_soc_init(o_ctrl);
if (rc) {
@ -328,6 +648,48 @@ static int cam_ois_component_bind(struct device *dev,
platform_set_drvdata(pdev, o_ctrl);
o_ctrl->cam_ois_state = CAM_OIS_INIT;
#ifdef CONFIG_MOT_DONGWOON_OIS_AF_DRIFT
g_o_ctrl = o_ctrl;
#endif
mutex_init(&(o_ctrl->vsync_mutex));
init_completion(&o_ctrl->ois_data_complete);
if (o_ctrl->ic_name != NULL && strstr(o_ctrl->ic_name, "aw86006"))
aw86006_ois_init(o_ctrl);
if (o_ctrl->is_ois_vsync_irq_supported) {
o_ctrl->vsync_irq = platform_get_irq_optional(pdev, 0);
if (o_ctrl->vsync_irq > 0) {
CAM_DBG(CAM_OIS, "get ois-vsync irq: %d", o_ctrl->vsync_irq);
if (o_ctrl->ic_name != NULL && strstr(o_ctrl->ic_name, "aw86006")) {
rc = devm_request_threaded_irq(dev,
o_ctrl->vsync_irq,
NULL,
cam_aw86006_ois_vsync_irq_thread,
(IRQF_TRIGGER_RISING | IRQF_ONESHOT),
"aw86006-vsync-irq",
o_ctrl);
} else {
rc = devm_request_threaded_irq(dev,
o_ctrl->vsync_irq,
NULL,
cam_ois_vsync_irq_thread,
(IRQF_TRIGGER_RISING | IRQF_ONESHOT),
"ois-vsync-irq",
o_ctrl);
}
if (rc != 0)
CAM_ERR(CAM_OIS, "failed: to request ois-vsync IRQ %d, rc %d", o_ctrl->vsync_irq, rc);
else
CAM_DBG(CAM_OIS, "request ois-vsync IRQ success");
} else
CAM_ERR(CAM_OIS, "failed: to get ois-vsync IRQ");
}
CAM_DBG(CAM_OIS, "Component bound successfully");
return rc;
unreg_subdev:
@ -336,6 +698,10 @@ free_soc:
kfree(soc_private);
free_cci_client:
kfree(o_ctrl->io_master_info.cci_client);
free_ois_data:
kfree(o_ctrl->ois_data);
free_ring_buff:
kfree(o_ctrl->ring_buff);
free_o_ctrl:
kfree(o_ctrl);
return rc;
@ -358,6 +724,9 @@ static void cam_ois_component_unbind(struct device *dev,
}
CAM_INFO(CAM_OIS, "platform driver remove invoked");
if (o_ctrl->ic_name != NULL && strstr(o_ctrl->ic_name, "aw86006"))
aw86006_ois_exit(o_ctrl);
soc_info = &o_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
@ -373,6 +742,8 @@ static void cam_ois_component_unbind(struct device *dev,
kfree(o_ctrl->soc_info.soc_private);
kfree(o_ctrl->io_master_info.cci_client);
kfree(o_ctrl->ois_data);
kfree(o_ctrl->ring_buff);
platform_set_drvdata(pdev, NULL);
v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, NULL);
kfree(o_ctrl);

View file

@ -25,6 +25,28 @@
#define DEFINE_MSM_MUTEX(mutexname) \
static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
#define MODE_ADDR 0x7014
#define ENABLE_ADDR 0x7015
#define PACKET_ADDR 0x70B0
#define DATA_READY_ADDR 0x70DA
#define DATA_READY 0x0001
#define READ_COUNT 3
#define PACKET_BYTE 62
#define MAX_PACKET 5
#define MAX_SAMPLE 30
#define READ_BYTE 0xC
#define QTIMER_ADDR 0x70DB
#define QTIMER_SAMPLE_TIME 2
#define QTIMER_MAX_SAMPLE 20
/* AW86006 EIS */
#define RING_BUFFER_LEN 42
#define AW86006_PACKET_ENABLE 0x0003
#define AW86006_PACKET_ADDR 0x0006
#define AW86006_MAX_SAMPLE 10
enum cam_ois_state {
CAM_OIS_INIT,
CAM_OIS_ACQUIRE,
@ -82,6 +104,13 @@ struct cam_ois_intf_params {
struct cam_req_mgr_crm_cb *crm_cb;
};
struct awrw_ctrl {
uint32_t addr[4];
uint16_t reg_num;
uint8_t flag;
uint8_t *reg_data;
};
/**
* struct cam_ois_ctrl_t - OIS ctrl private data
* @device_name : ois device_name
@ -95,12 +124,21 @@ struct cam_ois_intf_params {
* @i2c_init_data : ois i2c init settings
* @i2c_mode_data : ois i2c mode settings
* @i2c_time_data : ois i2c time write settings
* @i2c_preprog_data : ois i2c preprog settings
* @i2c_precoeff_data : ois i2c precoeff settings
* @i2c_postcalib_data : ois i2c postcalib settings
* @i2c_calib_data : ois i2c calib settings
* @ois_device_type : ois device type
* @cam_ois_state : ois_device_state
* @ois_fw_flag : flag for firmware download
* @ois_preprog_flag : flag for preprog reg settings
* @ois_precoeff_flag : flag for precoeff reg settings
* @is_ois_calib : flag for Calibration data
* @ois_postcalib_flag : flag for postcalib reg settings
* @opcode : ois opcode
* @ois_fw_inc_addr : flag to increment address when sending fw
* @ois_fw_addr_type : address type of fw
* @ois_fw_txn_data_sz : num data bytes per i2c txn when sending fw
* @device_name : Device name
*
*/
@ -115,15 +153,46 @@ struct cam_ois_ctrl_t {
struct cam_subdev v4l2_dev_str;
struct cam_ois_intf_params bridge_intf;
struct i2c_settings_array i2c_init_data;
struct i2c_settings_array i2c_preprog_data;
struct i2c_settings_array i2c_precoeff_data;
struct i2c_settings_array i2c_calib_data;
struct i2c_settings_array i2c_postcalib_data;
struct i2c_settings_array i2c_mode_data;
struct i2c_settings_array i2c_gyro_data;
struct i2c_settings_array i2c_time_data;
enum msm_camera_device_type_t ois_device_type;
enum cam_ois_state cam_ois_state;
char ois_name[32];
uint8_t ois_fw_flag;
uint8_t ois_preprog_flag;
uint8_t ois_precoeff_flag;
uint8_t is_ois_calib;
uint8_t ois_postcalib_flag;
uint8_t ois_fw_txn_data_sz;
uint8_t ois_fw_inc_addr;
uint8_t ois_fw_addr_type;
uint8_t ois_fw_data_type;
uint64_t prev_timestamp;
uint64_t curr_timestamp;
struct cam_ois_opcode opcode;
bool is_ois_vsync_irq_supported;
int vsync_irq;
struct mutex vsync_mutex;
struct completion ois_data_complete;
bool is_first_vsync;
uint8_t *ois_data;
int ois_data_size;
uint16_t q_timer_cnt;
uint64_t mono_timestamp;
/* awinic_add */
const char *ic_name;
struct work_struct aw_fw_update_work;
struct mutex aw_ois_mutex;
struct awrw_ctrl *awrw_ctrl;
uint8_t *ring_buff;
int ring_buff_size;
bool is_video_mode;
bool is_need_eis_data;
};
/**

View file

@ -0,0 +1,325 @@
/*
* Copyright (C) 2021 Motorola Mobility LLC.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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/module.h>
#include "cam_ois_core.h"
#include "cam_ois_soc.h"
#include "cam_sensor_util.h"
#include "cam_debug_util.h"
#include "cam_common_util.h"
#define DW9781C_CHIP_ID_ADDRESS 0x7000
#define DW9781C_CHECKSUM_ADDRESS 0x7007
#define DW9781C_CHIP_ID 0x9781
#define FW_VER_CURR_ADDR 0x7001
#define FW_TYPE_ADDR 0x700D
#define SET_FW 0x8001
#define EOK 0
#define FW_VERSION_OFFSET 10235
#define FW_CHECKSUM_OFFSET 10234
typedef struct
{
unsigned int driverIc;
unsigned int size;
const uint16_t *fwContentPtr;
uint16_t version;
uint16_t checksum;
} FirmwareContex;
static FirmwareContex g_dw9781FirmwareContext;
static int32_t dw9781_cci_write(struct camera_io_master * io_master_info, uint16_t reg, uint16_t val)
{
int32_t rc = 0;
struct cam_sensor_i2c_reg_array reg_setting;
struct cam_sensor_i2c_reg_setting wr_setting;
reg_setting.reg_addr = reg;
reg_setting.reg_data = val;
reg_setting.delay = 0;
reg_setting.data_mask = 0;
wr_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
wr_setting.data_type = CAMERA_SENSOR_I2C_TYPE_WORD;
wr_setting.reg_setting = &reg_setting;
wr_setting.size = 1;
wr_setting.delay = 0;
rc = camera_io_dev_write(io_master_info, &wr_setting);
return rc;
}
static int32_t dw9781_cci_read(struct camera_io_master * io_master_info, uint16_t reg, uint16_t *val)
{
int32_t rc = 0;
uint32_t regVal = 0;
rc = camera_io_dev_read(io_master_info, reg, &regVal, CAMERA_SENSOR_I2C_TYPE_WORD, CAMERA_SENSOR_I2C_TYPE_WORD);
if (!rc) {
*val = (uint16_t)regVal;
}
return rc;
}
static void dw9781_delay_ms(uint32_t ms)
{
usleep_range(ms*1000, ms*1000+10);
return;
}
void dw9781_ois_reset(struct camera_io_master * io_master_info)
{
CAM_DBG(CAM_OIS, "[dw9781c_ois_reset] ois reset");
dw9781_cci_write(io_master_info, 0xD002, 0x0001); /* DW9781_DBGc reset */
dw9781_delay_ms(4);
dw9781_cci_write(io_master_info, 0xD001, 0x0001); /* Active mode (DSP ON) */
dw9781_delay_ms(25); /* ST gyro - over wait 25ms, default Servo On */
dw9781_cci_write(io_master_info, 0xEBF1, 0x56FA); /* User protection release */
}
void dw9781_ois_ready_check(struct camera_io_master * io_master_info)
{
uint16_t fw_flag;
dw9781_cci_write(io_master_info, 0xD001, 0x0000); /* dsp off mode */
dw9781_cci_write(io_master_info, 0xFAFA, 0x98AC); /* All protection(1) */
dw9781_cci_write(io_master_info, 0xF053, 0x70BD); /* All protection(2) */
dw9781_cci_read(io_master_info, 0xA7F9, &fw_flag); /* check checksum flag */
CAM_DBG(CAM_OIS, "[dw9781c_ois_ready_check] checksum flag : 0x%04x", fw_flag);
if(fw_flag == 0xCC33)
{
CAM_DBG(CAM_OIS, "[dw9781c_ois_ready_check] checksum flag is ok");
dw9781_ois_reset(io_master_info); /* ois reset */
} else {
dw9781_cci_write(io_master_info, 0xD002, 0x0001); /* dw9781c reset */
dw9781_delay_ms(4);
CAM_ERR(CAM_OIS, "[dw9781c_ois_ready_check] previous firmware download fail");
}
}
void dw9781_all_protection_release(struct camera_io_master * io_master_info)
{
CAM_DBG(CAM_OIS, "[dw9781c_all_protection_release] execution");
/* release all protection */
dw9781_cci_write(io_master_info, 0xFAFA, 0x98AC);
dw9781_delay_ms(1);
dw9781_cci_write(io_master_info, 0xF053, 0x70BD);
dw9781_delay_ms(1);
}
static uint16_t dw9781_fw_checksum_verify(struct camera_io_master * io_master_info)
{
uint16_t data;
/* FW checksum command */
dw9781_cci_write(io_master_info, 0x7011, 0x2000);
/* command start */
dw9781_cci_write(io_master_info, 0x7010, 0x8000);
dw9781_delay_ms(10);
/* calc the checksum to write the 0x7005 */
dw9781_cci_read(io_master_info, 0x7005, &data);
CAM_DBG(CAM_OIS, "F/W Checksum calculated value : 0x%04X", data);
return data;
}
static int dw9781_erase_mtp_rewritefw(struct camera_io_master * io_master_info)
{
CAM_DBG(CAM_OIS, "dw9781c erase for rewritefw starting..");
/* 512 byte page */
dw9781_cci_write(io_master_info, 0xde03, 0x0027);
/* page erase */
dw9781_cci_write(io_master_info, 0xde04, 0x0008);
dw9781_delay_ms(10);
CAM_DBG(CAM_OIS, "dw9781c checksum flag erase : 0xCC33");
return 0;
}
static void dw9781_erase_mtp(struct camera_io_master * io_master_info)
{
CAM_DBG(CAM_OIS, "[dw9781c_erase_mtp] start erasing firmware flash");
/* 12c level adjust */
dw9781_cci_write(io_master_info, 0xd005, 0x0001);
dw9781_cci_write(io_master_info, 0xdd03, 0x0002);
dw9781_cci_write(io_master_info, 0xdd04, 0x0002);
/* 4k Sector_0 Erase*/
dw9781_cci_write(io_master_info, 0xde03, 0x0000);
dw9781_cci_write(io_master_info, 0xde04, 0x0002);
dw9781_delay_ms(10);
/* 4k Sector_1 Erase*/
dw9781_cci_write(io_master_info, 0xde03, 0x0008);
dw9781_cci_write(io_master_info, 0xde04, 0x0002);
dw9781_delay_ms(10);
/* 4k Sector_2 Erase*/
dw9781_cci_write(io_master_info, 0xde03, 0x0010);
dw9781_cci_write(io_master_info, 0xde04, 0x0002);
dw9781_delay_ms(10);
/* 4k Sector_3 Erase*/
dw9781_cci_write(io_master_info, 0xde03, 0x0018);
dw9781_cci_write(io_master_info, 0xde04, 0x0002);
dw9781_delay_ms(10);
/* 4k Sector_4 Erase*/
dw9781_cci_write(io_master_info, 0xde03, 0x0020);
dw9781_cci_write(io_master_info, 0xde04, 0x0002);
dw9781_delay_ms(10);
CAM_DBG(CAM_OIS, "[dw9781c_erase_mtp] complete erasing firmware flash");
}
static int dw9781_prepare_fw_download(struct camera_io_master * io_master_info)
{
/* step 1: MTP Erase and DSP Disable for firmware 0x8000 write */
/* step 2: MTP setup */
/* step 3: firmware sequential write to flash */
/* step 4: firmware sequential read from flash */
/* step 5: firmware verify */
dw9781_cci_write(io_master_info, 0xd001, 0x0000);
dw9781_all_protection_release(io_master_info);
dw9781_erase_mtp(io_master_info);
CAM_DBG(CAM_OIS, "[dw9781c_download_fw] start firmware download");
return 0;
}
int dw9781c_check_fw_download(struct camera_io_master * io_master_info, const uint8_t *fwData, uint32_t fwSize)
{
uint8_t ret;
uint8_t needDownload = 0;
uint16_t fwchecksum = 0;
uint16_t first_chip_id = 0;
uint16_t chip_checksum = 0;
uint16_t second_chip_id = 0;
uint16_t fw_version_current = 0;
uint16_t fw_version_latest = 0;
if (io_master_info == NULL) {
printk("FATAL: OIS CCI context error!!!");
return -1;
}
if (fwData == NULL || fwSize < FW_VERSION_OFFSET*sizeof(uint16_t)) {
printk("FATAL: firmware buffer(%p) is NULL or size(%d) abnormal!!!", fwData, fwSize);
return -1;
}
g_dw9781FirmwareContext.driverIc = 0x9781;
g_dw9781FirmwareContext.fwContentPtr = (const uint16_t *)fwData;
g_dw9781FirmwareContext.size = fwSize;
g_dw9781FirmwareContext.version = *(g_dw9781FirmwareContext.fwContentPtr+FW_VERSION_OFFSET);
g_dw9781FirmwareContext.version = ((g_dw9781FirmwareContext.version << 8) & 0xff00) |
((g_dw9781FirmwareContext.version >> 8) & 0xff);
g_dw9781FirmwareContext.checksum = *(g_dw9781FirmwareContext.fwContentPtr+FW_CHECKSUM_OFFSET);
g_dw9781FirmwareContext.checksum = ((g_dw9781FirmwareContext.checksum << 8) & 0xff00) |
((g_dw9781FirmwareContext.checksum >> 8) & 0xff);
dw9781_ois_ready_check(io_master_info);
dw9781_cci_read(io_master_info, DW9781C_CHIP_ID_ADDRESS, &first_chip_id);
dw9781_cci_read(io_master_info, 0x7001, &chip_checksum);
CAM_DBG(CAM_OIS, "[dw9781c] FW_VER_PHONE_MAKER : 0x%x", chip_checksum);
dw9781_cci_read(io_master_info, 0x7002, &chip_checksum);
CAM_DBG(CAM_OIS, "[dw9781c] FW_DATE_PHONE_MAKER : 0x%x", chip_checksum);
CAM_DBG(CAM_OIS, "[dw9781c] first_chip_id : 0x%x", first_chip_id);
if (first_chip_id != DW9781C_CHIP_ID) { /* first_chip_id verification failed */
dw9781_all_protection_release(io_master_info);
dw9781_cci_read(io_master_info, 0xd060, &second_chip_id); /* second_chip_id: 0x0020 */
if ( second_chip_id == 0x0020 ) /* Check the second_chip_id*/
{
CAM_DBG(CAM_OIS, "[dw9781c] start flash download:: size:%d, version:0x%x",
g_dw9781FirmwareContext.size, g_dw9781FirmwareContext.version);
needDownload = 1;
ret = dw9781_prepare_fw_download(io_master_info); /* Need to forced update OIS firmware again. */
} else {
dw9781_cci_write(io_master_info, 0xd000, 0x0000); /* Shutdown mode */
CAM_ERR(CAM_OIS, "[dw9781c] second_chip_id check fail");
CAM_ERR(CAM_OIS, "[dw9781c] change dw9781c state to shutdown mode");
return needDownload;
}
} else {
dw9781_cci_read(io_master_info, FW_VER_CURR_ADDR, &fw_version_current);
fw_version_latest = g_dw9781FirmwareContext.version; /*Firmware version read from file content.*/
CAM_DBG(CAM_OIS, "[dw9781c] fw_version_current = 0x%x, fw_version_latest = 0x%x",
fw_version_current, fw_version_latest);
/* download firmware, check if need update, download firmware to flash */
if (((fw_version_current & 0xFF) != (fw_version_latest & 0xFF))) {
fwchecksum = dw9781_fw_checksum_verify(io_master_info);
if(fwchecksum != g_dw9781FirmwareContext.checksum)
{
needDownload = 1;
CAM_DBG(CAM_OIS, "[dw9781c] firmware checksum error 0x%04X, 0x%04X",
g_dw9781FirmwareContext.checksum, fwchecksum);
}
if (needDownload)
{
CAM_DBG(CAM_OIS, "[dw9781c] start flash download:: size:%d, version:0x%x needDownload %d",
g_dw9781FirmwareContext.size, g_dw9781FirmwareContext.version, needDownload);
ret = dw9781_prepare_fw_download(io_master_info);
CAM_DBG(CAM_OIS, "[dw9781c] flash download::vendor_dw9781c");
if (ret != EOK) {
dw9781_erase_mtp_rewritefw(io_master_info);
dw9781_cci_write(io_master_info, 0xd000, 0x0000); /* Shut download mode */
CAM_ERR(CAM_OIS, "[dw9781c] firmware download error, ret = 0x%x", ret);
CAM_ERR(CAM_OIS, "[dw9781c] change dw9781c state to shutdown mode");
needDownload = 1;
}
} else {
CAM_DBG(CAM_OIS, "[dw9781c] ois firmware version is updated, skip download");
}
} else {
CAM_DBG(CAM_OIS, "[dw9781c] ois firmware version is updated, skip download");
}
}
return needDownload;
}
EXPORT_SYMBOL(dw9781c_check_fw_download);
void dw9781_post_firmware_download(struct camera_io_master * io_master_info, const uint8_t *fwData, uint32_t fwSize)
{
uint16_t fwchecksum = 0;
g_dw9781FirmwareContext.checksum = *(g_dw9781FirmwareContext.fwContentPtr+FW_CHECKSUM_OFFSET);
g_dw9781FirmwareContext.checksum = ((g_dw9781FirmwareContext.checksum << 8) & 0xff00) |
((g_dw9781FirmwareContext.checksum >> 8) & 0xff);
dw9781_ois_ready_check(io_master_info);
fwchecksum = dw9781_fw_checksum_verify(io_master_info);
if(fwchecksum != g_dw9781FirmwareContext.checksum)
{
CAM_ERR(CAM_OIS, "[dw9781c] firmware checksum error 0x%04X, 0x%04X", g_dw9781FirmwareContext.checksum, fwchecksum);
dw9781_cci_write(io_master_info, 0xd000, 0x0000); /* Shutdown mode */
dw9781_delay_ms(100);
dw9781_cci_write(io_master_info, 0xd000, 0x0001); /* Standby mode */
dw9781_delay_ms(100);
dw9781_all_protection_release(io_master_info); /* Disable write protect */
dw9781_erase_mtp_rewritefw(io_master_info);
dw9781_cci_write(io_master_info, 0xd000, 0x0000); /* Shutdown mode */
CAM_ERR(CAM_OIS, "[dw9781c] firmware download error");
CAM_ERR(CAM_OIS, "[dw9781c] change dw9781c state to shutdown mode");
} else {
CAM_DBG(CAM_OIS, "[dw9781c] Firmware download succes...");
dw9781_ois_reset(io_master_info);
}
return;
}
EXPORT_SYMBOL(dw9781_post_firmware_download);

View file

@ -0,0 +1,406 @@
/*
* Copyright (C) 2021 Motorola Mobility LLC.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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/module.h>
#include "cam_ois_core.h"
#include "cam_ois_soc.h"
#include "cam_sensor_util.h"
#include "cam_debug_util.h"
#include "cam_common_util.h"
#define DW9784_CHIP_ID_ADDRESS 0x7000
#define DW9784_CHECKSUM_ADDRESS 0x700C
#define DW9784_CHIP_ID 0x9784
#define FW_VER_CURR_ADDR 0x7001
#define EOK 0
#define FW_VERSION_OFFSET 10493
#define FW_CHECKSUM_OFFSET 10495
typedef struct
{
unsigned int driverIc;
unsigned int size;
const uint16_t *fwContentPtr;
uint16_t version;
uint16_t checksum;
} FirmwareContex;
static FirmwareContex g_dw9784FirmwareContext;
static int32_t dw9784_cci_write(struct camera_io_master * io_master_info, uint16_t reg, uint16_t val)
{
int32_t rc = 0;
struct cam_sensor_i2c_reg_array reg_setting;
struct cam_sensor_i2c_reg_setting wr_setting;
reg_setting.reg_addr = reg;
reg_setting.reg_data = val;
reg_setting.delay = 0;
reg_setting.data_mask = 0;
wr_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
wr_setting.data_type = CAMERA_SENSOR_I2C_TYPE_WORD;
wr_setting.reg_setting = &reg_setting;
wr_setting.size = 1;
wr_setting.delay = 0;
rc = camera_io_dev_write(io_master_info, &wr_setting);
return rc;
}
static int32_t dw9784_cci_read(struct camera_io_master * io_master_info, uint16_t reg, uint16_t *val)
{
int32_t rc = 0;
uint32_t regVal = 0;
rc = camera_io_dev_read(io_master_info, reg, &regVal, CAMERA_SENSOR_I2C_TYPE_WORD, CAMERA_SENSOR_I2C_TYPE_WORD);
if (!rc) {
*val = (uint16_t)regVal;
}
return rc;
}
static void dw9784_delay_ms(uint32_t ms)
{
usleep_range(ms*1000, ms*1000+10);
return;
}
void dw9784_ois_reset(struct camera_io_master * io_master_info)
{
CAM_INFO(CAM_OIS, "[dw9784_ois_reset] ois reset");
dw9784_cci_write(io_master_info, 0xD002, 0x0001); /* DW9784_DBGc reset */
dw9784_delay_ms(4);
dw9784_cci_write(io_master_info, 0xD001, 0x0001); /* Active mode (DSP ON) */
dw9784_delay_ms(25); /* ST gyro - over wait 25ms, default Servo On */
dw9784_cci_write(io_master_info, 0xEBF1, 0x56FA); /* User protection release */
}
void dw9784_code_pt_off(struct camera_io_master * io_master_info)
{
CAM_INFO(CAM_OIS, "[dw9784_code_pt_off] start");
/* release all protection */
dw9784_cci_write(io_master_info, 0xFD00, 0x5252);
dw9784_delay_ms(1);
CAM_INFO(CAM_OIS, "[dw9784_code_pt_off] finish");
}
void dw9784_pid_erase(struct camera_io_master * io_master_info)
{
CAM_INFO(CAM_OIS, "[dw9784_pid_erase] start pid flash(IF) erase");
dw9784_cci_write(io_master_info, 0xde03, 0x0000); // page 0
dw9784_delay_ms(1);
dw9784_cci_write(io_master_info, 0xde04, 0x0008); // page erase
dw9784_delay_ms(10); // need to delay after erase
CAM_INFO(CAM_OIS, "[dw9784_pid_erase] finish");
}
void dw9784_fw_eflash_erase(struct camera_io_master * io_master_info)
{
CAM_INFO(CAM_OIS, "[dw9784_fw_eflash_erase] start fw flash erase");
dw9784_cci_write(io_master_info, 0xde03, 0x0000); // 4k Sector_0
dw9784_delay_ms(1);
dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase
dw9784_delay_ms(10); // need to delay after erase
dw9784_cci_write(io_master_info, 0xde03, 0x0008); // 4k Sector_1
dw9784_delay_ms(1);
dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase
dw9784_delay_ms(10); // need to delay after erase
dw9784_cci_write(io_master_info, 0xde03, 0x0010); // 4k Sector_2
dw9784_delay_ms(1);
dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase
dw9784_delay_ms(10); // need to delay after erase
dw9784_cci_write(io_master_info, 0xde03, 0x0018); // 4k Sector_3
dw9784_delay_ms(1);
dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase
dw9784_delay_ms(10); // need to delay after erase
dw9784_cci_write(io_master_info, 0xde03, 0x0020); // 4k Sector_4
dw9784_delay_ms(1);
dw9784_cci_write(io_master_info, 0xde04, 0x0002); // 4k Sector Erase
dw9784_delay_ms(10); // need to delay after erase
CAM_INFO(CAM_OIS, "[dw9784_fw_eflash_erase] finish");
}
void dw9784_flash_acess(struct camera_io_master * io_master_info)
{
CAM_INFO(CAM_OIS, "[dw9784_flash_acess] execution");
/* release all protection */
dw9784_cci_write(io_master_info, 0xFAFA, 0x98AC);
dw9784_delay_ms(1);
dw9784_cci_write(io_master_info, 0xF053, 0x70BD);
dw9784_delay_ms(1);
}
int dw9784_whoami_chk(struct camera_io_master * io_master_info)
{
uint16_t sec_chip_id;
dw9784_cci_write(io_master_info, 0xD000, 0x0001); /* chip enable */
dw9784_delay_ms(4);
dw9784_cci_write(io_master_info, 0xD001, 0x0000); /* dsp off mode */
dw9784_delay_ms(1);
dw9784_flash_acess(io_master_info); /* All protection */
dw9784_cci_read(io_master_info, 0xD060, &sec_chip_id); /* 2nd chip id */
CAM_INFO(CAM_OIS, "[dw9784_ois_ready_check] sec_chip_id : 0x%04x", sec_chip_id);
if(sec_chip_id != 0x0020)
{
CAM_ERR(CAM_OIS, "[dw9784] second_chip_id check fail : 0x%04X", sec_chip_id);
CAM_ERR(CAM_OIS, "[dw9784] second_enter shutdown mode");
dw9784_cci_write(io_master_info, 0xD000, 0x0000); /* ic */
return -1;
}
dw9784_ois_reset(io_master_info); /* ois reset */
return 0;
}
int dw9784_checksum_fw_chk(struct camera_io_master * io_master_info)
{
/*
Bit [0]: FW checksum error
Bit [1]: Module cal. checksum error
Bit [2]: Set cal. checksum error
*/
uint16_t reg_fw_checksum; // 0x700C
uint16_t reg_checksum_status; // 0x700D
dw9784_cci_read(io_master_info, 0x700C, &reg_fw_checksum);
dw9784_cci_read(io_master_info, 0x700D, &reg_checksum_status);
CAM_INFO(CAM_OIS, "[dw9784_checksum_fw_chk] reg_checksum_status : 0x%04X", reg_checksum_status);
CAM_INFO(CAM_OIS, "[dw9784_checksum_fw_chk] reg_fw_checksum : 0x%04X", reg_fw_checksum);
if( (reg_checksum_status & 0x0001) == 0)
{
CAM_INFO(CAM_OIS, "[dw9784_checksum_fw_chk] fw checksum pass");
return 0;
}else
{
CAM_ERR(CAM_OIS, "[dw9784_checksum_fw_chk] fw checksum error reg_fw_checksum : 0x%04X", reg_fw_checksum);
return -1;
}
}
static int dw9784_erase_mtp_rewritefw(struct camera_io_master * io_master_info)
{
uint16_t FMC;
CAM_INFO(CAM_OIS, "dw9784 erase for rewritefw starting..");
dw9784_cci_write(io_master_info, 0xd001, 0x0000);
dw9784_delay_ms(1);
dw9784_flash_acess(io_master_info);
dw9784_cci_write(io_master_info, 0xDE01, 0x0000); // FMC block FW select
dw9784_delay_ms(1);
dw9784_cci_read(io_master_info, 0xDE01, &FMC);
if (FMC != 0)
{
CAM_INFO(CAM_OIS, "[dw9784_download_fw] FMC register value 1st warning : %04x", FMC);
dw9784_cci_write(io_master_info, 0xDE01, 0x0000);
dw9784_delay_ms(1);
FMC = 0; // initialize FMC value
dw9784_cci_read(io_master_info, 0xDE01, &FMC);
if (FMC != 0)
{
CAM_ERR(CAM_OIS, "[dw9784_download_fw] 2nd FMC register value 2nd warning : %04x", FMC);
CAM_ERR(CAM_OIS, "[dw9784_download_fw] stop f/w download");
return -1;
}
}
/* code protection off */
dw9784_code_pt_off(io_master_info);
/* 512 byte page */
dw9784_cci_write(io_master_info, 0xde03, 0x0027);
/* page erase */
dw9784_cci_write(io_master_info, 0xde04, 0x0008);
dw9784_delay_ms(10);
dw9784_cci_write(io_master_info, 0xd000, 0x0000); /* Shut download mode */
return 0;
}
static int dw9784_prepare_fw_download(struct camera_io_master * io_master_info)
{
/* step 1: MTP Erase and DSP Disable for firmware 0x8000 write */
/* step 2: MTP setup */
/* step 3. FMC register check */
/* step 4. code protection off */
/* step 5. erase flash fw data */
uint16_t FMC;
dw9784_cci_write(io_master_info, 0xd001, 0x0000);
dw9784_flash_acess(io_master_info);
dw9784_cci_write(io_master_info, 0xDE01, 0x0000); // FMC block FW select
dw9784_delay_ms(1);
dw9784_cci_read(io_master_info, 0xDE01, &FMC);
if (FMC != 0)
{
CAM_INFO(CAM_OIS, "[dw9784_download_fw] FMC register value 1st warning : %04x", FMC);
dw9784_cci_write(io_master_info, 0xDE01, 0x0000);
dw9784_delay_ms(1);
FMC = 0; // initialize FMC value
dw9784_cci_read(io_master_info, 0xDE01, &FMC);
if (FMC != 0)
{
CAM_ERR(CAM_OIS, "[dw9784_download_fw] 2nd FMC register value 2nd warning : %04x", FMC);
CAM_ERR(CAM_OIS, "[dw9784_download_fw] stop f/w download");
return -1;
}
}
dw9784_code_pt_off(io_master_info);
dw9784_fw_eflash_erase(io_master_info);
CAM_INFO(CAM_OIS, "[dw9784_download_fw] start firmware download");
return 0;
}
int dw9784_check_fw_download(struct camera_io_master * io_master_info, const uint8_t *fwData, uint32_t fwSize)
{
uint8_t ret;
uint8_t needDownload = 0;
uint16_t fwchecksum = 0;
uint16_t first_chip_id = 0;
uint16_t chip_checksum = 0;
uint16_t fw_version_current = 0;
uint16_t fw_version_latest = 0;
if (io_master_info == NULL) {
CAM_ERR(CAM_OIS, "FATAL: OIS CCI context error!!!");
return -1;
}
if (fwData == NULL || fwSize < FW_VERSION_OFFSET*sizeof(uint16_t)) {
CAM_ERR(CAM_OIS, "FATAL: firmware buffer(%p) is NULL or size(%d) abnormal!!!", fwData, fwSize);
return -1;
}
g_dw9784FirmwareContext.driverIc = 0x9784;
g_dw9784FirmwareContext.fwContentPtr = (const uint16_t *)fwData;
g_dw9784FirmwareContext.size = fwSize;
g_dw9784FirmwareContext.version = *(g_dw9784FirmwareContext.fwContentPtr+FW_VERSION_OFFSET);
g_dw9784FirmwareContext.version = ((g_dw9784FirmwareContext.version << 8) & 0xff00) |
((g_dw9784FirmwareContext.version >> 8) & 0xff);
g_dw9784FirmwareContext.checksum = *(g_dw9784FirmwareContext.fwContentPtr+FW_CHECKSUM_OFFSET);
g_dw9784FirmwareContext.checksum = ((g_dw9784FirmwareContext.checksum << 8) & 0xff00) |
((g_dw9784FirmwareContext.checksum >> 8) & 0xff);
if (dw9784_whoami_chk(io_master_info) != 0) {
CAM_ERR(CAM_OIS, "[dw9784] second chip id check fail");
return -1;
}
dw9784_cci_read(io_master_info, DW9784_CHIP_ID_ADDRESS, &first_chip_id);
dw9784_cci_read(io_master_info, 0x7001, &chip_checksum);
CAM_INFO(CAM_OIS, "[dw9784] FW_VER_PHONE_MAKER : 0x%x", chip_checksum);
dw9784_cci_read(io_master_info, 0x7002, &chip_checksum);
CAM_INFO(CAM_OIS, "[dw9784] FW_DATE_PHONE_MAKER : 0x%x", chip_checksum);
CAM_INFO(CAM_OIS, "[dw9784] first_chip_id : 0x%x", first_chip_id);
if (first_chip_id != DW9784_CHIP_ID) { /* first_chip_id verification failed */
CAM_INFO(CAM_OIS, "[dw9784] start flash download:: size:%d, version:0x%x",
g_dw9784FirmwareContext.size, g_dw9784FirmwareContext.version);
needDownload = 1;
ret = dw9784_prepare_fw_download(io_master_info); /* Need to forced update OIS firmware again. */
} else {
fwchecksum = dw9784_checksum_fw_chk(io_master_info);
if(fwchecksum != 0)
{
needDownload = 1;
CAM_INFO(CAM_OIS, "[dw9784] firmware checksum error");
}
dw9784_cci_read(io_master_info, FW_VER_CURR_ADDR, &fw_version_current);
fw_version_latest = g_dw9784FirmwareContext.version; /*Firmware version read from file content.*/
CAM_INFO(CAM_OIS, "[dw9784] fw_version_current = 0x%x, fw_version_latest = 0x%x",
fw_version_current, fw_version_latest);
/* download firmware, check if need update, download firmware to flash */
if (needDownload || ((fw_version_current & 0xFFFF) != (fw_version_latest & 0xFFFF))) {
needDownload = 1;
CAM_INFO(CAM_OIS, "[dw9784] start flash download:: size:%d, version:0x%x needDownload %d",
g_dw9784FirmwareContext.size, g_dw9784FirmwareContext.version, needDownload);
ret = dw9784_prepare_fw_download(io_master_info);
CAM_INFO(CAM_OIS, "[dw9784] flash download::vendor_dw9784");
if (ret != EOK) {
dw9784_erase_mtp_rewritefw(io_master_info);
CAM_ERR(CAM_OIS, "[dw9784] firmware download error, ret = 0x%x", ret);
CAM_ERR(CAM_OIS, "[dw9784] change dw9784 state to shutdown mode");
needDownload = 1;
}
} else {
CAM_INFO(CAM_OIS, "[dw9784] ois firmware version is updated, skip download");
}
}
return needDownload;
}
EXPORT_SYMBOL(dw9784_check_fw_download);
int dw9784_check_if_download(struct camera_io_master * io_master_info)
{
uint16_t FMC;
/* step 1. Writes 512Byte FW(PID) data to IF flash. (FMC register check) */
dw9784_cci_write(io_master_info, 0xDE01, 0x1000);
dw9784_delay_ms(1);
dw9784_cci_read(io_master_info,0xDE01, &FMC);
dw9784_delay_ms(1);
if (FMC != 0x1000)
{
CAM_INFO(CAM_OIS, "[dw9784_download_fw] IF FMC register value 1st warning : %04x", FMC);
dw9784_cci_write(io_master_info, 0xDE01, 0x1000);
dw9784_delay_ms(1);
FMC = 0; // initialize FMC value
dw9784_cci_read(io_master_info,0xDE01, &FMC);
if (FMC != 0x1000)
{
CAM_ERR(CAM_OIS, "[dw9784_download_fw] 2nd IF FMC register value 2nd fail : %04x", FMC);
CAM_ERR(CAM_OIS, "[dw9784_download_fw] stop firmware download");
return -1;
}
}
/* step 2. erease IF(FW/PID) eFLASH */
dw9784_pid_erase(io_master_info);
CAM_INFO(CAM_OIS, "[dw9784_download_fw] start firmware/pid download");
return 0;
}
EXPORT_SYMBOL(dw9784_check_if_download);
void dw9784_post_firmware_download(struct camera_io_master * io_master_info)
{
uint16_t fwchecksum = 0;
dw9784_ois_reset(io_master_info);
fwchecksum = dw9784_checksum_fw_chk(io_master_info);
if(fwchecksum != 0)
{
CAM_ERR(CAM_OIS, "[dw9784] firmware checksum error");
dw9784_erase_mtp_rewritefw(io_master_info);
CAM_ERR(CAM_OIS, "[dw9784] change dw9784 state to shutdown mode");
}
return;
}
EXPORT_SYMBOL(dw9784_post_firmware_download);

View file

@ -34,6 +34,25 @@ static int cam_ois_get_dt_data(struct cam_ois_ctrl_t *o_ctrl)
o_ctrl->ois_device_type);
return -EINVAL;
}
if (!of_property_read_bool(of_node, "vsync-irq-support")) {
o_ctrl->is_ois_vsync_irq_supported = false;
} else {
o_ctrl->is_ois_vsync_irq_supported = true;
}
rc = of_property_read_string(of_node, "ois-name", &o_ctrl->ic_name);
if (rc) {
CAM_DBG(CAM_OIS, "ois-name is not available in the node: %d", rc);
o_ctrl->ic_name = NULL;
}
#ifdef CONFIG_CAMERA_DISABLE_VSYNC_IRQ
o_ctrl->is_ois_vsync_irq_supported = false;
CAM_WARN(CAM_OIS, "disable ois vsync irq in factory build");
#endif
CAM_DBG(CAM_OIS, "is_ois_vsync_irq_supported %d", o_ctrl->is_ois_vsync_irq_supported);
rc = cam_soc_util_get_dt_properties(soc_info);
if (rc < 0) {
CAM_ERR(CAM_OIS, "cam_soc_util_get_dt_properties rc %d",

View file

@ -459,6 +459,7 @@ int cam_res_mgr_gpio_request(struct device *dev, uint gpio,
* from the gpio_res_list
* These two situations both need request gpio.
*/
CAM_DBG(CAM_RES, "shared gpio enable is %d shared gpio num is %d", cam_res->shared_gpio_enabled, cam_res->dt.num_shared_gpio);
if (!gpio_found) {
CAM_DBG(CAM_RES, "gpio: %u not found in gpio_res list", gpio);
rc = gpio_request_one(gpio, flags, label);
@ -572,7 +573,7 @@ bool cam_res_mgr_util_check_if_gpio_is_shared(
}
EXPORT_SYMBOL(cam_res_mgr_util_check_if_gpio_is_shared);
static void cam_res_mgr_gpio_free(struct device *dev, uint gpio)
void cam_res_mgr_gpio_free(struct device *dev, uint gpio)
{
bool gpio_found = false;
bool need_free = true;
@ -647,6 +648,7 @@ static void cam_res_mgr_gpio_free(struct device *dev, uint gpio)
mutex_unlock(&cam_res->gpio_res_lock);
}
EXPORT_SYMBOL(cam_res_mgr_gpio_free);
void cam_res_mgr_gpio_free_arry(struct device *dev,
const struct gpio *array, size_t num)

View file

@ -73,6 +73,18 @@ bool cam_res_mgr_util_check_if_gpio_is_shared(
int cam_res_mgr_gpio_request(struct device *dev, unsigned int gpio,
unsigned long flags, const char *label);
/**
* @brief: Free a GPIO
*
* Free the GPIO and release corresponding gpio_res.
*
* @dev : Pointer to the device
* @gpio : A GPIO number
*
* @return Status of operation. Negative in case of error. Zero otherwise.
*/
void cam_res_mgr_gpio_free(struct device *dev, uint gpio);
/**
* @brief: Free a array GPIO
*

View file

@ -155,7 +155,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
csl_packet = (struct cam_packet *)(generic_ptr +
(uint32_t)config.offset);
if (cam_packet_util_validate_packet(csl_packet,
if ((csl_packet == NULL) || cam_packet_util_validate_packet(csl_packet,
remain_len)) {
CAM_ERR(CAM_SENSOR, "Invalid packet params");
rc = -EINVAL;
@ -446,15 +446,90 @@ int32_t cam_sensor_update_slave_info(struct cam_cmd_probe *probe_info,
s_ctrl->sensor_probe_addr_type = probe_info->addr_type;
s_ctrl->sensor_probe_data_type = probe_info->data_type;
s_ctrl->probe_sub_device = probe_info->probe_sub_device;
s_ctrl->sub_device_addr = probe_info->sub_device_addr;
s_ctrl->sub_device_data_type = probe_info->sub_device_data_type;
s_ctrl->sub_device_addr_type = probe_info->sub_device_addr_type;
s_ctrl->sub_device_id_addr = probe_info->sub_device_id_addr;
s_ctrl->expected_sub_device_id = probe_info->expected_sub_device_id;
s_ctrl->sub_device_cci_master = probe_info->sub_device_cci_master;
s_ctrl->sub_device_cci_device = probe_info->sub_device_cci_device;
s_ctrl->sub_device_i2c_freq_mode = probe_info->sub_device_i2c_freq_mode;
#ifdef CONFIG_CAMERA_CCI_ADDR_SWITCH
s_ctrl->i2c_addr_switch = probe_info->i2c_addr_switch;
s_ctrl->second_i2c_address = probe_info->second_i2c_address;
s_ctrl->i2c_switch_reg_addr_Type = probe_info->i2c_switch_reg_addr_Type;
s_ctrl->i2c_switch_reg_data_Type = probe_info->i2c_switch_reg_data_Type;
s_ctrl->i2c_switch_reg_addr = probe_info->i2c_switch_reg_addr;
s_ctrl->i2c_switch_reg_data = probe_info->i2c_switch_reg_data;
s_ctrl->i2c_switch_reg_delayMs = probe_info->i2c_switch_reg_delayMs;
CAM_DBG(CAM_SENSOR,
"Sensor Addr: 0x%x sensor_id: 0x%x sensor_mask: 0x%x sensor_pipeline_delay:0x%x",
"Sensor Addr: 0x%x sensor_id: 0x%x sensor_mask: 0x%x sensor_pipeline_delay:0x%x i2c_addr_switch: 0x%x second_i2c_address: 0x%x i2c_switch_reg_addr: 0x%x",
s_ctrl->sensordata->slave_info.sensor_id_reg_addr,
s_ctrl->sensordata->slave_info.sensor_id,
s_ctrl->sensordata->slave_info.sensor_id_mask,
s_ctrl->pipeline_delay);
s_ctrl->pipeline_delay,
s_ctrl->i2c_addr_switch ,
s_ctrl->second_i2c_address ,
s_ctrl->i2c_switch_reg_addr);
#endif
return rc;
}
#ifdef CONFIG_CAMERA_CCI_ADDR_SWITCH
int cam_sensor_set_i2c_addr_switch_reg(struct cam_sensor_ctrl_t *s_ctrl)
{
int rc = 0;
uint16_t sensor_address = 0;
struct cam_sensor_i2c_reg_setting wr_setting;
struct cam_sensor_i2c_reg_array reg_setting;
/* if hal doesn't config i2c_addr_switch parameter in sensor xml, return success immediately */
if (!s_ctrl->i2c_addr_switch) {
return 0;
}
/* save sensor i2c address */
sensor_address = s_ctrl->io_master_info.cci_client->sid;
/* set sub-device i2c address */
if (s_ctrl->second_i2c_address) {
s_ctrl->io_master_info.cci_client->sid = s_ctrl->second_i2c_address >> 1;
}
reg_setting.reg_addr = s_ctrl->i2c_switch_reg_addr;
reg_setting.reg_data = s_ctrl->i2c_switch_reg_data;
reg_setting.delay = s_ctrl->i2c_switch_reg_delayMs; /* delay after switch iic addr */
reg_setting.data_mask = 0;
wr_setting.addr_type = s_ctrl->i2c_switch_reg_addr_Type;
wr_setting.data_type = s_ctrl->i2c_switch_reg_data_Type;
wr_setting.reg_setting = &reg_setting;
wr_setting.size = 1;
wr_setting.delay = 0;
rc = camera_io_dev_write(&s_ctrl->io_master_info, &wr_setting);
CAM_ERR(CAM_SENSOR,
"cam_sensor_set_i2c_addr_switch_reg slot:%d, slave_addr:0x%x, sensor_id:0x%x, sensor_address:0x%x",
s_ctrl->soc_info.index,
s_ctrl->sensordata->slave_info.sensor_slave_addr,
s_ctrl->sensordata->slave_info.sensor_id,
sensor_address);
/* restore sensor i2c address */
s_ctrl->io_master_info.cci_client->sid = sensor_address;
if (rc == 0) {
CAM_ERR(CAM_SENSOR, "write i2c addr switch reg success");
}
else {
CAM_ERR(CAM_SENSOR, "write i2c addr switch reg fail");
rc = -EINVAL;
}
return rc;
}
#endif
int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
struct cam_sensor_ctrl_t *s_ctrl,
int32_t cmd_buf_num, uint32_t cmd_buf_length, size_t remain_len)
@ -685,6 +760,10 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl)
int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl)
{
int rc = 0;
#ifdef CONFIG_CAM_SENSOR_PROBE_RETRY
int retries = 5;
bool matched = false;
#endif
uint32_t chipid = 0;
struct cam_camera_slave_info *slave_info;
@ -696,6 +775,28 @@ int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl)
return -EINVAL;
}
#ifdef CONFIG_CAM_SENSOR_PROBE_RETRY
while (retries-- && !matched) {
rc = camera_io_dev_read(
&(s_ctrl->io_master_info),
slave_info->sensor_id_reg_addr,
&chipid,
s_ctrl->sensor_probe_addr_type,
s_ctrl->sensor_probe_data_type);
CAM_INFO(CAM_SENSOR, "read id: 0x%x expected id 0x%x:",
chipid, slave_info->sensor_id);
if (cam_sensor_id_by_mask(s_ctrl, chipid) == slave_info->sensor_id)
matched = true;
if (!matched && !retries) {
CAM_ERR(CAM_SENSOR, "Failed read id: 0x%x expected id 0x%x:",
chipid, slave_info->sensor_id);
return -ENODEV;
}
}
#else
rc = camera_io_dev_read(
&(s_ctrl->io_master_info),
slave_info->sensor_id_reg_addr,
@ -711,6 +812,114 @@ int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl)
chipid, slave_info->sensor_id);
return -ENODEV;
}
#endif
return rc;
}
int cam_sensor_match_sub_device_id(struct cam_sensor_ctrl_t *s_ctrl)
{
int rc = 0;
int ret = 0;
uint32_t sub_device_id = 0;
uint16_t sensor_address = 0;
uint16_t sensor_freq_mode = 0;
uint8_t sensor_cci_master = 0;
uint8_t sensor_cci_device = 0;
/* if hal doesn't config ProbeSubDevice parameter in sensor xml, return success immediately */
if (!s_ctrl->probe_sub_device) {
return 0;
}
/* save sensor i2c address */
sensor_address = s_ctrl->io_master_info.cci_client->sid;
/* set sub-device i2c address */
if (s_ctrl->sub_device_addr) {
s_ctrl->io_master_info.cci_client->sid = s_ctrl->sub_device_addr >> 1;
}
/*if need change cci master*/
if (s_ctrl->need_change_cci_master) {
sensor_cci_master = s_ctrl->io_master_info.cci_client->cci_i2c_master;
sensor_freq_mode = s_ctrl->io_master_info.cci_client->i2c_freq_mode;
sensor_cci_device = s_ctrl->io_master_info.cci_client->cci_device;
ret = camera_io_release(&(s_ctrl->io_master_info));
if (ret != 0) {
CAM_ERR(CAM_SENSOR, "release sensor cci failed!");
}
s_ctrl->io_master_info.cci_client->cci_i2c_master = s_ctrl->sub_device_cci_master;
s_ctrl->io_master_info.cci_client->i2c_freq_mode = s_ctrl->sub_device_i2c_freq_mode;
if(s_ctrl->io_master_info.cci_client->cci_device != s_ctrl->sub_device_cci_device)
{
s_ctrl->io_master_info.cci_client->cci_device = s_ctrl->sub_device_cci_device;
}
rc = camera_io_init(&(s_ctrl->io_master_info));
if(rc != 0) {
ret = camera_io_release(&(s_ctrl->io_master_info));
CAM_ERR(CAM_SENSOR, "init sensor cci failed! rc=%d, release ret=%d, try again!", rc, ret);
usleep_range(100000, 100000);
rc = camera_io_init(&(s_ctrl->io_master_info));
if (rc != 0) {
ret = camera_io_release(&(s_ctrl->io_master_info));
CAM_ERR(CAM_SENSOR, "try again init sensor cci failed again! rc=%d, release ret=%d", rc, ret);
}
}
}
rc = camera_io_dev_read(
&(s_ctrl->io_master_info),
s_ctrl->sub_device_id_addr,
&sub_device_id,
s_ctrl->sub_device_addr_type,
s_ctrl->sub_device_data_type);
CAM_INFO(CAM_SENSOR, "Read sub device id: 0x%x expected sub device id 0x%x:",
sub_device_id, s_ctrl->expected_sub_device_id);
/* restore sensor i2c address */
s_ctrl->io_master_info.cci_client->sid = sensor_address;
/* reset cci master */
if (s_ctrl->need_change_cci_master) {
ret = camera_io_release(&(s_ctrl->io_master_info));
if (ret != 0) {
CAM_ERR(CAM_SENSOR, "release flash cci failed! ");
}
s_ctrl->io_master_info.cci_client->cci_i2c_master = sensor_cci_master;
s_ctrl->io_master_info.cci_client->i2c_freq_mode = sensor_freq_mode;
s_ctrl->io_master_info.cci_client->cci_device = sensor_cci_device;
rc = camera_io_init(&(s_ctrl->io_master_info));
if(rc != 0) {
ret = camera_io_release(&(s_ctrl->io_master_info));
CAM_ERR(CAM_SENSOR, "init sensor cci failed! rc=%d, release ret=%d, try again!", rc, ret);
usleep_range(100000, 100000);
rc = camera_io_init(&(s_ctrl->io_master_info));
if (rc != 0) {
ret = camera_io_release(&(s_ctrl->io_master_info));
CAM_ERR(CAM_SENSOR, "try again init sensor cci failed again! rc=%d, release ret=%d", rc, ret);
}
}
}
if (sub_device_id == s_ctrl->expected_sub_device_id) {
CAM_INFO(CAM_SENSOR,
"Probe sub device success,slot:%d,sub_device_addr:0x%x,sub_device_id:0x%x",
s_ctrl->soc_info.index,
s_ctrl->sub_device_addr,
s_ctrl->expected_sub_device_id);
rc = 0;
}
else {
CAM_ERR(CAM_SENSOR, "Probe sub device fail");
rc = -EINVAL;
}
return rc;
}
@ -789,6 +998,20 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
goto free_power_settings;
}
#ifdef CONFIG_CAMERA_CCI_ADDR_SWITCH
/* load probe setting before read sensorID */
rc = cam_sensor_set_i2c_addr_switch_reg(s_ctrl);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"set i2c addr switch reg failed ! slot:%d, slave_addr:0x%x, sensor_id:0x%x",
s_ctrl->soc_info.index,
s_ctrl->sensordata->slave_info.sensor_slave_addr,
s_ctrl->sensordata->slave_info.sensor_id);
cam_sensor_power_down(s_ctrl);
msleep(20);
goto free_power_settings;
}
#endif
/* Match sensor ID */
rc = cam_sensor_match_id(s_ctrl);
if (rc < 0) {
@ -797,6 +1020,14 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
goto free_power_settings;
}
/* Match sub-device ID */
rc = cam_sensor_match_sub_device_id(s_ctrl);
if (rc < 0) {
cam_sensor_power_down(s_ctrl);
usleep_range(20000,20000);
goto free_power_settings;
}
CAM_INFO(CAM_SENSOR,
"Probe success,slot:%d,slave_addr:0x%x,sensor_id:0x%x",
s_ctrl->soc_info.index,
@ -814,6 +1045,9 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
*/
s_ctrl->is_probe_succeed = 1;
s_ctrl->sensor_state = CAM_SENSOR_INIT;
#ifdef CONFIG_MOT_SENSOR_PRE_POWERUP
s_ctrl->sensor_power_up_done = 0;
#endif
}
break;
case CAM_ACQUIRE_DEV: {
@ -1103,6 +1337,69 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
}
}
break;
#ifdef CONFIG_MOT_SENSOR_PRE_POWERUP
case CAM_MOT_PRE_POWER_UP: {
if (!s_ctrl->sensor_power_up_done)
{
rc = cam_sensor_power_up(s_ctrl);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"MotPreAct - Sensor Power up failed for sensor_id:0x%x, slave_addr:0x%x",
s_ctrl->sensordata->slave_info.sensor_id,
s_ctrl->sensordata->slave_info.sensor_slave_addr);
goto release_mutex;
}
s_ctrl->sensor_power_up_done = 1;
CAM_DBG(CAM_SENSOR, "MotPreAct - Camera sensor_id:0x%x, slave_addr:0x%x, pre power on done = %d",
s_ctrl->sensordata->slave_info.sensor_id,
s_ctrl->sensordata->slave_info.sensor_slave_addr,
s_ctrl->sensor_power_up_done);
}
}
break;
case CAM_MOT_PRE_POWER_DOWN: {
if (s_ctrl->sensor_power_up_done)
{
rc = cam_sensor_power_down(s_ctrl);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Sensor Power Down failed sensor_id: 0x%x, slave_addr:0x%x",
s_ctrl->sensordata->slave_info.sensor_id,
s_ctrl->sensordata->slave_info.sensor_slave_addr);
goto release_mutex;
}
CAM_DBG(CAM_SENSOR, "MotPreAct - Camera sensor_id:0x%x, slave_addr:0x%x, pre power on done = %d",
s_ctrl->sensordata->slave_info.sensor_id,
s_ctrl->sensordata->slave_info.sensor_slave_addr,
s_ctrl->sensor_power_up_done);
}
}
break;
case CAM_MOT_QUERY_SENSOR_STATUS: {
uint32_t isSensorActive = 0;
if (s_ctrl->sensor_power_up_done)
{
isSensorActive = 1;
}
else
{
isSensorActive = 0;
}
if (copy_to_user(u64_to_user_ptr(cmd->handle),
&isSensorActive, sizeof(uint32_t))) {
CAM_ERR(CAM_SENSOR, "MotPreAct - Failed Copy to User");
rc = -EFAULT;
goto release_mutex;
}
CAM_DBG(CAM_SENSOR, "MotPreAct - Query camera sensor_id:0x%x, slave_addr:0x%x, status = %d",
s_ctrl->sensordata->slave_info.sensor_id,
s_ctrl->sensordata->slave_info.sensor_slave_addr,
isSensorActive);
}
break;
#endif
default:
CAM_ERR(CAM_SENSOR, "Invalid Opcode: %d", cmd->op_code);
rc = -EINVAL;
@ -1205,6 +1502,16 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl)
return -EINVAL;
}
#ifdef CONFIG_MOT_SENSOR_PRE_POWERUP
if (s_ctrl->sensor_power_up_done)
{
CAM_INFO(CAM_SENSOR, "MotPreAct - sensor has power on done for sensor_id:0x%x, slave_addr:0x%x",
s_ctrl->sensordata->slave_info.sensor_id,
s_ctrl->sensordata->slave_info.sensor_slave_addr);
return 0;
}
#endif
power_info = &s_ctrl->sensordata->power_info;
slave_info = &(s_ctrl->sensordata->slave_info);
@ -1279,6 +1586,9 @@ int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl)
}
camera_io_release(&(s_ctrl->io_master_info));
#ifdef CONFIG_MOT_SENSOR_PRE_POWERUP
s_ctrl->sensor_power_up_done = 0;
#endif
return rc;
}

View file

@ -111,6 +111,26 @@ struct cam_sensor_ctrl_t {
bool bob_pwm_switch;
uint32_t last_flush_req;
uint16_t pipeline_delay;
uint8_t probe_sub_device;
uint16_t sub_device_addr;
uint8_t sub_device_data_type;
uint8_t sub_device_addr_type;
uint16_t sub_device_id_addr;
uint16_t expected_sub_device_id;
uint8_t sub_device_cci_master;
uint8_t sub_device_cci_device;
uint8_t sub_device_i2c_freq_mode;
bool need_change_cci_master;
uint8_t i2c_addr_switch;
uint16_t second_i2c_address;
uint8_t i2c_switch_reg_addr_Type;
uint8_t i2c_switch_reg_data_Type;
uint16_t i2c_switch_reg_addr;
uint16_t i2c_switch_reg_data;
uint16_t i2c_switch_reg_delayMs;
#ifdef CONFIG_MOT_SENSOR_PRE_POWERUP
bool sensor_power_up_done;
#endif
};
/**

View file

@ -187,6 +187,13 @@ static int32_t cam_sensor_driver_get_dt_data(struct cam_sensor_ctrl_t *s_ctrl)
CAM_DBG(CAM_SENSOR, "cci-index %d", s_ctrl->cci_num);
}
if (of_property_read_bool(of_node, "need-change-cci-master")) {
CAM_DBG(CAM_SENSOR, "need-change-cci-master found in this imgsensor");
s_ctrl->need_change_cci_master = true;
} else {
s_ctrl->need_change_cci_master = false;
}
if (of_property_read_u32(of_node, "sensor-position-pitch",
&sensordata->pos_pitch) < 0) {
CAM_DBG(CAM_SENSOR, "Invalid sensor position");

View file

@ -93,6 +93,39 @@ int32_t cam_camera_cci_i2c_read_seq(struct cam_sensor_cci_client *cci_client,
return rc;
}
int32_t cam_camera_cci_i2c_ois_read_seq(struct cam_sensor_cci_client *cci_client,
uint32_t addr, uint8_t *data,
enum camera_sensor_i2c_type addr_type,
enum camera_sensor_i2c_type data_type,
uint32_t num_byte)
{
int32_t rc = -EFAULT;
struct cam_cci_ctrl cci_ctrl;
if ((addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX)
|| (data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)
|| (num_byte > I2C_REG_DATA_MAX)) {
CAM_ERR(CAM_SENSOR, "addr_type %d num_byte %d", addr_type,
num_byte);
return rc;
}
cci_ctrl.cmd = MSM_CCI_I2C_READ;
cci_ctrl.cci_info = cci_client;
cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr;
cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = addr_type;
cci_ctrl.cfg.cci_i2c_read_cfg.data_type = data_type;
cci_ctrl.cfg.cci_i2c_read_cfg.data = data;
cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = num_byte;
cci_ctrl.status = -EFAULT;
rc = v4l2_subdev_call(cci_client->cci_subdev,
core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
rc = cci_ctrl.status;
CAM_DBG(CAM_SENSOR, "addr = 0x%x, rc = %d", addr, rc);
return rc;
}
static int32_t cam_cci_i2c_write_table_cmd(
struct camera_io_master *client,
struct cam_sensor_i2c_reg_setting *write_setting,

View file

@ -49,6 +49,12 @@ int32_t cam_camera_cci_i2c_read_seq(struct cam_sensor_cci_client *client,
enum camera_sensor_i2c_type data_type,
uint32_t num_byte);
int32_t cam_camera_cci_i2c_ois_read_seq(struct cam_sensor_cci_client *client,
uint32_t addr, uint8_t *data,
enum camera_sensor_i2c_type addr_type,
enum camera_sensor_i2c_type data_type,
uint32_t num_byte);
/**
* @client: CCI client structure
* @write_setting: I2C register setting

View file

@ -6,6 +6,27 @@
#include "cam_sensor_io.h"
#include "cam_sensor_i2c.h"
#ifdef CONFIG_CAM_DISTINGUISH_SENSOR_VERSION
#define SPECIAL_SENSOR_ID 0x5041
#define SPECIAL_SENSOR_ADDR_ID 0x300B
#define SPECIAL_SENSOR_ADDR_VERSION 0x900E
#define SPECIAL_SENSOR_IIC_ADDR 0x10
static uint32_t s_r900e_val = 0;
struct cam_sensor_i2c_reg_array special_on_write_settings = {0x0100, 0x01, 0x05, 0xFF};
struct cam_sensor_i2c_reg_array special_off_write_settings = {0x0100, 0x00, 0x00, 0xFF};
struct cam_sensor_i2c_reg_array special_streamon_write_settings[] =
{
{0x7278, 0x00, 0x00, 0xFF},
{0x727a, 0x01, 0x00, 0xFF},
{0x7280, 0x07, 0x00, 0xFF},
{0x0100, 0x01, 0x00, 0xFF}
};
#endif
int32_t camera_io_dev_poll(struct camera_io_master *io_master_info,
uint32_t addr, uint16_t data, uint32_t data_mask,
enum camera_sensor_i2c_type addr_type,
@ -68,14 +89,25 @@ int32_t camera_io_dev_read(struct camera_io_master *io_master_info,
enum camera_sensor_i2c_type addr_type,
enum camera_sensor_i2c_type data_type)
{
#ifdef CONFIG_CAM_DISTINGUISH_SENSOR_VERSION
int32_t retval = 0;
uint32_t r900e = 0;
struct cam_sensor_i2c_reg_setting write_setting = {0};
#endif
if (!io_master_info) {
CAM_ERR(CAM_SENSOR, "Invalid Args");
return -EINVAL;
}
if (io_master_info->master_type == CCI_MASTER) {
#ifdef CONFIG_CAM_DISTINGUISH_SENSOR_VERSION
retval = cam_cci_i2c_read(io_master_info->cci_client,
addr, data, addr_type, data_type);
#else
return cam_cci_i2c_read(io_master_info->cci_client,
addr, data, addr_type, data_type);
#endif
} else if (io_master_info->master_type == I2C_MASTER) {
return cam_qup_i2c_read(io_master_info->client,
addr, data, addr_type, data_type);
@ -87,7 +119,50 @@ int32_t camera_io_dev_read(struct camera_io_master *io_master_info,
io_master_info->master_type);
return -EINVAL;
}
#ifdef CONFIG_CAM_DISTINGUISH_SENSOR_VERSION
if (retval == 0 &&
data != NULL &&
*data == SPECIAL_SENSOR_ID &&
addr == SPECIAL_SENSOR_ADDR_ID &&
io_master_info->cci_client != NULL &&
io_master_info->cci_client->cci_i2c_master == 0 &&
io_master_info->cci_client->sid == SPECIAL_SENSOR_IIC_ADDR)
{
write_setting.size = 1;
write_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
write_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
write_setting.delay = 21;
write_setting.read_buff = NULL;
write_setting.read_buff_len = 0;
write_setting.reg_setting = &special_on_write_settings;
retval = cam_cci_i2c_write_table(io_master_info, &write_setting);
retval = cam_cci_i2c_read(io_master_info->cci_client,
SPECIAL_SENSOR_ADDR_VERSION,
&r900e,
CAMERA_SENSOR_I2C_TYPE_WORD,
CAMERA_SENSOR_I2C_TYPE_BYTE);
CAM_INFO(CAM_SENSOR, "retval = %d, r900e = %d", retval, r900e);
if(retval == 0)
s_r900e_val = r900e;
write_setting.size = 1;
write_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_WORD;
write_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
write_setting.delay = 0;
write_setting.read_buff = NULL;
write_setting.read_buff_len = 0;
write_setting.reg_setting = &special_off_write_settings;
retval = cam_cci_i2c_write_table(io_master_info, &write_setting);
}
return retval;
#else
return 0;
#endif
}
int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info,
@ -115,9 +190,38 @@ int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info,
return 0;
}
int32_t camera_io_dev_ois_read_seq(struct camera_io_master *io_master_info,
uint32_t addr, uint8_t *data,
enum camera_sensor_i2c_type addr_type,
enum camera_sensor_i2c_type data_type, int32_t num_bytes)
{
if (io_master_info->master_type == CCI_MASTER) {
return cam_camera_cci_i2c_ois_read_seq(io_master_info->cci_client,
addr, data, addr_type, data_type, num_bytes);
} else if (io_master_info->master_type == I2C_MASTER) {
return cam_qup_i2c_read_seq(io_master_info->client,
addr, data, addr_type, num_bytes);
} else if (io_master_info->master_type == SPI_MASTER) {
return cam_spi_read_seq(io_master_info,
addr, data, addr_type, num_bytes);
} else if (io_master_info->master_type == SPI_MASTER) {
return cam_spi_write_seq(io_master_info,
addr, data, addr_type, num_bytes);
} else {
CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
io_master_info->master_type);
return -EINVAL;
}
return 0;
}
int32_t camera_io_dev_write(struct camera_io_master *io_master_info,
struct cam_sensor_i2c_reg_setting *write_setting)
{
#ifdef CONFIG_CAM_DISTINGUISH_SENSOR_VERSION
int32_t retval = 0;
#endif
if (!write_setting || !io_master_info) {
CAM_ERR(CAM_SENSOR,
"Input parameters not valid ws: %pK ioinfo: %pK",
@ -130,6 +234,44 @@ int32_t camera_io_dev_write(struct camera_io_master *io_master_info,
return -EINVAL;
}
#ifdef CONFIG_CAM_DISTINGUISH_SENSOR_VERSION
if (io_master_info->cci_client != NULL &&
io_master_info->cci_client->sid== SPECIAL_SENSOR_IIC_ADDR &&
io_master_info->cci_client->cci_device == 1 &&
io_master_info->cci_client->cci_i2c_master == 0 &&
write_setting->reg_setting->reg_addr == 0x0100 &&
write_setting->reg_setting->reg_data == 0x01)
{
CAM_INFO(CAM_SENSOR, "Detect stream on setting, r900e = %d", s_r900e_val);
if (s_r900e_val == 0x02)
{
write_setting->reg_setting->reg_addr = special_streamon_write_settings[0].reg_addr;
write_setting->reg_setting->reg_data = special_streamon_write_settings[0].reg_data;
write_setting->reg_setting->delay = special_streamon_write_settings[0].delay;
write_setting->reg_setting->data_mask = special_streamon_write_settings[0].data_mask;
retval = cam_cci_i2c_write_table(io_master_info, write_setting);
write_setting->reg_setting->reg_addr = special_streamon_write_settings[1].reg_addr;
write_setting->reg_setting->reg_data = special_streamon_write_settings[1].reg_data;
write_setting->reg_setting->delay = special_streamon_write_settings[1].delay;
write_setting->reg_setting->data_mask = special_streamon_write_settings[1].data_mask;
retval = cam_cci_i2c_write_table(io_master_info, write_setting);
write_setting->reg_setting->reg_addr = special_streamon_write_settings[2].reg_addr;
write_setting->reg_setting->reg_data = special_streamon_write_settings[2].reg_data;
write_setting->reg_setting->delay = special_streamon_write_settings[2].delay;
write_setting->reg_setting->data_mask = special_streamon_write_settings[2].data_mask;
retval = cam_cci_i2c_write_table(io_master_info, write_setting);
write_setting->reg_setting->reg_addr = special_streamon_write_settings[3].reg_addr;
write_setting->reg_setting->reg_data = special_streamon_write_settings[3].reg_data;
write_setting->reg_setting->delay = special_streamon_write_settings[3].delay;
write_setting->reg_setting->data_mask = special_streamon_write_settings[3].data_mask;
}
}
#endif
if (io_master_info->master_type == CCI_MASTER) {
return cam_cci_i2c_write_table(io_master_info,
write_setting);

View file

@ -57,6 +57,12 @@ int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info,
enum camera_sensor_i2c_type data_type,
int32_t num_bytes);
int32_t camera_io_dev_ois_read_seq(struct camera_io_master *io_master_info,
uint32_t addr, uint8_t *data,
enum camera_sensor_i2c_type addr_type,
enum camera_sensor_i2c_type data_type,
int32_t num_bytes);
/**
* @io_master_info: I2C/SPI master information
*

View file

@ -174,7 +174,12 @@ enum cam_ois_packet_opcodes {
CAM_OIS_PACKET_OPCODE_INIT,
CAM_OIS_PACKET_OPCODE_OIS_CONTROL,
CAM_OIS_PACKET_OPCODE_READ,
CAM_OIS_PACKET_OPCODE_WRITE_TIME
CAM_OIS_PACKET_OPCODE_WRITE_TIME,
CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_ROHM,
CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_DONGWOON,
CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_DONGWOON_QTIMER,
CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_AW86006,
CAM_OIS_PACKET_OPCODE_OIS_GYRO_OFFSET
};
enum msm_bus_perf_setting {

View file

@ -1231,6 +1231,11 @@ static int cam_soc_util_get_dt_regulator_info
{
int rc = 0, count = 0, i = 0;
struct device_node *of_node = NULL;
#ifdef CONFIG_CAMERA_VOLTAGE_COMPATIBLE
int idpin_gpio = 0, idpin_value = 0;
unsigned int second_vol_range[2];
const char *rgltr_name = "";
#endif
if (!soc_info || !soc_info->dev) {
CAM_ERR(CAM_UTIL, "Invalid parameters");
@ -1295,6 +1300,63 @@ static int cam_soc_util_get_dt_regulator_info
return -EINVAL;
}
#ifdef CONFIG_CAMERA_VOLTAGE_COMPATIBLE
idpin_gpio = of_get_named_gpio(of_node, "volt-compat-gpio",0);
if (idpin_gpio < 0) {
CAM_ERR(CAM_UTIL, "Not volt-compat-gpio found ,gpio=%d",idpin_gpio);
} else {
if(gpio_is_valid(idpin_gpio)) {
if(!gpio_request(idpin_gpio,"volt-compat-gpio")) {
gpio_direction_input(idpin_gpio);
CAM_DBG(CAM_UTIL, "volt-compat-gpio:%d =%d ", idpin_gpio, gpio_get_value(idpin_gpio));
rc = of_property_read_u32_array(of_node, "volt-compat-range", second_vol_range, 2);
if (rc) {
CAM_ERR(CAM_UTIL, "No volt-compat-range found, rc=%d", rc);
gpio_free(idpin_gpio);
idpin_gpio = 0;
return -EINVAL;
}
rc = of_property_read_string(of_node,"volt-compat-rgltr-name",&rgltr_name);
if (rc) {
CAM_ERR(CAM_UTIL, "No volt-compat-rgltr-name found, rc=%d", rc);
gpio_free(idpin_gpio);
idpin_gpio = 0;
return -EINVAL;
}
rc = of_property_read_u32(of_node,"volt-compat-gpio-value",&idpin_value);
if (rc) {
CAM_ERR(CAM_UTIL, "No volt-compat-gpio-value found, rc=%d", rc);
gpio_free(idpin_gpio);
idpin_gpio = 0;
return -EINVAL;
}
if(soc_info->index == 0 && idpin_gpio > 0) {
for (i = 0; i < soc_info->num_rgltr; i++) {
if((strcmp(soc_info->rgltr_name[i], rgltr_name)== 0)) {
int val = 1;
val = gpio_get_value(idpin_gpio);
if(val == idpin_value) {
soc_info->rgltr_min_volt [i]= second_vol_range[0];
soc_info->rgltr_max_volt[i]= second_vol_range[1];
}
CAM_ERR(CAM_UTIL, "cam:%d, %s, voltage range: min:%d max:%d",
soc_info->index,soc_info->rgltr_name[i], soc_info->rgltr_min_volt [i],soc_info->rgltr_max_volt[i]);
}
}
}
}else{
CAM_ERR(CAM_UTIL, "volt-compat-gpio request failed");
}
}else{
CAM_ERR(CAM_UTIL, "volt-compat-gpio is not vaild");
}
}
#endif
return rc;
}

View file

@ -20,9 +20,13 @@
#include "cam_cci_dev.h"
#include "cam_sensor_dev.h"
#include "cam_actuator_dev.h"
#ifdef CONFIG_AF_NOISE_ELIMINATION
#include "mot_actuator.h"
#endif
#include "cam_csiphy_dev.h"
#include "cam_eeprom_dev.h"
#include "cam_ois_dev.h"
#include "pm6125_flash_gpio.h"
#if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \
IS_REACHABLE(CONFIG_LEDS_QTI_FLASH)
@ -105,6 +109,9 @@ static const struct camera_submodule_component camera_sensor[] = {
{&cam_cci_init_module, &cam_cci_exit_module},
{&cam_csiphy_init_module, &cam_csiphy_exit_module},
{&cam_actuator_driver_init, &cam_actuator_driver_exit},
#ifdef CONFIG_AF_NOISE_ELIMINATION
{&mot_actuator_driver_init, &mot_actuator_driver_exit},
#endif
{&cam_sensor_driver_init, &cam_sensor_driver_exit},
{&cam_eeprom_driver_init, &cam_eeprom_driver_exit},
{&cam_ois_driver_init, &cam_ois_driver_exit},
@ -112,6 +119,9 @@ static const struct camera_submodule_component camera_sensor[] = {
IS_REACHABLE(CONFIG_LEDS_QTI_FLASH)
{&cam_flash_init_module, &cam_flash_exit_module},
#endif
#if IS_REACHABLE(CONFIG_CAMERA_FLASH_PWM)
{&pm6125_flash_gpio_init_module, &pm6125_flash_gpio_exit_module},
#endif
#endif
};

View file

@ -41,6 +41,9 @@ extern struct platform_driver cam_ois_platform_driver;
IS_REACHABLE(CONFIG_LEDS_QTI_FLASH)
extern struct platform_driver cam_flash_platform_driver;
#endif
#ifdef CONFIG_AF_NOISE_ELIMINATION
extern struct platform_driver mot_actuator_platform_driver;
#endif
#endif
#ifdef CONFIG_SPECTRA_ICP
extern struct platform_driver cam_a5_driver;
@ -102,6 +105,7 @@ static struct platform_driver *const cam_component_drivers[] = {
&cci_driver,
&csiphy_driver,
&cam_actuator_platform_driver,
&cam_sensor_platform_driver,
&cam_eeprom_platform_driver,
&cam_ois_platform_driver,
@ -109,6 +113,10 @@ static struct platform_driver *const cam_component_drivers[] = {
IS_REACHABLE(CONFIG_LEDS_QTI_FLASH)
&cam_flash_platform_driver,
#endif
#ifdef CONFIG_AF_NOISE_ELIMINATION
&mot_actuator_platform_driver,
#endif
#endif
#ifdef CONFIG_SPECTRA_ICP
&cam_a5_driver,

View file

@ -32,6 +32,12 @@
#define CAM_EXT_OPCODE_BASE 0x200
#define CAM_CONFIG_DEV_EXTERNAL (CAM_EXT_OPCODE_BASE + 0x1)
/* CONFIG_MOT_SENSOR_PRE_POWERUP */
#define CAM_MOT_OPCODE_BASE 0x250
#define CAM_MOT_PRE_POWER_UP (CAM_MOT_OPCODE_BASE + 0x1)
#define CAM_MOT_PRE_POWER_DOWN (CAM_MOT_OPCODE_BASE + 0x2)
#define CAM_MOT_QUERY_SENSOR_STATUS (CAM_MOT_OPCODE_BASE + 0x3)
/* camera handle type */
#define CAM_HANDLE_USER_POINTER 1
#define CAM_HANDLE_MEM_HANDLE 2

View file

@ -32,6 +32,7 @@
#define CAM_CUSTOM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 14)
#define CAM_OPE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 15)
#define CAM_TFE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 16)
#define CAM_MOT_ACTUATOR_TYPE (CAM_DEVICE_TYPE_BASE + 17)
/* cam_req_mgr hdl info */
#define CAM_REQ_MGR_HDL_IDX_POS 8

View file

@ -137,6 +137,13 @@ struct cam_cmd_ois_info {
__u8 cmd_type;
__u8 ois_fw_flag;
__u8 is_ois_calib;
__u8 ois_preprog_flag;
__u8 ois_precoeff_flag;
__u8 ois_postcalib_flag;
__u8 ois_fw_txn_data_sz;
__u8 ois_fw_inc_addr;
__u8 ois_fw_addr_type;
__u8 ois_fw_data_type;
char ois_name[MAX_OIS_NAME_SIZE];
struct cam_ois_opcode opcode;
} __attribute__((packed));
@ -165,6 +172,22 @@ struct cam_cmd_probe {
__u32 data_mask;
__u16 camera_id;
__u16 reserved;
__u8 probe_sub_device;
__u32 sub_device_addr;
__u8 sub_device_data_type;
__u8 sub_device_addr_type;
__u32 sub_device_id_addr;
__u32 expected_sub_device_id;
__u8 sub_device_cci_master;
__u8 sub_device_cci_device;
__u8 sub_device_i2c_freq_mode;
__u8 i2c_addr_switch;
__u32 second_i2c_address;
__u8 i2c_switch_reg_addr_Type;
__u8 i2c_switch_reg_data_Type;
__u32 i2c_switch_reg_addr;
__u32 i2c_switch_reg_data;
__u32 i2c_switch_reg_delayMs;
} __attribute__((packed));
/**
@ -485,6 +508,7 @@ struct cam_flash_query_cap_info {
__u32 max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS];
__u32 max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS];
__u32 flash_type;
__u32 flash_supplier;
} __attribute__ ((packed));
#endif