media/i2c/soc_camera: remove unused rockchip drivers

Signed-off-by: Tao Huang <huangtao@rock-chips.com>
Change-Id: I898b1035c9d591143ec35e7b4c137603201ef89a
This commit is contained in:
Tao Huang
2019-11-12 19:23:41 +08:00
parent c2482146d1
commit f45127c595
32 changed files with 0 additions and 28500 deletions

View File

@@ -1,105 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
config VIDEO_OV8858
tristate "ov8858 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is ov8858 camera driver adapt to rockchip cif isp platform.
config VIDEO_OV2710
tristate "ov2710 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is ov2710 camera driver adapt to rockchip cif isp platform.
config VIDEO_OV4689
tristate "ov4689 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is OV4689 camera driver adapt to rockchip cif isp platform.
config VIDEO_IMX323
tristate "imx323 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is imx323 camera driver adapt to rockchip cif isp platform.
config VIDEO_OV7750
tristate "ov7750 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is ov7750 camera driver adapt to rockchip cif isp platform.
config VIDEO_TC358749XBG
tristate "tc358749xbg driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is tc358749xbg hdmi video driver adapt to rockchip cif isp platform.
config VIDEO_ADV7181
tristate "adv7181 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is adv7181 cvbs video driver adapt to rockchip cif isp platform.
config VIDEO_OV7675
tristate "ov7675 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is ov7675 camera driver adapt to rockchip cif isp platform.
config VIDEO_NT99230
tristate "nt99230 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is nt99230 hdmi video driver adapt to rockchip cif isp platform.
config VIDEO_OV13850
tristate "ov13850 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is ov13850 camera driver adapt to rockchip cif isp platform.
config VIDEO_OV9281
tristate "ov9281 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
help
This is ov9281 camera driver adapt to rockchip cif isp platform.
config VIDEO_OV9750
tristate "ov9750 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
---help---
This is ov9750 camera driver adapt to rockchip cif isp platform.
config VIDEO_ov5640
tristate "ov5640 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
help
This is ov5640 camera driver adapt to rockchip cif isp platform.
config VIDEO_SC031GS
tristate "sc031gs driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
help
This is sc031gs camera driver adapt to rockchip cif isp platform.
config VIDEO_SC2232
tristate "sc2232 driver adapt to rockchip cif isp platform"
depends on VIDEO_V4L2 && VIDEO_RK_CIF_ISP10 && I2C
default n
help
This is sc2232 camera driver adapt to rockchip cif isp platform.

View File

@@ -1,16 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_VIDEO_OV8858) += ov_camera_module.o rk_camera_module.o ov8858_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_OV2710) += ov_camera_module.o rk_camera_module.o ov2710_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_OV4689) += ov_camera_module.o rk_camera_module.o ov4689_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_IMX323) += imx_camera_module.o rk_camera_module.o imx323_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_OV7750) += ov_camera_module.o rk_camera_module.o ov7750_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_TC358749XBG) += tc_camera_module.o rk_camera_module.o tc358749xbg_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_ADV7181) += adv_camera_module.o rk_camera_module.o adv7181_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_OV7675) += ov_camera_module.o rk_camera_module.o ov7675_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_NT99230) += ov_camera_module.o rk_camera_module.o nt99230_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_OV13850) += ov_camera_module.o rk_camera_module.o ov13850_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_OV9281) += ov_camera_module.o rk_camera_module.o ov9281_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_OV9750) += ov_camera_module.o rk_camera_module.o ov9750_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_ov5640) += ov_camera_module.o rk_camera_module.o ov5640_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_SC031GS) += sc_camera_module.o rk_camera_module.o sc031gs_v4l2-i2c-subdev.o
obj-$(CONFIG_VIDEO_SC2232) += sc_camera_module.o rk_camera_module.o sc2232_v4l2-i2c-subdev.o

View File

@@ -1,582 +0,0 @@
/*
* adv7181 sensor driver
*
* Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* Author: zhoupeng <benjo.zhou@rock-chips.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
* Note:
*
* v0.1.0:
* 1. Initialize version;
* 2. Stream on sensor in configuration,
* and stream off sensor after 1frame;
* 3. Stream delay time is define in power_up_delays_ms[2];
*/
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf-core.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
#include <media/v4l2-controls_rockchip.h>
#include "adv_camera_module.h"
#define ADV7181_DRIVER_NAME "adv7181"
/* product ID */
#define ADV7181_PID_MAGIC 0x20
#define ADV7181_PID_ADDR 0x11
#define ADV7181_STATUS1_REG 0x10
#define ADV7181_STATUS1_IN_LOCK 0x01
#define ADV7181_STATUS1_AUTOD_MASK 0x70
#define ADV7181_STATUS1_AUTOD_NTSM_M_J 0x00
#define ADV7181_STATUS1_AUTOD_NTSC_4_43 0x10
#define ADV7181_STATUS1_AUTOD_PAL_M 0x20
#define ADV7181_STATUS1_AUTOD_PAL_60 0x30
#define ADV7181_STATUS1_AUTOD_PAL_B_G 0x40
#define ADV7181_STATUS1_AUTOD_SECAM 0x50
#define ADV7181_STATUS1_AUTOD_PAL_COMB 0x60
#define ADV7181_STATUS1_AUTOD_SECAM_525 0x70
#define ADV7181_INPUT_CONTROL 0x00
#define ADV7181_INPUT_DEFAULT 0x00
#define ADV7181_INPUT_CVBS_AIN2 0x00
#define ADV7181_INPUT_CVBS_AIN3 0x01
#define ADV7181_INPUT_CVBS_AIN5 0x02
#define ADV7181_INPUT_CVBS_AIN6 0x03
#define ADV7181_INPUT_CVBS_AIN8 0x04
#define ADV7181_INPUT_CVBS_AIN10 0x05
#define ADV7181_INPUT_CVBS_AIN1 0x0B
#define ADV7181_INPUT_CVBS_AIN4 0x0D
#define ADV7181_INPUT_CVBS_AIN7 0x0F
#define ADV7181_INPUT_YPRPB_AIN6_8_10 0x09
#define ADV7181_EXT_CLK 24000000
/* ======================================================================== */
/* Base sensor configs */
/* ======================================================================== */
/* resolution 720x480 30fps */
static struct adv_camera_module_reg adv7180_cvbs_30fps[] = {
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x04, 0x77},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x17, 0x41},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x1D, 0x47},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x31, 0x02},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x3A, 0x17},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x3B, 0x81},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x3D, 0xA2},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x3E, 0x6A},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x3F, 0xA0},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x86, 0x0B},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xF3, 0x01},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xF9, 0x03},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x0E, 0x80},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x52, 0x46},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x54, 0x80},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x7F, 0xFF},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x81, 0x30},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x90, 0xC9},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x91, 0x40},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x92, 0x3C},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x93, 0xCA},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x94, 0xD5},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xB1, 0xFF},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xB6, 0x08},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xC0, 0x9A},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xCF, 0x50},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xD0, 0x4E},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xD1, 0xB9},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xD6, 0xDD},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xD7, 0xE2},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xE5, 0x51},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0xF6, 0x3B},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x0E, 0x00},
/* disable out put data */
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0x03, 0x4C},
{ADV_CAMERA_MODULE_REG_TYPE_DATA, 0X00, 0X0B},
};
/* ======================================================================== */
static struct adv_camera_module_config adv7181_configs[] = {
/* For normal preview NTSC 480i */
{
.name = "adv7180_cvbs_ntsc_30fps",
.frm_fmt = {
.width = 720,
.height = 480,
.code = MEDIA_BUS_FMT_UYVY8_2X8
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 30
}
},
.reg_table = (void *)adv7180_cvbs_30fps,
.reg_table_num_entries =
sizeof(adv7180_cvbs_30fps)
/
sizeof(adv7180_cvbs_30fps[0]),
.v_blanking_time_us = 0,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
.ignore_measurement_check = 1,
PLTFRM_CAM_ITF_DVP_CFG(
PLTFRM_CAM_ITF_BT656_8I,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
PLTFRM_CAM_SDR_NEG_EDG,
ADV7181_EXT_CLK)
},
/* For normal preview PAL 576i */
{
.name = "adv7180_cvbs_pal_25fps",
.frm_fmt = {
.width = 720,
.height = 576,
.code = MEDIA_BUS_FMT_UYVY8_2X8
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 25
}
},
.reg_table = (void *)adv7180_cvbs_30fps,
.reg_table_num_entries =
sizeof(adv7180_cvbs_30fps)
/
sizeof(adv7180_cvbs_30fps[0]),
.v_blanking_time_us = 0,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
.ignore_measurement_check = 1,
PLTFRM_CAM_ITF_DVP_CFG(
PLTFRM_CAM_ITF_BT656_8I,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
PLTFRM_CAM_SDR_NEG_EDG,
ADV7181_EXT_CLK)
},
};
/*--------------------------------------------------------------------------*/
static int adv7181_set_flip(
struct adv_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len)
{
return 0;
}
static int adv7181_g_ctrl(struct adv_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
adv_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
adv_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int adv7181_g_timings(struct adv_camera_module *cam_mod,
struct adv_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid)
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
else
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
adv_camera_module_pr_err(cam_mod,
"failed with error (%d)\n",
ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int adv7181_s_ctrl(struct adv_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
adv_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
break;
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
case V4L2_CID_FOCUS_ABSOLUTE:
/* todo*/
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
adv_camera_module_pr_err(cam_mod,
"failed with error (%d)\n",
ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int adv7181_s_ext_ctrls(struct adv_camera_module *cam_mod,
struct adv_camera_module_ext_ctrls *ctrls)
{
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = adv7181_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else
ret = -EINVAL;
if (IS_ERR_VALUE(ret))
adv_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int adv7181_start_streaming(struct adv_camera_module *cam_mod)
{
int ret = 0;
adv_camera_module_pr_debug(cam_mod,
"active config=%s\n", cam_mod->active_config->name);
adv_camera_module_pr_debug(cam_mod, "=====streaming on ===\n");
ret = adv_camera_module_write_reg(cam_mod, 0x03, 0x0c);
if (IS_ERR_VALUE(ret))
goto err;
return 0;
err:
adv_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int adv7181_stop_streaming(struct adv_camera_module *cam_mod)
{
int ret = 0;
adv_camera_module_pr_debug(cam_mod, "\n");
ret = adv_camera_module_write_reg(cam_mod, 0x03, 0x4c);
if (IS_ERR_VALUE(ret))
goto err;
return 0;
err:
adv_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int adv7181_check_camera_id(struct adv_camera_module *cam_mod)
{
u8 pid;
int ret = 0;
adv_camera_module_pr_err(cam_mod, "\n");
ret |= adv_camera_module_read_reg(cam_mod, ADV7181_PID_ADDR, &pid);
if (IS_ERR_VALUE(ret)) {
adv_camera_module_pr_err(cam_mod,
"register read failed, camera module powered off?\n");
goto err;
}
if (pid == ADV7181_PID_MAGIC)
adv_camera_module_pr_err(cam_mod,
"successfully detected camera ID 0x%02x\n",
pid);
else {
adv_camera_module_pr_err(cam_mod,
"wrong camera ID, expected 0x%02x, detected 0x%02x\n",
ADV7181_PID_MAGIC, pid);
ret = -EINVAL;
goto err;
}
return 0;
err:
adv_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/* ======================================================================== */
int adv_camera_7181_module_s_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl)
{
return 0;
}
/* ======================================================================== */
int adv_camera_7181_module_s_ext_ctrls(
struct v4l2_subdev *sd,
struct v4l2_ext_controls *ctrls)
{
return 0;
}
long adv_camera_7181_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg)
{
return 0;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
static struct v4l2_subdev_core_ops adv7181_camera_module_core_ops = {
.g_ctrl = adv_camera_module_g_ctrl,
.s_ctrl = adv_camera_module_s_ctrl,
.s_ext_ctrls = adv_camera_module_s_ext_ctrls,
.s_power = adv_camera_module_s_power,
.ioctl = adv_camera_module_ioctl
};
static struct v4l2_subdev_video_ops adv7181_camera_module_video_ops = {
.s_frame_interval = adv_camera_module_s_frame_interval,
.g_frame_interval = adv_camera_module_g_frame_interval,
.s_stream = adv_camera_module_s_stream
};
static struct v4l2_subdev_pad_ops adv7181_camera_module_pad_ops = {
.enum_frame_interval = adv_camera_module_enum_frameintervals,
.get_fmt = adv_camera_module_g_fmt,
.set_fmt = adv_camera_module_s_fmt,
};
static struct v4l2_subdev_ops adv7181_camera_module_ops = {
.core = &adv7181_camera_module_core_ops,
.video = &adv7181_camera_module_video_ops,
.pad = &adv7181_camera_module_pad_ops
};
static struct adv_camera_module adv7181;
static struct adv_camera_module_custom_config adv7181_custom_config = {
.start_streaming = adv7181_start_streaming,
.stop_streaming = adv7181_stop_streaming,
.s_ctrl = adv7181_s_ctrl,
.g_ctrl = adv7181_g_ctrl,
.s_ext_ctrls = adv7181_s_ext_ctrls,
.g_timings = adv7181_g_timings,
.set_flip = adv7181_set_flip,
.check_camera_id = adv7181_check_camera_id,
.configs = adv7181_configs,
.num_configs = ARRAY_SIZE(adv7181_configs),
.power_up_delays_ms = {5, 30, 30},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static ssize_t adv7181_debugfs_reg_write(
struct file *file,
const char __user *buf,
size_t count,
loff_t *ppos)
{
struct adv_camera_module *cam_mod =
((struct seq_file *)file->private_data)->private;
char kbuf[30];
int reg;
int reg_value;
int ret;
int nbytes = min(count, sizeof(kbuf) - 1);
if (copy_from_user(kbuf, buf, nbytes))
return -EFAULT;
kbuf[nbytes] = '\0';
adv_camera_module_pr_err(cam_mod, "kbuf is %s\n", kbuf);
ret = sscanf(kbuf, " %x %x", &reg, &reg_value);
adv_camera_module_pr_err(cam_mod, "ret = %d!\n", ret);
if (ret != 2) {
adv_camera_module_pr_err(cam_mod, "sscanf failed!\n");
return 0;
}
adv_camera_module_write_reg(cam_mod, (u8)reg, (u8)reg_value);
adv_camera_module_pr_err(cam_mod,
"%s(%d): read reg 0x%02x ---> 0x%x!\n",
__func__, __LINE__,
reg, reg_value);
return count;
}
static int adv7181_debugfs_reg_show(struct seq_file *s, void *v)
{
int i;
u8 val;
struct adv_camera_module *cam_mod = s->private;
adv_camera_module_pr_err(cam_mod, "test\n");
for (i = 0; i <= 0xff; i++) {
adv_camera_module_read_reg(cam_mod, (u8)i, &val);
seq_printf(s, "0x%02x : 0x%02x\n", i, val);
}
return 0;
}
static int adv7181_debugfs_open(struct inode *inode, struct file *file)
{
struct specific_sensor *spsensor = inode->i_private;
return single_open(file, adv7181_debugfs_reg_show, spsensor);
}
static const struct file_operations adv7181_debugfs_fops = {
.owner = THIS_MODULE,
.open = adv7181_debugfs_open,
.read = seq_read,
.write = adv7181_debugfs_reg_write,
.llseek = seq_lseek,
.release = single_release
};
static struct dentry *debugfs_dir;
static int adv7181_probe(
struct i2c_client *client,
const struct i2c_device_id *id)
{
dev_info(&client->dev, "probing...\n");
v4l2_i2c_subdev_init(&adv7181.sd, client,
&adv7181_camera_module_ops);
adv7181.custom = adv7181_custom_config;
debugfs_dir = debugfs_create_dir("adv7181", NULL);
if (IS_ERR(debugfs_dir))
printk(KERN_ERR "%s(%d): create debugfs dir failed!\n",
__func__, __LINE__);
else
debugfs_create_file("register", S_IRUSR,
debugfs_dir, &adv7181,
&adv7181_debugfs_fops);
dev_info(&client->dev, "probing successful\n");
return 0;
}
/* ======================================================================== */
static int adv7181_remove(
struct i2c_client *client)
{
struct adv_camera_module *cam_mod = i2c_get_clientdata(client);
dev_info(&client->dev, "remadving device...\n");
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
adv_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");
return 0;
}
static const struct i2c_device_id adv7181_id[] = {
{ ADV7181_DRIVER_NAME, 0 },
{ }
};
static const struct of_device_id adv7181_of_match[] = {
{.compatible = "adi,adv7181-v4l2-i2c-subdev"},
{},
};
MODULE_DEVICE_TABLE(i2c, adv7181_id);
static struct i2c_driver adv7181_i2c_driver = {
.driver = {
.name = ADV7181_DRIVER_NAME,
.of_match_table = adv7181_of_match
},
.probe = adv7181_probe,
.remove = adv7181_remove,
.id_table = adv7181_id,
};
module_i2c_driver(adv7181_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for adv7181");
MODULE_AUTHOR("Benjo");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -1,295 +0,0 @@
/*
* adv_camera_module.h
*
* Generic adi sensor driver
*
* Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef ADV_CAMERA_MODULE_H
#define ADV_CAMERA_MODULE_H
#include <linux/workqueue.h>
#include <linux/platform_data/rk_isp10_platform_camera_module.h>
#include <linux/platform_data/rk_isp10_platform.h>
/*
* TODO: references to v4l2 should be reomved from here and go into a
* platform dependent wrapper
*/
#define ADV_CAMERA_MODULE_REG_TYPE_DATA PLTFRM_CAMERA_MODULE_REG_TYPE_DATA
#define ADV_CAMERA_MODULE_REG_TYPE_TIMEOUT PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define adv_camera_module_csi_config
#define adv_camera_module_reg pltfrm_camera_module_reg
#define ADV_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define ADV_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define ADV_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define ADV_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
#define ADV_CAMERA_MODULE_CTRL_UPDT_WB_TEMPERATURE 0x04
#define ADV_CAMERA_MODULE_CTRL_UPDT_AUTO_WB 0x08
#define ADV_CAMERA_MODULE_CTRL_UPDT_AUTO_GAIN 0x10
#define ADV_CAMERA_MODULE_CTRL_UPDT_AUTO_EXP 0x20
#define ADV_CAMERA_MODULE_CTRL_UPDT_FOCUS_ABSOLUTE 0x40
#define ADV_CAMERA_MODULE_CTRL_UPDT_PRESET_WB 0x80
#define ADV_CAMERA_MODULE_CTRL_UPDT_VTS_VALUE 0x100
enum adv_camera_module_state {
ADV_CAMERA_MODULE_POWER_OFF = 0,
ADV_CAMERA_MODULE_HW_STANDBY = 1,
ADV_CAMERA_MODULE_SW_STANDBY = 2,
ADV_CAMERA_MODULE_STREAMING = 3
};
struct adv_camera_module;
struct adv_camera_module_timings {
/* public */
u32 coarse_integration_time_min;
u32 coarse_integration_time_max_margin;
u32 fine_integration_time_min;
u32 fine_integration_time_max_margin;
u32 frame_length_lines;
u32 line_length_pck;
u32 vt_pix_clk_freq_hz;
u32 sensor_output_width;
u32 sensor_output_height;
u32 crop_horizontal_start; /* Sensor crop start cord. (x0,y0) */
u32 crop_vertical_start;
u32 crop_horizontal_end; /* Sensor crop end cord. (x1,y1) */
u32 crop_vertical_end;
u8 binning_factor_x;
u8 binning_factor_y;
u32 exp_time;
u32 gain;
};
struct adv_camera_module_config {
const char *name;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
bool auto_exp_enabled;
bool auto_gain_enabled;
bool auto_wb_enabled;
struct adv_camera_module_reg *reg_table;
u32 reg_table_num_entries;
struct adv_camera_module_reg *reg_diff_table;
u32 reg_diff_table_num_entries;
u32 v_blanking_time_us;
u32 line_length_pck;
u32 frame_length_lines;
struct adv_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
struct adv_camera_module_exp_config {
s32 exp_time;
bool auto_exp;
u16 gain;
u16 gain_percent;
bool auto_gain;
enum v4l2_flash_led_mode flash_mode;
u32 vts_value;
};
struct adv_camera_module_wb_config {
u32 temperature;
u32 preset_id;
bool auto_wb;
};
struct adv_camera_module_af_config {
u32 abs_pos;
u32 rel_pos;
};
struct adv_camera_module_ext_ctrl {
/* public */
u32 id;
u32 value;
__u32 reserved2[1];
};
struct adv_camera_module_ext_ctrls {
/* public */
u32 count;
struct adv_camera_module_ext_ctrl *ctrls;
};
/*
* start_streaming: (mandatory) will be called when sensor should be
* put into streaming mode right after the base config has been
* written to the sensor. After a successful call of this function
* the sensor should start delivering frame data.
*
* stop_streaming: (mandatory) will be called when sensor should stop
* delivering data. After a successful call of this function the
* sensor should not deliver any more frame data.
*
* check_camera_id: (optional) will be called when the sensor is
* powered on. If pradvided should check the sensor ID/version
* required by the custom driver. Register access should be
* possible when this function is invoked.
*
* s_ctrl: (mandatory) will be called at the successful end of
* adv_camera_module_s_ctrl with the ctrl_id as argument.
*
* priv: (optional) for private data used by the custom driver.
*/
struct adv_camera_module_custom_config {
int (*start_streaming)(struct adv_camera_module *cam_mod);
int (*stop_streaming)(struct adv_camera_module *cam_mod);
int (*check_camera_id)(struct adv_camera_module *cam_mod);
int (*s_ctrl)(struct adv_camera_module *cam_mod, u32 ctrl_id);
int (*g_ctrl)(struct adv_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct adv_camera_module *cam_mod,
struct adv_camera_module_timings *timings);
int (*s_vts)(struct adv_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct adv_camera_module *cam_mod,
struct adv_camera_module_ext_ctrls *ctrls);
int (*set_flip)(
struct adv_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len);
int (*init_common)(struct adv_camera_module *cam_mod);
int (*read_otp)(struct adv_camera_module *cam_mod);
struct adv_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
struct adv_camera_module_otp_work {
struct work_struct work;
struct workqueue_struct *wq;
void *cam_mod;
};
struct adv_camera_module {
/* public */
struct v4l2_subdev sd;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
struct adv_camera_module_exp_config exp_config;
struct adv_camera_module_wb_config wb_config;
struct adv_camera_module_af_config af_config;
struct adv_camera_module_custom_config custom;
enum adv_camera_module_state state;
enum adv_camera_module_state state_before_suspend;
struct adv_camera_module_config *active_config;
struct adv_camera_module_otp_work otp_work;
u32 ctrl_updt;
u32 vts_cur;
u32 vts_min;
bool auto_adjust_fps;
bool update_config;
bool frm_fmt_valid;
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
struct mutex lock;
};
#define adv_camera_module_pr_info(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_info(&(cam_mod)->sd, fmt, ## arg)
#define adv_camera_module_pr_debug(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_debug(&(cam_mod)->sd, fmt, ## arg)
#define adv_camera_module_pr_warn(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_warn(&(cam_mod)->sd, fmt, ## arg)
#define adv_camera_module_pr_err(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_err(&(cam_mod)->sd, fmt, ## arg)
int adv_camera_module_write_reglist(
struct adv_camera_module *cam_mod,
const struct adv_camera_module_reg reglist[],
int len);
int adv_camera_module_write_reg(
struct adv_camera_module *cam_mod,
u8 reg,
u8 val);
int adv_camera_module_read_reg(
struct adv_camera_module *cam_mod,
u8 reg,
u8 *val);
int adv_camera_module_read_reg_table(
struct adv_camera_module *cam_mod,
u16 reg,
u32 *val);
int adv_camera_module_s_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int adv_camera_module_g_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int adv_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int adv_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int adv_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);
int adv_camera_module_s_power(
struct v4l2_subdev *sd,
int on);
int adv_camera_module_g_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int adv_camera_module_s_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int adv_camera_module_s_ext_ctrls(
struct v4l2_subdev *sd,
struct v4l2_ext_controls *ctrls);
int adv_camera_module_enum_frameintervals(
struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie);
int adv_camera_module_init(
struct adv_camera_module *cam_mod,
struct adv_camera_module_custom_config *custom);
void adv_camera_module_release(
struct adv_camera_module *cam_mod);
long adv_camera_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg);
int adv_camera_module_get_flip_mirror(
struct adv_camera_module *cam_mod);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,294 +0,0 @@
/*
* aptina_camera_module.h
*
* Generic galaxycore sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef APTINA_CAMERA_MODULE_H
#define APTINA_CAMERA_MODULE_H
#include <linux/workqueue.h>
#include <linux/platform_data/rk_isp10_platform_camera_module.h>
#include <linux/platform_data/rk_isp10_platform.h>
/*
* TODO: references to v4l2 should be reomved from here and go into a
* platform dependent wrapper
*/
#define APTINA_CAMERA_MODULE_REG_TYPE_DATA \
PLTFRM_CAMERA_MODULE_REG_TYPE_DATA
#define APTINA_CAMERA_MODULE_REG_TYPE_TIMEOUT \
PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define aptina_camera_module_csi_config
#define aptina_camera_module_reg pltfrm_camera_module_reg
#define APTINA_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define APTINA_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define APTINA_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define APTINA_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
#define APTINA_CAMERA_MODULE_CTRL_UPDT_WB_TEMPERATURE 0x04
#define APTINA_CAMERA_MODULE_CTRL_UPDT_AUTO_WB 0x08
#define APTINA_CAMERA_MODULE_CTRL_UPDT_AUTO_GAIN 0x10
#define APTINA_CAMERA_MODULE_CTRL_UPDT_AUTO_EXP 0x20
#define APTINA_CAMERA_MODULE_CTRL_UPDT_FOCUS_ABSOLUTE 0x40
#define APTINA_CAMERA_MODULE_CTRL_UPDT_PRESET_WB 0x80
#define APTINA_CAMERA_MODULE_CTRL_UPDT_VTS_VALUE 0x100
enum aptina_camera_module_state {
APTINA_CAMERA_MODULE_POWER_OFF = 0,
APTINA_CAMERA_MODULE_HW_STANDBY = 1,
APTINA_CAMERA_MODULE_SW_STANDBY = 2,
APTINA_CAMERA_MODULE_STREAMING = 3
};
struct aptina_camera_module;
struct aptina_camera_module_timings {
/* public */
u32 coarse_integration_time_min;
u32 coarse_integration_time_max_margin;
u32 fine_integration_time_min;
u32 fine_integration_time_max_margin;
u32 frame_length_lines;
u32 line_length_pck;
u32 vt_pix_clk_freq_hz;
u32 sensor_output_width;
u32 sensor_output_height;
u32 crop_horizontal_start; /* Sensor crop start cord. (x0,y0) */
u32 crop_vertical_start;
u32 crop_horizontal_end; /* Sensor crop end cord. (x1,y1) */
u32 crop_vertical_end;
u8 binning_factor_x;
u8 binning_factor_y;
};
struct aptina_camera_module_config {
const char *name;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
bool auto_exp_enabled;
bool auto_gain_enabled;
bool auto_wb_enabled;
struct aptina_camera_module_reg *reg_table;
u32 reg_table_num_entries;
u32 bayer_order_alter_enble;
u32 v_blanking_time_us;
u32 line_length_pck;
u32 frame_length_lines;
struct aptina_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
struct aptina_camera_module_exp_config {
u32 exp_time;
bool auto_exp;
u16 gain;
u16 gain_percent;
bool auto_gain;
enum v4l2_flash_led_mode flash_mode;
u32 vts_value;
};
struct aptina_camera_module_wb_config {
u32 temperature;
u32 preset_id;
bool auto_wb;
};
struct aptina_camera_module_af_config {
u32 abs_pos;
u32 rel_pos;
};
struct aptina_camera_module_ext_ctrl {
/* public */
u32 id;
u32 value;
__u32 reserved2[1];
};
struct aptina_camera_module_ext_ctrls {
/* public */
u32 count;
struct aptina_camera_module_ext_ctrl *ctrls;
};
/*
* start_streaming: (mandatory) will be called when sensor should be
* put into streaming mode right after the base config has been
* written to the sensor. After a successful call of this function
* the sensor should start delivering frame data.
*
* stop_streaming: (mandatory) will be called when sensor should stop
* delivering data. After a successful call of this function the
* sensor should not deliver any more frame data.
*
* check_camera_id: (optional) will be called when the sensor is
* powered on. If provided should check the sensor ID/version
* required by the custom driver. Register access should be
* possible when this function is invoked.
*
* s_ctrl: (mandatory) will be called at the successful end of
* aptina_camera_module_s_ctrl with the ctrl_id as argument.
*
* priv: (optional) for private data used by the custom driver.
*/
struct aptina_camera_module_custom_config {
int (*start_streaming)(struct aptina_camera_module *cam_mod);
int (*stop_streaming)(struct aptina_camera_module *cam_mod);
int (*check_camera_id)(struct aptina_camera_module *cam_mod);
int (*s_ctrl)(struct aptina_camera_module *cam_mod, u32 ctrl_id);
int (*g_ctrl)(struct aptina_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct aptina_camera_module *cam_mod,
struct aptina_camera_module_timings *timings);
int (*s_vts)(struct aptina_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct aptina_camera_module *cam_mod,
struct aptina_camera_module_ext_ctrls *ctrls);
int (*set_flip)(struct aptina_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len);
struct aptina_camera_module_config *configs;
int (*init_common)(struct aptina_camera_module *cam_mod);
int (*g_exposure_valid_frame)(struct aptina_camera_module *cam_mod);
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
struct aptina_camera_module_timings timings;
};
struct aptina_camera_module {
/* public */
struct v4l2_subdev sd;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
struct aptina_camera_module_exp_config exp_config;
struct aptina_camera_module_wb_config wb_config;
struct aptina_camera_module_af_config af_config;
struct aptina_camera_module_custom_config custom;
enum aptina_camera_module_state state;
enum aptina_camera_module_state state_before_suspend;
struct aptina_camera_module_config *active_config;
u32 ctrl_updt;
u32 vts_cur;
u32 vts_min;
bool auto_adjust_fps;
bool update_config;
bool frm_fmt_valid;
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
struct mutex lock;
};
#define aptina_camera_module_pr_info(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_info(&cam_mod->sd, fmt, ## arg)
#define aptina_camera_module_pr_debug(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_debug(&cam_mod->sd, fmt, ## arg)
#define aptina_camera_module_pr_warn(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_warn(&cam_mod->sd, fmt, ## arg)
#define aptina_camera_module_pr_err(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_err(&cam_mod->sd, fmt, ## arg)
int aptina_camera_module_write_reglist(
struct aptina_camera_module *cam_mod,
const struct aptina_camera_module_reg reglist[],
int len);
int aptina_camera_module_write_reg(
struct aptina_camera_module *cam_mod,
u16 reg,
u16 val);
int aptina_camera_module_read_reg(
struct aptina_camera_module *cam_mod,
u16 data_length,
u16 reg,
u32 *val);
int aptina_camera_module_read_reg_table(
struct aptina_camera_module *cam_mod,
u16 reg,
u32 *val);
int aptina_camera_module_try_fmt(
struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt);
int aptina_camera_module_s_fmt(
struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int aptina_camera_module_g_fmt(
struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int aptina_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int aptina_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int aptina_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);
int aptina_camera_module_s_power(
struct v4l2_subdev *sd,
int on);
int aptina_camera_module_g_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int aptina_camera_module_s_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int aptina_camera_module_s_ext_ctrls(
struct v4l2_subdev *sd,
struct v4l2_ext_controls *ctrls);
int aptina_camera_module_enum_frameintervals(
struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *file);
int aptina_camera_module_init(
struct aptina_camera_module *cam_mod,
struct aptina_camera_module_custom_config *custom);
void aptina_camera_module_release(
struct aptina_camera_module *cam_mod);
long aptina_camera_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg);
int aptina_camera_module_get_flip_mirror(
struct aptina_camera_module *cam_mod);
#endif

View File

@@ -1,660 +0,0 @@
/*
* IMX323 sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf-core.h>
#include <linux/slab.h>
#include "imx_camera_module.h"
#define IMX323_DRIVER_NAME "imx323"
#define IMX323_AEC_PK_GAIN_REG 0x301e
#define IMX323_AEC_PK_EXPO_HIGH_REG 0x0202
#define IMX323_AEC_PK_EXPO_LOW_REG 0x0203
#define IMX323_FETCH_HIGH_BYTE_EXP(VAL) ((VAL >> 8) & 0xFF)
#define IMX323_FETCH_LOW_BYTE_EXP(VAL) (VAL & 0xFF)
#define IMX323_PID_ADDR 0x0112
#define IMX323_PID_MAGIC 0xa
#define IMX323_TIMING_VTS_HIGH_REG 0x0340
#define IMX323_TIMING_VTS_LOW_REG 0x0341
#define IMX323_TIMING_HTS_HIGH_REG 0x0342
#define IMX323_TIMING_HTS_LOW_REG 0x0343
#define IMX323_INTEGRATION_TIME_MARGIN 8
#define IMX323_FINE_INTG_TIME_MIN 0
#define IMX323_FINE_INTG_TIME_MAX_MARGIN 0
#define IMX323_COARSE_INTG_TIME_MIN 16
#define IMX323_COARSE_INTG_TIME_MAX_MARGIN 4
#define IMX323_ORIENTATION_REG 0x0101
#define IMX323_ORIENTATION_H 0x1
#define IMX323_ORIENTATION_V 0x2
#define IMX323_EXT_CLK 37125000
static struct imx_camera_module imx323;
static struct imx_camera_module_custom_config imx323_custom_config;
/* ======================================================================== */
/* Base sensor configs */
/* ======================================================================== */
/* MCLK:37.125MHz 1920x1080 30fps DVP_12_DATA PCLK:74.25MHz */
static struct imx_camera_module_reg imx323_init_tab_1920_1080_30fps[] = {
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x0100, 0x00},
{IMX_CAMERA_MODULE_REG_TYPE_TIMEOUT, 0x0000, 0x01},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x0009, 0xf0},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x0112, 0x0c},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x0113, 0x0c},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x0340, 0x04},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x0341, 0x65},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x0342, 0x04},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x0343, 0x4c},
{IMX_CAMERA_MODULE_REG_TYPE_TIMEOUT, 0x0000, 0x01},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3000, 0x31},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3002, 0x0f},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3011, 0x00},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3012, 0x82},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3013, 0x40},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3016, 0x3c},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x301a, 0xc9},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x301c, 0x50},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x301f, 0x73},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3021, 0x00},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3022, 0x40},
{IMX_CAMERA_MODULE_REG_TYPE_TIMEOUT, 0x0000, 0x01},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3027, 0x20},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x302c, 0x00},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x303f, 0x0a},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x304f, 0x47},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3054, 0x11},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x307a, 0x00},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x307b, 0x00},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3098, 0x26},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3099, 0x02},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x309a, 0x26},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x309b, 0x02},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x30ce, 0x16},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x30cf, 0x82},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x30d0, 0x00},
{IMX_CAMERA_MODULE_REG_TYPE_DATA, 0x3117, 0x0d}
};
/* ======================================================================== */
static struct imx_camera_module_config imx323_configs[] = {
{
.name = "1920x1080_30fps",
.frm_fmt = {
.width = 2200,
.height = 1125,
.code = MEDIA_BUS_FMT_SGBRG12_1X12
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 30
}
},
.auto_exp_enabled = false,
.auto_gain_enabled = false,
.auto_wb_enabled = false,
.reg_table = (void *)imx323_init_tab_1920_1080_30fps,
.reg_table_num_entries =
sizeof(imx323_init_tab_1920_1080_30fps) /
sizeof(imx323_init_tab_1920_1080_30fps[0]),
.v_blanking_time_us = 5000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_DVP_CFG(
PLTFRM_CAM_ITF_BT601_12,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
PLTFRM_CAM_SDR_NEG_EDG,
IMX323_EXT_CLK)
}
};
/*--------------------------------------------------------------------------*/
static int imx323_g_VTS(struct imx_camera_module *cam_mod, u32 *vts)
{
u32 msb, lsb;
int ret;
ret = imx_camera_module_read_reg_table(
cam_mod,
IMX323_TIMING_VTS_HIGH_REG,
&msb);
if (IS_ERR_VALUE(ret))
goto err;
ret = imx_camera_module_read_reg_table(
cam_mod,
IMX323_TIMING_VTS_LOW_REG,
&lsb);
if (IS_ERR_VALUE(ret))
goto err;
*vts = (msb << 8) | lsb;
return 0;
err:
imx_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_auto_adjust_fps(struct imx_camera_module *cam_mod,
u32 exp_time)
{
int ret;
u32 vts;
if ((exp_time + IMX323_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = exp_time + IMX323_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
ret = imx_camera_module_write_reg(cam_mod,
IMX323_TIMING_VTS_LOW_REG, vts & 0xFF);
ret |= imx_camera_module_write_reg(cam_mod,
IMX323_TIMING_VTS_HIGH_REG, (vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
imx_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
imx_camera_module_pr_info(cam_mod,
"updated vts = %d,vts_min=%d\n", vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int imx323_set_vts(struct imx_camera_module *cam_mod,
u32 vts)
{
int ret = 0;
if (vts < cam_mod->vts_min)
return ret;
if (vts > 0xfff)
vts = 0xfff;
ret = imx_camera_module_write_reg(cam_mod,
IMX323_TIMING_VTS_LOW_REG, vts & 0xFF);
ret |= imx_camera_module_write_reg(cam_mod,
IMX323_TIMING_VTS_HIGH_REG, (vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
imx_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
} else {
imx_camera_module_pr_info(cam_mod, "updated vts=%d,vts_min=%d\n", vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_write_aec(struct imx_camera_module *cam_mod)
{
int ret = 0;
imx_camera_module_pr_debug(cam_mod,
"exp_time = %d, gain = %d, flash_mode = %d\n",
cam_mod->exp_config.exp_time,
cam_mod->exp_config.gain,
cam_mod->exp_config.flash_mode);
/*
* if the sensor is already streaming, write to shadow registers,
* if the sensor is in SW standby, write to active registers,
* if the sensor is off/registers are not writeable, do nothing
*/
if ((cam_mod->state == IMX_CAMERA_MODULE_SW_STANDBY) ||
(cam_mod->state == IMX_CAMERA_MODULE_STREAMING)) {
u32 a_gain = cam_mod->exp_config.gain;
u32 exp_time = cam_mod->exp_config.exp_time;
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
mutex_lock(&cam_mod->lock);
if (!IS_ERR_VALUE(ret) && cam_mod->auto_adjust_fps)
ret = imx323_auto_adjust_fps(cam_mod,
cam_mod->exp_config.exp_time);
/* Gain */
ret = imx_camera_module_write_reg(cam_mod,
IMX323_AEC_PK_GAIN_REG, a_gain);
/* Integration Time */
ret = imx_camera_module_write_reg(cam_mod,
IMX323_AEC_PK_EXPO_HIGH_REG,
IMX323_FETCH_HIGH_BYTE_EXP(exp_time));
ret |= imx_camera_module_write_reg(cam_mod,
IMX323_AEC_PK_EXPO_LOW_REG,
IMX323_FETCH_LOW_BYTE_EXP(exp_time));
if (!cam_mod->auto_adjust_fps)
ret |= imx323_set_vts(cam_mod, cam_mod->exp_config.vts_value);
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
imx_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_g_ctrl(struct imx_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
imx_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
imx_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_filltimings(struct imx_camera_module_custom_config *custom)
{
int i, j;
struct imx_camera_module_config *config;
struct imx_camera_module_timings *timings;
struct imx_camera_module_reg *reg_table;
int reg_table_num_entries;
for (i = 0; i < custom->num_configs; i++) {
config = &custom->configs[i];
reg_table = config->reg_table;
reg_table_num_entries = config->reg_table_num_entries;
timings = &config->timings;
for (j = 0; j < reg_table_num_entries; j++) {
switch (reg_table[j].reg) {
case IMX323_TIMING_VTS_HIGH_REG:
timings->frame_length_lines =
reg_table[j].val << 8;
break;
case IMX323_TIMING_VTS_LOW_REG:
timings->frame_length_lines |= reg_table[j].val;
break;
case IMX323_TIMING_HTS_HIGH_REG:
timings->line_length_pck =
(reg_table[j].val << 8);
break;
case IMX323_TIMING_HTS_LOW_REG:
timings->line_length_pck |= reg_table[j].val;
break;
}
}
timings->exp_time >>= 4;
timings->line_length_pck = timings->line_length_pck * 2;
timings->vt_pix_clk_freq_hz =
config->frm_intrvl.interval.denominator
* timings->frame_length_lines
* timings->line_length_pck;
timings->coarse_integration_time_min =
IMX323_COARSE_INTG_TIME_MIN;
timings->coarse_integration_time_max_margin =
IMX323_COARSE_INTG_TIME_MAX_MARGIN;
/* IMX Sensor do not use fine integration time. */
timings->fine_integration_time_min = IMX323_FINE_INTG_TIME_MIN;
timings->fine_integration_time_max_margin =
IMX323_FINE_INTG_TIME_MAX_MARGIN;
}
return 0;
}
static int imx323_g_timings(struct imx_camera_module *cam_mod,
struct imx_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid)
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
else
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
imx_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_set_flip(
struct imx_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len)
{
int i, mode = 0;
u16 orientation = 0;
mode = imx_camera_module_get_flip_mirror(cam_mod);
if (mode == -1) {
imx_camera_module_pr_info(cam_mod,
"dts don't set flip, return!\n");
return 0;
}
if (!IS_ERR_OR_NULL(cam_mod->active_config)) {
if (PLTFRM_CAMERA_MODULE_IS_MIRROR(mode))
orientation |= 0x01;
if (PLTFRM_CAMERA_MODULE_IS_FLIP(mode))
orientation |= 0x02;
for (i = 0; i < len; i++) {
if (reglist[i].reg == IMX323_ORIENTATION_REG)
reglist[i].val = orientation;
}
}
return 0;
}
/*--------------------------------------------------------------------------*/
static int imx323_s_ctrl(struct imx_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
imx_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
ret = imx323_write_aec(cam_mod);
break;
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
imx_camera_module_pr_debug(cam_mod,
"failed with error (%d) 0x%x\n",
ret, ctrl_id);
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_s_ext_ctrls(struct imx_camera_module *cam_mod,
struct imx_camera_module_ext_ctrls *ctrls)
{
int ret = 0;
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = imx323_write_aec(cam_mod);
else
ret = -EINVAL;
if (IS_ERR_VALUE(ret))
imx_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_start_streaming(struct imx_camera_module *cam_mod)
{
int ret = 0;
imx_camera_module_pr_debug(cam_mod,
"active config=%s\n", cam_mod->active_config->name);
ret = imx323_g_VTS(cam_mod, &cam_mod->vts_min);
if (IS_ERR_VALUE(ret))
goto err;
mutex_lock(&cam_mod->lock);
ret = imx_camera_module_write_reg(cam_mod, 0x0100, 1);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
return 0;
err:
imx_camera_module_pr_err(cam_mod, "failed with error (%d)\n",
ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_stop_streaming(struct imx_camera_module *cam_mod)
{
int ret = 0;
imx_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = imx_camera_module_write_reg(cam_mod, 0x0100, 0);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
return 0;
err:
imx_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int imx323_check_camera_id(struct imx_camera_module *cam_mod)
{
u32 pid;
int ret = 0;
imx_camera_module_pr_debug(cam_mod, "\n");
ret |= imx_camera_module_read_reg(cam_mod, 1, IMX323_PID_ADDR, &pid);
if (IS_ERR_VALUE(ret)) {
imx_camera_module_pr_err(cam_mod,
"register read failed, camera module powered off?\n");
goto err;
}
if (pid == IMX323_PID_MAGIC) {
imx_camera_module_pr_debug(cam_mod,
"successfully detected camera ID 0x%02x\n",
pid);
} else {
imx_camera_module_pr_err(cam_mod,
"wrong camera ID, expected 0x%02x, detected 0x%02x\n",
IMX323_PID_MAGIC, pid);
ret = -EINVAL;
goto err;
}
return 0;
err:
imx_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
static struct v4l2_subdev_core_ops imx323_camera_module_core_ops = {
.g_ctrl = imx_camera_module_g_ctrl,
.s_ctrl = imx_camera_module_s_ctrl,
.s_ext_ctrls = imx_camera_module_s_ext_ctrls,
.s_power = imx_camera_module_s_power,
.ioctl = imx_camera_module_ioctl
};
static struct v4l2_subdev_video_ops imx323_camera_module_video_ops = {
.s_frame_interval = imx_camera_module_s_frame_interval,
.g_frame_interval = imx_camera_module_g_frame_interval,
.s_stream = imx_camera_module_s_stream
};
static struct v4l2_subdev_pad_ops imx323_camera_module_pad_ops = {
.enum_frame_interval = imx_camera_module_enum_frameintervals,
.get_fmt = imx_camera_module_g_fmt,
.set_fmt = imx_camera_module_s_fmt,
};
static struct v4l2_subdev_ops imx323_camera_module_ops = {
.core = &imx323_camera_module_core_ops,
.video = &imx323_camera_module_video_ops,
.pad = &imx323_camera_module_pad_ops
};
static struct imx_camera_module_custom_config imx323_custom_config = {
.start_streaming = imx323_start_streaming,
.stop_streaming = imx323_stop_streaming,
.s_ctrl = imx323_s_ctrl,
.s_ext_ctrls = imx323_s_ext_ctrls,
.g_ctrl = imx323_g_ctrl,
.g_timings = imx323_g_timings,
.check_camera_id = imx323_check_camera_id,
.set_flip = imx323_set_flip,
.s_vts = imx323_auto_adjust_fps,
.configs = imx323_configs,
.num_configs = ARRAY_SIZE(imx323_configs),
.power_up_delays_ms = {5, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int imx323_probe(
struct i2c_client *client,
const struct i2c_device_id *id)
{
dev_info(&client->dev, "probing...\n");
imx323_filltimings(&imx323_custom_config);
v4l2_i2c_subdev_init(&imx323.sd, client, &imx323_camera_module_ops);
imx323.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
imx323.custom = imx323_custom_config;
mutex_init(&imx323.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
static int imx323_remove(struct i2c_client *client)
{
struct imx_camera_module *cam_mod = i2c_get_clientdata(client);
dev_info(&client->dev, "removing device...\n");
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
imx_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");
return 0;
}
static const struct i2c_device_id imx323_id[] = {
{ IMX323_DRIVER_NAME, 0 },
{ }
};
static const struct of_device_id imx323_of_match[] = {
{.compatible = "sony,imx323-v4l2-i2c-subdev"},
{},
};
MODULE_DEVICE_TABLE(i2c, imx323_id);
static struct i2c_driver imx323_i2c_driver = {
.driver = {
.name = IMX323_DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = imx323_of_match
},
.probe = imx323_probe,
.remove = imx323_remove,
.id_table = imx323_id,
};
module_i2c_driver(imx323_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for IMX323");
MODULE_AUTHOR("George");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -1,292 +0,0 @@
/*
* imx_camera_module.h
*
* Generic sony sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef IMX_CAMERA_MODULE_H
#define IMX_CAMERA_MODULE_H
#include <linux/workqueue.h>
#include <linux/platform_data/rk_isp10_platform_camera_module.h>
#include <linux/platform_data/rk_isp10_platform.h>
/*
* TODO: references to v4l2 should be reomved from here and go into a
* platform dependent wrapper
*/
#define IMX_CAMERA_MODULE_REG_TYPE_DATA PLTFRM_CAMERA_MODULE_REG_TYPE_DATA
#define IMX_CAMERA_MODULE_REG_TYPE_TIMEOUT PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define imx_camera_module_csi_config
#define imx_camera_module_reg pltfrm_camera_module_reg
#define IMX_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define IMX_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define IMX_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define IMX_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
#define IMX_CAMERA_MODULE_CTRL_UPDT_WB_TEMPERATURE 0x04
#define IMX_CAMERA_MODULE_CTRL_UPDT_AUTO_WB 0x08
#define IMX_CAMERA_MODULE_CTRL_UPDT_AUTO_GAIN 0x10
#define IMX_CAMERA_MODULE_CTRL_UPDT_AUTO_EXP 0x20
#define IMX_CAMERA_MODULE_CTRL_UPDT_FOCUS_ABSOLUTE 0x40
#define IMX_CAMERA_MODULE_CTRL_UPDT_PRESET_WB 0x80
#define IMX_CAMERA_MODULE_CTRL_UPDT_VTS_VALUE 0x100
enum imx_camera_module_state {
IMX_CAMERA_MODULE_POWER_OFF = 0,
IMX_CAMERA_MODULE_HW_STANDBY = 1,
IMX_CAMERA_MODULE_SW_STANDBY = 2,
IMX_CAMERA_MODULE_STREAMING = 3
};
struct imx_camera_module;
struct imx_camera_module_timings {
u32 coarse_integration_time_min;
u32 coarse_integration_time_max_margin;
u32 fine_integration_time_min;
u32 fine_integration_time_max_margin;
u32 frame_length_lines;
u32 line_length_pck;
u32 vt_pix_clk_freq_hz;
u32 sensor_output_width;
u32 sensor_output_height;
u32 crop_horizontal_start;
u32 crop_vertical_start;
u32 crop_horizontal_end;
u32 crop_vertical_end;
u8 binning_factor_x;
u8 binning_factor_y;
u32 exp_time;
u32 gain;
};
struct imx_camera_module_config {
const char *name;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
bool auto_exp_enabled;
bool auto_gain_enabled;
bool auto_wb_enabled;
struct imx_camera_module_reg *reg_table;
u32 reg_table_num_entries;
u32 reg_diff_table_num_entries;
u32 v_blanking_time_us;
u32 line_length_pck;
u32 frame_length_lines;
struct imx_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
struct imx_camera_module_exp_config {
u32 exp_time;
bool auto_exp;
u16 gain;
u16 gain_percent;
bool auto_gain;
enum v4l2_flash_led_mode flash_mode;
u32 vts_value;
};
struct imx_camera_module_wb_config {
u32 temperature;
u32 preset_id;
bool auto_wb;
};
struct imx_camera_module_af_config {
u32 abs_pos;
u32 rel_pos;
};
struct imx_camera_module_ext_ctrl {
/* public */
u32 id;
u32 value;
__u32 reserved2[1];
};
struct imx_camera_module_ext_ctrls {
/* public */
u32 count;
struct imx_camera_module_ext_ctrl *ctrls;
};
/*
* start_streaming: (mandatory) will be called when sensor should be
* put into streaming mode right after the base config has been
* written to the sensor. After a successful call of this function
* the sensor should start delivering frame data.
*
* stop_streaming: (mandatory) will be called when sensor should stop
* delivering data. After a successful call of this function the
* sensor should not deliver any more frame data.
*
* check_camera_id: (optional) will be called when the sensor is
* powered on. If provided should check the sensor ID/version
* required by the custom driver. Register access should be
* possible when this function is invoked.
*
* s_ctrl: (mandatory) will be called at the successful end of
* imx_camera_module_s_ctrl with the ctrl_id as argument.
*
* priv: (optional) for private data used by the custom driver.
*/
struct imx_camera_module_custom_config {
int (*start_streaming)(struct imx_camera_module *cam_mod);
int (*stop_streaming)(struct imx_camera_module *cam_mod);
int (*check_camera_id)(struct imx_camera_module *cam_mod);
int (*s_ctrl)(struct imx_camera_module *cam_mod, u32 ctrl_id);
int (*g_ctrl)(struct imx_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct imx_camera_module *cam_mod,
struct imx_camera_module_timings *timings);
int (*s_vts)(struct imx_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct imx_camera_module *cam_mod,
struct imx_camera_module_ext_ctrls *ctrls);
int (*set_flip)(struct imx_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len);
int (*init_common)(struct imx_camera_module *cam_mod);
struct imx_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
struct imx_camera_module_otp_work {
struct work_struct work;
struct workqueue_struct *wq;
void *cam_mod;
};
struct imx_camera_module {
/* public */
struct v4l2_subdev sd;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
struct imx_camera_module_exp_config exp_config;
struct imx_camera_module_wb_config wb_config;
struct imx_camera_module_af_config af_config;
struct imx_camera_module_custom_config custom;
enum imx_camera_module_state state;
enum imx_camera_module_state state_before_suspend;
struct imx_camera_module_config *active_config;
struct imx_camera_module_otp_work otp_work;
u32 ctrl_updt;
u32 vts_cur;
u32 vts_min;
bool auto_adjust_fps;
bool update_config;
bool frm_fmt_valid;
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
struct mutex lock;
};
#define imx_camera_module_pr_info(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_info(&cam_mod->sd, fmt, ## arg)
#define imx_camera_module_pr_debug(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_debug(&cam_mod->sd, fmt, ## arg)
#define imx_camera_module_pr_warn(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_warn(&cam_mod->sd, fmt, ## arg)
#define imx_camera_module_pr_err(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_err(&cam_mod->sd, fmt, ## arg)
int imx_camera_module_write_reglist(
struct imx_camera_module *cam_mod,
const struct imx_camera_module_reg reglist[],
int len);
int imx_camera_module_write_reg(
struct imx_camera_module *cam_mod,
u16 reg,
u8 val);
int imx_camera_module_read_reg(
struct imx_camera_module *cam_mod,
u16 data_length,
u16 reg,
u32 *val);
int imx_camera_module_read_reg_table(
struct imx_camera_module *cam_mod,
u16 reg,
u32 *val);
int imx_camera_module_s_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int imx_camera_module_g_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int imx_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int imx_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int imx_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);
int imx_camera_module_s_power(
struct v4l2_subdev *sd,
int on);
int imx_camera_module_g_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int imx_camera_module_s_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int imx_camera_module_s_ext_ctrls(
struct v4l2_subdev *sd,
struct v4l2_ext_controls *ctrls);
int imx_camera_module_enum_frameintervals(
struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie);
int imx_camera_module_init(
struct imx_camera_module *cam_mod,
struct imx_camera_module_custom_config *custom);
void imx_camera_module_release(
struct imx_camera_module *cam_mod);
long imx_camera_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg);
int imx_camera_module_get_flip_mirror(
struct imx_camera_module *cam_mod);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,955 +0,0 @@
/*
* drivers/media/i2c/soc_camera/xgold/ov2710.c
*
* ov2710 sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
* Note:
*
* v0.1.0:
* 1. Initialize version;
* 2. Stream on sensor in configuration,
* and stream off sensor after 1frame;
* 3. Stream delay time is define in power_up_delays_ms[2];
*/
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf-core.h>
#include <linux/slab.h>
#include <media/v4l2-controls_rockchip.h>
#include "ov_camera_module.h"
#define OV2710_DRIVER_NAME "ov2710"
#define OV2710_FETCH_LSB_GAIN(VAL) (VAL & 0x00FF) /* gain[7:0] */
#define OV2710_FETCH_MSB_GAIN(VAL) ((VAL >> 8) & 0x1) /* gain[10:8] */
#define OV2710_AEC_PK_LONG_GAIN_HIGH_REG 0x350a /* Bit 8 */
#define OV2710_AEC_PK_LONG_GAIN_LOW_REG 0x350b /* Bits 0 -7 */
#define OV2710_AEC_PK_LONG_EXPO_3RD_REG 0x3500 /* Exposure Bits 16-19 */
#define OV2710_AEC_PK_LONG_EXPO_2ND_REG 0x3501 /* Exposure Bits 8-15 */
#define OV2710_AEC_PK_LONG_EXPO_1ST_REG 0x3502 /* Exposure Bits 0-7 */
#define OV2710_AEC_GROUP_UPDATE_ADDRESS 0x3212
#define OV2710_AEC_GROUP_UPDATE_START_DATA 0x00
#define OV2710_AEC_GROUP_UPDATE_END_DATA 0x10
#define OV2710_AEC_GROUP_UPDATE_END_LAUNCH 0xA0
#define OV2710_FETCH_3RD_BYTE_EXP(VAL) (((VAL) >> 12) & 0xF) /* 4 Bits */
#define OV2710_FETCH_2ND_BYTE_EXP(VAL) (((VAL) >> 4) & 0xFF) /* 8 Bits */
#define OV2710_FETCH_1ST_BYTE_EXP(VAL) (((VAL) & 0x0F) << 4) /* 4 Bits */
#define OV2710_PIDH_ADDR 0x300A
#define OV2710_PIDL_ADDR 0x300B
/* High byte of product ID */
#define OV2710_PIDH_MAGIC 0x27
/* Low byte of product ID */
#define OV2710_PIDL_MAGIC 0x10
#define OV2710_EXT_CLK 24000000
#define OV2710_PLL_PREDIV0_REG 0x3088
#define OV2710_PLL_PREDIV_REG 0x3080
#define OV2710_PLL_MUL_HIGH_REG 0x3081
#define OV2710_PLL_MUL_LOW_REG 0x3082
#define OV2710_PLL_SPDIV_REG 0x3086
#define OV2710_PLL_DIVSYS_REG 0x3084
#define OV2710_TIMING_VTS_HIGH_REG 0x380e
#define OV2710_TIMING_VTS_LOW_REG 0x380f
#define OV2710_TIMING_HTS_HIGH_REG 0x380c
#define OV2710_TIMING_HTS_LOW_REG 0x380d
#define OV2710_FINE_INTG_TIME_MIN 0
#define OV2710_FINE_INTG_TIME_MAX_MARGIN 0
#define OV2710_COARSE_INTG_TIME_MIN 1
#define OV2710_COARSE_INTG_TIME_MAX_MARGIN 4
#define OV2710_TIMING_X_INC 0x3814
#define OV2710_TIMING_Y_INC 0x3815
#define OV2710_HORIZONTAL_START_HIGH_REG 0x3800
#define OV2710_HORIZONTAL_START_LOW_REG 0x3801
#define OV2710_VERTICAL_START_HIGH_REG 0x3802
#define OV2710_VERTICAL_START_LOW_REG 0x3803
#define OV2710_HORIZONTAL_END_HIGH_REG 0x3804
#define OV2710_HORIZONTAL_END_LOW_REG 0x3805
#define OV2710_VERTICAL_END_HIGH_REG 0x3806
#define OV2710_VERTICAL_END_LOW_REG 0x3807
#define OV2710_HORIZONTAL_OUTPUT_SIZE_HIGH_REG 0x3808
#define OV2710_HORIZONTAL_OUTPUT_SIZE_LOW_REG 0x3809
#define OV2710_VERTICAL_OUTPUT_SIZE_HIGH_REG 0x380a
#define OV2710_VERTICAL_OUTPUT_SIZE_LOW_REG 0x380b
#define OV2710_H_WIN_OFF_HIGH_REG 0x3810
#define OV2710_H_WIN_OFF_LOW_REG 0x3811
#define OV2710_V_WIN_OFF_HIGH_REG 0x3812
#define OV2710_V_WIN_OFF_LOW_REG 0x3813
#define OV2710_ANA_ARRAR01 0x3621
#define OV2710_TIMING_CONCTROL_VH 0x3803
#define OV2710_TIMING_CONCTROL18 0x3818
/* ======================================================================== */
/* Base sensor configs */
/* ======================================================================== */
/* MCLK:24MHz 1920x1080 30fps mipi 1lane 800Mbps/lane */
static struct ov_camera_module_reg ov2710_init_tab_1920_1080_30fps[] = {
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3008, 0x82},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3008, 0x42},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4201, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4202, 0x0f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3103, 0x93},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3017, 0x7f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3018, 0xfc},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3706, 0x61},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3712, 0x0c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3630, 0x6d},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3800, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3801, 0xb4},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3802, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3803, 0x0a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3818, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3804, 0x07},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3805, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3806, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3807, 0x38},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3808, 0x07},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3809, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380a, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380b, 0x38},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3810, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3811, 0x06},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3812, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3813, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3621, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3604, 0x60},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3603, 0xa7},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3631, 0x26},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3600, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3620, 0x37},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3623, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3702, 0x9e},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3703, 0x5c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3704, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x370d, 0x0f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3713, 0x9f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3714, 0x4c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3710, 0x9e},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3801, 0xc4},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3605, 0x05},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3606, 0x3f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x302d, 0x90},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x370b, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3716, 0x31},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3707, 0x52},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380d, 0x74},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5181, 0x20},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x518f, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4301, 0xff},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4303, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a00, 0x78},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x300f, 0x88},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3011, 0x28},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a1a, 0x06},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a18, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a19, 0x7a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a13, 0x54},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x382e, 0x0f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x381a, 0x1a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x401d, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5688, 0x03},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5684, 0x07},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5685, 0xa0},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5686, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5687, 0x43},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3011, 0x0a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x300f, 0x8a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3017, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3018, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x300e, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4801, 0x0f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x300f, 0xc3},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a0f, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a10, 0x38},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a1b, 0x48},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a1e, 0x30},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a11, 0x90},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3a1f, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380c, 0x09},/* HTS H */
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380d, 0x74},/* HTS L */
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380e, 0x04},/* VTS H */
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380f, 0x50},/* VTS L */
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3500, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3501, 0x28},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3502, 0x90},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3503, 0x07},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x350a, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x350b, 0x1f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5000, 0x5f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5001, 0x4e},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3406, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3400, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3401, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3402, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3403, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3404, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3405, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4800, 0x24},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4201, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4202, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3008, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_TIMEOUT, 0x0000, 40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3008, 0x42},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4201, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4202, 0x0f}
};
/* ======================================================================== */
static struct ov_camera_module_config ov2710_configs[] = {
{
.name = "1920x1080_30fps",
.frm_fmt = {
.width = 1920,
.height = 1080,
.code = MEDIA_BUS_FMT_SBGGR10_1X10
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 30
}
},
.auto_exp_enabled = false,
.auto_gain_enabled = false,
.auto_wb_enabled = false,
.reg_table = (void *)ov2710_init_tab_1920_1080_30fps,
.reg_table_num_entries =
sizeof(ov2710_init_tab_1920_1080_30fps) /
sizeof(ov2710_init_tab_1920_1080_30fps[0]),
.v_blanking_time_us = 3078,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
.ignore_measurement_check = 1,
PLTFRM_CAM_ITF_MIPI_CFG(0, 1, 800, 24000000)
}
};
/*--------------------------------------------------------------------------*/
static int ov2710_set_flip(
struct ov_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len)
{
int i, mode = 0;
u16 match_reg[3];
mode = ov_camera_module_get_flip_mirror(cam_mod);
if (mode == -1) {
ov_camera_module_pr_debug(
cam_mod,
"dts don't set flip, return!\n");
return 0;
}
if (mode == OV_FLIP_BIT_MASK) {
match_reg[0] = 0x04;
match_reg[1] = 0x09;
match_reg[2] = 0xa0;
} else if (mode == OV_MIRROR_BIT_MASK) {
match_reg[0] = 0x14;
match_reg[1] = 0x0a;
match_reg[2] = 0xc0;
} else if (mode == (OV_MIRROR_BIT_MASK |
OV_FLIP_BIT_MASK)) {
match_reg[0] = 0x14;
match_reg[1] = 0x09;
match_reg[2] = 0xe0;
} else {
match_reg[0] = 0x04;
match_reg[1] = 0x0a;
match_reg[2] = 0x80;
}
for (i = len; i > 0; i--) {
if (reglist[i].reg == OV2710_ANA_ARRAR01)
reglist[i].val = match_reg[0];
else if (reglist[i].reg == OV2710_TIMING_CONCTROL_VH)
reglist[i].val = match_reg[1];
else if (reglist[i].reg == OV2710_TIMING_CONCTROL18)
reglist[i].val = match_reg[2];
}
return 0;
}
/*--------------------------------------------------------------------------*/
static int OV2710_g_VTS(struct ov_camera_module *cam_mod, u32 *vts)
{
u32 msb, lsb;
int ret;
ret = ov_camera_module_read_reg_table(
cam_mod,
OV2710_TIMING_VTS_HIGH_REG,
&msb);
if (IS_ERR_VALUE(ret))
goto err;
ret = ov_camera_module_read_reg_table(
cam_mod,
OV2710_TIMING_VTS_LOW_REG,
&lsb);
if (IS_ERR_VALUE(ret))
goto err;
*vts = (msb << 8) | lsb;
return 0;
err:
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int OV2710_auto_adjust_fps(struct ov_camera_module *cam_mod,
u32 exp_time)
{
int ret;
u32 vts;
if ((exp_time + OV2710_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = exp_time + OV2710_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
if (vts > 0xfff)
vts = 0xfff;
else
vts = vts;/* VTS value is 0x380e[3:0]/380f[7:0] */
ret = ov_camera_module_write_reg(cam_mod,
OV2710_TIMING_VTS_LOW_REG,
vts & 0xFF);
ret |= ov_camera_module_write_reg(cam_mod,
OV2710_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0x0F);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
ov_camera_module_pr_info(cam_mod,
"updated vts = 0x%x,vts_min=0x%x\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int ov2710_set_vts(struct ov_camera_module *cam_mod,
u32 vts)
{
int ret = 0;
if (vts < cam_mod->vts_min)
return ret;
if (vts > 0xfff)
vts = 0xfff;
ret = ov_camera_module_write_reg(cam_mod,
OV2710_TIMING_VTS_LOW_REG,
vts & 0xFF);
ret |= ov_camera_module_write_reg(cam_mod,
OV2710_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0x0F);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
} else {
ov_camera_module_pr_info(cam_mod, "updated vts=%d,vts_min=%d\n", vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int ov2710_write_aec(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod,
"exp_time = %d lines, gain = %d, flash_mode = %d\n",
cam_mod->exp_config.exp_time,
cam_mod->exp_config.gain,
cam_mod->exp_config.flash_mode);
/*
* if the sensor is already streaming, write to shadow registers,
* if the sensor is in SW standby, write to active registers,
* if the sensor is off/registers are not writeable, do nothing
*/
if ((cam_mod->state == OV_CAMERA_MODULE_SW_STANDBY) ||
(cam_mod->state == OV_CAMERA_MODULE_STREAMING)) {
u32 a_gain = cam_mod->exp_config.gain;
u32 exp_time = cam_mod->exp_config.exp_time;
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
mutex_lock(&cam_mod->lock);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod,
OV2710_AEC_GROUP_UPDATE_ADDRESS,
OV2710_AEC_GROUP_UPDATE_START_DATA);
if (!IS_ERR_VALUE(ret) && cam_mod->auto_adjust_fps)
ret = OV2710_auto_adjust_fps(cam_mod,
cam_mod->exp_config.exp_time);
ret |= ov_camera_module_write_reg(cam_mod,
OV2710_AEC_PK_LONG_GAIN_HIGH_REG,
OV2710_FETCH_MSB_GAIN(a_gain));
ret |= ov_camera_module_write_reg(cam_mod,
OV2710_AEC_PK_LONG_GAIN_LOW_REG,
OV2710_FETCH_LSB_GAIN(a_gain));
ret = ov_camera_module_write_reg(cam_mod,
OV2710_AEC_PK_LONG_EXPO_3RD_REG,
OV2710_FETCH_3RD_BYTE_EXP(exp_time));
ret |= ov_camera_module_write_reg(cam_mod,
OV2710_AEC_PK_LONG_EXPO_2ND_REG,
OV2710_FETCH_2ND_BYTE_EXP(exp_time));
ret |= ov_camera_module_write_reg(cam_mod,
OV2710_AEC_PK_LONG_EXPO_1ST_REG,
OV2710_FETCH_1ST_BYTE_EXP(exp_time));
if (!cam_mod->auto_adjust_fps)
ret |= ov2710_set_vts(cam_mod, cam_mod->exp_config.vts_value);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING) {
ret = ov_camera_module_write_reg(cam_mod,
OV2710_AEC_GROUP_UPDATE_ADDRESS,
OV2710_AEC_GROUP_UPDATE_END_DATA);
ret = ov_camera_module_write_reg(cam_mod,
OV2710_AEC_GROUP_UPDATE_ADDRESS,
OV2710_AEC_GROUP_UPDATE_END_LAUNCH);
}
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int ov2710_g_ctrl(struct ov_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov2710_filltimings(struct ov_camera_module_custom_config *custom)
{
int i, j;
u32 win_h_off = 0, win_v_off = 0;
struct ov_camera_module_config *config;
struct ov_camera_module_timings *timings;
struct ov_camera_module_reg *reg_table;
int reg_table_num_entries;
for (i = 0; i < custom->num_configs; i++) {
config = &custom->configs[i];
reg_table = config->reg_table;
reg_table_num_entries = config->reg_table_num_entries;
timings = &config->timings;
memset(timings, 0x00, sizeof(*timings));
for (j = 0; j < reg_table_num_entries; j++) {
switch (reg_table[j].reg) {
case OV2710_TIMING_VTS_HIGH_REG:
timings->frame_length_lines =
((reg_table[j].val << 8) |
(timings->frame_length_lines & 0xff));
break;
case OV2710_TIMING_VTS_LOW_REG:
timings->frame_length_lines =
(reg_table[j].val |
(timings->frame_length_lines & 0xff00));
break;
case OV2710_TIMING_HTS_HIGH_REG:
timings->line_length_pck =
((reg_table[j].val << 8) |
timings->line_length_pck);
break;
case OV2710_TIMING_HTS_LOW_REG:
timings->line_length_pck =
(reg_table[j].val |
(timings->line_length_pck & 0xff00));
break;
case OV2710_TIMING_X_INC:
timings->binning_factor_x =
((reg_table[j].val >> 4) + 1) / 2;
if (timings->binning_factor_x == 0)
timings->binning_factor_x = 1;
break;
case OV2710_TIMING_Y_INC:
timings->binning_factor_y =
((reg_table[j].val >> 4) + 1) / 2;
if (timings->binning_factor_y == 0)
timings->binning_factor_y = 1;
break;
case OV2710_HORIZONTAL_START_HIGH_REG:
timings->crop_horizontal_start =
((reg_table[j].val << 8) |
(timings->crop_horizontal_start &
0xff));
break;
case OV2710_HORIZONTAL_START_LOW_REG:
timings->crop_horizontal_start =
(reg_table[j].val |
(timings->crop_horizontal_start &
0xff00));
break;
case OV2710_VERTICAL_START_HIGH_REG:
timings->crop_vertical_start =
((reg_table[j].val << 8) |
(timings->crop_vertical_start & 0xff));
break;
case OV2710_VERTICAL_START_LOW_REG:
timings->crop_vertical_start =
((reg_table[j].val) |
(timings->crop_vertical_start &
0xff00));
break;
case OV2710_HORIZONTAL_END_HIGH_REG:
timings->crop_horizontal_end =
((reg_table[j].val << 8) |
(timings->crop_horizontal_end & 0xff));
break;
case OV2710_HORIZONTAL_END_LOW_REG:
timings->crop_horizontal_end =
(reg_table[j].val |
(timings->crop_horizontal_end &
0xff00));
break;
case OV2710_VERTICAL_END_HIGH_REG:
timings->crop_vertical_end =
((reg_table[j].val << 8) |
(timings->crop_vertical_end & 0xff));
break;
case OV2710_VERTICAL_END_LOW_REG:
timings->crop_vertical_end =
(reg_table[j].val |
(timings->crop_vertical_end & 0xff00));
break;
case OV2710_H_WIN_OFF_HIGH_REG:
win_h_off = (reg_table[j].val & 0xf) << 8;
break;
case OV2710_H_WIN_OFF_LOW_REG:
win_h_off |= (reg_table[j].val & 0xff);
break;
case OV2710_V_WIN_OFF_HIGH_REG:
win_v_off = (reg_table[j].val & 0xf) << 8;
break;
case OV2710_V_WIN_OFF_LOW_REG:
win_v_off |= (reg_table[j].val & 0xff);
break;
case OV2710_HORIZONTAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_width =
((reg_table[j].val << 8) |
(timings->sensor_output_width & 0xff));
break;
case OV2710_HORIZONTAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_width =
(reg_table[j].val |
(timings->sensor_output_width &
0xff00));
break;
case OV2710_VERTICAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_height =
((reg_table[j].val << 8) |
(timings->sensor_output_height & 0xff));
break;
case OV2710_VERTICAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_height =
(reg_table[j].val |
(timings->sensor_output_height &
0xff00));
break;
}
}
timings->crop_horizontal_start += win_h_off;
timings->crop_horizontal_end -= win_h_off;
timings->crop_vertical_start += win_v_off;
timings->crop_vertical_end -= win_v_off;
timings->exp_time >>= 4;
timings->vt_pix_clk_freq_hz =
config->frm_intrvl.interval.denominator *
timings->frame_length_lines *
timings->line_length_pck;
timings->coarse_integration_time_min =
OV2710_COARSE_INTG_TIME_MIN;
timings->coarse_integration_time_max_margin =
OV2710_COARSE_INTG_TIME_MAX_MARGIN;
/* OV Sensor do not use fine integration time. */
timings->fine_integration_time_min =
OV2710_FINE_INTG_TIME_MIN;
timings->fine_integration_time_max_margin =
OV2710_FINE_INTG_TIME_MAX_MARGIN;
}
return 0;
}
/*--------------------------------------------------------------------------*/
static int ov2710_g_timings(struct ov_camera_module *cam_mod,
struct ov_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid)
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
else
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov2710_s_ctrl(struct ov_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
ret = ov2710_write_aec(cam_mod);
break;
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
case V4L2_CID_FOCUS_ABSOLUTE:
/* todo*/
break;
/*
* case RK_V4L2_CID_FPS_CTRL:
* if (cam_mod->auto_adjust_fps)
* ret = OV2710_auto_adjust_fps(
* cam_mod,
* cam_mod->exp_config.exp_time);
* break;
*/
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov2710_s_ext_ctrls(struct ov_camera_module *cam_mod,
struct ov_camera_module_ext_ctrls *ctrls)
{
int ret = 0;
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov2710_write_aec(cam_mod);
else
ret = -EINVAL;
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov2710_start_streaming(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod,
"active config=%s\n", cam_mod->active_config->name);
ret = OV2710_g_VTS(cam_mod, &cam_mod->vts_min);
if (IS_ERR_VALUE(ret))
goto err;
ov_camera_module_pr_debug(cam_mod, "=====streaming on ===\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x3008, 0x02);
ret |= ov_camera_module_write_reg(cam_mod, 0x4201, 0x00);
ret |= ov_camera_module_write_reg(cam_mod, 0x4202, 0x00);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n",
ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov2710_stop_streaming(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x3008, 0x42);
ret |= ov_camera_module_write_reg(cam_mod, 0x4201, 0x00);
ret |= ov_camera_module_write_reg(cam_mod, 0x4202, 0x0f);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov2710_check_camera_id(struct ov_camera_module *cam_mod)
{
u32 pidh, pidl;
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
ret |= ov_camera_module_read_reg(cam_mod, 1, OV2710_PIDH_ADDR, &pidh);
ret |= ov_camera_module_read_reg(cam_mod, 1, OV2710_PIDL_ADDR, &pidl);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"register read failed, camera module powered off?\n");
goto err;
}
if ((pidh == OV2710_PIDH_MAGIC) && (pidl == OV2710_PIDL_MAGIC))
ov_camera_module_pr_debug(cam_mod,
"successfully detected camera ID 0x%02x%02x\n",
pidh, pidl);
else {
ov_camera_module_pr_err(cam_mod,
"wrong camera ID, expected 0x%02x%02x, detected 0x%02x%02x\n",
OV2710_PIDH_MAGIC, OV2710_PIDL_MAGIC, pidh, pidl);
ret = -EINVAL;
goto err;
}
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/* ======================================================================== */
int ov_camera_2710_module_s_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl)
{
return 0;
}
/* ======================================================================== */
int ov_camera_2710_module_s_ext_ctrls(
struct v4l2_subdev *sd,
struct v4l2_ext_controls *ctrls)
{
return 0;
}
long ov_camera_2710_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg)
{
return 0;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
static struct v4l2_subdev_core_ops ov2710_camera_module_core_ops = {
.g_ctrl = ov_camera_module_g_ctrl,
.s_ctrl = ov_camera_module_s_ctrl,
.s_ext_ctrls = ov_camera_module_s_ext_ctrls,
.s_power = ov_camera_module_s_power,
.ioctl = ov_camera_module_ioctl
};
static struct v4l2_subdev_video_ops ov2710_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
static struct v4l2_subdev_pad_ops ov2710_camera_module_pad_ops = {
.enum_frame_interval = ov_camera_module_enum_frameintervals,
.get_fmt = ov_camera_module_g_fmt,
.set_fmt = ov_camera_module_s_fmt,
};
static struct v4l2_subdev_ops ov2710_camera_module_ops = {
.core = &ov2710_camera_module_core_ops,
.video = &ov2710_camera_module_video_ops,
.pad = &ov2710_camera_module_pad_ops
};
static struct ov_camera_module ov2710;
static struct ov_camera_module_custom_config ov2710_custom_config = {
.start_streaming = ov2710_start_streaming,
.stop_streaming = ov2710_stop_streaming,
.s_ctrl = ov2710_s_ctrl,
.g_ctrl = ov2710_g_ctrl,
.s_ext_ctrls = ov2710_s_ext_ctrls,
.g_timings = ov2710_g_timings,
.set_flip = ov2710_set_flip,
.check_camera_id = ov2710_check_camera_id,
.s_vts = OV2710_auto_adjust_fps,
.configs = ov2710_configs,
.num_configs = ARRAY_SIZE(ov2710_configs),
.power_up_delays_ms = {5, 30, 30},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 2}
};
static int ov2710_probe(
struct i2c_client *client,
const struct i2c_device_id *id)
{
dev_info(&client->dev, "probing...\n");
ov2710_filltimings(&ov2710_custom_config);
v4l2_i2c_subdev_init(&ov2710.sd, client,
&ov2710_camera_module_ops);
ov2710.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov2710.custom = ov2710_custom_config;
mutex_init(&ov2710.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
/* ======================================================================== */
static int ov2710_remove(
struct i2c_client *client)
{
struct ov_camera_module *cam_mod = i2c_get_clientdata(client);
dev_info(&client->dev, "removing device...\n");
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");
return 0;
}
static const struct i2c_device_id ov2710_id[] = {
{ OV2710_DRIVER_NAME, 0 },
{ }
};
static const struct of_device_id ov2710_of_match[] = {
{.compatible = "omnivision,ov2710-v4l2-i2c-subdev"},
{},
};
MODULE_DEVICE_TABLE(i2c, ov2710_id);
static struct i2c_driver ov2710_i2c_driver = {
.driver = {
.name = OV2710_DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = ov2710_of_match
},
.probe = ov2710_probe,
.remove = ov2710_remove,
.id_table = ov2710_id,
};
module_i2c_driver(ov2710_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for ov2710");
MODULE_AUTHOR("Eike Grimpe");
MODULE_LICENSE("GPL");

View File

@@ -1,994 +0,0 @@
/*
* ov4689 sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf-core.h>
#include <linux/slab.h>
#include "ov_camera_module.h"
#define ov4689_DRIVER_NAME "ov4689"
#define ov4689_AEC_PK_LONG_GAIN_HIGH_REG 0x3508 /* Bit 6-13 */
#define ov4689_AEC_PK_LONG_GAIN_LOW_REG 0x3509 /* Bits 0 -5 */
#define ov4689_FETCH_LSB_GAIN(VAL) ((VAL) & 0x00ff)
#define ov4689_FETCH_MSB_GAIN(VAL) (((VAL) >> 8) & 0xff)
#define ov4689_AEC_PK_LONG_EXPO_3RD_REG 0x3500 /* Exposure Bits 16-19 */
#define ov4689_AEC_PK_LONG_EXPO_2ND_REG 0x3501 /* Exposure Bits 8-15 */
#define ov4689_AEC_PK_LONG_EXPO_1ST_REG 0x3502 /* Exposure Bits 0-7 */
#define ov4689_FETCH_3RD_BYTE_EXP(VAL) (((VAL) >> 12) & 0xF) /* 4 Bits */
#define ov4689_FETCH_2ND_BYTE_EXP(VAL) (((VAL) >> 4) & 0xFF) /* 8 Bits */
#define ov4689_FETCH_1ST_BYTE_EXP(VAL) (((VAL) & 0x0F) << 4) /* 4 Bits */
#define ov4689_AEC_GROUP_UPDATE_ADDRESS 0x3208
#define ov4689_AEC_GROUP_UPDATE_START_DATA 0x00
#define ov4689_AEC_GROUP_UPDATE_END_DATA 0x10
#define ov4689_AEC_GROUP_UPDATE_END_LAUNCH 0xA0
#define ov4689_PIDH_ADDR 0x300A
#define ov4689_PIDL_ADDR 0x300B
#define ov4689_PIDH_MAGIC 0x46
#define ov4689_PIDL_MAGIC 0x88
#define ov4689_TIMING_VTS_HIGH_REG 0x380e
#define ov4689_TIMING_VTS_LOW_REG 0x380f
#define ov4689_TIMING_HTS_HIGH_REG 0x380c
#define ov4689_TIMING_HTS_LOW_REG 0x380d
#define ov4689_INTEGRATION_TIME_MARGIN 8
#define ov4689_FINE_INTG_TIME_MIN 0
#define ov4689_FINE_INTG_TIME_MAX_MARGIN 0
#define ov4689_COARSE_INTG_TIME_MIN 16
#define ov4689_COARSE_INTG_TIME_MAX_MARGIN 4
#define ov4689_TIMING_X_INC 0x3814
#define ov4689_TIMING_Y_INC 0x3815
#define ov4689_HORIZONTAL_START_HIGH_REG 0x3800
#define ov4689_HORIZONTAL_START_LOW_REG 0x3801
#define ov4689_VERTICAL_START_HIGH_REG 0x3802
#define ov4689_VERTICAL_START_LOW_REG 0x3803
#define ov4689_HORIZONTAL_END_HIGH_REG 0x3804
#define ov4689_HORIZONTAL_END_LOW_REG 0x3805
#define ov4689_VERTICAL_END_HIGH_REG 0x3806
#define ov4689_VERTICAL_END_LOW_REG 0x3807
#define ov4689_HORIZONTAL_OUTPUT_SIZE_HIGH_REG 0x3808
#define ov4689_HORIZONTAL_OUTPUT_SIZE_LOW_REG 0x3809
#define ov4689_VERTICAL_OUTPUT_SIZE_HIGH_REG 0x380a
#define ov4689_VERTICAL_OUTPUT_SIZE_LOW_REG 0x380b
#define ov4689_FLIP_REG 0x3820
#define ov4689_MIRROR_REG 0x3821
#define ov4689_EXT_CLK 24000000
#define ov4689_FULL_SIZE_RESOLUTION_WIDTH 2688
#define ov4689_BINING_SIZE_RESOLUTION_WIDTH 1280
static struct ov_camera_module ov4689;
static struct ov_camera_module_custom_config ov4689_custom_config;
/* ======================================================================== */
/* Base sensor configs */
/* ======================================================================== */
/* MCLK:24MHz 2688x1520 30fps mipi 4lane 1008Mbps/lane */
static struct ov_camera_module_reg ov4689_init_tab_2688_1520_30fps[] = {
/* global setting */
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0103, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3638, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0300, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0302, 0x2a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0303, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0304, 0x03},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x030b, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x030d, 0x1e},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x030e, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x030f, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0312, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x031e, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3000, 0x20},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3002, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3018, 0x32},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3020, 0x93},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3021, 0x03},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3022, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3031, 0x0a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x303f, 0x0c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3305, 0xf1},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3307, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3309, 0x29},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3500, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3501, 0x60},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3502, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3503, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3504, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3505, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3506, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3507, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3508, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3509, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x350a, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x350b, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x350c, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x350d, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x350e, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x350f, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3510, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3511, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3512, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3513, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3514, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3515, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3516, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3517, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3518, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3519, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x351a, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x351b, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x351c, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x351d, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x351e, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x351f, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3520, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3521, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3522, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3524, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3526, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3528, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x352a, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3602, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3603, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3604, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3605, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3606, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3607, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3609, 0x12},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x360a, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x360c, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x360f, 0xe5},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3608, 0x8f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3611, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3613, 0xf7},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3616, 0x58},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3619, 0x99},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x361b, 0x60},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x361c, 0x7a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x361e, 0x79},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x361f, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3632, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3633, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3634, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3635, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3636, 0x15},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3646, 0x86},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x364a, 0x0b},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3700, 0x17},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3701, 0x22},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3703, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x370a, 0x37},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3705, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3706, 0x63},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3709, 0x3c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x370b, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x370c, 0x30},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3710, 0x24},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3711, 0x0c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3716, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3720, 0x28},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3729, 0x7b},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x372a, 0x84},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x372b, 0xbd},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x372c, 0xbc},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x372e, 0x52},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x373c, 0x0e},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x373e, 0x33},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3743, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3744, 0x88},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3745, 0xc0},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x374a, 0x43},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x374c, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x374e, 0x23},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3751, 0x7b},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3752, 0x84},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3753, 0xbd},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3754, 0xbc},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3756, 0x52},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x375c, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3760, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3761, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3762, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3763, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3764, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3767, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3768, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3769, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x376a, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x376b, 0x20},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x376c, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x376d, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x376e, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3773, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3774, 0x51},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3776, 0xbd},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3777, 0xbd},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3781, 0x18},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3783, 0x25},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3798, 0x1b},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3800, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3801, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3802, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3803, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3804, 0x0a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3805, 0x97},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3806, 0x05},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3807, 0xfb},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3808, 0x0a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3809, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380a, 0x05},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380b, 0xf0},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380c, 0x0a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380d, 0x18},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380e, 0x06},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380f, 0x12},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3810, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3811, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3812, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3813, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3814, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3815, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3819, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3820, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3821, 0x06},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3829, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x382a, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x382b, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x382d, 0x7f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3830, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3836, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3837, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3841, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3846, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3847, 0x07},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3d85, 0x36},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3d8c, 0x71},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3d8d, 0xcb},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3f0a, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4000, 0xf1},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4001, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4002, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4003, 0x14},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x400e, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4011, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x401a, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x401b, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x401c, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x401d, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x401f, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4020, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4021, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4022, 0x07},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4023, 0xcf},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4024, 0x09},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4025, 0x60},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4026, 0x09},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4027, 0x6f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4028, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4029, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x402a, 0x06},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x402b, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x402c, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x402d, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x402e, 0x0e},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x402f, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4302, 0xff},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4303, 0xff},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4304, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4305, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4306, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4308, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4500, 0x6c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4501, 0xc4},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4502, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4503, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4601, 0xa7},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4800, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4813, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x481f, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4829, 0x78},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4837, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4b00, 0x2a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4b0d, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4d00, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4d01, 0x42},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4d02, 0xd1},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4d03, 0x93},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4d04, 0xf5},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4d05, 0xc1},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5000, 0xf3},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5001, 0x11},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5004, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x500a, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x500b, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5032, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5040, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5050, 0x0c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5500, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5501, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5502, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5503, 0x0f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8000, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8001, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8002, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8003, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8004, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8005, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8006, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8007, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x8008, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3638, 0x00},
/* {OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0100, 0x01} */
};
static struct ov_camera_module_config ov4689_configs[] = {
{
.name = "2688x1520_30fps",
.frm_fmt = {
.width = 2688,
.height = 1520,
.code = MEDIA_BUS_FMT_SBGGR10_1X10
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 30
}
},
.auto_exp_enabled = false,
.auto_gain_enabled = false,
.auto_wb_enabled = false,
.reg_table = (void *)ov4689_init_tab_2688_1520_30fps,
.reg_table_num_entries =
sizeof(ov4689_init_tab_2688_1520_30fps) /
sizeof(ov4689_init_tab_2688_1520_30fps[0]),
.v_blanking_time_us = 5000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 999, ov4689_EXT_CLK)
}
};
static int ov4689_g_VTS(struct ov_camera_module *cam_mod, u32 *vts)
{
u32 msb, lsb;
int ret;
ret = ov_camera_module_read_reg_table(
cam_mod,
ov4689_TIMING_VTS_HIGH_REG,
&msb);
if (IS_ERR_VALUE(ret))
goto err;
ret = ov_camera_module_read_reg_table(
cam_mod,
ov4689_TIMING_VTS_LOW_REG,
&lsb);
if (IS_ERR_VALUE(ret))
goto err;
*vts = (msb << 8) | lsb;
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
static int ov4689_auto_adjust_fps(struct ov_camera_module *cam_mod,
u32 exp_time)
{
int ret;
u32 vts;
if ((exp_time + ov4689_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = exp_time + ov4689_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
ret = ov_camera_module_write_reg(cam_mod,
ov4689_TIMING_VTS_LOW_REG, vts & 0xFF);
ret |= ov_camera_module_write_reg(cam_mod,
ov4689_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
ov_camera_module_pr_info(cam_mod,
"updated vts = %d,vts_min=%d\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int ov4689_set_vts(struct ov_camera_module *cam_mod,
u32 vts)
{
int ret = 0;
if (vts < cam_mod->vts_min)
return ret;
if (vts > 0xfff)
vts = 0xfff;
ret = ov_camera_module_write_reg(cam_mod,
ov4689_TIMING_VTS_LOW_REG, vts & 0xFF);
ret |= ov_camera_module_write_reg(cam_mod,
ov4689_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
} else {
ov_camera_module_pr_info(cam_mod, "updated vts=%d,vts_min=%d\n", vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int ov4689_write_aec(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod,
"exp_time = %d, gain = %d, flash_mode = %d\n",
cam_mod->exp_config.exp_time,
cam_mod->exp_config.gain,
cam_mod->exp_config.flash_mode);
/*
* if the sensor is already streaming, write to shadow registers,
* if the sensor is in SW standby, write to active registers,
* if the sensor is off/registers are not writeable, do nothing
*/
if ((cam_mod->state == OV_CAMERA_MODULE_SW_STANDBY) ||
(cam_mod->state == OV_CAMERA_MODULE_STREAMING)) {
u32 a_gain = cam_mod->exp_config.gain;
u32 exp_time = cam_mod->exp_config.exp_time;
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
mutex_lock(&cam_mod->lock);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod,
ov4689_AEC_GROUP_UPDATE_ADDRESS,
ov4689_AEC_GROUP_UPDATE_START_DATA);
if (!IS_ERR_VALUE(ret) && cam_mod->auto_adjust_fps)
ret = ov4689_auto_adjust_fps(cam_mod,
cam_mod->exp_config.exp_time);
ret |= ov_camera_module_write_reg(cam_mod,
ov4689_AEC_PK_LONG_GAIN_HIGH_REG,
ov4689_FETCH_MSB_GAIN(a_gain));
ret |= ov_camera_module_write_reg(cam_mod,
ov4689_AEC_PK_LONG_GAIN_LOW_REG,
ov4689_FETCH_LSB_GAIN(a_gain));
ret = ov_camera_module_write_reg(cam_mod,
ov4689_AEC_PK_LONG_EXPO_3RD_REG,
ov4689_FETCH_3RD_BYTE_EXP(exp_time));
ret |= ov_camera_module_write_reg(cam_mod,
ov4689_AEC_PK_LONG_EXPO_2ND_REG,
ov4689_FETCH_2ND_BYTE_EXP(exp_time));
ret |= ov_camera_module_write_reg(cam_mod,
ov4689_AEC_PK_LONG_EXPO_1ST_REG,
ov4689_FETCH_1ST_BYTE_EXP(exp_time));
if (!cam_mod->auto_adjust_fps)
ret |= ov4689_set_vts(cam_mod, cam_mod->exp_config.vts_value);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING) {
ret = ov_camera_module_write_reg(cam_mod,
ov4689_AEC_GROUP_UPDATE_ADDRESS,
ov4689_AEC_GROUP_UPDATE_END_DATA);
ret = ov_camera_module_write_reg(cam_mod,
ov4689_AEC_GROUP_UPDATE_ADDRESS,
ov4689_AEC_GROUP_UPDATE_END_LAUNCH);
}
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov4689_g_ctrl(struct ov_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int ov4689_filltimings(struct ov_camera_module_custom_config *custom)
{
int i, j;
struct ov_camera_module_config *config;
struct ov_camera_module_timings *timings;
struct ov_camera_module_reg *reg_table;
int reg_table_num_entries;
for (i = 0; i < custom->num_configs; i++) {
config = &custom->configs[i];
reg_table = config->reg_table;
reg_table_num_entries = config->reg_table_num_entries;
timings = &config->timings;
for (j = 0; j < reg_table_num_entries; j++) {
switch (reg_table[j].reg) {
case ov4689_TIMING_VTS_HIGH_REG:
timings->frame_length_lines =
reg_table[j].val << 8;
break;
case ov4689_TIMING_VTS_LOW_REG:
timings->frame_length_lines |= reg_table[j].val;
break;
case ov4689_TIMING_HTS_HIGH_REG:
timings->line_length_pck =
(reg_table[j].val << 8);
break;
case ov4689_TIMING_HTS_LOW_REG:
timings->line_length_pck |= reg_table[j].val;
break;
case ov4689_TIMING_X_INC:
timings->binning_factor_x =
((reg_table[j].val >> 4) + 1) / 2;
if (timings->binning_factor_x == 0)
timings->binning_factor_x = 1;
break;
case ov4689_TIMING_Y_INC:
timings->binning_factor_y =
((reg_table[j].val >> 4) + 1) / 2;
if (timings->binning_factor_y == 0)
timings->binning_factor_y = 1;
break;
case ov4689_HORIZONTAL_START_HIGH_REG:
timings->crop_horizontal_start =
reg_table[j].val << 8;
break;
case ov4689_HORIZONTAL_START_LOW_REG:
timings->crop_horizontal_start |=
reg_table[j].val;
break;
case ov4689_VERTICAL_START_HIGH_REG:
timings->crop_vertical_start =
reg_table[j].val << 8;
break;
case ov4689_VERTICAL_START_LOW_REG:
timings->crop_vertical_start |=
reg_table[j].val;
break;
case ov4689_HORIZONTAL_END_HIGH_REG:
timings->crop_horizontal_end =
reg_table[j].val << 8;
break;
case ov4689_HORIZONTAL_END_LOW_REG:
timings->crop_horizontal_end |=
reg_table[j].val;
break;
case ov4689_VERTICAL_END_HIGH_REG:
timings->crop_vertical_end =
reg_table[j].val << 8;
break;
case ov4689_VERTICAL_END_LOW_REG:
timings->crop_vertical_end |= reg_table[j].val;
break;
case ov4689_HORIZONTAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_width =
reg_table[j].val << 8;
break;
case ov4689_HORIZONTAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_width |=
reg_table[j].val;
break;
case ov4689_VERTICAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_height =
reg_table[j].val << 8;
break;
case ov4689_VERTICAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_height |=
reg_table[j].val;
break;
}
}
timings->vt_pix_clk_freq_hz =
config->frm_intrvl.interval.denominator *
timings->frame_length_lines *
timings->line_length_pck;
timings->coarse_integration_time_min =
ov4689_COARSE_INTG_TIME_MIN;
timings->coarse_integration_time_max_margin =
ov4689_COARSE_INTG_TIME_MAX_MARGIN;
/* OV Sensor do not use fine integration time. */
timings->fine_integration_time_min = ov4689_FINE_INTG_TIME_MIN;
timings->fine_integration_time_max_margin =
ov4689_FINE_INTG_TIME_MAX_MARGIN;
}
return 0;
}
static int ov4689_g_timings(struct ov_camera_module *cam_mod,
struct ov_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid)
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
else
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov4689_set_flip(
struct ov_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len)
{
int i, mode = 0;
u16 match_reg[2];
mode = ov_camera_module_get_flip_mirror(cam_mod);
if (mode == -1) {
ov_camera_module_pr_info(cam_mod,
"dts don't set flip, return!\n");
return 0;
}
if (!IS_ERR_OR_NULL(cam_mod->active_config)) {
switch (cam_mod->active_config->frm_fmt.width) {
case ov4689_FULL_SIZE_RESOLUTION_WIDTH:
if (mode == OV_FLIP_BIT_MASK) {
match_reg[0] = 0x06;
match_reg[1] = 0x00;
} else if (mode == OV_MIRROR_BIT_MASK) {
match_reg[0] = 0x00;
match_reg[1] = 0x06;
} else if (mode == (OV_MIRROR_BIT_MASK |
OV_FLIP_BIT_MASK)) {
match_reg[0] = 0x06;
match_reg[1] = 0x06;
} else {
match_reg[0] = 0x00;
match_reg[1] = 0x00;
}
break;
case ov4689_BINING_SIZE_RESOLUTION_WIDTH:
if (mode == OV_FLIP_BIT_MASK) {
match_reg[0] = 0x16;
match_reg[1] = 0x01;
} else if (mode == OV_MIRROR_BIT_MASK) {
match_reg[0] = 0x16;
match_reg[1] = 0x07;
} else if (mode == (OV_MIRROR_BIT_MASK |
OV_FLIP_BIT_MASK)) {
match_reg[0] = 0x16;
match_reg[1] = 0x07;
} else {
match_reg[0] = 0x10;
match_reg[1] = 0x01;
}
break;
default:
return 0;
}
for (i = len; i > 0; i--) {
if (reglist[i].reg == ov4689_FLIP_REG)
reglist[i].val = match_reg[0];
else if (reglist[i].reg == ov4689_MIRROR_REG)
reglist[i].val = match_reg[1];
}
}
return 0;
}
/*--------------------------------------------------------------------------*/
static int ov4689_s_ctrl(struct ov_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
ret = ov4689_write_aec(cam_mod);
break;
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d) 0x%x\n", ret, ctrl_id);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov4689_s_ext_ctrls(struct ov_camera_module *cam_mod,
struct ov_camera_module_ext_ctrls *ctrls)
{
int ret = 0;
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov4689_write_aec(cam_mod);
else
ret = -EINVAL;
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov4689_start_streaming(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod,
"active config=%s\n", cam_mod->active_config->name);
ret = ov4689_g_VTS(cam_mod, &cam_mod->vts_min);
if (IS_ERR_VALUE(ret))
goto err;
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 1);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n",
ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov4689_stop_streaming(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 0);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov4689_check_camera_id(struct ov_camera_module *cam_mod)
{
u32 pidh, pidl;
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
ret |= ov_camera_module_read_reg(cam_mod, 1, ov4689_PIDH_ADDR, &pidh);
ret |= ov_camera_module_read_reg(cam_mod, 1, ov4689_PIDL_ADDR, &pidl);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"register read failed, camera module powered off?\n");
goto err;
}
if ((pidh == ov4689_PIDH_MAGIC) && (pidl == ov4689_PIDL_MAGIC))
ov_camera_module_pr_debug(cam_mod,
"successfully detected camera ID 0x%02x%02x\n",
pidh, pidl);
else {
ov_camera_module_pr_err(cam_mod,
"wrong camera ID, expected 0x%02x%02x, detected 0x%02x%02x\n",
ov4689_PIDH_MAGIC, ov4689_PIDL_MAGIC, pidh, pidl);
ret = -EINVAL;
goto err;
}
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
static struct v4l2_subdev_core_ops ov4689_camera_module_core_ops = {
.g_ctrl = ov_camera_module_g_ctrl,
.s_ctrl = ov_camera_module_s_ctrl,
.s_ext_ctrls = ov_camera_module_s_ext_ctrls,
.s_power = ov_camera_module_s_power,
.ioctl = ov_camera_module_ioctl
};
static struct v4l2_subdev_video_ops ov4689_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
static struct v4l2_subdev_pad_ops ov4689_camera_module_pad_ops = {
.enum_frame_interval = ov_camera_module_enum_frameintervals,
.get_fmt = ov_camera_module_g_fmt,
.set_fmt = ov_camera_module_s_fmt,
};
static struct v4l2_subdev_ops ov4689_camera_module_ops = {
.core = &ov4689_camera_module_core_ops,
.video = &ov4689_camera_module_video_ops,
.pad = &ov4689_camera_module_pad_ops
};
static struct ov_camera_module_custom_config ov4689_custom_config = {
.start_streaming = ov4689_start_streaming,
.stop_streaming = ov4689_stop_streaming,
.s_ctrl = ov4689_s_ctrl,
.s_ext_ctrls = ov4689_s_ext_ctrls,
.g_ctrl = ov4689_g_ctrl,
.g_timings = ov4689_g_timings,
.check_camera_id = ov4689_check_camera_id,
.set_flip = ov4689_set_flip,
.s_vts = ov4689_auto_adjust_fps,
.configs = ov4689_configs,
.num_configs = ARRAY_SIZE(ov4689_configs),
.power_up_delays_ms = {5, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int ov4689_probe(
struct i2c_client *client,
const struct i2c_device_id *id)
{
dev_info(&client->dev, "probing...\n");
ov4689_filltimings(&ov4689_custom_config);
v4l2_i2c_subdev_init(&ov4689.sd, client, &ov4689_camera_module_ops);
ov4689.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov4689.custom = ov4689_custom_config;
mutex_init(&ov4689.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
static int ov4689_remove(struct i2c_client *client)
{
struct ov_camera_module *cam_mod = i2c_get_clientdata(client);
dev_info(&client->dev, "removing device...\n");
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");
return 0;
}
static const struct i2c_device_id ov4689_id[] = {
{ ov4689_DRIVER_NAME, 0 },
{ }
};
static const struct of_device_id ov4689_of_match[] = {
{.compatible = "omnivision,ov4689-v4l2-i2c-subdev"},
{},
};
MODULE_DEVICE_TABLE(i2c, ov4689_id);
static struct i2c_driver ov4689_i2c_driver = {
.driver = {
.name = ov4689_DRIVER_NAME,
.of_match_table = ov4689_of_match
},
.probe = ov4689_probe,
.remove = ov4689_remove,
.id_table = ov4689_id,
};
module_i2c_driver(ov4689_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for ov4689");
MODULE_AUTHOR("George");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -1,574 +0,0 @@
/*
* ov7675 sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf-core.h>
#include <linux/slab.h>
#include "ov_camera_module.h"
#define OV7675_CAMERA_MODULE_DATA (PLTFRM_CAMERA_MODULE_WR_SINGLE | \
PLTFRM_CAMERA_MODULE_RD_CONTINUE | PLTFRM_CAMERA_MODULE_REG1_TYPE_DATA1)
#define ov7675_DRIVER_NAME "ov7675"
#define ov7675_PIDH_ADDR 0x0a
#define ov7675_PIDL_ADDR 0x0b
#define ov7675_EXT_CLK 24000000
/* High byte of product ID */
#define ov7675_PIDH_MAGIC 0x76
/* Low byte of product ID */
#define ov7675_PIDL_MAGIC 0x73
static struct ov_camera_module ov7675;
static struct ov_camera_module_custom_config ov7675_custom_config;
/* ======================================================================== */
/* Base sensor configs */
/* ======================================================================== */
static struct ov_camera_module_reg ov7675_init_tab_640_480_30fps[] = {
{OV7675_CAMERA_MODULE_DATA, 0x12, 0x80},
{OV7675_CAMERA_MODULE_DATA, 0x09, 0x10},
{OV7675_CAMERA_MODULE_DATA, 0xc1, 0x7f},
{OV7675_CAMERA_MODULE_DATA, 0x11, 0x80},
{OV7675_CAMERA_MODULE_DATA, 0x3a, 0x0c},
{OV7675_CAMERA_MODULE_DATA, 0x3d, 0xc0},
{OV7675_CAMERA_MODULE_DATA, 0x12, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x15, 0x40},
{OV7675_CAMERA_MODULE_DATA, 0x17, 0x13},
{OV7675_CAMERA_MODULE_DATA, 0x18, 0x01},
{OV7675_CAMERA_MODULE_DATA, 0x32, 0xbf},
{OV7675_CAMERA_MODULE_DATA, 0x19, 0x02},
{OV7675_CAMERA_MODULE_DATA, 0x1a, 0x7a},
{OV7675_CAMERA_MODULE_DATA, 0x03, 0x0a},
{OV7675_CAMERA_MODULE_DATA, 0x0c, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x3e, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x70, 0x3a},
{OV7675_CAMERA_MODULE_DATA, 0x71, 0x35},
{OV7675_CAMERA_MODULE_DATA, 0x72, 0x11},
{OV7675_CAMERA_MODULE_DATA, 0x73, 0xf0},
{OV7675_CAMERA_MODULE_DATA, 0xa2, 0x02},
{OV7675_CAMERA_MODULE_DATA, 0x7a, 0x20},
{OV7675_CAMERA_MODULE_DATA, 0x7b, 0x03},
{OV7675_CAMERA_MODULE_DATA, 0x7c, 0x0a},
{OV7675_CAMERA_MODULE_DATA, 0x7d, 0x1a},
{OV7675_CAMERA_MODULE_DATA, 0x7e, 0x3f},
{OV7675_CAMERA_MODULE_DATA, 0x7f, 0x4e},
{OV7675_CAMERA_MODULE_DATA, 0x80, 0x5b},
{OV7675_CAMERA_MODULE_DATA, 0x81, 0x68},
{OV7675_CAMERA_MODULE_DATA, 0x82, 0x75},
{OV7675_CAMERA_MODULE_DATA, 0x83, 0x7f},
{OV7675_CAMERA_MODULE_DATA, 0x84, 0x89},
{OV7675_CAMERA_MODULE_DATA, 0x85, 0x9a},
{OV7675_CAMERA_MODULE_DATA, 0x86, 0xa6},
{OV7675_CAMERA_MODULE_DATA, 0x87, 0xbd},
{OV7675_CAMERA_MODULE_DATA, 0x88, 0xd3},
{OV7675_CAMERA_MODULE_DATA, 0x89, 0xe8},
{OV7675_CAMERA_MODULE_DATA, 0x13, 0xe0},
{OV7675_CAMERA_MODULE_DATA, 0x00, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x10, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x0d, 0x40},
{OV7675_CAMERA_MODULE_DATA, 0x14, 0x28},
{OV7675_CAMERA_MODULE_DATA, 0xa5, 0x02},
{OV7675_CAMERA_MODULE_DATA, 0xab, 0x02},
{OV7675_CAMERA_MODULE_DATA, 0x24, 0x68},
{OV7675_CAMERA_MODULE_DATA, 0x25, 0x58},
{OV7675_CAMERA_MODULE_DATA, 0x26, 0xc2},
{OV7675_CAMERA_MODULE_DATA, 0x9f, 0x78},
{OV7675_CAMERA_MODULE_DATA, 0xa0, 0x68},
{OV7675_CAMERA_MODULE_DATA, 0xa1, 0x03},
{OV7675_CAMERA_MODULE_DATA, 0xa6, 0xd8},
{OV7675_CAMERA_MODULE_DATA, 0xa7, 0xd8},
{OV7675_CAMERA_MODULE_DATA, 0xa8, 0xf0},
{OV7675_CAMERA_MODULE_DATA, 0xa9, 0x90},
{OV7675_CAMERA_MODULE_DATA, 0xaa, 0x14},
{OV7675_CAMERA_MODULE_DATA, 0x13, 0xe5},
{OV7675_CAMERA_MODULE_DATA, 0x0e, 0x61},
{OV7675_CAMERA_MODULE_DATA, 0x0f, 0x4b},
{OV7675_CAMERA_MODULE_DATA, 0x16, 0x02},
{OV7675_CAMERA_MODULE_DATA, 0x1e, 0x07},
{OV7675_CAMERA_MODULE_DATA, 0x21, 0x02},
{OV7675_CAMERA_MODULE_DATA, 0x22, 0x91},
{OV7675_CAMERA_MODULE_DATA, 0x29, 0x07},
{OV7675_CAMERA_MODULE_DATA, 0x33, 0x0b},
{OV7675_CAMERA_MODULE_DATA, 0x35, 0x0b},
{OV7675_CAMERA_MODULE_DATA, 0x37, 0x1d},
{OV7675_CAMERA_MODULE_DATA, 0x38, 0x71},
{OV7675_CAMERA_MODULE_DATA, 0x39, 0x2a},
{OV7675_CAMERA_MODULE_DATA, 0x3c, 0x78},
{OV7675_CAMERA_MODULE_DATA, 0x4d, 0x40},
{OV7675_CAMERA_MODULE_DATA, 0x4e, 0x20},
{OV7675_CAMERA_MODULE_DATA, 0x69, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x6b, 0x0a},
{OV7675_CAMERA_MODULE_DATA, 0x74, 0x10},
{OV7675_CAMERA_MODULE_DATA, 0x8d, 0x4f},
{OV7675_CAMERA_MODULE_DATA, 0x8e, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x8f, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x90, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x91, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x96, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x9a, 0x80},
{OV7675_CAMERA_MODULE_DATA, 0xb0, 0x84},
{OV7675_CAMERA_MODULE_DATA, 0xb1, 0x0c},
{OV7675_CAMERA_MODULE_DATA, 0xb2, 0x0e},
{OV7675_CAMERA_MODULE_DATA, 0xb3, 0x82},
{OV7675_CAMERA_MODULE_DATA, 0xb8, 0x0a},
{OV7675_CAMERA_MODULE_DATA, 0x43, 0x0a},
{OV7675_CAMERA_MODULE_DATA, 0x44, 0xf2},
{OV7675_CAMERA_MODULE_DATA, 0x45, 0x39},
{OV7675_CAMERA_MODULE_DATA, 0x46, 0x62},
{OV7675_CAMERA_MODULE_DATA, 0x47, 0x3d},
{OV7675_CAMERA_MODULE_DATA, 0x48, 0x55},
{OV7675_CAMERA_MODULE_DATA, 0x59, 0x83},
{OV7675_CAMERA_MODULE_DATA, 0x5a, 0x0d},
{OV7675_CAMERA_MODULE_DATA, 0x5b, 0xcd},
{OV7675_CAMERA_MODULE_DATA, 0x5c, 0x8c},
{OV7675_CAMERA_MODULE_DATA, 0x5d, 0x77},
{OV7675_CAMERA_MODULE_DATA, 0x5e, 0x16},
{OV7675_CAMERA_MODULE_DATA, 0x6c, 0x0a},
{OV7675_CAMERA_MODULE_DATA, 0x6d, 0x65},
{OV7675_CAMERA_MODULE_DATA, 0x6e, 0x11},
{OV7675_CAMERA_MODULE_DATA, 0x6f, 0x9e},
{OV7675_CAMERA_MODULE_DATA, 0x6a, 0x40},
{OV7675_CAMERA_MODULE_DATA, 0x01, 0x56},
{OV7675_CAMERA_MODULE_DATA, 0x02, 0x44},
{OV7675_CAMERA_MODULE_DATA, 0x13, 0xe7},
{OV7675_CAMERA_MODULE_DATA, 0x4f, 0x88},
{OV7675_CAMERA_MODULE_DATA, 0x50, 0x8b},
{OV7675_CAMERA_MODULE_DATA, 0x51, 0x04},
{OV7675_CAMERA_MODULE_DATA, 0x52, 0x11},
{OV7675_CAMERA_MODULE_DATA, 0x53, 0x8c},
{OV7675_CAMERA_MODULE_DATA, 0x54, 0x9d},
{OV7675_CAMERA_MODULE_DATA, 0x55, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x56, 0x40},
{OV7675_CAMERA_MODULE_DATA, 0x57, 0x80},
{OV7675_CAMERA_MODULE_DATA, 0x58, 0x9a},
{OV7675_CAMERA_MODULE_DATA, 0x41, 0x08},
{OV7675_CAMERA_MODULE_DATA, 0x3f, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x75, 0x04},
{OV7675_CAMERA_MODULE_DATA, 0x76, 0x60},
{OV7675_CAMERA_MODULE_DATA, 0x4c, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x77, 0x01},
{OV7675_CAMERA_MODULE_DATA, 0x3d, 0xc2},
{OV7675_CAMERA_MODULE_DATA, 0x4b, 0x09},
{OV7675_CAMERA_MODULE_DATA, 0xc9, 0x30},
{OV7675_CAMERA_MODULE_DATA, 0x41, 0x38},
{OV7675_CAMERA_MODULE_DATA, 0x56, 0x40},
{OV7675_CAMERA_MODULE_DATA, 0x34, 0x11},
{OV7675_CAMERA_MODULE_DATA, 0x3b, 0x12},
{OV7675_CAMERA_MODULE_DATA, 0xa4, 0x88},
{OV7675_CAMERA_MODULE_DATA, 0x96, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x97, 0x30},
{OV7675_CAMERA_MODULE_DATA, 0x98, 0x20},
{OV7675_CAMERA_MODULE_DATA, 0x99, 0x30},
{OV7675_CAMERA_MODULE_DATA, 0x9a, 0x84},
{OV7675_CAMERA_MODULE_DATA, 0x9b, 0x29},
{OV7675_CAMERA_MODULE_DATA, 0x9c, 0x03},
{OV7675_CAMERA_MODULE_DATA, 0x9d, 0x99},
{OV7675_CAMERA_MODULE_DATA, 0x9e, 0x7f},
{OV7675_CAMERA_MODULE_DATA, 0x78, 0x04},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x01},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0xf0},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x0f},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x10},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x7e},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x0a},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x80},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x0b},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x01},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x0c},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x0f},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x0d},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x20},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x09},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x80},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x02},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0xc0},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x03},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x40},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x05},
{OV7675_CAMERA_MODULE_DATA, 0xc8, 0x30},
{OV7675_CAMERA_MODULE_DATA, 0x79, 0x26},
{OV7675_CAMERA_MODULE_DATA, 0x62, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x63, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x64, 0x06},
{OV7675_CAMERA_MODULE_DATA, 0x65, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x66, 0x05},
{OV7675_CAMERA_MODULE_DATA, 0x94, 0x05},
{OV7675_CAMERA_MODULE_DATA, 0x95, 0x09},
{OV7675_CAMERA_MODULE_DATA, 0x2a, 0x10},
{OV7675_CAMERA_MODULE_DATA, 0x2b, 0xc2},
{OV7675_CAMERA_MODULE_DATA, 0x15, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x3a, 0x04},
{OV7675_CAMERA_MODULE_DATA, 0x3d, 0xc3},
{OV7675_CAMERA_MODULE_DATA, 0x19, 0x03},
{OV7675_CAMERA_MODULE_DATA, 0x1a, 0x7b},
{OV7675_CAMERA_MODULE_DATA, 0x2a, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x2b, 0x00},
{OV7675_CAMERA_MODULE_DATA, 0x18, 0x01},
{OV7675_CAMERA_MODULE_DATA, 0x66, 0x05},
{OV7675_CAMERA_MODULE_DATA, 0x62, 0x10},
{OV7675_CAMERA_MODULE_DATA, 0x63, 0x0b},
{OV7675_CAMERA_MODULE_DATA, 0x65, 0x07},
{OV7675_CAMERA_MODULE_DATA, 0x64, 0x0f},
{OV7675_CAMERA_MODULE_DATA, 0x94, 0x0e},
{OV7675_CAMERA_MODULE_DATA, 0x95, 0x10},
{OV7675_CAMERA_MODULE_DATA, 0x4f, 0x87},
{OV7675_CAMERA_MODULE_DATA, 0x50, 0x68},
{OV7675_CAMERA_MODULE_DATA, 0x51, 0x1e},
{OV7675_CAMERA_MODULE_DATA, 0x52, 0x15},
{OV7675_CAMERA_MODULE_DATA, 0x53, 0x7c},
{OV7675_CAMERA_MODULE_DATA, 0x54, 0x91},
{OV7675_CAMERA_MODULE_DATA, 0x58, 0x1e},
{OV7675_CAMERA_MODULE_DATA, 0x41, 0x38},
{OV7675_CAMERA_MODULE_DATA, 0x76, 0xe0},
{OV7675_CAMERA_MODULE_DATA, 0x24, 0x40},
{OV7675_CAMERA_MODULE_DATA, 0x25, 0x38},
{OV7675_CAMERA_MODULE_DATA, 0x26, 0x91},
{OV7675_CAMERA_MODULE_DATA, 0x7a, 0x09},
{OV7675_CAMERA_MODULE_DATA, 0x7b, 0x0c},
{OV7675_CAMERA_MODULE_DATA, 0x7c, 0x16},
{OV7675_CAMERA_MODULE_DATA, 0x7d, 0x28},
{OV7675_CAMERA_MODULE_DATA, 0x7e, 0x48},
{OV7675_CAMERA_MODULE_DATA, 0x7f, 0x57},
{OV7675_CAMERA_MODULE_DATA, 0x80, 0x64},
{OV7675_CAMERA_MODULE_DATA, 0x81, 0x71},
{OV7675_CAMERA_MODULE_DATA, 0x82, 0x7e},
{OV7675_CAMERA_MODULE_DATA, 0x83, 0x89},
{OV7675_CAMERA_MODULE_DATA, 0x84, 0x94},
{OV7675_CAMERA_MODULE_DATA, 0x85, 0xa8},
{OV7675_CAMERA_MODULE_DATA, 0x86, 0xba},
{OV7675_CAMERA_MODULE_DATA, 0x87, 0xd7},
{OV7675_CAMERA_MODULE_DATA, 0x88, 0xec},
{OV7675_CAMERA_MODULE_DATA, 0x89, 0xf9},
{OV7675_CAMERA_MODULE_DATA, 0x09, 0x00},
};
/* ======================================================================== */
static struct ov_camera_module_config ov7675_configs[] = {
{
.name = "640x480_30fps",
.frm_fmt = {
.width = 640,
.height = 480,
.code = MEDIA_BUS_FMT_YVYU8_2X8
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 30
}
},
.auto_exp_enabled = false,
.auto_gain_enabled = false,
.auto_wb_enabled = false,
.reg_table = (void *)ov7675_init_tab_640_480_30fps,
.reg_table_num_entries =
sizeof(ov7675_init_tab_640_480_30fps) /
sizeof(ov7675_init_tab_640_480_30fps[0]),
.v_blanking_time_us = 1000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_DVP_CFG(
PLTFRM_CAM_ITF_BT601_8,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
PLTFRM_CAM_SDR_POS_EDG,
ov7675_EXT_CLK)
}
};
/*--------------------------------------------------------------------------*/
static int ov7675_write_aec(struct ov_camera_module *cam_mod)
{
return 0;
}
/*--------------------------------------------------------------------------*/
static int ov7675_g_ctrl(struct ov_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
ov_camera_module_pr_info(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov7675_filltimings(struct ov_camera_module_custom_config *custom)
{
return 0;
}
static int ov7675_g_timings(struct ov_camera_module *cam_mod,
struct ov_camera_module_timings *timings)
{
return 0;
}
static int ov7675_s_ctrl(struct ov_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
ov_camera_module_pr_info(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
ret = ov7675_write_aec(cam_mod);
break;
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d) 0x%x\n", ret, ctrl_id);
return ret;
}
static int ov7675_s_ext_ctrls(struct ov_camera_module *cam_mod,
struct ov_camera_module_ext_ctrls *ctrls)
{
int ret = 0;
ov_camera_module_pr_info(cam_mod, "\n");
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov7675_write_aec(cam_mod);
else
ret = -EINVAL;
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int ov7675_set_flip(
struct ov_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len)
{
return 0;
}
static int ov7675_check_camera_id(struct ov_camera_module *cam_mod)
{
u32 pidh, pidl;
int ret = 0;
ov_camera_module_pr_info(cam_mod, "\n");
ret |= pltfrm_camera_module_read_reg_ex(&cam_mod->sd, 1,
OV7675_CAMERA_MODULE_DATA, ov7675_PIDH_ADDR, &pidh);
ret |= pltfrm_camera_module_read_reg_ex(&cam_mod->sd, 1,
OV7675_CAMERA_MODULE_DATA, ov7675_PIDL_ADDR, &pidl);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"register read failed, camera module powered off?\n");
goto err;
}
if ((pidh == ov7675_PIDH_MAGIC) && (pidl == ov7675_PIDL_MAGIC)) {
ov_camera_module_pr_info(cam_mod,
"successfully detected camera ID 0x%02x%02x\n",
pidh, pidl);
} else {
ov_camera_module_pr_err(cam_mod,
"wrong camera ID, expected 0x%02x%02x, detected 0x%02x%02x\n",
ov7675_PIDH_MAGIC, ov7675_PIDL_MAGIC, pidh, pidl);
ret = -EINVAL;
goto err;
}
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
static int ov7675_start_streaming(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
ret = pltfrm_camera_module_write_reg_ex(&cam_mod->sd,
OV7675_CAMERA_MODULE_DATA, 0x09, 0);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
static int ov7675_stop_streaming(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
ret = pltfrm_camera_module_write_reg_ex(&cam_mod->sd,
OV7675_CAMERA_MODULE_DATA, 0x09, 10);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
static struct v4l2_subdev_core_ops ov7675_camera_module_core_ops = {
.g_ctrl = ov_camera_module_g_ctrl,
.s_ctrl = ov_camera_module_s_ctrl,
.s_ext_ctrls = ov_camera_module_s_ext_ctrls,
.s_power = ov_camera_module_s_power,
.ioctl = ov_camera_module_ioctl
};
static struct v4l2_subdev_video_ops ov7675_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
static struct v4l2_subdev_pad_ops ov7675_camera_module_pad_ops = {
.enum_frame_interval = ov_camera_module_enum_frameintervals,
.get_fmt = ov_camera_module_g_fmt,
.set_fmt = ov_camera_module_s_fmt,
};
static struct v4l2_subdev_ops ov7675_camera_module_ops = {
.core = &ov7675_camera_module_core_ops,
.video = &ov7675_camera_module_video_ops,
.pad = &ov7675_camera_module_pad_ops
};
static struct ov_camera_module_custom_config ov7675_custom_config = {
.start_streaming = ov7675_start_streaming,
.stop_streaming = ov7675_stop_streaming,
.s_ctrl = ov7675_s_ctrl,
.s_ext_ctrls = ov7675_s_ext_ctrls,
.g_ctrl = ov7675_g_ctrl,
.g_timings = ov7675_g_timings,
.check_camera_id = ov7675_check_camera_id,
.set_flip = ov7675_set_flip,
.configs = ov7675_configs,
.num_configs = ARRAY_SIZE(ov7675_configs),
.power_up_delays_ms = {20, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int ov7675_probe(
struct i2c_client *client,
const struct i2c_device_id *id)
{
dev_info(&client->dev, "probing...\n");
ov7675_filltimings(&ov7675_custom_config);
v4l2_i2c_subdev_init(&ov7675.sd, client, &ov7675_camera_module_ops);
ov7675.custom = ov7675_custom_config;
dev_info(&client->dev, "probing successful\n");
return 0;
}
static int ov7675_remove(struct i2c_client *client)
{
struct ov_camera_module *cam_mod = i2c_get_clientdata(client);
dev_info(&client->dev, "removing device...\n");
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");
return 0;
}
static const struct i2c_device_id ov7675_id[] = {
{ ov7675_DRIVER_NAME, 0 },
{ }
};
static const struct of_device_id ov7675_of_match[] = {
{.compatible = "omnivision,ov7675-v4l2-i2c-subdev"},
{},
};
MODULE_DEVICE_TABLE(i2c, ov7675_id);
static struct i2c_driver ov7675_i2c_driver = {
.driver = {
.name = ov7675_DRIVER_NAME,
.of_match_table = ov7675_of_match
},
.probe = ov7675_probe,
.remove = ov7675_remove,
.id_table = ov7675_id,
};
module_i2c_driver(ov7675_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for ov7675");
MODULE_AUTHOR("George");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,830 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* drivers/media/i2c/soc_camera/xgold/ov9281.c
*
* ov9281 sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
* Note:
* 07/01/2014: new implementation using v4l2-subdev
* instead of v4l2-int-device.
*/
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf-core.h>
#include <linux/slab.h>
#include "ov_camera_module.h"
#define DEBUG
#define ov9281_DRIVER_NAME "ov9281"
#define ov9281_FETCH_LSB_GAIN(VAL) ((VAL) & 0x00ff)
#define ov9281_FETCH_MSB_GAIN(VAL) (((VAL) >> 8) & 0xff)
#define ov9281_AEC_PK_LONG_GAIN_REG 0x3509 /* Bits 0 -5 */
#define ov9281_AEC_PK_LONG_EXPO_3RD_REG 0x3500 /* Exposure Bits 16-19 */
#define ov9281_AEC_PK_LONG_EXPO_2ND_REG 0x3501 /* Exposure Bits 8-15 */
#define ov9281_AEC_PK_LONG_EXPO_1ST_REG 0x3502 /* Exposure Bits 0-7 */
#define ov9281_AEC_GROUP_UPDATE_ADDRESS 0x3208
#define ov9281_AEC_GROUP_UPDATE_START_DATA 0x00
#define ov9281_AEC_GROUP_UPDATE_END_DATA 0x10
#define ov9281_AEC_GROUP_UPDATE_END_LAUNCH 0xA0
#define ov9281_FETCH_3RD_BYTE_EXP(VAL) (((VAL) >> 16) & 0xF) /* 4 Bits */
#define ov9281_FETCH_2ND_BYTE_EXP(VAL) (((VAL) >> 8) & 0xFF) /* 8 Bits */
#define ov9281_FETCH_1ST_BYTE_EXP(VAL) ((VAL) & 0xFF) /* 8 Bits */
#define ov9281_PIDH_ADDR 0x300A
#define ov9281_PIDL_ADDR 0x300B
#define ov9281_TIMING_VTS_HIGH_REG 0x380e
#define ov9281_TIMING_VTS_LOW_REG 0x380f
#define ov9281_TIMING_HTS_HIGH_REG 0x380c
#define ov9281_TIMING_HTS_LOW_REG 0x380d
#define ov9281_INTEGRATION_TIME_MARGIN 8
#define ov9281_FINE_INTG_TIME_MIN 0
#define ov9281_FINE_INTG_TIME_MAX_MARGIN 0
#define ov9281_COARSE_INTG_TIME_MIN 1
#define ov9281_COARSE_INTG_TIME_MAX_MARGIN 25
#define ov9281_TIMING_X_INC 0x3814
#define ov9281_TIMING_Y_INC 0x3815
#define ov9281_HORIZONTAL_START_HIGH_REG 0x3800
#define ov9281_HORIZONTAL_START_LOW_REG 0x3801
#define ov9281_VERTICAL_START_HIGH_REG 0x3802
#define ov9281_VERTICAL_START_LOW_REG 0x3803
#define ov9281_HORIZONTAL_END_HIGH_REG 0x3804
#define ov9281_HORIZONTAL_END_LOW_REG 0x3805
#define ov9281_VERTICAL_END_HIGH_REG 0x3806
#define ov9281_VERTICAL_END_LOW_REG 0x3807
#define ov9281_HORIZONTAL_OUTPUT_SIZE_HIGH_REG 0x3808
#define ov9281_HORIZONTAL_OUTPUT_SIZE_LOW_REG 0x3809
#define ov9281_VERTICAL_OUTPUT_SIZE_HIGH_REG 0x380a
#define ov9281_VERTICAL_OUTPUT_SIZE_LOW_REG 0x380b
#define ov9281_FLIP_REG 0x3820
#define ov9281_MIRROR_REG 0x3821
#define ov9281_EXT_CLK 24000000
#define ov9281_FULL_SIZE_RESOLUTION_WIDTH 1280
#define ov9281_BINING_SIZE_RESOLUTION_WIDTH 1280
#define ov9281_VIDEO_SIZE_RESOLUTION_WIDTH 1200
#define ov9281_EXP_VALID_FRAMES 4
/* High byte of product ID */
#define ov9281_PIDH_MAGIC 0x92
/* Low byte of product ID */
#define ov9281_PIDL_MAGIC 0x81
#define ov9281_SNAPSHOT_MODE 1
static struct ov_camera_module ov9281;
static struct ov_camera_module_custom_config ov9281_custom_config;
/* ======================================================================== */
/* Base sensor configs */
/* ======================================================================== */
/* MCLK:26MHz 1280x800 60fps mipi 2lane 481Mbps/lane */
static struct ov_camera_module_reg
ov9281_init_tab_1280_800_60fps[] = {
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0103, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x0302, 0x32},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x030d, 0x50},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x030e, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3001, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3004, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3005, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3006, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3011, 0x0a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3013, 0x18},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3022, 0x01},
/* normal */
// {OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4f00, 0x01};
#ifdef ov9281_SNAPSHOT_MODE
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3023, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x302c, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x302f, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3030, 0x04},
#else
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3030, 0x10},
#endif
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3039, 0x32},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x303a, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x303f, 0x01},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3500, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3501, 0x2a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3502, 0x90},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3503, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3505, 0x8c},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3507, 0x03},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3508, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3509, 0x10},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3610, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3611, 0xa0},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3620, 0x6f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3632, 0x56},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3633, 0x78},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3662, 0x05},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3666, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x366f, 0x5a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3680, 0x84},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3712, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x372d, 0x22},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3731, 0x80},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3732, 0x30},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3778, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x377d, 0x22},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3788, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3789, 0xa4},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x378a, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x378b, 0x4a},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3799, 0x20},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3800, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3801, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3802, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3803, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3804, 0x05},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3805, 0x0f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3806, 0x03},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3807, 0x2f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3808, 0x05},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3809, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380a, 0x03},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380b, 0x20},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380c, 0x02},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380d, 0xd8},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380e, 0x03},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x380f, 0x8e},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3810, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3811, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3812, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3813, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3814, 0x11},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3815, 0x11},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3820, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3821, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3881, 0x42},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x38b1, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x3920, 0xff},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4003, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4008, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4009, 0x0b},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x400c, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x400d, 0x07},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4010, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4043, 0x40},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4307, 0x30},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4317, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4501, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4507, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4509, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x450a, 0x08},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4601, 0x04},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x470f, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4f07, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x4800, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5000, 0x9f},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5001, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5e00, 0x00},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5d00, 0x07},
{OV_CAMERA_MODULE_REG_TYPE_DATA, 0x5d01, 0x00}
};
/* ======================================================================== */
static struct ov_camera_module_config ov9281_configs[] = {
{
.name = "1280x800_60fps",
.frm_fmt = {
.width = 1280,
.height = 800,
.code = MEDIA_BUS_FMT_Y10_1X10
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 120
}
},
.auto_exp_enabled = false,
.auto_gain_enabled = false,
.auto_wb_enabled = false,
.reg_table = (void *)ov9281_init_tab_1280_800_60fps,
.reg_table_num_entries =
sizeof(ov9281_init_tab_1280_800_60fps) /
sizeof(ov9281_init_tab_1280_800_60fps[0]),
.v_blanking_time_us = 7251,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 450, 24000000)
}
};
/*--------------------------------------------------------------------------*/
static int ov9281_g_VTS(struct ov_camera_module *cam_mod, u32 *vts)
{
u32 msb, lsb;
int ret;
ret = ov_camera_module_read_reg_table(cam_mod,
ov9281_TIMING_VTS_HIGH_REG,
&msb);
if (IS_ERR_VALUE(ret))
goto err;
ret = ov_camera_module_read_reg_table(cam_mod,
ov9281_TIMING_VTS_LOW_REG,
&lsb);
if (IS_ERR_VALUE(ret))
goto err;
*vts = (msb << 8) | lsb;
cam_mod->vts_cur = *vts;
return 0;
err:
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov9281_auto_adjust_fps(struct ov_camera_module *cam_mod,
u32 exp_time)
{
int ret;
u32 vts;
if ((cam_mod->exp_config.exp_time + ov9281_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = cam_mod->exp_config.exp_time +
ov9281_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
ret = ov_camera_module_write_reg(cam_mod,
ov9281_TIMING_VTS_LOW_REG,
vts & 0xFF);
ret |= ov_camera_module_write_reg(cam_mod,
ov9281_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
ov_camera_module_pr_info(cam_mod,
"updated vts = %d,vts_min=%d\n", vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int ov9281_set_vts(struct ov_camera_module *cam_mod,
u32 vts)
{
int ret = 0;
if (vts <= cam_mod->vts_min)
return ret;
ret = ov_camera_module_write_reg(cam_mod,
ov9281_TIMING_VTS_LOW_REG,
vts & 0xFF);
ret |= ov_camera_module_write_reg(cam_mod,
ov9281_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0x0F);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
ov_camera_module_pr_info(cam_mod,
"updated vts = 0x%x,vts_min=0x%x\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int ov9281_write_aec(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_err(cam_mod,
"exp_time = %d, gain = %d, flash_mode = %d\n",
cam_mod->exp_config.exp_time,
cam_mod->exp_config.gain,
cam_mod->exp_config.flash_mode);
/*
* if the sensor is already streaming, write to shadow registers,
* if the sensor is in SW standby, write to active registers,
* if the sensor is off/registers are not writeable, do nothing
*/
if ((cam_mod->state == OV_CAMERA_MODULE_SW_STANDBY) ||
(cam_mod->state == OV_CAMERA_MODULE_STREAMING)) {
u32 a_gain = cam_mod->exp_config.gain;
u32 exp_time;
a_gain = a_gain > 0x7ff ? 0x7ff : a_gain;
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
exp_time = cam_mod->exp_config.exp_time << 4;
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod,
ov9281_AEC_GROUP_UPDATE_ADDRESS,
ov9281_AEC_GROUP_UPDATE_START_DATA);
if (!IS_ERR_VALUE(ret) && cam_mod->auto_adjust_fps)
ret = ov9281_auto_adjust_fps(cam_mod,
cam_mod->exp_config.exp_time);
ret |= ov_camera_module_write_reg(cam_mod,
ov9281_AEC_PK_LONG_GAIN_REG,
ov9281_FETCH_LSB_GAIN(a_gain));
ret = ov_camera_module_write_reg(cam_mod,
ov9281_AEC_PK_LONG_EXPO_3RD_REG,
ov9281_FETCH_3RD_BYTE_EXP(exp_time));
ret |= ov_camera_module_write_reg(cam_mod,
ov9281_AEC_PK_LONG_EXPO_2ND_REG,
ov9281_FETCH_2ND_BYTE_EXP(exp_time));
ret |= ov_camera_module_write_reg(cam_mod,
ov9281_AEC_PK_LONG_EXPO_1ST_REG,
ov9281_FETCH_1ST_BYTE_EXP(exp_time));
if (!cam_mod->auto_adjust_fps)
ret |= ov9281_set_vts(cam_mod,
cam_mod->exp_config.vts_value);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING) {
ret = ov_camera_module_write_reg(cam_mod,
ov9281_AEC_GROUP_UPDATE_ADDRESS,
ov9281_AEC_GROUP_UPDATE_END_DATA);
ret = ov_camera_module_write_reg(cam_mod,
ov9281_AEC_GROUP_UPDATE_ADDRESS,
ov9281_AEC_GROUP_UPDATE_END_LAUNCH);
}
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov9281_g_ctrl(struct ov_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov9281_filltimings(struct ov_camera_module_custom_config *custom)
{
size_t i;
int j;
struct ov_camera_module_config *config;
struct ov_camera_module_timings *timings;
struct ov_camera_module_reg *reg_table;
int reg_table_num_entries;
for (i = 0; i < custom->num_configs; i++) {
config = &custom->configs[i];
reg_table = config->reg_table;
reg_table_num_entries = config->reg_table_num_entries;
timings = &config->timings;
memset(timings, 0x00, sizeof(*timings));
for (j = 0; j < reg_table_num_entries; j++) {
switch (reg_table[j].reg) {
case ov9281_TIMING_VTS_HIGH_REG:
timings->frame_length_lines =
((reg_table[j].val << 8) |
(timings->frame_length_lines & 0xff));
break;
case ov9281_TIMING_VTS_LOW_REG:
timings->frame_length_lines =
(reg_table[j].val |
(timings->frame_length_lines & 0xff00));
break;
case ov9281_TIMING_HTS_HIGH_REG:
timings->line_length_pck =
((reg_table[j].val << 8) |
timings->line_length_pck);
break;
case ov9281_TIMING_HTS_LOW_REG:
timings->line_length_pck =
(reg_table[j].val |
(timings->line_length_pck & 0xff00));
break;
case ov9281_TIMING_X_INC:
timings->binning_factor_x =
((reg_table[j].val >> 4) + 1) / 2;
if (timings->binning_factor_x == 0)
timings->binning_factor_x = 1;
break;
case ov9281_TIMING_Y_INC:
timings->binning_factor_y =
((reg_table[j].val >> 4) + 1) / 2;
if (timings->binning_factor_y == 0)
timings->binning_factor_y = 1;
break;
case ov9281_HORIZONTAL_START_HIGH_REG:
timings->crop_horizontal_start =
((reg_table[j].val << 8) |
(timings->crop_horizontal_start &
0xff));
break;
case ov9281_HORIZONTAL_START_LOW_REG:
timings->crop_horizontal_start =
(reg_table[j].val |
(timings->crop_horizontal_start &
0xff00));
break;
case ov9281_VERTICAL_START_HIGH_REG:
timings->crop_vertical_start =
((reg_table[j].val << 8) |
(timings->crop_vertical_start & 0xff));
break;
case ov9281_VERTICAL_START_LOW_REG:
timings->crop_vertical_start =
((reg_table[j].val) |
(timings->crop_vertical_start &
0xff00));
break;
case ov9281_HORIZONTAL_END_HIGH_REG:
timings->crop_horizontal_end =
((reg_table[j].val << 8) |
(timings->crop_horizontal_end & 0xff));
break;
case ov9281_HORIZONTAL_END_LOW_REG:
timings->crop_horizontal_end =
(reg_table[j].val |
(timings->crop_horizontal_end &
0xff00));
break;
case ov9281_VERTICAL_END_HIGH_REG:
timings->crop_vertical_end =
((reg_table[j].val << 8) |
(timings->crop_vertical_end & 0xff));
break;
case ov9281_VERTICAL_END_LOW_REG:
timings->crop_vertical_end =
(reg_table[j].val |
(timings->crop_vertical_end & 0xff00));
break;
case ov9281_HORIZONTAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_width =
((reg_table[j].val << 8) |
(timings->sensor_output_width & 0xff));
break;
case ov9281_HORIZONTAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_width =
(reg_table[j].val |
(timings->sensor_output_width &
0xff00));
break;
case ov9281_VERTICAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_height =
((reg_table[j].val << 8) |
(timings->sensor_output_height & 0xff));
break;
case ov9281_VERTICAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_height =
(reg_table[j].val |
(timings->sensor_output_height &
0xff00));
break;
case ov9281_AEC_PK_LONG_EXPO_1ST_REG:
timings->exp_time =
((reg_table[j].val) |
(timings->exp_time & 0xffff00));
break;
case ov9281_AEC_PK_LONG_EXPO_2ND_REG:
timings->exp_time =
((reg_table[j].val << 8) |
(timings->exp_time & 0x00ff00));
break;
case ov9281_AEC_PK_LONG_EXPO_3RD_REG:
timings->exp_time =
(((reg_table[j].val & 0x0f) << 16) |
(timings->exp_time & 0xff0000));
break;
case ov9281_AEC_PK_LONG_GAIN_REG:
timings->gain =
((reg_table[j].val) |
(timings->gain & 0x00ff));
break;
}
}
timings->exp_time >>= 4;
timings->vt_pix_clk_freq_hz =
config->frm_intrvl.interval.denominator
* timings->frame_length_lines
* timings->line_length_pck;
timings->coarse_integration_time_min =
ov9281_COARSE_INTG_TIME_MIN;
timings->coarse_integration_time_max_margin =
ov9281_COARSE_INTG_TIME_MAX_MARGIN;
/* OV Sensor do not use fine integration time. */
timings->fine_integration_time_min =
ov9281_FINE_INTG_TIME_MIN;
timings->fine_integration_time_max_margin =
ov9281_FINE_INTG_TIME_MAX_MARGIN;
}
return 0;
}
static int ov9281_g_timings(struct ov_camera_module *cam_mod,
struct ov_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid)
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
else
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
return ret;
err:
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov9281_s_ctrl(struct ov_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
ret = ov9281_write_aec(cam_mod);
break;
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d) 0x%x\n", ret, ctrl_id);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov9281_s_ext_ctrls(struct ov_camera_module *cam_mod,
struct ov_camera_module_ext_ctrls *ctrls)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
/* Handles only exposure and gain together special case. */
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov9281_write_aec(cam_mod);
else
ret = -EINVAL;
if (IS_ERR_VALUE(ret))
ov_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov9281_start_streaming(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod,
"active config=%s\n", cam_mod->active_config->name);
ret = ov9281_g_VTS(cam_mod, &cam_mod->vts_min);
if (IS_ERR_VALUE(ret))
goto err;
#ifdef ov9281_SNAPSHOT_MODE
if (IS_ERR_VALUE(ov_camera_module_write_reg(cam_mod, 0x0100, 0)))
goto err;
#else
if (IS_ERR_VALUE(ov_camera_module_write_reg(cam_mod, 0x0100, 1)))
goto err;
#endif
msleep(25);
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n",
ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov9281_stop_streaming(struct ov_camera_module *cam_mod)
{
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 0);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int ov9281_check_camera_id(struct ov_camera_module *cam_mod)
{
u32 pidh, pidl = 0;
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
ret |= ov_camera_module_read_reg(cam_mod, 1, ov9281_PIDH_ADDR, &pidh);
ret |= ov_camera_module_read_reg(cam_mod, 1, ov9281_PIDL_ADDR, &pidl);
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"register read failed, camera module powered off?\n");
goto err;
}
if ((pidh == ov9281_PIDH_MAGIC) && (pidl == ov9281_PIDL_MAGIC)) {
ov_camera_module_pr_debug(cam_mod,
"successfully detected camera ID 0x%02x%02x\n",
pidh, pidl);
} else {
ov_camera_module_pr_err(cam_mod,
"wrong camera ID, expected 0x%02x%02x, detected 0x%02x%02x\n",
ov9281_PIDH_MAGIC, ov9281_PIDL_MAGIC, pidh, pidl);
ret = -EINVAL;
goto err;
}
return 0;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
static struct v4l2_subdev_core_ops ov9281_camera_module_core_ops = {
.g_ctrl = ov_camera_module_g_ctrl,
.s_ctrl = ov_camera_module_s_ctrl,
.s_ext_ctrls = ov_camera_module_s_ext_ctrls,
.s_power = ov_camera_module_s_power,
.ioctl = ov_camera_module_ioctl
};
static struct v4l2_subdev_video_ops ov9281_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.s_stream = ov_camera_module_s_stream
};
static struct v4l2_subdev_pad_ops ov9281_camera_module_pad_ops = {
.enum_frame_interval = ov_camera_module_enum_frameintervals,
.get_fmt = ov_camera_module_g_fmt,
.set_fmt = ov_camera_module_s_fmt,
};
static struct v4l2_subdev_ops ov9281_camera_module_ops = {
.core = &ov9281_camera_module_core_ops,
.video = &ov9281_camera_module_video_ops,
.pad = &ov9281_camera_module_pad_ops
};
static struct ov_camera_module_custom_config ov9281_custom_config = {
.start_streaming = ov9281_start_streaming,
.stop_streaming = ov9281_stop_streaming,
.s_ctrl = ov9281_s_ctrl,
.s_vts = ov9281_auto_adjust_fps,
.s_ext_ctrls = ov9281_s_ext_ctrls,
.g_ctrl = ov9281_g_ctrl,
.g_timings = ov9281_g_timings,
.check_camera_id = ov9281_check_camera_id,
.configs = ov9281_configs,
.num_configs = ARRAY_SIZE(ov9281_configs),
.power_up_delays_ms = {5, 20, 0}
};
static int ov9281_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
dev_info(&client->dev, "tlc cam probing...\n");
dev_dbg(&client->dev, "tlc cam debug...\n");
ov9281_filltimings(&ov9281_custom_config);
client->flags |= I2C_CLIENT_SCCB;
v4l2_i2c_subdev_init(&ov9281.sd, client, &ov9281_camera_module_ops);
ov9281.custom = ov9281_custom_config;
dev_info(&client->dev, "tlc cam probing successful\n");
return 0;
}
static int ov9281_remove(struct i2c_client *client)
{
struct ov_camera_module *cam_mod = i2c_get_clientdata(client);
dev_info(&client->dev, "removing device...\n");
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");
return 0;
}
static const struct i2c_device_id ov9281_id[] = {
{ ov9281_DRIVER_NAME, 0 },
{ }
};
static const struct of_device_id ov9281_of_match[] = {
{.compatible = "omnivision,ov9281-v4l2-i2c-subdev"},
{},
};
MODULE_DEVICE_TABLE(i2c, ov9281_id);
static struct i2c_driver ov9281_i2c_driver = {
.driver = {
.name = ov9281_DRIVER_NAME,
.of_match_table = ov9281_of_match
},
.probe = ov9281_probe,
.remove = ov9281_remove,
.id_table = ov9281_id,
};
module_i2c_driver(ov9281_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for ov9281");
MODULE_AUTHOR("George");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,302 +0,0 @@
/*
* ov_camera_module.h
*
* Generic omnivision sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef OV_CAMERA_MODULE_H
#define OV_CAMERA_MODULE_H
#include <linux/workqueue.h>
#include <linux/platform_data/rk_isp10_platform_camera_module.h>
#include <linux/platform_data/rk_isp10_platform.h>
/*
* TODO: references to v4l2 should be reomved from here and go into a
* platform dependent wrapper
*/
#define OV_CAMERA_MODULE_REG_TYPE_DATA PLTFRM_CAMERA_MODULE_REG_TYPE_DATA
#define OV_CAMERA_MODULE_REG_TYPE_TIMEOUT PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define ov_camera_module_csi_config
#define ov_camera_module_reg pltfrm_camera_module_reg
#define OV_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define OV_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define OV_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define OV_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
#define OV_CAMERA_MODULE_CTRL_UPDT_WB_TEMPERATURE 0x04
#define OV_CAMERA_MODULE_CTRL_UPDT_AUTO_WB 0x08
#define OV_CAMERA_MODULE_CTRL_UPDT_AUTO_GAIN 0x10
#define OV_CAMERA_MODULE_CTRL_UPDT_AUTO_EXP 0x20
#define OV_CAMERA_MODULE_CTRL_UPDT_FOCUS_ABSOLUTE 0x40
#define OV_CAMERA_MODULE_CTRL_UPDT_PRESET_WB 0x80
#define OV_CAMERA_MODULE_CTRL_UPDT_VTS_VALUE 0x100
enum ov_camera_module_state {
OV_CAMERA_MODULE_POWER_OFF = 0,
OV_CAMERA_MODULE_HW_STANDBY = 1,
OV_CAMERA_MODULE_SW_STANDBY = 2,
OV_CAMERA_MODULE_STREAMING = 3
};
struct ov_camera_module;
struct ov_camera_module_timings {
/* public */
u32 coarse_integration_time_min;
u32 coarse_integration_time_max_margin;
u32 fine_integration_time_min;
u32 fine_integration_time_max_margin;
u32 frame_length_lines;
u32 line_length_pck;
u32 vt_pix_clk_freq_hz;
u32 sensor_output_width;
u32 sensor_output_height;
u32 crop_horizontal_start; /* Sensor crop start cord. (x0,y0) */
u32 crop_vertical_start;
u32 crop_horizontal_end; /* Sensor crop end cord. (x1,y1) */
u32 crop_vertical_end;
u8 binning_factor_x;
u8 binning_factor_y;
u32 exp_time;
u32 gain;
};
struct ov_camera_module_config {
const char *name;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
bool auto_exp_enabled;
bool auto_gain_enabled;
bool auto_wb_enabled;
struct ov_camera_module_reg *reg_table;
u32 reg_table_num_entries;
struct ov_camera_module_reg *reg_diff_table;
u32 reg_diff_table_num_entries;
u32 v_blanking_time_us;
u32 line_length_pck;
u32 frame_length_lines;
struct ov_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
struct ov_camera_module_exp_config {
s32 exp_time;
bool auto_exp;
u16 gain;
u16 gain_percent;
bool auto_gain;
enum v4l2_flash_led_mode flash_mode;
u32 vts_value;
};
struct ov_camera_module_wb_config {
u32 temperature;
u32 preset_id;
bool auto_wb;
};
struct ov_camera_module_af_config {
u32 abs_pos;
u32 rel_pos;
};
struct ov_camera_module_ext_ctrl {
/* public */
u32 id;
u32 value;
__u32 reserved2[1];
};
struct ov_camera_module_ext_ctrls {
/* public */
u32 count;
struct ov_camera_module_ext_ctrl *ctrls;
};
/*
* start_streaming: (mandatory) will be called when sensor should be
* put into streaming mode right after the base config has been
* written to the sensor. After a successful call of this function
* the sensor should start delivering frame data.
*
* stop_streaming: (mandatory) will be called when sensor should stop
* delivering data. After a successful call of this function the
* sensor should not deliver any more frame data.
*
* check_camera_id: (optional) will be called when the sensor is
* powered on. If provided should check the sensor ID/version
* required by the custom driver. Register access should be
* possible when this function is invoked.
*
* s_ctrl: (mandatory) will be called at the successful end of
* ov_camera_module_s_ctrl with the ctrl_id as argument.
*
* priv: (optional) for private data used by the custom driver.
*/
struct ov_camera_module_custom_config {
int (*start_streaming)(struct ov_camera_module *cam_mod);
int (*stop_streaming)(struct ov_camera_module *cam_mod);
int (*check_camera_id)(struct ov_camera_module *cam_mod);
int (*s_ctrl)(struct ov_camera_module *cam_mod, u32 ctrl_id);
int (*g_ctrl)(struct ov_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct ov_camera_module *cam_mod,
struct ov_camera_module_timings *timings);
int (*s_vts)(struct ov_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct ov_camera_module *cam_mod,
struct ov_camera_module_ext_ctrls *ctrls);
int (*set_flip)(
struct ov_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len);
int (*init_common)(struct ov_camera_module *cam_mod);
int (*read_otp)(struct ov_camera_module *cam_mod);
struct ov_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
struct ov_camera_module_otp_work {
struct work_struct work;
struct workqueue_struct *wq;
void *cam_mod;
};
struct ov_camera_module {
/* public */
struct v4l2_subdev sd;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
struct ov_camera_module_exp_config exp_config;
struct ov_camera_module_wb_config wb_config;
struct ov_camera_module_af_config af_config;
struct ov_camera_module_custom_config custom;
enum ov_camera_module_state state;
enum ov_camera_module_state state_before_suspend;
struct ov_camera_module_config *active_config;
struct ov_camera_module_otp_work otp_work;
u32 ctrl_updt;
u32 vts_cur;
u32 vts_min;
bool auto_adjust_fps;
bool update_config;
bool frm_fmt_valid;
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
int as_master;
struct mutex lock;
};
#define ov_camera_module_pr_info(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_info(&(cam_mod)->sd, fmt, ## arg)
#define ov_camera_module_pr_debug(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_debug(&(cam_mod)->sd, fmt, ## arg)
#define ov_camera_module_pr_warn(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_warn(&(cam_mod)->sd, fmt, ## arg)
#define ov_camera_module_pr_err(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_err(&(cam_mod)->sd, fmt, ## arg)
int ov_camera_module_write_reglist(
struct ov_camera_module *cam_mod,
const struct ov_camera_module_reg reglist[],
int len);
int ov_camera_module_write_reg(
struct ov_camera_module *cam_mod,
u16 reg,
u8 val);
int ov_camera_module_read_reg(
struct ov_camera_module *cam_mod,
u16 data_length,
u16 reg,
u32 *val);
int ov_camera_module_read_reg_table(
struct ov_camera_module *cam_mod,
u16 reg,
u32 *val);
int ov_camera_module_s_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int ov_camera_module_g_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int ov_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int ov_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int ov_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);
int ov_camera_module_s_power(
struct v4l2_subdev *sd,
int on);
int ov_camera_module_g_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int ov_camera_module_s_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int ov_camera_module_s_ext_ctrls(
struct v4l2_subdev *sd,
struct v4l2_ext_controls *ctrls);
int ov_camera_module_enum_frame_size(
struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_size_enum *fse);
int ov_camera_module_enum_frameintervals(
struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie);
int ov_camera_module_init(
struct ov_camera_module *cam_mod,
struct ov_camera_module_custom_config *custom);
void ov_camera_module_release(
struct ov_camera_module *cam_mod);
long ov_camera_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg);
int ov_camera_module_get_flip_mirror(
struct ov_camera_module *cam_mod);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +0,0 @@
/*
* rk_camera_module.h
* (Based on Intel driver for sofiaxxx)
*
* Copyright (C) 2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _RK_CAMERA_MODULE_VERSION_H_
#define _RK_CAMERA_MODULE_VERSION_H_
#include <linux/version.h>
/*
* CIF DRIVER VERSION NOTE
*
* v0.1.0:
* 1. Initialize version;
* 2. Update sensor configuration after power up sensor in
* ov_camera_module_s_power.
* Because mipi datalane may be no still on LP11 state when
* sensor configuration;
*
*/
#define CONFIG_RK_CAMERA_MODULE_VERSION KERNEL_VERSION(0, 1, 0)
#endif

View File

@@ -1,787 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* sc031gs sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* Note:
*
*v0.1.0:
*1. Initialize version;
*
*/
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf-core.h>
#include <linux/slab.h>
#include <media/v4l2-controls_rockchip.h>
#include "sc_camera_module.h"
#define SC031GS_DRIVER_NAME "sc031gs"
#define SC031GS_AEC_PK_LONG_GAIN_HIGH_REG 0x3e08
#define SC031GS_AEC_PK_LONG_GAIN_LOW_REG 0x3e09
#define SC031GS_AEC_PK_LONG_EXPO_HIGH_REG 0x3e01
#define SC031GS_AEC_PK_LONG_EXPO_LOW_REG 0x3e02
#define SC031GS_AEC_GROUP_UPDATE_ADDRESS 0x3812
#define SC031GS_AEC_GROUP_UPDATE_START_DATA 0x00
#define SC031GS_AEC_GROUP_UPDATE_END_DATA 0x30
#define SC031GS_PIDH_ADDR 0x3107
#define SC031GS_PIDL_ADDR 0x3108
/* High byte of product ID */
#define SC031GS_PIDH_MAGIC 0x00
/* Low byte of product ID */
#define SC031GS_PIDL_MAGIC 0x31
#define SC031GS_EXT_CLK 24000000
#define SC031GS_TIMING_VTS_HIGH_REG 0x320e
#define SC031GS_TIMING_VTS_LOW_REG 0x320f
#define SC031GS_TIMING_HTS_HIGH_REG 0x320c
#define SC031GS_TIMING_HTS_LOW_REG 0x320d
#define SC031GS_FINE_INTG_TIME_MIN 0
#define SC031GS_FINE_INTG_TIME_MAX_MARGIN 0
#define SC031GS_COARSE_INTG_TIME_MIN 1
#define SC031GS_COARSE_INTG_TIME_MAX_MARGIN 4
#define SC031GS_HORIZONTAL_OUTPUT_SIZE_HIGH_REG 0x3208
#define SC031GS_HORIZONTAL_OUTPUT_SIZE_LOW_REG 0x3209
#define SC031GS_VERTICAL_OUTPUT_SIZE_HIGH_REG 0x320a
#define SC031GS_VERTICAL_OUTPUT_SIZE_LOW_REG 0x320b
#define SC031GS_MIRROR_FILP 0x3221
static struct sc_camera_module sc031gs;
/* ======================================================================== */
/* Base sensor configs */
/* ======================================================================== */
/* MCLK:24MHz 640x480 50fps mipi 1lane 10bit 720Mbps/lane */
static struct sc_camera_module_reg sc031gs_init_tab_640_480_50fps[] = {
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x0100, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3000, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3001, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x300f, 0x0f},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3018, 0x13},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3019, 0xfe},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x301c, 0x78},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3031, 0x0a},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3037, 0x20},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x303f, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3208, 0x02},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3209, 0x80},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320a, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320b, 0xe0},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320c, 0x03},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320d, 0x6e},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320e, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320f, 0x67},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3250, 0xc0},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3251, 0x02},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3252, 0x02},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3253, 0xa6},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3254, 0x02},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3255, 0x07},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3304, 0x48},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3306, 0x38},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3309, 0x68},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x330b, 0xe0},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x330c, 0x18},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x330f, 0x20},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3310, 0x10},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3314, 0x3a},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3315, 0x38},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3316, 0x48},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3317, 0x20},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3329, 0x3c},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x332d, 0x3c},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x332f, 0x40},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3335, 0x44},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3344, 0x44},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x335b, 0x80},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x335f, 0x80},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3366, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3385, 0x31},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3387, 0x51},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3389, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x33b1, 0x03},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x33b2, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3621, 0xa4},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3622, 0x05},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3630, 0x46},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3631, 0x48},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3633, 0x52},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3636, 0x25},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3637, 0x89},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3638, 0x0f},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3639, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x363a, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x363b, 0x48},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x363c, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x363d, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x363e, 0xf8},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3640, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3641, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x36e9, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x36ea, 0x3b},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x36eb, 0x0e},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x36ec, 0x0e},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x36ed, 0x33},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x36f9, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x36fa, 0x3a},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x36fc, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3908, 0x91},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3d08, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e01, 0x2a},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e02, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e03, 0x0b},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e06, 0x0c},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x4500, 0x59},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x4501, 0xc4},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x4603, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x5011, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x4418, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x4419, 0x8a},
};
static struct sc_camera_module_config sc031gs_configs[] = {
{
.name = "640x480_50fps",
.frm_fmt = {
.width = 640,
.height = 480,
.code = MEDIA_BUS_FMT_Y10_1X10
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 50
}
},
.auto_exp_enabled = false,
.auto_gain_enabled = false,
.auto_wb_enabled = false,
.reg_table = (void *)sc031gs_init_tab_640_480_50fps,
.reg_table_num_entries =
ARRAY_SIZE(sc031gs_init_tab_640_480_50fps),
.v_blanking_time_us = 3078,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 1, 720, SC031GS_EXT_CLK)
}
};
static int sc031gs_set_flip(struct sc_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len)
{
int i, mode = 0;
u16 orientation = 0;
mode = sc_camera_module_get_flip_mirror(cam_mod);
if (mode == -1) {
sc_camera_module_pr_debug(cam_mod,
"dts don't set flip, return!\n");
return 0;
}
if (!IS_ERR_OR_NULL(cam_mod->active_config)) {
if (mode == SC_MIRROR_BIT_MASK)
orientation |= 0x06;
if (mode == SC_FLIP_BIT_MASK)
orientation |= 0x60;
for (i = 0; i < len; i++) {
if (reglist[i].reg == SC031GS_MIRROR_FILP)
reglist[i].val = orientation;
}
}
return 0;
}
static int sc031gs_g_vts(struct sc_camera_module *cam_mod, u32 *vts)
{
u32 msb, lsb;
int ret;
ret = sc_camera_module_read_reg_table(cam_mod,
SC031GS_TIMING_VTS_HIGH_REG,
&msb);
if (IS_ERR_VALUE(ret))
goto err;
ret = sc_camera_module_read_reg_table(cam_mod,
SC031GS_TIMING_VTS_LOW_REG,
&lsb);
if (IS_ERR_VALUE(ret))
goto err;
*vts = (msb << 8) | lsb;
return 0;
err:
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc031gs_auto_adjust_fps(struct sc_camera_module *cam_mod,
u32 exp_time)
{
int ret;
u32 vts;
if ((exp_time + SC031GS_COARSE_INTG_TIME_MAX_MARGIN) >
cam_mod->vts_min)
vts = (exp_time + SC031GS_COARSE_INTG_TIME_MAX_MARGIN);
else
vts = cam_mod->vts_min;
ret = sc_camera_module_write_reg(cam_mod,
SC031GS_TIMING_VTS_LOW_REG,
vts & 0xFF);
ret |= sc_camera_module_write_reg(cam_mod,
SC031GS_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
sc_camera_module_pr_debug(cam_mod,
"updated vts = 0x%x,vts_min=0x%x\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int sc031gs_set_vts(struct sc_camera_module *cam_mod,
u32 vts)
{
int ret = 0;
if (vts <= cam_mod->vts_min)
return ret;
ret = sc_camera_module_write_reg(cam_mod,
SC031GS_TIMING_VTS_LOW_REG,
vts & 0xFF);
ret |= sc_camera_module_write_reg(cam_mod,
SC031GS_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
sc_camera_module_pr_debug(cam_mod,
"updated vts = 0x%x,vts_min=0x%x\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int sc031gs_write_aec(struct sc_camera_module *cam_mod)
{
int ret = 0;
sc_camera_module_pr_debug(cam_mod,
"exp_time = %d lines, gain = %d, flash_mode = %d\n",
cam_mod->exp_config.exp_time,
cam_mod->exp_config.gain,
cam_mod->exp_config.flash_mode);
/*
* if the sensor is already streaming, write to shadow registers,
* if the sensor is in SW standby, write to active registers,
* if the sensor is off/registers are not writeable, do nothing
*/
if (cam_mod->state == SC_CAMERA_MODULE_SW_STANDBY ||
cam_mod->state == SC_CAMERA_MODULE_STREAMING) {
u32 a_gain = cam_mod->exp_config.gain;
u32 exp_time = cam_mod->exp_config.exp_time;
u32 vts = cam_mod->vts_min;
u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg;
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
/* hold reg start */
mutex_lock(&cam_mod->lock);
ret = sc_camera_module_write_reg(cam_mod,
SC031GS_AEC_GROUP_UPDATE_ADDRESS,
SC031GS_AEC_GROUP_UPDATE_START_DATA);
if (!IS_ERR_VALUE(ret) && cam_mod->auto_adjust_fps)
ret |= sc031gs_auto_adjust_fps(cam_mod,
cam_mod->exp_config.exp_time);
if (exp_time > vts - 6)
exp_time = vts - 6;
if (a_gain < 0x20) { /*1x ~ 2x*/
fine_again = a_gain - 16;
coarse_again = 0x03;
fine_again_reg = ((0x01 << 4) & 0x10) |
(fine_again & 0x0f);
coarse_again_reg = coarse_again & 0x1F;
} else if (a_gain < 0x40) { /*2x ~ 4x*/
fine_again = (a_gain >> 1) - 16;
coarse_again = 0x7;
fine_again_reg = ((0x01 << 4) & 0x10) |
(fine_again & 0x0f);
coarse_again_reg = coarse_again & 0x1F;
} else if (a_gain < 0x80) { /*4x ~ 8x*/
fine_again = (a_gain >> 2) - 16;
coarse_again = 0xf;
fine_again_reg = ((0x01 << 4) & 0x10) |
(fine_again & 0x0f);
coarse_again_reg = coarse_again & 0x1F;
} else { /*8x ~ 16x*/
fine_again = (a_gain >> 3) - 16;
coarse_again = 0x1f;
fine_again_reg = ((0x01 << 4) & 0x10) |
(fine_again & 0x0f);
coarse_again_reg = coarse_again & 0x1F;
}
if (a_gain < 0x20) {
ret |= sc_camera_module_write_reg(cam_mod,
0x3314, 0x3a);
ret |= sc_camera_module_write_reg(cam_mod,
0x3317, 0x20);
} else {
ret |= sc_camera_module_write_reg(cam_mod,
0x3314, 0x44);
ret |= sc_camera_module_write_reg(cam_mod,
0x3317, 0x0f);
}
ret |= sc_camera_module_write_reg(cam_mod,
SC031GS_AEC_PK_LONG_GAIN_HIGH_REG,
coarse_again_reg);
ret |= sc_camera_module_write_reg(cam_mod,
SC031GS_AEC_PK_LONG_GAIN_LOW_REG,
fine_again_reg);
ret |= sc_camera_module_write_reg(cam_mod,
SC031GS_AEC_PK_LONG_EXPO_HIGH_REG,
(exp_time >> 4) & 0xff);
ret |= sc_camera_module_write_reg(cam_mod,
SC031GS_AEC_PK_LONG_EXPO_LOW_REG,
(exp_time & 0xff) << 4);
if (!cam_mod->auto_adjust_fps)
ret |= sc031gs_set_vts(cam_mod,
cam_mod->exp_config.vts_value);
/* hold reg end */
ret |= sc_camera_module_write_reg(cam_mod,
SC031GS_AEC_GROUP_UPDATE_ADDRESS,
SC031GS_AEC_GROUP_UPDATE_END_DATA);
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc031gs_g_ctrl(struct sc_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
sc_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
sc_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc031gs_filltimings(struct sc_camera_module_custom_config *custom)
{
u32 i, j;
u32 win_h_off = 0, win_v_off = 0;
struct sc_camera_module_config *config;
struct sc_camera_module_timings *timings;
struct sc_camera_module_reg *reg_table;
u32 reg_table_num_entries;
for (i = 0; i < custom->num_configs; i++) {
config = &custom->configs[i];
reg_table = config->reg_table;
reg_table_num_entries = config->reg_table_num_entries;
timings = &config->timings;
memset(timings, 0x00, sizeof(*timings));
for (j = 0; j < reg_table_num_entries; j++) {
switch (reg_table[j].reg) {
case SC031GS_TIMING_VTS_HIGH_REG:
if (timings->frame_length_lines & 0xff00)
timings->frame_length_lines = 0;
timings->frame_length_lines =
((reg_table[j].val << 8) |
(timings->frame_length_lines & 0xff));
break;
case SC031GS_TIMING_VTS_LOW_REG:
timings->frame_length_lines =
(reg_table[j].val |
(timings->frame_length_lines & 0xff00));
break;
case SC031GS_TIMING_HTS_HIGH_REG:
if (timings->line_length_pck & 0xff00)
timings->line_length_pck = 0;
timings->line_length_pck =
((reg_table[j].val << 8) |
timings->line_length_pck);
break;
case SC031GS_TIMING_HTS_LOW_REG:
timings->line_length_pck =
(reg_table[j].val |
(timings->line_length_pck & 0xff00));
break;
case SC031GS_HORIZONTAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_width =
((reg_table[j].val << 8) |
(timings->sensor_output_width & 0xff));
break;
case SC031GS_HORIZONTAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_width =
(reg_table[j].val |
(timings->sensor_output_width & 0xff00));
break;
case SC031GS_VERTICAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_height =
((reg_table[j].val << 8) |
(timings->sensor_output_height & 0xff));
break;
case SC031GS_VERTICAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_height =
(reg_table[j].val |
(timings->sensor_output_height & 0xff00));
break;
}
}
timings->crop_horizontal_start += win_h_off;
timings->crop_horizontal_end -= win_h_off;
timings->crop_vertical_start += win_v_off;
timings->crop_vertical_end -= win_v_off;
timings->exp_time = timings->exp_time >> 4;
timings->vt_pix_clk_freq_hz =
config->frm_intrvl.interval.denominator
* timings->frame_length_lines
* timings->line_length_pck;
timings->coarse_integration_time_min =
SC031GS_COARSE_INTG_TIME_MIN;
timings->coarse_integration_time_max_margin =
SC031GS_COARSE_INTG_TIME_MAX_MARGIN;
/* OV Sensor do not use fine integration time. */
timings->fine_integration_time_min =
SC031GS_FINE_INTG_TIME_MIN;
timings->fine_integration_time_max_margin =
SC031GS_FINE_INTG_TIME_MAX_MARGIN;
}
return 0;
}
static int sc031gs_g_timings(struct sc_camera_module *cam_mod,
struct sc_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid)
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
else
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc031gs_s_ctrl(struct sc_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
sc_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
ret = sc031gs_write_aec(cam_mod);
break;
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
case V4L2_CID_FOCUS_ABSOLUTE:
/* todo*/
break;
/*
*case RK_V4L2_CID_AUTO_FPS:
* if (cam_mod->auto_adjust_fps)
* ret = sc031gs_auto_adjust_fps(
*cam_mod,
*cam_mod->exp_config.exp_time);
*break;
*/
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc031gs_s_ext_ctrls(struct sc_camera_module *cam_mod,
struct sc_camera_module_ext_ctrls *ctrls)
{
int ret = 0;
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = sc031gs_write_aec(cam_mod);
else
ret = -EINVAL;
if (IS_ERR_VALUE(ret))
sc_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc031gs_start_streaming(struct sc_camera_module *cam_mod)
{
int ret = 0;
sc_camera_module_pr_info(cam_mod, "active config=%s\n",
cam_mod->active_config->name);
ret = sc031gs_g_vts(cam_mod, &cam_mod->vts_min);
if (IS_ERR_VALUE(ret))
goto err;
ret = sc_camera_module_write_reg(cam_mod, 0x0100, 0x01);
if (IS_ERR_VALUE(ret))
goto err;
return 0;
err:
sc_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
static int sc031gs_stop_streaming(struct sc_camera_module *cam_mod)
{
int ret = 0;
sc_camera_module_pr_info(cam_mod, "\n");
ret = sc_camera_module_write_reg(cam_mod, 0x0100, 0x00);
if (IS_ERR_VALUE(ret))
goto err;
return 0;
err:
sc_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
static int sc031gs_check_camera_id(struct sc_camera_module *cam_mod)
{
u32 pidh, pidl;
int ret = 0;
sc_camera_module_pr_debug(cam_mod, "\n");
ret |= sc_camera_module_read_reg(cam_mod, 1, SC031GS_PIDH_ADDR, &pidh);
ret |= sc_camera_module_read_reg(cam_mod, 1, SC031GS_PIDL_ADDR, &pidl);
if (IS_ERR_VALUE(ret)) {
sc_camera_module_pr_err(cam_mod,
"register read failed, camera module powered off?\n");
goto err;
}
if (pidh == SC031GS_PIDH_MAGIC && pidl == SC031GS_PIDL_MAGIC) {
sc_camera_module_pr_info(cam_mod,
"successfully detected camera ID 0x%02x%02x\n",
pidh, pidl);
} else {
sc_camera_module_pr_err(cam_mod,
"wrong camera ID, expected 0x%02x%02x, detected 0x%02x%02x\n",
SC031GS_PIDH_MAGIC, SC031GS_PIDL_MAGIC, pidh, pidl);
ret = -EINVAL;
goto err;
}
return 0;
err:
sc_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
static struct v4l2_subdev_core_ops sc031gs_camera_module_core_ops = {
.g_ctrl = sc_camera_module_g_ctrl,
.s_ctrl = sc_camera_module_s_ctrl,
.s_ext_ctrls = sc_camera_module_s_ext_ctrls,
.s_power = sc_camera_module_s_power,
.ioctl = sc_camera_module_ioctl
};
static struct v4l2_subdev_video_ops sc031gs_camera_module_video_ops = {
.s_frame_interval = sc_camera_module_s_frame_interval,
.g_frame_interval = sc_camera_module_g_frame_interval,
.s_stream = sc_camera_module_s_stream
};
static struct v4l2_subdev_pad_ops sc031gs_camera_module_pad_ops = {
.enum_frame_interval = sc_camera_module_enum_frameintervals,
.get_fmt = sc_camera_module_g_fmt,
.set_fmt = sc_camera_module_s_fmt,
};
static struct v4l2_subdev_ops sc031gs_camera_module_ops = {
.core = &sc031gs_camera_module_core_ops,
.video = &sc031gs_camera_module_video_ops,
.pad = &sc031gs_camera_module_pad_ops,
};
static struct sc_camera_module_custom_config sc031gs_custom_config = {
.start_streaming = sc031gs_start_streaming,
.stop_streaming = sc031gs_stop_streaming,
.s_ctrl = sc031gs_s_ctrl,
.g_ctrl = sc031gs_g_ctrl,
.s_ext_ctrls = sc031gs_s_ext_ctrls,
.g_timings = sc031gs_g_timings,
.set_flip = sc031gs_set_flip,
.s_vts = sc031gs_auto_adjust_fps,
.check_camera_id = sc031gs_check_camera_id,
.configs = sc031gs_configs,
.num_configs = ARRAY_SIZE(sc031gs_configs),
.power_up_delays_ms = {5, 30, 30},
/*
*0: Exposure time valid fields;
*1: Exposure gain valid fields;
*(2 fields == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int sc031gs_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
dev_info(&client->dev, "probing...\n");
sc031gs_filltimings(&sc031gs_custom_config);
v4l2_i2c_subdev_init(&sc031gs.sd, client,
&sc031gs_camera_module_ops);
sc031gs.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sc031gs.custom = sc031gs_custom_config;
mutex_init(&sc031gs.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
static int sc031gs_remove(struct i2c_client *client)
{
struct sc_camera_module *cam_mod = i2c_get_clientdata(client);
dev_info(&client->dev, "removing device...\n");
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
sc_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");
return 0;
}
static const struct i2c_device_id sc031gs_id[] = {
{ SC031GS_DRIVER_NAME, 0 },
{ }
};
static const struct of_device_id sc031gs_of_match[] = {
{.compatible = "smartsens,sc031gs-v4l2-i2c-subdev"},
{},
};
MODULE_DEVICE_TABLE(i2c, sc031gs_id);
static struct i2c_driver sc031gs_i2c_driver = {
.driver = {
.name = SC031GS_DRIVER_NAME,
.of_match_table = sc031gs_of_match
},
.probe = sc031gs_probe,
.remove = sc031gs_remove,
.id_table = sc031gs_id,
};
module_i2c_driver(sc031gs_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for sc031gs");
MODULE_AUTHOR("zack.zeng");
MODULE_LICENSE("GPL");

View File

@@ -1,844 +0,0 @@
/*
* sc2232 sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
* Note:
*
*v0.1.0:
*1. Initialize version;
*
*/
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf-core.h>
#include <linux/slab.h>
#include <media/v4l2-controls_rockchip.h>
#include "sc_camera_module.h"
#define SC2232_DRIVER_NAME "sc2232"
#define SC2232_AEC_PK_LONG_GAIN_HIGH_REG 0x3e08
#define SC2232_AEC_PK_LONG_GAIN_LOW_REG 0x3e09
#define SC2232_AEC_PK_LONG_EXPO_HIGH_REG 0x3e01
#define SC2232_AEC_PK_LONG_EXPO_LOW_REG 0x3e02
#define SC2232_AEC_GROUP_UPDATE_ADDRESS 0x3812
#define SC2232_AEC_GROUP_UPDATE_START_DATA 0x00
#define SC2232_AEC_GROUP_UPDATE_END_DATA 0x30
#define SC2232_PIDH_ADDR 0x3107
#define SC2232_PIDL_ADDR 0x3108
/* High byte of product ID */
#define SC2232_PIDH_MAGIC 0x22
/* Low byte of product ID */
#define SC2232_PIDL_MAGIC 0x32
#define SC2232_EXT_CLK 24000000
#define SC2232_TIMING_VTS_HIGH_REG 0x320e
#define SC2232_TIMING_VTS_LOW_REG 0x320f
#define SC2232_TIMING_HTS_HIGH_REG 0x320c
#define SC2232_TIMING_HTS_LOW_REG 0x320d
#define SC2232_FINE_INTG_TIME_MIN 0
#define SC2232_FINE_INTG_TIME_MAX_MARGIN 0
#define SC2232_COARSE_INTG_TIME_MIN 1
#define SC2232_COARSE_INTG_TIME_MAX_MARGIN 4
#define SC2232_HORIZONTAL_OUTPUT_SIZE_HIGH_REG 0x3208
#define SC2232_HORIZONTAL_OUTPUT_SIZE_LOW_REG 0x3209
#define SC2232_VERTICAL_OUTPUT_SIZE_HIGH_REG 0x320a
#define SC2232_VERTICAL_OUTPUT_SIZE_LOW_REG 0x320b
#define SC2232_MIRROR_FILP 0x3221
static struct sc_camera_module sc2232;
/* ======================================================================== */
/* Base sensor configs */
/* ======================================================================== */
/* MCLK:24MHz 1920x1080 30fps mipi 2lane 10bit 390Mbps/lane */
static struct sc_camera_module_reg sc2232_init_tab_1920_1080_30fps[] = {
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x0100, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3001, 0xfe},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3018, 0x33},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3031, 0x0a},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3034, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3035, 0x9b},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3037, 0x20},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3038, 0xff},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3039, 0x54},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x303a, 0xb3},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x303b, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x303c, 0x0e},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320c, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320d, 0x20},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320e, 0x04},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x320f, 0xe2},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3211, 0x0c},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3213, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3222, 0x29},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3235, 0x09},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3236, 0xc2},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3301, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3302, 0x1f},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3303, 0x20},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3306, 0x48},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3308, 0x10},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3309, 0x60},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x330b, 0xd3},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x330e, 0x30},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3314, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x331b, 0x83},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x331e, 0x19},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x331f, 0x59},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3320, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3326, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3333, 0x30},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x335e, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x335f, 0x03},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3366, 0x7c},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3367, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3368, 0x04},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3369, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x336a, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x336b, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x337c, 0x04},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x337d, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x337f, 0x03},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x33a0, 0x05},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x33aa, 0x10},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x360f, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3620, 0x28},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3621, 0x28},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3622, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3624, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3625, 0x02},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3630, 0x1c},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3631, 0x84},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3632, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3633, 0x4f},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3635, 0xa0},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3636, 0x25},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3637, 0x59},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3638, 0x1f},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3639, 0x09},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x363b, 0x0b},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x363c, 0x05},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x366e, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x366f, 0x2f},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3670, 0x0c},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3671, 0xc6},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3672, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3673, 0x16},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3677, 0x84},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3678, 0x88},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3679, 0x88},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x367a, 0x28},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x367b, 0x3f},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x367e, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x367f, 0x28},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3690, 0x34},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3691, 0x11},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3692, 0x42},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x369c, 0x08},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x369d, 0x28},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3802, 0x01},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3901, 0x02},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3902, 0x45},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3905, 0x98},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3907, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3908, 0x11},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x391b, 0x80},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e00, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e01, 0x8c},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e02, 0xa0},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e03, 0x03},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e06, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e07, 0x80},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e08, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e09, 0x10},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3e1e, 0x34},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3f00, 0x07},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3f04, 0x03},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x3f05, 0xec},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x4603, 0x00},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x4827, 0x48},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x4837, 0x34},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x5000, 0x06},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x5780, 0xff},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x5781, 0x04},
{SC_CAMERA_MODULE_REG_TYPE_DATA, 0x5785, 0x18},
};
/* ======================================================================== */
static struct sc_camera_module_config sc2232_configs[] = {
{
.name = "1920x1080_30fps",
.frm_fmt = {
.width = 1920,
.height = 1080,
.code = MEDIA_BUS_FMT_SBGGR10_1X10
},
.frm_intrvl = {
.interval = {
.numerator = 1,
.denominator = 30
}
},
.auto_exp_enabled = false,
.auto_gain_enabled = false,
.auto_wb_enabled = false,
.reg_table = (void *)sc2232_init_tab_1920_1080_30fps,
.reg_table_num_entries =
ARRAY_SIZE(sc2232_init_tab_1920_1080_30fps),
.v_blanking_time_us = 3078,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 390, SC2232_EXT_CLK)
}
};
static int sc2232_set_flip(struct sc_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len)
{
int i, mode = 0;
u16 orientation = 0;
mode = sc_camera_module_get_flip_mirror(cam_mod);
if (mode == -1) {
sc_camera_module_pr_debug(cam_mod,
"dts don't set flip, return!\n");
return 0;
}
if (!IS_ERR_OR_NULL(cam_mod->active_config)) {
if (mode == SC_MIRROR_BIT_MASK)
orientation |= 0x06;
if (mode == SC_FLIP_BIT_MASK)
orientation |= 0x60;
for (i = 0; i < len; i++) {
if (reglist[i].reg == SC2232_MIRROR_FILP)
reglist[i].val = orientation;
}
}
return 0;
}
static int SC2232_g_VTS(struct sc_camera_module *cam_mod, u32 *vts)
{
u32 msb, lsb;
int ret;
ret = sc_camera_module_read_reg_table(cam_mod,
SC2232_TIMING_VTS_HIGH_REG,
&msb);
if (IS_ERR_VALUE(ret))
goto err;
ret = sc_camera_module_read_reg_table(cam_mod,
SC2232_TIMING_VTS_LOW_REG,
&lsb);
if (IS_ERR_VALUE(ret))
goto err;
*vts = (msb << 8) | lsb;
return 0;
err:
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc2232_auto_adjust_fps(struct sc_camera_module *cam_mod,
u32 exp_time)
{
int ret;
u32 vts;
exp_time = exp_time << 1;
if ((exp_time + SC2232_COARSE_INTG_TIME_MAX_MARGIN) >
2 * cam_mod->vts_min)
vts = (exp_time + SC2232_COARSE_INTG_TIME_MAX_MARGIN) >> 1;
else
vts = cam_mod->vts_min;
ret = sc_camera_module_write_reg(cam_mod,
SC2232_TIMING_VTS_LOW_REG,
vts & 0xFF);
ret |= sc_camera_module_write_reg(cam_mod,
SC2232_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
sc_camera_module_pr_info(cam_mod,
"updated vts = 0x%x,vts_min=0x%x\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int sc2232_set_vts(struct sc_camera_module *cam_mod,
u32 vts)
{
int ret = 0;
if (vts <= cam_mod->vts_min)
return ret;
ret = sc_camera_module_write_reg(cam_mod,
SC2232_TIMING_VTS_LOW_REG,
vts & 0xFF);
ret |= sc_camera_module_write_reg(cam_mod,
SC2232_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret)) {
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
sc_camera_module_pr_info(cam_mod,
"updated vts = 0x%x,vts_min=0x%x\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
static int sc2232_write_aec(struct sc_camera_module *cam_mod)
{
int ret = 0;
sc_camera_module_pr_debug(cam_mod,
"exp_time = %d lines, gain = %d, flash_mode = %d\n",
cam_mod->exp_config.exp_time,
cam_mod->exp_config.gain,
cam_mod->exp_config.flash_mode);
/*
* if the sensor is already streaming, write to shadow registers,
* if the sensor is in SW standby, write to active registers,
* if the sensor is off/registers are not writeable, do nothing
*/
if (cam_mod->state == SC_CAMERA_MODULE_SW_STANDBY ||
cam_mod->state == SC_CAMERA_MODULE_STREAMING) {
u32 a_gain = cam_mod->exp_config.gain;
u32 exp_time = cam_mod->exp_config.exp_time;
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
if (!IS_ERR_VALUE(ret) && cam_mod->auto_adjust_fps)
ret |= sc2232_auto_adjust_fps(cam_mod,
cam_mod->exp_config.exp_time);
if (a_gain > 0xf04)
a_gain = 0xf04;
exp_time = exp_time << 1;
if (exp_time > 0xfff)
exp_time = 0xfff;
/* hold reg start */
mutex_lock(&cam_mod->lock);
ret = sc_camera_module_write_reg(cam_mod,
SC2232_AEC_GROUP_UPDATE_ADDRESS,
SC2232_AEC_GROUP_UPDATE_START_DATA);
ret |= sc_camera_module_write_reg(cam_mod,
SC2232_AEC_PK_LONG_GAIN_HIGH_REG,
(a_gain >> 8) & 0xff);
ret |= sc_camera_module_write_reg(cam_mod,
SC2232_AEC_PK_LONG_GAIN_LOW_REG,
a_gain & 0xff);
if (a_gain < 0x20) {//1x~2x
ret |= sc_camera_module_write_reg(cam_mod,
0x3301, 0x06);
ret |= sc_camera_module_write_reg(cam_mod,
0x3306, 0x48);
ret |= sc_camera_module_write_reg(cam_mod,
0x3632, 0x08);
} else if (a_gain < 0x40) {//2x~4x
ret |= sc_camera_module_write_reg(cam_mod,
0x3301, 0x14);
ret |= sc_camera_module_write_reg(cam_mod,
0x3306, 0x48);
ret |= sc_camera_module_write_reg(cam_mod,
0x3632, 0x08);
} else if (a_gain < 0x80) {//4x~8x
ret |= sc_camera_module_write_reg(cam_mod,
0x3301, 0x18);
ret |= sc_camera_module_write_reg(cam_mod,
0x3306, 0x48);
ret |= sc_camera_module_write_reg(cam_mod,
0x3632, 0x08);
} else if (a_gain < 0xf8) {//8x~15.5x
ret |= sc_camera_module_write_reg(cam_mod,
0x3301, 0x13);
ret |= sc_camera_module_write_reg(cam_mod,
0x3306, 0x48);
ret |= sc_camera_module_write_reg(cam_mod,
0x3632, 0x08);
} else if (a_gain < 0x1f0) {//15.5x~31x
ret |= sc_camera_module_write_reg(cam_mod,
0x3301, 0xc5);
ret |= sc_camera_module_write_reg(cam_mod,
0x3306, 0x78);
ret |= sc_camera_module_write_reg(cam_mod,
0x3632, 0x48);
} else {//31x~
ret |= sc_camera_module_write_reg(cam_mod,
0x3301, 0xc5);
ret |= sc_camera_module_write_reg(cam_mod,
0x3306, 0x78);
ret |= sc_camera_module_write_reg(cam_mod,
0x3632, 0x78);
}
ret |= sc_camera_module_write_reg(cam_mod,
SC2232_AEC_PK_LONG_EXPO_HIGH_REG,
(exp_time >> 4) & 0xff);
ret |= sc_camera_module_write_reg(cam_mod,
SC2232_AEC_PK_LONG_EXPO_LOW_REG,
(exp_time & 0xff) << 4);
if (!cam_mod->auto_adjust_fps)
ret |= sc2232_set_vts(cam_mod,
cam_mod->exp_config.vts_value);
/* hold reg end */
ret |= sc_camera_module_write_reg(cam_mod,
SC2232_AEC_GROUP_UPDATE_ADDRESS,
SC2232_AEC_GROUP_UPDATE_END_DATA);
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc2232_g_ctrl(struct sc_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
sc_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
sc_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
static int sc2232_filltimings(struct sc_camera_module_custom_config *custom)
{
int i, j;
u32 win_h_off = 0, win_v_off = 0;
struct sc_camera_module_config *config;
struct sc_camera_module_timings *timings;
struct sc_camera_module_reg *reg_table;
int reg_table_num_entries;
for (i = 0; i < custom->num_configs; i++) {
config = &custom->configs[i];
reg_table = config->reg_table;
reg_table_num_entries = config->reg_table_num_entries;
timings = &config->timings;
memset(timings, 0x00, sizeof(*timings));
for (j = 0; j < reg_table_num_entries; j++) {
switch (reg_table[j].reg) {
case SC2232_TIMING_VTS_HIGH_REG:
if (timings->frame_length_lines & 0xff00)
timings->frame_length_lines = 0;
timings->frame_length_lines =
((reg_table[j].val << 8) |
(timings->frame_length_lines & 0xff));
break;
case SC2232_TIMING_VTS_LOW_REG:
timings->frame_length_lines =
(reg_table[j].val |
(timings->frame_length_lines & 0xff00));
break;
case SC2232_TIMING_HTS_HIGH_REG:
if (timings->line_length_pck & 0xff00)
timings->line_length_pck = 0;
timings->line_length_pck =
((reg_table[j].val << 8) |
timings->line_length_pck);
break;
case SC2232_TIMING_HTS_LOW_REG:
timings->line_length_pck =
(reg_table[j].val |
(timings->line_length_pck & 0xff00));
break;
case SC2232_HORIZONTAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_width =
((reg_table[j].val << 8) |
(timings->sensor_output_width & 0xff));
break;
case SC2232_HORIZONTAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_width =
(reg_table[j].val |
(timings->sensor_output_width & 0xff00));
break;
case SC2232_VERTICAL_OUTPUT_SIZE_HIGH_REG:
timings->sensor_output_height =
((reg_table[j].val << 8) |
(timings->sensor_output_height & 0xff));
break;
case SC2232_VERTICAL_OUTPUT_SIZE_LOW_REG:
timings->sensor_output_height =
(reg_table[j].val |
(timings->sensor_output_height & 0xff00));
break;
}
}
timings->crop_horizontal_start += win_h_off;
timings->crop_horizontal_end -= win_h_off;
timings->crop_vertical_start += win_v_off;
timings->crop_vertical_end -= win_v_off;
timings->vt_pix_clk_freq_hz =
config->frm_intrvl.interval.denominator
* timings->frame_length_lines
* timings->line_length_pck;
timings->coarse_integration_time_min =
SC2232_COARSE_INTG_TIME_MIN;
timings->coarse_integration_time_max_margin =
SC2232_COARSE_INTG_TIME_MAX_MARGIN;
/* OV Sensor do not use fine integration time. */
timings->fine_integration_time_min =
SC2232_FINE_INTG_TIME_MIN;
timings->fine_integration_time_max_margin =
SC2232_FINE_INTG_TIME_MAX_MARGIN;
}
return 0;
}
/*--------------------------------------------------------------------------*/
static int sc2232_g_timings(struct sc_camera_module *cam_mod,
struct sc_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid) {
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
} else {
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator
* vts
* timings->line_length_pck;
}
timings->frame_length_lines = vts;
return ret;
err:
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int sc2232_s_ctrl(struct sc_camera_module *cam_mod, u32 ctrl_id)
{
int ret = 0;
sc_camera_module_pr_debug(cam_mod, "\n");
switch (ctrl_id) {
case V4L2_CID_GAIN:
case V4L2_CID_EXPOSURE:
ret = sc2232_write_aec(cam_mod);
break;
case V4L2_CID_FLASH_LED_MODE:
/* nothing to be done here */
break;
case V4L2_CID_FOCUS_ABSOLUTE:
/* todo*/
break;
/*
* case RK_V4L2_CID_FPS_CTRL:
* if (cam_mod->auto_adjust_fps)
* ret = OV2740_auto_adjust_fps(
* cam_mod,
* cam_mod->exp_config.exp_time);
* break;
*/
default:
ret = -EINVAL;
break;
}
if (IS_ERR_VALUE(ret))
sc_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int sc2232_s_ext_ctrls(struct sc_camera_module *cam_mod,
struct sc_camera_module_ext_ctrls *ctrls)
{
int ret = 0;
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = sc2232_write_aec(cam_mod);
else
ret = -EINVAL;
if (IS_ERR_VALUE(ret))
sc_camera_module_pr_debug(cam_mod,
"failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int sc2232_start_streaming(struct sc_camera_module *cam_mod)
{
int ret = 0;
sc_camera_module_pr_info(cam_mod, "active config=%s\n",
cam_mod->active_config->name);
ret = SC2232_g_VTS(cam_mod, &cam_mod->vts_min);
if (IS_ERR_VALUE(ret))
goto err;
mutex_lock(&cam_mod->lock);
ret = sc_camera_module_write_reg(cam_mod, 0x0100, 0x01);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
return 0;
err:
sc_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int sc2232_stop_streaming(struct sc_camera_module *cam_mod)
{
int ret = 0;
sc_camera_module_pr_info(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = sc_camera_module_write_reg(cam_mod, 0x0100, 0x00);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
return 0;
err:
sc_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/*--------------------------------------------------------------------------*/
static int sc2232_check_camera_id(struct sc_camera_module *cam_mod)
{
u32 pidh, pidl;
int ret = 0;
sc_camera_module_pr_debug(cam_mod, "\n");
ret |= sc_camera_module_read_reg(cam_mod, 1,
SC2232_PIDH_ADDR, &pidh);
ret |= sc_camera_module_read_reg(cam_mod, 1,
SC2232_PIDL_ADDR, &pidl);
if (IS_ERR_VALUE(ret)) {
sc_camera_module_pr_err(cam_mod,
"register read failed, camera module powered off?\n");
goto err;
}
if (pidh == SC2232_PIDH_MAGIC && pidl == SC2232_PIDL_MAGIC) {
sc_camera_module_pr_info(cam_mod,
"successfully detected camera ID 0x%02x%02x\n",
pidh, pidl);
} else {
sc_camera_module_pr_err(cam_mod,
"wrong camera ID, expected 0x%02x%02x, detected 0x%02x%02x\n",
SC2232_PIDH_MAGIC, SC2232_PIDL_MAGIC, pidh, pidl);
ret = -EINVAL;
goto err;
}
return 0;
err:
sc_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
return ret;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
static struct v4l2_subdev_core_ops sc2232_camera_module_core_ops = {
.g_ctrl = sc_camera_module_g_ctrl,
.s_ctrl = sc_camera_module_s_ctrl,
.s_ext_ctrls = sc_camera_module_s_ext_ctrls,
.s_power = sc_camera_module_s_power,
.ioctl = sc_camera_module_ioctl
};
static struct v4l2_subdev_video_ops sc2232_camera_module_video_ops = {
.s_frame_interval = sc_camera_module_s_frame_interval,
.g_frame_interval = sc_camera_module_g_frame_interval,
.s_stream = sc_camera_module_s_stream
};
static struct v4l2_subdev_pad_ops sc2232_camera_module_pad_ops = {
.enum_frame_interval = sc_camera_module_enum_frameintervals,
.get_fmt = sc_camera_module_g_fmt,
.set_fmt = sc_camera_module_s_fmt,
};
static struct v4l2_subdev_ops sc2232_camera_module_ops = {
.core = &sc2232_camera_module_core_ops,
.video = &sc2232_camera_module_video_ops,
.pad = &sc2232_camera_module_pad_ops
};
static struct sc_camera_module_custom_config sc2232_custom_config = {
.start_streaming = sc2232_start_streaming,
.stop_streaming = sc2232_stop_streaming,
.s_ctrl = sc2232_s_ctrl,
.g_ctrl = sc2232_g_ctrl,
.s_ext_ctrls = sc2232_s_ext_ctrls,
.g_timings = sc2232_g_timings,
.s_vts = sc2232_auto_adjust_fps,
.set_flip = sc2232_set_flip,
.check_camera_id = sc2232_check_camera_id,
.configs = sc2232_configs,
.num_configs = ARRAY_SIZE(sc2232_configs),
.power_up_delays_ms = {5, 30, 30},
.exposure_valid_frame = {4, 4}
};
static int sc2232_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
dev_info(&client->dev, "probing...\n");
sc2232_filltimings(&sc2232_custom_config);
v4l2_i2c_subdev_init(&sc2232.sd, client,
&sc2232_camera_module_ops);
sc2232.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sc2232.custom = sc2232_custom_config;
mutex_init(&sc2232.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
/* ======================================================================== */
static int sc2232_remove(struct i2c_client *client)
{
struct sc_camera_module *cam_mod = i2c_get_clientdata(client);
dev_info(&client->dev, "removing device...\n");
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
sc_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");
return 0;
}
static const struct i2c_device_id sc2232_id[] = {
{ SC2232_DRIVER_NAME, 0 },
{ }
};
static const struct of_device_id sc2232_of_match[] = {
{.compatible = "smartsens,sc2232-v4l2-i2c-subdev"},
{},
};
MODULE_DEVICE_TABLE(i2c, sc2232_id);
static struct i2c_driver sc2232_i2c_driver = {
.driver = {
.name = SC2232_DRIVER_NAME,
.of_match_table = sc2232_of_match
},
.probe = sc2232_probe,
.remove = sc2232_remove,
.id_table = sc2232_id,
};
module_i2c_driver(sc2232_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for sc2232");
MODULE_AUTHOR("zack.zeng");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@@ -1,281 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* sc_camera_module.h
*
* Generic omnivision sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
*/
#ifndef SC_CAMERA_MODULE_H
#define SC_CAMERA_MODULE_H
#include <linux/workqueue.h>
#include <linux/platform_data/rk_isp10_platform_camera_module.h>
#include <linux/platform_data/rk_isp10_platform.h>
/*
* TODO: references to v4l2 should be reomved from here and go into a
* platform dependent wrapper
*/
#define SC_CAMERA_MODULE_REG_TYPE_DATA PLTFRM_CAMERA_MODULE_REG_TYPE_DATA
#define SC_CAMERA_MODULE_REG_TYPE_TIMEOUT PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define sc_camera_module_csi_config
#define sc_camera_module_reg pltfrm_camera_module_reg
#define SC_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define SC_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define SC_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define SC_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
#define SC_CAMERA_MODULE_CTRL_UPDT_WB_TEMPERATURE 0x04
#define SC_CAMERA_MODULE_CTRL_UPDT_AUTO_WB 0x08
#define SC_CAMERA_MODULE_CTRL_UPDT_AUTO_GAIN 0x10
#define SC_CAMERA_MODULE_CTRL_UPDT_AUTO_EXP 0x20
#define SC_CAMERA_MODULE_CTRL_UPDT_FOCUS_ABSOLUTE 0x40
#define SC_CAMERA_MODULE_CTRL_UPDT_PRESET_WB 0x80
#define SC_CAMERA_MODULE_CTRL_UPDT_VTS_VALUE 0x100
enum sc_camera_module_state {
SC_CAMERA_MODULE_POWER_OFF = 0,
SC_CAMERA_MODULE_HW_STANDBY = 1,
SC_CAMERA_MODULE_SW_STANDBY = 2,
SC_CAMERA_MODULE_STREAMING = 3
};
struct sc_camera_module;
struct sc_camera_module_timings {
/* public */
u32 coarse_integration_time_min;
u32 coarse_integration_time_max_margin;
u32 fine_integration_time_min;
u32 fine_integration_time_max_margin;
u32 frame_length_lines;
u32 line_length_pck;
u32 vt_pix_clk_freq_hz;
u32 sensor_output_width;
u32 sensor_output_height;
u32 crop_horizontal_start; /* Sensor crop start cord. (x0,y0) */
u32 crop_vertical_start;
u32 crop_horizontal_end; /* Sensor crop end cord. (x1,y1) */
u32 crop_vertical_end;
u8 binning_factor_x;
u8 binning_factor_y;
u32 exp_time;
u32 gain;
};
struct sc_camera_module_config {
const char *name;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
u8 auto_exp_enabled;
u8 auto_gain_enabled;
u8 auto_wb_enabled;
struct sc_camera_module_reg *reg_table;
u32 reg_table_num_entries;
struct sc_camera_module_reg *reg_diff_table;
u32 reg_diff_table_num_entries;
u32 v_blanking_time_us;
u32 line_length_pck;
u32 frame_length_lines;
struct sc_camera_module_timings timings;
u8 soft_reset;
u8 ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
struct sc_camera_module_exp_config {
s32 exp_time;
u8 auto_exp;
u16 gain;
u16 gain_percent;
u8 auto_gain;
enum v4l2_flash_led_mode flash_mode;
u32 vts_value;
};
struct sc_camera_module_wb_config {
u32 temperature;
u32 preset_id;
u8 auto_wb;
};
struct sc_camera_module_af_config {
u32 abs_pos;
u32 rel_pos;
};
struct sc_camera_module_ext_ctrl {
/* public */
u32 id;
u32 value;
__u32 reserved2[1];
};
struct sc_camera_module_ext_ctrls {
/* public */
u32 count;
struct sc_camera_module_ext_ctrl *ctrls;
};
/*
* start_streaming: (mandatory) will be called when sensor should be
* put into streaming mode right after the base config has been
* written to the sensor. After a successful call of this function
* the sensor should start delivering frame data.
*
* stop_streaming: (mandatory) will be called when sensor should stop
* delivering data. After a successful call of this function the
* sensor should not deliver any more frame data.
*
* check_camera_id: (optional) will be called when the sensor is
* powered on. If provided should check the sensor ID/version
* required by the custom driver. Register access should be
* possible when this function is invoked.
*
* s_ctrl: (mandatory) will be called at the successful end of
* sc_camera_module_s_ctrl with the ctrl_id as argument.
*
* priv: (optional) for private data used by the custom driver.
*/
struct sc_camera_module_custom_config {
int (*start_streaming)(struct sc_camera_module *cam_mod);
int (*stop_streaming)(struct sc_camera_module *cam_mod);
int (*check_camera_id)(struct sc_camera_module *cam_mod);
int (*s_ctrl)(struct sc_camera_module *cam_mod, u32 ctrl_id);
int (*g_ctrl)(struct sc_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct sc_camera_module *cam_mod,
struct sc_camera_module_timings *timings);
int (*s_vts)(struct sc_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct sc_camera_module *cam_mod,
struct sc_camera_module_ext_ctrls *ctrls);
int (*set_flip)(struct sc_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len);
int (*init_common)(struct sc_camera_module *cam_mod);
int (*read_otp)(struct sc_camera_module *cam_mod);
struct sc_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
struct sc_camera_module_otp_work {
struct work_struct work;
struct workqueue_struct *wq;
void *cam_mod;
};
struct sc_camera_module {
/* public */
struct v4l2_subdev sd;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
struct sc_camera_module_exp_config exp_config;
struct sc_camera_module_wb_config wb_config;
struct sc_camera_module_af_config af_config;
struct sc_camera_module_custom_config custom;
enum sc_camera_module_state state;
enum sc_camera_module_state state_before_suspend;
struct sc_camera_module_config *active_config;
struct sc_camera_module_otp_work otp_work;
u32 ctrl_updt;
u32 vts_cur;
u32 vts_min;
u8 auto_adjust_fps;
u8 update_config;
u8 frm_fmt_valid;
u8 frm_intrvl_valid;
u8 hflip;
u8 vflip;
u8 flip_flg;
u32 rotation;
void *pltfm_data;
u8 inited;
int as_master;
struct mutex lock;
};
#define sc_camera_module_pr_info(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_info(&(cam_mod)->sd, fmt, ## arg)
#define sc_camera_module_pr_debug(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_debug(&(cam_mod)->sd, fmt, ## arg)
#define sc_camera_module_pr_warn(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_warn(&(cam_mod)->sd, fmt, ## arg)
#define sc_camera_module_pr_err(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_err(&(cam_mod)->sd, fmt, ## arg)
int sc_camera_module_write_reglist(struct sc_camera_module *cam_mod,
const struct sc_camera_module_reg reglist[],
int len);
int sc_camera_module_write_reg(struct sc_camera_module *cam_mod,
u16 reg,
u8 val);
int sc_camera_module_read_reg(struct sc_camera_module *cam_mod,
u16 data_length,
u16 reg,
u32 *val);
int sc_camera_module_read_reg_table(struct sc_camera_module *cam_mod,
u16 reg,
u32 *val);
int sc_camera_module_try_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt);
int sc_camera_module_s_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int sc_camera_module_g_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int sc_camera_module_s_frame_interval(struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int sc_camera_module_g_frame_interval(struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int sc_camera_module_s_stream(struct v4l2_subdev *sd,
int enable);
int sc_camera_module_s_power(struct v4l2_subdev *sd,
int on);
int sc_camera_module_g_ctrl(struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int sc_camera_module_s_ctrl(struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int sc_camera_module_s_ext_ctrls(struct v4l2_subdev *sd,
struct v4l2_ext_controls *ctrls);
int sc_camera_module_enum_frameintervals(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie);
int sc_camera_module_init(struct sc_camera_module *cam_mod,
struct sc_camera_module_custom_config *custom);
void sc_camera_module_release(struct sc_camera_module *cam_mod);
long sc_camera_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg);
int sc_camera_module_get_flip_mirror(struct sc_camera_module *cam_mod);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,336 +0,0 @@
/*
* tc_camera_module.h
*
* Generic toshiba sensor driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
* Copyright (C) 2012-2014 Intel Mobile Communications GmbH
*
* Copyright (C) 2008 Texas Instruments.
*
* Author:zhoupeng<benjo.zhou@rock-chips.com>
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef TC_CAMERA_MODULE_H
#define TC_CAMERA_MODULE_H
#include <linux/workqueue.h>
#include <linux/hdmi.h>
#include <linux/platform_data/rk_isp10_platform_camera_module.h>
#include <linux/platform_data/rk_isp10_platform.h>
/*
* TODO: references to v4l2 should be reomved from here and go into a
* platform dependent wrapper
*/
#define TC_CAMERA_MODULE_REG_TYPE_DATA PLTFRM_CAMERA_MODULE_REG_TYPE_DATA
#define TC_CAMERA_MODULE_REG_TYPE_TIMEOUT PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define TC_CAMERA_MOUDLE_REG_VALUE_LEN_8BIT 1
#define TC_CAMERA_MOUDLE_REG_VALUE_LEN_16BIT 2
#define TC_CAMERA_MOUDLE_REG_VALUE_LEN_32BIT 4
#define tc_camera_module_csi_config
#define TC_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define TC_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define TC_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define TC_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
#define TC_CAMERA_MODULE_CTRL_UPDT_WB_TEMPERATURE 0x04
#define TC_CAMERA_MODULE_CTRL_UPDT_AUTO_WB 0x08
#define TC_CAMERA_MODULE_CTRL_UPDT_AUTO_GAIN 0x10
#define TC_CAMERA_MODULE_CTRL_UPDT_AUTO_EXP 0x20
#define TC_CAMERA_MODULE_CTRL_UPDT_FOCUS_ABSOLUTE 0x40
#define TC_CAMERA_MODULE_CTRL_UPDT_PRESET_WB 0x80
#define TC_CAMERA_MODULE_CTRL_UPDT_VTS_VALUE 0x100
enum tc_camera_module_state {
TC_CAMERA_MODULE_POWER_OFF = 0,
TC_CAMERA_MODULE_HW_STANDBY = 1,
TC_CAMERA_MODULE_SW_STANDBY = 2,
TC_CAMERA_MODULE_STREAMING = 3
};
struct tc_camera_module;
struct tc_camera_module_reg {
u32 flag;
u16 reg;
u32 val;
u8 len;
};
struct tc_camera_module_timings {
/* public */
u32 coarse_integration_time_min;
u32 coarse_integration_time_max_margin;
u32 fine_integration_time_min;
u32 fine_integration_time_max_margin;
u32 frame_length_lines;
u32 line_length_pck;
u32 vt_pix_clk_freq_hz;
u32 sensor_output_width;
u32 sensor_output_height;
u32 crop_horizontal_start; /* Sensor crop start cord. (x0,y0) */
u32 crop_vertical_start;
u32 crop_horizontal_end; /* Sensor crop end cord. (x1,y1) */
u32 crop_vertical_end;
u8 binning_factor_x;
u8 binning_factor_y;
u32 exp_time;
u32 gain;
};
struct tc_camera_module_config {
const char *name;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
bool auto_exp_enabled;
bool auto_gain_enabled;
bool auto_wb_enabled;
struct tc_camera_module_reg *reg_table;
u32 reg_table_num_entries;
struct tc_camera_module_reg *reg_diff_table;
u32 reg_diff_table_num_entries;
u32 v_blanking_time_us;
u32 line_length_pck;
u32 frame_length_lines;
struct tc_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
struct tc_camera_module_exp_config {
s32 exp_time;
bool auto_exp;
u16 gain;
u16 gain_percent;
bool auto_gain;
enum v4l2_flash_led_mode flash_mode;
u32 vts_value;
};
struct tc_camera_module_wb_config {
u32 temperature;
u32 preset_id;
bool auto_wb;
};
struct tc_camera_module_af_config {
u32 abs_pos;
u32 rel_pos;
};
struct tc_camera_module_ext_ctrl {
/* public */
u32 id;
u32 value;
__u32 reserved2[1];
};
struct tc_camera_module_ext_ctrls {
/* public */
u32 count;
struct tc_camera_module_ext_ctrl *ctrls;
};
/*
* start_streaming: (mandatory) will be called when sensor should be
* put into streaming mode right after the base config has been
* written to the sensor. After a successful call of this function
* the sensor should start delivering frame data.
*
* stop_streaming: (mandatory) will be called when sensor should stop
* delivering data. After a successful call of this function the
* sensor should not deliver any more frame data.
*
* check_camera_id: (optional) will be called when the sensor is
* powered on. If prtcided should check the sensor ID/version
* required by the custom driver. Register access should be
* possible when this function is invoked.
*
* s_ctrl: (mandatory) will be called at the successful end of
* tc_camera_module_s_ctrl with the ctrl_id as argument.
*
* priv: (optional) for private data used by the custom driver.
*/
struct tc_camera_module_custom_config {
int (*check_camera_id)(struct tc_camera_module *cam_mod);
int (*s_ctrl)(struct tc_camera_module *cam_mod, u32 ctrl_id);
int (*g_ctrl)(struct tc_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct tc_camera_module *cam_mod,
struct tc_camera_module_timings *timings);
int (*s_vts)(struct tc_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct tc_camera_module *cam_mod,
struct tc_camera_module_ext_ctrls *ctrls);
int (*set_flip)(
struct tc_camera_module *cam_mod,
struct tc_camera_module_reg reglist[],
int len);
int (*init_common)(struct tc_camera_module *cam_mod);
int (*read_otp)(struct tc_camera_module *cam_mod);
int (*enable_stream)(struct tc_camera_module *cam_mod, bool enable);
int (*s_power)(struct tc_camera_module *cam_mod, bool enable);
struct tc_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
struct tc_camera_module_otp_work {
struct work_struct work;
struct workqueue_struct *wq;
void *cam_mod;
};
struct tc_camera_module {
/* public */
struct v4l2_subdev sd;
struct v4l2_mbus_framefmt frm_fmt;
struct v4l2_subdev_frame_interval frm_intrvl;
struct tc_camera_module_exp_config exp_config;
struct tc_camera_module_wb_config wb_config;
struct tc_camera_module_af_config af_config;
struct tc_camera_module_custom_config custom;
enum tc_camera_module_state state;
enum tc_camera_module_state state_before_suspend;
struct tc_camera_module_config *active_config;
struct tc_camera_module_otp_work otp_work;
u32 ctrl_updt;
u32 vts_cur;
u32 vts_min;
bool auto_adjust_fps;
bool update_config;
bool frm_fmt_valid;
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
struct mutex lock;
};
struct tc35x_priv {
struct regmap *regmap;
struct i2c_client *client;
struct device *dev;
struct gpio_desc *gpio_power;
struct gpio_desc *gpio_power18;
struct gpio_desc *gpio_power33;
struct gpio_desc *gpio_csi_ctl;
struct gpio_desc *gpio_reset;
struct gpio_desc *gpio_stanby;
struct gpio_desc *gpio_int;
};
#define tc_camera_module_pr_info(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_info(&(cam_mod)->sd, fmt, ## arg)
#define tc_camera_module_pr_debug(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_debug(&(cam_mod)->sd, fmt, ## arg)
#define tc_camera_module_pr_warn(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_warn(&(cam_mod)->sd, fmt, ## arg)
#define tc_camera_module_pr_err(cam_mod, fmt, arg...) \
pltfrm_camera_module_pr_err(&(cam_mod)->sd, fmt, ## arg)
int tc_camera_module_write8_reg(
struct tc_camera_module *cam_mod,
u16 reg,
u8 val);
int tc_camera_module_write16_reg(
struct tc_camera_module *cam_mod,
u16 reg,
u16 val);
int tc_camera_module_write32_reg(
struct tc_camera_module *cam_mod,
u16 reg,
u32 val);
u8 tc_camera_module_read8_reg(
struct tc_camera_module *cam_mod,
u16 reg);
u16 tc_camera_module_read16_reg(
struct tc_camera_module *cam_mod,
u16 reg);
u32 tc_camera_module_read32_reg(
struct tc_camera_module *cam_mod,
u16 reg);
int tc_camera_module_read_reg_table(
struct tc_camera_module *cam_mod,
u16 reg,
u32 *val);
int tc_camera_module_write_reglist(
struct tc_camera_module *cam_mod,
const struct tc_camera_module_reg reglist[],
int len);
int tc_camera_module_s_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int tc_camera_module_g_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int tc_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int tc_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int tc_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);
int tc_camera_module_s_power(
struct v4l2_subdev *sd,
int on);
int tc_camera_module_g_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int tc_camera_module_s_ctrl(
struct v4l2_subdev *sd,
struct v4l2_control *ctrl);
int tc_camera_module_s_ext_ctrls(
struct v4l2_subdev *sd,
struct v4l2_ext_controls *ctrls);
int tc_camera_module_enum_frameintervals(
struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie);
int tc_camera_module_init(
struct tc_camera_module *cam_mod,
struct tc_camera_module_custom_config *custom);
void tc_camera_module_release(
struct tc_camera_module *cam_mod);
long tc_camera_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg);
int tc_camera_module_get_flip_mirror(
struct tc_camera_module *cam_mod);
#endif

View File

@@ -1,169 +0,0 @@
/*
*************************************************************************
* Rockchip driver for CIF ISP 1.0
* (Based on Intel driver for sofiaxxx)
*
* Copyright (C) 2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*************************************************************************
*/
#ifndef PLATFORM_CAMERA_MODULE_H
#define PLATFORM_CAMERA_MODULE_H
#include <linux/videodev2.h>
#define PLTFRM_CAMERA_MODULE_REG_CODE_MASK 0xff
#define PLTFRM_CAMERA_MODULE_REG_LEN_BIT 8
#define PLTFRM_CAMERA_MODULE_REG_LEN_MASK (0x03 << PLTFRM_CAMERA_MODULE_REG_LEN_BIT)
#define PLTFRM_CAMERA_MODULE_REG_LEN(flag) \
(((flag & PLTFRM_CAMERA_MODULE_REG_LEN_MASK) >> PLTFRM_CAMERA_MODULE_REG_LEN_BIT) + 1)
#define PLTFRM_CAMERA_MODULE_DATA_LEN_BIT 10
#define PLTFRM_CAMERA_MODULE_DATA_LEN_MASK (0x03 << PLTFRM_CAMERA_MODULE_DATA_LEN_BIT)
#define PLTFRM_CAMERA_MODULE_DATA_LEN(flag) \
(((flag & PLTFRM_CAMERA_MODULE_DATA_LEN_MASK) >> PLTFRM_CAMERA_MODULE_DATA_LEN_BIT) + 1)
#define PLTFRM_CAMERA_MODULE_WR_CONTINUE_MASK 0x1000
#define PLTFRM_CAMERA_MODULE_WR_CONTINUE 0x0000
#define PLTFRM_CAMERA_MODULE_WR_SINGLE 0x1000
#define PLTFRM_CAMERA_MODULE_RD_CONTINUE_MASK 0x2000
#define PLTFRM_CAMERA_MODULE_RD_CONTINUE 0x2000
#define PLTFRM_CAMERA_MODULE_RD_SINGLE 0x0000
#define PLTFRM_CAMERA_MODULE_REG1_TYPE_DATA1 0x000
#define PLTFRM_CAMERA_MODULE_REG2_TYPE_DATA1 0x100
#define PLTFRM_CAMERA_MODULE_REG1_TYPE_DATA2 0x400
#define PLTFRM_CAMERA_MODULE_REG2_TYPE_DATA2 0x500
#define PLTFRM_CAMERA_MODULE_REG_TYPE_DATA PLTFRM_CAMERA_MODULE_REG2_TYPE_DATA1
#define PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT 0x01
#define PLTFRM_CAMERA_MODULE_REG_TYPE_DATA_SINGLE 0x1100
#define PLTFRM_CAMERA_MODULE_MIRROR_BIT 0
#define PLTFRM_CAMERA_MODULE_FLIP_BIT 1
#define PLTFRM_CAMERA_MODULE_IS_MIRROR(a) \
((a & PLTFRM_CAMERA_MODULE_MIRROR_BIT) == PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define PLTFRM_CAMERA_MODULE_IS_FLIP(a) \
((a & PLTFRM_CAMERA_MODULE_FLIP_BIT) == PLTFRM_CAMERA_MODULE_FLIP_BIT)
extern const char *PLTFRM_CAMERA_MODULE_PIN_PD;
extern const char *PLTFRM_CAMERA_MODULE_PIN_PWR;
extern const char *PLTFRM_CAMERA_MODULE_PIN_FLASH;
extern const char *PLTFRM_CAMERA_MODULE_PIN_TORCH;
extern const char *PLTFRM_CAMERA_MODULE_PIN_RESET;
extern const char *PLTFRM_CAMERA_MODULE_PIN_VSYNC;
enum pltfrm_camera_module_pin_state {
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE = 0,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE = 1
};
struct pltfrm_camera_module_reg {
u32 flag;
u16 reg;
u16 val;
};
struct pltfrm_camera_module_reg_table {
u32 reg_table_num_entries;
struct pltfrm_camera_module_reg *reg_table;
};
int pltfrm_camera_module_set_pm_state(
struct v4l2_subdev *sd,
int on);
int pltfrm_camera_module_set_pin_state(
struct v4l2_subdev *sd,
const char *pin,
enum pltfrm_camera_module_pin_state state);
int pltfrm_camera_module_get_pin_state(
struct v4l2_subdev *sd,
const char *pin);
int pltfrm_camera_module_s_power(
struct v4l2_subdev *sd,
int on);
int pltfrm_camera_module_patch_config(
struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *frm_fmt,
struct v4l2_subdev_frame_interval *frm_intrvl);
struct v4l2_subdev *pltfrm_camera_module_get_af_ctrl(
struct v4l2_subdev *sd);
struct v4l2_subdev *pltfrm_camera_module_get_fl_ctrl(
struct v4l2_subdev *sd);
char *pltfrm_camera_module_get_flash_driver_name(
struct v4l2_subdev *sd);
int pltfrm_camera_module_init(
struct v4l2_subdev *sd,
void **pldata);
void pltfrm_camera_module_release(
struct v4l2_subdev *sd);
int pltfrm_camera_module_read_reg(struct v4l2_subdev *sd,
u16 data_length,
u16 reg,
u32 *val);
int pltfrm_superpix_camera_module_read_reg(struct v4l2_subdev *sd,
u16 data_length,
u8 reg,
u8 *val);
int pltfrm_camera_module_write_reg(struct v4l2_subdev *sd,
u16 reg, u8 val);
int pltfrm_camera_module_read_reg_ex(struct v4l2_subdev *sd,
u16 data_length,
u32 flag,
u16 reg,
u32 *val);
int pltfrm_camera_module_write_reg_ex(struct v4l2_subdev *sd,
u32 flag, u16 reg, u16 val);
int pltfrm_camera_module_write_reglist(
struct v4l2_subdev *sd,
const struct pltfrm_camera_module_reg reglist[],
int len);
long pltfrm_camera_module_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg);
const char *pltfrm_dev_string(struct v4l2_subdev *sd);
int pltfrm_camera_module_get_flip_mirror(
struct v4l2_subdev *sd);
int pltfrm_camera_module_pix_fmt2csi2_dt(int src_pix_fmt);
#define pltfrm_camera_module_pr_debug(dev, fmt, arg...) \
pr_debug("%s.%s: " fmt, \
pltfrm_dev_string(dev), __func__, ## arg)
#define pltfrm_camera_module_pr_info(dev, fmt, arg...) \
pr_info("%s.%s: " fmt, \
pltfrm_dev_string(dev), __func__, ## arg)
#define pltfrm_camera_module_pr_warn(dev, fmt, arg...) \
pr_warn("%s.%s WARN: " fmt, \
pltfrm_dev_string(dev), __func__, ## arg)
#define pltfrm_camera_module_pr_err(dev, fmt, arg...) \
pr_err("%s.%s(%d) ERR: " fmt, \
pltfrm_dev_string(dev), __func__, __LINE__, \
## arg)
#endif