blob: e997419359c5d0aba389e4d90e499f982ffa393a [file] [log] [blame]
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <cam_sensor_cmn_header.h>
#include <cam_sensor_util.h>
#include <cam_sensor_io.h>
#include <cam_req_mgr_util.h>
#include "cam_sensor_soc.h"
#include "cam_soc_util.h"
int32_t cam_sensor_get_sub_module_index(struct device_node *of_node,
struct cam_sensor_board_info *s_info)
{
int rc = 0, i = 0;
uint32_t val = 0;
struct device_node *src_node = NULL;
struct cam_sensor_board_info *sensor_info;
sensor_info = s_info;
for (i = 0; i < SUB_MODULE_MAX; i++)
sensor_info->subdev_id[i] = -1;
src_node = of_parse_phandle(of_node, "actuator-src", 0);
if (!src_node) {
CAM_DBG(CAM_SENSOR, "src_node NULL");
} else {
rc = of_property_read_u32(src_node, "cell-index", &val);
CAM_DBG(CAM_SENSOR, "actuator cell index %d, rc %d", val, rc);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed %d", rc);
of_node_put(src_node);
return rc;
}
sensor_info->subdev_id[SUB_MODULE_ACTUATOR] = val;
of_node_put(src_node);
}
src_node = of_parse_phandle(of_node, "ois-src", 0);
if (!src_node) {
CAM_DBG(CAM_SENSOR, "src_node NULL");
} else {
rc = of_property_read_u32(src_node, "cell-index", &val);
CAM_DBG(CAM_SENSOR, " ois cell index %d, rc %d", val, rc);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed %d", rc);
of_node_put(src_node);
return rc;
}
sensor_info->subdev_id[SUB_MODULE_OIS] = val;
of_node_put(src_node);
}
src_node = of_parse_phandle(of_node, "eeprom-src", 0);
if (!src_node) {
CAM_DBG(CAM_SENSOR, "eeprom src_node NULL");
} else {
rc = of_property_read_u32(src_node, "cell-index", &val);
CAM_DBG(CAM_SENSOR, "eeprom cell index %d, rc %d", val, rc);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed %d", rc);
of_node_put(src_node);
return rc;
}
sensor_info->subdev_id[SUB_MODULE_EEPROM] = val;
of_node_put(src_node);
}
src_node = of_parse_phandle(of_node, "led-flash-src", 0);
if (!src_node) {
CAM_DBG(CAM_SENSOR, " src_node NULL");
} else {
rc = of_property_read_u32(src_node, "cell-index", &val);
CAM_DBG(CAM_SENSOR, "led flash cell index %d, rc %d", val, rc);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed %d", rc);
of_node_put(src_node);
return rc;
}
sensor_info->subdev_id[SUB_MODULE_LED_FLASH] = val;
of_node_put(src_node);
}
rc = of_property_read_u32(of_node, "csiphy-sd-index", &val);
if (rc < 0)
CAM_ERR(CAM_SENSOR, "paring the dt node for csiphy rc %d", rc);
else
sensor_info->subdev_id[SUB_MODULE_CSIPHY] = val;
return rc;
}
static int32_t cam_sensor_driver_get_dt_data(struct cam_sensor_ctrl_t *s_ctrl)
{
int32_t rc = 0;
int i = 0;
struct cam_sensor_board_info *sensordata = NULL;
struct device_node *of_node = s_ctrl->of_node;
struct cam_hw_soc_info *soc_info = &s_ctrl->soc_info;
s_ctrl->sensordata = kzalloc(sizeof(*sensordata), GFP_KERNEL);
if (!s_ctrl->sensordata)
return -ENOMEM;
sensordata = s_ctrl->sensordata;
rc = cam_soc_util_get_dt_properties(soc_info);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Failed to read DT properties rc %d", rc);
goto FREE_SENSOR_DATA;
}
rc = cam_sensor_util_init_gpio_pin_tbl(soc_info,
&sensordata->power_info.gpio_num_info);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Failed to read gpios %d", rc);
goto FREE_SENSOR_DATA;
}
s_ctrl->id = soc_info->index;
/* Validate cell_id */
if (s_ctrl->id >= MAX_CAMERAS) {
CAM_ERR(CAM_SENSOR, "Failed invalid cell_id %d", s_ctrl->id);
rc = -EINVAL;
goto FREE_SENSOR_DATA;
}
/* Store the index of BoB regulator if it is available */
for (i = 0; i < soc_info->num_rgltr; i++) {
if (!strcmp(soc_info->rgltr_name[i],
"cam_bob")) {
CAM_DBG(CAM_SENSOR,
"i: %d cam_bob", i);
s_ctrl->bob_reg_index = i;
soc_info->rgltr[i] = devm_regulator_get(soc_info->dev,
soc_info->rgltr_name[i]);
if (IS_ERR_OR_NULL(soc_info->rgltr[i])) {
CAM_WARN(CAM_SENSOR,
"Regulator: %s get failed",
soc_info->rgltr_name[i]);
soc_info->rgltr[i] = NULL;
} else {
if (!of_property_read_bool(of_node,
"pwm-switch")) {
CAM_DBG(CAM_SENSOR,
"No BoB PWM switch param defined");
s_ctrl->bob_pwm_switch = false;
} else {
s_ctrl->bob_pwm_switch = true;
}
}
}
}
/* Read subdev info */
rc = cam_sensor_get_sub_module_index(of_node, sensordata);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed to get sub module index, rc=%d",
rc);
goto FREE_SENSOR_DATA;
}
if (s_ctrl->io_master_info.master_type == CCI_MASTER) {
/* Get CCI master */
rc = of_property_read_u32(of_node, "cci-master",
&s_ctrl->cci_i2c_master);
CAM_DBG(CAM_SENSOR, "cci-master %d, rc %d",
s_ctrl->cci_i2c_master, rc);
if (rc < 0) {
/* Set default master 0 */
s_ctrl->cci_i2c_master = MASTER_0;
rc = 0;
}
}
if (of_property_read_u32(of_node, "sensor-position-pitch",
&sensordata->pos_pitch) < 0) {
CAM_DBG(CAM_SENSOR, "Invalid sensor position");
sensordata->pos_pitch = 360;
}
if (of_property_read_u32(of_node, "sensor-position-roll",
&sensordata->pos_roll) < 0) {
CAM_DBG(CAM_SENSOR, "Invalid sensor position");
sensordata->pos_roll = 360;
}
if (of_property_read_u32(of_node, "sensor-position-yaw",
&sensordata->pos_yaw) < 0) {
CAM_DBG(CAM_SENSOR, "Invalid sensor position");
sensordata->pos_yaw = 360;
}
return rc;
FREE_SENSOR_DATA:
kfree(sensordata);
return rc;
}
int32_t msm_sensor_init_default_params(struct cam_sensor_ctrl_t *s_ctrl)
{
/* Validate input parameters */
if (!s_ctrl) {
CAM_ERR(CAM_SENSOR, "failed: invalid params s_ctrl %pK",
s_ctrl);
return -EINVAL;
}
CAM_DBG(CAM_SENSOR,
"master_type: %d", s_ctrl->io_master_info.master_type);
/* Initialize cci_client */
if (s_ctrl->io_master_info.master_type == CCI_MASTER) {
s_ctrl->io_master_info.cci_client = kzalloc(sizeof(
struct cam_sensor_cci_client), GFP_KERNEL);
if (!(s_ctrl->io_master_info.cci_client))
return -ENOMEM;
} else if (s_ctrl->io_master_info.master_type == I2C_MASTER) {
if (!(s_ctrl->io_master_info.client))
return -EINVAL;
} else {
CAM_ERR(CAM_SENSOR,
"Invalid master / Master type Not supported");
return -EINVAL;
}
return 0;
}
int32_t cam_sensor_parse_dt(struct cam_sensor_ctrl_t *s_ctrl)
{
int32_t i, rc = 0;
struct cam_hw_soc_info *soc_info = &s_ctrl->soc_info;
/* Parse dt information and store in sensor control structure */
rc = cam_sensor_driver_get_dt_data(s_ctrl);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Failed to get dt data rc %d", rc);
return rc;
}
/* Initialize mutex */
mutex_init(&(s_ctrl->cam_sensor_mutex));
/* Initialize default parameters */
for (i = 0; i < soc_info->num_clk; i++) {
soc_info->clk[i] = devm_clk_get(soc_info->dev,
soc_info->clk_name[i]);
if (!soc_info->clk[i]) {
CAM_ERR(CAM_SENSOR, "get failed for %s",
soc_info->clk_name[i]);
rc = -ENOENT;
return rc;
}
}
rc = msm_sensor_init_default_params(s_ctrl);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"failed: msm_sensor_init_default_params rc %d", rc);
goto FREE_DT_DATA;
}
return rc;
FREE_DT_DATA:
kfree(s_ctrl->sensordata);
s_ctrl->sensordata = NULL;
return rc;
}