mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
media: i2c: gc05a2: add set flip & mirror support
note: gc05a2 flip & mirror use the same register; but write value to the register not valid immediately, so need record it in variable, to avoid being covered. Signed-off-by: Wang Panzhenzhuan <randy.wang@rock-chips.com> Change-Id: Ice9c9fcefdbf9fa56a83f9b049e434cfe1c23bba
This commit is contained in:
committed by
Tao Huang
parent
ff72684051
commit
71ea8ca835
@@ -8,6 +8,7 @@
|
||||
* V0.0X01.0X01 update sensor driver.
|
||||
* 1. adjust power sequence to suit spec.
|
||||
* 2. fix bayer pattern to suit setting.
|
||||
* V0.0X01.0X02 add mirror & flip support.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@@ -81,6 +82,10 @@
|
||||
#define GC05A2_REG_VTS_H 0x0340
|
||||
#define GC05A2_REG_VTS_L 0x0341
|
||||
|
||||
#define GC05A2_FLIP_MIRROR_REG 0x0101
|
||||
#define MIRROR_BIT_MASK BIT(0)
|
||||
#define FLIP_BIT_MASK BIT(1)
|
||||
|
||||
#define REG_NULL 0xFFFF
|
||||
|
||||
#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
|
||||
@@ -139,6 +144,9 @@ struct gc05a2 {
|
||||
struct v4l2_ctrl *hblank;
|
||||
struct v4l2_ctrl *vblank;
|
||||
struct v4l2_ctrl *link_freq;
|
||||
struct v4l2_ctrl *h_flip;
|
||||
struct v4l2_ctrl *v_flip;
|
||||
u8 flip_mirror;
|
||||
struct mutex mutex;
|
||||
bool streaming;
|
||||
unsigned int lane_num;
|
||||
@@ -157,49 +165,6 @@ struct gc05a2 {
|
||||
|
||||
#define to_gc05a2(sd) container_of(sd, struct gc05a2, subdev)
|
||||
|
||||
#undef GC05A2_MIRROR_NORMAL
|
||||
#undef GC05A2_MIRROR_H
|
||||
#undef GC05A2_MIRROR_V
|
||||
#undef GC05A2_MIRROR_HV
|
||||
|
||||
/* SENSOR MIRROR FLIP INFO */
|
||||
#define GC05A2_MIRROR_NORMAL 0
|
||||
#define GC05A2_MIRROR_H 1
|
||||
#define GC05A2_MIRROR_V 0
|
||||
#define GC05A2_MIRROR_HV 0
|
||||
|
||||
#if GC05A2_MIRROR_NORMAL
|
||||
#define GC05A2_MIRROR 0x00
|
||||
#define FULL_STARTY 0x06
|
||||
#define FULL_STARTX 0x08
|
||||
#define BINNING_STARTY 0x03
|
||||
#define BINNING_STARTX 0x03
|
||||
#elif GC05A2_MIRROR_H
|
||||
#define GC05A2_MIRROR 0x01
|
||||
#define FULL_STARTY 0x06
|
||||
#define FULL_STARTX 0x09
|
||||
#define BINNING_STARTY 0x03
|
||||
#define BINNING_STARTX 0x04
|
||||
#elif GC05A2_MIRROR_V
|
||||
#define GC05A2_MIRROR 0x02
|
||||
#define FULL_STARTY 0x07
|
||||
#define FULL_STARTX 0x08
|
||||
#define BINNING_STARTY 0x04
|
||||
#define BINNING_STARTX 0x03
|
||||
#elif GC05A2_MIRROR_HV
|
||||
#define GC05A2_MIRROR 0x03
|
||||
#define FULL_STARTY 0x07
|
||||
#define FULL_STARTX 0x09
|
||||
#define BINNING_STARTY 0x04
|
||||
#define BINNING_STARTX 0x04
|
||||
#else
|
||||
#define GC05A2_MIRROR 0x00
|
||||
#define FULL_STARTY 0x06
|
||||
#define FULL_STARTX 0x08
|
||||
#define BINNING_STARTY 0x03
|
||||
#define BINNING_STARTX 0x03
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Xclk 24Mhz
|
||||
*/
|
||||
@@ -1136,6 +1101,7 @@ static int gc05a2_s_power(struct v4l2_subdev *sd, int on)
|
||||
goto unlock_and_return;
|
||||
}
|
||||
|
||||
gc05a2->flip_mirror = 0;
|
||||
ret = gc05a2_write_array(gc05a2->client, gc05a2->cur_mode->global_reg_list);
|
||||
if (ret) {
|
||||
v4l2_err(sd, "could not set init registers\n");
|
||||
@@ -1421,15 +1387,15 @@ static int gc05a2_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_EXPOSURE:
|
||||
/* 4 least significant bits of expsoure are fractional part */
|
||||
dev_info(&client->dev, "set exposure value 0x%x\n", ctrl->val);
|
||||
dev_dbg(&client->dev, "set exposure value 0x%x\n", ctrl->val);
|
||||
ret = gc05a2_set_exposure_reg(gc05a2, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_ANALOGUE_GAIN:
|
||||
dev_info(&client->dev, "set analog gain value 0x%x\n", ctrl->val);
|
||||
dev_dbg(&client->dev, "set analog gain value 0x%x\n", ctrl->val);
|
||||
ret = gc05a2_set_gain_reg(gc05a2, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_VBLANK:
|
||||
dev_info(&client->dev, "set vb value 0x%x\n", ctrl->val);
|
||||
dev_dbg(&client->dev, "set vb value 0x%x\n", ctrl->val);
|
||||
ret = gc05a2_write_reg(gc05a2->client,
|
||||
GC05A2_REG_VTS_H,
|
||||
(ctrl->val + gc05a2->cur_mode->height)
|
||||
@@ -1439,6 +1405,27 @@ static int gc05a2_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
(ctrl->val + gc05a2->cur_mode->height)
|
||||
& 0xff);
|
||||
break;
|
||||
case V4L2_CID_HFLIP:
|
||||
dev_dbg(&client->dev, "set mirror value 0x%x\n", ctrl->val);
|
||||
|
||||
if (ctrl->val)
|
||||
gc05a2->flip_mirror |= MIRROR_BIT_MASK;
|
||||
else
|
||||
gc05a2->flip_mirror &= ~MIRROR_BIT_MASK;
|
||||
|
||||
ret |= gc05a2_write_reg(gc05a2->client, GC05A2_FLIP_MIRROR_REG,
|
||||
gc05a2->flip_mirror);
|
||||
break;
|
||||
case V4L2_CID_VFLIP:
|
||||
dev_dbg(&client->dev, "set flip value 0x%x\n", ctrl->val);
|
||||
if (ctrl->val)
|
||||
gc05a2->flip_mirror |= FLIP_BIT_MASK;
|
||||
else
|
||||
gc05a2->flip_mirror &= ~FLIP_BIT_MASK;
|
||||
|
||||
ret |= gc05a2_write_reg(gc05a2->client, GC05A2_FLIP_MIRROR_REG,
|
||||
gc05a2->flip_mirror);
|
||||
break;
|
||||
default:
|
||||
dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
|
||||
__func__, ctrl->id, ctrl->val);
|
||||
@@ -1501,6 +1488,11 @@ static int gc05a2_initialize_controls(struct gc05a2 *gc05a2)
|
||||
V4L2_CID_ANALOGUE_GAIN, GC05A2_AGAIN_MIN,
|
||||
GC05A2_AGAIN_MAX, GC05A2_AGAIN_STEP,
|
||||
GC05A2_AGAIN_DEFAULT);
|
||||
gc05a2->h_flip = v4l2_ctrl_new_std(handler, &gc05a2_ctrl_ops,
|
||||
V4L2_CID_HFLIP, 0, 1, 1, 0);
|
||||
|
||||
gc05a2->v_flip = v4l2_ctrl_new_std(handler, &gc05a2_ctrl_ops,
|
||||
V4L2_CID_VFLIP, 0, 1, 1, 0);
|
||||
|
||||
if (handler->error) {
|
||||
ret = handler->error;
|
||||
|
||||
Reference in New Issue
Block a user