18 #include <linux/i2c.h>
19 #include <linux/slab.h>
23 #include <linux/videodev2.h>
24 #include <linux/module.h>
34 #define MODULE_NAME "NOON010PC30"
40 #define POWER_CTRL_REG 0x0001
41 #define PAGEMODE_REG 0x03
42 #define DEVICE_ID_REG 0x0004
43 #define NOON010PC30_ID 0x86
44 #define VDO_CTL_REG(n) (0x0010 + (n))
45 #define SYNC_CTL_REG 0x0012
47 #define WIN_ROWH_REG 0x0013
48 #define WIN_ROWL_REG 0x0014
49 #define WIN_COLH_REG 0x0015
50 #define WIN_COLL_REG 0x0016
51 #define WIN_HEIGHTH_REG 0x0017
52 #define WIN_HEIGHTL_REG 0x0018
53 #define WIN_WIDTHH_REG 0x0019
54 #define WIN_WIDTHL_REG 0x001A
55 #define HBLANKH_REG 0x001B
56 #define HBLANKL_REG 0x001C
57 #define VSYNCH_REG 0x001D
58 #define VSYNCL_REG 0x001E
60 #define VS_CTL_REG(n) (0x00A1 + (n))
62 #define ISP_CTL_REG(n) (0x0110 + (n))
63 #define YOFS_REG 0x0119
64 #define DARK_YOFS_REG 0x011A
65 #define SAT_CTL_REG 0x0120
66 #define BSAT_REG 0x0121
67 #define RSAT_REG 0x0122
69 #define CMC_CTL_REG 0x0130
70 #define CMC_OFSGH_REG 0x0133
71 #define CMC_OFSGL_REG 0x0135
72 #define CMC_SIGN_REG 0x0136
73 #define CMC_GOFS_REG 0x0137
74 #define CMC_COEF_REG(n) (0x0138 + (n))
75 #define CMC_OFS_REG(n) (0x0141 + (n))
77 #define GMA_CTL_REG 0x0160
78 #define GMA_COEF_REG(n) (0x0161 + (n))
80 #define LENS_CTRL_REG 0x01D0
81 #define LENS_XCEN_REG 0x01D1
82 #define LENS_YCEN_REG 0x01D2
83 #define LENS_RC_REG 0x01D3
84 #define LENS_GC_REG 0x01D4
85 #define LENS_BC_REG 0x01D5
86 #define L_AGON_REG 0x01D6
87 #define L_AGOFF_REG 0x01D7
89 #define AE_CTL_REG(n) (0x0310 + (n))
90 #define AE_CTL9_REG 0x032C
91 #define AE_CTL10_REG 0x032D
92 #define AE_YLVL_REG 0x031C
93 #define AE_YTH_REG(n) (0x031D + (n))
94 #define AE_WGT_REG 0x0326
95 #define EXP_TIMEH_REG 0x0333
96 #define EXP_TIMEM_REG 0x0334
97 #define EXP_TIMEL_REG 0x0335
98 #define EXP_MMINH_REG 0x0336
99 #define EXP_MMINL_REG 0x0337
100 #define EXP_MMAXH_REG 0x0338
101 #define EXP_MMAXM_REG 0x0339
102 #define EXP_MMAXL_REG 0x033A
104 #define AWB_CTL_REG(n) (0x0410 + (n))
105 #define AWB_ENABE 0x80
106 #define AWB_WGHT_REG 0x0419
107 #define BGAIN_PAR_REG(n) (0x044F + (n))
109 #define MWB_RGAIN_REG 0x0466
110 #define MWB_BGAIN_REG 0x0467
113 #define REG_TERM 0xFFFF
127 static const char *
const noon010_supply_name[] = {
128 "vdd_core",
"vddio",
"vdda"
131 #define NOON010_NUM_SUPPLIES ARRAY_SIZE(noon010_supply_name)
201 static const struct i2c_regval noon010_base_regs[] = {
252 if (info->
i2c_reg_page != page && (reg & 0xFF) != 0x03) {
262 struct i2c_client *client = v4l2_get_subdevdata(sd);
264 int ret = set_i2c_page(info, client, reg_addr);
273 struct i2c_client *client = v4l2_get_subdevdata(sd);
275 int ret = set_i2c_page(info, client, reg_addr);
282 static inline int noon010_bulk_write_reg(
struct v4l2_subdev *sd,
286 int ret = cam_i2c_write(sd, msg->
addr, msg->
val);
296 static int noon010_power_ctrl(
struct v4l2_subdev *sd,
bool reset,
bool sleep)
299 u8 reg = sleep ? 0xF1 : 0xF0;
315 static int noon010_enable_autowhitebalance(
struct v4l2_subdev *sd,
int on)
319 ret = cam_i2c_write(sd,
AWB_CTL_REG(1), on ? 0x2E : 0x2F);
321 ret = cam_i2c_write(sd,
AWB_CTL_REG(0), on ? 0xFB : 0x7B);
341 ret = cam_i2c_write(sd,
VDO_CTL_REG(1), reg | 0x80);
350 static int noon010_set_params(
struct v4l2_subdev *sd)
363 static int noon010_try_frame_size(
struct v4l2_mbus_framefmt *mf,
366 unsigned int min_err = ~0;
382 mf->
width = match->width;
383 mf->height = match->height;
397 v4l2_info(&info->
sd,
"%s: sensor is already on\n", __func__);
438 v4l2_info(&info->
sd,
"%s: sensor is already off\n", __func__);
466 __func__, ctrl->
id, ctrl->
val);
479 ret = noon010_enable_autowhitebalance(sd, ctrl->
val);
495 static int noon010_enum_mbus_code(
struct v4l2_subdev *sd,
497 struct v4l2_subdev_mbus_code_enum *
code)
499 if (code->index >=
ARRAY_SIZE(noon010_formats))
502 code->code = noon010_formats[code->index].
code;
510 struct v4l2_mbus_framefmt *mf;
514 mf = v4l2_subdev_get_try_format(fh, 0);
523 mf->height = info->
curr_win->height;
525 mf->colorspace = info->
curr_fmt->colorspace;
534 struct v4l2_mbus_framefmt *mf)
539 if (mf->code == noon010_formats[i].
code)
541 mf->code = noon010_formats[
i].
code;
543 return &noon010_formats[
i];
552 struct v4l2_mbus_framefmt *mf;
555 nf = noon010_try_fmt(sd, &fmt->
format);
556 noon010_try_frame_size(&fmt->
format, &size);
561 mf = v4l2_subdev_get_try_format(fh, 0);
579 static int noon010_base_config(
struct v4l2_subdev *sd)
581 int ret = noon010_bulk_write_reg(sd, noon010_base_regs);
583 ret = noon010_set_params(sd);
585 ret = noon010_set_flip(sd, 1, 0);
590 static int noon010_s_power(
struct v4l2_subdev *sd,
int on)
597 ret = power_enable(info);
599 ret = noon010_base_config(sd);
601 noon010_power_ctrl(sd,
false,
true);
602 ret = power_disable(info);
613 static int noon010_s_stream(
struct v4l2_subdev *sd,
int on)
620 ret = noon010_power_ctrl(sd,
false, !on);
625 ret = noon010_set_params(sd);
633 static int noon010_log_status(
struct v4l2_subdev *sd)
643 struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
645 mf->width = noon010_sizes[0].
width;
646 mf->height = noon010_sizes[0].
height;
647 mf->code = noon010_formats[0].
code;
654 .open = noon010_open,
658 .s_ctrl = noon010_s_ctrl,
662 .s_power = noon010_s_power,
670 .log_status = noon010_log_status,
674 .enum_mbus_code = noon010_enum_mbus_code,
675 .get_fmt = noon010_get_fmt,
676 .set_fmt = noon010_set_fmt,
680 .s_stream = noon010_s_stream,
684 .core = &noon010_core_ops,
685 .pad = &noon010_pad_ops,
686 .video = &noon010_video_ops,
694 ret = power_enable(info);
700 dev_err(&client->
dev,
"I2C read failed: 0x%X\n", ret);
707 static int noon010_probe(
struct i2c_client *client,
713 = client->
dev.platform_data;
745 ret = info->
hdl.error;
752 info->
curr_fmt = &noon010_formats[0];
758 dev_err(&client->
dev,
"GPIO request error: %d\n", ret);
769 dev_err(&client->
dev,
"GPIO request error: %d\n", ret);
778 info->
supply[i].supply = noon010_supply_name[i];
791 ret = noon010_detect(client, info);
810 static int noon010_remove(
struct i2c_client *client)
812 struct v4l2_subdev *sd = i2c_get_clientdata(client);
838 static struct i2c_driver noon010_i2c_driver = {
842 .probe = noon010_probe,
843 .remove = noon010_remove,
844 .id_table = noon010_id,