mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
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:
@@ -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.
|
||||
@@ -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
|
||||
@@ -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", ®, ®_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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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");
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user