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:
Wang Panzhenzhuan
2024-07-11 19:43:13 +08:00
committed by Tao Huang
parent ff72684051
commit 71ea8ca835

View File

@@ -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;