summaryrefslogtreecommitdiff
path: root/drivers/media/video/wmt_v4l2/sensors/bf3a03
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/wmt_v4l2/sensors/bf3a03')
-rwxr-xr-xdrivers/media/video/wmt_v4l2/sensors/bf3a03/bf3a03.c335
-rwxr-xr-xdrivers/media/video/wmt_v4l2/sensors/bf3a03/bf3a03.h391
2 files changed, 726 insertions, 0 deletions
diff --git a/drivers/media/video/wmt_v4l2/sensors/bf3a03/bf3a03.c b/drivers/media/video/wmt_v4l2/sensors/bf3a03/bf3a03.c
new file mode 100755
index 00000000..dfc0a4bf
--- /dev/null
+++ b/drivers/media/video/wmt_v4l2/sensors/bf3a03/bf3a03.c
@@ -0,0 +1,335 @@
+
+#include "../cmos-subdev.h"
+#include "../../wmt-vid.h"
+#include "bf3a03.h"
+
+#define sensor_write_array(sd, arr, sz) \
+ cmos_init_8bit_addr(arr, sz, (sd)->i2c_addr)
+
+#define sensor_read(sd, reg) \
+ wmt_vid_i2c_read(sd->i2c_addr, reg)
+
+#define sensor_write(sd, reg, val) \
+ wmt_vid_i2c_write(sd->i2c_addr, reg, val)
+
+struct cmos_win_size {
+ char *name;
+ int width;
+ int height;
+ uint8_t *regs;
+ size_t size;
+};
+
+#define CMOS_WIN_SIZE(n, w, h, r) \
+ {.name = n, .width = w , .height = h, .regs = r, .size = ARRAY_SIZE(r) }
+
+
+static const struct cmos_win_size cmos_supported_win_sizes[] = {
+// CMOS_WIN_SIZE("QVGA", 320, 240, bf3a03_320x240),
+ CMOS_WIN_SIZE("VGA", 640, 480, bf3a03_640x480),
+};
+
+static const struct cmos_win_size *cmos_select_win(u32 *width, u32 *height)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cmos_supported_win_sizes); i++) {
+ if (cmos_supported_win_sizes[i].width == *width &&
+ cmos_supported_win_sizes[i].height == *height) {
+ *width = cmos_supported_win_sizes[i].width;
+ *height = cmos_supported_win_sizes[i].height;
+ return &cmos_supported_win_sizes[i];
+ }
+ }
+ return NULL;
+}
+
+static int sensor_s_wb(struct cmos_subdev *sd, enum v4l2_wb_mode value)
+{
+ uint8_t *regs;
+ size_t size;
+
+ switch (value) {
+ case WHITE_BALANCE_AUTO:
+ regs = bf3a03_wb_auto;
+ size = ARRAY_SIZE(bf3a03_wb_auto);
+ break;
+ case WHITE_BALANCE_INCANDESCENCE:
+ regs = bf3a03_wb_incandescent;
+ size = ARRAY_SIZE(bf3a03_wb_incandescent);
+ break;
+ case WHITE_BALANCE_DAYLIGHT:
+ regs = bf3a03_wb_daylight;
+ size = ARRAY_SIZE(bf3a03_wb_daylight);
+ break;
+ case WHITE_BALANCE_CLOUDY:
+ regs = bf3a03_wb_cloudy;
+ size = ARRAY_SIZE(bf3a03_wb_cloudy);
+ break;
+ case WHITE_BALANCE_FLUORESCENT:
+ regs = bf3a03_wb_fluorescent;
+ size = ARRAY_SIZE(bf3a03_wb_fluorescent);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ sensor_write_array(sd, regs, size);
+ return 0;
+}
+
+static int sensor_s_scenemode(struct cmos_subdev *sd, enum v4l2_scene_mode value)
+{
+ uint8_t *regs;
+ size_t size;
+
+ switch (value) {
+ case SCENE_MODE_AUTO:
+ regs = bf3a03_scene_mode_auto;
+ size = ARRAY_SIZE(bf3a03_scene_mode_auto);
+ break;
+ case SCENE_MODE_NIGHTSHOT:
+ regs = bf3a03_scene_mode_night;
+ size = ARRAY_SIZE(bf3a03_scene_mode_night);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ sensor_write_array(sd, regs, size);
+ return 0;
+}
+
+static int sensor_s_exposure(struct cmos_subdev *sd, int value)
+{
+ uint8_t *regs;
+ size_t size;
+
+ switch (value) {
+ case -2:
+ regs = bf3a03_exposure_neg6;
+ size = ARRAY_SIZE(bf3a03_exposure_neg6);
+ break;
+ case -1:
+ regs = bf3a03_exposure_neg3;
+ size = ARRAY_SIZE(bf3a03_exposure_neg3);
+ break;
+ case 0:
+ regs = bf3a03_exposure_zero;
+ size = ARRAY_SIZE(bf3a03_exposure_zero);
+ break;
+ case 1:
+ regs = bf3a03_exposure_pos3;
+ size = ARRAY_SIZE(bf3a03_exposure_pos3);
+ break;
+ case 2:
+ regs = bf3a03_exposure_pos6;
+ size = ARRAY_SIZE(bf3a03_exposure_pos6);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ sensor_write_array(sd, regs, size);
+ return 0;
+}
+
+static int sensor_s_hflip(struct cmos_subdev *sd, int value)
+{
+ uint8_t data;
+ uint8_t retry_times=0;
+
+
+ data = sensor_read(sd, 0x1e);
+
+ switch (value) {
+ case 0:
+ data &= ~0x20;
+ break;
+ case 1:
+ data |= 0x20;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ sensor_write(sd, 0x1e, data);
+ return 0;
+}
+
+static int sensor_s_vflip(struct cmos_subdev *sd, int value)
+{
+ uint8_t data;
+ uint8_t retry_times=0;
+
+
+
+ data = sensor_read(sd, 0x1e);
+
+ switch (value) {
+ case 0:
+ data &= ~0x10;
+ break;
+ case 1:
+ data |= 0x10;
+ break;
+ default:
+ return -EINVAL;
+ }
+ sensor_write(sd, 0x1e, data);
+
+
+ return 0;
+}
+
+static int sensor_queryctrl(struct cmos_subdev *sd, struct v4l2_queryctrl *qc)
+{
+ switch (qc->id) {
+ case V4L2_CID_VFLIP:
+ case V4L2_CID_HFLIP:
+ return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
+ case V4L2_CID_CAMERA_SCENE_MODE:
+ return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
+ case V4L2_CID_DO_WHITE_BALANCE:
+ return v4l2_ctrl_query_fill(qc, 0, 3, 1, 0);
+ case V4L2_CID_EXPOSURE:
+ return v4l2_ctrl_query_fill(qc, -2, 2, 1, 0);
+ }
+ return -EINVAL;
+}
+
+static int sensor_s_ctrl(struct cmos_subdev *sd, struct v4l2_control *ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_CAMERA_SCENE_MODE:
+ return sensor_s_scenemode(sd, ctrl->value);
+ case V4L2_CID_DO_WHITE_BALANCE:
+ return sensor_s_wb(sd, ctrl->value);
+ case V4L2_CID_EXPOSURE:
+ return sensor_s_exposure(sd, ctrl->value);
+ case V4L2_CID_HFLIP:
+ return sensor_s_hflip(sd, ctrl->value);
+ case V4L2_CID_VFLIP:
+ return sensor_s_vflip(sd, ctrl->value);
+ default:
+ case WMT_V4L2_CID_CAMERA_ANTIBANDING:
+ return -EINVAL;
+ }
+ return -EINVAL;
+}
+
+static int sensor_g_mbus_fmt(struct cmos_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ return -EINVAL;
+}
+
+static int sensor_s_mbus_fmt(struct cmos_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ const struct cmos_win_size *win;
+
+ win = cmos_select_win(&mf->width, &mf->height);
+ if (!win) {
+ pr_err("%s, s_mbus_fmt failed, width %d, height %d\n",
+ sd->name, mf->width, mf->height);
+ return -EINVAL;
+ }
+
+ sensor_write_array(sd, win->regs, win->size);
+ return 0;
+}
+
+static int sensor_try_mbus_fmt(struct cmos_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ return 0;
+}
+
+static int sensor_enum_framesizes(struct cmos_subdev *sd,
+ struct v4l2_frmsizeenum *fsize)
+{
+ int i;
+ int num_valid = -1;
+ __u32 index = fsize->index;
+
+ for (i = 0; i < ARRAY_SIZE(cmos_supported_win_sizes); i++) {
+ const struct cmos_win_size *win = &cmos_supported_win_sizes[index];
+ if (index == ++num_valid) {
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = win->width;
+ fsize->discrete.height = win->height;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int sensor_identify(struct cmos_subdev *sd)
+{
+ uint32_t data = 0;
+
+ data |= (sensor_read(sd, 0xfc) & 0xff) << 8;
+ data |= (sensor_read(sd, 0xfd) & 0xff);
+
+ return (data == sd->id) ? 0 : -EINVAL;
+}
+
+static int sensor_init(struct cmos_subdev *sd)
+{
+ uint32_t data = 0;
+
+ if (sensor_identify(sd)) {
+ return -1;
+ }
+
+ sensor_write_array(sd, bf3a03_default_regs_init,
+ ARRAY_SIZE(bf3a03_default_regs_init));
+ return 0;
+}
+
+static int sensor_exit(struct cmos_subdev *sd)
+{
+ sensor_write_array(sd, bf3a03_default_regs_exit,
+ ARRAY_SIZE(bf3a03_default_regs_exit));
+ return 0;
+}
+
+static struct cmos_subdev_ops bf3a03_ops = {
+ .identify = sensor_identify,
+ .init = sensor_init,
+ .exit = sensor_exit,
+ .queryctrl = sensor_queryctrl,
+ .s_ctrl = sensor_s_ctrl,
+ .s_mbus_fmt = sensor_s_mbus_fmt,
+ .g_mbus_fmt = sensor_g_mbus_fmt,
+ .try_mbus_fmt = sensor_try_mbus_fmt,
+ .enum_framesizes = sensor_enum_framesizes,
+};
+
+struct cmos_subdev bf3a03 = {
+ .name = "bf3a03",
+ .i2c_addr = 0x6e,
+ .id = 0x3a03,
+ .max_width = 640,
+ .max_height = 480,
+ .ops = &bf3a03_ops,
+};
+
+#if 0
+static int __init bf3a03_init(void)
+{
+ return cmos_register_sudbdev(&bf3a03);
+}
+
+static void __exit bf3a03_exit(void)
+{
+ return cmos_unregister_subdev(&bf3a03);
+}
+
+module_init(bf3a03_init);
+module_exit(bf3a03_exit);
+
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/media/video/wmt_v4l2/sensors/bf3a03/bf3a03.h b/drivers/media/video/wmt_v4l2/sensors/bf3a03/bf3a03.h
new file mode 100755
index 00000000..b7d2ac91
--- /dev/null
+++ b/drivers/media/video/wmt_v4l2/sensors/bf3a03/bf3a03.h
@@ -0,0 +1,391 @@
+#ifndef BF3A03_H
+#define BF3A03_H
+
+
+// Scene Mode
+uint8_t bf3a03_scene_mode_auto[] = {
+ 0x89, 0x6d,
+};
+
+uint8_t bf3a03_scene_mode_night[] = {
+ 0x89, 0x9d,
+};
+
+
+// White Balance
+uint8_t bf3a03_wb_auto [] = {
+ 0x13,0x07,
+ 0x01, 0x12,
+ 0x02, 0x22,
+};
+
+uint8_t bf3a03_wb_incandescent [] = {
+ 0x13,0x05,
+ 0x01, 0x1f,
+ 0x02, 0x20,
+};
+
+uint8_t bf3a03_wb_fluorescent [] = {
+ 0x13,0x05,
+ 0x01, 0x1a,
+ 0x02, 0x15,
+};
+
+uint8_t bf3a03_wb_daylight [] = {
+ 0x13,0x05,
+ 0x01, 0x15,
+ 0x02, 0x20,
+};
+
+uint8_t bf3a03_wb_cloudy [] = {
+ 0x13,0x05,
+ 0x01, 0x10,
+ 0x02, 0x2c,
+};
+
+
+// Exposure
+uint8_t bf3a03_exposure_neg6[] = {
+ 0x55, 0xb8,
+};
+
+uint8_t bf3a03_exposure_neg3[] = {
+0x55, 0x98,
+};
+
+uint8_t bf3a03_exposure_zero[] = {
+0x55, 0x00,
+};
+
+uint8_t bf3a03_exposure_pos3[] = {
+0x55, 0x18,
+};
+
+uint8_t bf3a03_exposure_pos6[] = {
+0x55, 0x38,
+};
+
+
+// Resolution
+uint8_t bf3a03_320x240[]= {
+ 0xda, 0x00,
+ 0xdb, 0xa2,
+ 0xdc, 0x00,
+ 0xdd, 0x7a,
+ 0xde, 0x00,
+ 0x4a, 0x98,
+ 0x0a, 0x21,
+ 0x10, 0x21,
+ 0x3d, 0x59,
+ 0x6b, 0x02,
+
+ 0x17, 0x00,
+ 0x18, 0xa0,
+ 0x19, 0x00,
+ 0x1a, 0x78,
+ 0x03, 0x00,
+ 0x12, 0x10,
+
+};
+
+uint8_t bf3a03_640x480[] = {
+ 0xda, 0x00,
+ 0xdb, 0xa2,
+ 0xdc, 0x00,
+ 0xdd, 0x7a,
+ 0xde, 0x00,
+ 0x4a, 0x98,
+ 0x0a, 0x21,
+ 0x10, 0x21,
+ 0x3d, 0x59,
+ 0x6b, 0x02,
+
+ 0x17, 0x00,
+ 0x18, 0xa0,
+ 0x19, 0x00,
+ 0x1a, 0x78,
+ 0x03, 0x00,
+ 0x12, 0x00,
+};
+
+uint8_t bf3a03_default_regs_init[] = {
+ //0x12,0x80,
+ 0x09,0x55,
+ 0x15,0x00,
+ 0x1e,0x70,//HV mirror
+
+ //Analog signals
+ 0x06,0x78,
+ 0x21,0x00,
+ 0x3e,0x37,
+ 0x29,0x2b,
+ 0x27,0x98,
+ 0x16,0x25,
+ 0x20,0x00,
+
+ //Clock
+ 0x2f,0x42,//有绿色雪花点时,写为0x4e;
+ 0x11,0x10,//分频[1:0]
+ 0x1b,0x09,//倍频 PLL使能与0x2f[1]、0x1b[3]
+
+ //数据输出格式
+ 0x4a,0x98,//Sub、Win
+ 0x12,0x00,//YUV、sub时序
+ 0x3a,0x00,//YUV时序
+
+ //Manual
+ 0x13,0x08,//手写bit[3]GLB GAIN0
+ 0x01,0x14,
+ 0x02,0x20,
+ 0x8c,0x02,
+ 0x8d,0x4c,
+ 0x87,0x16,//GLB GAIN0
+
+ ///Auto
+ 0x13,0x07,
+
+ //Denoise
+ 0x70,0x0f,//插值模块开关
+ 0x3b,0x00,//去格子噪声
+ 0x71,0x0c,//插值模块开关
+ 0x73,0x27,//Denoise
+ 0x75,0x88,//Outdoor denoise
+ 0x76,0xd8,
+ 0x77,0x0a,//Low light denoise
+ 0x78,0xff,
+ 0x79,0x14,
+ 0x7a,0x24,//边缘增强
+ 0x9e,0x04,
+ 0x7d,0x2a,//去紫边
+
+ //Gamma default
+ 0x39,0xa0,//Gamma offset
+ 0x3f,0xa0,
+ /*
+ 0x90,0x20,
+ 0x5f,0x03,//Dark_sel gamma
+ 0x40,0x22,
+ 0x41,0x23,
+ 0x42,0x28,
+ 0x43,0x25,
+ 0x44,0x1d,
+ 0x45,0x17,
+ 0x46,0x13,
+ 0x47,0x12,
+ 0x48,0x10,
+ 0x49,0x0d,
+ 0x4b,0x0b,
+ 0x4c,0x0b,
+ 0x4e,0x09,
+ 0x4f,0x07,
+ 0x50,0x06,
+
+ //Gamma low noise
+ 0x40,0x24,
+ 0x41,0x30,
+ 0x42,0x24,
+ 0x43,0x1d,
+ 0x44,0x1a,
+ 0x45,0x14,
+ 0x46,0x11,
+ 0x47,0x0e,
+ 0x48,0x0d,
+ 0x49,0x0c,
+ 0x4b,0x0b,
+ 0x4c,0x09,
+ 0x4e,0x09,
+ 0x4f,0x08,
+ 0x50,0x07, */
+
+ //Gamma smooth under over-ex
+ 0x40,0x18,
+ 0x41,0x2c,
+ 0x42,0x28,
+ 0x43,0x20,
+ 0x44,0x16,
+ 0x45,0x10,
+ 0x46,0x0f,
+ 0x47,0x0f,
+ 0x48,0x0e,
+ 0x49,0x0a,
+ 0x4b,0x0b,
+ 0x4c,0x09,
+ 0x4e,0x09,
+ 0x4f,0x08,
+ 0x50,0x06,
+ /*
+ //Gamma sharp and pretty 清晰亮丽
+ 0x40,0x19,
+ 0x41,0x1e,
+ 0x42,0x1f,
+ 0x43,0x20,
+ 0x44,0x1d,
+ 0x45,0x19,
+ 0x46,0x17,
+ 0x47,0x17,
+ 0x48,0x14,
+ 0x49,0x12,
+ 0x4b,0x0f,
+ 0x4c,0x0c,
+ 0x4e,0x08,
+ 0x4f,0x06,
+ 0x50,0x03,
+ */
+
+ //AE
+ 0x24,0x48,//非A光Y_target 0x50
+ 0x97,0x40,//A光Y_target
+ 0x25,0x88,//AE_LOC
+ 0x81,0x00,//AE speed
+ 0x82,0x18,
+ 0x83,0x30,
+ 0x84,0x20,
+ 0x85,0x38,
+ 0x86,0x55,
+ 0x94,0x82,//对AE亮度权重调节
+ 0x80,0x92,//对过曝点数调节,bit[1]choose 50HZ or 60HZ step;
+ 0x98,0xbb,//对窗口权重调节 0x8a
+ 0x89,0x6d,//帧率调节bit[7:3]
+ 0x8e,0x2c,
+ 0x8f,0x86,
+
+ //Banding
+ 0x2b,0x20,
+ 0x8a,0x93,//50HZ
+ 0x8b,0x7a,//60HZ
+ 0x92,0x6D,
+
+ //Color
+ 0x5a,0xec,//Outdoor color
+ 0x51,0x90,
+ 0x52,0x10,
+ 0x53,0x8d,
+ 0x54,0x88,
+ 0x57,0x82,
+ 0x58,0x8d,
+ 0x5a,0x7c,//A light color
+ 0x51,0x80,
+ 0x52,0x04,
+ 0x53,0x8d,
+ 0x54,0x88,
+ 0x57,0x82,
+ 0x58,0x8d,
+
+ //Color default
+ 0x5a,0x6c,//Indoor color
+ 0x51,0x93,
+ 0x52,0x04,
+ 0x53,0x8a,
+ 0x54,0x88,
+ 0x57,0x02,
+ 0x58,0x8d,
+
+ /*//Color色彩艳丽
+ 0x5a,0x6c,//Indoor color
+ 0x51,0xa0,
+ 0x52,0x01,
+ 0x53,0x8d,
+ 0x54,0x85,
+ 0x57,0x01,
+ 0x58,0x90,
+
+ //Color肤色较好
+ 0x5a,0x6c,//Indoor color
+ 0x51,0x90,
+ 0x52,0x0a,
+ 0x53,0x84,
+ 0x54,0x05,
+ 0x57,0x05,
+ 0x58,0x87,
+
+ //Color色彩淡
+ 0x5a,0x6c,//Indoor color
+ 0x51,0x85,
+ 0x52,0x06,
+ 0x53,0x8a,
+ 0x54,0x81,
+ 0x57,0x02,
+ 0x58,0x8a,
+ */
+
+ //Saturation
+ 0xb0,0xa0,//A光饱和度
+ 0xb1,0x26,
+ 0xb2,0x1c,
+ 0xb4,0xfd,
+ 0xb0,0x30,//非A光饱和度
+ 0xb1,0xc0, ///0xd8
+ 0xb2,0xa0, ///0xb0
+ 0xb4,0xf1,
+
+ //Contrast
+ 0x3c,0x40,//K1
+ 0x56,0x48,//K2 0xb4[4]选择new or old
+ 0x4d,0x40,//K3
+ 0x59,0x40,//K4
+
+ /*//G gain大一些
+ 0x35,0x56,//shading R
+ 0x65,0x36,//shading G
+ 0x66,0x44,//shading B
+ //AWB
+ 0x6a,0x91,
+ 0x23,0x44,
+ 0xa2,0x04,
+ 0xa3,0x26,
+ 0xa4,0x04,
+ 0xa5,0x26,
+ 0xa7,0x1a,
+ 0xa8,0x10,
+ 0xa9,0x1f,
+ 0xaa,0x16,
+ 0xab,0x16,
+ 0xac,0x30,
+ 0xad,0xf0,
+ 0xae,0x57,
+ 0xc5,0xaa,
+ 0xc7,0x38,
+ 0xc8,0x0d,
+ 0xc9,0x16,
+ 0xd3,0x09,
+ 0xd4,0x15,
+ 0xd0,0x00,
+ 0xd1,0x01,
+ 0xd2,0x18,
+ */
+
+ //G gain小一些
+ 0x35,0x46,//shading R
+ 0x65,0x38,//shading G
+ 0x66,0x42,//shading B
+ //AWB
+ 0x6a,0xd1,//AWB
+ 0x23,0x11,//G GAIN
+ 0xa2,0x0b,//非户外 B上下线
+ 0xa3,0x26,
+ 0xa4,0x04,//非户外 R上下线
+ 0xa5,0x26,
+ 0xa7,0x13,//B GAIN
+ 0xa8,0x8e,//R GAIN
+ 0xa9,0x16,//白点
+ 0xaa,0x16,
+ 0xab,0x16,
+ 0xac,0x30,
+ 0xad,0xf0,
+ 0xae,0x57,
+ 0xc5,0x66,
+ 0xc7,0x38,//户内、外开关bit[4]
+ 0xc8,0x0d,//非户外 B上下线
+ 0xc9,0x16,
+ 0xd3,0x09,//非户外 R上下线
+ 0xd4,0x15,
+ 0xd0,0x00,//A光下的offset
+ 0xd1,0x01,//非A光下的offset
+ 0xd2,0x18,
+ 0x20,0x40, ////[6] dependent or not
+ 0x09,0x5c,///0x55 0x57
+};
+
+uint8_t bf3a03_default_regs_exit[]={
+};
+#endif