/* * ov5693_v4l2.c - ov5693 sensor driver * * Copyright (c) 2013-2017, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "../platform/tegra/camera/camera_gpio.h" #include "ov5693_mode_tbls.h" /* ov5693 Registers */ #define OV5693_SC_MODE_SELECT_ADDR 0x0100 #define OV5693_SC_MODE_SELECT_STREAMING 0x01 #define OV5693_SC_CHIP_ID_HIGH_ADDR 0x300A #define OV5693_SC_CHIP_ID_LOW_ADDR 0x300B #define OV5693_SC_CTRL_SCCB_ID_ADDR 0x302B #define OV5693_SC_CTRL_3B_ADDR 0x303B #define OV5693_SC_CTRL_3B_SCCB_ID2_NACK_EN (1 << 0) #define OV5693_SC_CTRL_3B_SCCB_PGM_ID_EN (1 << 1) #define OV5693_GROUP_HOLD_ADDR 0x3208 #define OV5693_GROUP_HOLD_START 0x00 #define OV5693_GROUP_HOLD_END 0x10 #define OV5693_GROUP_HOLD_LAUNCH_LBLANK 0x60 #define OV5693_GROUP_HOLD_LAUNCH_VBLANK 0xA0 #define OV5693_GROUP_HOLD_LAUNCH_IMMED 0xE0 #define OV5693_GROUP_HOLD_BANK_0 0x00 #define OV5693_GROUP_HOLD_BANK_1 0x01 #define OV5693_EXPO_HIGH_ADDR 0x3500 #define OV5693_EXPO_MID_ADDR 0x3501 #define OV5693_EXPO_LOW_ADDR 0x3502 #define OV5693_GAIN_SHIFT_ADDR 0x3507 #define OV5693_GAIN_HIGH_ADDR 0x3508 #define OV5693_GAIN_LOW_ADDR 0x3509 #define OV5693_TIMING_VTS_HIGH_ADDR 0x380E #define OV5693_TIMING_VTS_LOW_ADDR 0x380F #define OV5693_TIMING_RST_FSIN_HIGH_ADDR 0x3826 #define OV5693_TIMING_RST_FSIN_LOW_ADDR 0x3827 #define OV5693_OTP_BUFFER_ADDR 0x3D00 #define OV5693_OTP_BUFFER_SIZE 32 #define OV5693_OTP_STR_SIZE (OV5693_OTP_BUFFER_SIZE * 2) #define OV5693_FUSE_ID_OTP_BUFFER_ADDR 0x3D00 #define OV5693_FUSE_ID_OTP_BUFFER_SIZE 16 #define OV5693_FUSE_ID_STR_SIZE (OV5693_FUSE_ID_OTP_BUFFER_SIZE * 2) #define OV5693_OTP_PROGRAM_CTRL_ADDR 0x3D80 #define OV5693_OTP_LOAD_CTRL_ADDR 0x3D81 #define OV5693_OTP_LOAD_CTRL_OTP_RD 0x01 #define OV5693_PRE_CTRL00_ADDR 0x5E00 #define OV5693_PRE_CTRL00_TEST_PATTERN_EN (1 << 7) /* ov5693 Other Stuffs */ #define OV5693_DEFAULT_GAIN 0x0010 /* 1.0x real gain */ #define OV5693_MIN_GAIN 0x0001 #define OV5693_MAX_GAIN 0x1FFF #define OV5693_DEFAULT_FRAME_LENGTH 0x038E #define OV5693_MIN_FRAME_LENGTH 0x0001 #define OV5693_MAX_FRAME_LENGTH 0xFFFF #define OV5693_MIN_EXPOSURE_COARSE 0x00000001 #define OV5693_MAX_EXPOSURE_COARSE 0x000FFFFF #define OV5693_DEFAULT_EXPOSURE_COARSE 0x00002A90 #define OV5693_DEFAULT_MODE OV5693_MODE_1280X800_60FPS #define OV5693_DEFAULT_WIDTH 1280 #define OV5693_DEFAULT_HEIGHT 800 #define OV5693_DEFAULT_DATAFMT MEDIA_BUS_FMT_SRGGB10_1X10 #define OV5693_DEFAULT_CLK_FREQ 24000000 struct ov5693 { struct camera_common_power_rail power; int numctrls; int fsync; struct v4l2_ctrl_handler ctrl_handler; struct i2c_client *i2c_client; struct v4l2_subdev *subdev; struct media_pad pad; s32 group_hold_prev; u32 frame_length; bool group_hold_en; struct regmap *regmap; struct camera_common_data *s_data; struct camera_common_pdata *pdata; struct v4l2_ctrl *ctrls[]; }; static struct regmap_config ov5693_regmap_config = { .reg_bits = 16, .val_bits = 8, }; static int ov5693_g_volatile_ctrl(struct v4l2_ctrl *ctrl); static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl); static const struct v4l2_ctrl_ops ov5693_ctrl_ops = { .g_volatile_ctrl = ov5693_g_volatile_ctrl, .s_ctrl = ov5693_s_ctrl, }; static struct v4l2_ctrl_config ctrl_config_list[] = { /* Do not change the name field for the controls! */ { .ops = &ov5693_ctrl_ops, .id = TEGRA_CAMERA_CID_GAIN, .name = "Gain", .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, .min = OV5693_MIN_GAIN, .max = OV5693_MAX_GAIN, .def = OV5693_DEFAULT_GAIN, .step = 1, }, { .ops = &ov5693_ctrl_ops, .id = TEGRA_CAMERA_CID_FRAME_LENGTH, .name = "Frame Length", .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, .min = OV5693_MIN_FRAME_LENGTH, .max = OV5693_MAX_FRAME_LENGTH, .def = OV5693_DEFAULT_FRAME_LENGTH, .step = 1, }, { .ops = &ov5693_ctrl_ops, .id = TEGRA_CAMERA_CID_COARSE_TIME, .name = "Coarse Time", .type = V4L2_CTRL_TYPE_INTEGER, .flags = V4L2_CTRL_FLAG_SLIDER, .min = OV5693_MIN_EXPOSURE_COARSE, .max = OV5693_MAX_EXPOSURE_COARSE, .def = OV5693_DEFAULT_EXPOSURE_COARSE, .step = 1, }, { .ops = &ov5693_ctrl_ops, .id = TEGRA_CAMERA_CID_GROUP_HOLD, .name = "Group Hold", .type = V4L2_CTRL_TYPE_INTEGER_MENU, .min = 0, .max = ARRAY_SIZE(switch_ctrl_qmenu) - 1, .menu_skip_mask = 0, .def = 0, .qmenu_int = switch_ctrl_qmenu, }, { .ops = &ov5693_ctrl_ops, .id = TEGRA_CAMERA_CID_HDR_EN, .name = "HDR enable", .type = V4L2_CTRL_TYPE_INTEGER_MENU, .min = 0, .max = ARRAY_SIZE(switch_ctrl_qmenu) - 1, .menu_skip_mask = 0, .def = 0, .qmenu_int = switch_ctrl_qmenu, }, }; static int test_mode; module_param(test_mode, int, 0644); static inline int ov5693_read_reg(struct camera_common_data *s_data, u16 addr, u8 *val) { struct ov5693 *priv = (struct ov5693 *)s_data->priv; int err = 0; u32 reg_val = 0; err = regmap_read(priv->regmap, addr, ®_val); *val = reg_val & 0xFF; return err; } static int ov5693_write_reg(struct camera_common_data *s_data, u16 addr, u8 val) { int err; struct ov5693 *priv = (struct ov5693 *)s_data->priv; err = regmap_write(priv->regmap, addr, val); if (err) pr_err("%s:i2c write failed, %x = %x\n", __func__, addr, val); return err; } static int ov5693_write_table(struct ov5693 *priv, const ov5693_reg table[]) { return regmap_util_write_table_8(priv->regmap, table, NULL, 0, OV5693_TABLE_WAIT_MS, OV5693_TABLE_END); } //static void ov5693_gpio_set(struct ov5693 *priv, // unsigned int gpio, int val) //{ // if (priv->pdata && priv->pdata->use_cam_gpio) // cam_gpio_ctrl(&priv->i2c_client->dev, gpio, val, 1); // else { // if (gpio_cansleep(gpio)) // gpio_set_value_cansleep(gpio, val); // else // gpio_set_value(gpio, val); // } //} static int ov5693_power_on(struct camera_common_data *s_data) { int err = 0; struct ov5693 *priv = (struct ov5693 *)s_data->priv; struct camera_common_power_rail *pw = &priv->power; // u32 frame_time; dev_dbg(&priv->i2c_client->dev, "[OV5693]: %s: power on\n", __func__); if (priv->pdata && priv->pdata->power_on) { err = priv->pdata->power_on(pw); if (err) pr_err("%s failed.\n", __func__); else pw->state = SWITCH_ON; return err; } /* sleeps calls in the sequence below are for internal device * signal propagation as specified by sensor vendor */ // if (pw->avdd) // err = regulator_enable(pw->avdd); // if (err) // goto ov5693_avdd_fail; // // if (pw->iovdd) // err = regulator_enable(pw->iovdd); // if (err) // goto ov5693_iovdd_fail; // // if (pw->dvdd) // err = regulator_enable(pw->dvdd); // if (err) // goto ov5693_dvdd_fail; // // usleep_range(1, 2); // if (pw->pwdn_gpio) // ov5693_gpio_set(priv, pw->pwdn_gpio, 1); // // /* // * datasheet 2.9: reset requires ~2ms settling time // * a power on reset is generated after core power becomes stable // */ // usleep_range(2000, 2010); // // if (pw->reset_gpio) // ov5693_gpio_set(priv, pw->reset_gpio, 1); // // /* datasheet fig 2-9: t3 */ // usleep_range(2000, 2010); usleep_range(5350, 5360); pw->state = SWITCH_ON; // /* need SW standby LP11 for mipical. // * sensor default is LP00, this will transition to LP11 */ // ov5693_write_reg(s_data, 0x0100, 0x1); // ov5693_write_reg(s_data, 0x0100, 0x0); // /* // * Sleep to allow SW reset to settle into LP11. After writing // * 0x1, according to the datasheet, it could take the remainder // * of the frame time to settle. Streaming too soon after this // * may have unintended consequences. // */ // frame_time = OV5693_DEFAULT_FRAME_LENGTH * // OV5693_DEFAULT_LINE_LENGTH / OV5693_DEFAULT_PIXEL_CLOCK; // usleep_range(frame_time, frame_time + 1000); return 0; //ov5693_iovdd_fail: //ov5693_dvdd_fail: // regulator_disable(pw->avdd); // //ov5693_avdd_fail: // pr_err("%s failed.\n", __func__); // return -ENODEV; } //pr_info("[OV5693]: ctrls_init failed\n"); static int ov5693_power_off(struct camera_common_data *s_data) { int err = 0; struct ov5693 *priv = (struct ov5693 *)s_data->priv; struct camera_common_power_rail *pw = &priv->power; dev_dbg(&priv->i2c_client->dev, "[OV5693]: %s: power off\n", __func__); if (priv->pdata && priv->pdata->power_off) { err = priv->pdata->power_off(pw); if (!err) { goto power_off_done; } else { pr_err("%s failed.\n", __func__); return err; } } /* sleeps calls in the sequence below are for internal device * signal propagation as specified by sensor vendor */ // usleep_range(21, 25); // if (pw->pwdn_gpio) // ov5693_gpio_set(priv, pw->pwdn_gpio, 0); // usleep_range(1, 2); // if (pw->reset_gpio) // ov5693_gpio_set(priv, pw->reset_gpio, 0); // // /* datasheet 2.9: reset requires ~2ms settling time*/ // usleep_range(2000, 2010); // // if (pw->iovdd) // regulator_disable(pw->iovdd); // if (pw->avdd) // regulator_disable(pw->avdd); // if (pw->dvdd) // regulator_disable(pw->dvdd); power_off_done: pw->state = SWITCH_OFF; return 0; } static int ov5693_power_put(struct ov5693 *priv) { // struct camera_common_power_rail *pw = &priv->power; // pr_info("[OV5693]: power_put\n"); // // if (unlikely(!pw)) // return -EFAULT; // // if (likely(pw->avdd)) // regulator_put(pw->avdd); // // if (likely(pw->iovdd)) // regulator_put(pw->iovdd); // // if (likely(pw->dvdd)) // regulator_put(pw->dvdd); // // pw->avdd = NULL; // pw->iovdd = NULL; // pw->dvdd = NULL; // // if (priv->pdata && priv->pdata->use_cam_gpio) // cam_gpio_deregister(&priv->i2c_client->dev, pw->pwdn_gpio); // else { // gpio_free(pw->pwdn_gpio); // gpio_free(pw->reset_gpio); // } return 0; } //pr_info("[OV5693]: ctrls_init failed\n"); static int ov5693_power_get(struct ov5693 *priv) { struct camera_common_power_rail *pw = &priv->power; struct camera_common_pdata *pdata = priv->pdata; const char *mclk_name; const char *parentclk_name; struct clk *parent; // int err = 0, ret = 0; int err = 0; pr_info("[OV5693]: power_get\n"); if (!pdata) { dev_err(&priv->i2c_client->dev, "[OV5693]: pdata missing\n"); return -EFAULT; } mclk_name = pdata->mclk_name ? pdata->mclk_name : "cam_mclk1"; pw->mclk = devm_clk_get(&priv->i2c_client->dev, mclk_name); if (IS_ERR(pw->mclk)) { dev_err(&priv->i2c_client->dev, "[OV5693]: unable to get clock %s\n", mclk_name); return PTR_ERR(pw->mclk); } parentclk_name = pdata->parentclk_name; if (parentclk_name) { parent = devm_clk_get(&priv->i2c_client->dev, parentclk_name); if (IS_ERR(parent)) { dev_err(&priv->i2c_client->dev, "[OV5693]: unable to get parent clcok %s", parentclk_name); } else { clk_set_parent(pw->mclk, parent); pr_info("[OV5693]: set parent clock\n"); } } // /* analog 2.8v */ // err |= camera_common_regulator_get(&priv->i2c_client->dev, // &pw->avdd, pdata->regulators.avdd); // /* IO 1.8v */ // err |= camera_common_regulator_get(&priv->i2c_client->dev, // &pw->iovdd, pdata->regulators.iovdd); // // /* IO 1.2v */ // err |= camera_common_regulator_get(&priv->i2c_client->dev, // &pw->dvdd, pdata->regulators.dvdd); // // if (!err) { // pw->reset_gpio = pdata->reset_gpio; // pw->pwdn_gpio = pdata->pwdn_gpio; // } // else { // pr_info("[OV5693]: camera_common_regulator_get failed\n"); // } // // if (pdata->use_cam_gpio) { // err = cam_gpio_register(&priv->i2c_client->dev, pw->pwdn_gpio); // if (err) // dev_err(&priv->i2c_client->dev, // "[OV5693]: %s ERR can't register cam gpio %u!\n", // __func__, pw->pwdn_gpio); // } else { // ret = gpio_request(pw->pwdn_gpio, "cam_pwdn_gpio"); // if (ret < 0) // dev_dbg(&priv->i2c_client->dev, // "[OV5693]: %s can't request pwdn_gpio %d\n", // __func__, ret); // ret = gpio_request(pw->reset_gpio, "cam_reset_gpio"); // if (ret < 0) // dev_dbg(&priv->i2c_client->dev, // "[OV5693]: %s can't request reset_gpio %d\n", // __func__, ret); // } pw->state = SWITCH_OFF; return err; } static int ov5693_set_gain(struct ov5693 *priv, s32 val); static int ov5693_set_frame_length(struct ov5693 *priv, s32 val); static int ov5693_set_coarse_time(struct ov5693 *priv, s32 val); static int ov5693_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct camera_common_data *s_data = to_camera_common_data(&client->dev); struct ov5693 *priv = (struct ov5693 *)s_data->priv; struct v4l2_control control; int err; if (!enable) { dev_dbg(&client->dev, "%s: stream off\n", __func__); return ov5693_write_table(priv, mode_table[OV5693_MODE_STOP_STREAM]); } dev_dbg(&client->dev, "%s: write mode table %d\n", __func__, s_data->mode); err = ov5693_write_table(priv, mode_table[s_data->mode]); if (err) goto exit; if (ov5693_fsync_table[priv->fsync]) { dev_dbg(&client->dev, "%s: write fsync table %d\n", __func__, priv->fsync); err = ov5693_write_table(priv, ov5693_fsync_table[priv->fsync]); if (err) goto exit; } if (s_data->override_enable) { /* write list of override regs for the asking frame length, */ /* coarse integration time, and gain. Failures to write */ /* overrides are non-fatal. */ control.id = TEGRA_CAMERA_CID_GAIN; err = v4l2_g_ctrl(&priv->ctrl_handler, &control); err |= ov5693_set_gain(priv, control.value); if (err) dev_warn(&client->dev, "%s: error gain override\n", __func__); control.id = TEGRA_CAMERA_CID_FRAME_LENGTH; err = v4l2_g_ctrl(&priv->ctrl_handler, &control); err |= ov5693_set_frame_length(priv, control.value); if (err) dev_warn(&client->dev, "%s: error frame length override\n", __func__); control.id = TEGRA_CAMERA_CID_COARSE_TIME; err = v4l2_g_ctrl(&priv->ctrl_handler, &control); err |= ov5693_set_coarse_time(priv, control.value); if (err) dev_warn(&client->dev, "%s: error coarse time override\n", __func__); } #ifdef TPG err = ov5693_write_reg(priv->s_data, OV5693_PRE_CTRL00_ADDR, OV5693_PRE_CTRL00_TEST_PATTERN_EN); if (err) dev_warn(&client->dev, "%s: error enabling TPG\n", __func__); #endif dev_dbg(&client->dev, "%s: stream on\n", __func__); err = ov5693_write_table(priv, mode_table[OV5693_MODE_START_STREAM]); if (err) goto exit; /* * If the sensor is in fsync slave mode, and is in the middle of * sending a frame when it gets a strobe on the fsin pin, it may * prematurely end the frame, resulting in a short frame on our * camera host. So, after starting streaming, we assume fsync * master has already been told to start streaming, and we wait some * amount of time in order to skip the possible short frame. The * length of time to wait should be at least our sample period. * Assume worse case of 120fps (8.3ms), and add a bit more. */ if (priv->fsync == OV5693_FSYNC_SLAVE) msleep_range(10); return 0; exit: dev_err(&client->dev, "%s: error setting stream\n", __func__); return err; } static int ov5693_g_input_status(struct v4l2_subdev *sd, u32 *status) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct camera_common_data *s_data = to_camera_common_data(&client->dev); struct ov5693 *priv = (struct ov5693 *)s_data->priv; struct camera_common_power_rail *pw = &priv->power; *status = pw->state == SWITCH_ON; return 0; } static struct v4l2_subdev_video_ops ov5693_subdev_video_ops = { .s_stream = ov5693_s_stream, .g_mbus_config = camera_common_g_mbus_config, .g_input_status = ov5693_g_input_status, }; static struct v4l2_subdev_core_ops ov5693_subdev_core_ops = { .s_power = camera_common_s_power, }; static int ov5693_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) { return camera_common_g_fmt(sd, &format->format); } static int ov5693_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) { int ret; if (format->which == V4L2_SUBDEV_FORMAT_TRY) ret = camera_common_try_fmt(sd, &format->format); else ret = camera_common_s_fmt(sd, &format->format); return ret; } static struct v4l2_subdev_pad_ops ov5693_subdev_pad_ops = { .set_fmt = ov5693_set_fmt, .get_fmt = ov5693_get_fmt, .enum_mbus_code = camera_common_enum_mbus_code, .enum_frame_size = camera_common_enum_framesizes, .enum_frame_interval = camera_common_enum_frameintervals, }; static struct v4l2_subdev_ops ov5693_subdev_ops = { .core = &ov5693_subdev_core_ops, .video = &ov5693_subdev_video_ops, .pad = &ov5693_subdev_pad_ops, }; static struct of_device_id ov5693_of_match[] = { { .compatible = "nvidia,ov5693", }, { }, }; static struct camera_common_sensor_ops ov5693_common_ops = { .power_on = ov5693_power_on, .power_off = ov5693_power_off, .write_reg = ov5693_write_reg, .read_reg = ov5693_read_reg, }; static int ov5693_set_group_hold(struct ov5693 *priv) { int gh_prev = switch_ctrl_qmenu[priv->group_hold_prev]; int err; if (priv->group_hold_en == true && gh_prev == SWITCH_OFF) { /* group hold start */ err = ov5693_write_reg(priv->s_data, OV5693_GROUP_HOLD_ADDR, (OV5693_GROUP_HOLD_START | OV5693_GROUP_HOLD_BANK_0)); if (err) goto fail; priv->group_hold_prev = 1; } else if (priv->group_hold_en == false && gh_prev == SWITCH_ON) { /* group hold end */ err = ov5693_write_reg(priv->s_data, OV5693_GROUP_HOLD_ADDR, (OV5693_GROUP_HOLD_END | OV5693_GROUP_HOLD_BANK_0)); /* quick launch */ err |= ov5693_write_reg(priv->s_data, OV5693_GROUP_HOLD_ADDR, (OV5693_GROUP_HOLD_LAUNCH_VBLANK | OV5693_GROUP_HOLD_BANK_0)); if (err) goto fail; priv->group_hold_prev = 0; } return 0; fail: dev_dbg(&priv->i2c_client->dev, "%s: Group hold control error\n", __func__); return err; } static int ov5693_set_gain(struct ov5693 *priv, s32 val) { ov5693_reg regs[4]; u16 gain; int err; if (val < OV5693_MIN_GAIN) gain = OV5693_MIN_GAIN; else if (val > OV5693_MAX_GAIN) gain = OV5693_MAX_GAIN; else gain = val; dev_dbg(&priv->i2c_client->dev, "%s: gain: %d\n", __func__, gain); regs[0].addr = OV5693_GAIN_SHIFT_ADDR; regs[0].val = 0x03; regs[1].addr = OV5693_GAIN_HIGH_ADDR; regs[1].val = gain >> 8; regs[2].addr = OV5693_GAIN_LOW_ADDR; regs[2].val = gain & 0xff; regs[3].addr = OV5693_TABLE_END; regs[3].val = 0; ov5693_set_group_hold(priv); err = ov5693_write_table(priv, regs); if (err) goto fail; return 0; fail: dev_dbg(&priv->i2c_client->dev, "%s: GAIN control error\n", __func__); return err; } static int ov5693_set_frame_length(struct ov5693 *priv, s32 val) { ov5693_reg regs[5]; u16 frame_length; int err; /* * This is a workaround for nvbug 1865041, where setting the VTS * timing registers when the sensor is set up for fsync master or * slave leads to streaming instability. */ if (priv->fsync != OV5693_FSYNC_NONE) return 0; frame_length = (u16)val; dev_dbg(&priv->i2c_client->dev, "%s: frame_length: %d\n", __func__, frame_length); regs[0].addr = OV5693_TIMING_VTS_HIGH_ADDR; regs[0].val = (frame_length >> 8) & 0xff; regs[1].addr = OV5693_TIMING_VTS_LOW_ADDR; regs[1].val = (frame_length) & 0xff; regs[2].addr = OV5693_TABLE_END; regs[2].val = 0; if (priv->fsync == OV5693_FSYNC_SLAVE) { regs[2].addr = OV5693_TIMING_RST_FSIN_HIGH_ADDR; regs[2].val = ((frame_length - 4) >> 8) & 0xff; regs[3].addr = OV5693_TIMING_RST_FSIN_LOW_ADDR; regs[3].val = (frame_length - 4) & 0xff; regs[4].addr = OV5693_TABLE_END; regs[4].val = 0; } ov5693_set_group_hold(priv); err = ov5693_write_table(priv, regs); if (err) goto fail; return 0; fail: dev_dbg(&priv->i2c_client->dev, "%s: FRAME_LENGTH control error\n", __func__); return err; } static int ov5693_set_coarse_time(struct ov5693 *priv, s32 val) { ov5693_reg regs[4]; u32 coarse_time; int err; coarse_time = (u32)val; dev_dbg(&priv->i2c_client->dev, "%s: coarse_time: %d\n", __func__, coarse_time); regs[0].addr = OV5693_EXPO_HIGH_ADDR; regs[0].val = (coarse_time >> 16) & 0xff; regs[1].addr = OV5693_EXPO_MID_ADDR; regs[1].val = (coarse_time >> 8) & 0xff; regs[2].addr = OV5693_EXPO_LOW_ADDR; regs[2].val = (coarse_time & 0xff); regs[3].addr = OV5693_TABLE_END; regs[3].val = 0; ov5693_set_group_hold(priv); err = ov5693_write_table(priv, regs); if (err) goto fail; return 0; fail: dev_dbg(&priv->i2c_client->dev, "%s: COARSE_TIME control error\n", __func__); return err; } /* OTP stuff */ //static int ov5693_read_otp(struct ov5693 *priv, u8 *buf, u16 addr, int size) //{ // int i; // int err; // // err = ov5693_write_reg(priv->s_data, OV5693_SC_MODE_SELECT_ADDR, // OV5693_SC_MODE_SELECT_STREAMING); // if (err) // return err; // // for (i = 0; i < size; i++) { // err = ov5693_write_reg(priv->s_data, addr + i, 0x00); // if (err) // return err; // } // // err = ov5693_write_reg(priv->s_data, OV5693_OTP_LOAD_CTRL_ADDR, // OV5693_OTP_LOAD_CTRL_OTP_RD); // // msleep(20); // // return regmap_bulk_read(priv->regmap, addr, buf, size); // return 0; //} //static int ov5693_otp_setup(struct ov5693 *priv) //{ // struct v4l2_ctrl *ctrl; // u8 otp_buf[OV5693_OTP_BUFFER_SIZE]; // int i; // int err; // // err = camera_common_s_power(priv->subdev, true); // if (err) // return -ENODEV; // // err = ov5693_read_otp(priv, otp_buf, OV5693_OTP_BUFFER_ADDR, // OV5693_OTP_BUFFER_SIZE); // if (err) // return err; // // ctrl = v4l2_ctrl_find(&priv->ctrl_handler, TEGRA_CAMERA_CID_OTP_DATA); // if (!ctrl) { // dev_err(&priv->i2c_client->dev, // "could not find device ctrl.\n"); // return -EINVAL; // } // // for (i = 0; i < OV5693_OTP_BUFFER_SIZE; i++) // sprintf(&ctrl->p_new.p_char[i*2], "%02x", otp_buf[i]); // ctrl->p_cur.p_char = ctrl->p_new.p_char; // // err = camera_common_s_power(priv->subdev, false); // if (err) // return -ENODEV; // // return 0; //} //static int ov5693_fuse_id_setup(struct ov5693 *priv) //{ // struct v4l2_ctrl *ctrl; // u8 fuse_id[OV5693_FUSE_ID_OTP_BUFFER_SIZE]; // int i; // int err; // // err = camera_common_s_power(priv->subdev, true); // if (err) // return -ENODEV; // // err = ov5693_read_otp(priv, fuse_id, OV5693_FUSE_ID_OTP_BUFFER_ADDR, // OV5693_FUSE_ID_OTP_BUFFER_SIZE); // if (err) // return err; // // ctrl = v4l2_ctrl_find(&priv->ctrl_handler, TEGRA_CAMERA_CID_FUSE_ID); // if (!ctrl) { // dev_err(&priv->i2c_client->dev, // "could not find device ctrl.\n"); // return -EINVAL; // } // // for (i = 0; i < OV5693_FUSE_ID_OTP_BUFFER_SIZE; i++) // sprintf(&ctrl->p_new.p_char[i*2], "%02x", fuse_id[i]); // ctrl->p_cur.p_char = ctrl->p_new.p_char; // // err = camera_common_s_power(priv->subdev, false); // if (err) // return -ENODEV; // // return 0; //} static int ov5693_g_volatile_ctrl(struct v4l2_ctrl *ctrl) { struct ov5693 *priv = container_of(ctrl->handler, struct ov5693, ctrl_handler); int err = 0; if (priv->power.state == SWITCH_OFF) return 0; switch (ctrl->id) { default: pr_err("%s: unknown ctrl id.\n", __func__); return -EINVAL; } return err; } static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl) { struct ov5693 *priv = container_of(ctrl->handler, struct ov5693, ctrl_handler); int err = 0; if (priv->power.state == SWITCH_OFF) return 0; switch (ctrl->id) { case TEGRA_CAMERA_CID_GAIN: err = ov5693_set_gain(priv, ctrl->val); break; case TEGRA_CAMERA_CID_FRAME_LENGTH: err = ov5693_set_frame_length(priv, ctrl->val); break; case TEGRA_CAMERA_CID_COARSE_TIME: err = ov5693_set_coarse_time(priv, ctrl->val); break; case TEGRA_CAMERA_CID_GROUP_HOLD: if (switch_ctrl_qmenu[ctrl->val] == SWITCH_ON) { priv->group_hold_en = true; } else { priv->group_hold_en = false; err = ov5693_set_group_hold(priv); } break; case TEGRA_CAMERA_CID_HDR_EN: break; default: pr_err("%s: unknown ctrl id.\n", __func__); return -EINVAL; } return err; } static int ov5693_ctrls_init(struct ov5693 *priv, bool eeprom_ctrl) { struct i2c_client *client = priv->i2c_client; // struct camera_common_data *common_data = priv->s_data; struct v4l2_ctrl *ctrl; int numctrls; int err; int i; pr_info("[OV5693]: controls initialize - start.\n"); dev_dbg(&client->dev, "%s++\n", __func__); numctrls = ARRAY_SIZE(ctrl_config_list); v4l2_ctrl_handler_init(&priv->ctrl_handler, numctrls); for (i = 0; i < numctrls; i++) { ctrl = v4l2_ctrl_new_custom(&priv->ctrl_handler, &ctrl_config_list[i], NULL); if (ctrl == NULL) { dev_err(&client->dev, "Failed to init %s ctrl\n", ctrl_config_list[i].name); continue; } if (ctrl_config_list[i].type == V4L2_CTRL_TYPE_STRING && ctrl_config_list[i].flags & V4L2_CTRL_FLAG_READ_ONLY) { ctrl->p_new.p_char = devm_kzalloc(&client->dev, ctrl_config_list[i].max + 1, GFP_KERNEL); if (!ctrl->p_new.p_char) return -ENOMEM; } priv->ctrls[i] = ctrl; } priv->numctrls = numctrls; priv->subdev->ctrl_handler = &priv->ctrl_handler; if (priv->ctrl_handler.error) { dev_err(&client->dev, "Error %d adding controls\n", priv->ctrl_handler.error); err = priv->ctrl_handler.error; goto error; } pr_info("[OV5693]: handler setup.\n"); err = v4l2_ctrl_handler_setup(&priv->ctrl_handler); if (err) { dev_err(&client->dev, "Error %d setting default controls\n", err); goto error; } // pr_info("[OV5693]: otp setup.\n"); // // err = ov5693_otp_setup(priv); // if (err) { // dev_err(&client->dev, // "Error %d reading otp data\n", err); // goto error; // } // // pr_info("[OV5693]: fuse setup.\n"); // // err = ov5693_fuse_id_setup(priv); // if (err) { // dev_err(&client->dev, // "Error %d reading fuse id data\n", err); // goto error; // } pr_info("[OV5693]: handler setup.\n"); pr_info("[OV5693]: controls initialize - pass.\n"); return 0; error: v4l2_ctrl_handler_free(&priv->ctrl_handler); pr_info("[OV5693]: controls initialize - error.\n"); return err; } MODULE_DEVICE_TABLE(of, ov5693_of_match); static struct camera_common_pdata *ov5693_parse_dt(struct i2c_client *client) { struct device_node *node = client->dev.of_node; struct camera_common_pdata *board_priv_pdata; const struct of_device_id *match; int gpio; int err; struct camera_common_pdata *ret = NULL; if (!node) return NULL; match = of_match_device(ov5693_of_match, &client->dev); if (!match) { dev_err(&client->dev, "Failed to find matching dt id\n"); return NULL; } board_priv_pdata = devm_kzalloc(&client->dev, sizeof(*board_priv_pdata), GFP_KERNEL); if (!board_priv_pdata) return NULL; err = camera_common_parse_clocks(&client->dev, board_priv_pdata); if (err) { dev_err(&client->dev, "Failed to find clocks\n"); goto error; } pr_info("[OV5693]: parentclk-name %s\n", board_priv_pdata->parentclk_name); pr_info("[OV5693]: mclkname %s.\n", board_priv_pdata->mclk_name); gpio = of_get_named_gpio(node, "pwdn-gpios", 0); if (gpio < 0) { if (gpio == -EPROBE_DEFER) { ret = ERR_PTR(-EPROBE_DEFER); goto error; } dev_err(&client->dev, "pwdn gpios not in DT\n"); goto error; } board_priv_pdata->pwdn_gpio = (unsigned int)gpio; gpio = of_get_named_gpio(node, "reset-gpios", 0); if (gpio < 0) { /* reset-gpio is not absolutely needed */ if (gpio == -EPROBE_DEFER) { ret = ERR_PTR(-EPROBE_DEFER); goto error; } dev_dbg(&client->dev, "reset gpios not in DT\n"); gpio = 0; } board_priv_pdata->reset_gpio = (unsigned int)gpio; board_priv_pdata->use_cam_gpio = of_property_read_bool(node, "cam,use-cam-gpio"); err = of_property_read_string(node, "avdd-reg", &board_priv_pdata->regulators.avdd); if (err) { dev_err(&client->dev, "avdd-reg not in DT\n"); goto error; } err = of_property_read_string(node, "iovdd-reg", &board_priv_pdata->regulators.iovdd); if (err) { dev_err(&client->dev, "iovdd-reg not in DT\n"); goto error; } err = of_property_read_string(node, "dvdd-reg", &board_priv_pdata->regulators.dvdd); if (err) { dev_err(&client->dev, "dvdd-reg not in DT\n"); goto error; } board_priv_pdata->v_flip = of_property_read_bool(node, "vertical-flip"); board_priv_pdata->h_mirror = of_property_read_bool(node, "horizontal-mirror"); return board_priv_pdata; error: devm_kfree(&client->dev, board_priv_pdata); return ret; } static int ov5693_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct i2c_client *client = v4l2_get_subdevdata(sd); dev_dbg(&client->dev, "%s:\n", __func__); return 0; } static const struct v4l2_subdev_internal_ops ov5693_subdev_internal_ops = { .open = ov5693_open, }; static const struct media_entity_operations ov5693_media_ops = { .link_validate = v4l2_subdev_link_validate, }; static int ov5693_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct camera_common_data *common_data; struct device_node *node = client->dev.of_node; struct ov5693 *priv; int err; int clock_err = 0; // struct clk *parent; struct camera_common_power_rail *pw; pr_info("[OV5693]: probing v4l2 sensor.\n"); if (!IS_ENABLED(CONFIG_OF) || !node) return -EINVAL; common_data = devm_kzalloc(&client->dev, sizeof(struct camera_common_data), GFP_KERNEL); if (!common_data) return -ENOMEM; priv = devm_kzalloc(&client->dev, sizeof(struct ov5693) + sizeof(struct v4l2_ctrl *) * ARRAY_SIZE(ctrl_config_list), GFP_KERNEL); if (!priv) return -ENOMEM; priv->regmap = devm_regmap_init_i2c(client, &ov5693_regmap_config); if (IS_ERR(priv->regmap)) { dev_err(&client->dev, "regmap init failed: %ld\n", PTR_ERR(priv->regmap)); return -ENODEV; } priv->pdata = ov5693_parse_dt(client); /* set to none */ priv->fsync = OV5693_FSYNC_NONE; if (PTR_ERR(priv->pdata) == -EPROBE_DEFER) return -EPROBE_DEFER; if (!priv->pdata) { dev_err(&client->dev, "unable to get platform data\n"); return -EFAULT; } pr_info("[OV5693]: parsed device tree.\n"); common_data->ops = &ov5693_common_ops; common_data->ctrl_handler = &priv->ctrl_handler; common_data->dev = &client->dev; common_data->frmfmt = ov5693_frmfmt; common_data->colorfmt = camera_common_find_datafmt( OV5693_DEFAULT_DATAFMT); common_data->power = &priv->power; common_data->ctrls = priv->ctrls; common_data->priv = (void *)priv; common_data->numctrls = ARRAY_SIZE(ctrl_config_list); common_data->numfmts = ARRAY_SIZE(ov5693_frmfmt); common_data->def_mode = OV5693_DEFAULT_MODE; common_data->def_width = OV5693_DEFAULT_WIDTH; common_data->def_height = OV5693_DEFAULT_HEIGHT; common_data->fmt_width = common_data->def_width; common_data->fmt_height = common_data->def_height; common_data->def_clk_freq = OV5693_DEFAULT_CLK_FREQ; priv->i2c_client = client; priv->s_data = common_data; priv->subdev = &common_data->subdev; priv->subdev->dev = &client->dev; priv->s_data->dev = &client->dev; err = ov5693_power_get(priv); pr_info("[OV5693]: get power.\n"); if (err) { pr_info("[OV5693]: get power failed\n"); return err; } err = camera_common_initialize(common_data, "ov5693"); if (err) { dev_err(&client->dev, "Failed to initialize ov5693.\n"); return err; } pr_info("[OV5693]: camera initialized\n"); v4l2_i2c_subdev_init(priv->subdev, client, &ov5693_subdev_ops); pr_info("[OV5693]: sub device initialized\n"); // /* eeprom interface */ // err = ov5693_eeprom_device_init(priv); // if (err && priv->pdata->has_eeprom) // dev_err(&client->dev, // "Failed to allocate eeprom reg map: %d\n", err); err = ov5693_ctrls_init(priv, !err); if (err) { pr_info("[OV5693]: ctrls_init failed\n"); return err; } priv->subdev->internal_ops = &ov5693_subdev_internal_ops; priv->subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; #if defined(CONFIG_MEDIA_CONTROLLER) priv->pad.flags = MEDIA_PAD_FL_SOURCE; priv->subdev->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; priv->subdev->entity.ops = &ov5693_media_ops; err = media_entity_init(&priv->subdev->entity, 1, &priv->pad, 0); if (err < 0) { dev_err(&client->dev, "unable to init media entity\n"); return err; } #endif pr_info("[OV5693]: register subdev\n"); err = v4l2_async_register_subdev(priv->subdev); if (err) { pr_info("[OV5693]: register subdev failed %d\n", err); return err; } dev_dbg(&client->dev, "Detected OV5693 sensor\n"); pr_info("[OV5693]: r\n"); pw = &priv->power; pw->mclk = devm_clk_get(&client->dev, priv->pdata->mclk_name); if (IS_ERR(pw->mclk)) { dev_err(&priv->i2c_client->dev, "[OV5693]: unable to get clock %s\n", priv->pdata->mclk_name); } // parent = devm_clk_get(&client->dev, priv->pdata->parentclk_name); // if (IS_ERR(parent)) { // dev_err(&priv->i2c_client->dev, // "[OV5693]: unable to get parent clcok %s", // priv->pdata->parentclk_name); // } else { // clk_set_parent(pw->mclk, parent); // pr_info("[OV5693]: set parent clock\n"); // } // clock_err = clk_set_rate(pw->mclk, 24000000); if (clock_err) { pr_info("[OV5693]: clock cannot set rate %d\n", clock_err); } clock_err = clk_enable(pw->mclk); if (clock_err) { pr_info("[OV5693]: clock cannot be enabled %d\n", clock_err); } return 0; } static int ov5693_remove(struct i2c_client *client) { struct camera_common_data *s_data = to_camera_common_data(&client->dev); struct ov5693 *priv = (struct ov5693 *)s_data->priv; v4l2_async_unregister_subdev(priv->subdev); #if defined(CONFIG_MEDIA_CONTROLLER) media_entity_cleanup(&priv->subdev->entity); #endif v4l2_ctrl_handler_free(&priv->ctrl_handler); ov5693_power_put(priv); camera_common_cleanup(s_data); return 0; } static const struct i2c_device_id ov5693_id[] = { { "ov5693", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ov5693_id); static struct i2c_driver ov5693_i2c_driver = { .driver = { .name = "ov5693", .owner = THIS_MODULE, .of_match_table = of_match_ptr(ov5693_of_match), }, .probe = ov5693_probe, .remove = ov5693_remove, .id_table = ov5693_id, }; module_i2c_driver(ov5693_i2c_driver); MODULE_DESCRIPTION("SoC Camera driver for Sony OV5693"); MODULE_AUTHOR("David Wang "); MODULE_LICENSE("GPL v2");