summaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r--drivers/media/i2c/Kconfig73
-rw-r--r--drivers/media/i2c/Makefile6
-rw-r--r--drivers/media/i2c/adv7180.c28
-rw-r--r--drivers/media/i2c/adv7183.c2
-rw-r--r--drivers/media/i2c/adv748x/adv748x-afe.c6
-rw-r--r--drivers/media/i2c/adv748x/adv748x-csi2.c2
-rw-r--r--drivers/media/i2c/adv748x/adv748x-hdmi.c6
-rw-r--r--drivers/media/i2c/adv7511-v4l2.c4
-rw-r--r--drivers/media/i2c/adv7604.c4
-rw-r--r--drivers/media/i2c/adv7842.c4
-rw-r--r--drivers/media/i2c/ak7375.c132
-rw-r--r--drivers/media/i2c/alvium-csi2.c2558
-rw-r--r--drivers/media/i2c/alvium-csi2.h475
-rw-r--r--drivers/media/i2c/ar0521.c5
-rw-r--r--drivers/media/i2c/ccs/Kconfig1
-rw-r--r--drivers/media/i2c/ccs/ccs-core.c134
-rw-r--r--drivers/media/i2c/ccs/ccs-reg-access.c213
-rw-r--r--drivers/media/i2c/ccs/ccs-regs.h906
-rw-r--r--drivers/media/i2c/ccs/ccs.h3
-rw-r--r--drivers/media/i2c/ccs/smiapp-reg-defs.h951
-rw-r--r--drivers/media/i2c/ds90ub913.c13
-rw-r--r--drivers/media/i2c/ds90ub953.c13
-rw-r--r--drivers/media/i2c/ds90ub960.c23
-rw-r--r--drivers/media/i2c/et8ek8/et8ek8_driver.c23
-rw-r--r--drivers/media/i2c/gc0308.c1451
-rw-r--r--drivers/media/i2c/gc2145.c1450
-rw-r--r--drivers/media/i2c/hi556.c13
-rw-r--r--drivers/media/i2c/hi846.c21
-rw-r--r--drivers/media/i2c/hi847.c9
-rw-r--r--drivers/media/i2c/imx208.c9
-rw-r--r--drivers/media/i2c/imx214.c207
-rw-r--r--drivers/media/i2c/imx219.c21
-rw-r--r--drivers/media/i2c/imx258.c9
-rw-r--r--drivers/media/i2c/imx274.c74
-rw-r--r--drivers/media/i2c/imx290.c18
-rw-r--r--drivers/media/i2c/imx296.c28
-rw-r--r--drivers/media/i2c/imx319.c19
-rw-r--r--drivers/media/i2c/imx334.c16
-rw-r--r--drivers/media/i2c/imx335.c223
-rw-r--r--drivers/media/i2c/imx355.c7
-rw-r--r--drivers/media/i2c/imx412.c16
-rw-r--r--drivers/media/i2c/imx415.c16
-rw-r--r--drivers/media/i2c/isl7998x.c6
-rw-r--r--drivers/media/i2c/max9286.c32
-rw-r--r--drivers/media/i2c/mt9m001.c16
-rw-r--r--drivers/media/i2c/mt9m111.c44
-rw-r--r--drivers/media/i2c/mt9m114.c102
-rw-r--r--drivers/media/i2c/mt9p031.c14
-rw-r--r--drivers/media/i2c/mt9t112.c1
-rw-r--r--drivers/media/i2c/mt9v011.c34
-rw-r--r--drivers/media/i2c/mt9v032.c10
-rw-r--r--drivers/media/i2c/mt9v111.c44
-rw-r--r--drivers/media/i2c/og01a1b.c10
-rw-r--r--drivers/media/i2c/ov01a10.c12
-rw-r--r--drivers/media/i2c/ov02a10.c16
-rw-r--r--drivers/media/i2c/ov08d10.c9
-rw-r--r--drivers/media/i2c/ov08x40.c7
-rw-r--r--drivers/media/i2c/ov13858.c10
-rw-r--r--drivers/media/i2c/ov13b10.c10
-rw-r--r--drivers/media/i2c/ov2640.c16
-rw-r--r--drivers/media/i2c/ov2659.c6
-rw-r--r--drivers/media/i2c/ov2680.c34
-rw-r--r--drivers/media/i2c/ov2685.c4
-rw-r--r--drivers/media/i2c/ov2740.c379
-rw-r--r--drivers/media/i2c/ov4689.c2
-rw-r--r--drivers/media/i2c/ov5640.c49
-rw-r--r--drivers/media/i2c/ov5645.c16
-rw-r--r--drivers/media/i2c/ov5647.c12
-rw-r--r--drivers/media/i2c/ov5648.c72
-rw-r--r--drivers/media/i2c/ov5670.c23
-rw-r--r--drivers/media/i2c/ov5675.c9
-rw-r--r--drivers/media/i2c/ov5693.c18
-rw-r--r--drivers/media/i2c/ov5695.c8
-rw-r--r--drivers/media/i2c/ov64a40.c3690
-rw-r--r--drivers/media/i2c/ov6650.c64
-rw-r--r--drivers/media/i2c/ov7251.c36
-rw-r--r--drivers/media/i2c/ov7670.c37
-rw-r--r--drivers/media/i2c/ov772x.c30
-rw-r--r--drivers/media/i2c/ov7740.c47
-rw-r--r--drivers/media/i2c/ov8856.c9
-rw-r--r--drivers/media/i2c/ov8858.c16
-rw-r--r--drivers/media/i2c/ov8865.c66
-rw-r--r--drivers/media/i2c/ov9282.c18
-rw-r--r--drivers/media/i2c/ov9640.c2
-rw-r--r--drivers/media/i2c/ov9650.c35
-rw-r--r--drivers/media/i2c/ov9734.c9
-rw-r--r--drivers/media/i2c/rj54n1cb0c.c4
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c65
-rw-r--r--drivers/media/i2c/s5k5baf.c69
-rw-r--r--drivers/media/i2c/s5k6a3.c8
-rw-r--r--drivers/media/i2c/saa6752hs.c4
-rw-r--r--drivers/media/i2c/st-mipid02.c486
-rw-r--r--drivers/media/i2c/st-vgxy61.c34
-rw-r--r--drivers/media/i2c/tc358746.c22
-rw-r--r--drivers/media/i2c/tda1997x.c16
-rw-r--r--drivers/media/i2c/thp7312.c2256
-rw-r--r--drivers/media/i2c/tvp514x.c41
-rw-r--r--drivers/media/i2c/tvp5150.c8
-rw-r--r--drivers/media/i2c/tvp7002.c6
-rw-r--r--drivers/media/i2c/tw9900.c781
-rw-r--r--drivers/media/i2c/tw9910.c2
-rw-r--r--drivers/media/i2c/video-i2c.c7
102 files changed, 15706 insertions, 2379 deletions
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 59ee0ca2c9..4c3435921f 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -41,6 +41,16 @@ config VIDEO_APTINA_PLL
config VIDEO_CCS_PLL
tristate
+config VIDEO_ALVIUM_CSI2
+ tristate "Allied Vision ALVIUM MIPI CSI-2 camera support"
+ select V4L2_CCI_I2C
+ help
+ This is a Video4Linux2 sensor-level driver for the Allied Vision
+ ALVIUM camera connected via MIPI CSI-2 interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called alvium-csi2.
+
config VIDEO_AR0521
tristate "ON Semiconductor AR0521 sensor support"
help
@@ -50,6 +60,26 @@ config VIDEO_AR0521
To compile this driver as a module, choose M here: the
module will be called ar0521.
+config VIDEO_GC0308
+ tristate "GalaxyCore GC0308 sensor support"
+ select V4L2_CCI_I2C
+ help
+ This is a Video4Linux2 sensor driver for the GalaxyCore
+ GC0308 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gc0308.
+
+config VIDEO_GC2145
+ select V4L2_CCI_I2C
+ tristate "GalaxyCore GC2145 sensor support"
+ help
+ This is a V4L2 sensor-level driver for GalaxyCore GC2145
+ 2 Mpixel camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gc2145.
+
config VIDEO_HI556
tristate "Hynix Hi-556 sensor support"
help
@@ -455,6 +485,16 @@ config VIDEO_OV5695
To compile this driver as a module, choose M here: the
module will be called ov5695.
+config VIDEO_OV64A40
+ tristate "OmniVision OV64A40 sensor support"
+ select V4L2_CCI_I2C
+ help
+ This is a Video4Linux2 sensor driver for the OmniVision
+ OV64A40 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ov64a40.
+
config VIDEO_OV6650
tristate "OmniVision OV6650 sensor support"
help
@@ -628,6 +668,23 @@ source "drivers/media/i2c/et8ek8/Kconfig"
endif
+menu "Camera ISPs"
+ visible if MEDIA_CAMERA_SUPPORT
+
+config VIDEO_THP7312
+ tristate "THine THP7312 support"
+ depends on I2C
+ select FW_LOADER
+ select MEDIA_CONTROLLER
+ select V4L2_CCI_I2C
+ select V4L2_FWNODE
+ select VIDEO_V4L2_SUBDEV_API
+ help
+ This is a Video4Linux2 sensor-level driver for the THine
+ THP7312 ISP.
+
+endmenu
+
menu "Lens drivers"
visible if MEDIA_CAMERA_SUPPORT
@@ -1186,6 +1243,21 @@ config VIDEO_TW2804
To compile this driver as a module, choose M here: the
module will be called tw2804.
+config VIDEO_TW9900
+ tristate "Techwell TW9900 video decoder"
+ depends on GPIOLIB
+ depends on VIDEO_DEV && I2C
+ depends on PM
+ select MEDIA_CONTROLLER
+ select VIDEO_V4L2_SUBDEV_API
+ select V4L2_ASYNC
+ help
+ Support for the Techwell TW9900 multi-standard video decoder.
+ It supports NTSC, PAL standards with auto-detection features.
+
+ To compile this driver as a module, choose M here: the
+ module will be called tw9900.
+
config VIDEO_TW9903
tristate "Techwell TW9903 video decoder"
depends on VIDEO_DEV && I2C
@@ -1432,6 +1504,7 @@ config VIDEO_ST_MIPID02
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
+ select V4L2_CCI_I2C
select V4L2_FWNODE
help
Support for STMicroelectronics MIPID02 CSI-2 to PARALLEL bridge.
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index f5010f80a2..dfbe6448b5 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o
obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o
obj-$(CONFIG_VIDEO_AK7375) += ak7375.o
obj-$(CONFIG_VIDEO_AK881X) += ak881x.o
+obj-$(CONFIG_VIDEO_ALVIUM_CSI2) += alvium-csi2.o
obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
obj-$(CONFIG_VIDEO_AR0521) += ar0521.o
obj-$(CONFIG_VIDEO_BT819) += bt819.o
@@ -36,6 +37,8 @@ obj-$(CONFIG_VIDEO_DW9719) += dw9719.o
obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/
+obj-$(CONFIG_VIDEO_GC0308) += gc0308.o
+obj-$(CONFIG_VIDEO_GC2145) += gc2145.o
obj-$(CONFIG_VIDEO_HI556) += hi556.o
obj-$(CONFIG_VIDEO_HI846) += hi846.o
obj-$(CONFIG_VIDEO_HI847) += hi847.o
@@ -92,6 +95,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o
obj-$(CONFIG_VIDEO_OV5675) += ov5675.o
obj-$(CONFIG_VIDEO_OV5693) += ov5693.o
obj-$(CONFIG_VIDEO_OV5695) += ov5695.o
+obj-$(CONFIG_VIDEO_OV64A40) += ov64a40.o
obj-$(CONFIG_VIDEO_OV6650) += ov6650.o
obj-$(CONFIG_VIDEO_OV7251) += ov7251.o
obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
@@ -128,6 +132,7 @@ obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
+obj-$(CONFIG_VIDEO_THP7312) += thp7312.o
obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
obj-$(CONFIG_VIDEO_THS8200) += ths8200.o
obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
@@ -136,6 +141,7 @@ obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
obj-$(CONFIG_VIDEO_TW2804) += tw2804.o
+obj-$(CONFIG_VIDEO_TW9900) += tw9900.o
obj-$(CONFIG_VIDEO_TW9903) += tw9903.o
obj-$(CONFIG_VIDEO_TW9906) += tw9906.o
obj-$(CONFIG_VIDEO_TW9910) += tw9910.o
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index 5413447318..409b9a37f0 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -463,11 +463,19 @@ static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
return 0;
}
-static int adv7180_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int adv7180_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct adv7180_state *state = to_state(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (state->curr_norm & V4L2_STD_525_60) {
fi->interval.numerator = 1001;
fi->interval.denominator = 30000;
@@ -769,7 +777,7 @@ static int adv7180_get_pad_format(struct v4l2_subdev *sd,
struct adv7180_state *state = to_state(sd);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- format->format = *v4l2_subdev_get_try_format(sd, sd_state, 0);
+ format->format = *v4l2_subdev_state_get_format(sd_state, 0);
} else {
adv7180_mbus_fmt(sd, &format->format);
format->format.field = state->field;
@@ -806,15 +814,15 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd,
adv7180_set_power(state, true);
}
} else {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ framefmt = v4l2_subdev_state_get_format(sd_state, 0);
*framefmt = format->format;
}
return ret;
}
-static int adv7180_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int adv7180_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_subdev_format fmt = {
.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY
@@ -913,7 +921,6 @@ static int adv7180_subscribe_event(struct v4l2_subdev *sd,
static const struct v4l2_subdev_video_ops adv7180_video_ops = {
.s_std = adv7180_s_std,
.g_std = adv7180_g_std,
- .g_frame_interval = adv7180_g_frame_interval,
.querystd = adv7180_querystd,
.g_input_status = adv7180_g_input_status,
.s_routing = adv7180_s_routing,
@@ -929,10 +936,10 @@ static const struct v4l2_subdev_core_ops adv7180_core_ops = {
};
static const struct v4l2_subdev_pad_ops adv7180_pad_ops = {
- .init_cfg = adv7180_init_cfg,
.enum_mbus_code = adv7180_enum_mbus_code,
.set_fmt = adv7180_set_pad_format,
.get_fmt = adv7180_get_pad_format,
+ .get_frame_interval = adv7180_get_frame_interval,
.get_mbus_config = adv7180_get_mbus_config,
};
@@ -947,6 +954,10 @@ static const struct v4l2_subdev_ops adv7180_ops = {
.sensor = &adv7180_sensor_ops,
};
+static const struct v4l2_subdev_internal_ops adv7180_internal_ops = {
+ .init_state = adv7180_init_state,
+};
+
static irqreturn_t adv7180_irq(int irq, void *devid)
{
struct adv7180_state *state = devid;
@@ -1458,6 +1469,7 @@ static int adv7180_probe(struct i2c_client *client)
state->input = 0;
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
+ sd->internal_ops = &adv7180_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
ret = adv7180_init_controls(state);
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
index 3659feafac..2a2cace4a1 100644
--- a/drivers/media/i2c/adv7183.c
+++ b/drivers/media/i2c/adv7183.c
@@ -442,8 +442,6 @@ static int adv7183_set_fmt(struct v4l2_subdev *sd,
}
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
decoder->fmt = *fmt;
- else
- sd_state->pads->try_fmt = *fmt;
return 0;
}
diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c
index 00095c7762..50d9fbadbe 100644
--- a/drivers/media/i2c/adv748x/adv748x-afe.c
+++ b/drivers/media/i2c/adv748x/adv748x-afe.c
@@ -354,8 +354,8 @@ static int adv748x_afe_get_format(struct v4l2_subdev *sd,
return -EINVAL;
if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
- mbusformat = v4l2_subdev_get_try_format(sd, sd_state,
- sdformat->pad);
+ mbusformat = v4l2_subdev_state_get_format(sd_state,
+ sdformat->pad);
sdformat->format = *mbusformat;
} else {
adv748x_afe_fill_format(afe, &sdformat->format);
@@ -378,7 +378,7 @@ static int adv748x_afe_set_format(struct v4l2_subdev *sd,
if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
return adv748x_afe_get_format(sd, sd_state, sdformat);
- mbusformat = v4l2_subdev_get_try_format(sd, sd_state, sdformat->pad);
+ mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
*mbusformat = sdformat->format;
return 0;
diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c
index a5a7cb2288..5b265b7223 100644
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
@@ -147,7 +147,7 @@ adv748x_csi2_get_pad_format(struct v4l2_subdev *sd,
struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(sd, sd_state, pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
return &tx->format;
}
diff --git a/drivers/media/i2c/adv748x/adv748x-hdmi.c b/drivers/media/i2c/adv748x/adv748x-hdmi.c
index 400d71c274..ec151dc69c 100644
--- a/drivers/media/i2c/adv748x/adv748x-hdmi.c
+++ b/drivers/media/i2c/adv748x/adv748x-hdmi.c
@@ -441,8 +441,8 @@ static int adv748x_hdmi_get_format(struct v4l2_subdev *sd,
return -EINVAL;
if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
- mbusformat = v4l2_subdev_get_try_format(sd, sd_state,
- sdformat->pad);
+ mbusformat = v4l2_subdev_state_get_format(sd_state,
+ sdformat->pad);
sdformat->format = *mbusformat;
} else {
adv748x_hdmi_fill_format(hdmi, &sdformat->format);
@@ -464,7 +464,7 @@ static int adv748x_hdmi_set_format(struct v4l2_subdev *sd,
if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
return adv748x_hdmi_get_format(sd, sd_state, sdformat);
- mbusformat = v4l2_subdev_get_try_format(sd, sd_state, sdformat->pad);
+ mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
*mbusformat = sdformat->format;
return 0;
diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c
index a9183d9282..0f780eb6ef 100644
--- a/drivers/media/i2c/adv7511-v4l2.c
+++ b/drivers/media/i2c/adv7511-v4l2.c
@@ -1238,7 +1238,7 @@ static int adv7511_get_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
format->format.code = fmt->code;
format->format.colorspace = fmt->colorspace;
format->format.ycbcr_enc = fmt->ycbcr_enc;
@@ -1293,7 +1293,7 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
fmt->code = format->format.code;
fmt->colorspace = format->format.colorspace;
fmt->ycbcr_enc = format->format.ycbcr_enc;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index b202a85fbe..810fa8826f 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1929,7 +1929,7 @@ static int adv76xx_get_format(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
format->format.code = fmt->code;
} else {
format->format.code = state->format->code;
@@ -1978,7 +1978,7 @@ static int adv76xx_set_format(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
fmt->code = format->format.code;
} else {
state->format = info;
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index c1664a3620..2ad0f9f550 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -2087,7 +2087,7 @@ static int adv7842_get_format(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
format->format.code = fmt->code;
} else {
format->format.code = state->format->code;
@@ -2119,7 +2119,7 @@ static int adv7842_set_format(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
fmt->code = format->format.code;
} else {
state->format = info;
diff --git a/drivers/media/i2c/ak7375.c b/drivers/media/i2c/ak7375.c
index 463b51d463..9a2432cea3 100644
--- a/drivers/media/i2c/ak7375.c
+++ b/drivers/media/i2c/ak7375.c
@@ -10,30 +10,60 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
-#define AK7375_MAX_FOCUS_POS 4095
-/*
- * This sets the minimum granularity for the focus positions.
- * A value of 1 gives maximum accuracy for a desired focus position
- */
-#define AK7375_FOCUS_STEPS 1
-/*
- * This acts as the minimum granularity of lens movement.
- * Keep this value power of 2, so the control steps can be
- * uniformly adjusted for gradual lens movement, with desired
- * number of control steps.
- */
-#define AK7375_CTRL_STEPS 64
-#define AK7375_CTRL_DELAY_US 1000
-/*
- * The vcm may take up 10 ms (tDELAY) to power on and start taking
- * I2C messages. Based on AK7371 datasheet.
- */
-#define AK7375_POWER_DELAY_US 10000
+struct ak73xx_chipdef {
+ u8 reg_position;
+ u8 reg_cont;
+ u8 shift_pos;
+ u8 mode_active;
+ u8 mode_standby;
+ bool has_standby; /* Some chips may not have standby mode */
+ u16 focus_pos_max;
+ /*
+ * This sets the minimum granularity for the focus positions.
+ * A value of 1 gives maximum accuracy for a desired focus position
+ */
+ u16 focus_steps;
+ /*
+ * This acts as the minimum granularity of lens movement.
+ * Keep this value power of 2, so the control steps can be
+ * uniformly adjusted for gradual lens movement, with desired
+ * number of control steps.
+ */
+ u16 ctrl_steps;
+ u16 ctrl_delay_us;
+ /*
+ * The vcm may take time (tDELAY) to power on and start taking
+ * I2C messages.
+ */
+ u16 power_delay_us;
+};
-#define AK7375_REG_POSITION 0x0
-#define AK7375_REG_CONT 0x2
-#define AK7375_MODE_ACTIVE 0x0
-#define AK7375_MODE_STANDBY 0x40
+static const struct ak73xx_chipdef ak7345_cdef = {
+ .reg_position = 0x0,
+ .reg_cont = 0x2,
+ .shift_pos = 7, /* 9 bits position values, need to << 7 */
+ .mode_active = 0x0,
+ .has_standby = false,
+ .focus_pos_max = 511,
+ .focus_steps = 1,
+ .ctrl_steps = 16,
+ .ctrl_delay_us = 1000,
+ .power_delay_us = 20000,
+};
+
+static const struct ak73xx_chipdef ak7375_cdef = {
+ .reg_position = 0x0,
+ .reg_cont = 0x2,
+ .shift_pos = 4, /* 12 bits position values, need to << 4 */
+ .mode_active = 0x0,
+ .mode_standby = 0x40,
+ .has_standby = true,
+ .focus_pos_max = 4095,
+ .focus_steps = 1,
+ .ctrl_steps = 64,
+ .ctrl_delay_us = 1000,
+ .power_delay_us = 10000,
+};
static const char * const ak7375_supply_names[] = {
"vdd",
@@ -42,6 +72,7 @@ static const char * const ak7375_supply_names[] = {
/* ak7375 device structure */
struct ak7375_device {
+ const struct ak73xx_chipdef *cdef;
struct v4l2_ctrl_handler ctrls_vcm;
struct v4l2_subdev sd;
struct v4l2_ctrl *focus;
@@ -86,10 +117,11 @@ static int ak7375_i2c_write(struct ak7375_device *ak7375,
static int ak7375_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct ak7375_device *dev_vcm = to_ak7375_vcm(ctrl);
+ const struct ak73xx_chipdef *cdef = dev_vcm->cdef;
if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE)
- return ak7375_i2c_write(dev_vcm, AK7375_REG_POSITION,
- ctrl->val << 4, 2);
+ return ak7375_i2c_write(dev_vcm, cdef->reg_position,
+ ctrl->val << cdef->shift_pos, 2);
return -EINVAL;
}
@@ -128,11 +160,12 @@ static int ak7375_init_controls(struct ak7375_device *dev_vcm)
{
struct v4l2_ctrl_handler *hdl = &dev_vcm->ctrls_vcm;
const struct v4l2_ctrl_ops *ops = &ak7375_vcm_ctrl_ops;
+ const struct ak73xx_chipdef *cdef = dev_vcm->cdef;
v4l2_ctrl_handler_init(hdl, 1);
dev_vcm->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
- 0, AK7375_MAX_FOCUS_POS, AK7375_FOCUS_STEPS, 0);
+ 0, cdef->focus_pos_max, cdef->focus_steps, 0);
if (hdl->error)
dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n",
@@ -153,6 +186,8 @@ static int ak7375_probe(struct i2c_client *client)
if (!ak7375_dev)
return -ENOMEM;
+ ak7375_dev->cdef = device_get_match_data(&client->dev);
+
for (i = 0; i < ARRAY_SIZE(ak7375_supply_names); i++)
ak7375_dev->supplies[i].supply = ak7375_supply_names[i];
@@ -206,32 +241,35 @@ static void ak7375_remove(struct i2c_client *client)
/*
* This function sets the vcm position, so it consumes least current
- * The lens position is gradually moved in units of AK7375_CTRL_STEPS,
+ * The lens position is gradually moved in units of ctrl_steps,
* to make the movements smoothly.
*/
static int __maybe_unused ak7375_vcm_suspend(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd);
+ const struct ak73xx_chipdef *cdef = ak7375_dev->cdef;
int ret, val;
if (!ak7375_dev->active)
return 0;
- for (val = ak7375_dev->focus->val & ~(AK7375_CTRL_STEPS - 1);
- val >= 0; val -= AK7375_CTRL_STEPS) {
- ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_POSITION,
- val << 4, 2);
+ for (val = ak7375_dev->focus->val & ~(cdef->ctrl_steps - 1);
+ val >= 0; val -= cdef->ctrl_steps) {
+ ret = ak7375_i2c_write(ak7375_dev, cdef->reg_position,
+ val << cdef->shift_pos, 2);
if (ret)
dev_err_once(dev, "%s I2C failure: %d\n",
__func__, ret);
- usleep_range(AK7375_CTRL_DELAY_US, AK7375_CTRL_DELAY_US + 10);
+ usleep_range(cdef->ctrl_delay_us, cdef->ctrl_delay_us + 10);
}
- ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_CONT,
- AK7375_MODE_STANDBY, 1);
- if (ret)
- dev_err(dev, "%s I2C failure: %d\n", __func__, ret);
+ if (cdef->has_standby) {
+ ret = ak7375_i2c_write(ak7375_dev, cdef->reg_cont,
+ cdef->mode_standby, 1);
+ if (ret)
+ dev_err(dev, "%s I2C failure: %d\n", __func__, ret);
+ }
ret = regulator_bulk_disable(ARRAY_SIZE(ak7375_supply_names),
ak7375_dev->supplies);
@@ -246,13 +284,14 @@ static int __maybe_unused ak7375_vcm_suspend(struct device *dev)
/*
* This function sets the vcm position to the value set by the user
* through v4l2_ctrl_ops s_ctrl handler
- * The lens position is gradually moved in units of AK7375_CTRL_STEPS,
+ * The lens position is gradually moved in units of ctrl_steps,
* to make the movements smoothly.
*/
static int __maybe_unused ak7375_vcm_resume(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd);
+ const struct ak73xx_chipdef *cdef = ak7375_dev->cdef;
int ret, val;
if (ak7375_dev->active)
@@ -264,24 +303,24 @@ static int __maybe_unused ak7375_vcm_resume(struct device *dev)
return ret;
/* Wait for vcm to become ready */
- usleep_range(AK7375_POWER_DELAY_US, AK7375_POWER_DELAY_US + 500);
+ usleep_range(cdef->power_delay_us, cdef->power_delay_us + 500);
- ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_CONT,
- AK7375_MODE_ACTIVE, 1);
+ ret = ak7375_i2c_write(ak7375_dev, cdef->reg_cont,
+ cdef->mode_active, 1);
if (ret) {
dev_err(dev, "%s I2C failure: %d\n", __func__, ret);
return ret;
}
- for (val = ak7375_dev->focus->val % AK7375_CTRL_STEPS;
+ for (val = ak7375_dev->focus->val % cdef->ctrl_steps;
val <= ak7375_dev->focus->val;
- val += AK7375_CTRL_STEPS) {
- ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_POSITION,
- val << 4, 2);
+ val += cdef->ctrl_steps) {
+ ret = ak7375_i2c_write(ak7375_dev, cdef->reg_position,
+ val << cdef->shift_pos, 2);
if (ret)
dev_err_ratelimited(dev, "%s I2C failure: %d\n",
__func__, ret);
- usleep_range(AK7375_CTRL_DELAY_US, AK7375_CTRL_DELAY_US + 10);
+ usleep_range(cdef->ctrl_delay_us, cdef->ctrl_delay_us + 10);
}
ak7375_dev->active = true;
@@ -290,7 +329,8 @@ static int __maybe_unused ak7375_vcm_resume(struct device *dev)
}
static const struct of_device_id ak7375_of_table[] = {
- { .compatible = "asahi-kasei,ak7375" },
+ { .compatible = "asahi-kasei,ak7345", .data = &ak7345_cdef, },
+ { .compatible = "asahi-kasei,ak7375", .data = &ak7375_cdef, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ak7375_of_table);
diff --git a/drivers/media/i2c/alvium-csi2.c b/drivers/media/i2c/alvium-csi2.c
new file mode 100644
index 0000000000..34ff7fad38
--- /dev/null
+++ b/drivers/media/i2c/alvium-csi2.c
@@ -0,0 +1,2558 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allied Vision Technologies GmbH Alvium camera driver
+ *
+ * Copyright (C) 2023 Tommaso Merciai
+ * Copyright (C) 2023 Martin Hecht
+ * Copyright (C) 2023 Avnet EMG GmbH
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <media/mipi-csi2.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#include "alvium-csi2.h"
+
+static const struct v4l2_mbus_framefmt alvium_csi2_default_fmt = {
+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .width = 640,
+ .height = 480,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB),
+ .quantization = V4L2_QUANTIZATION_FULL_RANGE,
+ .xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB),
+ .field = V4L2_FIELD_NONE,
+};
+
+static const struct alvium_pixfmt alvium_csi2_fmts[] = {
+ {
+ /* UYVY8_2X8 */
+ .id = ALVIUM_FMT_UYVY8_2X8,
+ .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_YUV422_8,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_YUV422_8B,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* UYVY8_1X16 */
+ .id = ALVIUM_FMT_UYVY8_1X16,
+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_YUV422_8,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_YUV422_8B,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* YUYV8_1X16 */
+ .id = ALVIUM_FMT_YUYV8_1X16,
+ .code = MEDIA_BUS_FMT_YUYV8_1X16,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_YUV422_8,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_YUV422_8B,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* YUYV8_2X8 */
+ .id = ALVIUM_FMT_YUYV8_2X8,
+ .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_YUV422_8,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_YUV422_8B,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* YUYV10_1X20 */
+ .id = ALVIUM_FMT_YUYV10_1X20,
+ .code = MEDIA_BUS_FMT_YUYV10_1X20,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_YUV422_10,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_YUV422_10B,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* RGB888_1X24 */
+ .id = ALVIUM_FMT_RGB888_1X24,
+ .code = MEDIA_BUS_FMT_RGB888_1X24,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_RGB888,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RGB888,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* RBG888_1X24 */
+ .id = ALVIUM_FMT_RBG888_1X24,
+ .code = MEDIA_BUS_FMT_RBG888_1X24,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_RGB888,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RGB888,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* BGR888_1X24 */
+ .id = ALVIUM_FMT_BGR888_1X24,
+ .code = MEDIA_BUS_FMT_BGR888_1X24,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_RGB888,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RGB888,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* RGB888_3X8 */
+ .id = ALVIUM_FMT_RGB888_3X8,
+ .code = MEDIA_BUS_FMT_RGB888_3X8,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .fmt_av_bit = ALVIUM_BIT_RGB888,
+ .bay_av_bit = ALVIUM_BIT_BAY_NONE,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RGB888,
+ .bay_fmt_regval = -1,
+ .is_raw = 0,
+ }, {
+ /* Y8_1X8 */
+ .id = ALVIUM_FMT_Y8_1X8,
+ .code = MEDIA_BUS_FMT_Y8_1X8,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW8,
+ .bay_av_bit = ALVIUM_BIT_BAY_MONO,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
+ .bay_fmt_regval = 0x00,
+ .is_raw = 1,
+ }, {
+ /* SGRBG8_1X8 */
+ .id = ALVIUM_FMT_SGRBG8_1X8,
+ .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW8,
+ .bay_av_bit = ALVIUM_BIT_BAY_GR,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
+ .bay_fmt_regval = 0x01,
+ .is_raw = 1,
+ }, {
+ /* SRGGB8_1X8 */
+ .id = ALVIUM_FMT_SRGGB8_1X8,
+ .code = MEDIA_BUS_FMT_SRGGB8_1X8,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW8,
+ .bay_av_bit = ALVIUM_BIT_BAY_RG,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
+ .bay_fmt_regval = 0x02,
+ .is_raw = 1,
+ }, {
+ /* SGBRG8_1X8 */
+ .id = ALVIUM_FMT_SGBRG8_1X8,
+ .code = MEDIA_BUS_FMT_SGBRG8_1X8,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW8,
+ .bay_av_bit = ALVIUM_BIT_BAY_GB,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
+ .bay_fmt_regval = 0x03,
+ .is_raw = 1,
+ }, {
+ /* SBGGR8_1X8 */
+ .id = ALVIUM_FMT_SBGGR8_1X8,
+ .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW8,
+ .bay_av_bit = ALVIUM_BIT_BAY_BG,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW8,
+ .bay_fmt_regval = 0x04,
+ .is_raw = 1,
+ }, {
+ /* Y10_1X10 */
+ .id = ALVIUM_FMT_Y10_1X10,
+ .code = MEDIA_BUS_FMT_Y10_1X10,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW10,
+ .bay_av_bit = ALVIUM_BIT_BAY_MONO,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
+ .bay_fmt_regval = 0x00,
+ .is_raw = 1,
+ }, {
+ /* SGRBG10_1X10 */
+ .id = ALVIUM_FMT_SGRBG10_1X10,
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW10,
+ .bay_av_bit = ALVIUM_BIT_BAY_GR,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
+ .bay_fmt_regval = 0x01,
+ .is_raw = 1,
+ }, {
+ /* SRGGB10_1X10 */
+ .id = ALVIUM_FMT_SRGGB10_1X10,
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW10,
+ .bay_av_bit = ALVIUM_BIT_BAY_RG,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
+ .bay_fmt_regval = 0x02,
+ .is_raw = 1,
+ }, {
+ /* SGBRG10_1X10 */
+ .id = ALVIUM_FMT_SGBRG10_1X10,
+ .code = MEDIA_BUS_FMT_SGBRG10_1X10,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW10,
+ .bay_av_bit = ALVIUM_BIT_BAY_GB,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
+ .bay_fmt_regval = 0x03,
+ .is_raw = 1,
+ }, {
+ /* SBGGR10_1X10 */
+ .id = ALVIUM_FMT_SBGGR10_1X10,
+ .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW10,
+ .bay_av_bit = ALVIUM_BIT_BAY_BG,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW10,
+ .bay_fmt_regval = 0x04,
+ .is_raw = 1,
+ }, {
+ /* Y12_1X12 */
+ .id = ALVIUM_FMT_Y12_1X12,
+ .code = MEDIA_BUS_FMT_Y12_1X12,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW12,
+ .bay_av_bit = ALVIUM_BIT_BAY_MONO,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
+ .bay_fmt_regval = 0x00,
+ .is_raw = 1,
+ }, {
+ /* SGRBG12_1X12 */
+ .id = ALVIUM_FMT_SGRBG12_1X12,
+ .code = MEDIA_BUS_FMT_SGRBG12_1X12,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW12,
+ .bay_av_bit = ALVIUM_BIT_BAY_GR,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
+ .bay_fmt_regval = 0x01,
+ .is_raw = 1,
+ }, {
+ /* SRGGB12_1X12 */
+ .id = ALVIUM_FMT_SRGGB12_1X12,
+ .code = MEDIA_BUS_FMT_SRGGB12_1X12,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW12,
+ .bay_av_bit = ALVIUM_BIT_BAY_RG,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
+ .bay_fmt_regval = 0x02,
+ .is_raw = 1,
+ }, {
+ /* SGBRG12_1X12 */
+ .id = ALVIUM_FMT_SGBRG12_1X12,
+ .code = MEDIA_BUS_FMT_SGBRG12_1X12,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW12,
+ .bay_av_bit = ALVIUM_BIT_BAY_GB,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
+ .bay_fmt_regval = 0x03,
+ .is_raw = 1,
+ }, {
+ /* SBGGR12_1X12 */
+ .id = ALVIUM_FMT_SBGGR12_1X12,
+ .code = MEDIA_BUS_FMT_SBGGR12_1X12,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW12,
+ .bay_av_bit = ALVIUM_BIT_BAY_BG,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW12,
+ .bay_fmt_regval = 0x04,
+ .is_raw = 1,
+ }, {
+ /* SBGGR14_1X14 */
+ .id = ALVIUM_FMT_SBGGR14_1X14,
+ .code = MEDIA_BUS_FMT_SBGGR14_1X14,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW14,
+ .bay_av_bit = ALVIUM_BIT_BAY_GR,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW14,
+ .bay_fmt_regval = 0x01,
+ .is_raw = 1,
+ }, {
+ /* SGBRG14_1X14 */
+ .id = ALVIUM_FMT_SGBRG14_1X14,
+ .code = MEDIA_BUS_FMT_SGBRG14_1X14,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW14,
+ .bay_av_bit = ALVIUM_BIT_BAY_RG,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW14,
+ .bay_fmt_regval = 0x02,
+ .is_raw = 1,
+ }, {
+ /* SRGGB14_1X14 */
+ .id = ALVIUM_FMT_SRGGB14_1X14,
+ .code = MEDIA_BUS_FMT_SRGGB14_1X14,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW14,
+ .bay_av_bit = ALVIUM_BIT_BAY_GB,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW14,
+ .bay_fmt_regval = 0x03,
+ .is_raw = 1,
+ }, {
+ /* SGRBG14_1X14 */
+ .id = ALVIUM_FMT_SGRBG14_1X14,
+ .code = MEDIA_BUS_FMT_SGRBG14_1X14,
+ .colorspace = V4L2_COLORSPACE_RAW,
+ .fmt_av_bit = ALVIUM_BIT_RAW14,
+ .bay_av_bit = ALVIUM_BIT_BAY_BG,
+ .mipi_fmt_regval = MIPI_CSI2_DT_RAW14,
+ .bay_fmt_regval = 0x04,
+ .is_raw = 1,
+ },
+ { /* sentinel */ }
+};
+
+static int alvium_read(struct alvium_dev *alvium, u32 reg, u64 *val, int *err)
+{
+ if (reg & REG_BCRM_V4L2) {
+ reg &= ~REG_BCRM_V4L2;
+ reg += alvium->bcrm_addr;
+ }
+
+ return cci_read(alvium->regmap, reg, val, err);
+}
+
+static int alvium_write(struct alvium_dev *alvium, u32 reg, u64 val, int *err)
+{
+ if (reg & REG_BCRM_V4L2) {
+ reg &= ~REG_BCRM_V4L2;
+ reg += alvium->bcrm_addr;
+ }
+
+ return cci_write(alvium->regmap, reg, val, err);
+}
+
+static int alvium_write_hshake(struct alvium_dev *alvium, u32 reg, u64 val)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ u64 hshake_bit;
+ int ret = 0;
+
+ /* reset handshake bit and write alvium reg */
+ alvium_write(alvium, REG_BCRM_WRITE_HANDSHAKE_RW, 0, &ret);
+ alvium_write(alvium, reg, val, &ret);
+ if (ret) {
+ dev_err(dev, "Fail to write reg\n");
+ return ret;
+ }
+
+ /* poll handshake bit since bit0 = 1 */
+ read_poll_timeout(alvium_read, hshake_bit,
+ ((hshake_bit & BCRM_HANDSHAKE_W_DONE_EN_BIT) == 1),
+ 15000, 45000, true,
+ alvium, REG_BCRM_WRITE_HANDSHAKE_RW,
+ &hshake_bit, &ret);
+ if (ret) {
+ dev_err(dev, "poll bit[0] = 1, hshake reg fail\n");
+ return ret;
+ }
+
+ /* reset handshake bit, write 0 to bit0 */
+ alvium_write(alvium, REG_BCRM_WRITE_HANDSHAKE_RW, 0, &ret);
+ if (ret) {
+ dev_err(dev, "Fail to reset hshake reg\n");
+ return ret;
+ }
+
+ /* poll handshake bit since bit0 = 0 */
+ read_poll_timeout(alvium_read, hshake_bit,
+ ((hshake_bit & BCRM_HANDSHAKE_W_DONE_EN_BIT) == 0),
+ 15000, 45000, true,
+ alvium, REG_BCRM_WRITE_HANDSHAKE_RW,
+ &hshake_bit, &ret);
+ if (ret) {
+ dev_err(dev, "poll bit[0] = 0, hshake reg fail\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_bcrm_vers(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ u64 min, maj;
+ int ret = 0;
+
+ ret = alvium_read(alvium, REG_BCRM_MINOR_VERSION_R, &min, &ret);
+ ret = alvium_read(alvium, REG_BCRM_MAJOR_VERSION_R, &maj, &ret);
+ if (ret)
+ return ret;
+
+ dev_info(dev, "bcrm version: %llu.%llu\n", min, maj);
+
+ return 0;
+}
+
+static int alvium_get_fw_version(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ u64 spec, maj, min, pat;
+ int ret = 0;
+
+ ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_SPEC_VERSION_R,
+ &spec, &ret);
+ ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_MAJOR_VERSION_R,
+ &maj, &ret);
+ ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_MINOR_VERSION_R,
+ &min, &ret);
+ ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_PATCH_VERSION_R,
+ &pat, &ret);
+ if (ret)
+ return ret;
+
+ dev_info(dev, "fw version: %llu.%llu.%llu.%llu\n", spec, maj, min, pat);
+
+ return 0;
+}
+
+static int alvium_get_bcrm_addr(struct alvium_dev *alvium)
+{
+ u64 val;
+ int ret;
+
+ ret = alvium_read(alvium, REG_BCRM_REG_ADDR_R, &val, NULL);
+ if (ret)
+ return ret;
+
+ alvium->bcrm_addr = val;
+
+ return 0;
+}
+
+static int alvium_is_alive(struct alvium_dev *alvium)
+{
+ u64 bcrm, hbeat;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_MINOR_VERSION_R, &bcrm, &ret);
+ alvium_read(alvium, REG_BCRM_HEARTBEAT_RW, &hbeat, &ret);
+ if (ret)
+ return ret;
+
+ return hbeat;
+}
+
+static void alvium_print_avail_mipi_fmt(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+
+ dev_dbg(dev, "avail mipi_fmt yuv420_8_leg: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8_LEG]);
+ dev_dbg(dev, "avail mipi_fmt yuv420_8: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8]);
+ dev_dbg(dev, "avail mipi_fmt yuv420_10: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_10]);
+ dev_dbg(dev, "avail mipi_fmt yuv420_8_csps: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8_CSPS]);
+ dev_dbg(dev, "avail mipi_fmt yuv420_10_csps: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_10_CSPS]);
+ dev_dbg(dev, "avail mipi_fmt yuv422_8: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV422_8]);
+ dev_dbg(dev, "avail mipi_fmt yuv422_10: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV422_10]);
+ dev_dbg(dev, "avail mipi_fmt rgb888: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB888]);
+ dev_dbg(dev, "avail mipi_fmt rgb666: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB666]);
+ dev_dbg(dev, "avail mipi_fmt rgb565: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB565]);
+ dev_dbg(dev, "avail mipi_fmt rgb555: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB555]);
+ dev_dbg(dev, "avail mipi_fmt rgb444: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB444]);
+ dev_dbg(dev, "avail mipi_fmt raw6: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW6]);
+ dev_dbg(dev, "avail mipi_fmt raw7: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW7]);
+ dev_dbg(dev, "avail mipi_fmt raw8: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW8]);
+ dev_dbg(dev, "avail mipi_fmt raw10: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW10]);
+ dev_dbg(dev, "avail mipi_fmt raw12: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW12]);
+ dev_dbg(dev, "avail mipi_fmt raw14: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW14]);
+ dev_dbg(dev, "avail mipi_fmt jpeg: %u\n",
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_JPEG]);
+}
+
+static void alvium_print_avail_feat(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+
+ dev_dbg(dev, "feature rev_x: %u\n", alvium->avail_ft.rev_x);
+ dev_dbg(dev, "feature rev_y: %u\n", alvium->avail_ft.rev_y);
+ dev_dbg(dev, "feature int_autop: %u\n", alvium->avail_ft.int_autop);
+ dev_dbg(dev, "feature black_lvl: %u\n", alvium->avail_ft.black_lvl);
+ dev_dbg(dev, "feature gain: %u\n", alvium->avail_ft.gain);
+ dev_dbg(dev, "feature gamma: %u\n", alvium->avail_ft.gamma);
+ dev_dbg(dev, "feature contrast: %u\n", alvium->avail_ft.contrast);
+ dev_dbg(dev, "feature sat: %u\n", alvium->avail_ft.sat);
+ dev_dbg(dev, "feature hue: %u\n", alvium->avail_ft.hue);
+ dev_dbg(dev, "feature whiteb: %u\n", alvium->avail_ft.whiteb);
+ dev_dbg(dev, "feature sharp: %u\n", alvium->avail_ft.sharp);
+ dev_dbg(dev, "feature auto_exp: %u\n", alvium->avail_ft.auto_exp);
+ dev_dbg(dev, "feature auto_gain: %u\n", alvium->avail_ft.auto_gain);
+ dev_dbg(dev, "feature auto_whiteb: %u\n", alvium->avail_ft.auto_whiteb);
+ dev_dbg(dev, "feature dev_temp: %u\n", alvium->avail_ft.dev_temp);
+ dev_dbg(dev, "feature acq_abort: %u\n", alvium->avail_ft.acq_abort);
+ dev_dbg(dev, "feature acq_fr: %u\n", alvium->avail_ft.acq_fr);
+ dev_dbg(dev, "feature fr_trigger: %u\n", alvium->avail_ft.fr_trigger);
+ dev_dbg(dev, "feature exp_acq_line: %u\n",
+ alvium->avail_ft.exp_acq_line);
+}
+
+static void alvium_print_avail_bayer(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+
+ dev_dbg(dev, "avail bayer mono: %u\n",
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_MONO]);
+ dev_dbg(dev, "avail bayer gr: %u\n",
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_GR]);
+ dev_dbg(dev, "avail bayer rg: %u\n",
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_RG]);
+ dev_dbg(dev, "avail bayer gb: %u\n",
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_GB]);
+ dev_dbg(dev, "avail bayer bg: %u\n",
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_BG]);
+}
+
+static int alvium_get_feat_inq(struct alvium_dev *alvium)
+{
+ struct alvium_avail_feat *f;
+ u64 val;
+ int ret;
+
+ ret = alvium_read(alvium, REG_BCRM_FEATURE_INQUIRY_R, &val, NULL);
+ if (ret)
+ return ret;
+
+ f = (struct alvium_avail_feat *)&val;
+ alvium->avail_ft = *f;
+ alvium_print_avail_feat(alvium);
+
+ return 0;
+}
+
+static int alvium_get_host_supp_csi_lanes(struct alvium_dev *alvium)
+{
+ u64 val;
+ int ret;
+
+ ret = alvium_read(alvium, REG_BCRM_CSI2_LANE_COUNT_RW, &val, NULL);
+ if (ret)
+ return ret;
+
+ alvium->h_sup_csi_lanes = val;
+
+ return 0;
+}
+
+static int alvium_set_csi_lanes(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ u64 num_lanes;
+ int ret;
+
+ num_lanes = alvium->ep.bus.mipi_csi2.num_data_lanes;
+
+ if (num_lanes > alvium->h_sup_csi_lanes)
+ return -EINVAL;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_CSI2_LANE_COUNT_RW,
+ num_lanes);
+ if (ret) {
+ dev_err(dev, "Fail to set csi lanes reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_lp2hs_delay(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret = 0;
+
+ /*
+ * The purpose of this reg is force a DPhy reset
+ * for the period described by the millisecond on
+ * the reg, before it starts streaming.
+ *
+ * To be clear, with that value bigger than 0 the
+ * Alvium forces a dphy-reset on all lanes for that period.
+ * That means all lanes go up into low power state.
+ *
+ */
+ alvium_write(alvium, REG_BCRM_LP2HS_DELAY_RW,
+ ALVIUM_LP2HS_DELAY_MS, &ret);
+ if (ret) {
+ dev_err(dev, "Fail to set lp2hs delay reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_csi_clk_params(struct alvium_dev *alvium)
+{
+ u64 min_csi_clk, max_csi_clk;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_CSI2_CLOCK_MIN_R, &min_csi_clk, &ret);
+ alvium_read(alvium, REG_BCRM_CSI2_CLOCK_MAX_R, &max_csi_clk, &ret);
+ if (ret)
+ return ret;
+
+ alvium->min_csi_clk = min_csi_clk;
+ alvium->max_csi_clk = max_csi_clk;
+
+ return 0;
+}
+
+static int alvium_set_csi_clk(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ u64 csi_clk;
+ int ret;
+
+ csi_clk = clamp(alvium->ep.link_frequencies[0],
+ (u64)alvium->min_csi_clk, (u64)alvium->max_csi_clk);
+
+ if (alvium->ep.link_frequencies[0] != (u64)csi_clk) {
+ dev_warn(dev,
+ "requested csi clock (%llu MHz) out of range [%u, %u] Adjusted to %llu\n",
+ alvium->ep.link_frequencies[0],
+ alvium->min_csi_clk, alvium->max_csi_clk, csi_clk);
+ }
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_CSI2_CLOCK_RW, csi_clk);
+ if (ret) {
+ dev_err(dev, "Fail to set csi clock reg\n");
+ return ret;
+ }
+
+ alvium->link_freq = csi_clk;
+
+ return 0;
+}
+
+static int alvium_get_img_width_params(struct alvium_dev *alvium)
+{
+ u64 imgw, imgw_min, imgw_max, imgw_inc;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_IMG_WIDTH_RW, &imgw, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_WIDTH_MIN_R, &imgw_min, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_WIDTH_MAX_R, &imgw_max, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_WIDTH_INC_R, &imgw_inc, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_img_width = imgw;
+ alvium->img_min_width = imgw_min;
+ alvium->img_max_width = imgw_max;
+ alvium->img_inc_width = imgw_inc;
+
+ return 0;
+}
+
+static int alvium_get_img_height_params(struct alvium_dev *alvium)
+{
+ u64 imgh, imgh_min, imgh_max, imgh_inc;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_IMG_HEIGHT_RW, &imgh, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_HEIGHT_MIN_R, &imgh_min, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_HEIGHT_MAX_R, &imgh_max, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_HEIGHT_INC_R, &imgh_inc, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_img_height = imgh;
+ alvium->img_min_height = imgh_min;
+ alvium->img_max_height = imgh_max;
+ alvium->img_inc_height = imgh_inc;
+
+ return 0;
+}
+
+static int alvium_set_img_width(struct alvium_dev *alvium, u32 width)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_IMG_WIDTH_RW, width);
+ if (ret) {
+ dev_err(dev, "Fail to set img width\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_img_height(struct alvium_dev *alvium, u32 height)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_IMG_HEIGHT_RW, height);
+ if (ret) {
+ dev_err(dev, "Fail to set img height\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_img_offx(struct alvium_dev *alvium, u32 offx)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_IMG_OFFSET_X_RW, offx);
+ if (ret) {
+ dev_err(dev, "Fail to set img offx\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_img_offy(struct alvium_dev *alvium, u32 offy)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_IMG_OFFSET_Y_RW, offy);
+ if (ret) {
+ dev_err(dev, "Fail to set img offy\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_offx_params(struct alvium_dev *alvium)
+{
+ u64 min_offx, max_offx, inc_offx;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_IMG_OFFSET_X_MIN_R, &min_offx, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_OFFSET_X_MAX_R, &max_offx, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_OFFSET_X_INC_R, &inc_offx, &ret);
+ if (ret)
+ return ret;
+
+ alvium->min_offx = min_offx;
+ alvium->max_offx = max_offx;
+ alvium->inc_offx = inc_offx;
+
+ return 0;
+}
+
+static int alvium_get_offy_params(struct alvium_dev *alvium)
+{
+ u64 min_offy, max_offy, inc_offy;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_IMG_OFFSET_Y_MIN_R, &min_offy, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_OFFSET_Y_MAX_R, &max_offy, &ret);
+ alvium_read(alvium, REG_BCRM_IMG_OFFSET_Y_INC_R, &inc_offy, &ret);
+ if (ret)
+ return ret;
+
+ alvium->min_offy = min_offy;
+ alvium->max_offy = max_offy;
+ alvium->inc_offy = inc_offy;
+
+ return 0;
+}
+
+static int alvium_get_gain_params(struct alvium_dev *alvium)
+{
+ u64 dft_gain, min_gain, max_gain, inc_gain;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_GAIN_RW, &dft_gain, &ret);
+ alvium_read(alvium, REG_BCRM_GAIN_MIN_R, &min_gain, &ret);
+ alvium_read(alvium, REG_BCRM_GAIN_MAX_R, &max_gain, &ret);
+ alvium_read(alvium, REG_BCRM_GAIN_INC_R, &inc_gain, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_gain = dft_gain;
+ alvium->min_gain = min_gain;
+ alvium->max_gain = max_gain;
+ alvium->inc_gain = inc_gain;
+
+ return 0;
+}
+
+static int alvium_get_exposure_params(struct alvium_dev *alvium)
+{
+ u64 dft_exp, min_exp, max_exp, inc_exp;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_RW, &dft_exp, &ret);
+ alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_MIN_R, &min_exp, &ret);
+ alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_MAX_R, &max_exp, &ret);
+ alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_INC_R, &inc_exp, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_exp = dft_exp;
+ alvium->min_exp = min_exp;
+ alvium->max_exp = max_exp;
+ alvium->inc_exp = inc_exp;
+
+ return 0;
+}
+
+static int alvium_get_red_balance_ratio_params(struct alvium_dev *alvium)
+{
+ u64 dft_rb, min_rb, max_rb, inc_rb;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_RED_BALANCE_RATIO_RW, &dft_rb, &ret);
+ alvium_read(alvium, REG_BCRM_RED_BALANCE_RATIO_MIN_R, &min_rb, &ret);
+ alvium_read(alvium, REG_BCRM_RED_BALANCE_RATIO_MAX_R, &max_rb, &ret);
+ alvium_read(alvium, REG_BCRM_RED_BALANCE_RATIO_INC_R, &inc_rb, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_rbalance = dft_rb;
+ alvium->min_rbalance = min_rb;
+ alvium->max_rbalance = max_rb;
+ alvium->inc_rbalance = inc_rb;
+
+ return 0;
+}
+
+static int alvium_get_blue_balance_ratio_params(struct alvium_dev *alvium)
+{
+ u64 dft_bb, min_bb, max_bb, inc_bb;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_BLUE_BALANCE_RATIO_RW, &dft_bb, &ret);
+ alvium_read(alvium, REG_BCRM_BLUE_BALANCE_RATIO_MIN_R, &min_bb, &ret);
+ alvium_read(alvium, REG_BCRM_BLUE_BALANCE_RATIO_MAX_R, &max_bb, &ret);
+ alvium_read(alvium, REG_BCRM_BLUE_BALANCE_RATIO_INC_R, &inc_bb, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_bbalance = dft_bb;
+ alvium->min_bbalance = min_bb;
+ alvium->max_bbalance = max_bb;
+ alvium->inc_bbalance = inc_bb;
+
+ return 0;
+}
+
+static int alvium_get_hue_params(struct alvium_dev *alvium)
+{
+ u64 dft_hue, min_hue, max_hue, inc_hue;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_HUE_RW, &dft_hue, &ret);
+ alvium_read(alvium, REG_BCRM_HUE_MIN_R, &min_hue, &ret);
+ alvium_read(alvium, REG_BCRM_HUE_MAX_R, &max_hue, &ret);
+ alvium_read(alvium, REG_BCRM_HUE_INC_R, &inc_hue, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_hue = (s32)dft_hue;
+ alvium->min_hue = (s32)min_hue;
+ alvium->max_hue = (s32)max_hue;
+ alvium->inc_hue = (s32)inc_hue;
+
+ return 0;
+}
+
+static int alvium_get_black_lvl_params(struct alvium_dev *alvium)
+{
+ u64 dft_blvl, min_blvl, max_blvl, inc_blvl;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_BLACK_LEVEL_RW, &dft_blvl, &ret);
+ alvium_read(alvium, REG_BCRM_BLACK_LEVEL_MIN_R, &min_blvl, &ret);
+ alvium_read(alvium, REG_BCRM_BLACK_LEVEL_MAX_R, &max_blvl, &ret);
+ alvium_read(alvium, REG_BCRM_BLACK_LEVEL_INC_R, &inc_blvl, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_black_lvl = (s32)dft_blvl;
+ alvium->min_black_lvl = (s32)min_blvl;
+ alvium->max_black_lvl = (s32)max_blvl;
+ alvium->inc_black_lvl = (s32)inc_blvl;
+
+ return 0;
+}
+
+static int alvium_get_gamma_params(struct alvium_dev *alvium)
+{
+ u64 dft_g, min_g, max_g, inc_g;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_GAMMA_RW, &dft_g, &ret);
+ alvium_read(alvium, REG_BCRM_GAMMA_MIN_R, &min_g, &ret);
+ alvium_read(alvium, REG_BCRM_GAMMA_MAX_R, &max_g, &ret);
+ alvium_read(alvium, REG_BCRM_GAMMA_INC_R, &inc_g, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_gamma = dft_g;
+ alvium->min_gamma = min_g;
+ alvium->max_gamma = max_g;
+ alvium->inc_gamma = inc_g;
+
+ return 0;
+}
+
+static int alvium_get_sharpness_params(struct alvium_dev *alvium)
+{
+ u64 dft_sh, min_sh, max_sh, inc_sh;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_SHARPNESS_RW, &dft_sh, &ret);
+ alvium_read(alvium, REG_BCRM_SHARPNESS_MIN_R, &min_sh, &ret);
+ alvium_read(alvium, REG_BCRM_BLACK_LEVEL_MAX_R, &max_sh, &ret);
+ alvium_read(alvium, REG_BCRM_SHARPNESS_INC_R, &inc_sh, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_sharp = (s32)dft_sh;
+ alvium->min_sharp = (s32)min_sh;
+ alvium->max_sharp = (s32)max_sh;
+ alvium->inc_sharp = (s32)inc_sh;
+
+ return 0;
+}
+
+static int alvium_get_contrast_params(struct alvium_dev *alvium)
+{
+ u64 dft_c, min_c, max_c, inc_c;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_CONTRAST_VALUE_RW, &dft_c, &ret);
+ alvium_read(alvium, REG_BCRM_CONTRAST_VALUE_MIN_R, &min_c, &ret);
+ alvium_read(alvium, REG_BCRM_CONTRAST_VALUE_MAX_R, &max_c, &ret);
+ alvium_read(alvium, REG_BCRM_CONTRAST_VALUE_INC_R, &inc_c, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_contrast = dft_c;
+ alvium->min_contrast = min_c;
+ alvium->max_contrast = max_c;
+ alvium->inc_contrast = inc_c;
+
+ return 0;
+}
+
+static int alvium_get_saturation_params(struct alvium_dev *alvium)
+{
+ u64 dft_sat, min_sat, max_sat, inc_sat;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_SATURATION_RW, &dft_sat, &ret);
+ alvium_read(alvium, REG_BCRM_SATURATION_MIN_R, &min_sat, &ret);
+ alvium_read(alvium, REG_BCRM_SATURATION_MAX_R, &max_sat, &ret);
+ alvium_read(alvium, REG_BCRM_SATURATION_INC_R, &inc_sat, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_sat = dft_sat;
+ alvium->min_sat = min_sat;
+ alvium->max_sat = max_sat;
+ alvium->inc_sat = inc_sat;
+
+ return 0;
+}
+
+static int alvium_set_bcm_mode(struct alvium_dev *alvium)
+{
+ int ret = 0;
+
+ alvium_write(alvium, REG_GENCP_CHANGEMODE_W, ALVIUM_BCM_MODE, &ret);
+ alvium->bcrm_mode = ALVIUM_BCM_MODE;
+
+ return ret;
+}
+
+static int alvium_get_mode(struct alvium_dev *alvium)
+{
+ u64 bcrm_mode;
+ int ret;
+
+ ret = alvium_read(alvium, REG_GENCP_CURRENTMODE_R, &bcrm_mode, NULL);
+ if (ret)
+ return ret;
+
+ switch (bcrm_mode) {
+ case ALVIUM_BCM_MODE:
+ alvium->bcrm_mode = ALVIUM_BCM_MODE;
+ break;
+ case ALVIUM_GENCP_MODE:
+ alvium->bcrm_mode = ALVIUM_GENCP_MODE;
+ break;
+ }
+
+ return 0;
+}
+
+static int alvium_get_avail_mipi_data_format(struct alvium_dev *alvium)
+{
+ struct alvium_avail_mipi_fmt *avail_fmt;
+ u64 val;
+ int ret;
+
+ ret = alvium_read(alvium, REG_BCRM_IMG_AVAILABLE_MIPI_DATA_FORMATS_R,
+ &val, NULL);
+ if (ret)
+ return ret;
+
+ avail_fmt = (struct alvium_avail_mipi_fmt *)&val;
+
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8_LEG] =
+ avail_fmt->yuv420_8_leg;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8] =
+ avail_fmt->yuv420_8;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_10] =
+ avail_fmt->yuv420_10;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_8_CSPS] =
+ avail_fmt->yuv420_8_csps;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV420_10_CSPS] =
+ avail_fmt->yuv420_10_csps;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV422_8] =
+ avail_fmt->yuv422_8;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_YUV422_10] =
+ avail_fmt->yuv422_10;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB888] =
+ avail_fmt->rgb888;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB666] =
+ avail_fmt->rgb666;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB565] =
+ avail_fmt->rgb565;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB555] =
+ avail_fmt->rgb555;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RGB444] =
+ avail_fmt->rgb444;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW6] =
+ avail_fmt->raw6;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW7] =
+ avail_fmt->raw7;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW8] =
+ avail_fmt->raw8;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW10] =
+ avail_fmt->raw10;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW12] =
+ avail_fmt->raw12;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_RAW14] =
+ avail_fmt->raw14;
+ alvium->is_mipi_fmt_avail[ALVIUM_BIT_JPEG] =
+ avail_fmt->jpeg;
+
+ alvium_print_avail_mipi_fmt(alvium);
+
+ return 0;
+}
+
+static int alvium_setup_mipi_fmt(struct alvium_dev *alvium)
+{
+ unsigned int avail_fmt_cnt = 0;
+ unsigned int fmt = 0;
+ size_t sz = 0;
+
+ /* calculate fmt array size */
+ for (fmt = 0; fmt < ALVIUM_NUM_SUPP_MIPI_DATA_FMT; fmt++) {
+ if (!alvium->is_mipi_fmt_avail[alvium_csi2_fmts[fmt].fmt_av_bit])
+ continue;
+
+ if (!alvium_csi2_fmts[fmt].is_raw ||
+ alvium->is_bay_avail[alvium_csi2_fmts[fmt].bay_av_bit])
+ sz++;
+ }
+
+ /* init alvium_csi2_fmt array */
+ alvium->alvium_csi2_fmt_n = sz;
+ alvium->alvium_csi2_fmt =
+ kmalloc_array(sz, sizeof(struct alvium_pixfmt), GFP_KERNEL);
+ if (!alvium->alvium_csi2_fmt)
+ return -ENOMEM;
+
+ /* Create the alvium_csi2 fmt array from formats available */
+ for (fmt = 0; fmt < ALVIUM_NUM_SUPP_MIPI_DATA_FMT; fmt++) {
+ if (!alvium->is_mipi_fmt_avail[alvium_csi2_fmts[fmt].fmt_av_bit])
+ continue;
+
+ if (!alvium_csi2_fmts[fmt].is_raw ||
+ alvium->is_bay_avail[alvium_csi2_fmts[fmt].bay_av_bit]) {
+ alvium->alvium_csi2_fmt[avail_fmt_cnt] =
+ alvium_csi2_fmts[fmt];
+ avail_fmt_cnt++;
+ }
+ }
+
+ return 0;
+}
+
+static int alvium_set_mipi_fmt(struct alvium_dev *alvium,
+ const struct alvium_pixfmt *pixfmt)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_IMG_MIPI_DATA_FORMAT_RW,
+ pixfmt->mipi_fmt_regval);
+ if (ret) {
+ dev_err(dev, "Fail to set mipi fmt\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_avail_bayer(struct alvium_dev *alvium)
+{
+ struct alvium_avail_bayer *avail_bay;
+ u64 val;
+ int ret;
+
+ ret = alvium_read(alvium, REG_BCRM_IMG_BAYER_PATTERN_INQUIRY_R,
+ &val, NULL);
+ if (ret)
+ return ret;
+
+ avail_bay = (struct alvium_avail_bayer *)&val;
+
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_MONO] = avail_bay->mono;
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_GR] = avail_bay->gr;
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_RG] = avail_bay->rg;
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_GB] = avail_bay->gb;
+ alvium->is_bay_avail[ALVIUM_BIT_BAY_BG] = avail_bay->bg;
+
+ alvium_print_avail_bayer(alvium);
+
+ return 0;
+}
+
+static int alvium_set_bayer_pattern(struct alvium_dev *alvium,
+ const struct alvium_pixfmt *pixfmt)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_IMG_BAYER_PATTERN_RW,
+ pixfmt->bay_fmt_regval);
+ if (ret) {
+ dev_err(dev, "Fail to set bayer pattern\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_frame_interval(struct alvium_dev *alvium)
+{
+ u64 dft_fr, min_fr, max_fr;
+ int ret = 0;
+
+ alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW,
+ &dft_fr, &ret);
+ alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R,
+ &min_fr, &ret);
+ alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R,
+ &max_fr, &ret);
+ if (ret)
+ return ret;
+
+ alvium->dft_fr = dft_fr;
+ alvium->min_fr = min_fr;
+ alvium->max_fr = max_fr;
+
+ return 0;
+}
+
+static int alvium_set_frame_rate(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW,
+ alvium->fr);
+ if (ret) {
+ dev_err(dev, "Fail to set frame rate lanes reg\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "set frame rate: %llu us\n", alvium->fr);
+
+ return 0;
+}
+
+static int alvium_set_stream_mipi(struct alvium_dev *alvium, bool on)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, on ? REG_BCRM_ACQUISITION_START_RW :
+ REG_BCRM_ACQUISITION_STOP_RW, 0x01);
+ if (ret) {
+ dev_err(dev, "Fail set_stream_mipi\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_gain(struct alvium_dev *alvium)
+{
+ u64 gain;
+ int ret;
+
+ /* The unit is millibel (1 mB = 0.01 dB) */
+ ret = alvium_read(alvium, REG_BCRM_GAIN_RW, &gain, NULL);
+ if (ret)
+ return ret;
+
+ return gain;
+}
+
+static int alvium_set_ctrl_gain(struct alvium_dev *alvium, int gain)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ /* The unit is millibel (1 mB = 0.01 dB) */
+ ret = alvium_write_hshake(alvium, REG_BCRM_GAIN_RW, (u64)gain);
+ if (ret) {
+ dev_err(dev, "Fail to set gain value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_auto_gain(struct alvium_dev *alvium, bool on)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_GAIN_AUTO_RW,
+ on ? 0x02 : 0x00);
+ if (ret) {
+ dev_err(dev, "Fail to set autogain reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_exposure(struct alvium_dev *alvium)
+{
+ u64 exp;
+ int ret;
+
+ /* Exposure time in ns */
+ ret = alvium_read(alvium, REG_BCRM_EXPOSURE_TIME_RW, &exp, NULL);
+ if (ret)
+ return ret;
+
+ return exp;
+}
+
+static int alvium_set_ctrl_auto_exposure(struct alvium_dev *alvium, bool on)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_WHITE_BALANCE_AUTO_RW,
+ on ? 0x02 : 0x00);
+ if (ret) {
+ dev_err(dev, "Fail to set autoexposure reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_exposure(struct alvium_dev *alvium, int exposure_ns)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_EXPOSURE_TIME_RW,
+ (u64)exposure_ns);
+ if (ret) {
+ dev_err(dev, "Fail to set exposure value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_blue_balance_ratio(struct alvium_dev *alvium,
+ int blue)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_BLUE_BALANCE_RATIO_RW,
+ (u64)blue);
+ if (ret) {
+ dev_err(dev, "Fail to set blue ratio value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_red_balance_ratio(struct alvium_dev *alvium, int red)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_RED_BALANCE_RATIO_RW,
+ (u64)red);
+ if (ret) {
+ dev_err(dev, "Fail to set red ratio value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_awb(struct alvium_dev *alvium, bool on)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_WHITE_BALANCE_AUTO_RW,
+ on ? 0x02 : 0x00);
+ if (ret) {
+ dev_err(dev, "Fail to set awb reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_hue(struct alvium_dev *alvium, int val)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_HUE_RW, (u64)val);
+ if (ret) {
+ dev_err(dev, "Fail to set hue value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_contrast(struct alvium_dev *alvium, int val)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_CONTRAST_VALUE_RW, (u64)val);
+ if (ret) {
+ dev_err(dev, "Fail to set contrast value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_saturation(struct alvium_dev *alvium, int val)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_SATURATION_RW, (u64)val);
+ if (ret) {
+ dev_err(dev, "Fail to set contrast value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_gamma(struct alvium_dev *alvium, int val)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_GAMMA_RW, (u64)val);
+ if (ret) {
+ dev_err(dev, "Fail to set gamma value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_sharpness(struct alvium_dev *alvium, int val)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_SHARPNESS_RW, (u64)val);
+ if (ret) {
+ dev_err(dev, "Fail to set sharpness value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_hflip(struct alvium_dev *alvium, int val)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_IMG_REVERSE_X_RW, (u64)val);
+ if (ret) {
+ dev_err(dev, "Fail to set reverse_x value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_set_ctrl_vflip(struct alvium_dev *alvium, int val)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_write_hshake(alvium, REG_BCRM_IMG_REVERSE_Y_RW, (u64)val);
+ if (ret) {
+ dev_err(dev, "Fail to set reverse_y value reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_hw_features_params(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_get_csi_clk_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read min/max csi clock regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_img_width_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read img width regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_img_height_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read img heigth regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_offx_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read offx regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_offy_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read offy regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_gain_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read gain regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_exposure_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read min/max exp regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_red_balance_ratio_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read red balance ratio regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_blue_balance_ratio_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read blue balance ratio regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_hue_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read hue regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_contrast_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read contrast regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_saturation_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read saturation regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_black_lvl_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read black lvl regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_gamma_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read gamma regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_sharpness_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read sharpness regs\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_get_hw_info(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ ret = alvium_get_bcrm_vers(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read bcrm version reg\n");
+ return ret;
+ }
+
+ ret = alvium_get_bcrm_addr(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to bcrm address reg\n");
+ return ret;
+ }
+
+ ret = alvium_get_fw_version(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read fw version reg\n");
+ return ret;
+ }
+
+ ret = alvium_get_host_supp_csi_lanes(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read host supported csi lanes reg\n");
+ return ret;
+ }
+
+ ret = alvium_get_feat_inq(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read bcrm feature inquiry reg\n");
+ return ret;
+ }
+
+ ret = alvium_get_hw_features_params(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read features params regs\n");
+ return ret;
+ }
+
+ ret = alvium_get_avail_mipi_data_format(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read available mipi data formats reg\n");
+ return ret;
+ }
+
+ ret = alvium_get_avail_bayer(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to read available Bayer patterns reg\n");
+ return ret;
+ }
+
+ ret = alvium_get_mode(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to get current mode reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_hw_init(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ int ret;
+
+ /* Set Alvium BCM mode*/
+ ret = alvium_set_bcm_mode(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to set BCM mode\n");
+ return ret;
+ }
+
+ ret = alvium_set_csi_lanes(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to set csi lanes\n");
+ return ret;
+ }
+
+ ret = alvium_set_csi_clk(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to set csi clk\n");
+ return ret;
+ }
+
+ ret = alvium_set_lp2hs_delay(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to set lp2hs reg\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/* --------------- Subdev Operations --------------- */
+
+static int alvium_g_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ fi->interval = alvium->frame_interval;
+
+ return 0;
+}
+
+static int alvium_set_frame_interval(struct alvium_dev *alvium,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ u64 req_fr, min_fr, max_fr;
+ int ret;
+
+ if (fi->interval.denominator == 0)
+ return -EINVAL;
+
+ ret = alvium_get_frame_interval(alvium);
+ if (ret) {
+ dev_err(dev, "Fail to get frame interval\n");
+ return ret;
+ }
+
+ min_fr = alvium->min_fr;
+ max_fr = alvium->max_fr;
+
+ dev_dbg(dev, "fi->interval.numerator = %d\n",
+ fi->interval.numerator);
+ dev_dbg(dev, "fi->interval.denominator = %d\n",
+ fi->interval.denominator);
+
+ req_fr = (u64)((fi->interval.denominator * USEC_PER_SEC) /
+ fi->interval.numerator);
+
+ if (req_fr >= max_fr && req_fr <= min_fr)
+ req_fr = alvium->dft_fr;
+
+ alvium->fr = req_fr;
+ alvium->frame_interval.numerator = fi->interval.numerator;
+ alvium->frame_interval.denominator = fi->interval.denominator;
+
+ return 0;
+}
+
+static int alvium_s_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ int ret;
+
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (alvium->streaming)
+ return -EBUSY;
+
+ ret = alvium_set_frame_interval(alvium, fi);
+ if (!ret)
+ ret = alvium_set_frame_rate(alvium);
+
+ return ret;
+}
+
+static int alvium_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+
+ if (code->index >= alvium->alvium_csi2_fmt_n)
+ return -EINVAL;
+
+ code->code = alvium->alvium_csi2_fmt[code->index].code;
+
+ return 0;
+}
+
+static const struct alvium_pixfmt *
+alvium_code_to_pixfmt(struct alvium_dev *alvium, u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; alvium->alvium_csi2_fmt[i].code; ++i)
+ if (alvium->alvium_csi2_fmt[i].code == code)
+ return &alvium->alvium_csi2_fmt[i];
+
+ return &alvium->alvium_csi2_fmt[0];
+}
+
+static int alvium_set_mode(struct alvium_dev *alvium,
+ struct v4l2_subdev_state *state)
+{
+ struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_rect *crop;
+ int ret;
+
+ crop = v4l2_subdev_state_get_crop(state, 0);
+ fmt = v4l2_subdev_state_get_format(state, 0);
+
+ v4l_bound_align_image(&fmt->width, alvium->img_min_width,
+ alvium->img_max_width, 0,
+ &fmt->height, alvium->img_min_height,
+ alvium->img_max_height, 0, 0);
+
+ /* alvium don't accept negative crop left/top */
+ crop->left = clamp((u32)max(0, crop->left), alvium->min_offx,
+ (u32)(alvium->img_max_width - fmt->width));
+ crop->top = clamp((u32)max(0, crop->top), alvium->min_offy,
+ (u32)(alvium->img_max_height - fmt->height));
+
+ ret = alvium_set_img_width(alvium, fmt->width);
+ if (ret)
+ return ret;
+
+ ret = alvium_set_img_height(alvium, fmt->height);
+ if (ret)
+ return ret;
+
+ ret = alvium_set_img_offx(alvium, crop->left);
+ if (ret)
+ return ret;
+
+ ret = alvium_set_img_offy(alvium, crop->top);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int alvium_set_framefmt(struct alvium_dev *alvium,
+ struct v4l2_mbus_framefmt *format)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ const struct alvium_pixfmt *alvium_csi2_fmt;
+ int ret = 0;
+
+ alvium_csi2_fmt = alvium_code_to_pixfmt(alvium, format->code);
+
+ ret = alvium_set_mipi_fmt(alvium, alvium_csi2_fmt);
+ if (ret)
+ return ret;
+
+ if (alvium_csi2_fmt->is_raw) {
+ ret = alvium_set_bayer_pattern(alvium, alvium_csi2_fmt);
+ if (ret)
+ return ret;
+ }
+
+ dev_dbg(dev, "start: %s, mipi_fmt_regval regval = 0x%llx",
+ __func__, alvium_csi2_fmt->mipi_fmt_regval);
+
+ return ret;
+}
+
+static int alvium_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(&alvium->sd);
+ struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_subdev_state *state;
+ int ret = 0;
+
+ state = v4l2_subdev_lock_and_get_active_state(sd);
+
+ if (enable) {
+ ret = pm_runtime_resume_and_get(&client->dev);
+ if (ret < 0)
+ goto out;
+
+ ret = __v4l2_ctrl_handler_setup(&alvium->ctrls.handler);
+ if (ret)
+ goto out;
+
+ ret = alvium_set_mode(alvium, state);
+ if (ret)
+ goto out;
+
+ fmt = v4l2_subdev_state_get_format(state, 0);
+ ret = alvium_set_framefmt(alvium, fmt);
+ if (ret)
+ goto out;
+
+ ret = alvium_set_stream_mipi(alvium, enable);
+ if (ret)
+ goto out;
+
+ } else {
+ alvium_set_stream_mipi(alvium, enable);
+ pm_runtime_mark_last_busy(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
+ }
+
+ alvium->streaming = !!enable;
+ v4l2_subdev_unlock_state(state);
+
+ return 0;
+
+out:
+ pm_runtime_put(&client->dev);
+ v4l2_subdev_unlock_state(state);
+ return ret;
+}
+
+static int alvium_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ struct alvium_mode *mode = &alvium->mode;
+ struct v4l2_subdev_format sd_fmt = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ .format = alvium_csi2_default_fmt,
+ };
+ struct v4l2_subdev_crop sd_crop = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ .rect = {
+ .left = mode->crop.left,
+ .top = mode->crop.top,
+ .width = mode->crop.width,
+ .height = mode->crop.height,
+ },
+ };
+
+ *v4l2_subdev_state_get_crop(state, 0) = sd_crop.rect;
+ *v4l2_subdev_state_get_format(state, 0) = sd_fmt.format;
+
+ return 0;
+}
+
+static int alvium_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *format)
+{
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ const struct alvium_pixfmt *alvium_csi2_fmt;
+ struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_rect *crop;
+
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
+ crop = v4l2_subdev_state_get_crop(sd_state, 0);
+
+ v4l_bound_align_image(&format->format.width, alvium->img_min_width,
+ alvium->img_max_width, 0,
+ &format->format.height, alvium->img_min_height,
+ alvium->img_max_height, 0, 0);
+
+ /* Adjust left and top to prevent roll over sensor area */
+ crop->left = clamp((u32)crop->left, (u32)0,
+ (alvium->img_max_width - fmt->width));
+ crop->top = clamp((u32)crop->top, (u32)0,
+ (alvium->img_max_height - fmt->height));
+
+ /* Set also the crop width and height when set a new fmt */
+ crop->width = fmt->width;
+ crop->height = fmt->height;
+
+ alvium_csi2_fmt = alvium_code_to_pixfmt(alvium, format->format.code);
+ fmt->code = alvium_csi2_fmt->code;
+
+ *fmt = format->format;
+
+ return 0;
+}
+
+static int alvium_set_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_selection *sel)
+{
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_rect *crop;
+
+ if (sel->target != V4L2_SEL_TGT_CROP)
+ return -EINVAL;
+
+ crop = v4l2_subdev_state_get_crop(sd_state, 0);
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
+
+ /*
+ * Alvium can only shift the origin of the img
+ * then we accept only value with the same value of the actual fmt
+ */
+ if (sel->r.width != fmt->width)
+ sel->r.width = fmt->width;
+
+ if (sel->r.height != fmt->height)
+ sel->r.height = fmt->height;
+
+ /* alvium don't accept negative crop left/top */
+ crop->left = clamp((u32)max(0, sel->r.left), alvium->min_offx,
+ alvium->img_max_width - sel->r.width);
+ crop->top = clamp((u32)max(0, sel->r.top), alvium->min_offy,
+ alvium->img_max_height - sel->r.height);
+
+ sel->r = *crop;
+
+ return 0;
+}
+
+static int alvium_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_selection *sel)
+{
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+
+ switch (sel->target) {
+ /* Current cropping area */
+ case V4L2_SEL_TGT_CROP:
+ sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
+ break;
+ /* Cropping bounds */
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = alvium->img_max_width;
+ sel->r.height = alvium->img_max_height;
+ break;
+ /* Default cropping area */
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ sel->r.top = alvium->min_offy;
+ sel->r.left = alvium->min_offx;
+ sel->r.width = alvium->img_max_width;
+ sel->r.height = alvium->img_max_height;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int alvium_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ int val;
+
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ val = alvium_get_gain(alvium);
+ if (val < 0)
+ return val;
+ alvium->ctrls.gain->val = val;
+ break;
+ case V4L2_CID_EXPOSURE:
+ val = alvium_get_exposure(alvium);
+ if (val < 0)
+ return val;
+ alvium->ctrls.exposure->val = val;
+ break;
+ }
+
+ return 0;
+}
+
+static int alvium_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(&alvium->sd);
+ int ret;
+
+ /*
+ * Applying V4L2 control value only happens
+ * when power is up for streaming
+ */
+ if (!pm_runtime_get_if_in_use(&client->dev))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ ret = alvium_set_ctrl_gain(alvium, ctrl->val);
+ break;
+ case V4L2_CID_AUTOGAIN:
+ ret = alvium_set_ctrl_auto_gain(alvium, ctrl->val);
+ break;
+ case V4L2_CID_EXPOSURE:
+ ret = alvium_set_ctrl_exposure(alvium, ctrl->val);
+ break;
+ case V4L2_CID_EXPOSURE_AUTO:
+ ret = alvium_set_ctrl_auto_exposure(alvium, ctrl->val);
+ break;
+ case V4L2_CID_RED_BALANCE:
+ ret = alvium_set_ctrl_red_balance_ratio(alvium, ctrl->val);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ ret = alvium_set_ctrl_blue_balance_ratio(alvium, ctrl->val);
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ret = alvium_set_ctrl_awb(alvium, ctrl->val);
+ break;
+ case V4L2_CID_HUE:
+ ret = alvium_set_ctrl_hue(alvium, ctrl->val);
+ break;
+ case V4L2_CID_CONTRAST:
+ ret = alvium_set_ctrl_contrast(alvium, ctrl->val);
+ break;
+ case V4L2_CID_SATURATION:
+ ret = alvium_set_ctrl_saturation(alvium, ctrl->val);
+ break;
+ case V4L2_CID_GAMMA:
+ ret = alvium_set_ctrl_gamma(alvium, ctrl->val);
+ break;
+ case V4L2_CID_SHARPNESS:
+ ret = alvium_set_ctrl_sharpness(alvium, ctrl->val);
+ break;
+ case V4L2_CID_HFLIP:
+ ret = alvium_set_ctrl_hflip(alvium, ctrl->val);
+ break;
+ case V4L2_CID_VFLIP:
+ ret = alvium_set_ctrl_vflip(alvium, ctrl->val);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ pm_runtime_put(&client->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops alvium_ctrl_ops = {
+ .g_volatile_ctrl = alvium_g_volatile_ctrl,
+ .s_ctrl = alvium_s_ctrl,
+};
+
+static int alvium_ctrl_init(struct alvium_dev *alvium)
+{
+ const struct v4l2_ctrl_ops *ops = &alvium_ctrl_ops;
+ struct alvium_ctrls *ctrls = &alvium->ctrls;
+ struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+ struct v4l2_fwnode_device_properties props;
+ int ret;
+
+ v4l2_ctrl_handler_init(hdl, 32);
+
+ /* Pixel rate is fixed */
+ ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_PIXEL_RATE, 0,
+ ALVIUM_DEFAULT_PIXEL_RATE_MHZ, 1,
+ ALVIUM_DEFAULT_PIXEL_RATE_MHZ);
+ ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ /* Link freq is fixed */
+ ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops,
+ V4L2_CID_LINK_FREQ,
+ 0, 0, &alvium->link_freq);
+ ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ /* Auto/manual white balance */
+ if (alvium->avail_ft.auto_whiteb) {
+ ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_AUTO_WHITE_BALANCE,
+ 0, 1, 1, 1);
+ v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
+ }
+
+ ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_BLUE_BALANCE,
+ alvium->min_bbalance,
+ alvium->max_bbalance,
+ alvium->inc_bbalance,
+ alvium->dft_bbalance);
+ ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_RED_BALANCE,
+ alvium->min_rbalance,
+ alvium->max_rbalance,
+ alvium->inc_rbalance,
+ alvium->dft_rbalance);
+
+ /* Auto/manual exposure */
+ if (alvium->avail_ft.auto_exp) {
+ ctrls->auto_exp =
+ v4l2_ctrl_new_std_menu(hdl, ops,
+ V4L2_CID_EXPOSURE_AUTO,
+ V4L2_EXPOSURE_MANUAL, 0,
+ V4L2_EXPOSURE_AUTO);
+ v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
+ }
+
+ ctrls->exposure = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_EXPOSURE,
+ alvium->min_exp,
+ alvium->max_exp,
+ alvium->inc_exp,
+ alvium->dft_exp);
+ ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+ /* Auto/manual gain */
+ if (alvium->avail_ft.auto_gain) {
+ ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_AUTOGAIN,
+ 0, 1, 1, 1);
+ v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
+ }
+
+ if (alvium->avail_ft.gain) {
+ ctrls->gain = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_GAIN,
+ alvium->min_gain,
+ alvium->max_gain,
+ alvium->inc_gain,
+ alvium->dft_gain);
+ ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ }
+
+ if (alvium->avail_ft.sat)
+ ctrls->saturation = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_SATURATION,
+ alvium->min_sat,
+ alvium->max_sat,
+ alvium->inc_sat,
+ alvium->dft_sat);
+
+ if (alvium->avail_ft.hue)
+ ctrls->hue = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_HUE,
+ alvium->min_hue,
+ alvium->max_hue,
+ alvium->inc_hue,
+ alvium->dft_hue);
+
+ if (alvium->avail_ft.contrast)
+ ctrls->contrast = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_CONTRAST,
+ alvium->min_contrast,
+ alvium->max_contrast,
+ alvium->inc_contrast,
+ alvium->dft_contrast);
+
+ if (alvium->avail_ft.gamma)
+ ctrls->gamma = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_GAMMA,
+ alvium->min_gamma,
+ alvium->max_gamma,
+ alvium->inc_gamma,
+ alvium->dft_gamma);
+
+ if (alvium->avail_ft.sharp)
+ ctrls->sharpness = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_SHARPNESS,
+ alvium->min_sharp,
+ alvium->max_sharp,
+ alvium->inc_sharp,
+ alvium->dft_sharp);
+
+ if (alvium->avail_ft.rev_x)
+ ctrls->hflip = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_HFLIP,
+ 0, 1, 1, 0);
+
+ if (alvium->avail_ft.rev_y)
+ ctrls->vflip = v4l2_ctrl_new_std(hdl, ops,
+ V4L2_CID_VFLIP,
+ 0, 1, 1, 0);
+
+ if (hdl->error) {
+ ret = hdl->error;
+ goto free_ctrls;
+ }
+
+ ret = v4l2_fwnode_device_parse(&alvium->i2c_client->dev, &props);
+ if (ret)
+ goto free_ctrls;
+
+ ret = v4l2_ctrl_new_fwnode_properties(hdl, ops, &props);
+ if (ret)
+ goto free_ctrls;
+
+ alvium->sd.ctrl_handler = hdl;
+ return 0;
+
+free_ctrls:
+ v4l2_ctrl_handler_free(hdl);
+ return ret;
+}
+
+static const struct v4l2_subdev_core_ops alvium_core_ops = {
+ .log_status = v4l2_ctrl_subdev_log_status,
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops alvium_video_ops = {
+ .s_stream = alvium_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops alvium_pad_ops = {
+ .enum_mbus_code = alvium_enum_mbus_code,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = alvium_set_fmt,
+ .get_selection = alvium_get_selection,
+ .set_selection = alvium_set_selection,
+ .get_frame_interval = alvium_g_frame_interval,
+ .set_frame_interval = alvium_s_frame_interval,
+};
+
+static const struct v4l2_subdev_internal_ops alvium_internal_ops = {
+ .init_state = alvium_init_state,
+};
+
+static const struct v4l2_subdev_ops alvium_subdev_ops = {
+ .core = &alvium_core_ops,
+ .pad = &alvium_pad_ops,
+ .video = &alvium_video_ops,
+};
+
+static int alvium_subdev_init(struct alvium_dev *alvium)
+{
+ struct i2c_client *client = alvium->i2c_client;
+ struct device *dev = &alvium->i2c_client->dev;
+ struct v4l2_subdev *sd = &alvium->sd;
+ int ret;
+
+ /* Setup initial frame interval*/
+ alvium->frame_interval.numerator = 1;
+ alvium->frame_interval.denominator = ALVIUM_DEFAULT_FR_HZ;
+ alvium->fr = ALVIUM_DEFAULT_FR_HZ;
+
+ /* Setup the initial mode */
+ alvium->mode.fmt = alvium_csi2_default_fmt;
+ alvium->mode.width = alvium_csi2_default_fmt.width;
+ alvium->mode.height = alvium_csi2_default_fmt.height;
+ alvium->mode.crop.left = alvium->min_offx;
+ alvium->mode.crop.top = alvium->min_offy;
+ alvium->mode.crop.width = alvium_csi2_default_fmt.width;
+ alvium->mode.crop.height = alvium_csi2_default_fmt.height;
+
+ /* init alvium sd */
+ v4l2_i2c_subdev_init(sd, client, &alvium_subdev_ops);
+
+ sd->internal_ops = &alvium_internal_ops;
+ sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+ alvium->pad.flags = MEDIA_PAD_FL_SOURCE;
+ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ ret = media_entity_pads_init(&sd->entity, 1, &alvium->pad);
+ if (ret) {
+ dev_err(dev, "Could not register media entity\n");
+ return ret;
+ }
+
+ ret = alvium_ctrl_init(alvium);
+ if (ret) {
+ dev_err(dev, "Control initialization error %d\n", ret);
+ goto entity_cleanup;
+ }
+
+ alvium->sd.state_lock = alvium->ctrls.handler.lock;
+
+ ret = v4l2_subdev_init_finalize(sd);
+ if (ret < 0) {
+ dev_err(dev, "subdev initialization error %d\n", ret);
+ goto err_ctrls;
+ }
+
+ return 0;
+
+err_ctrls:
+ v4l2_ctrl_handler_free(&alvium->ctrls.handler);
+entity_cleanup:
+ media_entity_cleanup(&alvium->sd.entity);
+ return ret;
+}
+
+static void alvium_subdev_cleanup(struct alvium_dev *alvium)
+{
+ v4l2_fwnode_endpoint_free(&alvium->ep);
+ v4l2_subdev_cleanup(&alvium->sd);
+ media_entity_cleanup(&alvium->sd.entity);
+ v4l2_ctrl_handler_free(&alvium->ctrls.handler);
+}
+
+static int alvium_get_dt_data(struct alvium_dev *alvium)
+{
+ struct device *dev = &alvium->i2c_client->dev;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
+ struct fwnode_handle *endpoint;
+
+ if (!fwnode)
+ return -EINVAL;
+
+ /* Only CSI2 is supported for now: */
+ alvium->ep.bus_type = V4L2_MBUS_CSI2_DPHY;
+
+ endpoint = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0, 0);
+ if (!endpoint) {
+ dev_err(dev, "endpoint node not found\n");
+ return -EINVAL;
+ }
+
+ if (v4l2_fwnode_endpoint_alloc_parse(endpoint, &alvium->ep)) {
+ dev_err(dev, "could not parse endpoint\n");
+ goto error_out;
+ }
+
+ if (!alvium->ep.nr_of_link_frequencies) {
+ dev_err(dev, "no link frequencies defined");
+ goto error_out;
+ }
+
+ return 0;
+
+error_out:
+ v4l2_fwnode_endpoint_free(&alvium->ep);
+ fwnode_handle_put(endpoint);
+
+ return -EINVAL;
+}
+
+static int alvium_set_power(struct alvium_dev *alvium, bool on)
+{
+ int ret;
+
+ if (!on)
+ return regulator_disable(alvium->reg_vcc);
+
+ ret = regulator_enable(alvium->reg_vcc);
+ if (ret)
+ return ret;
+
+ /* alvium boot time 7s */
+ msleep(7000);
+ return 0;
+}
+
+static int alvium_runtime_resume(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ int ret;
+
+ ret = alvium_set_power(alvium, true);
+ if (ret)
+ return ret;
+
+ ret = alvium_hw_init(alvium);
+ if (ret) {
+ alvium_set_power(alvium, false);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int alvium_runtime_suspend(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+
+ alvium_set_power(alvium, false);
+
+ return 0;
+}
+
+static const struct dev_pm_ops alvium_pm_ops = {
+ RUNTIME_PM_OPS(alvium_runtime_suspend, alvium_runtime_resume, NULL)
+};
+
+static int alvium_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct alvium_dev *alvium;
+ int ret;
+
+ alvium = devm_kzalloc(dev, sizeof(*alvium), GFP_KERNEL);
+ if (!alvium)
+ return -ENOMEM;
+
+ alvium->i2c_client = client;
+
+ alvium->regmap = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(alvium->regmap))
+ return PTR_ERR(alvium->regmap);
+
+ ret = alvium_get_dt_data(alvium);
+ if (ret)
+ return ret;
+
+ alvium->reg_vcc = devm_regulator_get_optional(dev, "vcc-ext-in");
+ if (IS_ERR(alvium->reg_vcc))
+ return dev_err_probe(dev, PTR_ERR(alvium->reg_vcc),
+ "no vcc-ext-in regulator provided\n");
+
+ ret = alvium_set_power(alvium, true);
+ if (ret)
+ goto err_powerdown;
+
+ if (!alvium_is_alive(alvium)) {
+ ret = -ENODEV;
+ dev_err_probe(dev, ret, "Device detection failed\n");
+ goto err_powerdown;
+ }
+
+ ret = alvium_get_hw_info(alvium);
+ if (ret) {
+ dev_err_probe(dev, ret, "get_hw_info fail\n");
+ goto err_powerdown;
+ }
+
+ ret = alvium_hw_init(alvium);
+ if (ret) {
+ dev_err_probe(dev, ret, "hw_init fail\n");
+ goto err_powerdown;
+ }
+
+ ret = alvium_setup_mipi_fmt(alvium);
+ if (ret) {
+ dev_err_probe(dev, ret, "setup_mipi_fmt fail\n");
+ goto err_powerdown;
+ }
+
+ /*
+ * Enable runtime PM without autosuspend:
+ *
+ * Don't use pm autosuspend (alvium have ~7s boot time).
+ * Alvium has been powered manually:
+ * - mark it as active
+ * - increase the usage count without resuming the device.
+ */
+ pm_runtime_set_active(dev);
+ pm_runtime_get_noresume(dev);
+ pm_runtime_enable(dev);
+
+ /* Initialize the V4L2 subdev. */
+ ret = alvium_subdev_init(alvium);
+ if (ret)
+ goto err_pm;
+
+ ret = v4l2_async_register_subdev(&alvium->sd);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "Could not register v4l2 device\n");
+ goto err_subdev;
+ }
+
+ return 0;
+
+err_subdev:
+ alvium_subdev_cleanup(alvium);
+err_pm:
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
+ kfree(alvium->alvium_csi2_fmt);
+err_powerdown:
+ alvium_set_power(alvium, false);
+
+ return ret;
+}
+
+static void alvium_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct alvium_dev *alvium = sd_to_alvium(sd);
+ struct device *dev = &alvium->i2c_client->dev;
+
+ v4l2_async_unregister_subdev(sd);
+ alvium_subdev_cleanup(alvium);
+ kfree(alvium->alvium_csi2_fmt);
+ /*
+ * Disable runtime PM. In case runtime PM is disabled in the kernel,
+ * make sure to turn power off manually.
+ */
+ pm_runtime_disable(dev);
+ if (!pm_runtime_status_suspended(dev))
+ alvium_set_power(alvium, false);
+ pm_runtime_set_suspended(dev);
+}
+
+static const struct of_device_id alvium_of_ids[] = {
+ { .compatible = "alliedvision,alvium-csi2", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, alvium_of_ids);
+
+static struct i2c_driver alvium_i2c_driver = {
+ .driver = {
+ .name = "alvium-csi2",
+ .pm = pm_ptr(&alvium_pm_ops),
+ .of_match_table = alvium_of_ids,
+ },
+ .probe = alvium_probe,
+ .remove = alvium_remove,
+};
+
+module_i2c_driver(alvium_i2c_driver);
+
+MODULE_DESCRIPTION("Allied Vision's Alvium Camera Driver");
+MODULE_AUTHOR("Tommaso Merciai <tomm.merciai@gmail.com>");
+MODULE_AUTHOR("Martin Hecht <martin.hecht@avnet.eu>");
+MODULE_AUTHOR("Avnet Silica Software & Services EMEA");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/alvium-csi2.h b/drivers/media/i2c/alvium-csi2.h
new file mode 100644
index 0000000000..b85a25169e
--- /dev/null
+++ b/drivers/media/i2c/alvium-csi2.h
@@ -0,0 +1,475 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Allied Vision Technologies GmbH Alvium camera driver
+ *
+ * Copyright (C) 2023 Tommaso Merciai
+ * Copyright (C) 2023 Martin Hecht
+ * Copyright (C) 2023 Avnet EMG GmbH
+ */
+
+#ifndef ALVIUM_CSI2_H_
+#define ALVIUM_CSI2_H_
+
+#include <linux/kernel.h>
+#include <linux/regulator/consumer.h>
+#include <media/v4l2-cci.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#define REG_BCRM_V4L2 BIT(31)
+
+#define REG_BCRM_V4L2_8BIT(n) (REG_BCRM_V4L2 | CCI_REG8(n))
+#define REG_BCRM_V4L2_16BIT(n) (REG_BCRM_V4L2 | CCI_REG16(n))
+#define REG_BCRM_V4L2_32BIT(n) (REG_BCRM_V4L2 | CCI_REG32(n))
+#define REG_BCRM_V4L2_64BIT(n) (REG_BCRM_V4L2 | CCI_REG64(n))
+
+/* Basic Control Register Map register offsets (BCRM) */
+#define REG_BCRM_MINOR_VERSION_R CCI_REG16(0x0000)
+#define REG_BCRM_MAJOR_VERSION_R CCI_REG16(0x0002)
+#define REG_BCRM_REG_ADDR_R CCI_REG16(0x0014)
+
+#define REG_BCRM_FEATURE_INQUIRY_R REG_BCRM_V4L2_64BIT(0x0008)
+#define REG_BCRM_DEVICE_FW_SPEC_VERSION_R REG_BCRM_V4L2_8BIT(0x0010)
+#define REG_BCRM_DEVICE_FW_MAJOR_VERSION_R REG_BCRM_V4L2_8BIT(0x0011)
+#define REG_BCRM_DEVICE_FW_MINOR_VERSION_R REG_BCRM_V4L2_16BIT(0x0012)
+#define REG_BCRM_DEVICE_FW_PATCH_VERSION_R REG_BCRM_V4L2_32BIT(0x0014)
+#define REG_BCRM_WRITE_HANDSHAKE_RW REG_BCRM_V4L2_8BIT(0x0018)
+
+/* Streaming Control Registers */
+#define REG_BCRM_SUPPORTED_CSI2_LANE_COUNTS_R REG_BCRM_V4L2_8BIT(0x0040)
+#define REG_BCRM_CSI2_LANE_COUNT_RW REG_BCRM_V4L2_8BIT(0x0044)
+#define REG_BCRM_CSI2_CLOCK_MIN_R REG_BCRM_V4L2_32BIT(0x0048)
+#define REG_BCRM_CSI2_CLOCK_MAX_R REG_BCRM_V4L2_32BIT(0x004c)
+#define REG_BCRM_CSI2_CLOCK_RW REG_BCRM_V4L2_32BIT(0x0050)
+#define REG_BCRM_BUFFER_SIZE_R REG_BCRM_V4L2_32BIT(0x0054)
+
+#define REG_BCRM_IPU_X_MIN_W REG_BCRM_V4L2_32BIT(0x0058)
+#define REG_BCRM_IPU_X_MAX_W REG_BCRM_V4L2_32BIT(0x005c)
+#define REG_BCRM_IPU_X_INC_W REG_BCRM_V4L2_32BIT(0x0060)
+#define REG_BCRM_IPU_Y_MIN_W REG_BCRM_V4L2_32BIT(0x0064)
+#define REG_BCRM_IPU_Y_MAX_W REG_BCRM_V4L2_32BIT(0x0068)
+#define REG_BCRM_IPU_Y_INC_W REG_BCRM_V4L2_32BIT(0x006c)
+#define REG_BCRM_IPU_X_R REG_BCRM_V4L2_32BIT(0x0070)
+#define REG_BCRM_IPU_Y_R REG_BCRM_V4L2_32BIT(0x0074)
+
+#define REG_BCRM_PHY_RESET_RW REG_BCRM_V4L2_8BIT(0x0078)
+#define REG_BCRM_LP2HS_DELAY_RW REG_BCRM_V4L2_32BIT(0x007c)
+
+/* Acquisition Control Registers */
+#define REG_BCRM_ACQUISITION_START_RW REG_BCRM_V4L2_8BIT(0x0080)
+#define REG_BCRM_ACQUISITION_STOP_RW REG_BCRM_V4L2_8BIT(0x0084)
+#define REG_BCRM_ACQUISITION_ABORT_RW REG_BCRM_V4L2_8BIT(0x0088)
+#define REG_BCRM_ACQUISITION_STATUS_R REG_BCRM_V4L2_8BIT(0x008c)
+#define REG_BCRM_ACQUISITION_FRAME_RATE_RW REG_BCRM_V4L2_64BIT(0x0090)
+#define REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R REG_BCRM_V4L2_64BIT(0x0098)
+#define REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R REG_BCRM_V4L2_64BIT(0x00a0)
+#define REG_BCRM_ACQUISITION_FRAME_RATE_INC_R REG_BCRM_V4L2_64BIT(0x00a8)
+#define REG_BCRM_ACQUISITION_FRAME_RATE_ENABLE_RW REG_BCRM_V4L2_8BIT(0x00b0)
+
+#define REG_BCRM_FRAME_START_TRIGGER_MODE_RW REG_BCRM_V4L2_8BIT(0x00b4)
+#define REG_BCRM_FRAME_START_TRIGGER_SOURCE_RW REG_BCRM_V4L2_8BIT(0x00b8)
+#define REG_BCRM_FRAME_START_TRIGGER_ACTIVATION_RW REG_BCRM_V4L2_8BIT(0x00bc)
+#define REG_BCRM_FRAME_START_TRIGGER_SOFTWARE_W REG_BCRM_V4L2_8BIT(0x00c0)
+#define REG_BCRM_FRAME_START_TRIGGER_DELAY_RW REG_BCRM_V4L2_32BIT(0x00c4)
+#define REG_BCRM_EXPOSURE_ACTIVE_LINE_MODE_RW REG_BCRM_V4L2_8BIT(0x00c8)
+#define REG_BCRM_EXPOSURE_ACTIVE_LINE_SELECTOR_RW REG_BCRM_V4L2_8BIT(0x00cc)
+#define REG_BCRM_LINE_CONFIGURATION_RW REG_BCRM_V4L2_32BIT(0x00d0)
+
+#define REG_BCRM_IMG_WIDTH_RW REG_BCRM_V4L2_32BIT(0x0100)
+#define REG_BCRM_IMG_WIDTH_MIN_R REG_BCRM_V4L2_32BIT(0x0104)
+#define REG_BCRM_IMG_WIDTH_MAX_R REG_BCRM_V4L2_32BIT(0x0108)
+#define REG_BCRM_IMG_WIDTH_INC_R REG_BCRM_V4L2_32BIT(0x010c)
+
+#define REG_BCRM_IMG_HEIGHT_RW REG_BCRM_V4L2_32BIT(0x0110)
+#define REG_BCRM_IMG_HEIGHT_MIN_R REG_BCRM_V4L2_32BIT(0x0114)
+#define REG_BCRM_IMG_HEIGHT_MAX_R REG_BCRM_V4L2_32BIT(0x0118)
+#define REG_BCRM_IMG_HEIGHT_INC_R REG_BCRM_V4L2_32BIT(0x011c)
+
+#define REG_BCRM_IMG_OFFSET_X_RW REG_BCRM_V4L2_32BIT(0x0120)
+#define REG_BCRM_IMG_OFFSET_X_MIN_R REG_BCRM_V4L2_32BIT(0x0124)
+#define REG_BCRM_IMG_OFFSET_X_MAX_R REG_BCRM_V4L2_32BIT(0x0128)
+#define REG_BCRM_IMG_OFFSET_X_INC_R REG_BCRM_V4L2_32BIT(0x012c)
+
+#define REG_BCRM_IMG_OFFSET_Y_RW REG_BCRM_V4L2_32BIT(0x0130)
+#define REG_BCRM_IMG_OFFSET_Y_MIN_R REG_BCRM_V4L2_32BIT(0x0134)
+#define REG_BCRM_IMG_OFFSET_Y_MAX_R REG_BCRM_V4L2_32BIT(0x0138)
+#define REG_BCRM_IMG_OFFSET_Y_INC_R REG_BCRM_V4L2_32BIT(0x013c)
+
+#define REG_BCRM_IMG_MIPI_DATA_FORMAT_RW REG_BCRM_V4L2_32BIT(0x0140)
+#define REG_BCRM_IMG_AVAILABLE_MIPI_DATA_FORMATS_R REG_BCRM_V4L2_64BIT(0x0148)
+#define REG_BCRM_IMG_BAYER_PATTERN_INQUIRY_R REG_BCRM_V4L2_8BIT(0x0150)
+#define REG_BCRM_IMG_BAYER_PATTERN_RW REG_BCRM_V4L2_8BIT(0x0154)
+#define REG_BCRM_IMG_REVERSE_X_RW REG_BCRM_V4L2_8BIT(0x0158)
+#define REG_BCRM_IMG_REVERSE_Y_RW REG_BCRM_V4L2_8BIT(0x015c)
+
+#define REG_BCRM_SENSOR_WIDTH_R REG_BCRM_V4L2_32BIT(0x0160)
+#define REG_BCRM_SENSOR_HEIGHT_R REG_BCRM_V4L2_32BIT(0x0164)
+#define REG_BCRM_WIDTH_MAX_R REG_BCRM_V4L2_32BIT(0x0168)
+#define REG_BCRM_HEIGHT_MAX_R REG_BCRM_V4L2_32BIT(0x016c)
+
+#define REG_BCRM_EXPOSURE_TIME_RW REG_BCRM_V4L2_64BIT(0x0180)
+#define REG_BCRM_EXPOSURE_TIME_MIN_R REG_BCRM_V4L2_64BIT(0x0188)
+#define REG_BCRM_EXPOSURE_TIME_MAX_R REG_BCRM_V4L2_64BIT(0x0190)
+#define REG_BCRM_EXPOSURE_TIME_INC_R REG_BCRM_V4L2_64BIT(0x0198)
+#define REG_BCRM_EXPOSURE_AUTO_RW REG_BCRM_V4L2_8BIT(0x01a0)
+
+#define REG_BCRM_INTENSITY_AUTO_PRECEDENCE_RW REG_BCRM_V4L2_8BIT(0x01a4)
+#define REG_BCRM_INTENSITY_AUTO_PRECEDENCE_VALUE_RW REG_BCRM_V4L2_32BIT(0x01a8)
+#define REG_BCRM_INTENSITY_AUTO_PRECEDENCE_MIN_R REG_BCRM_V4L2_32BIT(0x01ac)
+#define REG_BCRM_INTENSITY_AUTO_PRECEDENCE_MAX_R REG_BCRM_V4L2_32BIT(0x01b0)
+#define REG_BCRM_INTENSITY_AUTO_PRECEDENCE_INC_R REG_BCRM_V4L2_32BIT(0x01b4)
+
+#define REG_BCRM_BLACK_LEVEL_RW REG_BCRM_V4L2_32BIT(0x01b8)
+#define REG_BCRM_BLACK_LEVEL_MIN_R REG_BCRM_V4L2_32BIT(0x01bc)
+#define REG_BCRM_BLACK_LEVEL_MAX_R REG_BCRM_V4L2_32BIT(0x01c0)
+#define REG_BCRM_BLACK_LEVEL_INC_R REG_BCRM_V4L2_32BIT(0x01c4)
+
+#define REG_BCRM_GAIN_RW REG_BCRM_V4L2_64BIT(0x01c8)
+#define REG_BCRM_GAIN_MIN_R REG_BCRM_V4L2_64BIT(0x01d0)
+#define REG_BCRM_GAIN_MAX_R REG_BCRM_V4L2_64BIT(0x01d8)
+#define REG_BCRM_GAIN_INC_R REG_BCRM_V4L2_64BIT(0x01e0)
+#define REG_BCRM_GAIN_AUTO_RW REG_BCRM_V4L2_8BIT(0x01e8)
+
+#define REG_BCRM_GAMMA_RW REG_BCRM_V4L2_64BIT(0x01f0)
+#define REG_BCRM_GAMMA_MIN_R REG_BCRM_V4L2_64BIT(0x01f8)
+#define REG_BCRM_GAMMA_MAX_R REG_BCRM_V4L2_64BIT(0x0200)
+#define REG_BCRM_GAMMA_INC_R REG_BCRM_V4L2_64BIT(0x0208)
+
+#define REG_BCRM_CONTRAST_VALUE_RW REG_BCRM_V4L2_32BIT(0x0214)
+#define REG_BCRM_CONTRAST_VALUE_MIN_R REG_BCRM_V4L2_32BIT(0x0218)
+#define REG_BCRM_CONTRAST_VALUE_MAX_R REG_BCRM_V4L2_32BIT(0x021c)
+#define REG_BCRM_CONTRAST_VALUE_INC_R REG_BCRM_V4L2_32BIT(0x0220)
+
+#define REG_BCRM_SATURATION_RW REG_BCRM_V4L2_32BIT(0x0240)
+#define REG_BCRM_SATURATION_MIN_R REG_BCRM_V4L2_32BIT(0x0244)
+#define REG_BCRM_SATURATION_MAX_R REG_BCRM_V4L2_32BIT(0x0248)
+#define REG_BCRM_SATURATION_INC_R REG_BCRM_V4L2_32BIT(0x024c)
+
+#define REG_BCRM_HUE_RW REG_BCRM_V4L2_32BIT(0x0250)
+#define REG_BCRM_HUE_MIN_R REG_BCRM_V4L2_32BIT(0x0254)
+#define REG_BCRM_HUE_MAX_R REG_BCRM_V4L2_32BIT(0x0258)
+#define REG_BCRM_HUE_INC_R REG_BCRM_V4L2_32BIT(0x025c)
+
+#define REG_BCRM_ALL_BALANCE_RATIO_RW REG_BCRM_V4L2_64BIT(0x0260)
+#define REG_BCRM_ALL_BALANCE_RATIO_MIN_R REG_BCRM_V4L2_64BIT(0x0268)
+#define REG_BCRM_ALL_BALANCE_RATIO_MAX_R REG_BCRM_V4L2_64BIT(0x0270)
+#define REG_BCRM_ALL_BALANCE_RATIO_INC_R REG_BCRM_V4L2_64BIT(0x0278)
+
+#define REG_BCRM_RED_BALANCE_RATIO_RW REG_BCRM_V4L2_64BIT(0x0280)
+#define REG_BCRM_RED_BALANCE_RATIO_MIN_R REG_BCRM_V4L2_64BIT(0x0288)
+#define REG_BCRM_RED_BALANCE_RATIO_MAX_R REG_BCRM_V4L2_64BIT(0x0290)
+#define REG_BCRM_RED_BALANCE_RATIO_INC_R REG_BCRM_V4L2_64BIT(0x0298)
+
+#define REG_BCRM_GREEN_BALANCE_RATIO_RW REG_BCRM_V4L2_64BIT(0x02a0)
+#define REG_BCRM_GREEN_BALANCE_RATIO_MIN_R REG_BCRM_V4L2_64BIT(0x02a8)
+#define REG_BCRM_GREEN_BALANCE_RATIO_MAX_R REG_BCRM_V4L2_64BIT(0x02b0)
+#define REG_BCRM_GREEN_BALANCE_RATIO_INC_R REG_BCRM_V4L2_64BIT(0x02b8)
+
+#define REG_BCRM_BLUE_BALANCE_RATIO_RW REG_BCRM_V4L2_64BIT(0x02c0)
+#define REG_BCRM_BLUE_BALANCE_RATIO_MIN_R REG_BCRM_V4L2_64BIT(0x02c8)
+#define REG_BCRM_BLUE_BALANCE_RATIO_MAX_R REG_BCRM_V4L2_64BIT(0x02d0)
+#define REG_BCRM_BLUE_BALANCE_RATIO_INC_R REG_BCRM_V4L2_64BIT(0x02d8)
+
+#define REG_BCRM_WHITE_BALANCE_AUTO_RW REG_BCRM_V4L2_8BIT(0x02e0)
+#define REG_BCRM_SHARPNESS_RW REG_BCRM_V4L2_32BIT(0x0300)
+#define REG_BCRM_SHARPNESS_MIN_R REG_BCRM_V4L2_32BIT(0x0304)
+#define REG_BCRM_SHARPNESS_MAX_R REG_BCRM_V4L2_32BIT(0x0308)
+#define REG_BCRM_SHARPNESS_INC_R REG_BCRM_V4L2_32BIT(0x030c)
+
+#define REG_BCRM_DEVICE_TEMPERATURE_R REG_BCRM_V4L2_32BIT(0x0310)
+#define REG_BCRM_EXPOSURE_AUTO_MIN_RW REG_BCRM_V4L2_64BIT(0x0330)
+#define REG_BCRM_EXPOSURE_AUTO_MAX_RW REG_BCRM_V4L2_64BIT(0x0338)
+#define REG_BCRM_GAIN_AUTO_MIN_RW REG_BCRM_V4L2_64BIT(0x0340)
+#define REG_BCRM_GAIN_AUTO_MAX_RW REG_BCRM_V4L2_64BIT(0x0348)
+
+/* Heartbeat reg*/
+#define REG_BCRM_HEARTBEAT_RW CCI_REG8(0x021f)
+
+/* GenCP Registers */
+#define REG_GENCP_CHANGEMODE_W CCI_REG8(0x021c)
+#define REG_GENCP_CURRENTMODE_R CCI_REG8(0x021d)
+#define REG_GENCP_IN_HANDSHAKE_RW CCI_REG8(0x001c)
+#define REG_GENCP_OUT_SIZE_W CCI_REG16(0x0020)
+#define REG_GENCP_IN_SIZE_R CCI_REG16(0x0024)
+
+/* defines */
+#define REG_BCRM_HANDSHAKE_STATUS_MASK 0x01
+#define REG_BCRM_HANDSHAKE_AVAILABLE_MASK 0x80
+
+#define BCRM_HANDSHAKE_W_DONE_EN_BIT BIT(0)
+
+#define ALVIUM_DEFAULT_FR_HZ 10
+#define ALVIUM_DEFAULT_PIXEL_RATE_MHZ 148000000
+
+#define ALVIUM_LP2HS_DELAY_MS 100
+
+enum alvium_bcrm_mode {
+ ALVIUM_BCM_MODE,
+ ALVIUM_GENCP_MODE,
+ ALVIUM_NUM_MODE
+};
+
+enum alvium_mipi_fmt {
+ ALVIUM_FMT_UYVY8_2X8 = 0,
+ ALVIUM_FMT_UYVY8_1X16,
+ ALVIUM_FMT_YUYV8_1X16,
+ ALVIUM_FMT_YUYV8_2X8,
+ ALVIUM_FMT_YUYV10_1X20,
+ ALVIUM_FMT_RGB888_1X24,
+ ALVIUM_FMT_RBG888_1X24,
+ ALVIUM_FMT_BGR888_1X24,
+ ALVIUM_FMT_RGB888_3X8,
+ ALVIUM_FMT_Y8_1X8,
+ ALVIUM_FMT_SGRBG8_1X8,
+ ALVIUM_FMT_SRGGB8_1X8,
+ ALVIUM_FMT_SGBRG8_1X8,
+ ALVIUM_FMT_SBGGR8_1X8,
+ ALVIUM_FMT_Y10_1X10,
+ ALVIUM_FMT_SGRBG10_1X10,
+ ALVIUM_FMT_SRGGB10_1X10,
+ ALVIUM_FMT_SGBRG10_1X10,
+ ALVIUM_FMT_SBGGR10_1X10,
+ ALVIUM_FMT_Y12_1X12,
+ ALVIUM_FMT_SGRBG12_1X12,
+ ALVIUM_FMT_SRGGB12_1X12,
+ ALVIUM_FMT_SGBRG12_1X12,
+ ALVIUM_FMT_SBGGR12_1X12,
+ ALVIUM_FMT_SBGGR14_1X14,
+ ALVIUM_FMT_SGBRG14_1X14,
+ ALVIUM_FMT_SRGGB14_1X14,
+ ALVIUM_FMT_SGRBG14_1X14,
+ ALVIUM_NUM_SUPP_MIPI_DATA_FMT
+};
+
+enum alvium_av_bayer_bit {
+ ALVIUM_BIT_BAY_NONE = -1,
+ ALVIUM_BIT_BAY_MONO = 0,
+ ALVIUM_BIT_BAY_GR,
+ ALVIUM_BIT_BAY_RG,
+ ALVIUM_BIT_BAY_GB,
+ ALVIUM_BIT_BAY_BG,
+ ALVIUM_NUM_BAY_AV_BIT
+};
+
+enum alvium_av_mipi_bit {
+ ALVIUM_BIT_YUV420_8_LEG = 0,
+ ALVIUM_BIT_YUV420_8,
+ ALVIUM_BIT_YUV420_10,
+ ALVIUM_BIT_YUV420_8_CSPS,
+ ALVIUM_BIT_YUV420_10_CSPS,
+ ALVIUM_BIT_YUV422_8,
+ ALVIUM_BIT_YUV422_10,
+ ALVIUM_BIT_RGB888,
+ ALVIUM_BIT_RGB666,
+ ALVIUM_BIT_RGB565,
+ ALVIUM_BIT_RGB555,
+ ALVIUM_BIT_RGB444,
+ ALVIUM_BIT_RAW6,
+ ALVIUM_BIT_RAW7,
+ ALVIUM_BIT_RAW8,
+ ALVIUM_BIT_RAW10,
+ ALVIUM_BIT_RAW12,
+ ALVIUM_BIT_RAW14,
+ ALVIUM_BIT_JPEG,
+ ALVIUM_NUM_SUPP_MIPI_DATA_BIT
+};
+
+struct alvium_avail_feat {
+ u64 rev_x:1;
+ u64 rev_y:1;
+ u64 int_autop:1;
+ u64 black_lvl:1;
+ u64 gain:1;
+ u64 gamma:1;
+ u64 contrast:1;
+ u64 sat:1;
+ u64 hue:1;
+ u64 whiteb:1;
+ u64 sharp:1;
+ u64 auto_exp:1;
+ u64 auto_gain:1;
+ u64 auto_whiteb:1;
+ u64 dev_temp:1;
+ u64 acq_abort:1;
+ u64 acq_fr:1;
+ u64 fr_trigger:1;
+ u64 exp_acq_line:1;
+ u64 reserved:45;
+};
+
+struct alvium_avail_mipi_fmt {
+ u64 yuv420_8_leg:1;
+ u64 yuv420_8:1;
+ u64 yuv420_10:1;
+ u64 yuv420_8_csps:1;
+ u64 yuv420_10_csps:1;
+ u64 yuv422_8:1;
+ u64 yuv422_10:1;
+ u64 rgb888:1;
+ u64 rgb666:1;
+ u64 rgb565:1;
+ u64 rgb555:1;
+ u64 rgb444:1;
+ u64 raw6:1;
+ u64 raw7:1;
+ u64 raw8:1;
+ u64 raw10:1;
+ u64 raw12:1;
+ u64 raw14:1;
+ u64 jpeg:1;
+ u64 reserved:45;
+};
+
+struct alvium_avail_bayer {
+ u8 mono:1;
+ u8 gr:1;
+ u8 rg:1;
+ u8 gb:1;
+ u8 bg:1;
+ u8 reserved:3;
+};
+
+struct alvium_mode {
+ struct v4l2_rect crop;
+ struct v4l2_mbus_framefmt fmt;
+ u32 width;
+ u32 height;
+};
+
+struct alvium_pixfmt {
+ u32 code;
+ u32 colorspace;
+ u64 mipi_fmt_regval;
+ u64 bay_fmt_regval;
+ u8 id;
+ u8 is_raw;
+ u8 fmt_av_bit;
+ u8 bay_av_bit;
+};
+
+struct alvium_ctrls {
+ struct v4l2_ctrl_handler handler;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *auto_exp;
+ struct v4l2_ctrl *exposure;
+ struct v4l2_ctrl *auto_wb;
+ struct v4l2_ctrl *blue_balance;
+ struct v4l2_ctrl *red_balance;
+ struct v4l2_ctrl *auto_gain;
+ struct v4l2_ctrl *gain;
+ struct v4l2_ctrl *saturation;
+ struct v4l2_ctrl *hue;
+ struct v4l2_ctrl *contrast;
+ struct v4l2_ctrl *gamma;
+ struct v4l2_ctrl *sharpness;
+ struct v4l2_ctrl *hflip;
+ struct v4l2_ctrl *vflip;
+};
+
+struct alvium_dev {
+ struct i2c_client *i2c_client;
+ struct v4l2_subdev sd;
+ struct v4l2_fwnode_endpoint ep;
+ struct media_pad pad;
+ struct regmap *regmap;
+
+ struct regulator *reg_vcc;
+
+ u16 bcrm_addr;
+
+ struct alvium_avail_feat avail_ft;
+ u8 is_mipi_fmt_avail[ALVIUM_NUM_SUPP_MIPI_DATA_BIT];
+ u8 is_bay_avail[ALVIUM_NUM_BAY_AV_BIT];
+
+ u32 min_csi_clk;
+ u32 max_csi_clk;
+ u32 dft_img_width;
+ u32 img_min_width;
+ u32 img_max_width;
+ u32 img_inc_width;
+ u32 dft_img_height;
+ u32 img_min_height;
+ u32 img_max_height;
+ u32 img_inc_height;
+ u32 min_offx;
+ u32 max_offx;
+ u32 inc_offx;
+ u32 min_offy;
+ u32 max_offy;
+ u32 inc_offy;
+ u64 dft_gain;
+ u64 min_gain;
+ u64 max_gain;
+ u64 inc_gain;
+ u64 dft_exp;
+ u64 min_exp;
+ u64 max_exp;
+ u64 inc_exp;
+ u64 dft_rbalance;
+ u64 min_rbalance;
+ u64 max_rbalance;
+ u64 inc_rbalance;
+ u64 dft_bbalance;
+ u64 min_bbalance;
+ u64 max_bbalance;
+ u64 inc_bbalance;
+ s32 dft_hue;
+ s32 min_hue;
+ s32 max_hue;
+ s32 inc_hue;
+ u32 dft_contrast;
+ u32 min_contrast;
+ u32 max_contrast;
+ u32 inc_contrast;
+ u32 dft_sat;
+ u32 min_sat;
+ u32 max_sat;
+ u32 inc_sat;
+ s32 dft_black_lvl;
+ s32 min_black_lvl;
+ s32 max_black_lvl;
+ s32 inc_black_lvl;
+ u64 dft_gamma;
+ u64 min_gamma;
+ u64 max_gamma;
+ u64 inc_gamma;
+ s32 dft_sharp;
+ s32 min_sharp;
+ s32 max_sharp;
+ s32 inc_sharp;
+
+ struct alvium_mode mode;
+ struct v4l2_fract frame_interval;
+ u64 dft_fr;
+ u64 min_fr;
+ u64 max_fr;
+ u64 fr;
+
+ u8 h_sup_csi_lanes;
+ u64 link_freq;
+
+ struct alvium_ctrls ctrls;
+
+ u8 bcrm_mode;
+
+ struct alvium_pixfmt *alvium_csi2_fmt;
+ u8 alvium_csi2_fmt_n;
+
+ u8 streaming;
+ u8 apply_fiv;
+};
+
+static inline struct alvium_dev *sd_to_alvium(struct v4l2_subdev *sd)
+{
+ return container_of_const(sd, struct alvium_dev, sd);
+}
+
+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
+{
+ return &container_of_const(ctrl->handler, struct alvium_dev,
+ ctrls.handler)->sd;
+}
+#endif /* ALVIUM_CSI2_H_ */
diff --git a/drivers/media/i2c/ar0521.c b/drivers/media/i2c/ar0521.c
index 701f36345f..c7d5fa532a 100644
--- a/drivers/media/i2c/ar0521.c
+++ b/drivers/media/i2c/ar0521.c
@@ -446,8 +446,7 @@ static int ar0521_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&sensor->lock);
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt = v4l2_subdev_get_try_format(&sensor->sd, sd_state, 0
- /* pad */);
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
else
fmt = &sensor->fmt;
@@ -472,7 +471,7 @@ static int ar0521_set_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, 0 /* pad */);
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
*fmt = format->format;
mutex_unlock(&sensor->lock);
diff --git a/drivers/media/i2c/ccs/Kconfig b/drivers/media/i2c/ccs/Kconfig
index b55c93a2e2..710a729ae4 100644
--- a/drivers/media/i2c/ccs/Kconfig
+++ b/drivers/media/i2c/ccs/Kconfig
@@ -2,6 +2,7 @@
config VIDEO_CCS
tristate "MIPI CCS/SMIA++/SMIA sensor support"
depends on HAVE_CLK
+ select V4L2_CCI_I2C
select VIDEO_CCS_PLL
help
This is a generic driver for MIPI CCS, SMIA++ and SMIA compliant
diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
index 12e6f0a26f..e21287d50c 100644
--- a/drivers/media/i2c/ccs/ccs-core.c
+++ b/drivers/media/i2c/ccs/ccs-core.c
@@ -25,8 +25,9 @@
#include <linux/slab.h>
#include <linux/smiapp.h>
#include <linux/v4l2-mediabus.h>
-#include <media/v4l2-fwnode.h>
+#include <media/v4l2-cci.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
#include <uapi/linux/ccs.h>
#include "ccs.h"
@@ -98,7 +99,7 @@ static int ccs_limit_ptr(struct ccs_sensor *sensor, unsigned int limit,
linfo = &ccs_limits[ccs_limit_offsets[limit].info];
if (WARN_ON(!sensor->ccs_limits) ||
- WARN_ON(offset + ccs_reg_width(linfo->reg) >
+ WARN_ON(offset + CCI_REG_WIDTH_BYTES(linfo->reg) >
ccs_limit_offsets[limit + 1].lim))
return -EINVAL;
@@ -124,7 +125,7 @@ void ccs_replace_limit(struct ccs_sensor *sensor,
dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" %u = %u, 0x%x\n",
linfo->reg, linfo->name, offset, val, val);
- ccs_assign_limit(ptr, ccs_reg_width(linfo->reg), val);
+ ccs_assign_limit(ptr, CCI_REG_WIDTH_BYTES(linfo->reg), val);
}
u32 ccs_get_limit(struct ccs_sensor *sensor, unsigned int limit,
@@ -138,7 +139,7 @@ u32 ccs_get_limit(struct ccs_sensor *sensor, unsigned int limit,
if (ret)
return 0;
- switch (ccs_reg_width(ccs_limits[ccs_limit_offsets[limit].info].reg)) {
+ switch (CCI_REG_WIDTH_BYTES(ccs_limits[ccs_limit_offsets[limit].info].reg)) {
case sizeof(u8):
val = *(u8 *)ptr;
break;
@@ -172,9 +173,11 @@ static int ccs_read_all_limits(struct ccs_sensor *sensor)
end = alloc + ccs_limit_offsets[CCS_L_LAST].lim;
+ sensor->ccs_limits = alloc;
+
for (i = 0, l = 0, ptr = alloc; ccs_limits[i].size; i++) {
u32 reg = ccs_limits[i].reg;
- unsigned int width = ccs_reg_width(reg);
+ unsigned int width = CCI_REG_WIDTH_BYTES(reg);
unsigned int j;
if (l == CCS_L_LAST) {
@@ -186,6 +189,7 @@ static int ccs_read_all_limits(struct ccs_sensor *sensor)
for (j = 0; j < ccs_limits[i].size / width;
j++, reg += width, ptr += width) {
+ char str[16] = "";
u32 val;
ret = ccs_read_addr_noconv(sensor, reg, &val);
@@ -204,8 +208,15 @@ static int ccs_read_all_limits(struct ccs_sensor *sensor)
ccs_assign_limit(ptr, width, val);
- dev_dbg(&client->dev, "0x%8.8x \"%s\" = %u, 0x%x\n",
- reg, ccs_limits[i].name, val, val);
+#ifdef CONFIG_DYNAMIC_DEBUG
+ if (reg & (CCS_FL_FLOAT_IREAL | CCS_FL_IREAL))
+ snprintf(str, sizeof(str), ", %u",
+ ccs_reg_conv(sensor, reg, val));
+#endif
+
+ dev_dbg(&client->dev,
+ "0x%8.8x \"%s\" = %u, 0x%x%s\n",
+ reg, ccs_limits[i].name, val, val, str);
}
if (ccs_limits[i].flags & CCS_L_FL_SAME_REG)
@@ -222,14 +233,13 @@ static int ccs_read_all_limits(struct ccs_sensor *sensor)
goto out_err;
}
- sensor->ccs_limits = alloc;
-
if (CCS_LIM(sensor, SCALER_N_MIN) < 16)
ccs_replace_limit(sensor, CCS_L_SCALER_N_MIN, 0, 16);
return 0;
out_err:
+ sensor->ccs_limits = NULL;
kfree(alloc);
return ret;
@@ -1878,9 +1888,11 @@ static int ccs_pm_get_init(struct ccs_sensor *sensor)
goto error;
/* Device was already active, so don't set controls */
- if (rval == 1)
+ if (rval == 1 && !sensor->handler_setup_needed)
return 0;
+ sensor->handler_setup_needed = false;
+
/* Restore V4L2 controls to the previously suspended device */
rval = v4l2_ctrl_handler_setup(&sensor->pixel_array->ctrl_handler);
if (rval)
@@ -2030,7 +2042,7 @@ static int __ccs_get_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
- fmt->format = *v4l2_subdev_get_pad_format(subdev, sd_state, fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad);
return 0;
@@ -2061,10 +2073,10 @@ static void ccs_get_crop_compose(struct v4l2_subdev *subdev,
if (crops)
for (i = 0; i < subdev->entity.num_pads; i++)
crops[i] =
- v4l2_subdev_get_pad_crop(subdev, sd_state, i);
+ v4l2_subdev_state_get_crop(sd_state, i);
if (comps)
- *comps = v4l2_subdev_get_pad_compose(subdev, sd_state,
- ssd->sink_pad);
+ *comps = v4l2_subdev_state_get_compose(sd_state,
+ ssd->sink_pad);
}
/* Changes require propagation only on sink pad. */
@@ -2097,7 +2109,7 @@ static void ccs_propagate(struct v4l2_subdev *subdev,
fallthrough;
case V4L2_SEL_TGT_COMPOSE:
*crops[CCS_PAD_SRC] = *comp;
- fmt = v4l2_subdev_get_pad_format(subdev, sd_state, CCS_PAD_SRC);
+ fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC);
fmt->width = comp->width;
fmt->height = comp->height;
if (which == V4L2_SUBDEV_FORMAT_ACTIVE && ssd == sensor->src)
@@ -2507,7 +2519,7 @@ static int ccs_set_crop(struct v4l2_subdev *subdev,
if (sel->pad == ssd->sink_pad) {
struct v4l2_mbus_framefmt *mfmt =
- v4l2_subdev_get_pad_format(subdev, sd_state, sel->pad);
+ v4l2_subdev_state_get_format(sd_state, sel->pad);
src_size.width = mfmt->width;
src_size.height = mfmt->height;
@@ -2567,8 +2579,8 @@ static int ccs_get_selection(struct v4l2_subdev *subdev,
ccs_get_native_size(ssd, &sel->r);
} else if (sel->pad == ssd->sink_pad) {
struct v4l2_mbus_framefmt *sink_fmt =
- v4l2_subdev_get_pad_format(subdev, sd_state,
- ssd->sink_pad);
+ v4l2_subdev_state_get_format(sd_state,
+ ssd->sink_pad);
sel->r.top = sel->r.left = 0;
sel->r.width = sink_fmt->width;
sel->r.height = sink_fmt->height;
@@ -2714,66 +2726,54 @@ static int ccs_identify_module(struct ccs_sensor *sensor)
rval = ccs_read(sensor, MODULE_MANUFACTURER_ID,
&minfo->mipi_manufacturer_id);
if (!rval && !minfo->mipi_manufacturer_id)
- rval = ccs_read_addr_8only(sensor,
- SMIAPP_REG_U8_MANUFACTURER_ID,
- &minfo->smia_manufacturer_id);
+ rval = ccs_read_addr(sensor, SMIAPP_REG_U8_MANUFACTURER_ID,
+ &minfo->smia_manufacturer_id);
if (!rval)
- rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_MODEL_ID,
- &minfo->model_id);
+ rval = ccs_read(sensor, MODULE_MODEL_ID, &minfo->model_id);
if (!rval)
- rval = ccs_read_addr_8only(sensor,
- CCS_R_MODULE_REVISION_NUMBER_MAJOR,
- &rev);
+ rval = ccs_read(sensor, MODULE_REVISION_NUMBER_MAJOR, &rev);
if (!rval) {
- rval = ccs_read_addr_8only(sensor,
- CCS_R_MODULE_REVISION_NUMBER_MINOR,
- &minfo->revision_number);
+ rval = ccs_read(sensor, MODULE_REVISION_NUMBER_MINOR,
+ &minfo->revision_number);
minfo->revision_number |= rev << 8;
}
if (!rval)
- rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_YEAR,
- &minfo->module_year);
+ rval = ccs_read(sensor, MODULE_DATE_YEAR, &minfo->module_year);
if (!rval)
- rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_MONTH,
- &minfo->module_month);
+ rval = ccs_read(sensor, MODULE_DATE_MONTH,
+ &minfo->module_month);
if (!rval)
- rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_DAY,
- &minfo->module_day);
+ rval = ccs_read(sensor, MODULE_DATE_DAY, &minfo->module_day);
/* Sensor info */
if (!rval)
rval = ccs_read(sensor, SENSOR_MANUFACTURER_ID,
&minfo->sensor_mipi_manufacturer_id);
if (!rval && !minfo->sensor_mipi_manufacturer_id)
- rval = ccs_read_addr_8only(sensor,
- CCS_R_SENSOR_MANUFACTURER_ID,
- &minfo->sensor_smia_manufacturer_id);
+ rval = ccs_read(sensor, SENSOR_MANUFACTURER_ID,
+ &minfo->sensor_smia_manufacturer_id);
if (!rval)
- rval = ccs_read_addr_8only(sensor,
- CCS_R_SENSOR_MODEL_ID,
- &minfo->sensor_model_id);
+ rval = ccs_read(sensor, SENSOR_MODEL_ID,
+ &minfo->sensor_model_id);
if (!rval)
- rval = ccs_read_addr_8only(sensor,
- CCS_R_SENSOR_REVISION_NUMBER,
- &minfo->sensor_revision_number);
+ rval = ccs_read(sensor, SENSOR_REVISION_NUMBER,
+ &minfo->sensor_revision_number);
if (!rval && !minfo->sensor_revision_number)
- rval = ccs_read_addr_8only(sensor,
- CCS_R_SENSOR_REVISION_NUMBER_16,
- &minfo->sensor_revision_number);
+ rval = ccs_read(sensor, SENSOR_REVISION_NUMBER_16,
+ &minfo->sensor_revision_number);
if (!rval)
- rval = ccs_read_addr_8only(sensor,
- CCS_R_SENSOR_FIRMWARE_VERSION,
- &minfo->sensor_firmware_version);
+ rval = ccs_read(sensor, SENSOR_FIRMWARE_VERSION,
+ &minfo->sensor_firmware_version);
/* SMIA */
if (!rval)
rval = ccs_read(sensor, MIPI_CCS_VERSION, &minfo->ccs_version);
if (!rval && !minfo->ccs_version)
- rval = ccs_read_addr_8only(sensor, SMIAPP_REG_U8_SMIA_VERSION,
- &minfo->smia_version);
+ rval = ccs_read_addr(sensor, SMIAPP_REG_U8_SMIA_VERSION,
+ &minfo->smia_version);
if (!rval && !minfo->ccs_version)
- rval = ccs_read_addr_8only(sensor, SMIAPP_REG_U8_SMIAPP_VERSION,
- &minfo->smiapp_version);
+ rval = ccs_read_addr(sensor, SMIAPP_REG_U8_SMIAPP_VERSION,
+ &minfo->smiapp_version);
if (rval) {
dev_err(&client->dev, "sensor detection failed\n");
@@ -3004,17 +3004,17 @@ static int ccs_init_subdev(struct ccs_sensor *sensor,
return 0;
}
-static int ccs_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int ccs_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct ccs_subdev *ssd = to_ccs_subdev(sd);
struct ccs_sensor *sensor = ssd->sensor;
unsigned int pad = ssd == sensor->pixel_array ?
CCS_PA_PAD_SRC : CCS_PAD_SINK;
struct v4l2_mbus_framefmt *fmt =
- v4l2_subdev_get_pad_format(sd, sd_state, pad);
+ v4l2_subdev_state_get_format(sd_state, pad);
struct v4l2_rect *crop =
- v4l2_subdev_get_pad_crop(sd, sd_state, pad);
+ v4l2_subdev_state_get_crop(sd_state, pad);
bool is_active = !sd->active_state || sd->active_state == sd_state;
mutex_lock(&sensor->mutex);
@@ -3034,7 +3034,7 @@ static int ccs_init_cfg(struct v4l2_subdev *sd,
return 0;
}
- fmt = v4l2_subdev_get_pad_format(sd, sd_state, CCS_PAD_SRC);
+ fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC);
fmt->code = ssd == sensor->src ?
sensor->csi_format->code : sensor->internal_csi_format->code;
fmt->field = V4L2_FIELD_NONE;
@@ -3053,7 +3053,6 @@ static const struct v4l2_subdev_video_ops ccs_video_ops = {
};
static const struct v4l2_subdev_pad_ops ccs_pad_ops = {
- .init_cfg = ccs_init_cfg,
.enum_mbus_code = ccs_enum_mbus_code,
.get_fmt = ccs_get_format,
.set_fmt = ccs_set_format,
@@ -3077,6 +3076,7 @@ static const struct media_entity_operations ccs_entity_ops = {
};
static const struct v4l2_subdev_internal_ops ccs_internal_src_ops = {
+ .init_state = ccs_init_state,
.registered = ccs_registered,
.unregistered = ccs_unregistered,
};
@@ -3307,6 +3307,13 @@ static int ccs_probe(struct i2c_client *client)
if (IS_ERR(sensor->xshutdown))
return PTR_ERR(sensor->xshutdown);
+ sensor->regmap = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(sensor->regmap)) {
+ dev_err(&client->dev, "can't initialise CCI (%ld)\n",
+ PTR_ERR(sensor->regmap));
+ return PTR_ERR(sensor->regmap);
+ }
+
rval = ccs_power_on(&client->dev);
if (rval < 0)
return rval;
@@ -3532,6 +3539,7 @@ static int ccs_probe(struct i2c_client *client)
sensor->streaming = false;
sensor->dev_init_done = true;
+ sensor->handler_setup_needed = true;
rval = ccs_write_msr_regs(sensor);
if (rval)
@@ -3636,12 +3644,16 @@ static int ccs_module_init(void)
{
unsigned int i, l;
+ CCS_BUILD_BUG;
+
for (i = 0, l = 0; ccs_limits[i].size && l < CCS_L_LAST; i++) {
if (!(ccs_limits[i].flags & CCS_L_FL_SAME_REG)) {
ccs_limit_offsets[l + 1].lim =
ALIGN(ccs_limit_offsets[l].lim +
ccs_limits[i].size,
- ccs_reg_width(ccs_limits[i + 1].reg));
+ ccs_limits[i + 1].reg ?
+ CCI_REG_WIDTH_BYTES(ccs_limits[i + 1].reg) :
+ 1U);
ccs_limit_offsets[l].info = i;
l++;
} else {
diff --git a/drivers/media/i2c/ccs/ccs-reg-access.c b/drivers/media/i2c/ccs/ccs-reg-access.c
index 25993445f4..ed79075505 100644
--- a/drivers/media/i2c/ccs/ccs-reg-access.c
+++ b/drivers/media/i2c/ccs/ccs-reg-access.c
@@ -62,87 +62,6 @@ static u32 float_to_u32_mul_1000000(struct i2c_client *client, u32 phloat)
}
-/*
- * Read a 8/16/32-bit i2c register. The value is returned in 'val'.
- * Returns zero if successful, or non-zero otherwise.
- */
-static int ____ccs_read_addr(struct ccs_sensor *sensor, u16 reg, u16 len,
- u32 *val)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
- struct i2c_msg msg;
- unsigned char data_buf[sizeof(u32)] = { 0 };
- unsigned char offset_buf[sizeof(u16)];
- int r;
-
- if (len > sizeof(data_buf))
- return -EINVAL;
-
- msg.addr = client->addr;
- msg.flags = 0;
- msg.len = sizeof(offset_buf);
- msg.buf = offset_buf;
- put_unaligned_be16(reg, offset_buf);
-
- r = i2c_transfer(client->adapter, &msg, 1);
- if (r != 1) {
- if (r >= 0)
- r = -EBUSY;
- goto err;
- }
-
- msg.len = len;
- msg.flags = I2C_M_RD;
- msg.buf = &data_buf[sizeof(data_buf) - len];
-
- r = i2c_transfer(client->adapter, &msg, 1);
- if (r != 1) {
- if (r >= 0)
- r = -EBUSY;
- goto err;
- }
-
- *val = get_unaligned_be32(data_buf);
-
- return 0;
-
-err:
- dev_err(&client->dev, "read from offset 0x%x error %d\n", reg, r);
-
- return r;
-}
-
-/* Read a register using 8-bit access only. */
-static int ____ccs_read_addr_8only(struct ccs_sensor *sensor, u16 reg,
- u16 len, u32 *val)
-{
- unsigned int i;
- int rval;
-
- *val = 0;
-
- for (i = 0; i < len; i++) {
- u32 val8;
-
- rval = ____ccs_read_addr(sensor, reg + i, 1, &val8);
- if (rval < 0)
- return rval;
- *val |= val8 << ((len - i - 1) << 3);
- }
-
- return 0;
-}
-
-unsigned int ccs_reg_width(u32 reg)
-{
- if (reg & CCS_FL_16BIT)
- return sizeof(u16);
- if (reg & CCS_FL_32BIT)
- return sizeof(u32);
-
- return sizeof(u8);
-}
-
static u32 ireal32_to_u32_mul_1000000(struct i2c_client *client, u32 val)
{
if (val >> 10 > U32_MAX / 15625) {
@@ -178,29 +97,22 @@ u32 ccs_reg_conv(struct ccs_sensor *sensor, u32 reg, u32 val)
static int __ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val,
bool only8, bool conv)
{
- unsigned int len = ccs_reg_width(reg);
+ u64 __val;
int rval;
- if (!only8)
- rval = ____ccs_read_addr(sensor, CCS_REG_ADDR(reg), len, val);
- else
- rval = ____ccs_read_addr_8only(sensor, CCS_REG_ADDR(reg), len,
- val);
+ rval = cci_read(sensor->regmap, reg, &__val, NULL);
if (rval < 0)
return rval;
- if (!conv)
- return 0;
-
- *val = ccs_reg_conv(sensor, reg, *val);
+ *val = conv ? ccs_reg_conv(sensor, reg, __val) : __val;
return 0;
}
-static int __ccs_read_data(struct ccs_reg *regs, size_t num_regs,
- u32 reg, u32 *val)
+static int __ccs_static_data_read_ro_reg(struct ccs_reg *regs, size_t num_regs,
+ u32 reg, u32 *val)
{
- unsigned int width = ccs_reg_width(reg);
+ unsigned int width = CCI_REG_WIDTH_BYTES(reg);
size_t i;
for (i = 0; i < num_regs; i++, regs++) {
@@ -235,16 +147,17 @@ static int __ccs_read_data(struct ccs_reg *regs, size_t num_regs,
return -ENOENT;
}
-static int ccs_read_data(struct ccs_sensor *sensor, u32 reg, u32 *val)
+static int
+ccs_static_data_read_ro_reg(struct ccs_sensor *sensor, u32 reg, u32 *val)
{
- if (!__ccs_read_data(sensor->sdata.sensor_read_only_regs,
- sensor->sdata.num_sensor_read_only_regs,
- reg, val))
+ if (!__ccs_static_data_read_ro_reg(sensor->sdata.sensor_read_only_regs,
+ sensor->sdata.num_sensor_read_only_regs,
+ reg, val))
return 0;
- return __ccs_read_data(sensor->mdata.module_read_only_regs,
- sensor->mdata.num_module_read_only_regs,
- reg, val);
+ return __ccs_static_data_read_ro_reg(sensor->mdata.module_read_only_regs,
+ sensor->mdata.num_module_read_only_regs,
+ reg, val);
}
static int ccs_read_addr_raw(struct ccs_sensor *sensor, u32 reg, u32 *val,
@@ -253,7 +166,7 @@ static int ccs_read_addr_raw(struct ccs_sensor *sensor, u32 reg, u32 *val,
int rval;
if (data) {
- rval = ccs_read_data(sensor, reg, val);
+ rval = ccs_static_data_read_ro_reg(sensor, reg, val);
if (!rval)
return 0;
}
@@ -291,71 +204,13 @@ int ccs_read_addr_noconv(struct ccs_sensor *sensor, u32 reg, u32 *val)
return ccs_read_addr_raw(sensor, reg, val, false, true, false, true);
}
-static int ccs_write_retry(struct i2c_client *client, struct i2c_msg *msg)
-{
- unsigned int retries;
- int r;
-
- for (retries = 0; retries < 10; retries++) {
- /*
- * Due to unknown reason sensor stops responding. This
- * loop is a temporaty solution until the root cause
- * is found.
- */
- r = i2c_transfer(client->adapter, msg, 1);
- if (r != 1) {
- usleep_range(1000, 2000);
- continue;
- }
-
- if (retries)
- dev_err(&client->dev,
- "sensor i2c stall encountered. retries: %d\n",
- retries);
- return 0;
- }
-
- return r;
-}
-
-int ccs_write_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 val)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
- struct i2c_msg msg;
- unsigned char data[6];
- unsigned int len = ccs_reg_width(reg);
- int r;
-
- if (len > sizeof(data) - 2)
- return -EINVAL;
-
- msg.addr = client->addr;
- msg.flags = 0; /* Write */
- msg.len = 2 + len;
- msg.buf = data;
-
- put_unaligned_be16(CCS_REG_ADDR(reg), data);
- put_unaligned_be32(val << (8 * (sizeof(val) - len)), data + 2);
-
- dev_dbg(&client->dev, "writing reg 0x%4.4x value 0x%*.*x (%u)\n",
- CCS_REG_ADDR(reg), ccs_reg_width(reg) << 1,
- ccs_reg_width(reg) << 1, val, val);
-
- r = ccs_write_retry(client, &msg);
- if (r)
- dev_err(&client->dev,
- "wrote 0x%x to offset 0x%x error %d\n", val,
- CCS_REG_ADDR(reg), r);
-
- return r;
-}
-
/*
* Write to a 8/16-bit register.
* Returns zero if successful, or non-zero otherwise.
*/
int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val)
{
+ unsigned int retries = 10;
int rval;
rval = ccs_call_quirk(sensor, reg_access, true, &reg, &val);
@@ -364,7 +219,13 @@ int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val)
if (rval < 0)
return rval;
- return ccs_write_addr_no_quirk(sensor, reg, val);
+ rval = 0;
+ do {
+ if (cci_write(sensor->regmap, reg, val, &rval))
+ fsleep(1000);
+ } while (rval && --retries);
+
+ return rval;
}
#define MAX_WRITE_LEN 32U
@@ -373,40 +234,38 @@ int ccs_write_data_regs(struct ccs_sensor *sensor, struct ccs_reg *regs,
size_t num_regs)
{
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
- unsigned char buf[2 + MAX_WRITE_LEN];
- struct i2c_msg msg = {
- .addr = client->addr,
- .buf = buf,
- };
size_t i;
for (i = 0; i < num_regs; i++, regs++) {
unsigned char *regdata = regs->value;
unsigned int j;
+ int len;
- for (j = 0; j < regs->len;
- j += msg.len - 2, regdata += msg.len - 2) {
+ for (j = 0; j < regs->len; j += len, regdata += len) {
char printbuf[(MAX_WRITE_LEN << 1) +
1 /* \0 */] = { 0 };
+ unsigned int retries = 10;
int rval;
- msg.len = min(regs->len - j, MAX_WRITE_LEN);
+ len = min(regs->len - j, MAX_WRITE_LEN);
- bin2hex(printbuf, regdata, msg.len);
+ bin2hex(printbuf, regdata, len);
dev_dbg(&client->dev,
"writing msr reg 0x%4.4x value 0x%s\n",
regs->addr + j, printbuf);
- put_unaligned_be16(regs->addr + j, buf);
- memcpy(buf + 2, regdata, msg.len);
-
- msg.len += 2;
+ do {
+ rval = regmap_bulk_write(sensor->regmap,
+ regs->addr + j,
+ regdata, len);
+ if (rval)
+ fsleep(1000);
+ } while (rval && --retries);
- rval = ccs_write_retry(client, &msg);
if (rval) {
dev_err(&client->dev,
"error writing %u octets to address 0x%4.4x\n",
- msg.len, regs->addr + j);
+ len, regs->addr + j);
return rval;
}
}
diff --git a/drivers/media/i2c/ccs/ccs-regs.h b/drivers/media/i2c/ccs/ccs-regs.h
index 6ce84c5ecf..7b5dbc86e4 100644
--- a/drivers/media/i2c/ccs/ccs-regs.h
+++ b/drivers/media/i2c/ccs/ccs-regs.h
@@ -10,59 +10,59 @@
#include <linux/bits.h>
-#define CCS_FL_BASE 16
-#define CCS_FL_16BIT BIT(CCS_FL_BASE)
-#define CCS_FL_32BIT BIT(CCS_FL_BASE + 1)
-#define CCS_FL_FLOAT_IREAL BIT(CCS_FL_BASE + 2)
-#define CCS_FL_IREAL BIT(CCS_FL_BASE + 3)
-#define CCS_R_ADDR(r) ((r) & 0xffff)
+#include <media/v4l2-cci.h>
-#define CCS_R_MODULE_MODEL_ID (0x0000 | CCS_FL_16BIT)
-#define CCS_R_MODULE_REVISION_NUMBER_MAJOR 0x0002
-#define CCS_R_FRAME_COUNT 0x0005
-#define CCS_R_PIXEL_ORDER 0x0006
+#define CCS_FL_BASE CCI_REG_PRIVATE_SHIFT
+#define CCS_FL_FLOAT_IREAL BIT(CCS_FL_BASE)
+#define CCS_FL_IREAL BIT(CCS_FL_BASE + 1)
+#define CCS_BUILD_BUG \
+ BUILD_BUG_ON(~CCI_REG_PRIVATE_MASK & (BIT(CCS_FL_BASE) | BIT(CCS_FL_BASE + 1)))
+#define CCS_R_MODULE_MODEL_ID CCI_REG16(0x0000)
+#define CCS_R_MODULE_REVISION_NUMBER_MAJOR CCI_REG8(0x0002)
+#define CCS_R_FRAME_COUNT CCI_REG8(0x0005)
+#define CCS_R_PIXEL_ORDER CCI_REG8(0x0006)
#define CCS_PIXEL_ORDER_GRBG 0U
#define CCS_PIXEL_ORDER_RGGB 1U
#define CCS_PIXEL_ORDER_BGGR 2U
#define CCS_PIXEL_ORDER_GBRG 3U
-#define CCS_R_MIPI_CCS_VERSION 0x0007
+#define CCS_R_MIPI_CCS_VERSION CCI_REG8(0x0007)
#define CCS_MIPI_CCS_VERSION_V1_0 0x10
#define CCS_MIPI_CCS_VERSION_V1_1 0x11
#define CCS_MIPI_CCS_VERSION_MAJOR_SHIFT 4U
#define CCS_MIPI_CCS_VERSION_MAJOR_MASK 0xf0
#define CCS_MIPI_CCS_VERSION_MINOR_SHIFT 0U
#define CCS_MIPI_CCS_VERSION_MINOR_MASK 0xf
-#define CCS_R_DATA_PEDESTAL (0x0008 | CCS_FL_16BIT)
-#define CCS_R_MODULE_MANUFACTURER_ID (0x000e | CCS_FL_16BIT)
-#define CCS_R_MODULE_REVISION_NUMBER_MINOR 0x0010
-#define CCS_R_MODULE_DATE_YEAR 0x0012
-#define CCS_R_MODULE_DATE_MONTH 0x0013
-#define CCS_R_MODULE_DATE_DAY 0x0014
-#define CCS_R_MODULE_DATE_PHASE 0x0015
+#define CCS_R_DATA_PEDESTAL CCI_REG16(0x0008)
+#define CCS_R_MODULE_MANUFACTURER_ID CCI_REG16(0x000e)
+#define CCS_R_MODULE_REVISION_NUMBER_MINOR CCI_REG8(0x0010)
+#define CCS_R_MODULE_DATE_YEAR CCI_REG8(0x0012)
+#define CCS_R_MODULE_DATE_MONTH CCI_REG8(0x0013)
+#define CCS_R_MODULE_DATE_DAY CCI_REG8(0x0014)
+#define CCS_R_MODULE_DATE_PHASE CCI_REG8(0x0015)
#define CCS_MODULE_DATE_PHASE_SHIFT 0U
#define CCS_MODULE_DATE_PHASE_MASK 0x7
#define CCS_MODULE_DATE_PHASE_TS 0U
#define CCS_MODULE_DATE_PHASE_ES 1U
#define CCS_MODULE_DATE_PHASE_CS 2U
#define CCS_MODULE_DATE_PHASE_MP 3U
-#define CCS_R_SENSOR_MODEL_ID (0x0016 | CCS_FL_16BIT)
-#define CCS_R_SENSOR_REVISION_NUMBER 0x0018
-#define CCS_R_SENSOR_FIRMWARE_VERSION 0x001a
-#define CCS_R_SERIAL_NUMBER (0x001c | CCS_FL_32BIT)
-#define CCS_R_SENSOR_MANUFACTURER_ID (0x0020 | CCS_FL_16BIT)
-#define CCS_R_SENSOR_REVISION_NUMBER_16 (0x0022 | CCS_FL_16BIT)
-#define CCS_R_FRAME_FORMAT_MODEL_TYPE 0x0040
+#define CCS_R_SENSOR_MODEL_ID CCI_REG16(0x0016)
+#define CCS_R_SENSOR_REVISION_NUMBER CCI_REG8(0x0018)
+#define CCS_R_SENSOR_FIRMWARE_VERSION CCI_REG8(0x001a)
+#define CCS_R_SERIAL_NUMBER CCI_REG32(0x001c)
+#define CCS_R_SENSOR_MANUFACTURER_ID CCI_REG16(0x0020)
+#define CCS_R_SENSOR_REVISION_NUMBER_16 CCI_REG16(0x0022)
+#define CCS_R_FRAME_FORMAT_MODEL_TYPE CCI_REG8(0x0040)
#define CCS_FRAME_FORMAT_MODEL_TYPE_2_BYTE 1U
#define CCS_FRAME_FORMAT_MODEL_TYPE_4_BYTE 2U
-#define CCS_R_FRAME_FORMAT_MODEL_SUBTYPE 0x0041
+#define CCS_R_FRAME_FORMAT_MODEL_SUBTYPE CCI_REG8(0x0041)
#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_ROWS_SHIFT 0U
#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_ROWS_MASK 0xf
#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_SHIFT 4U
#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_MASK 0xf0
-#define CCS_R_FRAME_FORMAT_DESCRIPTOR(n) ((0x0042 | CCS_FL_16BIT) + (n) * 2)
+#define CCS_R_FRAME_FORMAT_DESCRIPTOR(n) CCI_REG16(0x0042 + (n) * 2)
#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_MIN_N 0U
#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_MAX_N 14U
-#define CCS_R_FRAME_FORMAT_DESCRIPTOR_4(n) ((0x0060 | CCS_FL_32BIT) + (n) * 4)
+#define CCS_R_FRAME_FORMAT_DESCRIPTOR_4(n) CCI_REG32(0x0060 + (n) * 4)
#define CCS_FRAME_FORMAT_DESCRIPTOR_PIXELS_SHIFT 0U
#define CCS_FRAME_FORMAT_DESCRIPTOR_PIXELS_MASK 0xfff
#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_SHIFT 12U
@@ -97,91 +97,91 @@
#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_4 12U
#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_5 13U
#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_6 14U
-#define CCS_R_ANALOG_GAIN_CAPABILITY (0x0080 | CCS_FL_16BIT)
+#define CCS_R_ANALOG_GAIN_CAPABILITY CCI_REG16(0x0080)
#define CCS_ANALOG_GAIN_CAPABILITY_GLOBAL 0U
#define CCS_ANALOG_GAIN_CAPABILITY_ALTERNATE_GLOBAL 2U
-#define CCS_R_ANALOG_GAIN_CODE_MIN (0x0084 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_GAIN_CODE_MAX (0x0086 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_GAIN_CODE_STEP (0x0088 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_GAIN_TYPE (0x008a | CCS_FL_16BIT)
-#define CCS_R_ANALOG_GAIN_M0 (0x008c | CCS_FL_16BIT)
-#define CCS_R_ANALOG_GAIN_C0 (0x008e | CCS_FL_16BIT)
-#define CCS_R_ANALOG_GAIN_M1 (0x0090 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_GAIN_C1 (0x0092 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_LINEAR_GAIN_MIN (0x0094 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_LINEAR_GAIN_MAX (0x0096 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_LINEAR_GAIN_STEP_SIZE (0x0098 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_EXPONENTIAL_GAIN_MIN (0x009a | CCS_FL_16BIT)
-#define CCS_R_ANALOG_EXPONENTIAL_GAIN_MAX (0x009c | CCS_FL_16BIT)
-#define CCS_R_ANALOG_EXPONENTIAL_GAIN_STEP_SIZE (0x009e | CCS_FL_16BIT)
-#define CCS_R_DATA_FORMAT_MODEL_TYPE 0x00c0
+#define CCS_R_ANALOG_GAIN_CODE_MIN CCI_REG16(0x0084)
+#define CCS_R_ANALOG_GAIN_CODE_MAX CCI_REG16(0x0086)
+#define CCS_R_ANALOG_GAIN_CODE_STEP CCI_REG16(0x0088)
+#define CCS_R_ANALOG_GAIN_TYPE CCI_REG16(0x008a)
+#define CCS_R_ANALOG_GAIN_M0 CCI_REG16(0x008c)
+#define CCS_R_ANALOG_GAIN_C0 CCI_REG16(0x008e)
+#define CCS_R_ANALOG_GAIN_M1 CCI_REG16(0x0090)
+#define CCS_R_ANALOG_GAIN_C1 CCI_REG16(0x0092)
+#define CCS_R_ANALOG_LINEAR_GAIN_MIN CCI_REG16(0x0094)
+#define CCS_R_ANALOG_LINEAR_GAIN_MAX CCI_REG16(0x0096)
+#define CCS_R_ANALOG_LINEAR_GAIN_STEP_SIZE CCI_REG16(0x0098)
+#define CCS_R_ANALOG_EXPONENTIAL_GAIN_MIN CCI_REG16(0x009a)
+#define CCS_R_ANALOG_EXPONENTIAL_GAIN_MAX CCI_REG16(0x009c)
+#define CCS_R_ANALOG_EXPONENTIAL_GAIN_STEP_SIZE CCI_REG16(0x009e)
+#define CCS_R_DATA_FORMAT_MODEL_TYPE CCI_REG8(0x00c0)
#define CCS_DATA_FORMAT_MODEL_TYPE_NORMAL 1U
#define CCS_DATA_FORMAT_MODEL_TYPE_EXTENDED 2U
-#define CCS_R_DATA_FORMAT_MODEL_SUBTYPE 0x00c1
+#define CCS_R_DATA_FORMAT_MODEL_SUBTYPE CCI_REG8(0x00c1)
#define CCS_DATA_FORMAT_MODEL_SUBTYPE_ROWS_SHIFT 0U
#define CCS_DATA_FORMAT_MODEL_SUBTYPE_ROWS_MASK 0xf
#define CCS_DATA_FORMAT_MODEL_SUBTYPE_COLUMNS_SHIFT 4U
#define CCS_DATA_FORMAT_MODEL_SUBTYPE_COLUMNS_MASK 0xf0
-#define CCS_R_DATA_FORMAT_DESCRIPTOR(n) ((0x00c2 | CCS_FL_16BIT) + (n) * 2)
+#define CCS_R_DATA_FORMAT_DESCRIPTOR(n) CCI_REG16(0x00c2 + (n) * 2)
#define CCS_LIM_DATA_FORMAT_DESCRIPTOR_MIN_N 0U
#define CCS_LIM_DATA_FORMAT_DESCRIPTOR_MAX_N 15U
#define CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_SHIFT 0U
#define CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_MASK 0xff
#define CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_SHIFT 8U
#define CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_MASK 0xff00
-#define CCS_R_MODE_SELECT 0x0100
+#define CCS_R_MODE_SELECT CCI_REG8(0x0100)
#define CCS_MODE_SELECT_SOFTWARE_STANDBY 0U
#define CCS_MODE_SELECT_STREAMING 1U
-#define CCS_R_IMAGE_ORIENTATION 0x0101
+#define CCS_R_IMAGE_ORIENTATION CCI_REG8(0x0101)
#define CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR BIT(0)
#define CCS_IMAGE_ORIENTATION_VERTICAL_FLIP BIT(1)
-#define CCS_R_SOFTWARE_RESET 0x0103
+#define CCS_R_SOFTWARE_RESET CCI_REG8(0x0103)
#define CCS_SOFTWARE_RESET_OFF 0U
#define CCS_SOFTWARE_RESET_ON 1U
-#define CCS_R_GROUPED_PARAMETER_HOLD 0x0104
-#define CCS_R_MASK_CORRUPTED_FRAMES 0x0105
+#define CCS_R_GROUPED_PARAMETER_HOLD CCI_REG8(0x0104)
+#define CCS_R_MASK_CORRUPTED_FRAMES CCI_REG8(0x0105)
#define CCS_MASK_CORRUPTED_FRAMES_ALLOW 0U
#define CCS_MASK_CORRUPTED_FRAMES_MASK 1U
-#define CCS_R_FAST_STANDBY_CTRL 0x0106
+#define CCS_R_FAST_STANDBY_CTRL CCI_REG8(0x0106)
#define CCS_FAST_STANDBY_CTRL_COMPLETE_FRAMES 0U
#define CCS_FAST_STANDBY_CTRL_FRAME_TRUNCATION 1U
-#define CCS_R_CCI_ADDRESS_CTRL 0x0107
-#define CCS_R_2ND_CCI_IF_CTRL 0x0108
+#define CCS_R_CCI_ADDRESS_CTRL CCI_REG8(0x0107)
+#define CCS_R_2ND_CCI_IF_CTRL CCI_REG8(0x0108)
#define CCS_2ND_CCI_IF_CTRL_ENABLE BIT(0)
#define CCS_2ND_CCI_IF_CTRL_ACK BIT(1)
-#define CCS_R_2ND_CCI_ADDRESS_CTRL 0x0109
-#define CCS_R_CSI_CHANNEL_IDENTIFIER 0x0110
-#define CCS_R_CSI_SIGNALING_MODE 0x0111
+#define CCS_R_2ND_CCI_ADDRESS_CTRL CCI_REG8(0x0109)
+#define CCS_R_CSI_CHANNEL_IDENTIFIER CCI_REG8(0x0110)
+#define CCS_R_CSI_SIGNALING_MODE CCI_REG8(0x0111)
#define CCS_CSI_SIGNALING_MODE_CSI_2_DPHY 2U
#define CCS_CSI_SIGNALING_MODE_CSI_2_CPHY 3U
-#define CCS_R_CSI_DATA_FORMAT (0x0112 | CCS_FL_16BIT)
-#define CCS_R_CSI_LANE_MODE 0x0114
-#define CCS_R_DPCM_FRAME_DT 0x011d
-#define CCS_R_BOTTOM_EMBEDDED_DATA_DT 0x011e
-#define CCS_R_BOTTOM_EMBEDDED_DATA_VC 0x011f
-#define CCS_R_GAIN_MODE 0x0120
+#define CCS_R_CSI_DATA_FORMAT CCI_REG16(0x0112)
+#define CCS_R_CSI_LANE_MODE CCI_REG8(0x0114)
+#define CCS_R_DPCM_FRAME_DT CCI_REG8(0x011d)
+#define CCS_R_BOTTOM_EMBEDDED_DATA_DT CCI_REG8(0x011e)
+#define CCS_R_BOTTOM_EMBEDDED_DATA_VC CCI_REG8(0x011f)
+#define CCS_R_GAIN_MODE CCI_REG8(0x0120)
#define CCS_GAIN_MODE_GLOBAL 0U
#define CCS_GAIN_MODE_ALTERNATE 1U
-#define CCS_R_ADC_BIT_DEPTH 0x0121
-#define CCS_R_EMB_DATA_CTRL 0x0122
+#define CCS_R_ADC_BIT_DEPTH CCI_REG8(0x0121)
+#define CCS_R_EMB_DATA_CTRL CCI_REG8(0x0122)
#define CCS_EMB_DATA_CTRL_RAW8_PACKING_FOR_RAW16 BIT(0)
#define CCS_EMB_DATA_CTRL_RAW10_PACKING_FOR_RAW20 BIT(1)
#define CCS_EMB_DATA_CTRL_RAW12_PACKING_FOR_RAW24 BIT(2)
-#define CCS_R_GPIO_TRIG_MODE 0x0130
-#define CCS_R_EXTCLK_FREQUENCY_MHZ (0x0136 | (CCS_FL_16BIT | CCS_FL_IREAL))
-#define CCS_R_TEMP_SENSOR_CTRL 0x0138
+#define CCS_R_GPIO_TRIG_MODE CCI_REG8(0x0130)
+#define CCS_R_EXTCLK_FREQUENCY_MHZ (CCI_REG16(0x0136) | CCS_FL_IREAL)
+#define CCS_R_TEMP_SENSOR_CTRL CCI_REG8(0x0138)
#define CCS_TEMP_SENSOR_CTRL_ENABLE BIT(0)
-#define CCS_R_TEMP_SENSOR_MODE 0x0139
-#define CCS_R_TEMP_SENSOR_OUTPUT 0x013a
-#define CCS_R_FINE_INTEGRATION_TIME (0x0200 | CCS_FL_16BIT)
-#define CCS_R_COARSE_INTEGRATION_TIME (0x0202 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_GAIN_CODE_GLOBAL (0x0204 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_LINEAR_GAIN_GLOBAL (0x0206 | CCS_FL_16BIT)
-#define CCS_R_ANALOG_EXPONENTIAL_GAIN_GLOBAL (0x0208 | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_GAIN_GLOBAL (0x020e | CCS_FL_16BIT)
-#define CCS_R_SHORT_ANALOG_GAIN_GLOBAL (0x0216 | CCS_FL_16BIT)
-#define CCS_R_SHORT_DIGITAL_GAIN_GLOBAL (0x0218 | CCS_FL_16BIT)
-#define CCS_R_HDR_MODE 0x0220
+#define CCS_R_TEMP_SENSOR_MODE CCI_REG8(0x0139)
+#define CCS_R_TEMP_SENSOR_OUTPUT CCI_REG8(0x013a)
+#define CCS_R_FINE_INTEGRATION_TIME CCI_REG16(0x0200)
+#define CCS_R_COARSE_INTEGRATION_TIME CCI_REG16(0x0202)
+#define CCS_R_ANALOG_GAIN_CODE_GLOBAL CCI_REG16(0x0204)
+#define CCS_R_ANALOG_LINEAR_GAIN_GLOBAL CCI_REG16(0x0206)
+#define CCS_R_ANALOG_EXPONENTIAL_GAIN_GLOBAL CCI_REG16(0x0208)
+#define CCS_R_DIGITAL_GAIN_GLOBAL CCI_REG16(0x020e)
+#define CCS_R_SHORT_ANALOG_GAIN_GLOBAL CCI_REG16(0x0216)
+#define CCS_R_SHORT_DIGITAL_GAIN_GLOBAL CCI_REG16(0x0218)
+#define CCS_R_HDR_MODE CCI_REG8(0x0220)
#define CCS_HDR_MODE_ENABLED BIT(0)
#define CCS_HDR_MODE_SEPARATE_ANALOG_GAIN BIT(1)
#define CCS_HDR_MODE_UPSCALING BIT(2)
@@ -189,421 +189,421 @@
#define CCS_HDR_MODE_TIMING_MODE BIT(4)
#define CCS_HDR_MODE_EXPOSURE_CTRL_DIRECT BIT(5)
#define CCS_HDR_MODE_SEPARATE_DIGITAL_GAIN BIT(6)
-#define CCS_R_HDR_RESOLUTION_REDUCTION 0x0221
+#define CCS_R_HDR_RESOLUTION_REDUCTION CCI_REG8(0x0221)
#define CCS_HDR_RESOLUTION_REDUCTION_ROW_SHIFT 0U
#define CCS_HDR_RESOLUTION_REDUCTION_ROW_MASK 0xf
#define CCS_HDR_RESOLUTION_REDUCTION_COLUMN_SHIFT 4U
#define CCS_HDR_RESOLUTION_REDUCTION_COLUMN_MASK 0xf0
-#define CCS_R_EXPOSURE_RATIO 0x0222
-#define CCS_R_HDR_INTERNAL_BIT_DEPTH 0x0223
-#define CCS_R_DIRECT_SHORT_INTEGRATION_TIME (0x0224 | CCS_FL_16BIT)
-#define CCS_R_SHORT_ANALOG_LINEAR_GAIN_GLOBAL (0x0226 | CCS_FL_16BIT)
-#define CCS_R_SHORT_ANALOG_EXPONENTIAL_GAIN_GLOBAL (0x0228 | CCS_FL_16BIT)
-#define CCS_R_VT_PIX_CLK_DIV (0x0300 | CCS_FL_16BIT)
-#define CCS_R_VT_SYS_CLK_DIV (0x0302 | CCS_FL_16BIT)
-#define CCS_R_PRE_PLL_CLK_DIV (0x0304 | CCS_FL_16BIT)
-#define CCS_R_PLL_MULTIPLIER (0x0306 | CCS_FL_16BIT)
-#define CCS_R_OP_PIX_CLK_DIV (0x0308 | CCS_FL_16BIT)
-#define CCS_R_OP_SYS_CLK_DIV (0x030a | CCS_FL_16BIT)
-#define CCS_R_OP_PRE_PLL_CLK_DIV (0x030c | CCS_FL_16BIT)
-#define CCS_R_OP_PLL_MULTIPLIER (0x030e | CCS_FL_16BIT)
-#define CCS_R_PLL_MODE 0x0310
+#define CCS_R_EXPOSURE_RATIO CCI_REG8(0x0222)
+#define CCS_R_HDR_INTERNAL_BIT_DEPTH CCI_REG8(0x0223)
+#define CCS_R_DIRECT_SHORT_INTEGRATION_TIME CCI_REG16(0x0224)
+#define CCS_R_SHORT_ANALOG_LINEAR_GAIN_GLOBAL CCI_REG16(0x0226)
+#define CCS_R_SHORT_ANALOG_EXPONENTIAL_GAIN_GLOBAL CCI_REG16(0x0228)
+#define CCS_R_VT_PIX_CLK_DIV CCI_REG16(0x0300)
+#define CCS_R_VT_SYS_CLK_DIV CCI_REG16(0x0302)
+#define CCS_R_PRE_PLL_CLK_DIV CCI_REG16(0x0304)
+#define CCS_R_PLL_MULTIPLIER CCI_REG16(0x0306)
+#define CCS_R_OP_PIX_CLK_DIV CCI_REG16(0x0308)
+#define CCS_R_OP_SYS_CLK_DIV CCI_REG16(0x030a)
+#define CCS_R_OP_PRE_PLL_CLK_DIV CCI_REG16(0x030c)
+#define CCS_R_OP_PLL_MULTIPLIER CCI_REG16(0x030e)
+#define CCS_R_PLL_MODE CCI_REG8(0x0310)
#define CCS_PLL_MODE_SHIFT 0U
#define CCS_PLL_MODE_MASK 0x1
#define CCS_PLL_MODE_SINGLE 0U
#define CCS_PLL_MODE_DUAL 1U
-#define CCS_R_OP_PIX_CLK_DIV_REV (0x0312 | CCS_FL_16BIT)
-#define CCS_R_OP_SYS_CLK_DIV_REV (0x0314 | CCS_FL_16BIT)
-#define CCS_R_FRAME_LENGTH_LINES (0x0340 | CCS_FL_16BIT)
-#define CCS_R_LINE_LENGTH_PCK (0x0342 | CCS_FL_16BIT)
-#define CCS_R_X_ADDR_START (0x0344 | CCS_FL_16BIT)
-#define CCS_R_Y_ADDR_START (0x0346 | CCS_FL_16BIT)
-#define CCS_R_X_ADDR_END (0x0348 | CCS_FL_16BIT)
-#define CCS_R_Y_ADDR_END (0x034a | CCS_FL_16BIT)
-#define CCS_R_X_OUTPUT_SIZE (0x034c | CCS_FL_16BIT)
-#define CCS_R_Y_OUTPUT_SIZE (0x034e | CCS_FL_16BIT)
-#define CCS_R_FRAME_LENGTH_CTRL 0x0350
+#define CCS_R_OP_PIX_CLK_DIV_REV CCI_REG16(0x0312)
+#define CCS_R_OP_SYS_CLK_DIV_REV CCI_REG16(0x0314)
+#define CCS_R_FRAME_LENGTH_LINES CCI_REG16(0x0340)
+#define CCS_R_LINE_LENGTH_PCK CCI_REG16(0x0342)
+#define CCS_R_X_ADDR_START CCI_REG16(0x0344)
+#define CCS_R_Y_ADDR_START CCI_REG16(0x0346)
+#define CCS_R_X_ADDR_END CCI_REG16(0x0348)
+#define CCS_R_Y_ADDR_END CCI_REG16(0x034a)
+#define CCS_R_X_OUTPUT_SIZE CCI_REG16(0x034c)
+#define CCS_R_Y_OUTPUT_SIZE CCI_REG16(0x034e)
+#define CCS_R_FRAME_LENGTH_CTRL CCI_REG8(0x0350)
#define CCS_FRAME_LENGTH_CTRL_AUTOMATIC BIT(0)
-#define CCS_R_TIMING_MODE_CTRL 0x0352
+#define CCS_R_TIMING_MODE_CTRL CCI_REG8(0x0352)
#define CCS_TIMING_MODE_CTRL_MANUAL_READOUT BIT(0)
#define CCS_TIMING_MODE_CTRL_DELAYED_EXPOSURE BIT(1)
-#define CCS_R_START_READOUT_RS 0x0353
+#define CCS_R_START_READOUT_RS CCI_REG8(0x0353)
#define CCS_START_READOUT_RS_MANUAL_READOUT_START BIT(0)
-#define CCS_R_FRAME_MARGIN (0x0354 | CCS_FL_16BIT)
-#define CCS_R_X_EVEN_INC (0x0380 | CCS_FL_16BIT)
-#define CCS_R_X_ODD_INC (0x0382 | CCS_FL_16BIT)
-#define CCS_R_Y_EVEN_INC (0x0384 | CCS_FL_16BIT)
-#define CCS_R_Y_ODD_INC (0x0386 | CCS_FL_16BIT)
-#define CCS_R_MONOCHROME_EN 0x0390
+#define CCS_R_FRAME_MARGIN CCI_REG16(0x0354)
+#define CCS_R_X_EVEN_INC CCI_REG16(0x0380)
+#define CCS_R_X_ODD_INC CCI_REG16(0x0382)
+#define CCS_R_Y_EVEN_INC CCI_REG16(0x0384)
+#define CCS_R_Y_ODD_INC CCI_REG16(0x0386)
+#define CCS_R_MONOCHROME_EN CCI_REG8(0x0390)
#define CCS_MONOCHROME_EN_ENABLED 0U
-#define CCS_R_SCALING_MODE (0x0400 | CCS_FL_16BIT)
+#define CCS_R_SCALING_MODE CCI_REG16(0x0400)
#define CCS_SCALING_MODE_NO_SCALING 0U
#define CCS_SCALING_MODE_HORIZONTAL 1U
-#define CCS_R_SCALE_M (0x0404 | CCS_FL_16BIT)
-#define CCS_R_SCALE_N (0x0406 | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_CROP_X_OFFSET (0x0408 | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_CROP_Y_OFFSET (0x040a | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_CROP_IMAGE_WIDTH (0x040c | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_CROP_IMAGE_HEIGHT (0x040e | CCS_FL_16BIT)
-#define CCS_R_COMPRESSION_MODE (0x0500 | CCS_FL_16BIT)
+#define CCS_R_SCALE_M CCI_REG16(0x0404)
+#define CCS_R_SCALE_N CCI_REG16(0x0406)
+#define CCS_R_DIGITAL_CROP_X_OFFSET CCI_REG16(0x0408)
+#define CCS_R_DIGITAL_CROP_Y_OFFSET CCI_REG16(0x040a)
+#define CCS_R_DIGITAL_CROP_IMAGE_WIDTH CCI_REG16(0x040c)
+#define CCS_R_DIGITAL_CROP_IMAGE_HEIGHT CCI_REG16(0x040e)
+#define CCS_R_COMPRESSION_MODE CCI_REG16(0x0500)
#define CCS_COMPRESSION_MODE_NONE 0U
#define CCS_COMPRESSION_MODE_DPCM_PCM_SIMPLE 1U
-#define CCS_R_TEST_PATTERN_MODE (0x0600 | CCS_FL_16BIT)
+#define CCS_R_TEST_PATTERN_MODE CCI_REG16(0x0600)
#define CCS_TEST_PATTERN_MODE_NONE 0U
#define CCS_TEST_PATTERN_MODE_SOLID_COLOR 1U
#define CCS_TEST_PATTERN_MODE_COLOR_BARS 2U
#define CCS_TEST_PATTERN_MODE_FADE_TO_GREY 3U
#define CCS_TEST_PATTERN_MODE_PN9 4U
#define CCS_TEST_PATTERN_MODE_COLOR_TILE 5U
-#define CCS_R_TEST_DATA_RED (0x0602 | CCS_FL_16BIT)
-#define CCS_R_TEST_DATA_GREENR (0x0604 | CCS_FL_16BIT)
-#define CCS_R_TEST_DATA_BLUE (0x0606 | CCS_FL_16BIT)
-#define CCS_R_TEST_DATA_GREENB (0x0608 | CCS_FL_16BIT)
-#define CCS_R_VALUE_STEP_SIZE_SMOOTH 0x060a
-#define CCS_R_VALUE_STEP_SIZE_QUANTISED 0x060b
-#define CCS_R_TCLK_POST 0x0800
-#define CCS_R_THS_PREPARE 0x0801
-#define CCS_R_THS_ZERO_MIN 0x0802
-#define CCS_R_THS_TRAIL 0x0803
-#define CCS_R_TCLK_TRAIL_MIN 0x0804
-#define CCS_R_TCLK_PREPARE 0x0805
-#define CCS_R_TCLK_ZERO 0x0806
-#define CCS_R_TLPX 0x0807
-#define CCS_R_PHY_CTRL 0x0808
+#define CCS_R_TEST_DATA_RED CCI_REG16(0x0602)
+#define CCS_R_TEST_DATA_GREENR CCI_REG16(0x0604)
+#define CCS_R_TEST_DATA_BLUE CCI_REG16(0x0606)
+#define CCS_R_TEST_DATA_GREENB CCI_REG16(0x0608)
+#define CCS_R_VALUE_STEP_SIZE_SMOOTH CCI_REG8(0x060a)
+#define CCS_R_VALUE_STEP_SIZE_QUANTISED CCI_REG8(0x060b)
+#define CCS_R_TCLK_POST CCI_REG8(0x0800)
+#define CCS_R_THS_PREPARE CCI_REG8(0x0801)
+#define CCS_R_THS_ZERO_MIN CCI_REG8(0x0802)
+#define CCS_R_THS_TRAIL CCI_REG8(0x0803)
+#define CCS_R_TCLK_TRAIL_MIN CCI_REG8(0x0804)
+#define CCS_R_TCLK_PREPARE CCI_REG8(0x0805)
+#define CCS_R_TCLK_ZERO CCI_REG8(0x0806)
+#define CCS_R_TLPX CCI_REG8(0x0807)
+#define CCS_R_PHY_CTRL CCI_REG8(0x0808)
#define CCS_PHY_CTRL_AUTO 0U
#define CCS_PHY_CTRL_UI 1U
#define CCS_PHY_CTRL_MANUAL 2U
-#define CCS_R_TCLK_POST_EX (0x080a | CCS_FL_16BIT)
-#define CCS_R_THS_PREPARE_EX (0x080c | CCS_FL_16BIT)
-#define CCS_R_THS_ZERO_MIN_EX (0x080e | CCS_FL_16BIT)
-#define CCS_R_THS_TRAIL_EX (0x0810 | CCS_FL_16BIT)
-#define CCS_R_TCLK_TRAIL_MIN_EX (0x0812 | CCS_FL_16BIT)
-#define CCS_R_TCLK_PREPARE_EX (0x0814 | CCS_FL_16BIT)
-#define CCS_R_TCLK_ZERO_EX (0x0816 | CCS_FL_16BIT)
-#define CCS_R_TLPX_EX (0x0818 | CCS_FL_16BIT)
-#define CCS_R_REQUESTED_LINK_RATE (0x0820 | CCS_FL_32BIT)
-#define CCS_R_DPHY_EQUALIZATION_MODE 0x0824
+#define CCS_R_TCLK_POST_EX CCI_REG16(0x080a)
+#define CCS_R_THS_PREPARE_EX CCI_REG16(0x080c)
+#define CCS_R_THS_ZERO_MIN_EX CCI_REG16(0x080e)
+#define CCS_R_THS_TRAIL_EX CCI_REG16(0x0810)
+#define CCS_R_TCLK_TRAIL_MIN_EX CCI_REG16(0x0812)
+#define CCS_R_TCLK_PREPARE_EX CCI_REG16(0x0814)
+#define CCS_R_TCLK_ZERO_EX CCI_REG16(0x0816)
+#define CCS_R_TLPX_EX CCI_REG16(0x0818)
+#define CCS_R_REQUESTED_LINK_RATE CCI_REG32(0x0820)
+#define CCS_R_DPHY_EQUALIZATION_MODE CCI_REG8(0x0824)
#define CCS_DPHY_EQUALIZATION_MODE_EQ2 BIT(0)
-#define CCS_R_PHY_EQUALIZATION_CTRL 0x0825
+#define CCS_R_PHY_EQUALIZATION_CTRL CCI_REG8(0x0825)
#define CCS_PHY_EQUALIZATION_CTRL_ENABLE BIT(0)
-#define CCS_R_DPHY_PREAMBLE_CTRL 0x0826
+#define CCS_R_DPHY_PREAMBLE_CTRL CCI_REG8(0x0826)
#define CCS_DPHY_PREAMBLE_CTRL_ENABLE BIT(0)
-#define CCS_R_DPHY_PREAMBLE_LENGTH 0x0826
-#define CCS_R_PHY_SSC_CTRL 0x0828
+#define CCS_R_DPHY_PREAMBLE_LENGTH CCI_REG8(0x0826)
+#define CCS_R_PHY_SSC_CTRL CCI_REG8(0x0828)
#define CCS_PHY_SSC_CTRL_ENABLE BIT(0)
-#define CCS_R_MANUAL_LP_CTRL 0x0829
+#define CCS_R_MANUAL_LP_CTRL CCI_REG8(0x0829)
#define CCS_MANUAL_LP_CTRL_ENABLE BIT(0)
-#define CCS_R_TWAKEUP 0x082a
-#define CCS_R_TINIT 0x082b
-#define CCS_R_THS_EXIT 0x082c
-#define CCS_R_THS_EXIT_EX (0x082e | CCS_FL_16BIT)
-#define CCS_R_PHY_PERIODIC_CALIBRATION_CTRL 0x0830
+#define CCS_R_TWAKEUP CCI_REG8(0x082a)
+#define CCS_R_TINIT CCI_REG8(0x082b)
+#define CCS_R_THS_EXIT CCI_REG8(0x082c)
+#define CCS_R_THS_EXIT_EX CCI_REG16(0x082e)
+#define CCS_R_PHY_PERIODIC_CALIBRATION_CTRL CCI_REG8(0x0830)
#define CCS_PHY_PERIODIC_CALIBRATION_CTRL_FRAME_BLANKING BIT(0)
-#define CCS_R_PHY_PERIODIC_CALIBRATION_INTERVAL 0x0831
-#define CCS_R_PHY_INIT_CALIBRATION_CTRL 0x0832
+#define CCS_R_PHY_PERIODIC_CALIBRATION_INTERVAL CCI_REG8(0x0831)
+#define CCS_R_PHY_INIT_CALIBRATION_CTRL CCI_REG8(0x0832)
#define CCS_PHY_INIT_CALIBRATION_CTRL_STREAM_START BIT(0)
-#define CCS_R_DPHY_CALIBRATION_MODE 0x0833
+#define CCS_R_DPHY_CALIBRATION_MODE CCI_REG8(0x0833)
#define CCS_DPHY_CALIBRATION_MODE_ALSO_ALTERNATE BIT(0)
-#define CCS_R_CPHY_CALIBRATION_MODE 0x0834
+#define CCS_R_CPHY_CALIBRATION_MODE CCI_REG8(0x0834)
#define CCS_CPHY_CALIBRATION_MODE_FORMAT_1 0U
#define CCS_CPHY_CALIBRATION_MODE_FORMAT_2 1U
#define CCS_CPHY_CALIBRATION_MODE_FORMAT_3 2U
-#define CCS_R_T3_CALPREAMBLE_LENGTH 0x0835
-#define CCS_R_T3_CALPREAMBLE_LENGTH_PER 0x0836
-#define CCS_R_T3_CALALTSEQ_LENGTH 0x0837
-#define CCS_R_T3_CALALTSEQ_LENGTH_PER 0x0838
-#define CCS_R_FM2_INIT_SEED (0x083a | CCS_FL_16BIT)
-#define CCS_R_T3_CALUDEFSEQ_LENGTH (0x083c | CCS_FL_16BIT)
-#define CCS_R_T3_CALUDEFSEQ_LENGTH_PER (0x083e | CCS_FL_16BIT)
-#define CCS_R_TGR_PREAMBLE_LENGTH 0x0841
+#define CCS_R_T3_CALPREAMBLE_LENGTH CCI_REG8(0x0835)
+#define CCS_R_T3_CALPREAMBLE_LENGTH_PER CCI_REG8(0x0836)
+#define CCS_R_T3_CALALTSEQ_LENGTH CCI_REG8(0x0837)
+#define CCS_R_T3_CALALTSEQ_LENGTH_PER CCI_REG8(0x0838)
+#define CCS_R_FM2_INIT_SEED CCI_REG16(0x083a)
+#define CCS_R_T3_CALUDEFSEQ_LENGTH CCI_REG16(0x083c)
+#define CCS_R_T3_CALUDEFSEQ_LENGTH_PER CCI_REG16(0x083e)
+#define CCS_R_TGR_PREAMBLE_LENGTH CCI_REG8(0x0841)
#define CCS_TGR_PREAMBLE_LENGTH_PREAMABLE_PROG_SEQ BIT(7)
#define CCS_TGR_PREAMBLE_LENGTH_BEGIN_PREAMBLE_LENGTH_SHIFT 0U
#define CCS_TGR_PREAMBLE_LENGTH_BEGIN_PREAMBLE_LENGTH_MASK 0x3f
-#define CCS_R_TGR_POST_LENGTH 0x0842
+#define CCS_R_TGR_POST_LENGTH CCI_REG8(0x0842)
#define CCS_TGR_POST_LENGTH_POST_LENGTH_SHIFT 0U
#define CCS_TGR_POST_LENGTH_POST_LENGTH_MASK 0x1f
-#define CCS_R_TGR_PREAMBLE_PROG_SEQUENCE(n2) (0x0843 + (n2))
+#define CCS_R_TGR_PREAMBLE_PROG_SEQUENCE(n2) CCI_REG8(0x0843 + (n2))
#define CCS_LIM_TGR_PREAMBLE_PROG_SEQUENCE_MIN_N2 0U
#define CCS_LIM_TGR_PREAMBLE_PROG_SEQUENCE_MAX_N2 6U
#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_1_SHIFT 3U
#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_1_MASK 0x38
#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_SHIFT 0U
#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_MASK 0x7
-#define CCS_R_T3_PREPARE (0x084e | CCS_FL_16BIT)
-#define CCS_R_T3_LPX (0x0850 | CCS_FL_16BIT)
-#define CCS_R_ALPS_CTRL 0x085a
+#define CCS_R_T3_PREPARE CCI_REG16(0x084e)
+#define CCS_R_T3_LPX CCI_REG16(0x0850)
+#define CCS_R_ALPS_CTRL CCI_REG8(0x085a)
#define CCS_ALPS_CTRL_LVLP_DPHY BIT(0)
#define CCS_ALPS_CTRL_LVLP_CPHY BIT(1)
#define CCS_ALPS_CTRL_ALP_CPHY BIT(2)
-#define CCS_R_TX_REG_CSI_EPD_EN_SSP_CPHY (0x0860 | CCS_FL_16BIT)
-#define CCS_R_TX_REG_CSI_EPD_OP_SLP_CPHY (0x0862 | CCS_FL_16BIT)
-#define CCS_R_TX_REG_CSI_EPD_EN_SSP_DPHY (0x0864 | CCS_FL_16BIT)
-#define CCS_R_TX_REG_CSI_EPD_OP_SLP_DPHY (0x0866 | CCS_FL_16BIT)
-#define CCS_R_TX_REG_CSI_EPD_MISC_OPTION_CPHY 0x0868
-#define CCS_R_TX_REG_CSI_EPD_MISC_OPTION_DPHY 0x0869
-#define CCS_R_SCRAMBLING_CTRL 0x0870
+#define CCS_R_TX_REG_CSI_EPD_EN_SSP_CPHY CCI_REG16(0x0860)
+#define CCS_R_TX_REG_CSI_EPD_OP_SLP_CPHY CCI_REG16(0x0862)
+#define CCS_R_TX_REG_CSI_EPD_EN_SSP_DPHY CCI_REG16(0x0864)
+#define CCS_R_TX_REG_CSI_EPD_OP_SLP_DPHY CCI_REG16(0x0866)
+#define CCS_R_TX_REG_CSI_EPD_MISC_OPTION_CPHY CCI_REG8(0x0868)
+#define CCS_R_TX_REG_CSI_EPD_MISC_OPTION_DPHY CCI_REG8(0x0869)
+#define CCS_R_SCRAMBLING_CTRL CCI_REG8(0x0870)
#define CCS_SCRAMBLING_CTRL_ENABLED BIT(0)
#define CCS_SCRAMBLING_CTRL_SHIFT 2U
#define CCS_SCRAMBLING_CTRL_MASK 0xc
#define CCS_SCRAMBLING_CTRL_1_SEED_CPHY 0U
#define CCS_SCRAMBLING_CTRL_4_SEED_CPHY 3U
-#define CCS_R_LANE_SEED_VALUE(seed, lane) ((0x0872 | CCS_FL_16BIT) + (seed) * 16 + (lane) * 2)
+#define CCS_R_LANE_SEED_VALUE(seed, lane) CCI_REG16(0x0872 + (seed) * 16 + (lane) * 2)
#define CCS_LIM_LANE_SEED_VALUE_MIN_SEED 0U
#define CCS_LIM_LANE_SEED_VALUE_MAX_SEED 3U
#define CCS_LIM_LANE_SEED_VALUE_MIN_LANE 0U
#define CCS_LIM_LANE_SEED_VALUE_MAX_LANE 7U
-#define CCS_R_TX_USL_REV_ENTRY (0x08c0 | CCS_FL_16BIT)
-#define CCS_R_TX_USL_REV_CLOCK_COUNTER (0x08c2 | CCS_FL_16BIT)
-#define CCS_R_TX_USL_REV_LP_COUNTER (0x08c4 | CCS_FL_16BIT)
-#define CCS_R_TX_USL_REV_FRAME_COUNTER (0x08c6 | CCS_FL_16BIT)
-#define CCS_R_TX_USL_REV_CHRONOLOGICAL_TIMER (0x08c8 | CCS_FL_16BIT)
-#define CCS_R_TX_USL_FWD_ENTRY (0x08ca | CCS_FL_16BIT)
-#define CCS_R_TX_USL_GPIO (0x08cc | CCS_FL_16BIT)
-#define CCS_R_TX_USL_OPERATION (0x08ce | CCS_FL_16BIT)
+#define CCS_R_TX_USL_REV_ENTRY CCI_REG16(0x08c0)
+#define CCS_R_TX_USL_REV_CLOCK_COUNTER CCI_REG16(0x08c2)
+#define CCS_R_TX_USL_REV_LP_COUNTER CCI_REG16(0x08c4)
+#define CCS_R_TX_USL_REV_FRAME_COUNTER CCI_REG16(0x08c6)
+#define CCS_R_TX_USL_REV_CHRONOLOGICAL_TIMER CCI_REG16(0x08c8)
+#define CCS_R_TX_USL_FWD_ENTRY CCI_REG16(0x08ca)
+#define CCS_R_TX_USL_GPIO CCI_REG16(0x08cc)
+#define CCS_R_TX_USL_OPERATION CCI_REG16(0x08ce)
#define CCS_TX_USL_OPERATION_RESET BIT(0)
-#define CCS_R_TX_USL_ALP_CTRL (0x08d0 | CCS_FL_16BIT)
+#define CCS_R_TX_USL_ALP_CTRL CCI_REG16(0x08d0)
#define CCS_TX_USL_ALP_CTRL_CLOCK_PAUSE BIT(0)
-#define CCS_R_TX_USL_APP_BTA_ACK_TIMEOUT (0x08d2 | CCS_FL_16BIT)
-#define CCS_R_TX_USL_SNS_BTA_ACK_TIMEOUT (0x08d2 | CCS_FL_16BIT)
-#define CCS_R_USL_CLOCK_MODE_D_CTRL 0x08d2
+#define CCS_R_TX_USL_APP_BTA_ACK_TIMEOUT CCI_REG16(0x08d2)
+#define CCS_R_TX_USL_SNS_BTA_ACK_TIMEOUT CCI_REG16(0x08d2)
+#define CCS_R_USL_CLOCK_MODE_D_CTRL CCI_REG8(0x08d2)
#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_STANDBY BIT(0)
#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_VBLANK BIT(1)
#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_HBLANK BIT(2)
-#define CCS_R_BINNING_MODE 0x0900
-#define CCS_R_BINNING_TYPE 0x0901
-#define CCS_R_BINNING_WEIGHTING 0x0902
-#define CCS_R_DATA_TRANSFER_IF_1_CTRL 0x0a00
+#define CCS_R_BINNING_MODE CCI_REG8(0x0900)
+#define CCS_R_BINNING_TYPE CCI_REG8(0x0901)
+#define CCS_R_BINNING_WEIGHTING CCI_REG8(0x0902)
+#define CCS_R_DATA_TRANSFER_IF_1_CTRL CCI_REG8(0x0a00)
#define CCS_DATA_TRANSFER_IF_1_CTRL_ENABLE BIT(0)
#define CCS_DATA_TRANSFER_IF_1_CTRL_WRITE BIT(1)
#define CCS_DATA_TRANSFER_IF_1_CTRL_CLEAR_ERROR BIT(2)
-#define CCS_R_DATA_TRANSFER_IF_1_STATUS 0x0a01
+#define CCS_R_DATA_TRANSFER_IF_1_STATUS CCI_REG8(0x0a01)
#define CCS_DATA_TRANSFER_IF_1_STATUS_READ_IF_READY BIT(0)
#define CCS_DATA_TRANSFER_IF_1_STATUS_WRITE_IF_READY BIT(1)
#define CCS_DATA_TRANSFER_IF_1_STATUS_DATA_CORRUPTED BIT(2)
#define CCS_DATA_TRANSFER_IF_1_STATUS_IMPROPER_IF_USAGE BIT(3)
-#define CCS_R_DATA_TRANSFER_IF_1_PAGE_SELECT 0x0a02
-#define CCS_R_DATA_TRANSFER_IF_1_DATA(p) (0x0a04 + (p))
+#define CCS_R_DATA_TRANSFER_IF_1_PAGE_SELECT CCI_REG8(0x0a02)
+#define CCS_R_DATA_TRANSFER_IF_1_DATA(p) CCI_REG8(0x0a04 + (p))
#define CCS_LIM_DATA_TRANSFER_IF_1_DATA_MIN_P 0U
#define CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P 63U
-#define CCS_R_SHADING_CORRECTION_EN 0x0b00
+#define CCS_R_SHADING_CORRECTION_EN CCI_REG8(0x0b00)
#define CCS_SHADING_CORRECTION_EN_ENABLE BIT(0)
-#define CCS_R_LUMINANCE_CORRECTION_LEVEL 0x0b01
-#define CCS_R_GREEN_IMBALANCE_FILTER_EN 0x0b02
+#define CCS_R_LUMINANCE_CORRECTION_LEVEL CCI_REG8(0x0b01)
+#define CCS_R_GREEN_IMBALANCE_FILTER_EN CCI_REG8(0x0b02)
#define CCS_GREEN_IMBALANCE_FILTER_EN_ENABLE BIT(0)
-#define CCS_R_MAPPED_DEFECT_CORRECT_EN 0x0b05
+#define CCS_R_MAPPED_DEFECT_CORRECT_EN CCI_REG8(0x0b05)
#define CCS_MAPPED_DEFECT_CORRECT_EN_ENABLE BIT(0)
-#define CCS_R_SINGLE_DEFECT_CORRECT_EN 0x0b06
+#define CCS_R_SINGLE_DEFECT_CORRECT_EN CCI_REG8(0x0b06)
#define CCS_SINGLE_DEFECT_CORRECT_EN_ENABLE BIT(0)
-#define CCS_R_DYNAMIC_COUPLET_CORRECT_EN 0x0b08
+#define CCS_R_DYNAMIC_COUPLET_CORRECT_EN CCI_REG8(0x0b08)
#define CCS_DYNAMIC_COUPLET_CORRECT_EN_ENABLE BIT(0)
-#define CCS_R_COMBINED_DEFECT_CORRECT_EN 0x0b0a
+#define CCS_R_COMBINED_DEFECT_CORRECT_EN CCI_REG8(0x0b0a)
#define CCS_COMBINED_DEFECT_CORRECT_EN_ENABLE BIT(0)
-#define CCS_R_MODULE_SPECIFIC_CORRECTION_EN 0x0b0c
+#define CCS_R_MODULE_SPECIFIC_CORRECTION_EN CCI_REG8(0x0b0c)
#define CCS_MODULE_SPECIFIC_CORRECTION_EN_ENABLE BIT(0)
-#define CCS_R_DYNAMIC_TRIPLET_DEFECT_CORRECT_EN 0x0b13
+#define CCS_R_DYNAMIC_TRIPLET_DEFECT_CORRECT_EN CCI_REG8(0x0b13)
#define CCS_DYNAMIC_TRIPLET_DEFECT_CORRECT_EN_ENABLE BIT(0)
-#define CCS_R_NF_CTRL 0x0b15
+#define CCS_R_NF_CTRL CCI_REG8(0x0b15)
#define CCS_NF_CTRL_LUMA BIT(0)
#define CCS_NF_CTRL_CHROMA BIT(1)
#define CCS_NF_CTRL_COMBINED BIT(2)
-#define CCS_R_OB_READOUT_CONTROL 0x0b30
+#define CCS_R_OB_READOUT_CONTROL CCI_REG8(0x0b30)
#define CCS_OB_READOUT_CONTROL_ENABLE BIT(0)
#define CCS_OB_READOUT_CONTROL_INTERLEAVING BIT(1)
-#define CCS_R_OB_VIRTUAL_CHANNEL 0x0b31
-#define CCS_R_OB_DT 0x0b32
-#define CCS_R_OB_DATA_FORMAT 0x0b33
-#define CCS_R_COLOR_TEMPERATURE (0x0b8c | CCS_FL_16BIT)
-#define CCS_R_ABSOLUTE_GAIN_GREENR (0x0b8e | CCS_FL_16BIT)
-#define CCS_R_ABSOLUTE_GAIN_RED (0x0b90 | CCS_FL_16BIT)
-#define CCS_R_ABSOLUTE_GAIN_BLUE (0x0b92 | CCS_FL_16BIT)
-#define CCS_R_ABSOLUTE_GAIN_GREENB (0x0b94 | CCS_FL_16BIT)
-#define CCS_R_CFA_CONVERSION_CTRL 0x0ba0
+#define CCS_R_OB_VIRTUAL_CHANNEL CCI_REG8(0x0b31)
+#define CCS_R_OB_DT CCI_REG8(0x0b32)
+#define CCS_R_OB_DATA_FORMAT CCI_REG8(0x0b33)
+#define CCS_R_COLOR_TEMPERATURE CCI_REG16(0x0b8c)
+#define CCS_R_ABSOLUTE_GAIN_GREENR CCI_REG16(0x0b8e)
+#define CCS_R_ABSOLUTE_GAIN_RED CCI_REG16(0x0b90)
+#define CCS_R_ABSOLUTE_GAIN_BLUE CCI_REG16(0x0b92)
+#define CCS_R_ABSOLUTE_GAIN_GREENB CCI_REG16(0x0b94)
+#define CCS_R_CFA_CONVERSION_CTRL CCI_REG8(0x0ba0)
#define CCS_CFA_CONVERSION_CTRL_BAYER_CONVERSION_ENABLE BIT(0)
-#define CCS_R_FLASH_STROBE_ADJUSTMENT 0x0c12
-#define CCS_R_FLASH_STROBE_START_POINT (0x0c14 | CCS_FL_16BIT)
-#define CCS_R_TFLASH_STROBE_DELAY_RS_CTRL (0x0c16 | CCS_FL_16BIT)
-#define CCS_R_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL (0x0c18 | CCS_FL_16BIT)
-#define CCS_R_FLASH_MODE_RS 0x0c1a
+#define CCS_R_FLASH_STROBE_ADJUSTMENT CCI_REG8(0x0c12)
+#define CCS_R_FLASH_STROBE_START_POINT CCI_REG16(0x0c14)
+#define CCS_R_TFLASH_STROBE_DELAY_RS_CTRL CCI_REG16(0x0c16)
+#define CCS_R_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL CCI_REG16(0x0c18)
+#define CCS_R_FLASH_MODE_RS CCI_REG8(0x0c1a)
#define CCS_FLASH_MODE_RS_CONTINUOUS BIT(0)
#define CCS_FLASH_MODE_RS_TRUNCATE BIT(1)
#define CCS_FLASH_MODE_RS_ASYNC BIT(3)
-#define CCS_R_FLASH_TRIGGER_RS 0x0c1b
-#define CCS_R_FLASH_STATUS 0x0c1c
+#define CCS_R_FLASH_TRIGGER_RS CCI_REG8(0x0c1b)
+#define CCS_R_FLASH_STATUS CCI_REG8(0x0c1c)
#define CCS_FLASH_STATUS_RETIMED BIT(0)
-#define CCS_R_SA_STROBE_MODE 0x0c1d
+#define CCS_R_SA_STROBE_MODE CCI_REG8(0x0c1d)
#define CCS_SA_STROBE_MODE_CONTINUOUS BIT(0)
#define CCS_SA_STROBE_MODE_TRUNCATE BIT(1)
#define CCS_SA_STROBE_MODE_ASYNC BIT(3)
#define CCS_SA_STROBE_MODE_ADJUST_EDGE BIT(4)
-#define CCS_R_SA_STROBE_START_POINT (0x0c1e | CCS_FL_16BIT)
-#define CCS_R_TSA_STROBE_DELAY_CTRL (0x0c20 | CCS_FL_16BIT)
-#define CCS_R_TSA_STROBE_WIDTH_CTRL (0x0c22 | CCS_FL_16BIT)
-#define CCS_R_SA_STROBE_TRIGGER 0x0c24
-#define CCS_R_SA_STROBE_STATUS 0x0c25
+#define CCS_R_SA_STROBE_START_POINT CCI_REG16(0x0c1e)
+#define CCS_R_TSA_STROBE_DELAY_CTRL CCI_REG16(0x0c20)
+#define CCS_R_TSA_STROBE_WIDTH_CTRL CCI_REG16(0x0c22)
+#define CCS_R_SA_STROBE_TRIGGER CCI_REG8(0x0c24)
+#define CCS_R_SA_STROBE_STATUS CCI_REG8(0x0c25)
#define CCS_SA_STROBE_STATUS_RETIMED BIT(0)
-#define CCS_R_TSA_STROBE_RE_DELAY_CTRL (0x0c30 | CCS_FL_16BIT)
-#define CCS_R_TSA_STROBE_FE_DELAY_CTRL (0x0c32 | CCS_FL_16BIT)
-#define CCS_R_PDAF_CTRL (0x0d00 | CCS_FL_16BIT)
+#define CCS_R_TSA_STROBE_RE_DELAY_CTRL CCI_REG16(0x0c30)
+#define CCS_R_TSA_STROBE_FE_DELAY_CTRL CCI_REG16(0x0c32)
+#define CCS_R_PDAF_CTRL CCI_REG16(0x0d00)
#define CCS_PDAF_CTRL_ENABLE BIT(0)
#define CCS_PDAF_CTRL_PROCESSED BIT(1)
#define CCS_PDAF_CTRL_INTERLEAVED BIT(2)
#define CCS_PDAF_CTRL_VISIBLE_PDAF_CORRECTION BIT(3)
-#define CCS_R_PDAF_VC 0x0d02
-#define CCS_R_PDAF_DT 0x0d03
-#define CCS_R_PD_X_ADDR_START (0x0d04 | CCS_FL_16BIT)
-#define CCS_R_PD_Y_ADDR_START (0x0d06 | CCS_FL_16BIT)
-#define CCS_R_PD_X_ADDR_END (0x0d08 | CCS_FL_16BIT)
-#define CCS_R_PD_Y_ADDR_END (0x0d0a | CCS_FL_16BIT)
-#define CCS_R_BRACKETING_LUT_CTRL 0x0e00
-#define CCS_R_BRACKETING_LUT_MODE 0x0e01
+#define CCS_R_PDAF_VC CCI_REG8(0x0d02)
+#define CCS_R_PDAF_DT CCI_REG8(0x0d03)
+#define CCS_R_PD_X_ADDR_START CCI_REG16(0x0d04)
+#define CCS_R_PD_Y_ADDR_START CCI_REG16(0x0d06)
+#define CCS_R_PD_X_ADDR_END CCI_REG16(0x0d08)
+#define CCS_R_PD_Y_ADDR_END CCI_REG16(0x0d0a)
+#define CCS_R_BRACKETING_LUT_CTRL CCI_REG8(0x0e00)
+#define CCS_R_BRACKETING_LUT_MODE CCI_REG8(0x0e01)
#define CCS_BRACKETING_LUT_MODE_CONTINUE_STREAMING BIT(0)
#define CCS_BRACKETING_LUT_MODE_LOOP_MODE BIT(1)
-#define CCS_R_BRACKETING_LUT_ENTRY_CTRL 0x0e02
-#define CCS_R_BRACKETING_LUT_FRAME(n) (0x0e10 + (n))
+#define CCS_R_BRACKETING_LUT_ENTRY_CTRL CCI_REG8(0x0e02)
+#define CCS_R_BRACKETING_LUT_FRAME(n) CCI_REG8(0x0e10 + (n))
#define CCS_LIM_BRACKETING_LUT_FRAME_MIN_N 0U
#define CCS_LIM_BRACKETING_LUT_FRAME_MAX_N 239U
-#define CCS_R_INTEGRATION_TIME_CAPABILITY (0x1000 | CCS_FL_16BIT)
+#define CCS_R_INTEGRATION_TIME_CAPABILITY CCI_REG16(0x1000)
#define CCS_INTEGRATION_TIME_CAPABILITY_FINE BIT(0)
-#define CCS_R_COARSE_INTEGRATION_TIME_MIN (0x1004 | CCS_FL_16BIT)
-#define CCS_R_COARSE_INTEGRATION_TIME_MAX_MARGIN (0x1006 | CCS_FL_16BIT)
-#define CCS_R_FINE_INTEGRATION_TIME_MIN (0x1008 | CCS_FL_16BIT)
-#define CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN (0x100a | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_GAIN_CAPABILITY 0x1081
+#define CCS_R_COARSE_INTEGRATION_TIME_MIN CCI_REG16(0x1004)
+#define CCS_R_COARSE_INTEGRATION_TIME_MAX_MARGIN CCI_REG16(0x1006)
+#define CCS_R_FINE_INTEGRATION_TIME_MIN CCI_REG16(0x1008)
+#define CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN CCI_REG16(0x100a)
+#define CCS_R_DIGITAL_GAIN_CAPABILITY CCI_REG8(0x1081)
#define CCS_DIGITAL_GAIN_CAPABILITY_NONE 0U
#define CCS_DIGITAL_GAIN_CAPABILITY_GLOBAL 2U
-#define CCS_R_DIGITAL_GAIN_MIN (0x1084 | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_GAIN_MAX (0x1086 | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_GAIN_STEP_SIZE (0x1088 | CCS_FL_16BIT)
-#define CCS_R_PEDESTAL_CAPABILITY 0x10e0
-#define CCS_R_ADC_CAPABILITY 0x10f0
+#define CCS_R_DIGITAL_GAIN_MIN CCI_REG16(0x1084)
+#define CCS_R_DIGITAL_GAIN_MAX CCI_REG16(0x1086)
+#define CCS_R_DIGITAL_GAIN_STEP_SIZE CCI_REG16(0x1088)
+#define CCS_R_PEDESTAL_CAPABILITY CCI_REG8(0x10e0)
+#define CCS_R_ADC_CAPABILITY CCI_REG8(0x10f0)
#define CCS_ADC_CAPABILITY_BIT_DEPTH_CTRL BIT(0)
-#define CCS_R_ADC_BIT_DEPTH_CAPABILITY (0x10f4 | CCS_FL_32BIT)
-#define CCS_R_MIN_EXT_CLK_FREQ_MHZ (0x1100 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_EXT_CLK_FREQ_MHZ (0x1104 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MIN_PRE_PLL_CLK_DIV (0x1108 | CCS_FL_16BIT)
-#define CCS_R_MAX_PRE_PLL_CLK_DIV (0x110a | CCS_FL_16BIT)
-#define CCS_R_MIN_PLL_IP_CLK_FREQ_MHZ (0x110c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_PLL_IP_CLK_FREQ_MHZ (0x1110 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MIN_PLL_MULTIPLIER (0x1114 | CCS_FL_16BIT)
-#define CCS_R_MAX_PLL_MULTIPLIER (0x1116 | CCS_FL_16BIT)
-#define CCS_R_MIN_PLL_OP_CLK_FREQ_MHZ (0x1118 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_PLL_OP_CLK_FREQ_MHZ (0x111c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MIN_VT_SYS_CLK_DIV (0x1120 | CCS_FL_16BIT)
-#define CCS_R_MAX_VT_SYS_CLK_DIV (0x1122 | CCS_FL_16BIT)
-#define CCS_R_MIN_VT_SYS_CLK_FREQ_MHZ (0x1124 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_VT_SYS_CLK_FREQ_MHZ (0x1128 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MIN_VT_PIX_CLK_FREQ_MHZ (0x112c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_VT_PIX_CLK_FREQ_MHZ (0x1130 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MIN_VT_PIX_CLK_DIV (0x1134 | CCS_FL_16BIT)
-#define CCS_R_MAX_VT_PIX_CLK_DIV (0x1136 | CCS_FL_16BIT)
-#define CCS_R_CLOCK_CALCULATION 0x1138
+#define CCS_R_ADC_BIT_DEPTH_CAPABILITY CCI_REG32(0x10f4)
+#define CCS_R_MIN_EXT_CLK_FREQ_MHZ (CCI_REG32(0x1100) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_EXT_CLK_FREQ_MHZ (CCI_REG32(0x1104) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MIN_PRE_PLL_CLK_DIV CCI_REG16(0x1108)
+#define CCS_R_MAX_PRE_PLL_CLK_DIV CCI_REG16(0x110a)
+#define CCS_R_MIN_PLL_IP_CLK_FREQ_MHZ (CCI_REG32(0x110c) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_PLL_IP_CLK_FREQ_MHZ (CCI_REG32(0x1110) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MIN_PLL_MULTIPLIER CCI_REG16(0x1114)
+#define CCS_R_MAX_PLL_MULTIPLIER CCI_REG16(0x1116)
+#define CCS_R_MIN_PLL_OP_CLK_FREQ_MHZ (CCI_REG32(0x1118) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_PLL_OP_CLK_FREQ_MHZ (CCI_REG32(0x111c) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MIN_VT_SYS_CLK_DIV CCI_REG16(0x1120)
+#define CCS_R_MAX_VT_SYS_CLK_DIV CCI_REG16(0x1122)
+#define CCS_R_MIN_VT_SYS_CLK_FREQ_MHZ (CCI_REG32(0x1124) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_VT_SYS_CLK_FREQ_MHZ (CCI_REG32(0x1128) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MIN_VT_PIX_CLK_FREQ_MHZ (CCI_REG32(0x112c) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_VT_PIX_CLK_FREQ_MHZ (CCI_REG32(0x1130) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MIN_VT_PIX_CLK_DIV CCI_REG16(0x1134)
+#define CCS_R_MAX_VT_PIX_CLK_DIV CCI_REG16(0x1136)
+#define CCS_R_CLOCK_CALCULATION CCI_REG8(0x1138)
#define CCS_CLOCK_CALCULATION_LANE_SPEED BIT(0)
#define CCS_CLOCK_CALCULATION_LINK_DECOUPLED BIT(1)
#define CCS_CLOCK_CALCULATION_DUAL_PLL_OP_SYS_DDR BIT(2)
#define CCS_CLOCK_CALCULATION_DUAL_PLL_OP_PIX_DDR BIT(3)
-#define CCS_R_NUM_OF_VT_LANES 0x1139
-#define CCS_R_NUM_OF_OP_LANES 0x113a
-#define CCS_R_OP_BITS_PER_LANE 0x113b
-#define CCS_R_MIN_FRAME_LENGTH_LINES (0x1140 | CCS_FL_16BIT)
-#define CCS_R_MAX_FRAME_LENGTH_LINES (0x1142 | CCS_FL_16BIT)
-#define CCS_R_MIN_LINE_LENGTH_PCK (0x1144 | CCS_FL_16BIT)
-#define CCS_R_MAX_LINE_LENGTH_PCK (0x1146 | CCS_FL_16BIT)
-#define CCS_R_MIN_LINE_BLANKING_PCK (0x1148 | CCS_FL_16BIT)
-#define CCS_R_MIN_FRAME_BLANKING_LINES (0x114a | CCS_FL_16BIT)
-#define CCS_R_MIN_LINE_LENGTH_PCK_STEP_SIZE 0x114c
-#define CCS_R_TIMING_MODE_CAPABILITY 0x114d
+#define CCS_R_NUM_OF_VT_LANES CCI_REG8(0x1139)
+#define CCS_R_NUM_OF_OP_LANES CCI_REG8(0x113a)
+#define CCS_R_OP_BITS_PER_LANE CCI_REG8(0x113b)
+#define CCS_R_MIN_FRAME_LENGTH_LINES CCI_REG16(0x1140)
+#define CCS_R_MAX_FRAME_LENGTH_LINES CCI_REG16(0x1142)
+#define CCS_R_MIN_LINE_LENGTH_PCK CCI_REG16(0x1144)
+#define CCS_R_MAX_LINE_LENGTH_PCK CCI_REG16(0x1146)
+#define CCS_R_MIN_LINE_BLANKING_PCK CCI_REG16(0x1148)
+#define CCS_R_MIN_FRAME_BLANKING_LINES CCI_REG16(0x114a)
+#define CCS_R_MIN_LINE_LENGTH_PCK_STEP_SIZE CCI_REG8(0x114c)
+#define CCS_R_TIMING_MODE_CAPABILITY CCI_REG8(0x114d)
#define CCS_TIMING_MODE_CAPABILITY_AUTO_FRAME_LENGTH BIT(0)
#define CCS_TIMING_MODE_CAPABILITY_ROLLING_SHUTTER_MANUAL_READOUT BIT(2)
#define CCS_TIMING_MODE_CAPABILITY_DELAYED_EXPOSURE_START BIT(3)
#define CCS_TIMING_MODE_CAPABILITY_MANUAL_EXPOSURE_EMBEDDED_DATA BIT(4)
-#define CCS_R_FRAME_MARGIN_MAX_VALUE (0x114e | CCS_FL_16BIT)
-#define CCS_R_FRAME_MARGIN_MIN_VALUE 0x1150
-#define CCS_R_GAIN_DELAY_TYPE 0x1151
+#define CCS_R_FRAME_MARGIN_MAX_VALUE CCI_REG16(0x114e)
+#define CCS_R_FRAME_MARGIN_MIN_VALUE CCI_REG8(0x1150)
+#define CCS_R_GAIN_DELAY_TYPE CCI_REG8(0x1151)
#define CCS_GAIN_DELAY_TYPE_FIXED 0U
#define CCS_GAIN_DELAY_TYPE_VARIABLE 1U
-#define CCS_R_MIN_OP_SYS_CLK_DIV (0x1160 | CCS_FL_16BIT)
-#define CCS_R_MAX_OP_SYS_CLK_DIV (0x1162 | CCS_FL_16BIT)
-#define CCS_R_MIN_OP_SYS_CLK_FREQ_MHZ (0x1164 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_OP_SYS_CLK_FREQ_MHZ (0x1168 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MIN_OP_PIX_CLK_DIV (0x116c | CCS_FL_16BIT)
-#define CCS_R_MAX_OP_PIX_CLK_DIV (0x116e | CCS_FL_16BIT)
-#define CCS_R_MIN_OP_PIX_CLK_FREQ_MHZ (0x1170 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_OP_PIX_CLK_FREQ_MHZ (0x1174 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_X_ADDR_MIN (0x1180 | CCS_FL_16BIT)
-#define CCS_R_Y_ADDR_MIN (0x1182 | CCS_FL_16BIT)
-#define CCS_R_X_ADDR_MAX (0x1184 | CCS_FL_16BIT)
-#define CCS_R_Y_ADDR_MAX (0x1186 | CCS_FL_16BIT)
-#define CCS_R_MIN_X_OUTPUT_SIZE (0x1188 | CCS_FL_16BIT)
-#define CCS_R_MIN_Y_OUTPUT_SIZE (0x118a | CCS_FL_16BIT)
-#define CCS_R_MAX_X_OUTPUT_SIZE (0x118c | CCS_FL_16BIT)
-#define CCS_R_MAX_Y_OUTPUT_SIZE (0x118e | CCS_FL_16BIT)
-#define CCS_R_X_ADDR_START_DIV_CONSTANT 0x1190
-#define CCS_R_Y_ADDR_START_DIV_CONSTANT 0x1191
-#define CCS_R_X_ADDR_END_DIV_CONSTANT 0x1192
-#define CCS_R_Y_ADDR_END_DIV_CONSTANT 0x1193
-#define CCS_R_X_SIZE_DIV 0x1194
-#define CCS_R_Y_SIZE_DIV 0x1195
-#define CCS_R_X_OUTPUT_DIV 0x1196
-#define CCS_R_Y_OUTPUT_DIV 0x1197
-#define CCS_R_NON_FLEXIBLE_RESOLUTION_SUPPORT 0x1198
+#define CCS_R_MIN_OP_SYS_CLK_DIV CCI_REG16(0x1160)
+#define CCS_R_MAX_OP_SYS_CLK_DIV CCI_REG16(0x1162)
+#define CCS_R_MIN_OP_SYS_CLK_FREQ_MHZ (CCI_REG32(0x1164) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_OP_SYS_CLK_FREQ_MHZ (CCI_REG32(0x1168) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MIN_OP_PIX_CLK_DIV CCI_REG16(0x116c)
+#define CCS_R_MAX_OP_PIX_CLK_DIV CCI_REG16(0x116e)
+#define CCS_R_MIN_OP_PIX_CLK_FREQ_MHZ (CCI_REG32(0x1170) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_OP_PIX_CLK_FREQ_MHZ (CCI_REG32(0x1174) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_X_ADDR_MIN CCI_REG16(0x1180)
+#define CCS_R_Y_ADDR_MIN CCI_REG16(0x1182)
+#define CCS_R_X_ADDR_MAX CCI_REG16(0x1184)
+#define CCS_R_Y_ADDR_MAX CCI_REG16(0x1186)
+#define CCS_R_MIN_X_OUTPUT_SIZE CCI_REG16(0x1188)
+#define CCS_R_MIN_Y_OUTPUT_SIZE CCI_REG16(0x118a)
+#define CCS_R_MAX_X_OUTPUT_SIZE CCI_REG16(0x118c)
+#define CCS_R_MAX_Y_OUTPUT_SIZE CCI_REG16(0x118e)
+#define CCS_R_X_ADDR_START_DIV_CONSTANT CCI_REG8(0x1190)
+#define CCS_R_Y_ADDR_START_DIV_CONSTANT CCI_REG8(0x1191)
+#define CCS_R_X_ADDR_END_DIV_CONSTANT CCI_REG8(0x1192)
+#define CCS_R_Y_ADDR_END_DIV_CONSTANT CCI_REG8(0x1193)
+#define CCS_R_X_SIZE_DIV CCI_REG8(0x1194)
+#define CCS_R_Y_SIZE_DIV CCI_REG8(0x1195)
+#define CCS_R_X_OUTPUT_DIV CCI_REG8(0x1196)
+#define CCS_R_Y_OUTPUT_DIV CCI_REG8(0x1197)
+#define CCS_R_NON_FLEXIBLE_RESOLUTION_SUPPORT CCI_REG8(0x1198)
#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_NEW_PIX_ADDR BIT(0)
#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_NEW_OUTPUT_RES BIT(1)
#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_OUTPUT_CROP_NO_PAD BIT(2)
#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_OUTPUT_SIZE_LANE_DEP BIT(3)
-#define CCS_R_MIN_OP_PRE_PLL_CLK_DIV (0x11a0 | CCS_FL_16BIT)
-#define CCS_R_MAX_OP_PRE_PLL_CLK_DIV (0x11a2 | CCS_FL_16BIT)
-#define CCS_R_MIN_OP_PLL_IP_CLK_FREQ_MHZ (0x11a4 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_OP_PLL_IP_CLK_FREQ_MHZ (0x11a8 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MIN_OP_PLL_MULTIPLIER (0x11ac | CCS_FL_16BIT)
-#define CCS_R_MAX_OP_PLL_MULTIPLIER (0x11ae | CCS_FL_16BIT)
-#define CCS_R_MIN_OP_PLL_OP_CLK_FREQ_MHZ (0x11b0 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_OP_PLL_OP_CLK_FREQ_MHZ (0x11b4 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_CLOCK_TREE_PLL_CAPABILITY 0x11b8
+#define CCS_R_MIN_OP_PRE_PLL_CLK_DIV CCI_REG16(0x11a0)
+#define CCS_R_MAX_OP_PRE_PLL_CLK_DIV CCI_REG16(0x11a2)
+#define CCS_R_MIN_OP_PLL_IP_CLK_FREQ_MHZ (CCI_REG32(0x11a4) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_OP_PLL_IP_CLK_FREQ_MHZ (CCI_REG32(0x11a8) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MIN_OP_PLL_MULTIPLIER CCI_REG16(0x11ac)
+#define CCS_R_MAX_OP_PLL_MULTIPLIER CCI_REG16(0x11ae)
+#define CCS_R_MIN_OP_PLL_OP_CLK_FREQ_MHZ (CCI_REG32(0x11b0) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_OP_PLL_OP_CLK_FREQ_MHZ (CCI_REG32(0x11b4) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_CLOCK_TREE_PLL_CAPABILITY CCI_REG8(0x11b8)
#define CCS_CLOCK_TREE_PLL_CAPABILITY_DUAL_PLL BIT(0)
#define CCS_CLOCK_TREE_PLL_CAPABILITY_SINGLE_PLL BIT(1)
#define CCS_CLOCK_TREE_PLL_CAPABILITY_EXT_DIVIDER BIT(2)
#define CCS_CLOCK_TREE_PLL_CAPABILITY_FLEXIBLE_OP_PIX_CLK_DIV BIT(3)
-#define CCS_R_CLOCK_CAPA_TYPE_CAPABILITY 0x11b9
+#define CCS_R_CLOCK_CAPA_TYPE_CAPABILITY CCI_REG8(0x11b9)
#define CCS_CLOCK_CAPA_TYPE_CAPABILITY_IREAL BIT(0)
-#define CCS_R_MIN_EVEN_INC (0x11c0 | CCS_FL_16BIT)
-#define CCS_R_MIN_ODD_INC (0x11c2 | CCS_FL_16BIT)
-#define CCS_R_MAX_EVEN_INC (0x11c4 | CCS_FL_16BIT)
-#define CCS_R_MAX_ODD_INC (0x11c6 | CCS_FL_16BIT)
-#define CCS_R_AUX_SUBSAMP_CAPABILITY 0x11c8
+#define CCS_R_MIN_EVEN_INC CCI_REG16(0x11c0)
+#define CCS_R_MIN_ODD_INC CCI_REG16(0x11c2)
+#define CCS_R_MAX_EVEN_INC CCI_REG16(0x11c4)
+#define CCS_R_MAX_ODD_INC CCI_REG16(0x11c6)
+#define CCS_R_AUX_SUBSAMP_CAPABILITY CCI_REG8(0x11c8)
#define CCS_AUX_SUBSAMP_CAPABILITY_FACTOR_POWER_OF_2 BIT(1)
-#define CCS_R_AUX_SUBSAMP_MONO_CAPABILITY 0x11c9
+#define CCS_R_AUX_SUBSAMP_MONO_CAPABILITY CCI_REG8(0x11c9)
#define CCS_AUX_SUBSAMP_MONO_CAPABILITY_FACTOR_POWER_OF_2 BIT(1)
-#define CCS_R_MONOCHROME_CAPABILITY 0x11ca
+#define CCS_R_MONOCHROME_CAPABILITY CCI_REG8(0x11ca)
#define CCS_MONOCHROME_CAPABILITY_INC_ODD 0U
#define CCS_MONOCHROME_CAPABILITY_INC_EVEN 1U
-#define CCS_R_PIXEL_READOUT_CAPABILITY 0x11cb
+#define CCS_R_PIXEL_READOUT_CAPABILITY CCI_REG8(0x11cb)
#define CCS_PIXEL_READOUT_CAPABILITY_BAYER 0U
#define CCS_PIXEL_READOUT_CAPABILITY_MONOCHROME 1U
#define CCS_PIXEL_READOUT_CAPABILITY_BAYER_AND_MONO 2U
-#define CCS_R_MIN_EVEN_INC_MONO (0x11cc | CCS_FL_16BIT)
-#define CCS_R_MAX_EVEN_INC_MONO (0x11ce | CCS_FL_16BIT)
-#define CCS_R_MIN_ODD_INC_MONO (0x11d0 | CCS_FL_16BIT)
-#define CCS_R_MAX_ODD_INC_MONO (0x11d2 | CCS_FL_16BIT)
-#define CCS_R_MIN_EVEN_INC_BC2 (0x11d4 | CCS_FL_16BIT)
-#define CCS_R_MAX_EVEN_INC_BC2 (0x11d6 | CCS_FL_16BIT)
-#define CCS_R_MIN_ODD_INC_BC2 (0x11d8 | CCS_FL_16BIT)
-#define CCS_R_MAX_ODD_INC_BC2 (0x11da | CCS_FL_16BIT)
-#define CCS_R_MIN_EVEN_INC_MONO_BC2 (0x11dc | CCS_FL_16BIT)
-#define CCS_R_MAX_EVEN_INC_MONO_BC2 (0x11de | CCS_FL_16BIT)
-#define CCS_R_MIN_ODD_INC_MONO_BC2 (0x11f0 | CCS_FL_16BIT)
-#define CCS_R_MAX_ODD_INC_MONO_BC2 (0x11f2 | CCS_FL_16BIT)
-#define CCS_R_SCALING_CAPABILITY (0x1200 | CCS_FL_16BIT)
+#define CCS_R_MIN_EVEN_INC_MONO CCI_REG16(0x11cc)
+#define CCS_R_MAX_EVEN_INC_MONO CCI_REG16(0x11ce)
+#define CCS_R_MIN_ODD_INC_MONO CCI_REG16(0x11d0)
+#define CCS_R_MAX_ODD_INC_MONO CCI_REG16(0x11d2)
+#define CCS_R_MIN_EVEN_INC_BC2 CCI_REG16(0x11d4)
+#define CCS_R_MAX_EVEN_INC_BC2 CCI_REG16(0x11d6)
+#define CCS_R_MIN_ODD_INC_BC2 CCI_REG16(0x11d8)
+#define CCS_R_MAX_ODD_INC_BC2 CCI_REG16(0x11da)
+#define CCS_R_MIN_EVEN_INC_MONO_BC2 CCI_REG16(0x11dc)
+#define CCS_R_MAX_EVEN_INC_MONO_BC2 CCI_REG16(0x11de)
+#define CCS_R_MIN_ODD_INC_MONO_BC2 CCI_REG16(0x11f0)
+#define CCS_R_MAX_ODD_INC_MONO_BC2 CCI_REG16(0x11f2)
+#define CCS_R_SCALING_CAPABILITY CCI_REG16(0x1200)
#define CCS_SCALING_CAPABILITY_NONE 0U
#define CCS_SCALING_CAPABILITY_HORIZONTAL 1U
#define CCS_SCALING_CAPABILITY_RESERVED 2U
-#define CCS_R_SCALER_M_MIN (0x1204 | CCS_FL_16BIT)
-#define CCS_R_SCALER_M_MAX (0x1206 | CCS_FL_16BIT)
-#define CCS_R_SCALER_N_MIN (0x1208 | CCS_FL_16BIT)
-#define CCS_R_SCALER_N_MAX (0x120a | CCS_FL_16BIT)
-#define CCS_R_DIGITAL_CROP_CAPABILITY 0x120e
+#define CCS_R_SCALER_M_MIN CCI_REG16(0x1204)
+#define CCS_R_SCALER_M_MAX CCI_REG16(0x1206)
+#define CCS_R_SCALER_N_MIN CCI_REG16(0x1208)
+#define CCS_R_SCALER_N_MAX CCI_REG16(0x120a)
+#define CCS_R_DIGITAL_CROP_CAPABILITY CCI_REG8(0x120e)
#define CCS_DIGITAL_CROP_CAPABILITY_NONE 0U
#define CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP 1U
-#define CCS_R_HDR_CAPABILITY_1 0x1210
+#define CCS_R_HDR_CAPABILITY_1 CCI_REG8(0x1210)
#define CCS_HDR_CAPABILITY_1_2X2_BINNING BIT(0)
#define CCS_HDR_CAPABILITY_1_COMBINED_ANALOG_GAIN BIT(1)
#define CCS_HDR_CAPABILITY_1_SEPARATE_ANALOG_GAIN BIT(2)
@@ -611,66 +611,66 @@
#define CCS_HDR_CAPABILITY_1_RESET_SYNC BIT(4)
#define CCS_HDR_CAPABILITY_1_DIRECT_SHORT_EXP_TIMING BIT(5)
#define CCS_HDR_CAPABILITY_1_DIRECT_SHORT_EXP_SYNTHESIS BIT(6)
-#define CCS_R_MIN_HDR_BIT_DEPTH 0x1211
-#define CCS_R_HDR_RESOLUTION_SUB_TYPES 0x1212
-#define CCS_R_HDR_RESOLUTION_SUB_TYPE(n) (0x1213 + (n))
+#define CCS_R_MIN_HDR_BIT_DEPTH CCI_REG8(0x1211)
+#define CCS_R_HDR_RESOLUTION_SUB_TYPES CCI_REG8(0x1212)
+#define CCS_R_HDR_RESOLUTION_SUB_TYPE(n) CCI_REG8(0x1213 + (n))
#define CCS_LIM_HDR_RESOLUTION_SUB_TYPE_MIN_N 0U
#define CCS_LIM_HDR_RESOLUTION_SUB_TYPE_MAX_N 1U
#define CCS_HDR_RESOLUTION_SUB_TYPE_ROW_SHIFT 0U
#define CCS_HDR_RESOLUTION_SUB_TYPE_ROW_MASK 0xf
#define CCS_HDR_RESOLUTION_SUB_TYPE_COLUMN_SHIFT 4U
#define CCS_HDR_RESOLUTION_SUB_TYPE_COLUMN_MASK 0xf0
-#define CCS_R_HDR_CAPABILITY_2 0x121b
+#define CCS_R_HDR_CAPABILITY_2 CCI_REG8(0x121b)
#define CCS_HDR_CAPABILITY_2_COMBINED_DIGITAL_GAIN BIT(0)
#define CCS_HDR_CAPABILITY_2_SEPARATE_DIGITAL_GAIN BIT(1)
#define CCS_HDR_CAPABILITY_2_TIMING_MODE BIT(3)
#define CCS_HDR_CAPABILITY_2_SYNTHESIS_MODE BIT(4)
-#define CCS_R_MAX_HDR_BIT_DEPTH 0x121c
-#define CCS_R_USL_SUPPORT_CAPABILITY 0x1230
+#define CCS_R_MAX_HDR_BIT_DEPTH CCI_REG8(0x121c)
+#define CCS_R_USL_SUPPORT_CAPABILITY CCI_REG8(0x1230)
#define CCS_USL_SUPPORT_CAPABILITY_CLOCK_TREE BIT(0)
#define CCS_USL_SUPPORT_CAPABILITY_REV_CLOCK_TREE BIT(1)
#define CCS_USL_SUPPORT_CAPABILITY_REV_CLOCK_CALC BIT(2)
-#define CCS_R_USL_CLOCK_MODE_D_CAPABILITY 0x1231
+#define CCS_R_USL_CLOCK_MODE_D_CAPABILITY CCI_REG8(0x1231)
#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_STANDBY BIT(0)
#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_VBLANK BIT(1)
#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_HBLANK BIT(2)
#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_STANDBY BIT(3)
#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_VBLANK BIT(4)
#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_HBLANK BIT(5)
-#define CCS_R_MIN_OP_SYS_CLK_DIV_REV 0x1234
-#define CCS_R_MAX_OP_SYS_CLK_DIV_REV 0x1236
-#define CCS_R_MIN_OP_PIX_CLK_DIV_REV 0x1238
-#define CCS_R_MAX_OP_PIX_CLK_DIV_REV 0x123a
-#define CCS_R_MIN_OP_SYS_CLK_FREQ_REV_MHZ (0x123c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_OP_SYS_CLK_FREQ_REV_MHZ (0x1240 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MIN_OP_PIX_CLK_FREQ_REV_MHZ (0x1244 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_OP_PIX_CLK_FREQ_REV_MHZ (0x1248 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL))
-#define CCS_R_MAX_BITRATE_REV_D_MODE_MBPS (0x124c | (CCS_FL_32BIT | CCS_FL_IREAL))
-#define CCS_R_MAX_SYMRATE_REV_C_MODE_MSPS (0x1250 | (CCS_FL_32BIT | CCS_FL_IREAL))
-#define CCS_R_COMPRESSION_CAPABILITY 0x1300
+#define CCS_R_MIN_OP_SYS_CLK_DIV_REV CCI_REG8(0x1234)
+#define CCS_R_MAX_OP_SYS_CLK_DIV_REV CCI_REG8(0x1236)
+#define CCS_R_MIN_OP_PIX_CLK_DIV_REV CCI_REG8(0x1238)
+#define CCS_R_MAX_OP_PIX_CLK_DIV_REV CCI_REG8(0x123a)
+#define CCS_R_MIN_OP_SYS_CLK_FREQ_REV_MHZ (CCI_REG32(0x123c) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_OP_SYS_CLK_FREQ_REV_MHZ (CCI_REG32(0x1240) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MIN_OP_PIX_CLK_FREQ_REV_MHZ (CCI_REG32(0x1244) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_OP_PIX_CLK_FREQ_REV_MHZ (CCI_REG32(0x1248) | CCS_FL_FLOAT_IREAL)
+#define CCS_R_MAX_BITRATE_REV_D_MODE_MBPS (CCI_REG32(0x124c) | CCS_FL_IREAL)
+#define CCS_R_MAX_SYMRATE_REV_C_MODE_MSPS (CCI_REG32(0x1250) | CCS_FL_IREAL)
+#define CCS_R_COMPRESSION_CAPABILITY CCI_REG8(0x1300)
#define CCS_COMPRESSION_CAPABILITY_DPCM_PCM_SIMPLE BIT(0)
-#define CCS_R_TEST_MODE_CAPABILITY (0x1310 | CCS_FL_16BIT)
+#define CCS_R_TEST_MODE_CAPABILITY CCI_REG16(0x1310)
#define CCS_TEST_MODE_CAPABILITY_SOLID_COLOR BIT(0)
#define CCS_TEST_MODE_CAPABILITY_COLOR_BARS BIT(1)
#define CCS_TEST_MODE_CAPABILITY_FADE_TO_GREY BIT(2)
#define CCS_TEST_MODE_CAPABILITY_PN9 BIT(3)
#define CCS_TEST_MODE_CAPABILITY_COLOR_TILE BIT(5)
-#define CCS_R_PN9_DATA_FORMAT1 0x1312
-#define CCS_R_PN9_DATA_FORMAT2 0x1313
-#define CCS_R_PN9_DATA_FORMAT3 0x1314
-#define CCS_R_PN9_DATA_FORMAT4 0x1315
-#define CCS_R_PN9_MISC_CAPABILITY 0x1316
+#define CCS_R_PN9_DATA_FORMAT1 CCI_REG8(0x1312)
+#define CCS_R_PN9_DATA_FORMAT2 CCI_REG8(0x1313)
+#define CCS_R_PN9_DATA_FORMAT3 CCI_REG8(0x1314)
+#define CCS_R_PN9_DATA_FORMAT4 CCI_REG8(0x1315)
+#define CCS_R_PN9_MISC_CAPABILITY CCI_REG8(0x1316)
#define CCS_PN9_MISC_CAPABILITY_NUM_PIXELS_SHIFT 0U
#define CCS_PN9_MISC_CAPABILITY_NUM_PIXELS_MASK 0x7
#define CCS_PN9_MISC_CAPABILITY_COMPRESSION BIT(3)
-#define CCS_R_TEST_PATTERN_CAPABILITY 0x1317
+#define CCS_R_TEST_PATTERN_CAPABILITY CCI_REG8(0x1317)
#define CCS_TEST_PATTERN_CAPABILITY_NO_REPEAT BIT(1)
-#define CCS_R_PATTERN_SIZE_DIV_M1 0x1318
-#define CCS_R_FIFO_SUPPORT_CAPABILITY 0x1502
+#define CCS_R_PATTERN_SIZE_DIV_M1 CCI_REG8(0x1318)
+#define CCS_R_FIFO_SUPPORT_CAPABILITY CCI_REG8(0x1502)
#define CCS_FIFO_SUPPORT_CAPABILITY_NONE 0U
#define CCS_FIFO_SUPPORT_CAPABILITY_DERATING 1U
#define CCS_FIFO_SUPPORT_CAPABILITY_DERATING_OVERRATING 2U
-#define CCS_R_PHY_CTRL_CAPABILITY 0x1600
+#define CCS_R_PHY_CTRL_CAPABILITY CCI_REG8(0x1600)
#define CCS_PHY_CTRL_CAPABILITY_AUTO_PHY_CTL BIT(0)
#define CCS_PHY_CTRL_CAPABILITY_UI_PHY_CTL BIT(1)
#define CCS_PHY_CTRL_CAPABILITY_DPHY_TIME_UI_REG_1_CTL BIT(2)
@@ -679,7 +679,7 @@
#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_UI_REG_1_CTL BIT(5)
#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_UI_REG_2_CTL BIT(6)
#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_CTL BIT(7)
-#define CCS_R_CSI_DPHY_LANE_MODE_CAPABILITY 0x1601
+#define CCS_R_CSI_DPHY_LANE_MODE_CAPABILITY CCI_REG8(0x1601)
#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_1_LANE BIT(0)
#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_2_LANE BIT(1)
#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_3_LANE BIT(2)
@@ -688,22 +688,22 @@
#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_6_LANE BIT(5)
#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_7_LANE BIT(6)
#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_8_LANE BIT(7)
-#define CCS_R_CSI_SIGNALING_MODE_CAPABILITY 0x1602
+#define CCS_R_CSI_SIGNALING_MODE_CAPABILITY CCI_REG8(0x1602)
#define CCS_CSI_SIGNALING_MODE_CAPABILITY_CSI_DPHY BIT(2)
#define CCS_CSI_SIGNALING_MODE_CAPABILITY_CSI_CPHY BIT(3)
-#define CCS_R_FAST_STANDBY_CAPABILITY 0x1603
+#define CCS_R_FAST_STANDBY_CAPABILITY CCI_REG8(0x1603)
#define CCS_FAST_STANDBY_CAPABILITY_NO_FRAME_TRUNCATION 0U
#define CCS_FAST_STANDBY_CAPABILITY_FRAME_TRUNCATION 1U
-#define CCS_R_CSI_ADDRESS_CONTROL_CAPABILITY 0x1604
+#define CCS_R_CSI_ADDRESS_CONTROL_CAPABILITY CCI_REG8(0x1604)
#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_CCI_ADDR_CHANGE BIT(0)
#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_2ND_CCI_ADDR BIT(1)
#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_SW_CHANGEABLE_2ND_CCI_ADDR BIT(2)
-#define CCS_R_DATA_TYPE_CAPABILITY 0x1605
+#define CCS_R_DATA_TYPE_CAPABILITY CCI_REG8(0x1605)
#define CCS_DATA_TYPE_CAPABILITY_DPCM_PROGRAMMABLE BIT(0)
#define CCS_DATA_TYPE_CAPABILITY_BOTTOM_EMBEDDED_DT_PROGRAMMABLE BIT(1)
#define CCS_DATA_TYPE_CAPABILITY_BOTTOM_EMBEDDED_VC_PROGRAMMABLE BIT(2)
#define CCS_DATA_TYPE_CAPABILITY_EXT_VC_RANGE BIT(3)
-#define CCS_R_CSI_CPHY_LANE_MODE_CAPABILITY 0x1606
+#define CCS_R_CSI_CPHY_LANE_MODE_CAPABILITY CCI_REG8(0x1606)
#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_1_LANE BIT(0)
#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_2_LANE BIT(1)
#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_3_LANE BIT(2)
@@ -712,44 +712,44 @@
#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_6_LANE BIT(5)
#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_7_LANE BIT(6)
#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_8_LANE BIT(7)
-#define CCS_R_EMB_DATA_CAPABILITY 0x1607
+#define CCS_R_EMB_DATA_CAPABILITY CCI_REG8(0x1607)
#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW16 BIT(0)
#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW20 BIT(1)
#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW24 BIT(2)
#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW16 BIT(3)
#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW20 BIT(4)
#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW24 BIT(5)
-#define CCS_R_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS(n) ((0x1608 | (CCS_FL_32BIT | CCS_FL_IREAL)) + ((n) < 4 ? (n) * 4 : 0x32 + ((n) - 4) * 4))
+#define CCS_R_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS(n) (CCI_REG32(0x1608 + ((n) < 4 ? (n) * 4 : 0x32 + ((n) - 4) * 4)) | CCS_FL_IREAL)
#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS_MIN_N 0U
#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS_MAX_N 7U
-#define CCS_R_TEMP_SENSOR_CAPABILITY 0x1618
+#define CCS_R_TEMP_SENSOR_CAPABILITY CCI_REG8(0x1618)
#define CCS_TEMP_SENSOR_CAPABILITY_SUPPORTED BIT(0)
#define CCS_TEMP_SENSOR_CAPABILITY_CCS_FORMAT BIT(1)
#define CCS_TEMP_SENSOR_CAPABILITY_RESET_0X80 BIT(2)
-#define CCS_R_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS(n) ((0x161a | (CCS_FL_32BIT | CCS_FL_IREAL)) + ((n) < 4 ? (n) * 4 : 0x30 + ((n) - 4) * 4))
+#define CCS_R_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS(n) (CCI_REG32(0x161a + ((n) < 4 ? (n) * 4 : 0x30 + ((n) - 4) * 4)) | CCS_FL_IREAL)
#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS_MIN_N 0U
#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS_MAX_N 7U
-#define CCS_R_DPHY_EQUALIZATION_CAPABILITY 0x162b
+#define CCS_R_DPHY_EQUALIZATION_CAPABILITY CCI_REG8(0x162b)
#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQUALIZATION_CTRL BIT(0)
#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQ1 BIT(1)
#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQ2 BIT(2)
-#define CCS_R_CPHY_EQUALIZATION_CAPABILITY 0x162c
+#define CCS_R_CPHY_EQUALIZATION_CAPABILITY CCI_REG8(0x162c)
#define CCS_CPHY_EQUALIZATION_CAPABILITY_EQUALIZATION_CTRL BIT(0)
-#define CCS_R_DPHY_PREAMBLE_CAPABILITY 0x162d
+#define CCS_R_DPHY_PREAMBLE_CAPABILITY CCI_REG8(0x162d)
#define CCS_DPHY_PREAMBLE_CAPABILITY_PREAMBLE_SEQ_CTRL BIT(0)
-#define CCS_R_DPHY_SSC_CAPABILITY 0x162e
+#define CCS_R_DPHY_SSC_CAPABILITY CCI_REG8(0x162e)
#define CCS_DPHY_SSC_CAPABILITY_SUPPORTED BIT(0)
-#define CCS_R_CPHY_CALIBRATION_CAPABILITY 0x162f
+#define CCS_R_CPHY_CALIBRATION_CAPABILITY CCI_REG8(0x162f)
#define CCS_CPHY_CALIBRATION_CAPABILITY_MANUAL BIT(0)
#define CCS_CPHY_CALIBRATION_CAPABILITY_MANUAL_STREAMING BIT(1)
#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_1_CTRL BIT(2)
#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_2_CTRL BIT(3)
#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_3_CTRL BIT(4)
-#define CCS_R_DPHY_CALIBRATION_CAPABILITY 0x1630
+#define CCS_R_DPHY_CALIBRATION_CAPABILITY CCI_REG8(0x1630)
#define CCS_DPHY_CALIBRATION_CAPABILITY_MANUAL BIT(0)
#define CCS_DPHY_CALIBRATION_CAPABILITY_MANUAL_STREAMING BIT(1)
#define CCS_DPHY_CALIBRATION_CAPABILITY_ALTERNATE_SEQ BIT(2)
-#define CCS_R_PHY_CTRL_CAPABILITY_2 0x1631
+#define CCS_R_PHY_CTRL_CAPABILITY_2 CCI_REG8(0x1631)
#define CCS_PHY_CTRL_CAPABILITY_2_TGR_LENGTH BIT(0)
#define CCS_PHY_CTRL_CAPABILITY_2_TGR_PREAMBLE_PROG_SEQ BIT(1)
#define CCS_PHY_CTRL_CAPABILITY_2_EXTRA_CPHY_MANUAL_TIMING BIT(2)
@@ -758,13 +758,13 @@
#define CCS_PHY_CTRL_CAPABILITY_2_CLOCK_BASED_MANUAL_CPHY BIT(5)
#define CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_DPHY BIT(6)
#define CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_CPHY BIT(7)
-#define CCS_R_LRTE_CPHY_CAPABILITY 0x1632
+#define CCS_R_LRTE_CPHY_CAPABILITY CCI_REG8(0x1632)
#define CCS_LRTE_CPHY_CAPABILITY_PDQ_SHORT BIT(0)
#define CCS_LRTE_CPHY_CAPABILITY_SPACER_SHORT BIT(1)
#define CCS_LRTE_CPHY_CAPABILITY_PDQ_LONG BIT(2)
#define CCS_LRTE_CPHY_CAPABILITY_SPACER_LONG BIT(3)
#define CCS_LRTE_CPHY_CAPABILITY_SPACER_NO_PDQ BIT(4)
-#define CCS_R_LRTE_DPHY_CAPABILITY 0x1633
+#define CCS_R_LRTE_DPHY_CAPABILITY CCI_REG8(0x1633)
#define CCS_LRTE_DPHY_CAPABILITY_PDQ_SHORT_OPT1 BIT(0)
#define CCS_LRTE_DPHY_CAPABILITY_SPACER_SHORT_OPT1 BIT(1)
#define CCS_LRTE_DPHY_CAPABILITY_PDQ_LONG_OPT1 BIT(2)
@@ -773,18 +773,18 @@
#define CCS_LRTE_DPHY_CAPABILITY_SPACER_LONG_OPT2 BIT(5)
#define CCS_LRTE_DPHY_CAPABILITY_SPACER_NO_PDQ_OPT1 BIT(6)
#define CCS_LRTE_DPHY_CAPABILITY_SPACER_VARIABLE_OPT2 BIT(7)
-#define CCS_R_ALPS_CAPABILITY_DPHY 0x1634
+#define CCS_R_ALPS_CAPABILITY_DPHY CCI_REG8(0x1634)
#define CCS_ALPS_CAPABILITY_DPHY_LVLP_NOT_SUPPORTED 0U
#define CCS_ALPS_CAPABILITY_DPHY_LVLP_SUPPORTED 1U
#define CCS_ALPS_CAPABILITY_DPHY_CONTROLLABLE_LVLP 2U
-#define CCS_R_ALPS_CAPABILITY_CPHY 0x1635
+#define CCS_R_ALPS_CAPABILITY_CPHY CCI_REG8(0x1635)
#define CCS_ALPS_CAPABILITY_CPHY_LVLP_NOT_SUPPORTED 0U
#define CCS_ALPS_CAPABILITY_CPHY_LVLP_SUPPORTED 1U
#define CCS_ALPS_CAPABILITY_CPHY_CONTROLLABLE_LVLP 2U
#define CCS_ALPS_CAPABILITY_CPHY_ALP_NOT_SUPPORTED 0xc
#define CCS_ALPS_CAPABILITY_CPHY_ALP_SUPPORTED 0xd
#define CCS_ALPS_CAPABILITY_CPHY_CONTROLLABLE_ALP 0xe
-#define CCS_R_SCRAMBLING_CAPABILITY 0x1636
+#define CCS_R_SCRAMBLING_CAPABILITY CCI_REG8(0x1636)
#define CCS_SCRAMBLING_CAPABILITY_SCRAMBLING_SUPPORTED BIT(0)
#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_SHIFT 1U
#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_MASK 0x6
@@ -796,11 +796,11 @@
#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_1 1U
#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_4 4U
#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_PER_LANE BIT(6)
-#define CCS_R_DPHY_MANUAL_CONSTANT 0x1637
-#define CCS_R_CPHY_MANUAL_CONSTANT 0x1638
-#define CCS_R_CSI2_INTERFACE_CAPABILITY_MISC 0x1639
+#define CCS_R_DPHY_MANUAL_CONSTANT CCI_REG8(0x1637)
+#define CCS_R_CPHY_MANUAL_CONSTANT CCI_REG8(0x1638)
+#define CCS_R_CSI2_INTERFACE_CAPABILITY_MISC CCI_REG8(0x1639)
#define CCS_CSI2_INTERFACE_CAPABILITY_MISC_EOTP_SHORT_PKT_OPT2 BIT(0)
-#define CCS_R_PHY_CTRL_CAPABILITY_3 0x165c
+#define CCS_R_PHY_CTRL_CAPABILITY_3 CCI_REG8(0x165c)
#define CCS_PHY_CTRL_CAPABILITY_3_DPHY_TIMING_NOT_MULTIPLE BIT(0)
#define CCS_PHY_CTRL_CAPABILITY_3_DPHY_MIN_TIMING_VALUE_1 BIT(1)
#define CCS_PHY_CTRL_CAPABILITY_3_TWAKEUP_SUPPORTED BIT(2)
@@ -808,130 +808,130 @@
#define CCS_PHY_CTRL_CAPABILITY_3_THS_EXIT_SUPPORTED BIT(4)
#define CCS_PHY_CTRL_CAPABILITY_3_CPHY_TIMING_NOT_MULTIPLE BIT(5)
#define CCS_PHY_CTRL_CAPABILITY_3_CPHY_MIN_TIMING_VALUE_1 BIT(6)
-#define CCS_R_DPHY_SF 0x165d
-#define CCS_R_CPHY_SF 0x165e
+#define CCS_R_DPHY_SF CCI_REG8(0x165d)
+#define CCS_R_CPHY_SF CCI_REG8(0x165e)
#define CCS_CPHY_SF_TWAKEUP_SHIFT 0U
#define CCS_CPHY_SF_TWAKEUP_MASK 0xf
#define CCS_CPHY_SF_TINIT_SHIFT 4U
#define CCS_CPHY_SF_TINIT_MASK 0xf0
-#define CCS_R_DPHY_LIMITS_1 0x165f
+#define CCS_R_DPHY_LIMITS_1 CCI_REG8(0x165f)
#define CCS_DPHY_LIMITS_1_THS_PREPARE_SHIFT 0U
#define CCS_DPHY_LIMITS_1_THS_PREPARE_MASK 0xf
#define CCS_DPHY_LIMITS_1_THS_ZERO_SHIFT 4U
#define CCS_DPHY_LIMITS_1_THS_ZERO_MASK 0xf0
-#define CCS_R_DPHY_LIMITS_2 0x1660
+#define CCS_R_DPHY_LIMITS_2 CCI_REG8(0x1660)
#define CCS_DPHY_LIMITS_2_THS_TRAIL_SHIFT 0U
#define CCS_DPHY_LIMITS_2_THS_TRAIL_MASK 0xf
#define CCS_DPHY_LIMITS_2_TCLK_TRAIL_MIN_SHIFT 4U
#define CCS_DPHY_LIMITS_2_TCLK_TRAIL_MIN_MASK 0xf0
-#define CCS_R_DPHY_LIMITS_3 0x1661
+#define CCS_R_DPHY_LIMITS_3 CCI_REG8(0x1661)
#define CCS_DPHY_LIMITS_3_TCLK_PREPARE_SHIFT 0U
#define CCS_DPHY_LIMITS_3_TCLK_PREPARE_MASK 0xf
#define CCS_DPHY_LIMITS_3_TCLK_ZERO_SHIFT 4U
#define CCS_DPHY_LIMITS_3_TCLK_ZERO_MASK 0xf0
-#define CCS_R_DPHY_LIMITS_4 0x1662
+#define CCS_R_DPHY_LIMITS_4 CCI_REG8(0x1662)
#define CCS_DPHY_LIMITS_4_TCLK_POST_SHIFT 0U
#define CCS_DPHY_LIMITS_4_TCLK_POST_MASK 0xf
#define CCS_DPHY_LIMITS_4_TLPX_SHIFT 4U
#define CCS_DPHY_LIMITS_4_TLPX_MASK 0xf0
-#define CCS_R_DPHY_LIMITS_5 0x1663
+#define CCS_R_DPHY_LIMITS_5 CCI_REG8(0x1663)
#define CCS_DPHY_LIMITS_5_THS_EXIT_SHIFT 0U
#define CCS_DPHY_LIMITS_5_THS_EXIT_MASK 0xf
#define CCS_DPHY_LIMITS_5_TWAKEUP_SHIFT 4U
#define CCS_DPHY_LIMITS_5_TWAKEUP_MASK 0xf0
-#define CCS_R_DPHY_LIMITS_6 0x1664
+#define CCS_R_DPHY_LIMITS_6 CCI_REG8(0x1664)
#define CCS_DPHY_LIMITS_6_TINIT_SHIFT 0U
#define CCS_DPHY_LIMITS_6_TINIT_MASK 0xf
-#define CCS_R_CPHY_LIMITS_1 0x1665
+#define CCS_R_CPHY_LIMITS_1 CCI_REG8(0x1665)
#define CCS_CPHY_LIMITS_1_T3_PREPARE_MAX_SHIFT 0U
#define CCS_CPHY_LIMITS_1_T3_PREPARE_MAX_MASK 0xf
#define CCS_CPHY_LIMITS_1_T3_LPX_MAX_SHIFT 4U
#define CCS_CPHY_LIMITS_1_T3_LPX_MAX_MASK 0xf0
-#define CCS_R_CPHY_LIMITS_2 0x1666
+#define CCS_R_CPHY_LIMITS_2 CCI_REG8(0x1666)
#define CCS_CPHY_LIMITS_2_THS_EXIT_MAX_SHIFT 0U
#define CCS_CPHY_LIMITS_2_THS_EXIT_MAX_MASK 0xf
#define CCS_CPHY_LIMITS_2_TWAKEUP_MAX_SHIFT 4U
#define CCS_CPHY_LIMITS_2_TWAKEUP_MAX_MASK 0xf0
-#define CCS_R_CPHY_LIMITS_3 0x1667
+#define CCS_R_CPHY_LIMITS_3 CCI_REG8(0x1667)
#define CCS_CPHY_LIMITS_3_TINIT_MAX_SHIFT 0U
#define CCS_CPHY_LIMITS_3_TINIT_MAX_MASK 0xf
-#define CCS_R_MIN_FRAME_LENGTH_LINES_BIN (0x1700 | CCS_FL_16BIT)
-#define CCS_R_MAX_FRAME_LENGTH_LINES_BIN (0x1702 | CCS_FL_16BIT)
-#define CCS_R_MIN_LINE_LENGTH_PCK_BIN (0x1704 | CCS_FL_16BIT)
-#define CCS_R_MAX_LINE_LENGTH_PCK_BIN (0x1706 | CCS_FL_16BIT)
-#define CCS_R_MIN_LINE_BLANKING_PCK_BIN (0x1708 | CCS_FL_16BIT)
-#define CCS_R_FINE_INTEGRATION_TIME_MIN_BIN (0x170a | CCS_FL_16BIT)
-#define CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN (0x170c | CCS_FL_16BIT)
-#define CCS_R_BINNING_CAPABILITY 0x1710
+#define CCS_R_MIN_FRAME_LENGTH_LINES_BIN CCI_REG16(0x1700)
+#define CCS_R_MAX_FRAME_LENGTH_LINES_BIN CCI_REG16(0x1702)
+#define CCS_R_MIN_LINE_LENGTH_PCK_BIN CCI_REG16(0x1704)
+#define CCS_R_MAX_LINE_LENGTH_PCK_BIN CCI_REG16(0x1706)
+#define CCS_R_MIN_LINE_BLANKING_PCK_BIN CCI_REG16(0x1708)
+#define CCS_R_FINE_INTEGRATION_TIME_MIN_BIN CCI_REG16(0x170a)
+#define CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN CCI_REG16(0x170c)
+#define CCS_R_BINNING_CAPABILITY CCI_REG8(0x1710)
#define CCS_BINNING_CAPABILITY_UNSUPPORTED 0U
#define CCS_BINNING_CAPABILITY_BINNING_THEN_SUBSAMPLING 1U
#define CCS_BINNING_CAPABILITY_SUBSAMPLING_THEN_BINNING 2U
-#define CCS_R_BINNING_WEIGHTING_CAPABILITY 0x1711
+#define CCS_R_BINNING_WEIGHTING_CAPABILITY CCI_REG8(0x1711)
#define CCS_BINNING_WEIGHTING_CAPABILITY_AVERAGED BIT(0)
#define CCS_BINNING_WEIGHTING_CAPABILITY_SUMMED BIT(1)
#define CCS_BINNING_WEIGHTING_CAPABILITY_BAYER_CORRECTED BIT(2)
#define CCS_BINNING_WEIGHTING_CAPABILITY_MODULE_SPECIFIC_WEIGHT BIT(3)
-#define CCS_R_BINNING_SUB_TYPES 0x1712
-#define CCS_R_BINNING_SUB_TYPE(n) (0x1713 + (n))
+#define CCS_R_BINNING_SUB_TYPES CCI_REG8(0x1712)
+#define CCS_R_BINNING_SUB_TYPE(n) CCI_REG8(0x1713 + (n))
#define CCS_LIM_BINNING_SUB_TYPE_MIN_N 0U
#define CCS_LIM_BINNING_SUB_TYPE_MAX_N 63U
#define CCS_BINNING_SUB_TYPE_ROW_SHIFT 0U
#define CCS_BINNING_SUB_TYPE_ROW_MASK 0xf
#define CCS_BINNING_SUB_TYPE_COLUMN_SHIFT 4U
#define CCS_BINNING_SUB_TYPE_COLUMN_MASK 0xf0
-#define CCS_R_BINNING_WEIGHTING_MONO_CAPABILITY 0x1771
+#define CCS_R_BINNING_WEIGHTING_MONO_CAPABILITY CCI_REG8(0x1771)
#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_AVERAGED BIT(0)
#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_SUMMED BIT(1)
#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_BAYER_CORRECTED BIT(2)
#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_MODULE_SPECIFIC_WEIGHT BIT(3)
-#define CCS_R_BINNING_SUB_TYPES_MONO 0x1772
-#define CCS_R_BINNING_SUB_TYPE_MONO(n) (0x1773 + (n))
+#define CCS_R_BINNING_SUB_TYPES_MONO CCI_REG8(0x1772)
+#define CCS_R_BINNING_SUB_TYPE_MONO(n) CCI_REG8(0x1773 + (n))
#define CCS_LIM_BINNING_SUB_TYPE_MONO_MIN_N 0U
#define CCS_LIM_BINNING_SUB_TYPE_MONO_MAX_N 63U
-#define CCS_R_DATA_TRANSFER_IF_CAPABILITY 0x1800
+#define CCS_R_DATA_TRANSFER_IF_CAPABILITY CCI_REG8(0x1800)
#define CCS_DATA_TRANSFER_IF_CAPABILITY_SUPPORTED BIT(0)
#define CCS_DATA_TRANSFER_IF_CAPABILITY_POLLING BIT(2)
-#define CCS_R_SHADING_CORRECTION_CAPABILITY 0x1900
+#define CCS_R_SHADING_CORRECTION_CAPABILITY CCI_REG8(0x1900)
#define CCS_SHADING_CORRECTION_CAPABILITY_COLOR_SHADING BIT(0)
#define CCS_SHADING_CORRECTION_CAPABILITY_LUMINANCE_CORRECTION BIT(1)
-#define CCS_R_GREEN_IMBALANCE_CAPABILITY 0x1901
+#define CCS_R_GREEN_IMBALANCE_CAPABILITY CCI_REG8(0x1901)
#define CCS_GREEN_IMBALANCE_CAPABILITY_SUPPORTED BIT(0)
-#define CCS_R_MODULE_SPECIFIC_CORRECTION_CAPABILITY 0x1903
-#define CCS_R_DEFECT_CORRECTION_CAPABILITY (0x1904 | CCS_FL_16BIT)
+#define CCS_R_MODULE_SPECIFIC_CORRECTION_CAPABILITY CCI_REG8(0x1903)
+#define CCS_R_DEFECT_CORRECTION_CAPABILITY CCI_REG16(0x1904)
#define CCS_DEFECT_CORRECTION_CAPABILITY_MAPPED_DEFECT BIT(0)
#define CCS_DEFECT_CORRECTION_CAPABILITY_DYNAMIC_COUPLET BIT(2)
#define CCS_DEFECT_CORRECTION_CAPABILITY_DYNAMIC_SINGLE BIT(5)
#define CCS_DEFECT_CORRECTION_CAPABILITY_COMBINED_DYNAMIC BIT(8)
-#define CCS_R_DEFECT_CORRECTION_CAPABILITY_2 (0x1906 | CCS_FL_16BIT)
+#define CCS_R_DEFECT_CORRECTION_CAPABILITY_2 CCI_REG16(0x1906)
#define CCS_DEFECT_CORRECTION_CAPABILITY_2_DYNAMIC_TRIPLET BIT(3)
-#define CCS_R_NF_CAPABILITY 0x1908
+#define CCS_R_NF_CAPABILITY CCI_REG8(0x1908)
#define CCS_NF_CAPABILITY_LUMA BIT(0)
#define CCS_NF_CAPABILITY_CHROMA BIT(1)
#define CCS_NF_CAPABILITY_COMBINED BIT(2)
-#define CCS_R_OB_READOUT_CAPABILITY 0x1980
+#define CCS_R_OB_READOUT_CAPABILITY CCI_REG8(0x1980)
#define CCS_OB_READOUT_CAPABILITY_CONTROLLABLE_READOUT BIT(0)
#define CCS_OB_READOUT_CAPABILITY_VISIBLE_PIXEL_READOUT BIT(1)
#define CCS_OB_READOUT_CAPABILITY_DIFFERENT_VC_READOUT BIT(2)
#define CCS_OB_READOUT_CAPABILITY_DIFFERENT_DT_READOUT BIT(3)
#define CCS_OB_READOUT_CAPABILITY_PROG_DATA_FORMAT BIT(4)
-#define CCS_R_COLOR_FEEDBACK_CAPABILITY 0x1987
+#define CCS_R_COLOR_FEEDBACK_CAPABILITY CCI_REG8(0x1987)
#define CCS_COLOR_FEEDBACK_CAPABILITY_KELVIN BIT(0)
#define CCS_COLOR_FEEDBACK_CAPABILITY_AWB_GAIN BIT(1)
-#define CCS_R_CFA_PATTERN_CAPABILITY 0x1990
+#define CCS_R_CFA_PATTERN_CAPABILITY CCI_REG8(0x1990)
#define CCS_CFA_PATTERN_CAPABILITY_BAYER 0U
#define CCS_CFA_PATTERN_CAPABILITY_MONOCHROME 1U
#define CCS_CFA_PATTERN_CAPABILITY_4X4_QUAD_BAYER 2U
#define CCS_CFA_PATTERN_CAPABILITY_VENDOR_SPECIFIC 3U
-#define CCS_R_CFA_PATTERN_CONVERSION_CAPABILITY 0x1991
+#define CCS_R_CFA_PATTERN_CONVERSION_CAPABILITY CCI_REG8(0x1991)
#define CCS_CFA_PATTERN_CONVERSION_CAPABILITY_BAYER BIT(0)
-#define CCS_R_FLASH_MODE_CAPABILITY 0x1a02
+#define CCS_R_FLASH_MODE_CAPABILITY CCI_REG8(0x1a02)
#define CCS_FLASH_MODE_CAPABILITY_SINGLE_STROBE BIT(0)
-#define CCS_R_SA_STROBE_MODE_CAPABILITY 0x1a03
+#define CCS_R_SA_STROBE_MODE_CAPABILITY CCI_REG8(0x1a03)
#define CCS_SA_STROBE_MODE_CAPABILITY_FIXED_WIDTH BIT(0)
#define CCS_SA_STROBE_MODE_CAPABILITY_EDGE_CTRL BIT(1)
-#define CCS_R_RESET_MAX_DELAY 0x1a10
-#define CCS_R_RESET_MIN_TIME 0x1a11
-#define CCS_R_PDAF_CAPABILITY_1 0x1b80
+#define CCS_R_RESET_MAX_DELAY CCI_REG8(0x1a10)
+#define CCS_R_RESET_MIN_TIME CCI_REG8(0x1a11)
+#define CCS_R_PDAF_CAPABILITY_1 CCI_REG8(0x1b80)
#define CCS_PDAF_CAPABILITY_1_SUPPORTED BIT(0)
#define CCS_PDAF_CAPABILITY_1_PROCESSED_BOTTOM_EMBEDDED BIT(1)
#define CCS_PDAF_CAPABILITY_1_PROCESSED_INTERLEAVED BIT(2)
@@ -940,19 +940,19 @@
#define CCS_PDAF_CAPABILITY_1_VISIBLE_PDAF_CORRECTION BIT(5)
#define CCS_PDAF_CAPABILITY_1_VC_INTERLEAVING BIT(6)
#define CCS_PDAF_CAPABILITY_1_DT_INTERLEAVING BIT(7)
-#define CCS_R_PDAF_CAPABILITY_2 0x1b81
+#define CCS_R_PDAF_CAPABILITY_2 CCI_REG8(0x1b81)
#define CCS_PDAF_CAPABILITY_2_ROI BIT(0)
#define CCS_PDAF_CAPABILITY_2_AFTER_DIGITAL_CROP BIT(1)
#define CCS_PDAF_CAPABILITY_2_CTRL_RETIMED BIT(2)
-#define CCS_R_BRACKETING_LUT_CAPABILITY_1 0x1c00
+#define CCS_R_BRACKETING_LUT_CAPABILITY_1 CCI_REG8(0x1c00)
#define CCS_BRACKETING_LUT_CAPABILITY_1_COARSE_INTEGRATION BIT(0)
#define CCS_BRACKETING_LUT_CAPABILITY_1_GLOBAL_ANALOG_GAIN BIT(1)
#define CCS_BRACKETING_LUT_CAPABILITY_1_FLASH BIT(4)
#define CCS_BRACKETING_LUT_CAPABILITY_1_GLOBAL_DIGITAL_GAIN BIT(5)
#define CCS_BRACKETING_LUT_CAPABILITY_1_ALTERNATE_GLOBAL_ANALOG_GAIN BIT(6)
-#define CCS_R_BRACKETING_LUT_CAPABILITY_2 0x1c01
+#define CCS_R_BRACKETING_LUT_CAPABILITY_2 CCI_REG8(0x1c01)
#define CCS_BRACKETING_LUT_CAPABILITY_2_SINGLE_BRACKETING_MODE BIT(0)
#define CCS_BRACKETING_LUT_CAPABILITY_2_LOOPED_BRACKETING_MODE BIT(1)
-#define CCS_R_BRACKETING_LUT_SIZE 0x1c02
+#define CCS_R_BRACKETING_LUT_SIZE CCI_REG8(0x1c02)
#endif /* __CCS_REGS_H__ */
diff --git a/drivers/media/i2c/ccs/ccs.h b/drivers/media/i2c/ccs/ccs.h
index 9c3587b2fb..096573845a 100644
--- a/drivers/media/i2c/ccs/ccs.h
+++ b/drivers/media/i2c/ccs/ccs.h
@@ -13,6 +13,7 @@
#define __CCS_H__
#include <linux/mutex.h>
+#include <linux/regmap.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
@@ -211,6 +212,7 @@ struct ccs_sensor {
struct clk *ext_clk;
struct gpio_desc *xshutdown;
struct gpio_desc *reset;
+ struct regmap *regmap;
void *ccs_limits;
u8 nbinning_subtypes;
struct ccs_binning_subtype binning_subtypes[CCS_LIM_BINNING_SUB_TYPE_MAX_N + 1];
@@ -236,6 +238,7 @@ struct ccs_sensor {
bool streaming;
bool dev_init_done;
+ bool handler_setup_needed;
u8 compressed_min_bpp;
struct ccs_module_info minfo;
diff --git a/drivers/media/i2c/ccs/smiapp-reg-defs.h b/drivers/media/i2c/ccs/smiapp-reg-defs.h
index 177e3e5120..ebd0f90e10 100644
--- a/drivers/media/i2c/ccs/smiapp-reg-defs.h
+++ b/drivers/media/i2c/ccs/smiapp-reg-defs.h
@@ -12,481 +12,484 @@
#ifndef __SMIAPP_REG_DEFS_H__
#define __SMIAPP_REG_DEFS_H__
+#include <linux/bits.h>
+#include <media/v4l2-cci.h>
+
/* Register addresses */
-#define SMIAPP_REG_U16_MODEL_ID (0x0000 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR 0x0002
-#define SMIAPP_REG_U8_MANUFACTURER_ID 0x0003
-#define SMIAPP_REG_U8_SMIA_VERSION 0x0004
-#define SMIAPP_REG_U8_FRAME_COUNT 0x0005
-#define SMIAPP_REG_U8_PIXEL_ORDER 0x0006
-#define SMIAPP_REG_U16_DATA_PEDESTAL (0x0008 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_PIXEL_DEPTH 0x000c
-#define SMIAPP_REG_U8_REVISION_NUMBER_MINOR 0x0010
-#define SMIAPP_REG_U8_SMIAPP_VERSION 0x0011
-#define SMIAPP_REG_U8_MODULE_DATE_YEAR 0x0012
-#define SMIAPP_REG_U8_MODULE_DATE_MONTH 0x0013
-#define SMIAPP_REG_U8_MODULE_DATE_DAY 0x0014
-#define SMIAPP_REG_U8_MODULE_DATE_PHASE 0x0015
-#define SMIAPP_REG_U16_SENSOR_MODEL_ID (0x0016 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_SENSOR_REVISION_NUMBER 0x0018
-#define SMIAPP_REG_U8_SENSOR_MANUFACTURER_ID 0x0019
-#define SMIAPP_REG_U8_SENSOR_FIRMWARE_VERSION 0x001a
-#define SMIAPP_REG_U32_SERIAL_NUMBER (0x001c | CCS_FL_32BIT)
-#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE 0x0040
-#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_SUBTYPE 0x0041
-#define SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(n) ((0x0042 + ((n) << 1)) | CCS_FL_16BIT) /* 0 <= n <= 14 */
-#define SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(n) ((0x0060 + ((n) << 2)) | CCS_FL_32BIT) /* 0 <= n <= 7 */
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CAPABILITY (0x0080 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MIN (0x0084 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MAX (0x0086 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_STEP (0x0088 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_TYPE (0x008a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_M0 (0x008c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_C0 (0x008e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_M1 (0x0090 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_C1 (0x0092 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_TYPE 0x00c0
-#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_SUBTYPE 0x00c1
-#define SMIAPP_REG_U16_DATA_FORMAT_DESCRIPTOR(n) ((0x00c2 + ((n) << 1)) | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_MODE_SELECT 0x0100
-#define SMIAPP_REG_U8_IMAGE_ORIENTATION 0x0101
-#define SMIAPP_REG_U8_SOFTWARE_RESET 0x0103
-#define SMIAPP_REG_U8_GROUPED_PARAMETER_HOLD 0x0104
-#define SMIAPP_REG_U8_MASK_CORRUPTED_FRAMES 0x0105
-#define SMIAPP_REG_U8_FAST_STANDBY_CTRL 0x0106
-#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL 0x0107
-#define SMIAPP_REG_U8_2ND_CCI_IF_CONTROL 0x0108
-#define SMIAPP_REG_U8_2ND_CCI_ADDRESS_CONTROL 0x0109
-#define SMIAPP_REG_U8_CSI_CHANNEL_IDENTIFIER 0x0110
-#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE 0x0111
-#define SMIAPP_REG_U16_CSI_DATA_FORMAT (0x0112 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_CSI_LANE_MODE 0x0114
-#define SMIAPP_REG_U8_CSI2_10_TO_8_DT 0x0115
-#define SMIAPP_REG_U8_CSI2_10_TO_7_DT 0x0116
-#define SMIAPP_REG_U8_CSI2_10_TO_6_DT 0x0117
-#define SMIAPP_REG_U8_CSI2_12_TO_8_DT 0x0118
-#define SMIAPP_REG_U8_CSI2_12_TO_7_DT 0x0119
-#define SMIAPP_REG_U8_CSI2_12_TO_6_DT 0x011a
-#define SMIAPP_REG_U8_CSI2_14_TO_10_DT 0x011b
-#define SMIAPP_REG_U8_CSI2_14_TO_8_DT 0x011c
-#define SMIAPP_REG_U8_CSI2_16_TO_10_DT 0x011d
-#define SMIAPP_REG_U8_CSI2_16_TO_8_DT 0x011e
-#define SMIAPP_REG_U8_GAIN_MODE 0x0120
-#define SMIAPP_REG_U16_VANA_VOLTAGE (0x0130 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_VDIG_VOLTAGE (0x0132 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_VIO_VOLTAGE (0x0134 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ (0x0136 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_TEMP_SENSOR_CONTROL 0x0138
-#define SMIAPP_REG_U8_TEMP_SENSOR_MODE 0x0139
-#define SMIAPP_REG_U8_TEMP_SENSOR_OUTPUT 0x013a
-#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME (0x0200 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME (0x0202 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL (0x0204 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENR (0x0206 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_RED (0x0208 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_BLUE (0x020a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENB (0x020c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENR (0x020e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_GAIN_RED (0x0210 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_GAIN_BLUE (0x0212 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENB (0x0214 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_VT_PIX_CLK_DIV (0x0300 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_VT_SYS_CLK_DIV (0x0302 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_PRE_PLL_CLK_DIV (0x0304 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_PLL_MULTIPLIER (0x0306 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_OP_PIX_CLK_DIV (0x0308 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_OP_SYS_CLK_DIV (0x030a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FRAME_LENGTH_LINES (0x0340 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_LINE_LENGTH_PCK (0x0342 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_X_ADDR_START (0x0344 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_Y_ADDR_START (0x0346 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_X_ADDR_END (0x0348 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_Y_ADDR_END (0x034a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_X_OUTPUT_SIZE (0x034c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_Y_OUTPUT_SIZE (0x034e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_X_EVEN_INC (0x0380 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_X_ODD_INC (0x0382 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_Y_EVEN_INC (0x0384 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_Y_ODD_INC (0x0386 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SCALING_MODE (0x0400 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SPATIAL_SAMPLING (0x0402 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SCALE_M (0x0404 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SCALE_N (0x0406 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_CROP_X_OFFSET (0x0408 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_CROP_Y_OFFSET (0x040a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_WIDTH (0x040c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_HEIGHT (0x040e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_COMPRESSION_MODE (0x0500 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TEST_PATTERN_MODE (0x0600 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TEST_DATA_RED (0x0602 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TEST_DATA_GREENR (0x0604 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TEST_DATA_BLUE (0x0606 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TEST_DATA_GREENB (0x0608 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_WIDTH (0x060a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_POSITION (0x060c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_VERTICAL_CURSOR_WIDTH (0x060e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_VERTICAL_CURSOR_POSITION (0x0610 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FIFO_WATER_MARK_PIXELS (0x0700 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_TCLK_POST 0x0800
-#define SMIAPP_REG_U8_THS_PREPARE 0x0801
-#define SMIAPP_REG_U8_THS_ZERO_MIN 0x0802
-#define SMIAPP_REG_U8_THS_TRAIL 0x0803
-#define SMIAPP_REG_U8_TCLK_TRAIL_MIN 0x0804
-#define SMIAPP_REG_U8_TCLK_PREPARE 0x0805
-#define SMIAPP_REG_U8_TCLK_ZERO 0x0806
-#define SMIAPP_REG_U8_TLPX 0x0807
-#define SMIAPP_REG_U8_DPHY_CTRL 0x0808
-#define SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS (0x0820 | CCS_FL_32BIT)
-#define SMIAPP_REG_U8_BINNING_MODE 0x0900
-#define SMIAPP_REG_U8_BINNING_TYPE 0x0901
-#define SMIAPP_REG_U8_BINNING_WEIGHTING 0x0902
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL 0x0a00
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS 0x0a01
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT 0x0a02
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_0 0x0a04
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_1 0x0a05
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_2 0x0a06
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_3 0x0a07
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_4 0x0a08
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_5 0x0a09
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_12 0x0a10
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_13 0x0a11
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_14 0x0a12
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_15 0x0a13
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_16 0x0a14
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_17 0x0a15
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_18 0x0a16
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_19 0x0a17
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_20 0x0a18
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_21 0x0a19
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_22 0x0a1a
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_23 0x0a1b
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_24 0x0a1c
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_25 0x0a1d
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_26 0x0a1e
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_27 0x0a1f
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_28 0x0a20
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_29 0x0a21
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_30 0x0a22
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_31 0x0a23
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_32 0x0a24
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_33 0x0a25
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_34 0x0a26
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_35 0x0a27
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_36 0x0a28
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_37 0x0a29
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_38 0x0a2a
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_39 0x0a2b
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_40 0x0a2c
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_41 0x0a2d
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_42 0x0a2e
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_43 0x0a2f
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_44 0x0a30
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_45 0x0a31
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_46 0x0a32
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_47 0x0a33
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_48 0x0a34
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_49 0x0a35
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_50 0x0a36
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_51 0x0a37
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_52 0x0a38
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_53 0x0a39
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_54 0x0a3a
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_55 0x0a3b
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_56 0x0a3c
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_57 0x0a3d
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_58 0x0a3e
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_59 0x0a3f
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_60 0x0a40
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_61 0x0a41
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_62 0x0a42
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_63 0x0a43
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_CTRL 0x0a44
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_STATUS 0x0a45
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_PAGE_SELECT 0x0a46
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_0 0x0a48
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_1 0x0a49
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_2 0x0a4a
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_3 0x0a4b
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_4 0x0a4c
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_5 0x0a4d
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_6 0x0a4e
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_7 0x0a4f
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_8 0x0a50
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_9 0x0a51
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_10 0x0a52
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_11 0x0a53
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_12 0x0a54
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_13 0x0a55
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_14 0x0a56
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_15 0x0a57
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_16 0x0a58
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_17 0x0a59
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_18 0x0a5a
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_19 0x0a5b
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_20 0x0a5c
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_21 0x0a5d
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_22 0x0a5e
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_23 0x0a5f
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_24 0x0a60
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_25 0x0a61
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_26 0x0a62
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_27 0x0a63
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_28 0x0a64
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_29 0x0a65
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_30 0x0a66
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_31 0x0a67
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_32 0x0a68
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_33 0x0a69
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_34 0x0a6a
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_35 0x0a6b
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_36 0x0a6c
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_37 0x0a6d
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_38 0x0a6e
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_39 0x0a6f
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_40 0x0a70
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_41 0x0a71
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_42 0x0a72
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_43 0x0a73
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_44 0x0a74
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_45 0x0a75
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_46 0x0a76
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_47 0x0a77
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_48 0x0a78
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_49 0x0a79
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_50 0x0a7a
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_51 0x0a7b
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_52 0x0a7c
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_53 0x0a7d
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_54 0x0a7e
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_55 0x0a7f
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_56 0x0a80
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_57 0x0a81
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_58 0x0a82
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_59 0x0a83
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_60 0x0a84
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_61 0x0a85
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_62 0x0a86
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_63 0x0a87
-#define SMIAPP_REG_U8_SHADING_CORRECTION_ENABLE 0x0b00
-#define SMIAPP_REG_U8_LUMINANCE_CORRECTION_LEVEL 0x0b01
-#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_ENABLE 0x0b02
-#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_WEIGHT 0x0b03
-#define SMIAPP_REG_U8_BLACK_LEVEL_CORRECTION_ENABLE 0x0b04
-#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ENABLE 0x0b05
-#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_ENABLE 0x0b06
-#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_WEIGHT 0x0b07
-#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_ENABLE 0x0b08
-#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_WEIGHT 0x0b09
-#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_ENABLE 0x0b0a
-#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_WEIGHT 0x0b0b
-#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_ENABLE 0x0b0c
-#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_WEIGHT 0x0b0d
-#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ENABLE 0x0b0e
-#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ADJUST 0x0b0f
-#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ADJUST 0x0b10
-#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ENABLE 0x0b11
-#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ADJUST 0x0b12
-#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ENABLE 0x0b13
-#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ADJUST 0x0b14
-#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ENABLE 0x0b15
-#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ADJUST 0x0b16
-#define SMIAPP_REG_U8_EDOF_MODE 0x0b80
-#define SMIAPP_REG_U8_SHARPNESS 0x0b83
-#define SMIAPP_REG_U8_DENOISING 0x0b84
-#define SMIAPP_REG_U8_MODULE_SPECIFIC 0x0b85
-#define SMIAPP_REG_U16_DEPTH_OF_FIELD (0x0b86 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FOCUS_DISTANCE (0x0b88 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_ESTIMATION_MODE_CTRL 0x0b8a
-#define SMIAPP_REG_U16_COLOUR_TEMPERATURE (0x0b8c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENR (0x0b8e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ABSOLUTE_GAIN_RED (0x0b90 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ABSOLUTE_GAIN_BLUE (0x0b92 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENB (0x0b94 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_ESTIMATION_ZONE_MODE 0x0bc0
-#define SMIAPP_REG_U16_FIXED_ZONE_WEIGHTING (0x0bc2 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_CUSTOM_ZONE_X_START (0x0bc4 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_CUSTOM_ZONE_Y_START (0x0bc6 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_CUSTOM_ZONE_WIDTH (0x0bc8 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_CUSTOM_ZONE_HEIGHT (0x0bca | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL1 0x0c00
-#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL2 0x0c01
-#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_1 0x0c02
-#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_2 0x0c03
-#define SMIAPP_REG_U16_TRDY_CTRL (0x0c04 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TRDOUT_CTRL (0x0c06 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TSHUTTER_STROBE_DELAY_CTRL (0x0c08 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TSHUTTER_STROBE_WIDTH_CTRL (0x0c0a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_CTRL (0x0c0c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_CTRL (0x0c0e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TGRST_INTERVAL_CTRL (0x0c10 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_FLASH_STROBE_ADJUSTMENT 0x0c12
-#define SMIAPP_REG_U16_FLASH_STROBE_START_POINT (0x0c14 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_RS_CTRL (0x0c16 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL (0x0c18 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_FLASH_MODE_RS 0x0c1a
-#define SMIAPP_REG_U8_FLASH_TRIGGER_RS 0x0c1b
-#define SMIAPP_REG_U8_FLASH_STATUS 0x0c1c
-#define SMIAPP_REG_U8_SA_STROBE_MODE 0x0c1d
-#define SMIAPP_REG_U16_SA_STROBE_START_POINT (0x0c1e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TSA_STROBE_DELAY_CTRL (0x0c20 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TSA_STROBE_WIDTH_CTRL (0x0c22 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_SA_STROBE_TRIGGER 0x0c24
-#define SMIAPP_REG_U8_SPECIAL_ACTUATOR_STATUS 0x0c25
-#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_RS_CTRL (0x0c26 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_RS_CTRL (0x0c28 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_RS_CTRL 0x0c2a
-#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_CTRL 0x0c2b
-#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_CTRL (0x0c2c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_CTRL (0x0c2e | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_LOW_LEVEL_CTRL 0x0c80
-#define SMIAPP_REG_U16_MAIN_TRIGGER_REF_POINT (0x0c82 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAIN_TRIGGER_T3 (0x0c84 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_MAIN_TRIGGER_COUNT 0x0c86
-#define SMIAPP_REG_U16_PHASE1_TRIGGER_T3 (0x0c88 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_PHASE1_TRIGGER_COUNT 0x0c8a
-#define SMIAPP_REG_U16_PHASE2_TRIGGER_T3 (0x0c8c | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_PHASE2_TRIGGER_COUNT 0x0c8e
-#define SMIAPP_REG_U8_MECH_SHUTTER_CTRL 0x0d00
-#define SMIAPP_REG_U8_OPERATION_MODE 0x0d01
-#define SMIAPP_REG_U8_ACT_STATE1 0x0d02
-#define SMIAPP_REG_U8_ACT_STATE2 0x0d03
-#define SMIAPP_REG_U16_FOCUS_CHANGE (0x0d80 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FOCUS_CHANGE_CONTROL (0x0d82 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE1 (0x0d84 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE2 (0x0d86 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_STROBE_COUNT_PHASE1 0x0d88
-#define SMIAPP_REG_U8_STROBE_COUNT_PHASE2 0x0d89
-#define SMIAPP_REG_U8_POSITION 0x0d8a
-#define SMIAPP_REG_U8_BRACKETING_LUT_CONTROL 0x0e00
-#define SMIAPP_REG_U8_BRACKETING_LUT_MODE 0x0e01
-#define SMIAPP_REG_U8_BRACKETING_LUT_ENTRY_CONTROL 0x0e02
-#define SMIAPP_REG_U8_LUT_PARAMETERS_START 0x0e10
-#define SMIAPP_REG_U8_LUT_PARAMETERS_END 0x0eff
-#define SMIAPP_REG_U16_INTEGRATION_TIME_CAPABILITY (0x1000 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MIN (0x1004 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MAX_MARGIN (0x1006 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN (0x1008 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN (0x100a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_GAIN_CAPABILITY (0x1080 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_GAIN_MIN (0x1084 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_GAIN_MAX (0x1086 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DIGITAL_GAIN_STEP_SIZE (0x1088 | CCS_FL_16BIT)
-#define SMIAPP_REG_F32_MIN_EXT_CLK_FREQ_HZ (0x1100 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_F32_MAX_EXT_CLK_FREQ_HZ (0x1104 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_U16_MIN_PRE_PLL_CLK_DIV (0x1108 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_PRE_PLL_CLK_DIV (0x110a | CCS_FL_16BIT)
-#define SMIAPP_REG_F32_MIN_PLL_IP_FREQ_HZ (0x110c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_F32_MAX_PLL_IP_FREQ_HZ (0x1110 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_U16_MIN_PLL_MULTIPLIER (0x1114 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_PLL_MULTIPLIER (0x1116 | CCS_FL_16BIT)
-#define SMIAPP_REG_F32_MIN_PLL_OP_FREQ_HZ (0x1118 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_F32_MAX_PLL_OP_FREQ_HZ (0x111c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_U16_MIN_VT_SYS_CLK_DIV (0x1120 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_VT_SYS_CLK_DIV (0x1122 | CCS_FL_16BIT)
-#define SMIAPP_REG_F32_MIN_VT_SYS_CLK_FREQ_HZ (0x1124 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_F32_MAX_VT_SYS_CLK_FREQ_HZ (0x1128 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_F32_MIN_VT_PIX_CLK_FREQ_HZ (0x112c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_F32_MAX_VT_PIX_CLK_FREQ_HZ (0x1130 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_U16_MIN_VT_PIX_CLK_DIV (0x1134 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_VT_PIX_CLK_DIV (0x1136 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES (0x1140 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES (0x1142 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK (0x1144 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK (0x1146 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK (0x1148 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_FRAME_BLANKING_LINES (0x114a | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_MIN_LINE_LENGTH_PCK_STEP_SIZE 0x114c
-#define SMIAPP_REG_U16_MIN_OP_SYS_CLK_DIV (0x1160 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_OP_SYS_CLK_DIV (0x1162 | CCS_FL_16BIT)
-#define SMIAPP_REG_F32_MIN_OP_SYS_CLK_FREQ_HZ (0x1164 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_F32_MAX_OP_SYS_CLK_FREQ_HZ (0x1168 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_U16_MIN_OP_PIX_CLK_DIV (0x116c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_OP_PIX_CLK_DIV (0x116e | CCS_FL_16BIT)
-#define SMIAPP_REG_F32_MIN_OP_PIX_CLK_FREQ_HZ (0x1170 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_F32_MAX_OP_PIX_CLK_FREQ_HZ (0x1174 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT)
-#define SMIAPP_REG_U16_X_ADDR_MIN (0x1180 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_Y_ADDR_MIN (0x1182 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_X_ADDR_MAX (0x1184 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_Y_ADDR_MAX (0x1186 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_X_OUTPUT_SIZE (0x1188 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_Y_OUTPUT_SIZE (0x118a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_X_OUTPUT_SIZE (0x118c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_Y_OUTPUT_SIZE (0x118e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_EVEN_INC (0x11c0 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_EVEN_INC (0x11c2 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_ODD_INC (0x11c4 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_ODD_INC (0x11c6 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SCALING_CAPABILITY (0x1200 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SCALER_M_MIN (0x1204 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SCALER_M_MAX (0x1206 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SCALER_N_MIN (0x1208 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SCALER_N_MAX (0x120a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_SPATIAL_SAMPLING_CAPABILITY (0x120c | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_DIGITAL_CROP_CAPABILITY 0x120e
-#define SMIAPP_REG_U16_COMPRESSION_CAPABILITY (0x1300 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINRED (0x1400 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINRED (0x1402 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINRED (0x1404 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINGREEN (0x1406 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINGREEN (0x1408 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINGREEN (0x140a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINBLUE (0x140c | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINBLUE (0x140e | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINBLUE (0x1410 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FIFO_SIZE_PIXELS (0x1500 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_FIFO_SUPPORT_CAPABILITY 0x1502
-#define SMIAPP_REG_U8_DPHY_CTRL_CAPABILITY 0x1600
-#define SMIAPP_REG_U8_CSI_LANE_MODE_CAPABILITY 0x1601
-#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE_CAPABILITY 0x1602
-#define SMIAPP_REG_U8_FAST_STANDBY_CAPABILITY 0x1603
-#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL_CAPABILITY 0x1604
-#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS (0x1608 | CCS_FL_32BIT)
-#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS (0x160c | CCS_FL_32BIT)
-#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS (0x1610 | CCS_FL_32BIT)
-#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS (0x1614 | CCS_FL_32BIT)
-#define SMIAPP_REG_U8_TEMP_SENSOR_CAPABILITY 0x1618
-#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES_BIN (0x1700 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES_BIN (0x1702 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK_BIN (0x1704 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK_BIN (0x1706 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK_BIN (0x1708 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN_BIN (0x170a | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN (0x170c | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_BINNING_CAPABILITY 0x1710
-#define SMIAPP_REG_U8_BINNING_WEIGHTING_CAPABILITY 0x1711
-#define SMIAPP_REG_U8_BINNING_SUBTYPES 0x1712
-#define SMIAPP_REG_U8_BINNING_TYPE_n(n) (0x1713 + (n)) /* 1 <= n <= 237 */
-#define SMIAPP_REG_U8_DATA_TRANSFER_IF_CAPABILITY 0x1800
-#define SMIAPP_REG_U8_SHADING_CORRECTION_CAPABILITY 0x1900
-#define SMIAPP_REG_U8_GREEN_IMBALANCE_CAPABILITY 0x1901
-#define SMIAPP_REG_U8_BLACK_LEVEL_CAPABILITY 0x1902
-#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_CAPABILITY 0x1903
-#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY (0x1904 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY_2 (0x1906 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_EDOF_CAPABILITY 0x1980
-#define SMIAPP_REG_U8_ESTIMATION_FRAMES 0x1981
-#define SMIAPP_REG_U8_SUPPORTS_SHARPNESS_ADJ 0x1982
-#define SMIAPP_REG_U8_SUPPORTS_DENOISING_ADJ 0x1983
-#define SMIAPP_REG_U8_SUPPORTS_MODULE_SPECIFIC_ADJ 0x1984
-#define SMIAPP_REG_U8_SUPPORTS_DEPTH_OF_FIELD_ADJ 0x1985
-#define SMIAPP_REG_U8_SUPPORTS_FOCUS_DISTANCE_ADJ 0x1986
-#define SMIAPP_REG_U8_COLOUR_FEEDBACK_CAPABILITY 0x1987
-#define SMIAPP_REG_U8_EDOF_SUPPORT_AB_NXM 0x1988
-#define SMIAPP_REG_U8_ESTIMATION_MODE_CAPABILITY 0x19c0
-#define SMIAPP_REG_U8_ESTIMATION_ZONE_CAPABILITY 0x19c1
-#define SMIAPP_REG_U16_EST_DEPTH_OF_FIELD (0x19c2 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_EST_FOCUS_DISTANCE (0x19c4 | CCS_FL_16BIT)
-#define SMIAPP_REG_U16_CAPABILITY_TRDY_MIN (0x1a00 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_FLASH_MODE_CAPABILITY 0x1a02
-#define SMIAPP_REG_U16_MECH_SHUT_AND_ACT_START_ADDR (0x1b02 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_ACTUATOR_CAPABILITY 0x1b04
-#define SMIAPP_REG_U16_ACTUATOR_TYPE (0x1b40 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_AF_DEVICE_ADDRESS 0x1b42
-#define SMIAPP_REG_U16_FOCUS_CHANGE_ADDRESS (0x1b44 | CCS_FL_16BIT)
-#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_1 0x1c00
-#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_2 0x1c01
-#define SMIAPP_REG_U8_BRACKETING_LUT_SIZE 0x1c02
+#define SMIAPP_REG_U16_MODEL_ID CCI_REG16(0x0000)
+#define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR CCI_REG8(0x0002)
+#define SMIAPP_REG_U8_MANUFACTURER_ID CCI_REG8(0x0003)
+#define SMIAPP_REG_U8_SMIA_VERSION CCI_REG8(0x0004)
+#define SMIAPP_REG_U8_FRAME_COUNT CCI_REG8(0x0005)
+#define SMIAPP_REG_U8_PIXEL_ORDER CCI_REG8(0x0006)
+#define SMIAPP_REG_U16_DATA_PEDESTAL CCI_REG16(0x0008)
+#define SMIAPP_REG_U8_PIXEL_DEPTH CCI_REG8(0x000c)
+#define SMIAPP_REG_U8_REVISION_NUMBER_MINOR CCI_REG8(0x0010)
+#define SMIAPP_REG_U8_SMIAPP_VERSION CCI_REG8(0x0011)
+#define SMIAPP_REG_U8_MODULE_DATE_YEAR CCI_REG8(0x0012)
+#define SMIAPP_REG_U8_MODULE_DATE_MONTH CCI_REG8(0x0013)
+#define SMIAPP_REG_U8_MODULE_DATE_DAY CCI_REG8(0x0014)
+#define SMIAPP_REG_U8_MODULE_DATE_PHASE CCI_REG8(0x0015)
+#define SMIAPP_REG_U16_SENSOR_MODEL_ID CCI_REG16(0x0016)
+#define SMIAPP_REG_U8_SENSOR_REVISION_NUMBER CCI_REG8(0x0018)
+#define SMIAPP_REG_U8_SENSOR_MANUFACTURER_ID CCI_REG8(0x0019)
+#define SMIAPP_REG_U8_SENSOR_FIRMWARE_VERSION CCI_REG8(0x001a)
+#define SMIAPP_REG_U32_SERIAL_NUMBER CCI_REG32(0x001c)
+#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE CCI_REG8(0x0040)
+#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_SUBTYPE CCI_REG8(0x0041)
+#define SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(n) CCI_REG16(0x0042 + ((n) << 1)) /* 0 <= n <= 14 */
+#define SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(n) CCI_REG32(0x0060 + ((n) << 2)) /* 0 <= n <= 7 */
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CAPABILITY CCI_REG16(0x0080)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MIN CCI_REG16(0x0084)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MAX CCI_REG16(0x0086)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_STEP CCI_REG16(0x0088)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_TYPE CCI_REG16(0x008a)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_M0 CCI_REG16(0x008c)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_C0 CCI_REG16(0x008e)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_M1 CCI_REG16(0x0090)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_C1 CCI_REG16(0x0092)
+#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_TYPE CCI_REG8(0x00c0)
+#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_SUBTYPE CCI_REG8(0x00c1)
+#define SMIAPP_REG_U16_DATA_FORMAT_DESCRIPTOR(n) CCI_REG16(0x00c2 + ((n) << 1))
+#define SMIAPP_REG_U8_MODE_SELECT CCI_REG8(0x0100)
+#define SMIAPP_REG_U8_IMAGE_ORIENTATION CCI_REG8(0x0101)
+#define SMIAPP_REG_U8_SOFTWARE_RESET CCI_REG8(0x0103)
+#define SMIAPP_REG_U8_GROUPED_PARAMETER_HOLD CCI_REG8(0x0104)
+#define SMIAPP_REG_U8_MASK_CORRUPTED_FRAMES CCI_REG8(0x0105)
+#define SMIAPP_REG_U8_FAST_STANDBY_CTRL CCI_REG8(0x0106)
+#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL CCI_REG8(0x0107)
+#define SMIAPP_REG_U8_2ND_CCI_IF_CONTROL CCI_REG8(0x0108)
+#define SMIAPP_REG_U8_2ND_CCI_ADDRESS_CONTROL CCI_REG8(0x0109)
+#define SMIAPP_REG_U8_CSI_CHANNEL_IDENTIFIER CCI_REG8(0x0110)
+#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE CCI_REG8(0x0111)
+#define SMIAPP_REG_U16_CSI_DATA_FORMAT CCI_REG16(0x0112)
+#define SMIAPP_REG_U8_CSI_LANE_MODE CCI_REG8(0x0114)
+#define SMIAPP_REG_U8_CSI2_10_TO_8_DT CCI_REG8(0x0115)
+#define SMIAPP_REG_U8_CSI2_10_TO_7_DT CCI_REG8(0x0116)
+#define SMIAPP_REG_U8_CSI2_10_TO_6_DT CCI_REG8(0x0117)
+#define SMIAPP_REG_U8_CSI2_12_TO_8_DT CCI_REG8(0x0118)
+#define SMIAPP_REG_U8_CSI2_12_TO_7_DT CCI_REG8(0x0119)
+#define SMIAPP_REG_U8_CSI2_12_TO_6_DT CCI_REG8(0x011a)
+#define SMIAPP_REG_U8_CSI2_14_TO_10_DT CCI_REG8(0x011b)
+#define SMIAPP_REG_U8_CSI2_14_TO_8_DT CCI_REG8(0x011c)
+#define SMIAPP_REG_U8_CSI2_16_TO_10_DT CCI_REG8(0x011d)
+#define SMIAPP_REG_U8_CSI2_16_TO_8_DT CCI_REG8(0x011e)
+#define SMIAPP_REG_U8_GAIN_MODE CCI_REG8(0x0120)
+#define SMIAPP_REG_U16_VANA_VOLTAGE CCI_REG16(0x0130)
+#define SMIAPP_REG_U16_VDIG_VOLTAGE CCI_REG16(0x0132)
+#define SMIAPP_REG_U16_VIO_VOLTAGE CCI_REG16(0x0134)
+#define SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ CCI_REG16(0x0136)
+#define SMIAPP_REG_U8_TEMP_SENSOR_CONTROL CCI_REG8(0x0138)
+#define SMIAPP_REG_U8_TEMP_SENSOR_MODE CCI_REG8(0x0139)
+#define SMIAPP_REG_U8_TEMP_SENSOR_OUTPUT CCI_REG8(0x013a)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME CCI_REG16(0x0200)
+#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME CCI_REG16(0x0202)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL CCI_REG16(0x0204)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENR CCI_REG16(0x0206)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_RED CCI_REG16(0x0208)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_BLUE CCI_REG16(0x020a)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENB CCI_REG16(0x020c)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENR CCI_REG16(0x020e)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_RED CCI_REG16(0x0210)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_BLUE CCI_REG16(0x0212)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENB CCI_REG16(0x0214)
+#define SMIAPP_REG_U16_VT_PIX_CLK_DIV CCI_REG16(0x0300)
+#define SMIAPP_REG_U16_VT_SYS_CLK_DIV CCI_REG16(0x0302)
+#define SMIAPP_REG_U16_PRE_PLL_CLK_DIV CCI_REG16(0x0304)
+#define SMIAPP_REG_U16_PLL_MULTIPLIER CCI_REG16(0x0306)
+#define SMIAPP_REG_U16_OP_PIX_CLK_DIV CCI_REG16(0x0308)
+#define SMIAPP_REG_U16_OP_SYS_CLK_DIV CCI_REG16(0x030a)
+#define SMIAPP_REG_U16_FRAME_LENGTH_LINES CCI_REG16(0x0340)
+#define SMIAPP_REG_U16_LINE_LENGTH_PCK CCI_REG16(0x0342)
+#define SMIAPP_REG_U16_X_ADDR_START CCI_REG16(0x0344)
+#define SMIAPP_REG_U16_Y_ADDR_START CCI_REG16(0x0346)
+#define SMIAPP_REG_U16_X_ADDR_END CCI_REG16(0x0348)
+#define SMIAPP_REG_U16_Y_ADDR_END CCI_REG16(0x034a)
+#define SMIAPP_REG_U16_X_OUTPUT_SIZE CCI_REG16(0x034c)
+#define SMIAPP_REG_U16_Y_OUTPUT_SIZE CCI_REG16(0x034e)
+#define SMIAPP_REG_U16_X_EVEN_INC CCI_REG16(0x0380)
+#define SMIAPP_REG_U16_X_ODD_INC CCI_REG16(0x0382)
+#define SMIAPP_REG_U16_Y_EVEN_INC CCI_REG16(0x0384)
+#define SMIAPP_REG_U16_Y_ODD_INC CCI_REG16(0x0386)
+#define SMIAPP_REG_U16_SCALING_MODE CCI_REG16(0x0400)
+#define SMIAPP_REG_U16_SPATIAL_SAMPLING CCI_REG16(0x0402)
+#define SMIAPP_REG_U16_SCALE_M CCI_REG16(0x0404)
+#define SMIAPP_REG_U16_SCALE_N CCI_REG16(0x0406)
+#define SMIAPP_REG_U16_DIGITAL_CROP_X_OFFSET CCI_REG16(0x0408)
+#define SMIAPP_REG_U16_DIGITAL_CROP_Y_OFFSET CCI_REG16(0x040a)
+#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_WIDTH CCI_REG16(0x040c)
+#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_HEIGHT CCI_REG16(0x040e)
+#define SMIAPP_REG_U16_COMPRESSION_MODE CCI_REG16(0x0500)
+#define SMIAPP_REG_U16_TEST_PATTERN_MODE CCI_REG16(0x0600)
+#define SMIAPP_REG_U16_TEST_DATA_RED CCI_REG16(0x0602)
+#define SMIAPP_REG_U16_TEST_DATA_GREENR CCI_REG16(0x0604)
+#define SMIAPP_REG_U16_TEST_DATA_BLUE CCI_REG16(0x0606)
+#define SMIAPP_REG_U16_TEST_DATA_GREENB CCI_REG16(0x0608)
+#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_WIDTH CCI_REG16(0x060a)
+#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_POSITION CCI_REG16(0x060c)
+#define SMIAPP_REG_U16_VERTICAL_CURSOR_WIDTH CCI_REG16(0x060e)
+#define SMIAPP_REG_U16_VERTICAL_CURSOR_POSITION CCI_REG16(0x0610)
+#define SMIAPP_REG_U16_FIFO_WATER_MARK_PIXELS CCI_REG16(0x0700)
+#define SMIAPP_REG_U8_TCLK_POST CCI_REG8(0x0800)
+#define SMIAPP_REG_U8_THS_PREPARE CCI_REG8(0x0801)
+#define SMIAPP_REG_U8_THS_ZERO_MIN CCI_REG8(0x0802)
+#define SMIAPP_REG_U8_THS_TRAIL CCI_REG8(0x0803)
+#define SMIAPP_REG_U8_TCLK_TRAIL_MIN CCI_REG8(0x0804)
+#define SMIAPP_REG_U8_TCLK_PREPARE CCI_REG8(0x0805)
+#define SMIAPP_REG_U8_TCLK_ZERO CCI_REG8(0x0806)
+#define SMIAPP_REG_U8_TLPX CCI_REG8(0x0807)
+#define SMIAPP_REG_U8_DPHY_CTRL CCI_REG8(0x0808)
+#define SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS CCI_REG32(0x0820)
+#define SMIAPP_REG_U8_BINNING_MODE CCI_REG8(0x0900)
+#define SMIAPP_REG_U8_BINNING_TYPE CCI_REG8(0x0901)
+#define SMIAPP_REG_U8_BINNING_WEIGHTING CCI_REG8(0x0902)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL CCI_REG8(0x0a00)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS CCI_REG8(0x0a01)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT CCI_REG8(0x0a02)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_0 CCI_REG8(0x0a04)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_1 CCI_REG8(0x0a05)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_2 CCI_REG8(0x0a06)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_3 CCI_REG8(0x0a07)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_4 CCI_REG8(0x0a08)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_5 CCI_REG8(0x0a09)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_12 CCI_REG8(0x0a10)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_13 CCI_REG8(0x0a11)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_14 CCI_REG8(0x0a12)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_15 CCI_REG8(0x0a13)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_16 CCI_REG8(0x0a14)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_17 CCI_REG8(0x0a15)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_18 CCI_REG8(0x0a16)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_19 CCI_REG8(0x0a17)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_20 CCI_REG8(0x0a18)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_21 CCI_REG8(0x0a19)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_22 CCI_REG8(0x0a1a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_23 CCI_REG8(0x0a1b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_24 CCI_REG8(0x0a1c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_25 CCI_REG8(0x0a1d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_26 CCI_REG8(0x0a1e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_27 CCI_REG8(0x0a1f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_28 CCI_REG8(0x0a20)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_29 CCI_REG8(0x0a21)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_30 CCI_REG8(0x0a22)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_31 CCI_REG8(0x0a23)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_32 CCI_REG8(0x0a24)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_33 CCI_REG8(0x0a25)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_34 CCI_REG8(0x0a26)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_35 CCI_REG8(0x0a27)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_36 CCI_REG8(0x0a28)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_37 CCI_REG8(0x0a29)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_38 CCI_REG8(0x0a2a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_39 CCI_REG8(0x0a2b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_40 CCI_REG8(0x0a2c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_41 CCI_REG8(0x0a2d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_42 CCI_REG8(0x0a2e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_43 CCI_REG8(0x0a2f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_44 CCI_REG8(0x0a30)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_45 CCI_REG8(0x0a31)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_46 CCI_REG8(0x0a32)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_47 CCI_REG8(0x0a33)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_48 CCI_REG8(0x0a34)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_49 CCI_REG8(0x0a35)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_50 CCI_REG8(0x0a36)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_51 CCI_REG8(0x0a37)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_52 CCI_REG8(0x0a38)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_53 CCI_REG8(0x0a39)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_54 CCI_REG8(0x0a3a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_55 CCI_REG8(0x0a3b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_56 CCI_REG8(0x0a3c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_57 CCI_REG8(0x0a3d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_58 CCI_REG8(0x0a3e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_59 CCI_REG8(0x0a3f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_60 CCI_REG8(0x0a40)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_61 CCI_REG8(0x0a41)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_62 CCI_REG8(0x0a42)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_63 CCI_REG8(0x0a43)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_CTRL CCI_REG8(0x0a44)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_STATUS CCI_REG8(0x0a45)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_PAGE_SELECT CCI_REG8(0x0a46)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_0 CCI_REG8(0x0a48)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_1 CCI_REG8(0x0a49)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_2 CCI_REG8(0x0a4a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_3 CCI_REG8(0x0a4b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_4 CCI_REG8(0x0a4c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_5 CCI_REG8(0x0a4d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_6 CCI_REG8(0x0a4e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_7 CCI_REG8(0x0a4f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_8 CCI_REG8(0x0a50)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_9 CCI_REG8(0x0a51)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_10 CCI_REG8(0x0a52)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_11 CCI_REG8(0x0a53)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_12 CCI_REG8(0x0a54)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_13 CCI_REG8(0x0a55)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_14 CCI_REG8(0x0a56)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_15 CCI_REG8(0x0a57)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_16 CCI_REG8(0x0a58)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_17 CCI_REG8(0x0a59)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_18 CCI_REG8(0x0a5a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_19 CCI_REG8(0x0a5b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_20 CCI_REG8(0x0a5c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_21 CCI_REG8(0x0a5d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_22 CCI_REG8(0x0a5e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_23 CCI_REG8(0x0a5f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_24 CCI_REG8(0x0a60)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_25 CCI_REG8(0x0a61)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_26 CCI_REG8(0x0a62)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_27 CCI_REG8(0x0a63)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_28 CCI_REG8(0x0a64)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_29 CCI_REG8(0x0a65)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_30 CCI_REG8(0x0a66)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_31 CCI_REG8(0x0a67)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_32 CCI_REG8(0x0a68)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_33 CCI_REG8(0x0a69)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_34 CCI_REG8(0x0a6a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_35 CCI_REG8(0x0a6b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_36 CCI_REG8(0x0a6c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_37 CCI_REG8(0x0a6d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_38 CCI_REG8(0x0a6e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_39 CCI_REG8(0x0a6f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_40 CCI_REG8(0x0a70)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_41 CCI_REG8(0x0a71)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_42 CCI_REG8(0x0a72)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_43 CCI_REG8(0x0a73)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_44 CCI_REG8(0x0a74)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_45 CCI_REG8(0x0a75)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_46 CCI_REG8(0x0a76)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_47 CCI_REG8(0x0a77)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_48 CCI_REG8(0x0a78)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_49 CCI_REG8(0x0a79)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_50 CCI_REG8(0x0a7a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_51 CCI_REG8(0x0a7b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_52 CCI_REG8(0x0a7c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_53 CCI_REG8(0x0a7d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_54 CCI_REG8(0x0a7e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_55 CCI_REG8(0x0a7f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_56 CCI_REG8(0x0a80)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_57 CCI_REG8(0x0a81)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_58 CCI_REG8(0x0a82)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_59 CCI_REG8(0x0a83)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_60 CCI_REG8(0x0a84)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_61 CCI_REG8(0x0a85)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_62 CCI_REG8(0x0a86)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_63 CCI_REG8(0x0a87)
+#define SMIAPP_REG_U8_SHADING_CORRECTION_ENABLE CCI_REG8(0x0b00)
+#define SMIAPP_REG_U8_LUMINANCE_CORRECTION_LEVEL CCI_REG8(0x0b01)
+#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_ENABLE CCI_REG8(0x0b02)
+#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_WEIGHT CCI_REG8(0x0b03)
+#define SMIAPP_REG_U8_BLACK_LEVEL_CORRECTION_ENABLE CCI_REG8(0x0b04)
+#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ENABLE CCI_REG8(0x0b05)
+#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_ENABLE CCI_REG8(0x0b06)
+#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_WEIGHT CCI_REG8(0x0b07)
+#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_ENABLE CCI_REG8(0x0b08)
+#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_WEIGHT CCI_REG8(0x0b09)
+#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_ENABLE CCI_REG8(0x0b0a)
+#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_WEIGHT CCI_REG8(0x0b0b)
+#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_ENABLE CCI_REG8(0x0b0c)
+#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_WEIGHT CCI_REG8(0x0b0d)
+#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ENABLE CCI_REG8(0x0b0e)
+#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ADJUST CCI_REG8(0x0b0f)
+#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ADJUST CCI_REG8(0x0b10)
+#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ENABLE CCI_REG8(0x0b11)
+#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ADJUST CCI_REG8(0x0b12)
+#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ENABLE CCI_REG8(0x0b13)
+#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ADJUST CCI_REG8(0x0b14)
+#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ENABLE CCI_REG8(0x0b15)
+#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ADJUST CCI_REG8(0x0b16)
+#define SMIAPP_REG_U8_EDOF_MODE CCI_REG8(0x0b80)
+#define SMIAPP_REG_U8_SHARPNESS CCI_REG8(0x0b83)
+#define SMIAPP_REG_U8_DENOISING CCI_REG8(0x0b84)
+#define SMIAPP_REG_U8_MODULE_SPECIFIC CCI_REG8(0x0b85)
+#define SMIAPP_REG_U16_DEPTH_OF_FIELD CCI_REG16(0x0b86)
+#define SMIAPP_REG_U16_FOCUS_DISTANCE CCI_REG16(0x0b88)
+#define SMIAPP_REG_U8_ESTIMATION_MODE_CTRL CCI_REG8(0x0b8a)
+#define SMIAPP_REG_U16_COLOUR_TEMPERATURE CCI_REG16(0x0b8c)
+#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENR CCI_REG16(0x0b8e)
+#define SMIAPP_REG_U16_ABSOLUTE_GAIN_RED CCI_REG16(0x0b90)
+#define SMIAPP_REG_U16_ABSOLUTE_GAIN_BLUE CCI_REG16(0x0b92)
+#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENB CCI_REG16(0x0b94)
+#define SMIAPP_REG_U8_ESTIMATION_ZONE_MODE CCI_REG8(0x0bc0)
+#define SMIAPP_REG_U16_FIXED_ZONE_WEIGHTING CCI_REG16(0x0bc2)
+#define SMIAPP_REG_U16_CUSTOM_ZONE_X_START CCI_REG16(0x0bc4)
+#define SMIAPP_REG_U16_CUSTOM_ZONE_Y_START CCI_REG16(0x0bc6)
+#define SMIAPP_REG_U16_CUSTOM_ZONE_WIDTH CCI_REG16(0x0bc8)
+#define SMIAPP_REG_U16_CUSTOM_ZONE_HEIGHT CCI_REG16(0x0bca)
+#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL1 CCI_REG8(0x0c00)
+#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL2 CCI_REG8(0x0c01)
+#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_1 CCI_REG8(0x0c02)
+#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_2 CCI_REG8(0x0c03)
+#define SMIAPP_REG_U16_TRDY_CTRL CCI_REG16(0x0c04)
+#define SMIAPP_REG_U16_TRDOUT_CTRL CCI_REG16(0x0c06)
+#define SMIAPP_REG_U16_TSHUTTER_STROBE_DELAY_CTRL CCI_REG16(0x0c08)
+#define SMIAPP_REG_U16_TSHUTTER_STROBE_WIDTH_CTRL CCI_REG16(0x0c0a)
+#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_CTRL CCI_REG16(0x0c0c)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_CTRL CCI_REG16(0x0c0e)
+#define SMIAPP_REG_U16_TGRST_INTERVAL_CTRL CCI_REG16(0x0c10)
+#define SMIAPP_REG_U8_FLASH_STROBE_ADJUSTMENT CCI_REG8(0x0c12)
+#define SMIAPP_REG_U16_FLASH_STROBE_START_POINT CCI_REG16(0x0c14)
+#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_RS_CTRL CCI_REG16(0x0c16)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL CCI_REG16(0x0c18)
+#define SMIAPP_REG_U8_FLASH_MODE_RS CCI_REG8(0x0c1a)
+#define SMIAPP_REG_U8_FLASH_TRIGGER_RS CCI_REG8(0x0c1b)
+#define SMIAPP_REG_U8_FLASH_STATUS CCI_REG8(0x0c1c)
+#define SMIAPP_REG_U8_SA_STROBE_MODE CCI_REG8(0x0c1d)
+#define SMIAPP_REG_U16_SA_STROBE_START_POINT CCI_REG16(0x0c1e)
+#define SMIAPP_REG_U16_TSA_STROBE_DELAY_CTRL CCI_REG16(0x0c20)
+#define SMIAPP_REG_U16_TSA_STROBE_WIDTH_CTRL CCI_REG16(0x0c22)
+#define SMIAPP_REG_U8_SA_STROBE_TRIGGER CCI_REG8(0x0c24)
+#define SMIAPP_REG_U8_SPECIAL_ACTUATOR_STATUS CCI_REG8(0x0c25)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_RS_CTRL CCI_REG16(0x0c26)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_RS_CTRL CCI_REG16(0x0c28)
+#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_RS_CTRL CCI_REG8(0x0c2a)
+#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_CTRL CCI_REG8(0x0c2b)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_CTRL CCI_REG16(0x0c2c)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_CTRL CCI_REG16(0x0c2e)
+#define SMIAPP_REG_U8_LOW_LEVEL_CTRL CCI_REG8(0x0c80)
+#define SMIAPP_REG_U16_MAIN_TRIGGER_REF_POINT CCI_REG16(0x0c82)
+#define SMIAPP_REG_U16_MAIN_TRIGGER_T3 CCI_REG16(0x0c84)
+#define SMIAPP_REG_U8_MAIN_TRIGGER_COUNT CCI_REG8(0x0c86)
+#define SMIAPP_REG_U16_PHASE1_TRIGGER_T3 CCI_REG16(0x0c88)
+#define SMIAPP_REG_U8_PHASE1_TRIGGER_COUNT CCI_REG8(0x0c8a)
+#define SMIAPP_REG_U16_PHASE2_TRIGGER_T3 CCI_REG16(0x0c8c)
+#define SMIAPP_REG_U8_PHASE2_TRIGGER_COUNT CCI_REG8(0x0c8e)
+#define SMIAPP_REG_U8_MECH_SHUTTER_CTRL CCI_REG8(0x0d00)
+#define SMIAPP_REG_U8_OPERATION_MODE CCI_REG8(0x0d01)
+#define SMIAPP_REG_U8_ACT_STATE1 CCI_REG8(0x0d02)
+#define SMIAPP_REG_U8_ACT_STATE2 CCI_REG8(0x0d03)
+#define SMIAPP_REG_U16_FOCUS_CHANGE CCI_REG16(0x0d80)
+#define SMIAPP_REG_U16_FOCUS_CHANGE_CONTROL CCI_REG16(0x0d82)
+#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE1 CCI_REG16(0x0d84)
+#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE2 CCI_REG16(0x0d86)
+#define SMIAPP_REG_U8_STROBE_COUNT_PHASE1 CCI_REG8(0x0d88)
+#define SMIAPP_REG_U8_STROBE_COUNT_PHASE2 CCI_REG8(0x0d89)
+#define SMIAPP_REG_U8_POSITION CCI_REG8(0x0d8a)
+#define SMIAPP_REG_U8_BRACKETING_LUT_CONTROL CCI_REG8(0x0e00)
+#define SMIAPP_REG_U8_BRACKETING_LUT_MODE CCI_REG8(0x0e01)
+#define SMIAPP_REG_U8_BRACKETING_LUT_ENTRY_CONTROL CCI_REG8(0x0e02)
+#define SMIAPP_REG_U8_LUT_PARAMETERS_START CCI_REG8(0x0e10)
+#define SMIAPP_REG_U8_LUT_PARAMETERS_END CCI_REG8(0x0eff)
+#define SMIAPP_REG_U16_INTEGRATION_TIME_CAPABILITY CCI_REG16(0x1000)
+#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MIN CCI_REG16(0x1004)
+#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MAX_MARGIN CCI_REG16(0x1006)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN CCI_REG16(0x1008)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN CCI_REG16(0x100a)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_CAPABILITY CCI_REG16(0x1080)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_MIN CCI_REG16(0x1084)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_MAX CCI_REG16(0x1086)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_STEP_SIZE CCI_REG16(0x1088)
+#define SMIAPP_REG_F32_MIN_EXT_CLK_FREQ_HZ (CCI_REG32(0x1100) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_F32_MAX_EXT_CLK_FREQ_HZ (CCI_REG32(0x1104) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_U16_MIN_PRE_PLL_CLK_DIV CCI_REG16(0x1108)
+#define SMIAPP_REG_U16_MAX_PRE_PLL_CLK_DIV CCI_REG16(0x110a)
+#define SMIAPP_REG_F32_MIN_PLL_IP_FREQ_HZ (CCI_REG32(0x110c) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_F32_MAX_PLL_IP_FREQ_HZ (CCI_REG32(0x1110) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_U16_MIN_PLL_MULTIPLIER CCI_REG16(0x1114)
+#define SMIAPP_REG_U16_MAX_PLL_MULTIPLIER CCI_REG16(0x1116)
+#define SMIAPP_REG_F32_MIN_PLL_OP_FREQ_HZ (CCI_REG32(0x1118) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_F32_MAX_PLL_OP_FREQ_HZ (CCI_REG32(0x111c) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_U16_MIN_VT_SYS_CLK_DIV CCI_REG16(0x1120)
+#define SMIAPP_REG_U16_MAX_VT_SYS_CLK_DIV CCI_REG16(0x1122)
+#define SMIAPP_REG_F32_MIN_VT_SYS_CLK_FREQ_HZ (CCI_REG32(0x1124) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_F32_MAX_VT_SYS_CLK_FREQ_HZ (CCI_REG32(0x1128) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_F32_MIN_VT_PIX_CLK_FREQ_HZ (CCI_REG32(0x112c) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_F32_MAX_VT_PIX_CLK_FREQ_HZ (CCI_REG32(0x1130) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_U16_MIN_VT_PIX_CLK_DIV CCI_REG16(0x1134)
+#define SMIAPP_REG_U16_MAX_VT_PIX_CLK_DIV CCI_REG16(0x1136)
+#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES CCI_REG16(0x1140)
+#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES CCI_REG16(0x1142)
+#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK CCI_REG16(0x1144)
+#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK CCI_REG16(0x1146)
+#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK CCI_REG16(0x1148)
+#define SMIAPP_REG_U16_MIN_FRAME_BLANKING_LINES CCI_REG16(0x114a)
+#define SMIAPP_REG_U8_MIN_LINE_LENGTH_PCK_STEP_SIZE CCI_REG8(0x114c)
+#define SMIAPP_REG_U16_MIN_OP_SYS_CLK_DIV CCI_REG16(0x1160)
+#define SMIAPP_REG_U16_MAX_OP_SYS_CLK_DIV CCI_REG16(0x1162)
+#define SMIAPP_REG_F32_MIN_OP_SYS_CLK_FREQ_HZ (CCI_REG32(0x1164) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_F32_MAX_OP_SYS_CLK_FREQ_HZ (CCI_REG32(0x1168) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_U16_MIN_OP_PIX_CLK_DIV CCI_REG16(0x116c)
+#define SMIAPP_REG_U16_MAX_OP_PIX_CLK_DIV CCI_REG16(0x116e)
+#define SMIAPP_REG_F32_MIN_OP_PIX_CLK_FREQ_HZ (CCI_REG32(0x1170) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_F32_MAX_OP_PIX_CLK_FREQ_HZ (CCI_REG32(0x1174) | CCS_FL_FLOAT_IREAL)
+#define SMIAPP_REG_U16_X_ADDR_MIN CCI_REG16(0x1180)
+#define SMIAPP_REG_U16_Y_ADDR_MIN CCI_REG16(0x1182)
+#define SMIAPP_REG_U16_X_ADDR_MAX CCI_REG16(0x1184)
+#define SMIAPP_REG_U16_Y_ADDR_MAX CCI_REG16(0x1186)
+#define SMIAPP_REG_U16_MIN_X_OUTPUT_SIZE CCI_REG16(0x1188)
+#define SMIAPP_REG_U16_MIN_Y_OUTPUT_SIZE CCI_REG16(0x118a)
+#define SMIAPP_REG_U16_MAX_X_OUTPUT_SIZE CCI_REG16(0x118c)
+#define SMIAPP_REG_U16_MAX_Y_OUTPUT_SIZE CCI_REG16(0x118e)
+#define SMIAPP_REG_U16_MIN_EVEN_INC CCI_REG16(0x11c0)
+#define SMIAPP_REG_U16_MAX_EVEN_INC CCI_REG16(0x11c2)
+#define SMIAPP_REG_U16_MIN_ODD_INC CCI_REG16(0x11c4)
+#define SMIAPP_REG_U16_MAX_ODD_INC CCI_REG16(0x11c6)
+#define SMIAPP_REG_U16_SCALING_CAPABILITY CCI_REG16(0x1200)
+#define SMIAPP_REG_U16_SCALER_M_MIN CCI_REG16(0x1204)
+#define SMIAPP_REG_U16_SCALER_M_MAX CCI_REG16(0x1206)
+#define SMIAPP_REG_U16_SCALER_N_MIN CCI_REG16(0x1208)
+#define SMIAPP_REG_U16_SCALER_N_MAX CCI_REG16(0x120a)
+#define SMIAPP_REG_U16_SPATIAL_SAMPLING_CAPABILITY CCI_REG16(0x120c)
+#define SMIAPP_REG_U8_DIGITAL_CROP_CAPABILITY CCI_REG8(0x120e)
+#define SMIAPP_REG_U16_COMPRESSION_CAPABILITY CCI_REG16(0x1300)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINRED CCI_REG16(0x1400)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINRED CCI_REG16(0x1402)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINRED CCI_REG16(0x1404)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINGREEN CCI_REG16(0x1406)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINGREEN CCI_REG16(0x1408)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINGREEN CCI_REG16(0x140a)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINBLUE CCI_REG16(0x140c)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINBLUE CCI_REG16(0x140e)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINBLUE CCI_REG16(0x1410)
+#define SMIAPP_REG_U16_FIFO_SIZE_PIXELS CCI_REG16(0x1500)
+#define SMIAPP_REG_U8_FIFO_SUPPORT_CAPABILITY CCI_REG8(0x1502)
+#define SMIAPP_REG_U8_DPHY_CTRL_CAPABILITY CCI_REG8(0x1600)
+#define SMIAPP_REG_U8_CSI_LANE_MODE_CAPABILITY CCI_REG8(0x1601)
+#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE_CAPABILITY CCI_REG8(0x1602)
+#define SMIAPP_REG_U8_FAST_STANDBY_CAPABILITY CCI_REG8(0x1603)
+#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL_CAPABILITY CCI_REG8(0x1604)
+#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS CCI_REG32(0x1608)
+#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS CCI_REG32(0x160c)
+#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS CCI_REG32(0x1610)
+#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS CCI_REG32(0x1614)
+#define SMIAPP_REG_U8_TEMP_SENSOR_CAPABILITY CCI_REG8(0x1618)
+#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES_BIN CCI_REG16(0x1700)
+#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES_BIN CCI_REG16(0x1702)
+#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK_BIN CCI_REG16(0x1704)
+#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK_BIN CCI_REG16(0x1706)
+#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK_BIN CCI_REG16(0x1708)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN_BIN CCI_REG16(0x170a)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN CCI_REG16(0x170c)
+#define SMIAPP_REG_U8_BINNING_CAPABILITY CCI_REG8(0x1710)
+#define SMIAPP_REG_U8_BINNING_WEIGHTING_CAPABILITY CCI_REG8(0x1711)
+#define SMIAPP_REG_U8_BINNING_SUBTYPES CCI_REG8(0x1712)
+#define SMIAPP_REG_U8_BINNING_TYPE_n(n) CCI_REG8(0x1713 + (n)) /* 1 <= n <= 237 */
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_CAPABILITY CCI_REG8(0x1800)
+#define SMIAPP_REG_U8_SHADING_CORRECTION_CAPABILITY CCI_REG8(0x1900)
+#define SMIAPP_REG_U8_GREEN_IMBALANCE_CAPABILITY CCI_REG8(0x1901)
+#define SMIAPP_REG_U8_BLACK_LEVEL_CAPABILITY CCI_REG8(0x1902)
+#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_CAPABILITY CCI_REG8(0x1903)
+#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY CCI_REG16(0x1904)
+#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY_2 CCI_REG16(0x1906)
+#define SMIAPP_REG_U8_EDOF_CAPABILITY CCI_REG8(0x1980)
+#define SMIAPP_REG_U8_ESTIMATION_FRAMES CCI_REG8(0x1981)
+#define SMIAPP_REG_U8_SUPPORTS_SHARPNESS_ADJ CCI_REG8(0x1982)
+#define SMIAPP_REG_U8_SUPPORTS_DENOISING_ADJ CCI_REG8(0x1983)
+#define SMIAPP_REG_U8_SUPPORTS_MODULE_SPECIFIC_ADJ CCI_REG8(0x1984)
+#define SMIAPP_REG_U8_SUPPORTS_DEPTH_OF_FIELD_ADJ CCI_REG8(0x1985)
+#define SMIAPP_REG_U8_SUPPORTS_FOCUS_DISTANCE_ADJ CCI_REG8(0x1986)
+#define SMIAPP_REG_U8_COLOUR_FEEDBACK_CAPABILITY CCI_REG8(0x1987)
+#define SMIAPP_REG_U8_EDOF_SUPPORT_AB_NXM CCI_REG8(0x1988)
+#define SMIAPP_REG_U8_ESTIMATION_MODE_CAPABILITY CCI_REG8(0x19c0)
+#define SMIAPP_REG_U8_ESTIMATION_ZONE_CAPABILITY CCI_REG8(0x19c1)
+#define SMIAPP_REG_U16_EST_DEPTH_OF_FIELD CCI_REG16(0x19c2)
+#define SMIAPP_REG_U16_EST_FOCUS_DISTANCE CCI_REG16(0x19c4)
+#define SMIAPP_REG_U16_CAPABILITY_TRDY_MIN CCI_REG16(0x1a00)
+#define SMIAPP_REG_U8_FLASH_MODE_CAPABILITY CCI_REG8(0x1a02)
+#define SMIAPP_REG_U16_MECH_SHUT_AND_ACT_START_ADDR CCI_REG16(0x1b02)
+#define SMIAPP_REG_U8_ACTUATOR_CAPABILITY CCI_REG8(0x1b04)
+#define SMIAPP_REG_U16_ACTUATOR_TYPE CCI_REG16(0x1b40)
+#define SMIAPP_REG_U8_AF_DEVICE_ADDRESS CCI_REG8(0x1b42)
+#define SMIAPP_REG_U16_FOCUS_CHANGE_ADDRESS CCI_REG16(0x1b44)
+#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_1 CCI_REG8(0x1c00)
+#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_2 CCI_REG8(0x1c01)
+#define SMIAPP_REG_U8_BRACKETING_LUT_SIZE CCI_REG8(0x1c02)
/* Register bit definitions */
#define SMIAPP_IMAGE_ORIENTATION_HFLIP BIT(0)
diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c
index 8e9ebed09f..ca9bb29dab 100644
--- a/drivers/media/i2c/ds90ub913.c
+++ b/drivers/media/i2c/ds90ub913.c
@@ -424,8 +424,7 @@ static int ub913_set_fmt(struct v4l2_subdev *sd,
}
/* Set sink format */
- fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
- format->stream);
+ fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
if (!fmt)
return -EINVAL;
@@ -444,8 +443,8 @@ static int ub913_set_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int ub913_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int ub913_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_subdev_route routes[] = {
{
@@ -504,7 +503,6 @@ static const struct v4l2_subdev_pad_ops ub913_pad_ops = {
.get_frame_desc = ub913_get_frame_desc,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ub913_set_fmt,
- .init_cfg = ub913_init_cfg,
};
static const struct v4l2_subdev_ops ub913_subdev_ops = {
@@ -512,6 +510,10 @@ static const struct v4l2_subdev_ops ub913_subdev_ops = {
.pad = &ub913_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ub913_internal_ops = {
+ .init_state = ub913_init_state,
+};
+
static const struct media_entity_operations ub913_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -745,6 +747,7 @@ static int ub913_subdev_init(struct ub913_data *priv)
int ret;
v4l2_i2c_subdev_init(&priv->sd, priv->client, &ub913_subdev_ops);
+ priv->sd.internal_ops = &ub913_internal_ops;
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
priv->sd.entity.ops = &ub913_entity_ops;
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index 6440223128..16f88db149 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -558,8 +558,7 @@ static int ub953_set_fmt(struct v4l2_subdev *sd,
return v4l2_subdev_get_fmt(sd, state, format);
/* Set sink format */
- fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
- format->stream);
+ fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
if (!fmt)
return -EINVAL;
@@ -576,8 +575,8 @@ static int ub953_set_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int ub953_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int ub953_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_subdev_route routes[] = {
{
@@ -714,7 +713,6 @@ static const struct v4l2_subdev_pad_ops ub953_pad_ops = {
.get_frame_desc = ub953_get_frame_desc,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ub953_set_fmt,
- .init_cfg = ub953_init_cfg,
};
static const struct v4l2_subdev_core_ops ub953_subdev_core_ops = {
@@ -728,6 +726,10 @@ static const struct v4l2_subdev_ops ub953_subdev_ops = {
.pad = &ub953_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ub953_internal_ops = {
+ .init_state = ub953_init_state,
+};
+
static const struct media_entity_operations ub953_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -1241,6 +1243,7 @@ static int ub953_subdev_init(struct ub953_data *priv)
int ret;
v4l2_i2c_subdev_init(&priv->sd, priv->client, &ub953_subdev_ops);
+ priv->sd.internal_ops = &ub953_internal_ops;
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_STREAMS;
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index b8f3e5ca03..ffe5f25f86 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -2451,9 +2451,8 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
if (rx_data[nport].num_streams > 2)
return -EPIPE;
- fmt = v4l2_subdev_state_get_stream_format(state,
- route->sink_pad,
- route->sink_stream);
+ fmt = v4l2_subdev_state_get_format(state, route->sink_pad,
+ route->sink_stream);
if (!fmt)
return -EPIPE;
@@ -2842,8 +2841,8 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
const struct ub960_format_info *ub960_fmt;
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_state_get_stream_format(state, pad,
- route->source_stream);
+ fmt = v4l2_subdev_state_get_format(state, pad,
+ route->source_stream);
if (!fmt) {
ret = -EINVAL;
@@ -2891,8 +2890,7 @@ static int ub960_set_fmt(struct v4l2_subdev *sd,
if (!ub960_find_format(format->format.code))
format->format.code = ub960_formats[0].code;
- fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
- format->stream);
+ fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
if (!fmt)
return -EINVAL;
@@ -2908,8 +2906,8 @@ static int ub960_set_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int ub960_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int ub960_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct ub960_data *priv = sd_to_ub960(sd);
@@ -2940,8 +2938,6 @@ static const struct v4l2_subdev_pad_ops ub960_pad_ops = {
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ub960_set_fmt,
-
- .init_cfg = ub960_init_cfg,
};
static int ub960_log_status(struct v4l2_subdev *sd)
@@ -3093,6 +3089,10 @@ static const struct v4l2_subdev_core_ops ub960_subdev_core_ops = {
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
+static const struct v4l2_subdev_internal_ops ub960_internal_ops = {
+ .init_state = ub960_init_state,
+};
+
static const struct v4l2_subdev_ops ub960_subdev_ops = {
.core = &ub960_subdev_core_ops,
.pad = &ub960_pad_ops,
@@ -3652,6 +3652,7 @@ static int ub960_create_subdev(struct ub960_data *priv)
int ret;
v4l2_i2c_subdev_init(&priv->sd, priv->client, &ub960_subdev_ops);
+ priv->sd.internal_ops = &ub960_internal_ops;
v4l2_ctrl_handler_init(&priv->ctrl_handler, 1);
priv->sd.ctrl_handler = &priv->ctrl_handler;
diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c
index d6fc843f93..f548b1bb75 100644
--- a/drivers/media/i2c/et8ek8/et8ek8_driver.c
+++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c
@@ -995,8 +995,7 @@ __et8ek8_get_pad_format(struct et8ek8_sensor *sensor,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&sensor->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &sensor->format;
default:
@@ -1047,10 +1046,18 @@ static int et8ek8_set_pad_format(struct v4l2_subdev *subdev,
}
static int et8ek8_get_frame_interval(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval *fi)
{
struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
memset(fi, 0, sizeof(*fi));
fi->interval = sensor->current_reglist->mode.timeperframe;
@@ -1058,11 +1065,19 @@ static int et8ek8_get_frame_interval(struct v4l2_subdev *subdev,
}
static int et8ek8_set_frame_interval(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval *fi)
{
struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);
struct et8ek8_reglist *reglist;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
reglist = et8ek8_reglist_find_mode_ival(&meta_reglist,
sensor->current_reglist,
&fi->interval);
@@ -1343,8 +1358,6 @@ static int et8ek8_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
static const struct v4l2_subdev_video_ops et8ek8_video_ops = {
.s_stream = et8ek8_s_stream,
- .g_frame_interval = et8ek8_get_frame_interval,
- .s_frame_interval = et8ek8_set_frame_interval,
};
static const struct v4l2_subdev_core_ops et8ek8_core_ops = {
@@ -1357,6 +1370,8 @@ static const struct v4l2_subdev_pad_ops et8ek8_pad_ops = {
.enum_frame_interval = et8ek8_enum_frame_ival,
.get_fmt = et8ek8_get_pad_format,
.set_fmt = et8ek8_set_pad_format,
+ .get_frame_interval = et8ek8_get_frame_interval,
+ .set_frame_interval = et8ek8_set_frame_interval,
};
static const struct v4l2_subdev_ops et8ek8_ops = {
diff --git a/drivers/media/i2c/gc0308.c b/drivers/media/i2c/gc0308.c
new file mode 100644
index 0000000000..fa754a8a39
--- /dev/null
+++ b/drivers/media/i2c/gc0308.c
@@ -0,0 +1,1451 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the GalaxyCore GC0308 camera sensor.
+ *
+ * Copyright (c) 2023 Sebastian Reichel <sre@kernel.org>
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/v4l2-cci.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+/* Analog & CISCTL*/
+#define GC0308_CHIP_ID CCI_REG8(0x000)
+#define GC0308_HBLANK CCI_REG8(0x001)
+#define GC0308_VBLANK CCI_REG8(0x002)
+#define GC0308_EXP CCI_REG16(0x003)
+#define GC0308_ROW_START CCI_REG16(0x005)
+#define GC0308_COL_START CCI_REG16(0x007)
+#define GC0308_WIN_HEIGHT CCI_REG16(0x009)
+#define GC0308_WIN_WIDTH CCI_REG16(0x00b)
+#define GC0308_VS_START_TIME CCI_REG8(0x00d) /* in rows */
+#define GC0308_VS_END_TIME CCI_REG8(0x00e) /* in rows */
+#define GC0308_VB_HB CCI_REG8(0x00f)
+#define GC0308_RSH_WIDTH CCI_REG8(0x010)
+#define GC0308_TSP_WIDTH CCI_REG8(0x011)
+#define GC0308_SAMPLE_HOLD_DELAY CCI_REG8(0x012)
+#define GC0308_ROW_TAIL_WIDTH CCI_REG8(0x013)
+#define GC0308_CISCTL_MODE1 CCI_REG8(0x014)
+#define GC0308_CISCTL_MODE2 CCI_REG8(0x015)
+#define GC0308_CISCTL_MODE3 CCI_REG8(0x016)
+#define GC0308_CISCTL_MODE4 CCI_REG8(0x017)
+#define GC0308_ANALOG_MODE1 CCI_REG8(0x01a)
+#define GC0308_ANALOG_MODE2 CCI_REG8(0x01b)
+#define GC0308_HRST_RSG_V18 CCI_REG8(0x01c)
+#define GC0308_VREF_V25 CCI_REG8(0x01d)
+#define GC0308_ADC_R CCI_REG8(0x01e)
+#define GC0308_PAD_DRV CCI_REG8(0x01f)
+#define GC0308_SOFT_RESET CCI_REG8(0x0fe)
+
+/* ISP */
+#define GC0308_BLOCK_EN1 CCI_REG8(0x020)
+#define GC0308_BLOCK_EN2 CCI_REG8(0x021)
+#define GC0308_AAAA_EN CCI_REG8(0x022)
+#define GC0308_SPECIAL_EFFECT CCI_REG8(0x023)
+#define GC0308_OUT_FORMAT CCI_REG8(0x024)
+#define GC0308_OUT_EN CCI_REG8(0x025)
+#define GC0308_SYNC_MODE CCI_REG8(0x026)
+#define GC0308_CLK_DIV_MODE CCI_REG8(0x028)
+#define GC0308_BYPASS_MODE CCI_REG8(0x029)
+#define GC0308_CLK_GATING CCI_REG8(0x02a)
+#define GC0308_DITHER_MODE CCI_REG8(0x02b)
+#define GC0308_DITHER_BIT CCI_REG8(0x02c)
+#define GC0308_DEBUG_MODE1 CCI_REG8(0x02d)
+#define GC0308_DEBUG_MODE2 CCI_REG8(0x02e)
+#define GC0308_DEBUG_MODE3 CCI_REG8(0x02f)
+#define GC0308_CROP_WIN_MODE CCI_REG8(0x046)
+#define GC0308_CROP_WIN_Y1 CCI_REG8(0x047)
+#define GC0308_CROP_WIN_X1 CCI_REG8(0x048)
+#define GC0308_CROP_WIN_HEIGHT CCI_REG16(0x049)
+#define GC0308_CROP_WIN_WIDTH CCI_REG16(0x04b)
+
+/* BLK */
+#define GC0308_BLK_MODE CCI_REG8(0x030)
+#define GC0308_BLK_LIMIT_VAL CCI_REG8(0x031)
+#define GC0308_GLOBAL_OFF CCI_REG8(0x032)
+#define GC0308_CURRENT_R_OFF CCI_REG8(0x033)
+#define GC0308_CURRENT_G_OFF CCI_REG8(0x034)
+#define GC0308_CURRENT_B_OFF CCI_REG8(0x035)
+#define GC0308_CURRENT_R_DARK_CURRENT CCI_REG8(0x036)
+#define GC0308_CURRENT_G_DARK_CURRENT CCI_REG8(0x037)
+#define GC0308_CURRENT_B_DARK_CURRENT CCI_REG8(0x038)
+#define GC0308_EXP_RATE_DARKC CCI_REG8(0x039)
+#define GC0308_OFF_SUBMODE CCI_REG8(0x03a)
+#define GC0308_DARKC_SUBMODE CCI_REG8(0x03b)
+#define GC0308_MANUAL_G1_OFF CCI_REG8(0x03c)
+#define GC0308_MANUAL_R1_OFF CCI_REG8(0x03d)
+#define GC0308_MANUAL_B2_OFF CCI_REG8(0x03e)
+#define GC0308_MANUAL_G2_OFF CCI_REG8(0x03f)
+
+/* PREGAIN */
+#define GC0308_GLOBAL_GAIN CCI_REG8(0x050)
+#define GC0308_AUTO_PREGAIN CCI_REG8(0x051)
+#define GC0308_AUTO_POSTGAIN CCI_REG8(0x052)
+#define GC0308_CHANNEL_GAIN_G1 CCI_REG8(0x053)
+#define GC0308_CHANNEL_GAIN_R CCI_REG8(0x054)
+#define GC0308_CHANNEL_GAIN_B CCI_REG8(0x055)
+#define GC0308_CHANNEL_GAIN_G2 CCI_REG8(0x056)
+#define GC0308_R_RATIO CCI_REG8(0x057)
+#define GC0308_G_RATIO CCI_REG8(0x058)
+#define GC0308_B_RATIO CCI_REG8(0x059)
+#define GC0308_AWB_R_GAIN CCI_REG8(0x05a)
+#define GC0308_AWB_G_GAIN CCI_REG8(0x05b)
+#define GC0308_AWB_B_GAIN CCI_REG8(0x05c)
+#define GC0308_LSC_DEC_LVL1 CCI_REG8(0x05d)
+#define GC0308_LSC_DEC_LVL2 CCI_REG8(0x05e)
+#define GC0308_LSC_DEC_LVL3 CCI_REG8(0x05f)
+
+/* DNDD */
+#define GC0308_DN_MODE_EN CCI_REG8(0x060)
+#define GC0308_DN_MODE_RATIO CCI_REG8(0x061)
+#define GC0308_DN_BILAT_B_BASE CCI_REG8(0x062)
+#define GC0308_DN_B_INCR CCI_REG8(0x063)
+#define GC0308_DN_BILAT_N_BASE CCI_REG8(0x064)
+#define GC0308_DN_N_INCR CCI_REG8(0x065)
+#define GC0308_DD_DARK_BRIGHT_TH CCI_REG8(0x066)
+#define GC0308_DD_FLAT_TH CCI_REG8(0x067)
+#define GC0308_DD_LIMIT CCI_REG8(0x068)
+
+/* ASDE - Auto Saturation De-noise and Edge-Enhancement */
+#define GC0308_ASDE_GAIN_TRESH CCI_REG8(0x069)
+#define GC0308_ASDE_GAIN_MODE CCI_REG8(0x06a)
+#define GC0308_ASDE_DN_SLOPE CCI_REG8(0x06b)
+#define GC0308_ASDE_DD_BRIGHT CCI_REG8(0x06c)
+#define GC0308_ASDE_DD_LIMIT CCI_REG8(0x06d)
+#define GC0308_ASDE_AUTO_EE1 CCI_REG8(0x06e)
+#define GC0308_ASDE_AUTO_EE2 CCI_REG8(0x06f)
+#define GC0308_ASDE_AUTO_SAT_DEC_SLOPE CCI_REG8(0x070)
+#define GC0308_ASDE_AUTO_SAT_LOW_LIMIT CCI_REG8(0x071)
+
+/* INTPEE - Interpolation and Edge-Enhancement */
+#define GC0308_EEINTP_MODE_1 CCI_REG8(0x072)
+#define GC0308_EEINTP_MODE_2 CCI_REG8(0x073)
+#define GC0308_DIRECTION_TH1 CCI_REG8(0x074)
+#define GC0308_DIRECTION_TH2 CCI_REG8(0x075)
+#define GC0308_DIFF_HV_TI_TH CCI_REG8(0x076)
+#define GC0308_EDGE12_EFFECT CCI_REG8(0x077)
+#define GC0308_EDGE_POS_RATIO CCI_REG8(0x078)
+#define GC0308_EDGE1_MINMAX CCI_REG8(0x079)
+#define GC0308_EDGE2_MINMAX CCI_REG8(0x07a)
+#define GC0308_EDGE12_TH CCI_REG8(0x07b)
+#define GC0308_EDGE_MAX CCI_REG8(0x07c)
+
+/* ABB - Auto Black Balance */
+#define GC0308_ABB_MODE CCI_REG8(0x080)
+#define GC0308_ABB_TARGET_AVGH CCI_REG8(0x081)
+#define GC0308_ABB_TARGET_AVGL CCI_REG8(0x082)
+#define GC0308_ABB_LIMIT_VAL CCI_REG8(0x083)
+#define GC0308_ABB_SPEED CCI_REG8(0x084)
+#define GC0308_CURR_R_BLACK_LVL CCI_REG8(0x085)
+#define GC0308_CURR_G_BLACK_LVL CCI_REG8(0x086)
+#define GC0308_CURR_B_BLACK_LVL CCI_REG8(0x087)
+#define GC0308_CURR_R_BLACK_FACTOR CCI_REG8(0x088)
+#define GC0308_CURR_G_BLACK_FACTOR CCI_REG8(0x089)
+#define GC0308_CURR_B_BLACK_FACTOR CCI_REG8(0x08a)
+
+/* LSC - Lens Shading Correction */
+#define GC0308_LSC_RED_B2 CCI_REG8(0x08b)
+#define GC0308_LSC_GREEN_B2 CCI_REG8(0x08c)
+#define GC0308_LSC_BLUE_B2 CCI_REG8(0x08d)
+#define GC0308_LSC_RED_B4 CCI_REG8(0x08e)
+#define GC0308_LSC_GREEN_B4 CCI_REG8(0x08f)
+#define GC0308_LSC_BLUE_B4 CCI_REG8(0x090)
+#define GC0308_LSC_ROW_CENTER CCI_REG8(0x091)
+#define GC0308_LSC_COL_CENTER CCI_REG8(0x092)
+
+/* CC - Channel Coefficient */
+#define GC0308_CC_MATRIX_C11 CCI_REG8(0x093)
+#define GC0308_CC_MATRIX_C12 CCI_REG8(0x094)
+#define GC0308_CC_MATRIX_C13 CCI_REG8(0x095)
+#define GC0308_CC_MATRIX_C21 CCI_REG8(0x096)
+#define GC0308_CC_MATRIX_C22 CCI_REG8(0x097)
+#define GC0308_CC_MATRIX_C23 CCI_REG8(0x098)
+#define GC0308_CC_MATRIX_C41 CCI_REG8(0x09c)
+#define GC0308_CC_MATRIX_C42 CCI_REG8(0x09d)
+#define GC0308_CC_MATRIX_C43 CCI_REG8(0x09e)
+
+/* GAMMA */
+#define GC0308_GAMMA_OUT0 CCI_REG8(0x09f)
+#define GC0308_GAMMA_OUT1 CCI_REG8(0x0a0)
+#define GC0308_GAMMA_OUT2 CCI_REG8(0x0a1)
+#define GC0308_GAMMA_OUT3 CCI_REG8(0x0a2)
+#define GC0308_GAMMA_OUT4 CCI_REG8(0x0a3)
+#define GC0308_GAMMA_OUT5 CCI_REG8(0x0a4)
+#define GC0308_GAMMA_OUT6 CCI_REG8(0x0a5)
+#define GC0308_GAMMA_OUT7 CCI_REG8(0x0a6)
+#define GC0308_GAMMA_OUT8 CCI_REG8(0x0a7)
+#define GC0308_GAMMA_OUT9 CCI_REG8(0x0a8)
+#define GC0308_GAMMA_OUT10 CCI_REG8(0x0a9)
+#define GC0308_GAMMA_OUT11 CCI_REG8(0x0aa)
+#define GC0308_GAMMA_OUT12 CCI_REG8(0x0ab)
+#define GC0308_GAMMA_OUT13 CCI_REG8(0x0ac)
+#define GC0308_GAMMA_OUT14 CCI_REG8(0x0ad)
+#define GC0308_GAMMA_OUT15 CCI_REG8(0x0ae)
+#define GC0308_GAMMA_OUT16 CCI_REG8(0x0af)
+
+/* YCP */
+#define GC0308_GLOBAL_SATURATION CCI_REG8(0x0b0)
+#define GC0308_SATURATION_CB CCI_REG8(0x0b1)
+#define GC0308_SATURATION_CR CCI_REG8(0x0b2)
+#define GC0308_LUMA_CONTRAST CCI_REG8(0x0b3)
+#define GC0308_CONTRAST_CENTER CCI_REG8(0x0b4)
+#define GC0308_LUMA_OFFSET CCI_REG8(0x0b5)
+#define GC0308_SKIN_CB_CENTER CCI_REG8(0x0b6)
+#define GC0308_SKIN_CR_CENTER CCI_REG8(0x0b7)
+#define GC0308_SKIN_RADIUS_SQUARE CCI_REG8(0x0b8)
+#define GC0308_SKIN_BRIGHTNESS CCI_REG8(0x0b9)
+#define GC0308_FIXED_CB CCI_REG8(0x0ba)
+#define GC0308_FIXED_CR CCI_REG8(0x0bb)
+#define GC0308_EDGE_DEC_SA CCI_REG8(0x0bd)
+#define GC0308_AUTO_GRAY_MODE CCI_REG8(0x0be)
+#define GC0308_SATURATION_SUB_STRENGTH CCI_REG8(0x0bf)
+#define GC0308_Y_GAMMA_OUT0 CCI_REG8(0x0c0)
+#define GC0308_Y_GAMMA_OUT1 CCI_REG8(0x0c1)
+#define GC0308_Y_GAMMA_OUT2 CCI_REG8(0x0c2)
+#define GC0308_Y_GAMMA_OUT3 CCI_REG8(0x0c3)
+#define GC0308_Y_GAMMA_OUT4 CCI_REG8(0x0c4)
+#define GC0308_Y_GAMMA_OUT5 CCI_REG8(0x0c5)
+#define GC0308_Y_GAMMA_OUT6 CCI_REG8(0x0c6)
+#define GC0308_Y_GAMMA_OUT7 CCI_REG8(0x0c7)
+#define GC0308_Y_GAMMA_OUT8 CCI_REG8(0x0c8)
+#define GC0308_Y_GAMMA_OUT9 CCI_REG8(0x0c9)
+#define GC0308_Y_GAMMA_OUT10 CCI_REG8(0x0ca)
+#define GC0308_Y_GAMMA_OUT11 CCI_REG8(0x0cb)
+#define GC0308_Y_GAMMA_OUT12 CCI_REG8(0x0cc)
+
+/* AEC - Automatic Exposure Control */
+#define GC0308_AEC_MODE1 CCI_REG8(0x0d0)
+#define GC0308_AEC_MODE2 CCI_REG8(0x0d1)
+#define GC0308_AEC_MODE3 CCI_REG8(0x0d2)
+#define GC0308_AEC_TARGET_Y CCI_REG8(0x0d3)
+#define GC0308_Y_AVG CCI_REG8(0x0d4)
+#define GC0308_AEC_HIGH_LOW_RANGE CCI_REG8(0x0d5)
+#define GC0308_AEC_IGNORE CCI_REG8(0x0d6)
+#define GC0308_AEC_LIMIT_HIGH_RANGE CCI_REG8(0x0d7)
+#define GC0308_AEC_R_OFFSET CCI_REG8(0x0d9)
+#define GC0308_AEC_GB_OFFSET CCI_REG8(0x0da)
+#define GC0308_AEC_SLOW_MARGIN CCI_REG8(0x0db)
+#define GC0308_AEC_FAST_MARGIN CCI_REG8(0x0dc)
+#define GC0308_AEC_EXP_CHANGE_GAIN CCI_REG8(0x0dd)
+#define GC0308_AEC_STEP2_SUNLIGHT CCI_REG8(0x0de)
+#define GC0308_AEC_I_FRAMES CCI_REG8(0x0df)
+#define GC0308_AEC_I_STOP_L_MARGIN CCI_REG8(0x0e0)
+#define GC0308_AEC_I_STOP_MARGIN CCI_REG8(0x0e1)
+#define GC0308_ANTI_FLICKER_STEP CCI_REG16(0x0e2)
+#define GC0308_EXP_LVL_1 CCI_REG16(0x0e4)
+#define GC0308_EXP_LVL_2 CCI_REG16(0x0e6)
+#define GC0308_EXP_LVL_3 CCI_REG16(0x0e8)
+#define GC0308_EXP_LVL_4 CCI_REG16(0x0ea)
+#define GC0308_MAX_EXP_LVL CCI_REG8(0x0ec)
+#define GC0308_EXP_MIN_L CCI_REG8(0x0ed)
+#define GC0308_MAX_POST_DF_GAIN CCI_REG8(0x0ee)
+#define GC0308_MAX_PRE_DG_GAIN CCI_REG8(0x0ef)
+
+/* ABS */
+#define GC0308_ABS_RANGE_COMP CCI_REG8(0x0f0)
+#define GC0308_ABS_STOP_MARGIN CCI_REG8(0x0f1)
+#define GC0308_Y_S_COMP CCI_REG8(0x0f2)
+#define GC0308_Y_STRETCH_LIMIT CCI_REG8(0x0f3)
+#define GC0308_Y_TILT CCI_REG8(0x0f4)
+#define GC0308_Y_STRETCH CCI_REG8(0x0f5)
+
+/* Measure Window */
+#define GC0308_BIG_WIN_X0 CCI_REG8(0x0f7)
+#define GC0308_BIG_WIN_Y0 CCI_REG8(0x0f8)
+#define GC0308_BIG_WIN_X1 CCI_REG8(0x0f9)
+#define GC0308_BIG_WIN_Y1 CCI_REG8(0x0fa)
+#define GC0308_DIFF_Y_BIG_THD CCI_REG8(0x0fb)
+
+/* OUT Module (P1) */
+#define GC0308_CLOSE_FRAME_EN CCI_REG8(0x150)
+#define GC0308_CLOSE_FRAME_NUM1 CCI_REG8(0x151)
+#define GC0308_CLOSE_FRAME_NUM2 CCI_REG8(0x152)
+#define GC0308_BAYER_MODE CCI_REG8(0x153)
+#define GC0308_SUBSAMPLE CCI_REG8(0x154)
+#define GC0308_SUBMODE CCI_REG8(0x155)
+#define GC0308_SUB_ROW_N1 CCI_REG8(0x156)
+#define GC0308_SUB_ROW_N2 CCI_REG8(0x157)
+#define GC0308_SUB_COL_N1 CCI_REG8(0x158)
+#define GC0308_SUB_COL_N2 CCI_REG8(0x159)
+
+/* AWB (P1) - Auto White Balance */
+#define GC0308_AWB_RGB_HIGH_LOW CCI_REG8(0x100)
+#define GC0308_AWB_Y_TO_C_DIFF2 CCI_REG8(0x102)
+#define GC0308_AWB_C_MAX CCI_REG8(0x104)
+#define GC0308_AWB_C_INTER CCI_REG8(0x105)
+#define GC0308_AWB_C_INTER2 CCI_REG8(0x106)
+#define GC0308_AWB_C_MAX_BIG CCI_REG8(0x108)
+#define GC0308_AWB_Y_HIGH CCI_REG8(0x109)
+#define GC0308_AWB_NUMBER_LIMIT CCI_REG8(0x10a)
+#define GC0308_KWIN_RATIO CCI_REG8(0x10b)
+#define GC0308_KWIN_THD CCI_REG8(0x10c)
+#define GC0308_LIGHT_GAIN_RANGE CCI_REG8(0x10d)
+#define GC0308_SMALL_WIN_WIDTH_STEP CCI_REG8(0x10e)
+#define GC0308_SMALL_WIN_HEIGHT_STEP CCI_REG8(0x10f)
+#define GC0308_AWB_YELLOW_TH CCI_REG8(0x110)
+#define GC0308_AWB_MODE CCI_REG8(0x111)
+#define GC0308_AWB_ADJUST_SPEED CCI_REG8(0x112)
+#define GC0308_AWB_EVERY_N CCI_REG8(0x113)
+#define GC0308_R_AVG_USE CCI_REG8(0x1d0)
+#define GC0308_G_AVG_USE CCI_REG8(0x1d1)
+#define GC0308_B_AVG_USE CCI_REG8(0x1d2)
+
+#define GC0308_HBLANK_MIN 0x021
+#define GC0308_HBLANK_MAX 0xfff
+#define GC0308_HBLANK_DEF 0x040
+
+#define GC0308_VBLANK_MIN 0x000
+#define GC0308_VBLANK_MAX 0xfff
+#define GC0308_VBLANK_DEF 0x020
+
+#define GC0308_PIXEL_RATE 24000000
+
+/*
+ * frame_time = (BT + height + 8) * row_time
+ * width = 640 (driver does not change window size)
+ * height = 480 (driver does not change window size)
+ * row_time = HBLANK + SAMPLE_HOLD_DELAY + width + 8 + 4
+ *
+ * When EXP_TIME > (BT + height):
+ * BT = EXP_TIME - height - 8 - VS_START_TIME + VS_END_TIME
+ * else:
+ * BT = VBLANK + VS_START_TIME + VS_END_TIME
+ *
+ * max is 30 FPS
+ *
+ * In my tests frame rate mostly depends on exposure time. Unfortuantely
+ * it's unclear how this is calculated exactly. Also since we enable AEC,
+ * the frame times vary depending on ambient light conditions.
+ */
+#define GC0308_FRAME_RATE_MAX 30
+
+enum gc0308_exp_val {
+ GC0308_EXP_M4 = 0,
+ GC0308_EXP_M3,
+ GC0308_EXP_M2,
+ GC0308_EXP_M1,
+ GC0308_EXP_0,
+ GC0308_EXP_P1,
+ GC0308_EXP_P2,
+ GC0308_EXP_P3,
+ GC0308_EXP_P4,
+};
+
+static const s64 gc0308_exposure_menu[] = {
+ -4, -3, -2, -1, 0, 1, 2, 3, 4
+};
+
+struct gc0308_exposure {
+ u8 luma_offset;
+ u8 aec_target_y;
+};
+
+#define GC0308_EXPOSURE(luma_offset_reg, aec_target_y_reg) \
+ { .luma_offset = luma_offset_reg, .aec_target_y = aec_target_y_reg }
+
+static const struct gc0308_exposure gc0308_exposure_values[] = {
+ [GC0308_EXP_M4] = GC0308_EXPOSURE(0xc0, 0x30),
+ [GC0308_EXP_M3] = GC0308_EXPOSURE(0xd0, 0x38),
+ [GC0308_EXP_M2] = GC0308_EXPOSURE(0xe0, 0x40),
+ [GC0308_EXP_M1] = GC0308_EXPOSURE(0xf0, 0x48),
+ [GC0308_EXP_0] = GC0308_EXPOSURE(0x08, 0x50),
+ [GC0308_EXP_P1] = GC0308_EXPOSURE(0x10, 0x5c),
+ [GC0308_EXP_P2] = GC0308_EXPOSURE(0x20, 0x60),
+ [GC0308_EXP_P3] = GC0308_EXPOSURE(0x30, 0x68),
+ [GC0308_EXP_P4] = GC0308_EXPOSURE(0x40, 0x70),
+};
+
+struct gc0308_awb_gains {
+ u8 r;
+ u8 g;
+ u8 b;
+};
+
+#define GC0308_AWB_GAINS(red, green, blue) \
+ { .r = red, .g = green, .b = blue }
+
+static const struct gc0308_awb_gains gc0308_awb_gains[] = {
+ [V4L2_WHITE_BALANCE_AUTO] = GC0308_AWB_GAINS(0x56, 0x40, 0x4a),
+ [V4L2_WHITE_BALANCE_CLOUDY] = GC0308_AWB_GAINS(0x8c, 0x50, 0x40),
+ [V4L2_WHITE_BALANCE_DAYLIGHT] = GC0308_AWB_GAINS(0x74, 0x52, 0x40),
+ [V4L2_WHITE_BALANCE_INCANDESCENT] = GC0308_AWB_GAINS(0x48, 0x40, 0x5c),
+ [V4L2_WHITE_BALANCE_FLUORESCENT] = GC0308_AWB_GAINS(0x40, 0x42, 0x50),
+};
+
+struct gc0308_format {
+ u32 code;
+ u8 regval;
+};
+
+#define GC0308_FORMAT(v4l2_code, gc0308_regval) \
+ { .code = v4l2_code, .regval = gc0308_regval }
+
+static const struct gc0308_format gc0308_formats[] = {
+ GC0308_FORMAT(MEDIA_BUS_FMT_UYVY8_2X8, 0x00),
+ GC0308_FORMAT(MEDIA_BUS_FMT_VYUY8_2X8, 0x01),
+ GC0308_FORMAT(MEDIA_BUS_FMT_YUYV8_2X8, 0x02),
+ GC0308_FORMAT(MEDIA_BUS_FMT_YVYU8_2X8, 0x03),
+ GC0308_FORMAT(MEDIA_BUS_FMT_RGB565_2X8_BE, 0x06),
+ GC0308_FORMAT(MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, 0x07),
+ GC0308_FORMAT(MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE, 0x09),
+};
+
+struct gc0308_frame_size {
+ u8 subsample;
+ u32 width;
+ u32 height;
+};
+
+#define GC0308_FRAME_SIZE(s, w, h) \
+ { .subsample = s, .width = w, .height = h }
+
+static const struct gc0308_frame_size gc0308_frame_sizes[] = {
+ GC0308_FRAME_SIZE(0x11, 640, 480),
+ GC0308_FRAME_SIZE(0x22, 320, 240),
+ GC0308_FRAME_SIZE(0x44, 160, 120),
+};
+
+struct gc0308_mode_registers {
+ u8 out_format;
+ u8 subsample;
+ u16 width;
+ u16 height;
+};
+
+struct gc0308 {
+ struct v4l2_subdev sd;
+ struct v4l2_ctrl_handler hdl;
+ struct media_pad pad;
+ struct device *dev;
+ struct clk *clk;
+ struct regmap *regmap;
+ struct regulator *vdd;
+ struct gpio_desc *pwdn_gpio;
+ struct gpio_desc *reset_gpio;
+ unsigned int mbus_config;
+ struct gc0308_mode_registers mode;
+ struct {
+ /* mirror cluster */
+ struct v4l2_ctrl *hflip;
+ struct v4l2_ctrl *vflip;
+ };
+ struct {
+ /* blanking cluster */
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *vblank;
+ };
+};
+
+static inline struct gc0308 *to_gc0308(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct gc0308, sd);
+}
+
+static const struct regmap_range_cfg gc0308_ranges[] = {
+ {
+ .range_min = 0x0000,
+ .range_max = 0x01ff,
+ .selector_reg = 0xfe,
+ .selector_mask = 0x01,
+ .selector_shift = 0x00,
+ .window_start = 0x00,
+ .window_len = 0x100,
+ },
+};
+
+static const struct regmap_config gc0308_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .max_register = 0x1ff,
+ .ranges = gc0308_ranges,
+ .num_ranges = ARRAY_SIZE(gc0308_ranges),
+ .disable_locking = true,
+};
+
+static const struct cci_reg_sequence sensor_default_regs[] = {
+ {GC0308_VB_HB, 0x00},
+ {GC0308_HBLANK, 0x40},
+ {GC0308_VBLANK, 0x20},
+ {GC0308_EXP, 0x0258},
+ {GC0308_AWB_R_GAIN, 0x56},
+ {GC0308_AWB_G_GAIN, 0x40},
+ {GC0308_AWB_B_GAIN, 0x4a},
+ {GC0308_ANTI_FLICKER_STEP, 0x0078},
+ {GC0308_EXP_LVL_1, 0x0258},
+ {GC0308_EXP_LVL_2, 0x0258},
+ {GC0308_EXP_LVL_3, 0x0258},
+ {GC0308_EXP_LVL_4, 0x0ea6},
+ {GC0308_MAX_EXP_LVL, 0x20},
+ {GC0308_ROW_START, 0x0000},
+ {GC0308_COL_START, 0x0000},
+ {GC0308_WIN_HEIGHT, 488},
+ {GC0308_WIN_WIDTH, 648},
+ {GC0308_VS_START_TIME, 0x02},
+ {GC0308_VS_END_TIME, 0x02},
+ {GC0308_RSH_WIDTH, 0x22},
+ {GC0308_TSP_WIDTH, 0x0d},
+ {GC0308_SAMPLE_HOLD_DELAY, 0x50},
+ {GC0308_ROW_TAIL_WIDTH, 0x0f},
+ {GC0308_CISCTL_MODE1, 0x10},
+ {GC0308_CISCTL_MODE2, 0x0a},
+ {GC0308_CISCTL_MODE3, 0x05},
+ {GC0308_CISCTL_MODE4, 0x01},
+ {CCI_REG8(0x018), 0x44}, /* undocumented */
+ {CCI_REG8(0x019), 0x44}, /* undocumented */
+ {GC0308_ANALOG_MODE1, 0x2a},
+ {GC0308_ANALOG_MODE2, 0x00},
+ {GC0308_HRST_RSG_V18, 0x49},
+ {GC0308_VREF_V25, 0x9a},
+ {GC0308_ADC_R, 0x61},
+ {GC0308_PAD_DRV, 0x01}, /* drv strength: pclk=4mA */
+ {GC0308_BLOCK_EN1, 0x7f},
+ {GC0308_BLOCK_EN2, 0xfa},
+ {GC0308_AAAA_EN, 0x57},
+ {GC0308_OUT_FORMAT, 0xa2}, /* YCbYCr */
+ {GC0308_OUT_EN, 0x0f},
+ {GC0308_SYNC_MODE, 0x03},
+ {GC0308_CLK_DIV_MODE, 0x00},
+ {GC0308_DEBUG_MODE1, 0x0a},
+ {GC0308_DEBUG_MODE2, 0x00},
+ {GC0308_DEBUG_MODE3, 0x01},
+ {GC0308_BLK_MODE, 0xf7},
+ {GC0308_BLK_LIMIT_VAL, 0x50},
+ {GC0308_GLOBAL_OFF, 0x00},
+ {GC0308_CURRENT_R_OFF, 0x28},
+ {GC0308_CURRENT_G_OFF, 0x2a},
+ {GC0308_CURRENT_B_OFF, 0x28},
+ {GC0308_EXP_RATE_DARKC, 0x04},
+ {GC0308_OFF_SUBMODE, 0x20},
+ {GC0308_DARKC_SUBMODE, 0x20},
+ {GC0308_MANUAL_G1_OFF, 0x00},
+ {GC0308_MANUAL_R1_OFF, 0x00},
+ {GC0308_MANUAL_B2_OFF, 0x00},
+ {GC0308_MANUAL_G2_OFF, 0x00},
+ {GC0308_GLOBAL_GAIN, 0x14},
+ {GC0308_AUTO_POSTGAIN, 0x41},
+ {GC0308_CHANNEL_GAIN_G1, 0x80},
+ {GC0308_CHANNEL_GAIN_R, 0x80},
+ {GC0308_CHANNEL_GAIN_B, 0x80},
+ {GC0308_CHANNEL_GAIN_G2, 0x80},
+ {GC0308_LSC_RED_B2, 0x20},
+ {GC0308_LSC_GREEN_B2, 0x20},
+ {GC0308_LSC_BLUE_B2, 0x20},
+ {GC0308_LSC_RED_B4, 0x14},
+ {GC0308_LSC_GREEN_B4, 0x10},
+ {GC0308_LSC_BLUE_B4, 0x14},
+ {GC0308_LSC_ROW_CENTER, 0x3c},
+ {GC0308_LSC_COL_CENTER, 0x50},
+ {GC0308_LSC_DEC_LVL1, 0x12},
+ {GC0308_LSC_DEC_LVL2, 0x1a},
+ {GC0308_LSC_DEC_LVL3, 0x24},
+ {GC0308_DN_MODE_EN, 0x07},
+ {GC0308_DN_MODE_RATIO, 0x15},
+ {GC0308_DN_BILAT_B_BASE, 0x08},
+ {GC0308_DN_BILAT_N_BASE, 0x03},
+ {GC0308_DD_DARK_BRIGHT_TH, 0xe8},
+ {GC0308_DD_FLAT_TH, 0x86},
+ {GC0308_DD_LIMIT, 0x82},
+ {GC0308_ASDE_GAIN_TRESH, 0x18},
+ {GC0308_ASDE_GAIN_MODE, 0x0f},
+ {GC0308_ASDE_DN_SLOPE, 0x00},
+ {GC0308_ASDE_DD_BRIGHT, 0x5f},
+ {GC0308_ASDE_DD_LIMIT, 0x8f},
+ {GC0308_ASDE_AUTO_EE1, 0x55},
+ {GC0308_ASDE_AUTO_EE2, 0x38},
+ {GC0308_ASDE_AUTO_SAT_DEC_SLOPE, 0x15},
+ {GC0308_ASDE_AUTO_SAT_LOW_LIMIT, 0x33},
+ {GC0308_EEINTP_MODE_1, 0xdc},
+ {GC0308_EEINTP_MODE_2, 0x00},
+ {GC0308_DIRECTION_TH1, 0x02},
+ {GC0308_DIRECTION_TH2, 0x3f},
+ {GC0308_DIFF_HV_TI_TH, 0x02},
+ {GC0308_EDGE12_EFFECT, 0x38},
+ {GC0308_EDGE_POS_RATIO, 0x88},
+ {GC0308_EDGE1_MINMAX, 0x81},
+ {GC0308_EDGE2_MINMAX, 0x81},
+ {GC0308_EDGE12_TH, 0x22},
+ {GC0308_EDGE_MAX, 0xff},
+ {GC0308_CC_MATRIX_C11, 0x48},
+ {GC0308_CC_MATRIX_C12, 0x02},
+ {GC0308_CC_MATRIX_C13, 0x07},
+ {GC0308_CC_MATRIX_C21, 0xe0},
+ {GC0308_CC_MATRIX_C22, 0x40},
+ {GC0308_CC_MATRIX_C23, 0xf0},
+ {GC0308_SATURATION_CB, 0x40},
+ {GC0308_SATURATION_CR, 0x40},
+ {GC0308_LUMA_CONTRAST, 0x40},
+ {GC0308_SKIN_CB_CENTER, 0xe0},
+ {GC0308_EDGE_DEC_SA, 0x38},
+ {GC0308_AUTO_GRAY_MODE, 0x36},
+ {GC0308_AEC_MODE1, 0xcb},
+ {GC0308_AEC_MODE2, 0x10},
+ {GC0308_AEC_MODE3, 0x90},
+ {GC0308_AEC_TARGET_Y, 0x48},
+ {GC0308_AEC_HIGH_LOW_RANGE, 0xf2},
+ {GC0308_AEC_IGNORE, 0x16},
+ {GC0308_AEC_SLOW_MARGIN, 0x92},
+ {GC0308_AEC_FAST_MARGIN, 0xa5},
+ {GC0308_AEC_I_FRAMES, 0x23},
+ {GC0308_AEC_R_OFFSET, 0x00},
+ {GC0308_AEC_GB_OFFSET, 0x00},
+ {GC0308_AEC_I_STOP_L_MARGIN, 0x09},
+ {GC0308_EXP_MIN_L, 0x04},
+ {GC0308_MAX_POST_DF_GAIN, 0xa0},
+ {GC0308_MAX_PRE_DG_GAIN, 0x40},
+ {GC0308_ABB_MODE, 0x03},
+ {GC0308_GAMMA_OUT0, 0x10},
+ {GC0308_GAMMA_OUT1, 0x20},
+ {GC0308_GAMMA_OUT2, 0x38},
+ {GC0308_GAMMA_OUT3, 0x4e},
+ {GC0308_GAMMA_OUT4, 0x63},
+ {GC0308_GAMMA_OUT5, 0x76},
+ {GC0308_GAMMA_OUT6, 0x87},
+ {GC0308_GAMMA_OUT7, 0xa2},
+ {GC0308_GAMMA_OUT8, 0xb8},
+ {GC0308_GAMMA_OUT9, 0xca},
+ {GC0308_GAMMA_OUT10, 0xd8},
+ {GC0308_GAMMA_OUT11, 0xe3},
+ {GC0308_GAMMA_OUT12, 0xeb},
+ {GC0308_GAMMA_OUT13, 0xf0},
+ {GC0308_GAMMA_OUT14, 0xf8},
+ {GC0308_GAMMA_OUT15, 0xfd},
+ {GC0308_GAMMA_OUT16, 0xff},
+ {GC0308_Y_GAMMA_OUT0, 0x00},
+ {GC0308_Y_GAMMA_OUT1, 0x10},
+ {GC0308_Y_GAMMA_OUT2, 0x1c},
+ {GC0308_Y_GAMMA_OUT3, 0x30},
+ {GC0308_Y_GAMMA_OUT4, 0x43},
+ {GC0308_Y_GAMMA_OUT5, 0x54},
+ {GC0308_Y_GAMMA_OUT6, 0x65},
+ {GC0308_Y_GAMMA_OUT7, 0x75},
+ {GC0308_Y_GAMMA_OUT8, 0x93},
+ {GC0308_Y_GAMMA_OUT9, 0xb0},
+ {GC0308_Y_GAMMA_OUT10, 0xcb},
+ {GC0308_Y_GAMMA_OUT11, 0xe6},
+ {GC0308_Y_GAMMA_OUT12, 0xff},
+ {GC0308_ABS_RANGE_COMP, 0x02},
+ {GC0308_ABS_STOP_MARGIN, 0x01},
+ {GC0308_Y_S_COMP, 0x02},
+ {GC0308_Y_STRETCH_LIMIT, 0x30},
+ {GC0308_BIG_WIN_X0, 0x12},
+ {GC0308_BIG_WIN_Y0, 0x0a},
+ {GC0308_BIG_WIN_X1, 0x9f},
+ {GC0308_BIG_WIN_Y1, 0x78},
+ {GC0308_AWB_RGB_HIGH_LOW, 0xf5},
+ {GC0308_AWB_Y_TO_C_DIFF2, 0x20},
+ {GC0308_AWB_C_MAX, 0x10},
+ {GC0308_AWB_C_INTER, 0x08},
+ {GC0308_AWB_C_INTER2, 0x20},
+ {GC0308_AWB_C_MAX_BIG, 0x0a},
+ {GC0308_AWB_NUMBER_LIMIT, 0xa0},
+ {GC0308_KWIN_RATIO, 0x60},
+ {GC0308_KWIN_THD, 0x08},
+ {GC0308_SMALL_WIN_WIDTH_STEP, 0x44},
+ {GC0308_SMALL_WIN_HEIGHT_STEP, 0x32},
+ {GC0308_AWB_YELLOW_TH, 0x41},
+ {GC0308_AWB_MODE, 0x37},
+ {GC0308_AWB_ADJUST_SPEED, 0x22},
+ {GC0308_AWB_EVERY_N, 0x19},
+ {CCI_REG8(0x114), 0x44}, /* AWB set1 */
+ {CCI_REG8(0x115), 0x44}, /* AWB set1 */
+ {CCI_REG8(0x116), 0xc2}, /* AWB set1 */
+ {CCI_REG8(0x117), 0xa8}, /* AWB set1 */
+ {CCI_REG8(0x118), 0x18}, /* AWB set1 */
+ {CCI_REG8(0x119), 0x50}, /* AWB set1 */
+ {CCI_REG8(0x11a), 0xd8}, /* AWB set1 */
+ {CCI_REG8(0x11b), 0xf5}, /* AWB set1 */
+ {CCI_REG8(0x170), 0x40}, /* AWB set2 */
+ {CCI_REG8(0x171), 0x58}, /* AWB set2 */
+ {CCI_REG8(0x172), 0x30}, /* AWB set2 */
+ {CCI_REG8(0x173), 0x48}, /* AWB set2 */
+ {CCI_REG8(0x174), 0x20}, /* AWB set2 */
+ {CCI_REG8(0x175), 0x60}, /* AWB set2 */
+ {CCI_REG8(0x177), 0x20}, /* AWB set2 */
+ {CCI_REG8(0x178), 0x32}, /* AWB set2 */
+ {CCI_REG8(0x130), 0x03}, /* undocumented */
+ {CCI_REG8(0x131), 0x40}, /* undocumented */
+ {CCI_REG8(0x132), 0x10}, /* undocumented */
+ {CCI_REG8(0x133), 0xe0}, /* undocumented */
+ {CCI_REG8(0x134), 0xe0}, /* undocumented */
+ {CCI_REG8(0x135), 0x00}, /* undocumented */
+ {CCI_REG8(0x136), 0x80}, /* undocumented */
+ {CCI_REG8(0x137), 0x00}, /* undocumented */
+ {CCI_REG8(0x138), 0x04}, /* undocumented */
+ {CCI_REG8(0x139), 0x09}, /* undocumented */
+ {CCI_REG8(0x13a), 0x12}, /* undocumented */
+ {CCI_REG8(0x13b), 0x1c}, /* undocumented */
+ {CCI_REG8(0x13c), 0x28}, /* undocumented */
+ {CCI_REG8(0x13d), 0x31}, /* undocumented */
+ {CCI_REG8(0x13e), 0x44}, /* undocumented */
+ {CCI_REG8(0x13f), 0x57}, /* undocumented */
+ {CCI_REG8(0x140), 0x6c}, /* undocumented */
+ {CCI_REG8(0x141), 0x81}, /* undocumented */
+ {CCI_REG8(0x142), 0x94}, /* undocumented */
+ {CCI_REG8(0x143), 0xa7}, /* undocumented */
+ {CCI_REG8(0x144), 0xb8}, /* undocumented */
+ {CCI_REG8(0x145), 0xd6}, /* undocumented */
+ {CCI_REG8(0x146), 0xee}, /* undocumented */
+ {CCI_REG8(0x147), 0x0d}, /* undocumented */
+ {CCI_REG8(0x162), 0xf7}, /* undocumented */
+ {CCI_REG8(0x163), 0x68}, /* undocumented */
+ {CCI_REG8(0x164), 0xd3}, /* undocumented */
+ {CCI_REG8(0x165), 0xd3}, /* undocumented */
+ {CCI_REG8(0x166), 0x60}, /* undocumented */
+};
+
+struct gc0308_colormode {
+ u8 special_effect;
+ u8 dbg_mode1;
+ u8 block_en1;
+ u8 aec_mode3;
+ u8 eeintp_mode_2;
+ u8 edge12_effect;
+ u8 luma_contrast;
+ u8 contrast_center;
+ u8 fixed_cb;
+ u8 fixed_cr;
+};
+
+#define GC0308_COLOR_FX(reg_special_effect, reg_dbg_mode1, reg_block_en1, \
+ reg_aec_mode3, reg_eeintp_mode_2, reg_edge12_effect, \
+ reg_luma_contrast, reg_contrast_center, \
+ reg_fixed_cb, reg_fixed_cr) \
+ { \
+ .special_effect = reg_special_effect, \
+ .dbg_mode1 = reg_dbg_mode1, \
+ .block_en1 = reg_block_en1, \
+ .aec_mode3 = reg_aec_mode3, \
+ .eeintp_mode_2 = reg_eeintp_mode_2, \
+ .edge12_effect = reg_edge12_effect, \
+ .luma_contrast = reg_luma_contrast, \
+ .contrast_center = reg_contrast_center, \
+ .fixed_cb = reg_fixed_cb, \
+ .fixed_cr = reg_fixed_cr, \
+ }
+
+static const struct gc0308_colormode gc0308_colormodes[] = {
+ [V4L2_COLORFX_NONE] =
+ GC0308_COLOR_FX(0x00, 0x0a, 0xff, 0x90, 0x00,
+ 0x54, 0x3c, 0x80, 0x00, 0x00),
+ [V4L2_COLORFX_BW] =
+ GC0308_COLOR_FX(0x02, 0x0a, 0xff, 0x90, 0x00,
+ 0x54, 0x40, 0x80, 0x00, 0x00),
+ [V4L2_COLORFX_SEPIA] =
+ GC0308_COLOR_FX(0x02, 0x0a, 0xff, 0x90, 0x00,
+ 0x38, 0x40, 0x80, 0xd0, 0x28),
+ [V4L2_COLORFX_NEGATIVE] =
+ GC0308_COLOR_FX(0x01, 0x0a, 0xff, 0x90, 0x00,
+ 0x38, 0x40, 0x80, 0x00, 0x00),
+ [V4L2_COLORFX_EMBOSS] =
+ GC0308_COLOR_FX(0x02, 0x0a, 0xbf, 0x10, 0x01,
+ 0x38, 0x40, 0x80, 0x00, 0x00),
+ [V4L2_COLORFX_SKETCH] =
+ GC0308_COLOR_FX(0x02, 0x0a, 0xff, 0x10, 0x80,
+ 0x38, 0x80, 0x90, 0x00, 0x00),
+ [V4L2_COLORFX_SKY_BLUE] =
+ GC0308_COLOR_FX(0x02, 0x0a, 0xff, 0x90, 0x00,
+ 0x38, 0x40, 0x80, 0x50, 0xe0),
+ [V4L2_COLORFX_GRASS_GREEN] =
+ GC0308_COLOR_FX(0x02, 0x0a, 0xff, 0x90, 0x01,
+ 0x38, 0x40, 0x80, 0xc0, 0xc0),
+ [V4L2_COLORFX_SKIN_WHITEN] =
+ GC0308_COLOR_FX(0x02, 0x0a, 0xbf, 0x10, 0x01,
+ 0x38, 0x60, 0x40, 0x00, 0x00),
+};
+
+static int gc0308_power_on(struct device *dev)
+{
+ struct gc0308 *gc0308 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_enable(gc0308->vdd);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(gc0308->clk);
+ if (ret)
+ goto clk_fail;
+
+ gpiod_set_value_cansleep(gc0308->pwdn_gpio, 0);
+ usleep_range(10000, 20000);
+
+ gpiod_set_value_cansleep(gc0308->reset_gpio, 1);
+ usleep_range(10000, 20000);
+ gpiod_set_value_cansleep(gc0308->reset_gpio, 0);
+ msleep(30);
+
+ return 0;
+
+clk_fail:
+ regulator_disable(gc0308->vdd);
+ return ret;
+}
+
+static int gc0308_power_off(struct device *dev)
+{
+ struct gc0308 *gc0308 = dev_get_drvdata(dev);
+
+ gpiod_set_value_cansleep(gc0308->pwdn_gpio, 1);
+ clk_disable_unprepare(gc0308->clk);
+ regulator_disable(gc0308->vdd);
+
+ return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int gc0308_g_register(struct v4l2_subdev *sd,
+ struct v4l2_dbg_register *reg)
+{
+ struct gc0308 *gc0308 = to_gc0308(sd);
+
+ return cci_read(gc0308->regmap, CCI_REG8(reg->reg), &reg->val, NULL);
+}
+
+static int gc0308_s_register(struct v4l2_subdev *sd,
+ const struct v4l2_dbg_register *reg)
+{
+ struct gc0308 *gc0308 = to_gc0308(sd);
+
+ return cci_write(gc0308->regmap, CCI_REG8(reg->reg), reg->val, NULL);
+}
+#endif
+
+static int gc0308_set_exposure(struct gc0308 *gc0308, enum gc0308_exp_val exp)
+{
+ const struct gc0308_exposure *regs = &gc0308_exposure_values[exp];
+ struct cci_reg_sequence exposure_reg_seq[] = {
+ {GC0308_LUMA_OFFSET, regs->luma_offset},
+ {GC0308_AEC_TARGET_Y, regs->aec_target_y},
+ };
+
+ return cci_multi_reg_write(gc0308->regmap, exposure_reg_seq,
+ ARRAY_SIZE(exposure_reg_seq), NULL);
+}
+
+static int gc0308_set_awb_mode(struct gc0308 *gc0308,
+ enum v4l2_auto_n_preset_white_balance val)
+{
+ const struct gc0308_awb_gains *regs = &gc0308_awb_gains[val];
+ struct cci_reg_sequence awb_reg_seq[] = {
+ {GC0308_AWB_R_GAIN, regs->r},
+ {GC0308_AWB_G_GAIN, regs->g},
+ {GC0308_AWB_B_GAIN, regs->b},
+ };
+ int ret;
+
+ ret = cci_update_bits(gc0308->regmap, GC0308_AAAA_EN,
+ BIT(1), val == V4L2_WHITE_BALANCE_AUTO, NULL);
+ ret = cci_multi_reg_write(gc0308->regmap, awb_reg_seq,
+ ARRAY_SIZE(awb_reg_seq), &ret);
+
+ return ret;
+}
+
+static int gc0308_set_colormode(struct gc0308 *gc0308, enum v4l2_colorfx mode)
+{
+ const struct gc0308_colormode *regs = &gc0308_colormodes[mode];
+ struct cci_reg_sequence colormode_reg_seq[] = {
+ {GC0308_SPECIAL_EFFECT, regs->special_effect},
+ {GC0308_DEBUG_MODE1, regs->dbg_mode1},
+ {GC0308_BLOCK_EN1, regs->block_en1},
+ {GC0308_AEC_MODE3, regs->aec_mode3},
+ {GC0308_EEINTP_MODE_2, regs->eeintp_mode_2},
+ {GC0308_EDGE12_EFFECT, regs->edge12_effect},
+ {GC0308_LUMA_CONTRAST, regs->luma_contrast},
+ {GC0308_CONTRAST_CENTER, regs->contrast_center},
+ {GC0308_FIXED_CB, regs->fixed_cb},
+ {GC0308_FIXED_CR, regs->fixed_cr},
+ };
+
+ return cci_multi_reg_write(gc0308->regmap, colormode_reg_seq,
+ ARRAY_SIZE(colormode_reg_seq), NULL);
+}
+
+static int gc0308_set_power_line_freq(struct gc0308 *gc0308, int frequency)
+{
+ static const struct cci_reg_sequence pwr_line_50hz[] = {
+ {GC0308_ANTI_FLICKER_STEP, 0x0078},
+ {GC0308_EXP_LVL_1, 0x0258},
+ {GC0308_EXP_LVL_2, 0x0348},
+ {GC0308_EXP_LVL_3, 0x04b0},
+ {GC0308_EXP_LVL_4, 0x05a0},
+ };
+ static const struct cci_reg_sequence pwr_line_60hz[] = {
+ {GC0308_ANTI_FLICKER_STEP, 0x0064},
+ {GC0308_EXP_LVL_1, 0x0258},
+ {GC0308_EXP_LVL_2, 0x0384},
+ {GC0308_EXP_LVL_3, 0x04b0},
+ {GC0308_EXP_LVL_4, 0x05dc},
+ };
+
+ switch (frequency) {
+ case V4L2_CID_POWER_LINE_FREQUENCY_60HZ:
+ return cci_multi_reg_write(gc0308->regmap, pwr_line_60hz,
+ ARRAY_SIZE(pwr_line_60hz), NULL);
+ case V4L2_CID_POWER_LINE_FREQUENCY_50HZ:
+ return cci_multi_reg_write(gc0308->regmap, pwr_line_50hz,
+ ARRAY_SIZE(pwr_line_50hz), NULL);
+ }
+
+ return -EINVAL;
+}
+
+static int gc0308_update_mirror(struct gc0308 *gc0308)
+{
+ u8 regval = 0x00;
+
+ if (gc0308->vflip->val)
+ regval |= BIT(1);
+
+ if (gc0308->hflip->val)
+ regval |= BIT(0);
+
+ return cci_update_bits(gc0308->regmap, GC0308_CISCTL_MODE1,
+ GENMASK(1, 0), regval, NULL);
+}
+
+static int gc0308_update_blanking(struct gc0308 *gc0308)
+{
+ u16 vblank = gc0308->vblank->val;
+ u16 hblank = gc0308->hblank->val;
+ u8 vbhb = ((vblank >> 4) & 0xf0) | ((hblank >> 8) & 0x0f);
+ int ret = 0;
+
+ cci_write(gc0308->regmap, GC0308_VB_HB, vbhb, &ret);
+ cci_write(gc0308->regmap, GC0308_HBLANK, hblank & 0xff, &ret);
+ cci_write(gc0308->regmap, GC0308_VBLANK, vblank & 0xff, &ret);
+
+ return ret;
+}
+
+static int _gc0308_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct gc0308 *gc0308 = container_of(ctrl->handler, struct gc0308, hdl);
+ u8 flipval = ctrl->val ? 0xff : 0x00;
+
+ switch (ctrl->id) {
+ case V4L2_CID_HBLANK:
+ case V4L2_CID_VBLANK:
+ return gc0308_update_blanking(gc0308);
+ case V4L2_CID_VFLIP:
+ case V4L2_CID_HFLIP:
+ return gc0308_update_mirror(gc0308);
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ return cci_update_bits(gc0308->regmap, GC0308_AAAA_EN,
+ BIT(1), flipval, NULL);
+ case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
+ return gc0308_set_awb_mode(gc0308, ctrl->val);
+ case V4L2_CID_POWER_LINE_FREQUENCY:
+ return gc0308_set_power_line_freq(gc0308, ctrl->val);
+ case V4L2_CID_COLORFX:
+ return gc0308_set_colormode(gc0308, ctrl->val);
+ case V4L2_CID_TEST_PATTERN:
+ return cci_update_bits(gc0308->regmap, GC0308_DEBUG_MODE2,
+ GENMASK(1, 0), ctrl->val, NULL);
+ case V4L2_CID_AUTO_EXPOSURE_BIAS:
+ return gc0308_set_exposure(gc0308, ctrl->val);
+ }
+
+ return -EINVAL;
+}
+
+static int gc0308_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct gc0308 *gc0308 = container_of(ctrl->handler, struct gc0308, hdl);
+ int ret;
+
+ if (!pm_runtime_get_if_in_use(gc0308->dev))
+ return 0;
+
+ ret = _gc0308_s_ctrl(ctrl);
+ if (ret)
+ dev_err(gc0308->dev, "failed to set control: %d\n", ret);
+
+ pm_runtime_mark_last_busy(gc0308->dev);
+ pm_runtime_put_autosuspend(gc0308->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops gc0308_ctrl_ops = {
+ .s_ctrl = gc0308_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops gc0308_core_ops = {
+ .log_status = v4l2_ctrl_subdev_log_status,
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .g_register = gc0308_g_register,
+ .s_register = gc0308_s_register,
+#endif
+};
+
+static int gc0308_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index >= ARRAY_SIZE(gc0308_formats))
+ return -EINVAL;
+
+ code->code = gc0308_formats[code->index].code;
+
+ return 0;
+}
+
+static int gc0308_get_format_idx(u32 code)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(gc0308_formats); i++) {
+ if (gc0308_formats[i].code == code)
+ return i;
+ }
+
+ return -1;
+}
+
+static int gc0308_enum_frame_size(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index >= ARRAY_SIZE(gc0308_frame_sizes))
+ return -EINVAL;
+
+ if (gc0308_get_format_idx(fse->code) < 0)
+ return -EINVAL;
+
+ fse->min_width = gc0308_frame_sizes[fse->index].width;
+ fse->max_width = gc0308_frame_sizes[fse->index].width;
+ fse->min_height = gc0308_frame_sizes[fse->index].height;
+ fse->max_height = gc0308_frame_sizes[fse->index].height;
+
+ return 0;
+}
+
+static void gc0308_update_pad_format(const struct gc0308_frame_size *mode,
+ struct v4l2_mbus_framefmt *fmt, u32 code)
+{
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->code = code;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+}
+
+static int gc0308_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct gc0308 *gc0308 = to_gc0308(sd);
+ const struct gc0308_frame_size *mode;
+ int i = gc0308_get_format_idx(fmt->format.code);
+
+ if (i < 0)
+ i = 0;
+
+ mode = v4l2_find_nearest_size(gc0308_frame_sizes,
+ ARRAY_SIZE(gc0308_frame_sizes), width,
+ height, fmt->format.width,
+ fmt->format.height);
+
+ gc0308_update_pad_format(mode, &fmt->format, gc0308_formats[i].code);
+ *v4l2_subdev_state_get_format(sd_state, 0) = fmt->format;
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
+ gc0308->mode.out_format = gc0308_formats[i].regval;
+ gc0308->mode.subsample = mode->subsample;
+ gc0308->mode.width = mode->width;
+ gc0308->mode.height = mode->height;
+
+ return 0;
+}
+
+static int gc0308_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ struct v4l2_mbus_framefmt *format =
+ v4l2_subdev_state_get_format(sd_state, 0);
+
+ format->width = 640;
+ format->height = 480;
+ format->code = gc0308_formats[0].code;
+ format->colorspace = V4L2_COLORSPACE_SRGB;
+ format->field = V4L2_FIELD_NONE;
+ format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ format->quantization = V4L2_QUANTIZATION_DEFAULT;
+ format->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_pad_ops gc0308_pad_ops = {
+ .enum_mbus_code = gc0308_enum_mbus_code,
+ .enum_frame_size = gc0308_enum_frame_size,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = gc0308_set_format,
+};
+
+static int gc0308_set_resolution(struct gc0308 *gc0308, int *ret)
+{
+ struct cci_reg_sequence resolution_regs[] = {
+ {GC0308_SUBSAMPLE, gc0308->mode.subsample},
+ {GC0308_SUBMODE, 0x03},
+ {GC0308_SUB_ROW_N1, 0x00},
+ {GC0308_SUB_ROW_N2, 0x00},
+ {GC0308_SUB_COL_N1, 0x00},
+ {GC0308_SUB_COL_N2, 0x00},
+ {GC0308_CROP_WIN_MODE, 0x80},
+ {GC0308_CROP_WIN_Y1, 0x00},
+ {GC0308_CROP_WIN_X1, 0x00},
+ {GC0308_CROP_WIN_HEIGHT, gc0308->mode.height},
+ {GC0308_CROP_WIN_WIDTH, gc0308->mode.width},
+ };
+
+ return cci_multi_reg_write(gc0308->regmap, resolution_regs,
+ ARRAY_SIZE(resolution_regs), ret);
+}
+
+static int gc0308_start_stream(struct gc0308 *gc0308)
+{
+ int ret, sync_mode;
+
+ ret = pm_runtime_resume_and_get(gc0308->dev);
+ if (ret < 0)
+ return ret;
+
+ cci_multi_reg_write(gc0308->regmap, sensor_default_regs,
+ ARRAY_SIZE(sensor_default_regs), &ret);
+ cci_update_bits(gc0308->regmap, GC0308_OUT_FORMAT,
+ GENMASK(4, 0), gc0308->mode.out_format, &ret);
+ gc0308_set_resolution(gc0308, &ret);
+
+ if (ret) {
+ dev_err(gc0308->dev, "failed to update registers: %d\n", ret);
+ goto disable_pm;
+ }
+
+ ret = __v4l2_ctrl_handler_setup(&gc0308->hdl);
+ if (ret) {
+ dev_err(gc0308->dev, "failed to setup controls\n");
+ goto disable_pm;
+ }
+
+ /* HSYNC/VSYNC polarity */
+ sync_mode = 0x3;
+ if (gc0308->mbus_config & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+ sync_mode &= ~BIT(0);
+ if (gc0308->mbus_config & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+ sync_mode &= ~BIT(1);
+ ret = cci_write(gc0308->regmap, GC0308_SYNC_MODE, sync_mode, NULL);
+ if (ret)
+ goto disable_pm;
+
+ return 0;
+
+disable_pm:
+ pm_runtime_mark_last_busy(gc0308->dev);
+ pm_runtime_put_autosuspend(gc0308->dev);
+ return ret;
+}
+
+static int gc0308_stop_stream(struct gc0308 *gc0308)
+{
+ pm_runtime_mark_last_busy(gc0308->dev);
+ pm_runtime_put_autosuspend(gc0308->dev);
+ return 0;
+}
+
+static int gc0308_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct gc0308 *gc0308 = to_gc0308(sd);
+ struct v4l2_subdev_state *sd_state;
+ int ret;
+
+ sd_state = v4l2_subdev_lock_and_get_active_state(sd);
+
+ if (enable)
+ ret = gc0308_start_stream(gc0308);
+ else
+ ret = gc0308_stop_stream(gc0308);
+
+ v4l2_subdev_unlock_state(sd_state);
+ return ret;
+}
+
+static const struct v4l2_subdev_video_ops gc0308_video_ops = {
+ .s_stream = gc0308_s_stream,
+};
+
+static const struct v4l2_subdev_ops gc0308_subdev_ops = {
+ .core = &gc0308_core_ops,
+ .pad = &gc0308_pad_ops,
+ .video = &gc0308_video_ops,
+};
+
+static const struct v4l2_subdev_internal_ops gc0308_internal_ops = {
+ .init_state = gc0308_init_state,
+};
+
+static int gc0308_bus_config(struct gc0308 *gc0308)
+{
+ struct device *dev = gc0308->dev;
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_PARALLEL
+ };
+ struct fwnode_handle *ep;
+ int ret;
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
+ if (!ep)
+ return -EINVAL;
+
+ ret = v4l2_fwnode_endpoint_parse(ep, &bus_cfg);
+ fwnode_handle_put(ep);
+ if (ret)
+ return ret;
+
+ gc0308->mbus_config = bus_cfg.bus.parallel.flags;
+
+ return 0;
+}
+
+static const char * const gc0308_test_pattern_menu[] = {
+ "Disabled",
+ "Test Image 1",
+ "Test Image 2",
+};
+
+static int gc0308_init_controls(struct gc0308 *gc0308)
+{
+ int ret;
+
+ v4l2_ctrl_handler_init(&gc0308->hdl, 11);
+ gc0308->hblank = v4l2_ctrl_new_std(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_HBLANK, GC0308_HBLANK_MIN,
+ GC0308_HBLANK_MAX, 1,
+ GC0308_HBLANK_DEF);
+ gc0308->vblank = v4l2_ctrl_new_std(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_VBLANK, GC0308_VBLANK_MIN,
+ GC0308_VBLANK_MAX, 1,
+ GC0308_VBLANK_DEF);
+ gc0308->hflip = v4l2_ctrl_new_std(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ gc0308->vflip = v4l2_ctrl_new_std(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(&gc0308->hdl, &gc0308_ctrl_ops, V4L2_CID_PIXEL_RATE,
+ GC0308_PIXEL_RATE, GC0308_PIXEL_RATE, 1,
+ GC0308_PIXEL_RATE);
+ v4l2_ctrl_new_std(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+ v4l2_ctrl_new_std_menu_items(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(gc0308_test_pattern_menu) - 1,
+ 0, 0, gc0308_test_pattern_menu);
+ v4l2_ctrl_new_std_menu(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+ 8, ~0x14e, V4L2_WHITE_BALANCE_AUTO);
+ v4l2_ctrl_new_std_menu(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_COLORFX, 8, 0, V4L2_COLORFX_NONE);
+ v4l2_ctrl_new_std_menu(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_POWER_LINE_FREQUENCY,
+ V4L2_CID_POWER_LINE_FREQUENCY_60HZ,
+ ~0x6, V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
+ v4l2_ctrl_new_int_menu(&gc0308->hdl, &gc0308_ctrl_ops,
+ V4L2_CID_AUTO_EXPOSURE_BIAS,
+ ARRAY_SIZE(gc0308_exposure_menu) - 1,
+ ARRAY_SIZE(gc0308_exposure_menu) / 2,
+ gc0308_exposure_menu);
+
+ gc0308->sd.ctrl_handler = &gc0308->hdl;
+ if (gc0308->hdl.error) {
+ ret = gc0308->hdl.error;
+ v4l2_ctrl_handler_free(&gc0308->hdl);
+ return ret;
+ }
+
+ v4l2_ctrl_cluster(2, &gc0308->hflip);
+ v4l2_ctrl_cluster(2, &gc0308->hblank);
+
+ return 0;
+}
+
+static int gc0308_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct gc0308 *gc0308;
+ unsigned long clkrate;
+ u64 regval;
+ int ret;
+
+ gc0308 = devm_kzalloc(dev, sizeof(*gc0308), GFP_KERNEL);
+ if (!gc0308)
+ return -ENOMEM;
+
+ gc0308->dev = dev;
+ dev_set_drvdata(dev, gc0308);
+
+ ret = gc0308_bus_config(gc0308);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get bus config\n");
+
+ gc0308->clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(gc0308->clk))
+ return dev_err_probe(dev, PTR_ERR(gc0308->clk),
+ "could not get clk\n");
+
+ gc0308->vdd = devm_regulator_get(dev, "vdd28");
+ if (IS_ERR(gc0308->vdd))
+ return dev_err_probe(dev, PTR_ERR(gc0308->vdd),
+ "failed to get vdd28 regulator\n");
+
+ gc0308->pwdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW);
+ if (IS_ERR(gc0308->pwdn_gpio))
+ return dev_err_probe(dev, PTR_ERR(gc0308->pwdn_gpio),
+ "failed to get powerdown gpio\n");
+
+ gc0308->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(gc0308->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(gc0308->reset_gpio),
+ "failed to get reset gpio\n");
+
+ /*
+ * This is not using devm_cci_regmap_init_i2c(), because the driver
+ * makes use of regmap's pagination feature. The chosen settings are
+ * compatible with the CCI helpers.
+ */
+ gc0308->regmap = devm_regmap_init_i2c(client, &gc0308_regmap_config);
+ if (IS_ERR(gc0308->regmap))
+ return dev_err_probe(dev, PTR_ERR(gc0308->regmap),
+ "failed to init regmap\n");
+
+ v4l2_i2c_subdev_init(&gc0308->sd, client, &gc0308_subdev_ops);
+ gc0308->sd.internal_ops = &gc0308_internal_ops;
+ gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ gc0308->sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
+
+ ret = gc0308_init_controls(gc0308);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to init controls\n");
+
+ gc0308->sd.state_lock = gc0308->hdl.lock;
+ gc0308->pad.flags = MEDIA_PAD_FL_SOURCE;
+ gc0308->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+ ret = media_entity_pads_init(&gc0308->sd.entity, 1, &gc0308->pad);
+ if (ret < 0)
+ goto fail_ctrl_hdl_cleanup;
+
+ ret = v4l2_subdev_init_finalize(&gc0308->sd);
+ if (ret)
+ goto fail_media_entity_cleanup;
+
+ ret = gc0308_power_on(dev);
+ if (ret)
+ goto fail_subdev_cleanup;
+
+ if (gc0308->clk) {
+ clkrate = clk_get_rate(gc0308->clk);
+ if (clkrate != 24000000)
+ dev_warn(dev, "unexpected clock rate: %lu\n", clkrate);
+ }
+
+ ret = cci_read(gc0308->regmap, GC0308_CHIP_ID, &regval, NULL);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "failed to read chip ID\n");
+ goto fail_power_off;
+ }
+
+ if (regval != 0x9b) {
+ ret = -EINVAL;
+ dev_err_probe(dev, ret, "invalid chip ID (%02llx)\n", regval);
+ goto fail_power_off;
+ }
+
+ /*
+ * Enable runtime PM with autosuspend. As the device has been powered
+ * manually, mark it as active, and increase the usage count without
+ * resuming the device.
+ */
+ pm_runtime_set_active(dev);
+ pm_runtime_get_noresume(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(dev, 1000);
+ pm_runtime_use_autosuspend(dev);
+
+ ret = v4l2_async_register_subdev(&gc0308->sd);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to register v4l subdev\n");
+ goto fail_rpm;
+ }
+
+ return 0;
+
+fail_rpm:
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
+fail_power_off:
+ gc0308_power_off(dev);
+fail_subdev_cleanup:
+ v4l2_subdev_cleanup(&gc0308->sd);
+fail_media_entity_cleanup:
+ media_entity_cleanup(&gc0308->sd.entity);
+fail_ctrl_hdl_cleanup:
+ v4l2_ctrl_handler_free(&gc0308->hdl);
+ return ret;
+}
+
+static void gc0308_remove(struct i2c_client *client)
+{
+ struct gc0308 *gc0308 = i2c_get_clientdata(client);
+ struct device *dev = &client->dev;
+
+ v4l2_async_unregister_subdev(&gc0308->sd);
+ v4l2_ctrl_handler_free(&gc0308->hdl);
+ media_entity_cleanup(&gc0308->sd.entity);
+
+ pm_runtime_disable(dev);
+ if (!pm_runtime_status_suspended(dev))
+ gc0308_power_off(dev);
+ pm_runtime_set_suspended(dev);
+}
+
+static const struct dev_pm_ops gc0308_pm_ops = {
+ SET_RUNTIME_PM_OPS(gc0308_power_off, gc0308_power_on, NULL)
+};
+
+static const struct of_device_id gc0308_of_match[] = {
+ { .compatible = "galaxycore,gc0308" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, gc0308_of_match);
+
+static struct i2c_driver gc0308_i2c_driver = {
+ .driver = {
+ .name = "gc0308",
+ .pm = &gc0308_pm_ops,
+ .of_match_table = gc0308_of_match,
+ },
+ .probe = gc0308_probe,
+ .remove = gc0308_remove,
+};
+module_i2c_driver(gc0308_i2c_driver);
+
+MODULE_DESCRIPTION("GalaxyCore GC0308 Camera Driver");
+MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/gc2145.c b/drivers/media/i2c/gc2145.c
new file mode 100644
index 0000000000..bef7b0e056
--- /dev/null
+++ b/drivers/media/i2c/gc2145.c
@@ -0,0 +1,1450 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * A V4L2 driver for Galaxycore GC2145 camera.
+ * Copyright (C) 2023, STMicroelectronics SA
+ *
+ * Inspired by the imx219.c driver
+ *
+ * Datasheet v1.0 available at http://files.pine64.org/doc/datasheet/PinebookPro/GC2145%20CSP%20DataSheet%20release%20V1.0_20131201.pdf
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-cci.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mediabus.h>
+
+/* Chip ID */
+#define GC2145_CHIP_ID 0x2145
+
+/* Page 0 */
+#define GC2145_REG_EXPOSURE CCI_REG16(0x03)
+#define GC2145_REG_HBLANK CCI_REG16(0x05)
+#define GC2145_REG_VBLANK CCI_REG16(0x07)
+#define GC2145_REG_ROW_START CCI_REG16(0x09)
+#define GC2145_REG_COL_START CCI_REG16(0x0b)
+#define GC2145_REG_WIN_HEIGHT CCI_REG16(0x0d)
+#define GC2145_REG_WIN_WIDTH CCI_REG16(0x0f)
+#define GC2145_REG_ANALOG_MODE1 CCI_REG8(0x17)
+#define GC2145_REG_OUTPUT_FMT CCI_REG8(0x84)
+#define GC2145_REG_SYNC_MODE CCI_REG8(0x86)
+#define GC2145_SYNC_MODE_COL_SWITCH BIT(4)
+#define GC2145_SYNC_MODE_ROW_SWITCH BIT(5)
+#define GC2145_REG_BYPASS_MODE CCI_REG8(0x89)
+#define GC2145_BYPASS_MODE_SWITCH BIT(5)
+#define GC2145_REG_DEBUG_MODE2 CCI_REG8(0x8c)
+#define GC2145_REG_DEBUG_MODE3 CCI_REG8(0x8d)
+#define GC2145_REG_CROP_ENABLE CCI_REG8(0x90)
+#define GC2145_REG_CROP_Y CCI_REG16(0x91)
+#define GC2145_REG_CROP_X CCI_REG16(0x93)
+#define GC2145_REG_CROP_HEIGHT CCI_REG16(0x95)
+#define GC2145_REG_CROP_WIDTH CCI_REG16(0x97)
+#define GC2145_REG_GLOBAL_GAIN CCI_REG8(0xb0)
+#define GC2145_REG_CHIP_ID CCI_REG16(0xf0)
+#define GC2145_REG_PAD_IO CCI_REG8(0xf2)
+#define GC2145_REG_PAGE_SELECT CCI_REG8(0xfe)
+/* Page 3 */
+#define GC2145_REG_DPHY_ANALOG_MODE1 CCI_REG8(0x01)
+#define GC2145_DPHY_MODE_PHY_CLK_EN BIT(0)
+#define GC2145_DPHY_MODE_PHY_LANE0_EN BIT(1)
+#define GC2145_DPHY_MODE_PHY_LANE1_EN BIT(2)
+#define GC2145_DPHY_MODE_PHY_CLK_LANE_P2S_SEL BIT(7)
+#define GC2145_REG_DPHY_ANALOG_MODE2 CCI_REG8(0x02)
+#define GC2145_DPHY_CLK_DIFF(a) ((a) & 0x07)
+#define GC2145_DPHY_LANE0_DIFF(a) (((a) & 0x07) << 4)
+#define GC2145_REG_DPHY_ANALOG_MODE3 CCI_REG8(0x03)
+#define GC2145_DPHY_LANE1_DIFF(a) ((a) & 0x07)
+#define GC2145_DPHY_CLK_DELAY BIT(4)
+#define GC2145_DPHY_LANE0_DELAY BIT(5)
+#define GC2145_DPHY_LANE1_DELAY BIT(6)
+#define GC2145_REG_FIFO_FULL_LVL_LOW CCI_REG8(0x04)
+#define GC2145_REG_FIFO_FULL_LVL_HIGH CCI_REG8(0x05)
+#define GC2145_REG_FIFO_MODE CCI_REG8(0x06)
+#define GC2145_FIFO_MODE_READ_GATE BIT(3)
+#define GC2145_FIFO_MODE_MIPI_CLK_MODULE BIT(7)
+#define GC2145_REG_BUF_CSI2_MODE CCI_REG8(0x10)
+#define GC2145_CSI2_MODE_DOUBLE BIT(0)
+#define GC2145_CSI2_MODE_RAW8 BIT(2)
+#define GC2145_CSI2_MODE_MIPI_EN BIT(4)
+#define GC2145_CSI2_MODE_EN BIT(7)
+#define GC2145_REG_MIPI_DT CCI_REG8(0x11)
+#define GC2145_REG_LWC_LOW CCI_REG8(0x12)
+#define GC2145_REG_LWC_HIGH CCI_REG8(0x13)
+#define GC2145_REG_DPHY_MODE CCI_REG8(0x15)
+#define GC2145_DPHY_MODE_TRIGGER_PROG BIT(4)
+#define GC2145_REG_FIFO_GATE_MODE CCI_REG8(0x17)
+#define GC2145_REG_T_LPX CCI_REG8(0x21)
+#define GC2145_REG_T_CLK_HS_PREPARE CCI_REG8(0x22)
+#define GC2145_REG_T_CLK_ZERO CCI_REG8(0x23)
+#define GC2145_REG_T_CLK_PRE CCI_REG8(0x24)
+#define GC2145_REG_T_CLK_POST CCI_REG8(0x25)
+#define GC2145_REG_T_CLK_TRAIL CCI_REG8(0x26)
+#define GC2145_REG_T_HS_EXIT CCI_REG8(0x27)
+#define GC2145_REG_T_WAKEUP CCI_REG8(0x28)
+#define GC2145_REG_T_HS_PREPARE CCI_REG8(0x29)
+#define GC2145_REG_T_HS_ZERO CCI_REG8(0x2a)
+#define GC2145_REG_T_HS_TRAIL CCI_REG8(0x2b)
+
+/* External clock frequency is 24.0MHz */
+#define GC2145_XCLK_FREQ (24 * HZ_PER_MHZ)
+
+#define GC2145_NATIVE_WIDTH 1616U
+#define GC2145_NATIVE_HEIGHT 1232U
+
+/**
+ * struct gc2145_mode - GC2145 mode description
+ * @width: frame width (in pixels)
+ * @height: frame height (in pixels)
+ * @reg_seq: registers config sequence to enter into the mode
+ * @reg_seq_size: size of the sequence
+ * @pixel_rate: pixel rate associated with the mode
+ * @crop: window area captured
+ * @hblank: default horizontal blanking
+ * @vblank: default vertical blanking
+ * @link_freq_index: index within the link frequency menu
+ */
+struct gc2145_mode {
+ unsigned int width;
+ unsigned int height;
+ const struct cci_reg_sequence *reg_seq;
+ size_t reg_seq_size;
+ unsigned long pixel_rate;
+ struct v4l2_rect crop;
+ unsigned int hblank;
+ unsigned int vblank;
+ unsigned int link_freq_index;
+};
+
+#define GC2145_DEFAULT_EXPOSURE 0x04e2
+#define GC2145_DEFAULT_GLOBAL_GAIN 0x55
+static const struct cci_reg_sequence gc2145_common_regs[] = {
+ {GC2145_REG_PAGE_SELECT, 0x00},
+ /* SH Delay */
+ {CCI_REG8(0x12), 0x2e},
+ /* Flip */
+ {GC2145_REG_ANALOG_MODE1, 0x14},
+ /* Analog Conf */
+ {CCI_REG8(0x18), 0x22}, {CCI_REG8(0x19), 0x0e}, {CCI_REG8(0x1a), 0x01},
+ {CCI_REG8(0x1b), 0x4b}, {CCI_REG8(0x1c), 0x07}, {CCI_REG8(0x1d), 0x10},
+ {CCI_REG8(0x1e), 0x88}, {CCI_REG8(0x1f), 0x78}, {CCI_REG8(0x20), 0x03},
+ {CCI_REG8(0x21), 0x40}, {CCI_REG8(0x22), 0xa0}, {CCI_REG8(0x24), 0x16},
+ {CCI_REG8(0x25), 0x01}, {CCI_REG8(0x26), 0x10}, {CCI_REG8(0x2d), 0x60},
+ {CCI_REG8(0x30), 0x01}, {CCI_REG8(0x31), 0x90}, {CCI_REG8(0x33), 0x06},
+ {CCI_REG8(0x34), 0x01},
+ /* ISP related */
+ {CCI_REG8(0x80), 0x7f}, {CCI_REG8(0x81), 0x26}, {CCI_REG8(0x82), 0xfa},
+ {CCI_REG8(0x83), 0x00}, {CCI_REG8(0x84), 0x02}, {CCI_REG8(0x86), 0x02},
+ {CCI_REG8(0x88), 0x03},
+ {GC2145_REG_BYPASS_MODE, 0x03},
+ {CCI_REG8(0x85), 0x08}, {CCI_REG8(0x8a), 0x00}, {CCI_REG8(0x8b), 0x00},
+ {GC2145_REG_GLOBAL_GAIN, GC2145_DEFAULT_GLOBAL_GAIN},
+ {CCI_REG8(0xc3), 0x00}, {CCI_REG8(0xc4), 0x80}, {CCI_REG8(0xc5), 0x90},
+ {CCI_REG8(0xc6), 0x3b}, {CCI_REG8(0xc7), 0x46},
+ /* BLK */
+ {GC2145_REG_PAGE_SELECT, 0x00},
+ {CCI_REG8(0x40), 0x42}, {CCI_REG8(0x41), 0x00}, {CCI_REG8(0x43), 0x5b},
+ {CCI_REG8(0x5e), 0x00}, {CCI_REG8(0x5f), 0x00}, {CCI_REG8(0x60), 0x00},
+ {CCI_REG8(0x61), 0x00}, {CCI_REG8(0x62), 0x00}, {CCI_REG8(0x63), 0x00},
+ {CCI_REG8(0x64), 0x00}, {CCI_REG8(0x65), 0x00}, {CCI_REG8(0x66), 0x20},
+ {CCI_REG8(0x67), 0x20}, {CCI_REG8(0x68), 0x20}, {CCI_REG8(0x69), 0x20},
+ {CCI_REG8(0x76), 0x00}, {CCI_REG8(0x6a), 0x08}, {CCI_REG8(0x6b), 0x08},
+ {CCI_REG8(0x6c), 0x08}, {CCI_REG8(0x6d), 0x08}, {CCI_REG8(0x6e), 0x08},
+ {CCI_REG8(0x6f), 0x08}, {CCI_REG8(0x70), 0x08}, {CCI_REG8(0x71), 0x08},
+ {CCI_REG8(0x76), 0x00}, {CCI_REG8(0x72), 0xf0}, {CCI_REG8(0x7e), 0x3c},
+ {CCI_REG8(0x7f), 0x00},
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0x48), 0x15}, {CCI_REG8(0x49), 0x00}, {CCI_REG8(0x4b), 0x0b},
+ /* AEC */
+ {GC2145_REG_PAGE_SELECT, 0x00},
+ {GC2145_REG_EXPOSURE, GC2145_DEFAULT_EXPOSURE},
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ {CCI_REG8(0x01), 0x04}, {CCI_REG8(0x02), 0xc0}, {CCI_REG8(0x03), 0x04},
+ {CCI_REG8(0x04), 0x90}, {CCI_REG8(0x05), 0x30}, {CCI_REG8(0x06), 0x90},
+ {CCI_REG8(0x07), 0x30}, {CCI_REG8(0x08), 0x80}, {CCI_REG8(0x09), 0x00},
+ {CCI_REG8(0x0a), 0x82}, {CCI_REG8(0x0b), 0x11}, {CCI_REG8(0x0c), 0x10},
+ {CCI_REG8(0x11), 0x10}, {CCI_REG8(0x13), 0x7b}, {CCI_REG8(0x17), 0x00},
+ {CCI_REG8(0x1c), 0x11}, {CCI_REG8(0x1e), 0x61}, {CCI_REG8(0x1f), 0x35},
+ {CCI_REG8(0x20), 0x40}, {CCI_REG8(0x22), 0x40}, {CCI_REG8(0x23), 0x20},
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0x0f), 0x04},
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ {CCI_REG8(0x12), 0x35}, {CCI_REG8(0x15), 0xb0}, {CCI_REG8(0x10), 0x31},
+ {CCI_REG8(0x3e), 0x28}, {CCI_REG8(0x3f), 0xb0}, {CCI_REG8(0x40), 0x90},
+ {CCI_REG8(0x41), 0x0f},
+ /* INTPEE */
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0x90), 0x6c}, {CCI_REG8(0x91), 0x03}, {CCI_REG8(0x92), 0xcb},
+ {CCI_REG8(0x94), 0x33}, {CCI_REG8(0x95), 0x84}, {CCI_REG8(0x97), 0x65},
+ {CCI_REG8(0xa2), 0x11},
+ /* DNDD */
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0x80), 0xc1}, {CCI_REG8(0x81), 0x08}, {CCI_REG8(0x82), 0x05},
+ {CCI_REG8(0x83), 0x08}, {CCI_REG8(0x84), 0x0a}, {CCI_REG8(0x86), 0xf0},
+ {CCI_REG8(0x87), 0x50}, {CCI_REG8(0x88), 0x15}, {CCI_REG8(0x89), 0xb0},
+ {CCI_REG8(0x8a), 0x30}, {CCI_REG8(0x8b), 0x10},
+ /* ASDE */
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ {CCI_REG8(0x21), 0x04},
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0xa3), 0x50}, {CCI_REG8(0xa4), 0x20}, {CCI_REG8(0xa5), 0x40},
+ {CCI_REG8(0xa6), 0x80}, {CCI_REG8(0xab), 0x40}, {CCI_REG8(0xae), 0x0c},
+ {CCI_REG8(0xb3), 0x46}, {CCI_REG8(0xb4), 0x64}, {CCI_REG8(0xb6), 0x38},
+ {CCI_REG8(0xb7), 0x01}, {CCI_REG8(0xb9), 0x2b}, {CCI_REG8(0x3c), 0x04},
+ {CCI_REG8(0x3d), 0x15}, {CCI_REG8(0x4b), 0x06}, {CCI_REG8(0x4c), 0x20},
+ /* Gamma */
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0x10), 0x09}, {CCI_REG8(0x11), 0x0d}, {CCI_REG8(0x12), 0x13},
+ {CCI_REG8(0x13), 0x19}, {CCI_REG8(0x14), 0x27}, {CCI_REG8(0x15), 0x37},
+ {CCI_REG8(0x16), 0x45}, {CCI_REG8(0x17), 0x53}, {CCI_REG8(0x18), 0x69},
+ {CCI_REG8(0x19), 0x7d}, {CCI_REG8(0x1a), 0x8f}, {CCI_REG8(0x1b), 0x9d},
+ {CCI_REG8(0x1c), 0xa9}, {CCI_REG8(0x1d), 0xbd}, {CCI_REG8(0x1e), 0xcd},
+ {CCI_REG8(0x1f), 0xd9}, {CCI_REG8(0x20), 0xe3}, {CCI_REG8(0x21), 0xea},
+ {CCI_REG8(0x22), 0xef}, {CCI_REG8(0x23), 0xf5}, {CCI_REG8(0x24), 0xf9},
+ {CCI_REG8(0x25), 0xff},
+ {GC2145_REG_PAGE_SELECT, 0x00},
+ {CCI_REG8(0xc6), 0x20}, {CCI_REG8(0xc7), 0x2b},
+ /* Gamma 2 */
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0x26), 0x0f}, {CCI_REG8(0x27), 0x14}, {CCI_REG8(0x28), 0x19},
+ {CCI_REG8(0x29), 0x1e}, {CCI_REG8(0x2a), 0x27}, {CCI_REG8(0x2b), 0x33},
+ {CCI_REG8(0x2c), 0x3b}, {CCI_REG8(0x2d), 0x45}, {CCI_REG8(0x2e), 0x59},
+ {CCI_REG8(0x2f), 0x69}, {CCI_REG8(0x30), 0x7c}, {CCI_REG8(0x31), 0x89},
+ {CCI_REG8(0x32), 0x98}, {CCI_REG8(0x33), 0xae}, {CCI_REG8(0x34), 0xc0},
+ {CCI_REG8(0x35), 0xcf}, {CCI_REG8(0x36), 0xda}, {CCI_REG8(0x37), 0xe2},
+ {CCI_REG8(0x38), 0xe9}, {CCI_REG8(0x39), 0xf3}, {CCI_REG8(0x3a), 0xf9},
+ {CCI_REG8(0x3b), 0xff},
+ /* YCP */
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0xd1), 0x32}, {CCI_REG8(0xd2), 0x32}, {CCI_REG8(0xd3), 0x40},
+ {CCI_REG8(0xd6), 0xf0}, {CCI_REG8(0xd7), 0x10}, {CCI_REG8(0xd8), 0xda},
+ {CCI_REG8(0xdd), 0x14}, {CCI_REG8(0xde), 0x86}, {CCI_REG8(0xed), 0x80},
+ {CCI_REG8(0xee), 0x00}, {CCI_REG8(0xef), 0x3f}, {CCI_REG8(0xd8), 0xd8},
+ /* ABS */
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ {CCI_REG8(0x9f), 0x40},
+ /* LSC */
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ {CCI_REG8(0xc2), 0x14}, {CCI_REG8(0xc3), 0x0d}, {CCI_REG8(0xc4), 0x0c},
+ {CCI_REG8(0xc8), 0x15}, {CCI_REG8(0xc9), 0x0d}, {CCI_REG8(0xca), 0x0a},
+ {CCI_REG8(0xbc), 0x24}, {CCI_REG8(0xbd), 0x10}, {CCI_REG8(0xbe), 0x0b},
+ {CCI_REG8(0xb6), 0x25}, {CCI_REG8(0xb7), 0x16}, {CCI_REG8(0xb8), 0x15},
+ {CCI_REG8(0xc5), 0x00}, {CCI_REG8(0xc6), 0x00}, {CCI_REG8(0xc7), 0x00},
+ {CCI_REG8(0xcb), 0x00}, {CCI_REG8(0xcc), 0x00}, {CCI_REG8(0xcd), 0x00},
+ {CCI_REG8(0xbf), 0x07}, {CCI_REG8(0xc0), 0x00}, {CCI_REG8(0xc1), 0x00},
+ {CCI_REG8(0xb9), 0x00}, {CCI_REG8(0xba), 0x00}, {CCI_REG8(0xbb), 0x00},
+ {CCI_REG8(0xaa), 0x01}, {CCI_REG8(0xab), 0x01}, {CCI_REG8(0xac), 0x00},
+ {CCI_REG8(0xad), 0x05}, {CCI_REG8(0xae), 0x06}, {CCI_REG8(0xaf), 0x0e},
+ {CCI_REG8(0xb0), 0x0b}, {CCI_REG8(0xb1), 0x07}, {CCI_REG8(0xb2), 0x06},
+ {CCI_REG8(0xb3), 0x17}, {CCI_REG8(0xb4), 0x0e}, {CCI_REG8(0xb5), 0x0e},
+ {CCI_REG8(0xd0), 0x09}, {CCI_REG8(0xd1), 0x00}, {CCI_REG8(0xd2), 0x00},
+ {CCI_REG8(0xd6), 0x08}, {CCI_REG8(0xd7), 0x00}, {CCI_REG8(0xd8), 0x00},
+ {CCI_REG8(0xd9), 0x00}, {CCI_REG8(0xda), 0x00}, {CCI_REG8(0xdb), 0x00},
+ {CCI_REG8(0xd3), 0x0a}, {CCI_REG8(0xd4), 0x00}, {CCI_REG8(0xd5), 0x00},
+ {CCI_REG8(0xa4), 0x00}, {CCI_REG8(0xa5), 0x00}, {CCI_REG8(0xa6), 0x77},
+ {CCI_REG8(0xa7), 0x77}, {CCI_REG8(0xa8), 0x77}, {CCI_REG8(0xa9), 0x77},
+ {CCI_REG8(0xa1), 0x80}, {CCI_REG8(0xa2), 0x80},
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ {CCI_REG8(0xdf), 0x0d}, {CCI_REG8(0xdc), 0x25}, {CCI_REG8(0xdd), 0x30},
+ {CCI_REG8(0xe0), 0x77}, {CCI_REG8(0xe1), 0x80}, {CCI_REG8(0xe2), 0x77},
+ {CCI_REG8(0xe3), 0x90}, {CCI_REG8(0xe6), 0x90}, {CCI_REG8(0xe7), 0xa0},
+ {CCI_REG8(0xe8), 0x90}, {CCI_REG8(0xe9), 0xa0},
+ /* AWB */
+ /* measure window */
+ {GC2145_REG_PAGE_SELECT, 0x00},
+ {CCI_REG8(0xec), 0x06}, {CCI_REG8(0xed), 0x04}, {CCI_REG8(0xee), 0x60},
+ {CCI_REG8(0xef), 0x90}, {CCI_REG8(0xb6), 0x01},
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ {CCI_REG8(0x4f), 0x00}, {CCI_REG8(0x4f), 0x00}, {CCI_REG8(0x4b), 0x01},
+ {CCI_REG8(0x4f), 0x00},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x71}, {CCI_REG8(0x4e), 0x01},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x91}, {CCI_REG8(0x4e), 0x01},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x70}, {CCI_REG8(0x4e), 0x01},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x90}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xb0}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x8f}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x6f}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xaf}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xd0}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xf0}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xcf}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xef}, {CCI_REG8(0x4e), 0x02},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x6e}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x8e}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xae}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xce}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x4d}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x6d}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x8d}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xad}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xcd}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x4c}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x6c}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x8c}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xac}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xcc}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xcb}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x4b}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x6b}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x8b}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xab}, {CCI_REG8(0x4e), 0x03},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x8a}, {CCI_REG8(0x4e), 0x04},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xaa}, {CCI_REG8(0x4e), 0x04},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xca}, {CCI_REG8(0x4e), 0x04},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xca}, {CCI_REG8(0x4e), 0x04},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xc9}, {CCI_REG8(0x4e), 0x04},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x8a}, {CCI_REG8(0x4e), 0x04},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0x89}, {CCI_REG8(0x4e), 0x04},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xa9}, {CCI_REG8(0x4e), 0x04},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x0b}, {CCI_REG8(0x4e), 0x05},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x0a}, {CCI_REG8(0x4e), 0x05},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xeb}, {CCI_REG8(0x4e), 0x05},
+ {CCI_REG8(0x4c), 0x01}, {CCI_REG8(0x4d), 0xea}, {CCI_REG8(0x4e), 0x05},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x09}, {CCI_REG8(0x4e), 0x05},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x29}, {CCI_REG8(0x4e), 0x05},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x2a}, {CCI_REG8(0x4e), 0x05},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x4a}, {CCI_REG8(0x4e), 0x05},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x8a}, {CCI_REG8(0x4e), 0x06},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x49}, {CCI_REG8(0x4e), 0x06},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x69}, {CCI_REG8(0x4e), 0x06},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x89}, {CCI_REG8(0x4e), 0x06},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xa9}, {CCI_REG8(0x4e), 0x06},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x48}, {CCI_REG8(0x4e), 0x06},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x68}, {CCI_REG8(0x4e), 0x06},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0x69}, {CCI_REG8(0x4e), 0x06},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xca}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xc9}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xe9}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x03}, {CCI_REG8(0x4d), 0x09}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xc8}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xe8}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xa7}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xc7}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x02}, {CCI_REG8(0x4d), 0xe7}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4c), 0x03}, {CCI_REG8(0x4d), 0x07}, {CCI_REG8(0x4e), 0x07},
+ {CCI_REG8(0x4f), 0x01},
+ {CCI_REG8(0x50), 0x80}, {CCI_REG8(0x51), 0xa8}, {CCI_REG8(0x52), 0x47},
+ {CCI_REG8(0x53), 0x38}, {CCI_REG8(0x54), 0xc7}, {CCI_REG8(0x56), 0x0e},
+ {CCI_REG8(0x58), 0x08}, {CCI_REG8(0x5b), 0x00}, {CCI_REG8(0x5c), 0x74},
+ {CCI_REG8(0x5d), 0x8b}, {CCI_REG8(0x61), 0xdb}, {CCI_REG8(0x62), 0xb8},
+ {CCI_REG8(0x63), 0x86}, {CCI_REG8(0x64), 0xc0}, {CCI_REG8(0x65), 0x04},
+ {CCI_REG8(0x67), 0xa8}, {CCI_REG8(0x68), 0xb0}, {CCI_REG8(0x69), 0x00},
+ {CCI_REG8(0x6a), 0xa8}, {CCI_REG8(0x6b), 0xb0}, {CCI_REG8(0x6c), 0xaf},
+ {CCI_REG8(0x6d), 0x8b}, {CCI_REG8(0x6e), 0x50}, {CCI_REG8(0x6f), 0x18},
+ {CCI_REG8(0x73), 0xf0}, {CCI_REG8(0x70), 0x0d}, {CCI_REG8(0x71), 0x60},
+ {CCI_REG8(0x72), 0x80}, {CCI_REG8(0x74), 0x01}, {CCI_REG8(0x75), 0x01},
+ {CCI_REG8(0x7f), 0x0c}, {CCI_REG8(0x76), 0x70}, {CCI_REG8(0x77), 0x58},
+ {CCI_REG8(0x78), 0xa0}, {CCI_REG8(0x79), 0x5e}, {CCI_REG8(0x7a), 0x54},
+ {CCI_REG8(0x7b), 0x58},
+ /* CC */
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0xc0), 0x01}, {CCI_REG8(0xc1), 0x44}, {CCI_REG8(0xc2), 0xfd},
+ {CCI_REG8(0xc3), 0x04}, {CCI_REG8(0xc4), 0xf0}, {CCI_REG8(0xc5), 0x48},
+ {CCI_REG8(0xc6), 0xfd}, {CCI_REG8(0xc7), 0x46}, {CCI_REG8(0xc8), 0xfd},
+ {CCI_REG8(0xc9), 0x02}, {CCI_REG8(0xca), 0xe0}, {CCI_REG8(0xcb), 0x45},
+ {CCI_REG8(0xcc), 0xec}, {CCI_REG8(0xcd), 0x48}, {CCI_REG8(0xce), 0xf0},
+ {CCI_REG8(0xcf), 0xf0}, {CCI_REG8(0xe3), 0x0c}, {CCI_REG8(0xe4), 0x4b},
+ {CCI_REG8(0xe5), 0xe0},
+ /* ABS */
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ {CCI_REG8(0x9f), 0x40},
+ /* Dark sun */
+ {GC2145_REG_PAGE_SELECT, 0x02},
+ {CCI_REG8(0x40), 0xbf}, {CCI_REG8(0x46), 0xcf},
+};
+
+#define GC2145_640_480_PIXELRATE 30000000
+#define GC2145_640_480_LINKFREQ 120000000
+#define GC2145_640_480_HBLANK 0x0130
+#define GC2145_640_480_VBLANK 0x000c
+static const struct cci_reg_sequence gc2145_mode_640_480_regs[] = {
+ {GC2145_REG_PAGE_SELECT, 0xf0}, {GC2145_REG_PAGE_SELECT, 0xf0},
+ {GC2145_REG_PAGE_SELECT, 0xf0}, {CCI_REG8(0xfc), 0x06},
+ {CCI_REG8(0xf6), 0x00}, {CCI_REG8(0xf7), 0x1d}, {CCI_REG8(0xf8), 0x86},
+ {CCI_REG8(0xfa), 0x00}, {CCI_REG8(0xf9), 0x8e},
+ /* Disable PAD IO */
+ {GC2145_REG_PAD_IO, 0x00},
+ {GC2145_REG_PAGE_SELECT, 0x00},
+ /* Row/Col start - 0/0 */
+ {GC2145_REG_ROW_START, 0x0000},
+ {GC2145_REG_COL_START, 0x0000},
+ /* Window size 1216/1618 */
+ {GC2145_REG_WIN_HEIGHT, 0x04c0},
+ {GC2145_REG_WIN_WIDTH, 0x0652},
+ /* Scalar more */
+ {CCI_REG8(0xfd), 0x01}, {CCI_REG8(0xfa), 0x00},
+ /* Crop 640-480@0-0 */
+ {GC2145_REG_CROP_ENABLE, 0x01},
+ {GC2145_REG_CROP_Y, 0x0000},
+ {GC2145_REG_CROP_X, 0x0000},
+ {GC2145_REG_CROP_HEIGHT, 0x01e0},
+ {GC2145_REG_CROP_WIDTH, 0x0280},
+ /* Subsampling configuration */
+ {CCI_REG8(0x99), 0x55}, {CCI_REG8(0x9a), 0x06}, {CCI_REG8(0x9b), 0x01},
+ {CCI_REG8(0x9c), 0x23}, {CCI_REG8(0x9d), 0x00}, {CCI_REG8(0x9e), 0x00},
+ {CCI_REG8(0x9f), 0x01}, {CCI_REG8(0xa0), 0x23}, {CCI_REG8(0xa1), 0x00},
+ {CCI_REG8(0xa2), 0x00},
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ /* AEC anti-flicker */
+ {CCI_REG16(0x25), 0x0175},
+ /* AEC exposure level 1-5 */
+ {CCI_REG16(0x27), 0x045f}, {CCI_REG16(0x29), 0x045f},
+ {CCI_REG16(0x2b), 0x045f}, {CCI_REG16(0x2d), 0x045f},
+};
+
+#define GC2145_1280_720_PIXELRATE 48000000
+#define GC2145_1280_720_LINKFREQ 192000000
+#define GC2145_1280_720_HBLANK 0x0156
+#define GC2145_1280_720_VBLANK 0x0011
+static const struct cci_reg_sequence gc2145_mode_1280_720_regs[] = {
+ {GC2145_REG_PAGE_SELECT, 0xf0}, {GC2145_REG_PAGE_SELECT, 0xf0},
+ {GC2145_REG_PAGE_SELECT, 0xf0}, {CCI_REG8(0xfc), 0x06},
+ {CCI_REG8(0xf6), 0x00}, {CCI_REG8(0xf7), 0x1d}, {CCI_REG8(0xf8), 0x83},
+ {CCI_REG8(0xfa), 0x00}, {CCI_REG8(0xf9), 0x8e},
+ /* Disable PAD IO */
+ {GC2145_REG_PAD_IO, 0x00},
+ {GC2145_REG_PAGE_SELECT, 0x00},
+ /* Row/Col start - 240/160 */
+ {GC2145_REG_ROW_START, 0x00f0},
+ {GC2145_REG_COL_START, 0x00a0},
+ /* Window size 736/1296 */
+ {GC2145_REG_WIN_HEIGHT, 0x02e0},
+ {GC2145_REG_WIN_WIDTH, 0x0510},
+ /* Crop 1280-720@0-0 */
+ {GC2145_REG_CROP_ENABLE, 0x01},
+ {GC2145_REG_CROP_Y, 0x0000},
+ {GC2145_REG_CROP_X, 0x0000},
+ {GC2145_REG_CROP_HEIGHT, 0x02d0},
+ {GC2145_REG_CROP_WIDTH, 0x0500},
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ /* AEC anti-flicker */
+ {CCI_REG16(0x25), 0x00e6},
+ /* AEC exposure level 1-5 */
+ {CCI_REG16(0x27), 0x02b2}, {CCI_REG16(0x29), 0x02b2},
+ {CCI_REG16(0x2b), 0x02b2}, {CCI_REG16(0x2d), 0x02b2},
+};
+
+#define GC2145_1600_1200_PIXELRATE 60000000
+#define GC2145_1600_1200_LINKFREQ 240000000
+#define GC2145_1600_1200_HBLANK 0x0156
+#define GC2145_1600_1200_VBLANK 0x0010
+static const struct cci_reg_sequence gc2145_mode_1600_1200_regs[] = {
+ {GC2145_REG_PAGE_SELECT, 0xf0}, {GC2145_REG_PAGE_SELECT, 0xf0},
+ {GC2145_REG_PAGE_SELECT, 0xf0}, {CCI_REG8(0xfc), 0x06},
+ {CCI_REG8(0xf6), 0x00}, {CCI_REG8(0xf7), 0x1d}, {CCI_REG8(0xf8), 0x84},
+ {CCI_REG8(0xfa), 0x00}, {CCI_REG8(0xf9), 0x8e},
+ /* Disable PAD IO */
+ {GC2145_REG_PAD_IO, 0x00},
+ {GC2145_REG_PAGE_SELECT, 0x00},
+ /* Row/Col start - 0/0 */
+ {GC2145_REG_ROW_START, 0x0000},
+ {GC2145_REG_COL_START, 0x0000},
+ /* Window size: 1216/1618 */
+ {GC2145_REG_WIN_HEIGHT, 0x04c0},
+ {GC2145_REG_WIN_WIDTH, 0x0652},
+ /* Crop 1600-1200@0-0 */
+ {GC2145_REG_CROP_ENABLE, 0x01},
+ {GC2145_REG_CROP_Y, 0x0000},
+ {GC2145_REG_CROP_X, 0x0000},
+ {GC2145_REG_CROP_HEIGHT, 0x04b0},
+ {GC2145_REG_CROP_WIDTH, 0x0640},
+ {GC2145_REG_PAGE_SELECT, 0x01},
+ /* AEC anti-flicker */
+ {CCI_REG16(0x25), 0x00fa},
+ /* AEC exposure level 1-5 */
+ {CCI_REG16(0x27), 0x04e2}, {CCI_REG16(0x29), 0x04e2},
+ {CCI_REG16(0x2b), 0x04e2}, {CCI_REG16(0x2d), 0x04e2},
+};
+
+static const s64 gc2145_link_freq_menu[] = {
+ GC2145_640_480_LINKFREQ,
+ GC2145_1280_720_LINKFREQ,
+ GC2145_1600_1200_LINKFREQ,
+};
+
+/* Regulators supplies */
+static const char * const gc2145_supply_name[] = {
+ "iovdd", /* Digital I/O (1.7-3V) suppply */
+ "avdd", /* Analog (2.7-3V) supply */
+ "dvdd", /* Digital Core (1.7-1.9V) supply */
+};
+
+#define GC2145_NUM_SUPPLIES ARRAY_SIZE(gc2145_supply_name)
+
+/* Mode configs */
+#define GC2145_MODE_640X480 0
+#define GC2145_MODE_1280X720 1
+#define GC2145_MODE_1600X1200 2
+static const struct gc2145_mode supported_modes[] = {
+ {
+ /* 640x480 30fps mode */
+ .width = 640,
+ .height = 480,
+ .reg_seq = gc2145_mode_640_480_regs,
+ .reg_seq_size = ARRAY_SIZE(gc2145_mode_640_480_regs),
+ .pixel_rate = GC2145_640_480_PIXELRATE,
+ .crop = {
+ .top = 0,
+ .left = 0,
+ .width = 640,
+ .height = 480,
+ },
+ .hblank = GC2145_640_480_HBLANK,
+ .vblank = GC2145_640_480_VBLANK,
+ .link_freq_index = GC2145_MODE_640X480,
+ },
+ {
+ /* 1280x720 30fps mode */
+ .width = 1280,
+ .height = 720,
+ .reg_seq = gc2145_mode_1280_720_regs,
+ .reg_seq_size = ARRAY_SIZE(gc2145_mode_1280_720_regs),
+ .pixel_rate = GC2145_1280_720_PIXELRATE,
+ .crop = {
+ .top = 160,
+ .left = 240,
+ .width = 1280,
+ .height = 720,
+ },
+ .hblank = GC2145_1280_720_HBLANK,
+ .vblank = GC2145_1280_720_VBLANK,
+ .link_freq_index = GC2145_MODE_1280X720,
+ },
+ {
+ /* 1600x1200 20fps mode */
+ .width = 1600,
+ .height = 1200,
+ .reg_seq = gc2145_mode_1600_1200_regs,
+ .reg_seq_size = ARRAY_SIZE(gc2145_mode_1600_1200_regs),
+ .pixel_rate = GC2145_1600_1200_PIXELRATE,
+ .crop = {
+ .top = 0,
+ .left = 0,
+ .width = 1600,
+ .height = 1200,
+ },
+ .hblank = GC2145_1600_1200_HBLANK,
+ .vblank = GC2145_1600_1200_VBLANK,
+ .link_freq_index = GC2145_MODE_1600X1200,
+ },
+};
+
+/**
+ * struct gc2145_format - GC2145 pixel format description
+ * @code: media bus (MBUS) associated code
+ * @datatype: MIPI CSI2 data type
+ * @output_fmt: GC2145 output format
+ * @switch_bit: GC2145 first/second switch
+ */
+struct gc2145_format {
+ unsigned int code;
+ unsigned char datatype;
+ unsigned char output_fmt;
+ bool switch_bit;
+};
+
+/* All supported formats */
+static const struct gc2145_format supported_formats[] = {
+ {
+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .datatype = MIPI_CSI2_DT_YUV422_8B,
+ .output_fmt = 0x00,
+ },
+ {
+ .code = MEDIA_BUS_FMT_VYUY8_1X16,
+ .datatype = MIPI_CSI2_DT_YUV422_8B,
+ .output_fmt = 0x01,
+ },
+ {
+ .code = MEDIA_BUS_FMT_YUYV8_1X16,
+ .datatype = MIPI_CSI2_DT_YUV422_8B,
+ .output_fmt = 0x02,
+ },
+ {
+ .code = MEDIA_BUS_FMT_YVYU8_1X16,
+ .datatype = MIPI_CSI2_DT_YUV422_8B,
+ .output_fmt = 0x03,
+ },
+ {
+ .code = MEDIA_BUS_FMT_RGB565_1X16,
+ .datatype = MIPI_CSI2_DT_RGB565,
+ .output_fmt = 0x06,
+ .switch_bit = true,
+ },
+};
+
+struct gc2145_ctrls {
+ struct v4l2_ctrl_handler handler;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *test_pattern;
+ struct v4l2_ctrl *hflip;
+ struct v4l2_ctrl *vflip;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *vblank;
+};
+
+struct gc2145 {
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+
+ struct regmap *regmap;
+ struct clk *xclk;
+
+ struct gpio_desc *reset_gpio;
+ struct gpio_desc *powerdown_gpio;
+ struct regulator_bulk_data supplies[GC2145_NUM_SUPPLIES];
+
+ /* V4L2 controls */
+ struct gc2145_ctrls ctrls;
+
+ /* Current mode */
+ const struct gc2145_mode *mode;
+};
+
+static inline struct gc2145 *to_gc2145(struct v4l2_subdev *_sd)
+{
+ return container_of(_sd, struct gc2145, sd);
+}
+
+static inline struct v4l2_subdev *gc2145_ctrl_to_sd(struct v4l2_ctrl *ctrl)
+{
+ return &container_of(ctrl->handler, struct gc2145,
+ ctrls.handler)->sd;
+}
+
+static const struct gc2145_format *
+gc2145_get_format_code(struct gc2145 *gc2145, u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
+ if (supported_formats[i].code == code)
+ break;
+ }
+
+ if (i >= ARRAY_SIZE(supported_formats))
+ i = 0;
+
+ return &supported_formats[i];
+}
+
+static void gc2145_update_pad_format(struct gc2145 *gc2145,
+ const struct gc2145_mode *mode,
+ struct v4l2_mbus_framefmt *fmt, u32 code)
+{
+ fmt->code = code;
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+ fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
+ fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+}
+
+static int gc2145_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct gc2145 *gc2145 = to_gc2145(sd);
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *crop;
+
+ /* Initialize pad format */
+ format = v4l2_subdev_state_get_format(state, 0);
+ gc2145_update_pad_format(gc2145, &supported_modes[0], format,
+ MEDIA_BUS_FMT_RGB565_1X16);
+
+ /* Initialize crop rectangle. */
+ crop = v4l2_subdev_state_get_crop(state, 0);
+ *crop = supported_modes[0].crop;
+
+ return 0;
+}
+
+static int gc2145_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_selection *sel)
+{
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP:
+ sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
+ return 0;
+
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = GC2145_NATIVE_WIDTH;
+ sel->r.height = GC2145_NATIVE_HEIGHT;
+
+ return 0;
+
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = 1600;
+ sel->r.height = 1200;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int gc2145_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index >= ARRAY_SIZE(supported_formats))
+ return -EINVAL;
+
+ code->code = supported_formats[code->index].code;
+ return 0;
+}
+
+static int gc2145_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct gc2145 *gc2145 = to_gc2145(sd);
+ const struct gc2145_format *gc2145_format;
+ u32 code;
+
+ if (fse->index >= ARRAY_SIZE(supported_modes))
+ return -EINVAL;
+
+ gc2145_format = gc2145_get_format_code(gc2145, fse->code);
+ code = gc2145_format->code;
+ if (fse->code != code)
+ return -EINVAL;
+
+ fse->min_width = supported_modes[fse->index].width;
+ fse->max_width = fse->min_width;
+ fse->min_height = supported_modes[fse->index].height;
+ fse->max_height = fse->min_height;
+
+ return 0;
+}
+
+static int gc2145_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct gc2145 *gc2145 = to_gc2145(sd);
+ const struct gc2145_mode *mode;
+ const struct gc2145_format *gc2145_fmt;
+ struct v4l2_mbus_framefmt *framefmt;
+ struct gc2145_ctrls *ctrls = &gc2145->ctrls;
+ struct v4l2_rect *crop;
+
+ gc2145_fmt = gc2145_get_format_code(gc2145, fmt->format.code);
+ mode = v4l2_find_nearest_size(supported_modes,
+ ARRAY_SIZE(supported_modes),
+ width, height,
+ fmt->format.width, fmt->format.height);
+
+ gc2145_update_pad_format(gc2145, mode, &fmt->format, gc2145_fmt->code);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ gc2145->mode = mode;
+ /* Update pixel_rate based on the mode */
+ __v4l2_ctrl_s_ctrl_int64(ctrls->pixel_rate, mode->pixel_rate);
+ /* Update link_freq based on the mode */
+ __v4l2_ctrl_s_ctrl(ctrls->link_freq, mode->link_freq_index);
+ /* Update hblank/vblank based on the mode */
+ __v4l2_ctrl_s_ctrl(ctrls->hblank, mode->hblank);
+ __v4l2_ctrl_s_ctrl(ctrls->vblank, mode->vblank);
+ }
+ *framefmt = fmt->format;
+ crop = v4l2_subdev_state_get_crop(sd_state, fmt->pad);
+ *crop = mode->crop;
+
+ return 0;
+}
+
+static const struct cci_reg_sequence gc2145_common_mipi_regs[] = {
+ {GC2145_REG_PAGE_SELECT, 0x03},
+ {GC2145_REG_DPHY_ANALOG_MODE1, GC2145_DPHY_MODE_PHY_CLK_EN |
+ GC2145_DPHY_MODE_PHY_LANE0_EN |
+ GC2145_DPHY_MODE_PHY_LANE1_EN |
+ GC2145_DPHY_MODE_PHY_CLK_LANE_P2S_SEL},
+ {GC2145_REG_DPHY_ANALOG_MODE2, GC2145_DPHY_CLK_DIFF(2) |
+ GC2145_DPHY_LANE0_DIFF(2)},
+ {GC2145_REG_DPHY_ANALOG_MODE3, GC2145_DPHY_LANE1_DIFF(0) |
+ GC2145_DPHY_CLK_DELAY},
+ {GC2145_REG_FIFO_MODE, GC2145_FIFO_MODE_READ_GATE |
+ GC2145_FIFO_MODE_MIPI_CLK_MODULE},
+ {GC2145_REG_DPHY_MODE, GC2145_DPHY_MODE_TRIGGER_PROG},
+ /* Clock & Data lanes timing */
+ {GC2145_REG_T_LPX, 0x10},
+ {GC2145_REG_T_CLK_HS_PREPARE, 0x04}, {GC2145_REG_T_CLK_ZERO, 0x10},
+ {GC2145_REG_T_CLK_PRE, 0x10}, {GC2145_REG_T_CLK_POST, 0x10},
+ {GC2145_REG_T_CLK_TRAIL, 0x05},
+ {GC2145_REG_T_HS_PREPARE, 0x03}, {GC2145_REG_T_HS_ZERO, 0x0a},
+ {GC2145_REG_T_HS_TRAIL, 0x06},
+};
+
+static int gc2145_config_mipi_mode(struct gc2145 *gc2145,
+ const struct gc2145_format *gc2145_format)
+{
+ u16 lwc, fifo_full_lvl;
+ int ret = 0;
+
+ /* Common MIPI settings */
+ cci_multi_reg_write(gc2145->regmap, gc2145_common_mipi_regs,
+ ARRAY_SIZE(gc2145_common_mipi_regs), &ret);
+
+ /*
+ * Adjust the MIPI buffer settings.
+ * For YUV/RGB, LWC = image width * 2
+ * For RAW8, LWC = image width
+ * For RAW10, LWC = image width * 1.25
+ */
+ lwc = gc2145->mode->width * 2;
+ cci_write(gc2145->regmap, GC2145_REG_LWC_HIGH, lwc >> 8, &ret);
+ cci_write(gc2145->regmap, GC2145_REG_LWC_LOW, lwc & 0xff, &ret);
+
+ /*
+ * Adjust the MIPI FIFO Full Level
+ * 640x480 RGB: 0x0190
+ * 1280x720 / 1600x1200 (aka no scaler) non RAW: 0x0001
+ * 1600x1200 RAW: 0x0190
+ */
+ if (gc2145->mode->width == 1280 || gc2145->mode->width == 1600)
+ fifo_full_lvl = 0x0001;
+ else
+ fifo_full_lvl = 0x0190;
+
+ cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL_HIGH,
+ fifo_full_lvl >> 8, &ret);
+ cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL_LOW,
+ fifo_full_lvl & 0xff, &ret);
+
+ /*
+ * Set the FIFO gate mode / MIPI wdiv set:
+ * 0xf1 in case of RAW mode and 0xf0 otherwise
+ */
+ cci_write(gc2145->regmap, GC2145_REG_FIFO_GATE_MODE, 0xf0, &ret);
+
+ /* Set the MIPI data type */
+ cci_write(gc2145->regmap, GC2145_REG_MIPI_DT,
+ gc2145_format->datatype, &ret);
+
+ /* Configure mode and enable CSI */
+ cci_write(gc2145->regmap, GC2145_REG_BUF_CSI2_MODE,
+ GC2145_CSI2_MODE_RAW8 | GC2145_CSI2_MODE_DOUBLE |
+ GC2145_CSI2_MODE_EN | GC2145_CSI2_MODE_MIPI_EN, &ret);
+
+ return ret;
+}
+
+static int gc2145_start_streaming(struct gc2145 *gc2145,
+ struct v4l2_subdev_state *state)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
+ const struct gc2145_format *gc2145_format;
+ struct v4l2_mbus_framefmt *fmt;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(&client->dev);
+ if (ret < 0)
+ return ret;
+
+ /* Apply default values of current mode */
+ cci_multi_reg_write(gc2145->regmap, gc2145->mode->reg_seq,
+ gc2145->mode->reg_seq_size, &ret);
+ cci_multi_reg_write(gc2145->regmap, gc2145_common_regs,
+ ARRAY_SIZE(gc2145_common_regs), &ret);
+ if (ret) {
+ dev_err(&client->dev, "%s failed to write regs\n", __func__);
+ goto err_rpm_put;
+ }
+
+ fmt = v4l2_subdev_state_get_format(state, 0);
+ gc2145_format = gc2145_get_format_code(gc2145, fmt->code);
+
+ /* Set the output format */
+ cci_write(gc2145->regmap, GC2145_REG_PAGE_SELECT, 0x00, &ret);
+
+ cci_write(gc2145->regmap, GC2145_REG_OUTPUT_FMT,
+ gc2145_format->output_fmt, &ret);
+ cci_update_bits(gc2145->regmap, GC2145_REG_BYPASS_MODE,
+ GC2145_BYPASS_MODE_SWITCH,
+ gc2145_format->switch_bit ? GC2145_BYPASS_MODE_SWITCH
+ : 0, &ret);
+ if (ret) {
+ dev_err(&client->dev, "%s failed to write regs\n", __func__);
+ goto err_rpm_put;
+ }
+
+ /* Apply customized values from user */
+ ret = __v4l2_ctrl_handler_setup(&gc2145->ctrls.handler);
+ if (ret) {
+ dev_err(&client->dev, "%s failed to apply ctrls\n", __func__);
+ goto err_rpm_put;
+ }
+
+ /* Perform MIPI specific configuration */
+ ret = gc2145_config_mipi_mode(gc2145, gc2145_format);
+ if (ret) {
+ dev_err(&client->dev, "%s failed to write mipi conf\n",
+ __func__);
+ goto err_rpm_put;
+ }
+
+ cci_write(gc2145->regmap, GC2145_REG_PAGE_SELECT, 0x00, &ret);
+
+ return 0;
+
+err_rpm_put:
+ pm_runtime_mark_last_busy(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
+ return ret;
+}
+
+static void gc2145_stop_streaming(struct gc2145 *gc2145)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
+ int ret = 0;
+
+ /* Disable lanes & mipi streaming */
+ cci_write(gc2145->regmap, GC2145_REG_PAGE_SELECT, 0x03, &ret);
+ cci_update_bits(gc2145->regmap, GC2145_REG_BUF_CSI2_MODE,
+ GC2145_CSI2_MODE_EN | GC2145_CSI2_MODE_MIPI_EN, 0,
+ &ret);
+ cci_write(gc2145->regmap, GC2145_REG_PAGE_SELECT, 0x00, &ret);
+ if (ret)
+ dev_err(&client->dev, "%s failed to write regs\n", __func__);
+
+ pm_runtime_mark_last_busy(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
+}
+
+static int gc2145_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct gc2145 *gc2145 = to_gc2145(sd);
+ struct v4l2_subdev_state *state;
+ int ret = 0;
+
+ state = v4l2_subdev_lock_and_get_active_state(sd);
+
+ if (enable)
+ ret = gc2145_start_streaming(gc2145, state);
+ else
+ gc2145_stop_streaming(gc2145);
+
+ v4l2_subdev_unlock_state(state);
+
+ return ret;
+}
+
+/* Power/clock management functions */
+static int gc2145_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct gc2145 *gc2145 = to_gc2145(sd);
+ int ret;
+
+ ret = regulator_bulk_enable(GC2145_NUM_SUPPLIES, gc2145->supplies);
+ if (ret) {
+ dev_err(dev, "failed to enable regulators\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(gc2145->xclk);
+ if (ret) {
+ dev_err(dev, "failed to enable clock\n");
+ goto reg_off;
+ }
+
+ gpiod_set_value_cansleep(gc2145->powerdown_gpio, 0);
+ gpiod_set_value_cansleep(gc2145->reset_gpio, 0);
+
+ /*
+ * Datasheet doesn't mention timing between PWDN/RESETB control and
+ * i2c access however, experimentation shows that a rather big delay is
+ * needed.
+ */
+ msleep(41);
+
+ return 0;
+
+reg_off:
+ regulator_bulk_disable(GC2145_NUM_SUPPLIES, gc2145->supplies);
+
+ return ret;
+}
+
+static int gc2145_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct gc2145 *gc2145 = to_gc2145(sd);
+
+ gpiod_set_value_cansleep(gc2145->powerdown_gpio, 1);
+ gpiod_set_value_cansleep(gc2145->reset_gpio, 1);
+ clk_disable_unprepare(gc2145->xclk);
+ regulator_bulk_disable(GC2145_NUM_SUPPLIES, gc2145->supplies);
+
+ return 0;
+}
+
+static int gc2145_get_regulators(struct gc2145 *gc2145)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
+ unsigned int i;
+
+ for (i = 0; i < GC2145_NUM_SUPPLIES; i++)
+ gc2145->supplies[i].supply = gc2145_supply_name[i];
+
+ return devm_regulator_bulk_get(&client->dev, GC2145_NUM_SUPPLIES,
+ gc2145->supplies);
+}
+
+/* Verify chip ID */
+static int gc2145_identify_module(struct gc2145 *gc2145)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
+ int ret;
+ u64 chip_id;
+
+ ret = cci_read(gc2145->regmap, GC2145_REG_CHIP_ID, &chip_id, NULL);
+ if (ret) {
+ dev_err(&client->dev, "failed to read chip id (%d)\n", ret);
+ return ret;
+ }
+
+ if (chip_id != GC2145_CHIP_ID) {
+ dev_err(&client->dev, "chip id mismatch: %x!=%llx\n",
+ GC2145_CHIP_ID, chip_id);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static const char * const test_pattern_menu[] = {
+ "Disabled",
+ "Colored patterns",
+ "Uniform white",
+ "Uniform yellow",
+ "Uniform cyan",
+ "Uniform green",
+ "Uniform magenta",
+ "Uniform red",
+ "Uniform black",
+};
+
+#define GC2145_TEST_PATTERN_ENABLE BIT(0)
+#define GC2145_TEST_PATTERN_UXGA BIT(3)
+
+#define GC2145_TEST_UNIFORM BIT(3)
+#define GC2145_TEST_WHITE (4 << 4)
+#define GC2145_TEST_YELLOW (8 << 4)
+#define GC2145_TEST_CYAN (9 << 4)
+#define GC2145_TEST_GREEN (6 << 4)
+#define GC2145_TEST_MAGENTA (10 << 4)
+#define GC2145_TEST_RED (5 << 4)
+#define GC2145_TEST_BLACK (0)
+
+static const u8 test_pattern_val[] = {
+ 0,
+ GC2145_TEST_PATTERN_ENABLE,
+ GC2145_TEST_UNIFORM | GC2145_TEST_WHITE,
+ GC2145_TEST_UNIFORM | GC2145_TEST_YELLOW,
+ GC2145_TEST_UNIFORM | GC2145_TEST_CYAN,
+ GC2145_TEST_UNIFORM | GC2145_TEST_GREEN,
+ GC2145_TEST_UNIFORM | GC2145_TEST_MAGENTA,
+ GC2145_TEST_UNIFORM | GC2145_TEST_RED,
+ GC2145_TEST_UNIFORM | GC2145_TEST_BLACK,
+};
+
+static const struct v4l2_subdev_core_ops gc2145_core_ops = {
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops gc2145_video_ops = {
+ .s_stream = gc2145_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops gc2145_pad_ops = {
+ .enum_mbus_code = gc2145_enum_mbus_code,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = gc2145_set_pad_format,
+ .get_selection = gc2145_get_selection,
+ .enum_frame_size = gc2145_enum_frame_size,
+};
+
+static const struct v4l2_subdev_ops gc2145_subdev_ops = {
+ .core = &gc2145_core_ops,
+ .video = &gc2145_video_ops,
+ .pad = &gc2145_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops gc2145_subdev_internal_ops = {
+ .init_state = gc2145_init_state,
+};
+
+static int gc2145_set_ctrl_test_pattern(struct gc2145 *gc2145, int value)
+{
+ int ret = 0;
+
+ if (!value) {
+ /* Disable test pattern */
+ cci_write(gc2145->regmap, GC2145_REG_DEBUG_MODE2, 0, &ret);
+ return cci_write(gc2145->regmap, GC2145_REG_DEBUG_MODE3, 0,
+ &ret);
+ }
+
+ /* Enable test pattern, colored or uniform */
+ cci_write(gc2145->regmap, GC2145_REG_DEBUG_MODE2,
+ GC2145_TEST_PATTERN_ENABLE | GC2145_TEST_PATTERN_UXGA, &ret);
+
+ if (!(test_pattern_val[value] & GC2145_TEST_UNIFORM))
+ return cci_write(gc2145->regmap, GC2145_REG_DEBUG_MODE3, 0,
+ &ret);
+
+ /* Uniform */
+ return cci_write(gc2145->regmap, GC2145_REG_DEBUG_MODE3,
+ test_pattern_val[value], &ret);
+}
+
+static int gc2145_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct v4l2_subdev *sd = gc2145_ctrl_to_sd(ctrl);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct gc2145 *gc2145 = to_gc2145(sd);
+ int ret;
+
+ if (pm_runtime_get_if_in_use(&client->dev) == 0)
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_HBLANK:
+ ret = cci_write(gc2145->regmap, GC2145_REG_HBLANK, ctrl->val,
+ NULL);
+ break;
+ case V4L2_CID_VBLANK:
+ ret = cci_write(gc2145->regmap, GC2145_REG_VBLANK, ctrl->val,
+ NULL);
+ break;
+ case V4L2_CID_TEST_PATTERN:
+ ret = gc2145_set_ctrl_test_pattern(gc2145, ctrl->val);
+ break;
+ case V4L2_CID_HFLIP:
+ ret = cci_update_bits(gc2145->regmap, GC2145_REG_ANALOG_MODE1,
+ BIT(0), (ctrl->val ? BIT(0) : 0), NULL);
+ break;
+ case V4L2_CID_VFLIP:
+ ret = cci_update_bits(gc2145->regmap, GC2145_REG_ANALOG_MODE1,
+ BIT(1), (ctrl->val ? BIT(1) : 0), NULL);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ pm_runtime_mark_last_busy(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops gc2145_ctrl_ops = {
+ .s_ctrl = gc2145_s_ctrl,
+};
+
+/* Initialize control handlers */
+static int gc2145_init_controls(struct gc2145 *gc2145)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&gc2145->sd);
+ const struct v4l2_ctrl_ops *ops = &gc2145_ctrl_ops;
+ struct gc2145_ctrls *ctrls = &gc2145->ctrls;
+ struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+ struct v4l2_fwnode_device_properties props;
+ int ret;
+
+ ret = v4l2_ctrl_handler_init(hdl, 12);
+ if (ret)
+ return ret;
+
+ ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
+ GC2145_640_480_PIXELRATE,
+ GC2145_1600_1200_PIXELRATE, 1,
+ supported_modes[0].pixel_rate);
+
+ ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops, V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(gc2145_link_freq_menu) - 1,
+ 0, gc2145_link_freq_menu);
+ if (ctrls->link_freq)
+ ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ ctrls->hblank = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HBLANK,
+ 0, 0xfff, 1, GC2145_640_480_HBLANK);
+
+ ctrls->vblank = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VBLANK,
+ 0, 0x1fff, 1, GC2145_640_480_VBLANK);
+
+ ctrls->test_pattern =
+ v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(test_pattern_menu) - 1,
+ 0, 0, test_pattern_menu);
+ ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
+ 0, 1, 1, 0);
+ ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
+ 0, 1, 1, 0);
+
+ if (hdl->error) {
+ ret = hdl->error;
+ dev_err(&client->dev, "control init failed (%d)\n", ret);
+ goto error;
+ }
+
+ ret = v4l2_fwnode_device_parse(&client->dev, &props);
+ if (ret)
+ goto error;
+
+ ret = v4l2_ctrl_new_fwnode_properties(hdl, &gc2145_ctrl_ops,
+ &props);
+ if (ret)
+ goto error;
+
+ gc2145->sd.ctrl_handler = hdl;
+
+ return 0;
+
+error:
+ v4l2_ctrl_handler_free(hdl);
+
+ return ret;
+}
+
+static int gc2145_check_hwcfg(struct device *dev)
+{
+ struct fwnode_handle *endpoint;
+ struct v4l2_fwnode_endpoint ep_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ int ret;
+
+ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
+ if (!endpoint) {
+ dev_err(dev, "endpoint node not found\n");
+ return -EINVAL;
+ }
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep_cfg);
+ fwnode_handle_put(endpoint);
+ if (ret)
+ return ret;
+
+ /* Check the number of MIPI CSI2 data lanes */
+ if (ep_cfg.bus.mipi_csi2.num_data_lanes != 2) {
+ dev_err(dev, "only 2 data lanes are currently supported\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Check the link frequency set in device tree */
+ if (!ep_cfg.nr_of_link_frequencies) {
+ dev_err(dev, "link-frequency property not found in DT\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (ep_cfg.nr_of_link_frequencies != 3 ||
+ ep_cfg.link_frequencies[0] != GC2145_640_480_LINKFREQ ||
+ ep_cfg.link_frequencies[1] != GC2145_1280_720_LINKFREQ ||
+ ep_cfg.link_frequencies[2] != GC2145_1600_1200_LINKFREQ) {
+ dev_err(dev, "Invalid link-frequencies provided\n");
+ ret = -EINVAL;
+ }
+
+out:
+ v4l2_fwnode_endpoint_free(&ep_cfg);
+
+ return ret;
+}
+
+static int gc2145_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ unsigned int xclk_freq;
+ struct gc2145 *gc2145;
+ int ret;
+
+ gc2145 = devm_kzalloc(&client->dev, sizeof(*gc2145), GFP_KERNEL);
+ if (!gc2145)
+ return -ENOMEM;
+
+ v4l2_i2c_subdev_init(&gc2145->sd, client, &gc2145_subdev_ops);
+ gc2145->sd.internal_ops = &gc2145_subdev_internal_ops;
+
+ /* Check the hardware configuration in device tree */
+ if (gc2145_check_hwcfg(dev))
+ return -EINVAL;
+
+ /* Get system clock (xclk) */
+ gc2145->xclk = devm_clk_get(dev, NULL);
+ if (IS_ERR(gc2145->xclk))
+ return dev_err_probe(dev, PTR_ERR(gc2145->xclk),
+ "failed to get xclk\n");
+
+ xclk_freq = clk_get_rate(gc2145->xclk);
+ if (xclk_freq != GC2145_XCLK_FREQ) {
+ dev_err(dev, "xclk frequency not supported: %d Hz\n",
+ xclk_freq);
+ return -EINVAL;
+ }
+
+ ret = gc2145_get_regulators(gc2145);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get regulators\n");
+
+ /* Request optional reset pin */
+ gc2145->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(gc2145->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(gc2145->reset_gpio),
+ "failed to get reset_gpio\n");
+
+ /* Request optional powerdown pin */
+ gc2145->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(gc2145->powerdown_gpio))
+ return dev_err_probe(dev, PTR_ERR(gc2145->powerdown_gpio),
+ "failed to get powerdown_gpio\n");
+
+ /* Initialise the regmap for further cci access */
+ gc2145->regmap = devm_cci_regmap_init_i2c(client, 8);
+ if (IS_ERR(gc2145->regmap))
+ return dev_err_probe(dev, PTR_ERR(gc2145->regmap),
+ "failed to get cci regmap\n");
+
+ /*
+ * The sensor must be powered for gc2145_identify_module()
+ * to be able to read the CHIP_ID register
+ */
+ ret = gc2145_power_on(dev);
+ if (ret)
+ return ret;
+
+ ret = gc2145_identify_module(gc2145);
+ if (ret)
+ goto error_power_off;
+
+ /* Set default mode */
+ gc2145->mode = &supported_modes[0];
+
+ ret = gc2145_init_controls(gc2145);
+ if (ret)
+ goto error_power_off;
+
+ /* Initialize subdev */
+ gc2145->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+ V4L2_SUBDEV_FL_HAS_EVENTS;
+ gc2145->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ /* Initialize source pad */
+ gc2145->pad.flags = MEDIA_PAD_FL_SOURCE;
+
+ ret = media_entity_pads_init(&gc2145->sd.entity, 1, &gc2145->pad);
+ if (ret) {
+ dev_err(dev, "failed to init entity pads: %d\n", ret);
+ goto error_handler_free;
+ }
+
+ gc2145->sd.state_lock = gc2145->ctrls.handler.lock;
+ ret = v4l2_subdev_init_finalize(&gc2145->sd);
+ if (ret < 0) {
+ dev_err(dev, "subdev init error: %d\n", ret);
+ goto error_media_entity;
+ }
+
+ /* Enable runtime PM and turn off the device */
+ pm_runtime_set_active(dev);
+ pm_runtime_get_noresume(&client->dev);
+ pm_runtime_enable(dev);
+
+ pm_runtime_set_autosuspend_delay(&client->dev, 1000);
+ pm_runtime_use_autosuspend(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
+
+ ret = v4l2_async_register_subdev_sensor(&gc2145->sd);
+ if (ret < 0) {
+ dev_err(dev, "failed to register sensor sub-device: %d\n", ret);
+ goto error_subdev_cleanup;
+ }
+
+ return 0;
+
+error_subdev_cleanup:
+ v4l2_subdev_cleanup(&gc2145->sd);
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+
+error_media_entity:
+ media_entity_cleanup(&gc2145->sd.entity);
+
+error_handler_free:
+ v4l2_ctrl_handler_free(&gc2145->ctrls.handler);
+
+error_power_off:
+ gc2145_power_off(dev);
+
+ return ret;
+}
+
+static void gc2145_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct gc2145 *gc2145 = to_gc2145(sd);
+
+ v4l2_subdev_cleanup(sd);
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(&gc2145->ctrls.handler);
+
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev))
+ gc2145_power_off(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+}
+
+static const struct of_device_id gc2145_dt_ids[] = {
+ { .compatible = "galaxycore,gc2145" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, gc2145_dt_ids);
+
+static const struct dev_pm_ops gc2145_pm_ops = {
+ RUNTIME_PM_OPS(gc2145_power_off, gc2145_power_on, NULL)
+};
+
+static struct i2c_driver gc2145_i2c_driver = {
+ .driver = {
+ .name = "gc2145",
+ .of_match_table = gc2145_dt_ids,
+ .pm = pm_ptr(&gc2145_pm_ops),
+ },
+ .probe = gc2145_probe,
+ .remove = gc2145_remove,
+};
+
+module_i2c_driver(gc2145_i2c_driver);
+
+MODULE_AUTHOR("Alain Volmat <alain.volmat@foss.st.com>");
+MODULE_DESCRIPTION("GalaxyCore GC2145 sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c
index f6ea9b7b97..38c77d5157 100644
--- a/drivers/media/i2c/hi556.c
+++ b/drivers/media/i2c/hi556.c
@@ -935,7 +935,7 @@ __hi556_get_pad_crop(struct hi556 *hi556,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&hi556->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &hi556->cur_mode->crop;
}
@@ -1075,7 +1075,7 @@ static int hi556_set_format(struct v4l2_subdev *sd,
mutex_lock(&hi556->mutex);
hi556_assign_pad_format(mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
} else {
hi556->cur_mode = mode;
__v4l2_ctrl_s_ctrl(hi556->link_freq, mode->link_freq_index);
@@ -1109,9 +1109,8 @@ static int hi556_get_format(struct v4l2_subdev *sd,
mutex_lock(&hi556->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&hi556->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
hi556_assign_pad_format(hi556->cur_mode, &fmt->format);
@@ -1157,10 +1156,10 @@ static int hi556_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&hi556->mutex);
hi556_assign_pad_format(&supported_modes[0],
- v4l2_subdev_get_try_format(sd, fh->state, 0));
+ v4l2_subdev_state_get_format(fh->state, 0));
/* Initialize try_crop rectangle. */
- try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
+ try_crop = v4l2_subdev_state_get_crop(fh->state, 0);
try_crop->top = HI556_PIXEL_ARRAY_TOP;
try_crop->left = HI556_PIXEL_ARRAY_LEFT;
try_crop->width = HI556_PIXEL_ARRAY_WIDTH;
diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c
index 825fc8dc48..9c565ec033 100644
--- a/drivers/media/i2c/hi846.c
+++ b/drivers/media/i2c/hi846.c
@@ -1705,7 +1705,7 @@ static int hi846_set_format(struct v4l2_subdev *sd,
}
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, format->pad) = *mf;
+ *v4l2_subdev_state_get_format(sd_state, format->pad) = *mf;
return 0;
}
@@ -1783,9 +1783,8 @@ static int hi846_get_format(struct v4l2_subdev *sd,
struct i2c_client *client = v4l2_get_subdevdata(sd);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- format->format = *v4l2_subdev_get_try_format(&hi846->sd,
- sd_state,
- format->pad);
+ format->format = *v4l2_subdev_state_get_format(sd_state,
+ format->pad);
return 0;
}
@@ -1852,7 +1851,7 @@ static int hi846_get_selection(struct v4l2_subdev *sd,
mutex_lock(&hi846->mutex);
switch (sel->which) {
case V4L2_SUBDEV_FORMAT_TRY:
- v4l2_subdev_get_try_crop(sd, sd_state, sel->pad);
+ v4l2_subdev_state_get_crop(sd_state, sel->pad);
break;
case V4L2_SUBDEV_FORMAT_ACTIVE:
sel->r = hi846->cur_mode->crop;
@@ -1872,13 +1871,13 @@ static int hi846_get_selection(struct v4l2_subdev *sd,
}
}
-static int hi846_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int hi846_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct hi846 *hi846 = to_hi846(sd);
struct v4l2_mbus_framefmt *mf;
- mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ mf = v4l2_subdev_state_get_format(sd_state, 0);
mutex_lock(&hi846->mutex);
mf->code = HI846_MEDIA_BUS_FORMAT;
@@ -1896,7 +1895,6 @@ static const struct v4l2_subdev_video_ops hi846_video_ops = {
};
static const struct v4l2_subdev_pad_ops hi846_pad_ops = {
- .init_cfg = hi846_init_cfg,
.enum_frame_size = hi846_enum_frame_size,
.enum_mbus_code = hi846_enum_mbus_code,
.set_fmt = hi846_set_format,
@@ -1909,6 +1907,10 @@ static const struct v4l2_subdev_ops hi846_subdev_ops = {
.pad = &hi846_pad_ops,
};
+static const struct v4l2_subdev_internal_ops hi846_internal_ops = {
+ .init_state = hi846_init_state,
+};
+
static const struct media_entity_operations hi846_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -2072,6 +2074,7 @@ static int hi846_probe(struct i2c_client *client)
return ret;
v4l2_i2c_subdev_init(&hi846->sd, client, &hi846_subdev_ops);
+ hi846->sd.internal_ops = &hi846_internal_ops;
mutex_init(&hi846->mutex);
diff --git a/drivers/media/i2c/hi847.c b/drivers/media/i2c/hi847.c
index 4075c38980..72c60747a8 100644
--- a/drivers/media/i2c/hi847.c
+++ b/drivers/media/i2c/hi847.c
@@ -2655,7 +2655,7 @@ static int hi847_set_format(struct v4l2_subdev *sd,
mutex_lock(&hi847->mutex);
hi847_assign_pad_format(mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) =
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) =
fmt->format;
} else {
hi847->cur_mode = mode;
@@ -2690,9 +2690,8 @@ static int hi847_get_format(struct v4l2_subdev *sd,
mutex_lock(&hi847->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&hi847->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
hi847_assign_pad_format(hi847->cur_mode, &fmt->format);
@@ -2737,7 +2736,7 @@ static int hi847_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&hi847->mutex);
hi847_assign_pad_format(&supported_modes[0],
- v4l2_subdev_get_try_format(sd, fh->state, 0));
+ v4l2_subdev_state_get_format(fh->state, 0));
mutex_unlock(&hi847->mutex);
return 0;
diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c
index a9b0aea1ae..639e05340d 100644
--- a/drivers/media/i2c/imx208.c
+++ b/drivers/media/i2c/imx208.c
@@ -395,7 +395,7 @@ static int imx208_write_regs(struct imx208 *imx208,
static int imx208_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
/* Initialize try_fmt */
try_fmt->width = supported_modes[0].width;
@@ -548,9 +548,8 @@ static int __imx208_get_pad_format(struct imx208 *imx208,
struct v4l2_subdev_format *fmt)
{
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&imx208->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
imx208_mode_to_pad_format(imx208, imx208->cur_mode, fmt);
@@ -591,7 +590,7 @@ static int imx208_set_pad_format(struct v4l2_subdev *sd,
fmt->format.width, fmt->format.height);
imx208_mode_to_pad_format(imx208, mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
} else {
imx208->cur_mode = mode;
__v4l2_ctrl_s_ctrl(imx208->link_freq, mode->link_freq_index);
diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
index 4f77ea02cc..b148b1bd2b 100644
--- a/drivers/media/i2c/imx214.c
+++ b/drivers/media/i2c/imx214.c
@@ -19,12 +19,31 @@
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
+#define IMX214_REG_MODE_SELECT 0x0100
+#define IMX214_MODE_STANDBY 0x00
+#define IMX214_MODE_STREAMING 0x01
+
#define IMX214_DEFAULT_CLK_FREQ 24000000
#define IMX214_DEFAULT_LINK_FREQ 480000000
#define IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * 8LL) / 10)
#define IMX214_FPS 30
#define IMX214_MBUS_CODE MEDIA_BUS_FMT_SRGGB10_1X10
+/* Exposure control */
+#define IMX214_REG_EXPOSURE 0x0202
+#define IMX214_EXPOSURE_MIN 0
+#define IMX214_EXPOSURE_MAX 3184
+#define IMX214_EXPOSURE_STEP 1
+#define IMX214_EXPOSURE_DEFAULT 3184
+
+/* IMX214 native and active pixel array size */
+#define IMX214_NATIVE_WIDTH 4224U
+#define IMX214_NATIVE_HEIGHT 3136U
+#define IMX214_PIXEL_ARRAY_LEFT 8U
+#define IMX214_PIXEL_ARRAY_TOP 8U
+#define IMX214_PIXEL_ARRAY_WIDTH 4208U
+#define IMX214_PIXEL_ARRAY_HEIGHT 3120U
+
static const char * const imx214_supply_name[] = {
"vdda",
"vddd",
@@ -538,7 +557,7 @@ __imx214_get_pad_format(struct imx214 *imx214,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&imx214->sd, sd_state, pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &imx214->fmt;
default:
@@ -568,7 +587,7 @@ __imx214_get_pad_crop(struct imx214 *imx214,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&imx214->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &imx214->crop;
default:
@@ -623,18 +642,35 @@ static int imx214_get_selection(struct v4l2_subdev *sd,
{
struct imx214 *imx214 = to_imx214(sd);
- if (sel->target != V4L2_SEL_TGT_CROP)
- return -EINVAL;
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP:
+ mutex_lock(&imx214->mutex);
+ sel->r = *__imx214_get_pad_crop(imx214, sd_state, sel->pad,
+ sel->which);
+ mutex_unlock(&imx214->mutex);
+ return 0;
- mutex_lock(&imx214->mutex);
- sel->r = *__imx214_get_pad_crop(imx214, sd_state, sel->pad,
- sel->which);
- mutex_unlock(&imx214->mutex);
- return 0;
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = IMX214_NATIVE_WIDTH;
+ sel->r.height = IMX214_NATIVE_HEIGHT;
+ return 0;
+
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = IMX214_PIXEL_ARRAY_TOP;
+ sel->r.left = IMX214_PIXEL_ARRAY_LEFT;
+ sel->r.width = IMX214_PIXEL_ARRAY_WIDTH;
+ sel->r.height = IMX214_PIXEL_ARRAY_HEIGHT;
+ return 0;
+ }
+
+ return -EINVAL;
}
-static int imx214_entity_init_cfg(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *sd_state)
+static int imx214_entity_init_state(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_subdev_format fmt = { };
@@ -665,7 +701,7 @@ static int imx214_set_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE:
vals[1] = ctrl->val;
vals[0] = ctrl->val >> 8;
- ret = regmap_bulk_write(imx214->regmap, 0x202, vals, 2);
+ ret = regmap_bulk_write(imx214->regmap, IMX214_REG_EXPOSURE, vals, 2);
if (ret < 0)
dev_err(imx214->dev, "Error %d\n", ret);
ret = 0;
@@ -684,6 +720,76 @@ static const struct v4l2_ctrl_ops imx214_ctrl_ops = {
.s_ctrl = imx214_set_ctrl,
};
+static int imx214_ctrls_init(struct imx214 *imx214)
+{
+ static const s64 link_freq[] = {
+ IMX214_DEFAULT_LINK_FREQ
+ };
+ static const struct v4l2_area unit_size = {
+ .width = 1120,
+ .height = 1120,
+ };
+ struct v4l2_fwnode_device_properties props;
+ struct v4l2_ctrl_handler *ctrl_hdlr;
+ int ret;
+
+ ret = v4l2_fwnode_device_parse(imx214->dev, &props);
+ if (ret < 0)
+ return ret;
+
+ ctrl_hdlr = &imx214->ctrls;
+ ret = v4l2_ctrl_handler_init(&imx214->ctrls, 6);
+ if (ret)
+ return ret;
+
+ imx214->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, NULL,
+ V4L2_CID_PIXEL_RATE, 0,
+ IMX214_DEFAULT_PIXEL_RATE, 1,
+ IMX214_DEFAULT_PIXEL_RATE);
+
+ imx214->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, NULL,
+ V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(link_freq) - 1,
+ 0, link_freq);
+ if (imx214->link_freq)
+ imx214->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ /*
+ * WARNING!
+ * Values obtained reverse engineering blobs and/or devices.
+ * Ranges and functionality might be wrong.
+ *
+ * Sony, please release some register set documentation for the
+ * device.
+ *
+ * Yours sincerely, Ricardo.
+ */
+ imx214->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx214_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ IMX214_EXPOSURE_MIN,
+ IMX214_EXPOSURE_MAX,
+ IMX214_EXPOSURE_STEP,
+ IMX214_EXPOSURE_DEFAULT);
+
+ imx214->unit_size = v4l2_ctrl_new_std_compound(ctrl_hdlr,
+ NULL,
+ V4L2_CID_UNIT_CELL_SIZE,
+ v4l2_ctrl_ptr_create((void *)&unit_size));
+
+ v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx214_ctrl_ops, &props);
+
+ ret = ctrl_hdlr->error;
+ if (ret) {
+ v4l2_ctrl_handler_free(ctrl_hdlr);
+ dev_err(imx214->dev, "failed to add controls: %d\n", ret);
+ return ret;
+ }
+
+ imx214->sd.ctrl_handler = ctrl_hdlr;
+
+ return 0;
+};
+
#define MAX_CMD 4
static int imx214_write_table(struct imx214 *imx214,
const struct reg_8 table[])
@@ -743,7 +849,7 @@ static int imx214_start_streaming(struct imx214 *imx214)
dev_err(imx214->dev, "could not sync v4l2 controls\n");
goto error;
}
- ret = regmap_write(imx214->regmap, 0x100, 1);
+ ret = regmap_write(imx214->regmap, IMX214_REG_MODE_SELECT, IMX214_MODE_STREAMING);
if (ret < 0) {
dev_err(imx214->dev, "could not sent start table %d\n", ret);
goto error;
@@ -761,7 +867,7 @@ static int imx214_stop_streaming(struct imx214 *imx214)
{
int ret;
- ret = regmap_write(imx214->regmap, 0x100, 0);
+ ret = regmap_write(imx214->regmap, IMX214_REG_MODE_SELECT, IMX214_MODE_STANDBY);
if (ret < 0)
dev_err(imx214->dev, "could not sent stop table %d\n", ret);
@@ -795,9 +901,17 @@ err_rpm_put:
return ret;
}
-static int imx214_g_frame_interval(struct v4l2_subdev *subdev,
- struct v4l2_subdev_frame_interval *fival)
+static int imx214_get_frame_interval(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fival)
{
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
fival->interval.numerator = 1;
fival->interval.denominator = IMX214_FPS;
@@ -828,8 +942,6 @@ static int imx214_enum_frame_interval(struct v4l2_subdev *subdev,
static const struct v4l2_subdev_video_ops imx214_video_ops = {
.s_stream = imx214_s_stream,
- .g_frame_interval = imx214_g_frame_interval,
- .s_frame_interval = imx214_g_frame_interval,
};
static const struct v4l2_subdev_pad_ops imx214_subdev_pad_ops = {
@@ -839,7 +951,8 @@ static const struct v4l2_subdev_pad_ops imx214_subdev_pad_ops = {
.get_fmt = imx214_get_format,
.set_fmt = imx214_set_format,
.get_selection = imx214_get_selection,
- .init_cfg = imx214_entity_init_cfg,
+ .get_frame_interval = imx214_get_frame_interval,
+ .set_frame_interval = imx214_get_frame_interval,
};
static const struct v4l2_subdev_ops imx214_subdev_ops = {
@@ -848,6 +961,10 @@ static const struct v4l2_subdev_ops imx214_subdev_ops = {
.pad = &imx214_subdev_pad_ops,
};
+static const struct v4l2_subdev_internal_ops imx214_internal_ops = {
+ .init_state = imx214_entity_init_state,
+};
+
static const struct regmap_config sensor_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
@@ -907,13 +1024,6 @@ static int imx214_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct imx214 *imx214;
- static const s64 link_freq[] = {
- IMX214_DEFAULT_LINK_FREQ,
- };
- static const struct v4l2_area unit_size = {
- .width = 1120,
- .height = 1120,
- };
int ret;
ret = imx214_parse_fwnode(dev);
@@ -957,6 +1067,7 @@ static int imx214_probe(struct i2c_client *client)
}
v4l2_i2c_subdev_init(&imx214->sd, client, &imx214_subdev_ops);
+ imx214->sd.internal_ops = &imx214_internal_ops;
/*
* Enable power initially, to avoid warnings
@@ -968,45 +1079,10 @@ static int imx214_probe(struct i2c_client *client)
pm_runtime_enable(imx214->dev);
pm_runtime_idle(imx214->dev);
- v4l2_ctrl_handler_init(&imx214->ctrls, 3);
-
- imx214->pixel_rate = v4l2_ctrl_new_std(&imx214->ctrls, NULL,
- V4L2_CID_PIXEL_RATE, 0,
- IMX214_DEFAULT_PIXEL_RATE, 1,
- IMX214_DEFAULT_PIXEL_RATE);
- imx214->link_freq = v4l2_ctrl_new_int_menu(&imx214->ctrls, NULL,
- V4L2_CID_LINK_FREQ,
- ARRAY_SIZE(link_freq) - 1,
- 0, link_freq);
- if (imx214->link_freq)
- imx214->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
- /*
- * WARNING!
- * Values obtained reverse engineering blobs and/or devices.
- * Ranges and functionality might be wrong.
- *
- * Sony, please release some register set documentation for the
- * device.
- *
- * Yours sincerely, Ricardo.
- */
- imx214->exposure = v4l2_ctrl_new_std(&imx214->ctrls, &imx214_ctrl_ops,
- V4L2_CID_EXPOSURE,
- 0, 3184, 1, 0x0c70);
-
- imx214->unit_size = v4l2_ctrl_new_std_compound(&imx214->ctrls,
- NULL,
- V4L2_CID_UNIT_CELL_SIZE,
- v4l2_ctrl_ptr_create((void *)&unit_size));
- ret = imx214->ctrls.error;
- if (ret) {
- dev_err(&client->dev, "%s control init failed (%d)\n",
- __func__, ret);
- goto free_ctrl;
- }
+ ret = imx214_ctrls_init(imx214);
+ if (ret < 0)
+ goto error_power_off;
- imx214->sd.ctrl_handler = &imx214->ctrls;
mutex_init(&imx214->mutex);
imx214->ctrls.lock = &imx214->mutex;
@@ -1021,7 +1097,7 @@ static int imx214_probe(struct i2c_client *client)
goto free_ctrl;
}
- imx214_entity_init_cfg(&imx214->sd, NULL);
+ imx214_entity_init_state(&imx214->sd, NULL);
ret = v4l2_async_register_subdev_sensor(&imx214->sd);
if (ret < 0) {
@@ -1036,6 +1112,7 @@ free_entity:
free_ctrl:
mutex_destroy(&imx214->mutex);
v4l2_ctrl_handler_free(&imx214->ctrls);
+error_power_off:
pm_runtime_disable(imx214->dev);
return ret;
diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index 8436880dcf..e17ef2e9d9 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -374,7 +374,7 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
int ret = 0;
state = v4l2_subdev_get_locked_active_state(&imx219->sd);
- format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
if (ctrl->id == V4L2_CID_VBLANK) {
int exposure_max, exposure_def;
@@ -593,8 +593,8 @@ static int imx219_set_framefmt(struct imx219 *imx219,
u64 bin_h, bin_v;
int ret = 0;
- format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0);
- crop = v4l2_subdev_get_pad_crop(&imx219->sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
+ crop = v4l2_subdev_state_get_crop(state, 0);
switch (format->code) {
case MEDIA_BUS_FMT_SRGGB8_1X8:
@@ -826,7 +826,7 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code);
- format = v4l2_subdev_get_pad_format(sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
*format = fmt->format;
/*
@@ -836,7 +836,7 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
bin_h = min(IMX219_PIXEL_ARRAY_WIDTH / format->width, 2U);
bin_v = min(IMX219_PIXEL_ARRAY_HEIGHT / format->height, 2U);
- crop = v4l2_subdev_get_pad_crop(sd, state, 0);
+ crop = v4l2_subdev_state_get_crop(state, 0);
crop->width = format->width * bin_h;
crop->height = format->height * bin_v;
crop->left = (IMX219_NATIVE_WIDTH - crop->width) / 2;
@@ -880,7 +880,7 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
{
switch (sel->target) {
case V4L2_SEL_TGT_CROP: {
- sel->r = *v4l2_subdev_get_pad_crop(sd, state, 0);
+ sel->r = *v4l2_subdev_state_get_crop(state, 0);
return 0;
}
@@ -905,8 +905,8 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
return -EINVAL;
}
-static int imx219_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int imx219_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_TRY,
@@ -933,7 +933,6 @@ static const struct v4l2_subdev_video_ops imx219_video_ops = {
};
static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
- .init_cfg = imx219_init_cfg,
.enum_mbus_code = imx219_enum_mbus_code,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = imx219_set_pad_format,
@@ -947,6 +946,9 @@ static const struct v4l2_subdev_ops imx219_subdev_ops = {
.pad = &imx219_pad_ops,
};
+static const struct v4l2_subdev_internal_ops imx219_internal_ops = {
+ .init_state = imx219_init_state,
+};
/* -----------------------------------------------------------------------------
* Power management
@@ -1098,6 +1100,7 @@ static int imx219_probe(struct i2c_client *client)
return -ENOMEM;
v4l2_i2c_subdev_init(&imx219->sd, client, &imx219_subdev_ops);
+ imx219->sd.internal_ops = &imx219_internal_ops;
/* Check the hardware configuration in device tree */
if (imx219_check_hwcfg(dev, imx219))
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index b3827f4bc0..a577afb530 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -708,7 +708,7 @@ static int imx258_write_regs(struct imx258 *imx258,
static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
/* Initialize try_fmt */
try_fmt->width = supported_modes[0].width;
@@ -862,9 +862,8 @@ static int __imx258_get_pad_format(struct imx258 *imx258,
struct v4l2_subdev_format *fmt)
{
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&imx258->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
imx258_update_pad_format(imx258->cur_mode, fmt);
@@ -908,7 +907,7 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd,
fmt->format.width, fmt->format.height);
imx258_update_pad_format(mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
imx258->cur_mode = mode;
diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c
index f33b692e69..352da68b8b 100644
--- a/drivers/media/i2c/imx274.c
+++ b/drivers/media/i2c/imx274.c
@@ -594,8 +594,8 @@ static int imx274_set_gain(struct stimx274 *priv, struct v4l2_ctrl *ctrl);
static int imx274_set_exposure(struct stimx274 *priv, int val);
static int imx274_set_vflip(struct stimx274 *priv, int val);
static int imx274_set_test_pattern(struct stimx274 *priv, int val);
-static int imx274_set_frame_interval(struct stimx274 *priv,
- struct v4l2_fract frame_interval);
+static int __imx274_set_frame_interval(struct stimx274 *priv,
+ struct v4l2_fract frame_interval);
static inline void msleep_range(unsigned int delay_base)
{
@@ -1018,8 +1018,8 @@ static int __imx274_change_compose(struct stimx274 *imx274,
int best_goodness = INT_MIN;
if (which == V4L2_SUBDEV_FORMAT_TRY) {
- cur_crop = &sd_state->pads->try_crop;
- tgt_fmt = &sd_state->pads->try_fmt;
+ cur_crop = v4l2_subdev_state_get_crop(sd_state, 0);
+ tgt_fmt = v4l2_subdev_state_get_format(sd_state, 0);
} else {
cur_crop = &imx274->crop;
tgt_fmt = &imx274->format;
@@ -1112,7 +1112,7 @@ static int imx274_set_fmt(struct v4l2_subdev *sd,
*/
fmt->field = V4L2_FIELD_NONE;
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- sd_state->pads->try_fmt = *fmt;
+ *v4l2_subdev_state_get_format(sd_state, 0) = *fmt;
else
imx274->format = *fmt;
@@ -1143,8 +1143,8 @@ static int imx274_get_selection(struct v4l2_subdev *sd,
}
if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
- src_crop = &sd_state->pads->try_crop;
- src_fmt = &sd_state->pads->try_fmt;
+ src_crop = v4l2_subdev_state_get_crop(sd_state, 0);
+ src_fmt = v4l2_subdev_state_get_format(sd_state, 0);
} else {
src_crop = &imx274->crop;
src_fmt = &imx274->format;
@@ -1215,7 +1215,7 @@ static int imx274_set_selection_crop(struct stimx274 *imx274,
sel->r = new_crop;
if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
- tgt_crop = &sd_state->pads->try_crop;
+ tgt_crop = v4l2_subdev_state_get_crop(sd_state, 0);
else
tgt_crop = &imx274->crop;
@@ -1327,20 +1327,19 @@ static int imx274_apply_trimming(struct stimx274 *imx274)
return err;
}
-/**
- * imx274_g_frame_interval - Get the frame interval
- * @sd: Pointer to V4L2 Sub device structure
- * @fi: Pointer to V4l2 Sub device frame interval structure
- *
- * This function is used to get the frame interval.
- *
- * Return: 0 on success
- */
-static int imx274_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int imx274_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct stimx274 *imx274 = to_imx274(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
fi->interval = imx274->frame_interval;
dev_dbg(&imx274->client->dev, "%s frame rate = %d / %d\n",
__func__, imx274->frame_interval.numerator,
@@ -1349,29 +1348,28 @@ static int imx274_g_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-/**
- * imx274_s_frame_interval - Set the frame interval
- * @sd: Pointer to V4L2 Sub device structure
- * @fi: Pointer to V4l2 Sub device frame interval structure
- *
- * This function is used to set the frame intervavl.
- *
- * Return: 0 on success
- */
-static int imx274_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int imx274_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct stimx274 *imx274 = to_imx274(sd);
struct v4l2_ctrl *ctrl = imx274->ctrls.exposure;
int min, max, def;
int ret;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
ret = pm_runtime_resume_and_get(&imx274->client->dev);
if (ret < 0)
return ret;
mutex_lock(&imx274->lock);
- ret = imx274_set_frame_interval(imx274, fi->interval);
+ ret = __imx274_set_frame_interval(imx274, fi->interval);
if (!ret) {
fi->interval = imx274->frame_interval;
@@ -1466,8 +1464,8 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on)
* are changed.
* gain is not affected.
*/
- ret = imx274_set_frame_interval(imx274,
- imx274->frame_interval);
+ ret = __imx274_set_frame_interval(imx274,
+ imx274->frame_interval);
if (ret)
goto fail;
@@ -1830,7 +1828,7 @@ fail:
}
/*
- * imx274_set_frame_interval - Function called when setting frame interval
+ * __imx274_set_frame_interval - Function called when setting frame interval
* @priv: Pointer to device structure
* @frame_interval: Variable for frame interval
*
@@ -1839,8 +1837,8 @@ fail:
*
* Return: 0 on success
*/
-static int imx274_set_frame_interval(struct stimx274 *priv,
- struct v4l2_fract frame_interval)
+static int __imx274_set_frame_interval(struct stimx274 *priv,
+ struct v4l2_fract frame_interval)
{
int err;
u32 frame_length, req_frame_rate;
@@ -1927,11 +1925,11 @@ static const struct v4l2_subdev_pad_ops imx274_pad_ops = {
.set_fmt = imx274_set_fmt,
.get_selection = imx274_get_selection,
.set_selection = imx274_set_selection,
+ .get_frame_interval = imx274_get_frame_interval,
+ .set_frame_interval = imx274_set_frame_interval,
};
static const struct v4l2_subdev_video_ops imx274_video_ops = {
- .g_frame_interval = imx274_g_frame_interval,
- .s_frame_interval = imx274_s_frame_interval,
.s_stream = imx274_s_stream,
};
diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 6dacd38ae9..4150e6e4b9 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -758,7 +758,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
return 0;
state = v4l2_subdev_get_locked_active_state(&imx290->sd);
- format = v4l2_subdev_get_pad_format(&imx290->sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
switch (ctrl->id) {
case V4L2_CID_ANALOGUE_GAIN:
@@ -994,7 +994,7 @@ static int imx290_start_streaming(struct imx290 *imx290,
}
/* Apply the register values related to current frame format */
- format = v4l2_subdev_get_pad_format(&imx290->sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
ret = imx290_setup_format(imx290, format);
if (ret < 0) {
dev_err(imx290->dev, "Could not set frame format - %d\n", ret);
@@ -1132,7 +1132,7 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
fmt->format.quantization = V4L2_QUANTIZATION_FULL_RANGE;
fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
- format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
+ format = v4l2_subdev_state_get_format(sd_state, 0);
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
imx290->current_mode = mode;
@@ -1155,7 +1155,7 @@ static int imx290_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP: {
- format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
+ format = v4l2_subdev_state_get_format(sd_state, 0);
/*
* The sensor moves the readout by 1 pixel based on flips to
@@ -1195,8 +1195,8 @@ static int imx290_get_selection(struct v4l2_subdev *sd,
}
}
-static int imx290_entity_init_cfg(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *sd_state)
+static int imx290_entity_init_state(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_TRY,
@@ -1221,7 +1221,6 @@ static const struct v4l2_subdev_video_ops imx290_video_ops = {
};
static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
- .init_cfg = imx290_entity_init_cfg,
.enum_mbus_code = imx290_enum_mbus_code,
.enum_frame_size = imx290_enum_frame_size,
.get_fmt = v4l2_subdev_get_fmt,
@@ -1235,6 +1234,10 @@ static const struct v4l2_subdev_ops imx290_subdev_ops = {
.pad = &imx290_pad_ops,
};
+static const struct v4l2_subdev_internal_ops imx290_internal_ops = {
+ .init_state = imx290_entity_init_state,
+};
+
static const struct media_entity_operations imx290_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -1248,6 +1251,7 @@ static int imx290_subdev_init(struct imx290 *imx290)
imx290->current_mode = &imx290_modes_ptr(imx290)[0];
v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
+ imx290->sd.internal_ops = &imx290_internal_ops;
imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
imx290->sd.dev = imx290->dev;
diff --git a/drivers/media/i2c/imx296.c b/drivers/media/i2c/imx296.c
index 94aac9d273..83149fa729 100644
--- a/drivers/media/i2c/imx296.c
+++ b/drivers/media/i2c/imx296.c
@@ -323,7 +323,7 @@ static int imx296_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
state = v4l2_subdev_get_locked_active_state(&sensor->subdev);
- format = v4l2_subdev_get_pad_format(&sensor->subdev, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
@@ -511,8 +511,8 @@ static int imx296_setup(struct imx296 *sensor, struct v4l2_subdev_state *state)
unsigned int i;
int ret = 0;
- format = v4l2_subdev_get_pad_format(&sensor->subdev, state, 0);
- crop = v4l2_subdev_get_pad_crop(&sensor->subdev, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
+ crop = v4l2_subdev_state_get_crop(state, 0);
for (i = 0; i < ARRAY_SIZE(imx296_init_table); ++i)
imx296_write(sensor, imx296_init_table[i].reg,
@@ -662,7 +662,7 @@ static int imx296_enum_frame_size(struct v4l2_subdev *sd,
{
const struct v4l2_mbus_framefmt *format;
- format = v4l2_subdev_get_pad_format(sd, state, fse->pad);
+ format = v4l2_subdev_state_get_format(state, fse->pad);
if (fse->index >= 2 || fse->code != format->code)
return -EINVAL;
@@ -683,8 +683,8 @@ static int imx296_set_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format;
struct v4l2_rect *crop;
- crop = v4l2_subdev_get_pad_crop(sd, state, fmt->pad);
- format = v4l2_subdev_get_pad_format(sd, state, fmt->pad);
+ crop = v4l2_subdev_state_get_crop(state, fmt->pad);
+ format = v4l2_subdev_state_get_format(state, fmt->pad);
/*
* Binning is only allowed when cropping is disabled according to the
@@ -732,7 +732,7 @@ static int imx296_get_selection(struct v4l2_subdev *sd,
{
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
- sel->r = *v4l2_subdev_get_pad_crop(sd, state, sel->pad);
+ sel->r = *v4l2_subdev_state_get_crop(state, sel->pad);
break;
case V4L2_SEL_TGT_CROP_DEFAULT:
@@ -780,14 +780,14 @@ static int imx296_set_selection(struct v4l2_subdev *sd,
rect.height = min_t(unsigned int, rect.height,
IMX296_PIXEL_ARRAY_HEIGHT - rect.top);
- crop = v4l2_subdev_get_pad_crop(sd, state, sel->pad);
+ crop = v4l2_subdev_state_get_crop(state, sel->pad);
if (rect.width != crop->width || rect.height != crop->height) {
/*
* Reset the output image size if the crop rectangle size has
* been modified.
*/
- format = v4l2_subdev_get_pad_format(sd, state, sel->pad);
+ format = v4l2_subdev_state_get_format(state, sel->pad);
format->width = rect.width;
format->height = rect.height;
}
@@ -798,8 +798,8 @@ static int imx296_set_selection(struct v4l2_subdev *sd,
return 0;
}
-static int imx296_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int imx296_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_subdev_selection sel = {
.target = V4L2_SEL_TGT_CROP,
@@ -830,7 +830,6 @@ static const struct v4l2_subdev_pad_ops imx296_subdev_pad_ops = {
.set_fmt = imx296_set_format,
.get_selection = imx296_get_selection,
.set_selection = imx296_set_selection,
- .init_cfg = imx296_init_cfg,
};
static const struct v4l2_subdev_ops imx296_subdev_ops = {
@@ -838,12 +837,17 @@ static const struct v4l2_subdev_ops imx296_subdev_ops = {
.pad = &imx296_subdev_pad_ops,
};
+static const struct v4l2_subdev_internal_ops imx296_internal_ops = {
+ .init_state = imx296_init_state,
+};
+
static int imx296_subdev_init(struct imx296 *sensor)
{
struct i2c_client *client = to_i2c_client(sensor->dev);
int ret;
v4l2_i2c_subdev_init(&sensor->subdev, client, &imx296_subdev_ops);
+ sensor->subdev.internal_ops = &imx296_internal_ops;
ret = imx296_ctrls_init(sensor);
if (ret < 0)
diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c
index 5378f607f3..e47eff672e 100644
--- a/drivers/media/i2c/imx319.c
+++ b/drivers/media/i2c/imx319.c
@@ -1860,7 +1860,7 @@ static int imx319_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct imx319 *imx319 = to_imx319(sd);
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
mutex_lock(&imx319->mutex);
@@ -2001,10 +2001,9 @@ static int imx319_do_get_pad_format(struct imx319 *imx319,
struct v4l2_subdev_format *fmt)
{
struct v4l2_mbus_framefmt *framefmt;
- struct v4l2_subdev *sd = &imx319->sd;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
imx319_update_pad_format(imx319, imx319->cur_mode, fmt);
@@ -2055,7 +2054,7 @@ imx319_set_pad_format(struct v4l2_subdev *sd,
fmt->format.width, fmt->format.height);
imx319_update_pad_format(imx319, mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
imx319->cur_mode = mode;
@@ -2464,19 +2463,21 @@ static int imx319_probe(struct i2c_client *client)
goto error_handler_free;
}
- ret = v4l2_async_register_subdev_sensor(&imx319->sd);
- if (ret < 0)
- goto error_media_entity;
-
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
+ ret = v4l2_async_register_subdev_sensor(&imx319->sd);
+ if (ret < 0)
+ goto error_media_entity_pm;
+
return 0;
-error_media_entity:
+error_media_entity_pm:
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
media_entity_cleanup(&imx319->sd.entity);
error_handler_free:
diff --git a/drivers/media/i2c/imx334.c b/drivers/media/i2c/imx334.c
index 1196fe9350..6725b3e2a7 100644
--- a/drivers/media/i2c/imx334.c
+++ b/drivers/media/i2c/imx334.c
@@ -879,7 +879,7 @@ static int imx334_get_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
fmt->format.code = imx334->cur_code;
@@ -920,7 +920,7 @@ static int imx334_set_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else if (imx334->cur_mode != mode || imx334->cur_code != fmt->format.code) {
imx334->cur_code = fmt->format.code;
@@ -935,14 +935,14 @@ static int imx334_set_pad_format(struct v4l2_subdev *sd,
}
/**
- * imx334_init_pad_cfg() - Initialize sub-device pad configuration
+ * imx334_init_state() - Initialize sub-device state
* @sd: pointer to imx334 V4L2 sub-device structure
* @sd_state: V4L2 sub-device state
*
* Return: 0 if successful, error code otherwise.
*/
-static int imx334_init_pad_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int imx334_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct imx334 *imx334 = to_imx334(sd);
struct v4l2_subdev_format fmt = { 0 };
@@ -1190,7 +1190,6 @@ static const struct v4l2_subdev_video_ops imx334_video_ops = {
};
static const struct v4l2_subdev_pad_ops imx334_pad_ops = {
- .init_cfg = imx334_init_pad_cfg,
.enum_mbus_code = imx334_enum_mbus_code,
.enum_frame_size = imx334_enum_frame_size,
.get_fmt = imx334_get_pad_format,
@@ -1202,6 +1201,10 @@ static const struct v4l2_subdev_ops imx334_subdev_ops = {
.pad = &imx334_pad_ops,
};
+static const struct v4l2_subdev_internal_ops imx334_internal_ops = {
+ .init_state = imx334_init_state,
+};
+
/**
* imx334_power_on() - Sensor power on sequence
* @dev: pointer to i2c device
@@ -1359,6 +1362,7 @@ static int imx334_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&imx334->sd, client, &imx334_subdev_ops);
+ imx334->sd.internal_ops = &imx334_internal_ops;
ret = imx334_parse_hw_config(imx334);
if (ret) {
diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c
index 964a81bec5..7a37eb327f 100644
--- a/drivers/media/i2c/imx335.c
+++ b/drivers/media/i2c/imx335.c
@@ -55,6 +55,14 @@
#define IMX335_REG_MIN 0x00
#define IMX335_REG_MAX 0xfffff
+/* IMX335 native and active pixel array size. */
+#define IMX335_NATIVE_WIDTH 2616U
+#define IMX335_NATIVE_HEIGHT 1964U
+#define IMX335_PIXEL_ARRAY_LEFT 12U
+#define IMX335_PIXEL_ARRAY_TOP 12U
+#define IMX335_PIXEL_ARRAY_WIDTH 2592U
+#define IMX335_PIXEL_ARRAY_HEIGHT 1944U
+
/**
* struct imx335_reg - imx335 sensor register
* @address: Register address
@@ -75,6 +83,12 @@ struct imx335_reg_list {
const struct imx335_reg *regs;
};
+static const char * const imx335_supply_name[] = {
+ "avdd", /* Analog (2.9V) supply */
+ "ovdd", /* Digital I/O (1.8V) supply */
+ "dvdd", /* Digital Core (1.2V) supply */
+};
+
/**
* struct imx335_mode - imx335 sensor mode structure
* @width: Frame width
@@ -108,6 +122,7 @@ struct imx335_mode {
* @sd: V4L2 sub-device
* @pad: Media pad. Only one pad supported
* @reset_gpio: Sensor reset gpio
+ * @supplies: Regulator supplies to handle power control
* @inclk: Sensor input clock
* @ctrl_handler: V4L2 control handler
* @link_freq_ctrl: Pointer to link frequency control
@@ -119,6 +134,7 @@ struct imx335_mode {
* @vblank: Vertical blanking in lines
* @cur_mode: Pointer to current selected sensor mode
* @mutex: Mutex for serializing sensor controls
+ * @cur_mbus_code: Currently selected media bus format code
*/
struct imx335 {
struct device *dev;
@@ -126,6 +142,8 @@ struct imx335 {
struct v4l2_subdev sd;
struct media_pad pad;
struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(imx335_supply_name)];
+
struct clk *inclk;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *link_freq_ctrl;
@@ -139,6 +157,7 @@ struct imx335 {
u32 vblank;
const struct imx335_mode *cur_mode;
struct mutex mutex;
+ u32 cur_mbus_code;
};
static const s64 link_freq[] = {
@@ -233,6 +252,25 @@ static const struct imx335_reg mode_2592x1940_regs[] = {
{0x3a00, 0x01},
};
+static const struct imx335_reg raw10_framefmt_regs[] = {
+ {0x3050, 0x00},
+ {0x319d, 0x00},
+ {0x341c, 0xff},
+ {0x341d, 0x01},
+};
+
+static const struct imx335_reg raw12_framefmt_regs[] = {
+ {0x3050, 0x01},
+ {0x319d, 0x01},
+ {0x341c, 0x47},
+ {0x341d, 0x00},
+};
+
+static const u32 imx335_mbus_codes[] = {
+ MEDIA_BUS_FMT_SRGGB12_1X12,
+ MEDIA_BUS_FMT_SRGGB10_1X10,
+};
+
/* Supported sensor mode configurations */
static const struct imx335_mode supported_mode = {
.width = 2592,
@@ -243,7 +281,6 @@ static const struct imx335_mode supported_mode = {
.vblank_max = 133060,
.pclk = 396000000,
.link_freq_idx = 0,
- .code = MEDIA_BUS_FMT_SRGGB12_1X12,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2592x1940_regs),
.regs = mode_2592x1940_regs,
@@ -396,7 +433,7 @@ static int imx335_update_exp_gain(struct imx335 *imx335, u32 exposure, u32 gain)
lpfr = imx335->vblank + imx335->cur_mode->height;
shutter = lpfr - exposure;
- dev_dbg(imx335->dev, "Set exp %u, analog gain %u, shutter %u, lpfr %u",
+ dev_dbg(imx335->dev, "Set exp %u, analog gain %u, shutter %u, lpfr %u\n",
exposure, gain, shutter, lpfr);
ret = imx335_write_reg(imx335, IMX335_REG_HOLD, 1, 1);
@@ -443,7 +480,7 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_VBLANK:
imx335->vblank = imx335->vblank_ctrl->val;
- dev_dbg(imx335->dev, "Received vblank %u, new lpfr %u",
+ dev_dbg(imx335->dev, "Received vblank %u, new lpfr %u\n",
imx335->vblank,
imx335->vblank + imx335->cur_mode->height);
@@ -462,7 +499,7 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
exposure = ctrl->val;
analog_gain = imx335->again_ctrl->val;
- dev_dbg(imx335->dev, "Received exp %u, analog gain %u",
+ dev_dbg(imx335->dev, "Received exp %u, analog gain %u\n",
exposure, analog_gain);
ret = imx335_update_exp_gain(imx335, exposure, analog_gain);
@@ -471,7 +508,7 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl)
break;
default:
- dev_err(imx335->dev, "Invalid control %d", ctrl->id);
+ dev_err(imx335->dev, "Invalid control %d\n", ctrl->id);
ret = -EINVAL;
}
@@ -483,6 +520,18 @@ static const struct v4l2_ctrl_ops imx335_ctrl_ops = {
.s_ctrl = imx335_set_ctrl,
};
+static int imx335_get_format_code(struct imx335 *imx335, u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(imx335_mbus_codes); i++) {
+ if (imx335_mbus_codes[i] == code)
+ return imx335_mbus_codes[i];
+ }
+
+ return imx335_mbus_codes[0];
+}
+
/**
* imx335_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
* @sd: pointer to imx335 V4L2 sub-device structure
@@ -495,10 +544,10 @@ static int imx335_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
- if (code->index > 0)
+ if (code->index >= ARRAY_SIZE(imx335_mbus_codes))
return -EINVAL;
- code->code = supported_mode.code;
+ code->code = imx335_mbus_codes[code->index];
return 0;
}
@@ -515,10 +564,14 @@ static int imx335_enum_frame_size(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fsize)
{
- if (fsize->index > 0)
+ struct imx335 *imx335 = to_imx335(sd);
+ u32 code;
+
+ if (fsize->index > ARRAY_SIZE(imx335_mbus_codes))
return -EINVAL;
- if (fsize->code != supported_mode.code)
+ code = imx335_get_format_code(imx335, fsize->code);
+ if (fsize->code != code)
return -EINVAL;
fsize->min_width = supported_mode.width;
@@ -542,7 +595,7 @@ static void imx335_fill_pad_format(struct imx335 *imx335,
{
fmt->format.width = mode->width;
fmt->format.height = mode->height;
- fmt->format.code = mode->code;
+ fmt->format.code = imx335->cur_mbus_code;
fmt->format.field = V4L2_FIELD_NONE;
fmt->format.colorspace = V4L2_COLORSPACE_RAW;
fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
@@ -569,7 +622,7 @@ static int imx335_get_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
imx335_fill_pad_format(imx335, imx335->cur_mode, fmt);
@@ -594,17 +647,22 @@ static int imx335_set_pad_format(struct v4l2_subdev *sd,
{
struct imx335 *imx335 = to_imx335(sd);
const struct imx335_mode *mode;
- int ret = 0;
+ int i, ret = 0;
mutex_lock(&imx335->mutex);
mode = &supported_mode;
+ for (i = 0; i < ARRAY_SIZE(imx335_mbus_codes); i++) {
+ if (imx335_mbus_codes[i] == fmt->format.code)
+ imx335->cur_mbus_code = imx335_mbus_codes[i];
+ }
+
imx335_fill_pad_format(imx335, mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
ret = imx335_update_controls(imx335, mode);
@@ -618,14 +676,14 @@ static int imx335_set_pad_format(struct v4l2_subdev *sd,
}
/**
- * imx335_init_pad_cfg() - Initialize sub-device pad configuration
+ * imx335_init_state() - Initialize sub-device state
* @sd: pointer to imx335 V4L2 sub-device structure
* @sd_state: V4L2 sub-device configuration
*
* Return: 0 if successful, error code otherwise.
*/
-static int imx335_init_pad_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int imx335_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct imx335 *imx335 = to_imx335(sd);
struct v4l2_subdev_format fmt = { 0 };
@@ -637,6 +695,56 @@ static int imx335_init_pad_cfg(struct v4l2_subdev *sd,
}
/**
+ * imx335_get_selection() - Selection API
+ * @sd: pointer to imx335 V4L2 sub-device structure
+ * @sd_state: V4L2 sub-device configuration
+ * @sel: V4L2 selection info
+ *
+ * Return: 0 if successful, error code otherwise.
+ */
+static int imx335_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_selection *sel)
+{
+ switch (sel->target) {
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = IMX335_NATIVE_WIDTH;
+ sel->r.height = IMX335_NATIVE_HEIGHT;
+
+ return 0;
+
+ case V4L2_SEL_TGT_CROP:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = IMX335_PIXEL_ARRAY_TOP;
+ sel->r.left = IMX335_PIXEL_ARRAY_LEFT;
+ sel->r.width = IMX335_PIXEL_ARRAY_WIDTH;
+ sel->r.height = IMX335_PIXEL_ARRAY_HEIGHT;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int imx335_set_framefmt(struct imx335 *imx335)
+{
+ switch (imx335->cur_mbus_code) {
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ return imx335_write_regs(imx335, raw10_framefmt_regs,
+ ARRAY_SIZE(raw10_framefmt_regs));
+
+ case MEDIA_BUS_FMT_SRGGB12_1X12:
+ return imx335_write_regs(imx335, raw12_framefmt_regs,
+ ARRAY_SIZE(raw12_framefmt_regs));
+ }
+
+ return -EINVAL;
+}
+
+/**
* imx335_start_streaming() - Start sensor stream
* @imx335: pointer to imx335 device
*
@@ -652,14 +760,21 @@ static int imx335_start_streaming(struct imx335 *imx335)
ret = imx335_write_regs(imx335, reg_list->regs,
reg_list->num_of_regs);
if (ret) {
- dev_err(imx335->dev, "fail to write initial registers");
+ dev_err(imx335->dev, "fail to write initial registers\n");
+ return ret;
+ }
+
+ ret = imx335_set_framefmt(imx335);
+ if (ret) {
+ dev_err(imx335->dev, "%s failed to set frame format: %d\n",
+ __func__, ret);
return ret;
}
/* Setup handler will write actual exposure and gain */
ret = __v4l2_ctrl_handler_setup(imx335->sd.ctrl_handler);
if (ret) {
- dev_err(imx335->dev, "fail to setup handler");
+ dev_err(imx335->dev, "fail to setup handler\n");
return ret;
}
@@ -667,7 +782,7 @@ static int imx335_start_streaming(struct imx335 *imx335)
ret = imx335_write_reg(imx335, IMX335_REG_MODE_SELECT,
1, IMX335_MODE_STREAMING);
if (ret) {
- dev_err(imx335->dev, "fail to start streaming");
+ dev_err(imx335->dev, "fail to start streaming\n");
return ret;
}
@@ -744,7 +859,7 @@ static int imx335_detect(struct imx335 *imx335)
return ret;
if (val != IMX335_ID) {
- dev_err(imx335->dev, "chip id mismatch: %x!=%x",
+ dev_err(imx335->dev, "chip id mismatch: %x!=%x\n",
IMX335_ID, val);
return -ENXIO;
}
@@ -776,27 +891,40 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
imx335->reset_gpio = devm_gpiod_get_optional(imx335->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(imx335->reset_gpio)) {
- dev_err(imx335->dev, "failed to get reset gpio %ld",
+ dev_err(imx335->dev, "failed to get reset gpio %ld\n",
PTR_ERR(imx335->reset_gpio));
return PTR_ERR(imx335->reset_gpio);
}
+ for (i = 0; i < ARRAY_SIZE(imx335_supply_name); i++)
+ imx335->supplies[i].supply = imx335_supply_name[i];
+
+ ret = devm_regulator_bulk_get(imx335->dev,
+ ARRAY_SIZE(imx335_supply_name),
+ imx335->supplies);
+ if (ret) {
+ dev_err(imx335->dev, "Failed to get regulators\n");
+ return ret;
+ }
+
/* Get sensor input clock */
imx335->inclk = devm_clk_get(imx335->dev, NULL);
if (IS_ERR(imx335->inclk)) {
- dev_err(imx335->dev, "could not get inclk");
+ dev_err(imx335->dev, "could not get inclk\n");
return PTR_ERR(imx335->inclk);
}
rate = clk_get_rate(imx335->inclk);
if (rate != IMX335_INCLK_RATE) {
- dev_err(imx335->dev, "inclk frequency mismatch");
+ dev_err(imx335->dev, "inclk frequency mismatch\n");
return -EINVAL;
}
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
- if (!ep)
+ if (!ep) {
+ dev_err(imx335->dev, "Failed to get next endpoint\n");
return -ENXIO;
+ }
ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
fwnode_handle_put(ep);
@@ -805,14 +933,14 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX335_NUM_DATA_LANES) {
dev_err(imx335->dev,
- "number of CSI2 data lanes %d is not supported",
+ "number of CSI2 data lanes %d is not supported\n",
bus_cfg.bus.mipi_csi2.num_data_lanes);
ret = -EINVAL;
goto done_endpoint_free;
}
if (!bus_cfg.nr_of_link_frequencies) {
- dev_err(imx335->dev, "no link frequencies defined");
+ dev_err(imx335->dev, "no link frequencies defined\n");
ret = -EINVAL;
goto done_endpoint_free;
}
@@ -821,6 +949,8 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
if (bus_cfg.link_frequencies[i] == IMX335_LINK_FREQ)
goto done_endpoint_free;
+ dev_err(imx335->dev, "no compatible link frequencies found\n");
+
ret = -EINVAL;
done_endpoint_free:
@@ -835,9 +965,10 @@ static const struct v4l2_subdev_video_ops imx335_video_ops = {
};
static const struct v4l2_subdev_pad_ops imx335_pad_ops = {
- .init_cfg = imx335_init_pad_cfg,
.enum_mbus_code = imx335_enum_mbus_code,
.enum_frame_size = imx335_enum_frame_size,
+ .get_selection = imx335_get_selection,
+ .set_selection = imx335_get_selection,
.get_fmt = imx335_get_pad_format,
.set_fmt = imx335_set_pad_format,
};
@@ -847,6 +978,10 @@ static const struct v4l2_subdev_ops imx335_subdev_ops = {
.pad = &imx335_pad_ops,
};
+static const struct v4l2_subdev_internal_ops imx335_internal_ops = {
+ .init_state = imx335_init_state,
+};
+
/**
* imx335_power_on() - Sensor power on sequence
* @dev: pointer to i2c device
@@ -859,20 +994,32 @@ static int imx335_power_on(struct device *dev)
struct imx335 *imx335 = to_imx335(sd);
int ret;
+ ret = regulator_bulk_enable(ARRAY_SIZE(imx335_supply_name),
+ imx335->supplies);
+ if (ret) {
+ dev_err(dev, "%s: failed to enable regulators\n",
+ __func__);
+ return ret;
+ }
+
+ usleep_range(500, 550); /* Tlow */
+
+ /* Set XCLR */
gpiod_set_value_cansleep(imx335->reset_gpio, 1);
ret = clk_prepare_enable(imx335->inclk);
if (ret) {
- dev_err(imx335->dev, "fail to enable inclk");
+ dev_err(imx335->dev, "fail to enable inclk\n");
goto error_reset;
}
- usleep_range(20, 22);
+ usleep_range(20, 22); /* T4 */
return 0;
error_reset:
gpiod_set_value_cansleep(imx335->reset_gpio, 0);
+ regulator_bulk_disable(ARRAY_SIZE(imx335_supply_name), imx335->supplies);
return ret;
}
@@ -889,8 +1036,8 @@ static int imx335_power_off(struct device *dev)
struct imx335 *imx335 = to_imx335(sd);
gpiod_set_value_cansleep(imx335->reset_gpio, 0);
-
clk_disable_unprepare(imx335->inclk);
+ regulator_bulk_disable(ARRAY_SIZE(imx335_supply_name), imx335->supplies);
return 0;
}
@@ -969,7 +1116,7 @@ static int imx335_init_controls(struct imx335 *imx335)
imx335->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
if (ctrl_hdlr->error) {
- dev_err(imx335->dev, "control init failed: %d",
+ dev_err(imx335->dev, "control init failed: %d\n",
ctrl_hdlr->error);
v4l2_ctrl_handler_free(ctrl_hdlr);
return ctrl_hdlr->error;
@@ -999,10 +1146,11 @@ static int imx335_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&imx335->sd, client, &imx335_subdev_ops);
+ imx335->sd.internal_ops = &imx335_internal_ops;
ret = imx335_parse_hw_config(imx335);
if (ret) {
- dev_err(imx335->dev, "HW configuration is not supported");
+ dev_err(imx335->dev, "HW configuration is not supported\n");
return ret;
}
@@ -1010,24 +1158,25 @@ static int imx335_probe(struct i2c_client *client)
ret = imx335_power_on(imx335->dev);
if (ret) {
- dev_err(imx335->dev, "failed to power-on the sensor");
+ dev_err(imx335->dev, "failed to power-on the sensor\n");
goto error_mutex_destroy;
}
/* Check module identity */
ret = imx335_detect(imx335);
if (ret) {
- dev_err(imx335->dev, "failed to find sensor: %d", ret);
+ dev_err(imx335->dev, "failed to find sensor: %d\n", ret);
goto error_power_off;
}
/* Set default mode to max resolution */
imx335->cur_mode = &supported_mode;
+ imx335->cur_mbus_code = imx335_mbus_codes[0];
imx335->vblank = imx335->cur_mode->vblank;
ret = imx335_init_controls(imx335);
if (ret) {
- dev_err(imx335->dev, "failed to init controls: %d", ret);
+ dev_err(imx335->dev, "failed to init controls: %d\n", ret);
goto error_power_off;
}
@@ -1039,14 +1188,14 @@ static int imx335_probe(struct i2c_client *client)
imx335->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&imx335->sd.entity, 1, &imx335->pad);
if (ret) {
- dev_err(imx335->dev, "failed to init entity pads: %d", ret);
+ dev_err(imx335->dev, "failed to init entity pads: %d\n", ret);
goto error_handler_free;
}
ret = v4l2_async_register_subdev_sensor(&imx335->sd);
if (ret < 0) {
dev_err(imx335->dev,
- "failed to register async subdev: %d", ret);
+ "failed to register async subdev: %d\n", ret);
goto error_media_entity;
}
diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c
index 81bb61407b..8c995c5874 100644
--- a/drivers/media/i2c/imx355.c
+++ b/drivers/media/i2c/imx355.c
@@ -1158,7 +1158,7 @@ static int imx355_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct imx355 *imx355 = to_imx355(sd);
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
mutex_lock(&imx355->mutex);
@@ -1299,10 +1299,9 @@ static int imx355_do_get_pad_format(struct imx355 *imx355,
struct v4l2_subdev_format *fmt)
{
struct v4l2_mbus_framefmt *framefmt;
- struct v4l2_subdev *sd = &imx355->sd;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
imx355_update_pad_format(imx355, imx355->cur_mode, fmt);
@@ -1353,7 +1352,7 @@ imx355_set_pad_format(struct v4l2_subdev *sd,
fmt->format.width, fmt->format.height);
imx355_update_pad_format(imx355, mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
imx355->cur_mode = mode;
diff --git a/drivers/media/i2c/imx412.c b/drivers/media/i2c/imx412.c
index 962b3136c3..0efce32952 100644
--- a/drivers/media/i2c/imx412.c
+++ b/drivers/media/i2c/imx412.c
@@ -721,7 +721,7 @@ static int imx412_get_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
imx412_fill_pad_format(imx412, imx412->cur_mode, fmt);
@@ -756,7 +756,7 @@ static int imx412_set_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
ret = imx412_update_controls(imx412, mode);
@@ -770,14 +770,14 @@ static int imx412_set_pad_format(struct v4l2_subdev *sd,
}
/**
- * imx412_init_pad_cfg() - Initialize sub-device pad configuration
+ * imx412_init_state() - Initialize sub-device state
* @sd: pointer to imx412 V4L2 sub-device structure
* @sd_state: V4L2 sub-device configuration
*
* Return: 0 if successful, error code otherwise.
*/
-static int imx412_init_pad_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int imx412_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct imx412 *imx412 = to_imx412(sd);
struct v4l2_subdev_format fmt = { 0 };
@@ -997,7 +997,6 @@ static const struct v4l2_subdev_video_ops imx412_video_ops = {
};
static const struct v4l2_subdev_pad_ops imx412_pad_ops = {
- .init_cfg = imx412_init_pad_cfg,
.enum_mbus_code = imx412_enum_mbus_code,
.enum_frame_size = imx412_enum_frame_size,
.get_fmt = imx412_get_pad_format,
@@ -1009,6 +1008,10 @@ static const struct v4l2_subdev_ops imx412_subdev_ops = {
.pad = &imx412_pad_ops,
};
+static const struct v4l2_subdev_internal_ops imx412_internal_ops = {
+ .init_state = imx412_init_state,
+};
+
/**
* imx412_power_on() - Sensor power on sequence
* @dev: pointer to i2c device
@@ -1177,6 +1180,7 @@ static int imx412_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&imx412->sd, client, &imx412_subdev_ops);
+ imx412->sd.internal_ops = &imx412_internal_ops;
ret = imx412_parse_hw_config(imx412);
if (ret) {
diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c
index b3fa71a168..1e5f20c3ed 100644
--- a/drivers/media/i2c/imx415.c
+++ b/drivers/media/i2c/imx415.c
@@ -546,7 +546,7 @@ static int imx415_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
state = v4l2_subdev_get_locked_active_state(&sensor->subdev);
- format = v4l2_subdev_get_pad_format(&sensor->subdev, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
@@ -828,7 +828,7 @@ static int imx415_enum_frame_size(struct v4l2_subdev *sd,
{
const struct v4l2_mbus_framefmt *format;
- format = v4l2_subdev_get_pad_format(sd, state, fse->pad);
+ format = v4l2_subdev_state_get_format(state, fse->pad);
if (fse->index > 0 || fse->code != format->code)
return -EINVAL;
@@ -846,7 +846,7 @@ static int imx415_set_format(struct v4l2_subdev *sd,
{
struct v4l2_mbus_framefmt *format;
- format = v4l2_subdev_get_pad_format(sd, state, fmt->pad);
+ format = v4l2_subdev_state_get_format(state, fmt->pad);
format->width = fmt->format.width;
format->height = fmt->format.height;
@@ -880,8 +880,8 @@ static int imx415_get_selection(struct v4l2_subdev *sd,
return -EINVAL;
}
-static int imx415_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int imx415_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_subdev_format format = {
.format = {
@@ -905,7 +905,6 @@ static const struct v4l2_subdev_pad_ops imx415_subdev_pad_ops = {
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = imx415_set_format,
.get_selection = imx415_get_selection,
- .init_cfg = imx415_init_cfg,
};
static const struct v4l2_subdev_ops imx415_subdev_ops = {
@@ -913,12 +912,17 @@ static const struct v4l2_subdev_ops imx415_subdev_ops = {
.pad = &imx415_subdev_pad_ops,
};
+static const struct v4l2_subdev_internal_ops imx415_internal_ops = {
+ .init_state = imx415_init_state,
+};
+
static int imx415_subdev_init(struct imx415 *sensor)
{
struct i2c_client *client = to_i2c_client(sensor->dev);
int ret;
v4l2_i2c_subdev_init(&sensor->subdev, client, &imx415_subdev_ops);
+ sensor->subdev.internal_ops = &imx415_internal_ops;
ret = imx415_ctrls_init(sensor);
if (ret)
diff --git a/drivers/media/i2c/isl7998x.c b/drivers/media/i2c/isl7998x.c
index 73460688c3..89e13ebbce 100644
--- a/drivers/media/i2c/isl7998x.c
+++ b/drivers/media/i2c/isl7998x.c
@@ -1007,8 +1007,8 @@ static int isl7998x_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&isl7998x->lock);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- format->format = *v4l2_subdev_get_try_format(sd, sd_state,
- format->pad);
+ format->format = *v4l2_subdev_state_get_format(sd_state,
+ format->pad);
goto out;
}
@@ -1044,7 +1044,7 @@ static int isl7998x_set_fmt(struct v4l2_subdev *sd,
mf->field = mode->field;
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *v4l2_subdev_get_try_format(sd, sd_state, format->pad) = format->format;
+ *v4l2_subdev_state_get_format(sd_state, format->pad) = format->format;
mutex_unlock(&isl7998x->lock);
diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index fc1cf196ef..d685d445cf 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -868,11 +868,19 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
return 0;
}
-static int max9286_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *interval)
+static int max9286_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *interval)
{
struct max9286_priv *priv = sd_to_max9286(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (interval->pad != MAX9286_SRC_PAD)
return -EINVAL;
@@ -881,11 +889,19 @@ static int max9286_g_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-static int max9286_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *interval)
+static int max9286_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *interval)
{
struct max9286_priv *priv = sd_to_max9286(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (interval->pad != MAX9286_SRC_PAD)
return -EINVAL;
@@ -913,7 +929,7 @@ max9286_get_pad_format(struct max9286_priv *priv,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&priv->sd, sd_state, pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &priv->fmt[pad];
default:
@@ -983,14 +999,14 @@ static int max9286_get_fmt(struct v4l2_subdev *sd,
static const struct v4l2_subdev_video_ops max9286_video_ops = {
.s_stream = max9286_s_stream,
- .g_frame_interval = max9286_g_frame_interval,
- .s_frame_interval = max9286_s_frame_interval,
};
static const struct v4l2_subdev_pad_ops max9286_pad_ops = {
.enum_mbus_code = max9286_enum_mbus_code,
.get_fmt = max9286_get_fmt,
.set_fmt = max9286_set_fmt,
+ .get_frame_interval = max9286_get_frame_interval,
+ .set_frame_interval = max9286_set_frame_interval,
};
static const struct v4l2_subdev_ops max9286_subdev_ops = {
@@ -1020,7 +1036,7 @@ static int max9286_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
unsigned int i;
for (i = 0; i < MAX9286_N_SINKS; i++) {
- format = v4l2_subdev_get_try_format(subdev, fh->state, i);
+ format = v4l2_subdev_state_get_format(fh->state, i);
max9286_init_format(format);
}
diff --git a/drivers/media/i2c/mt9m001.c b/drivers/media/i2c/mt9m001.c
index 79192cf79d..ad1a3ab774 100644
--- a/drivers/media/i2c/mt9m001.c
+++ b/drivers/media/i2c/mt9m001.c
@@ -325,7 +325,7 @@ static int mt9m001_get_fmt(struct v4l2_subdev *sd,
return -EINVAL;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ mf = v4l2_subdev_state_get_format(sd_state, 0);
format->format = *mf;
return 0;
}
@@ -405,7 +405,7 @@ static int mt9m001_set_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
return mt9m001_s_fmt(sd, fmt, mf);
- sd_state->pads->try_fmt = *mf;
+ *v4l2_subdev_state_get_format(sd_state, 0) = *mf;
return 0;
}
@@ -650,13 +650,13 @@ static const struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
#endif
};
-static int mt9m001_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int mt9m001_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m001 *mt9m001 = to_mt9m001(client);
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, sd_state, 0);
+ v4l2_subdev_state_get_format(sd_state, 0);
try_fmt->width = MT9M001_MAX_WIDTH;
try_fmt->height = MT9M001_MAX_HEIGHT;
@@ -708,7 +708,6 @@ static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
};
static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = {
- .init_cfg = mt9m001_init_cfg,
.enum_mbus_code = mt9m001_enum_mbus_code,
.get_selection = mt9m001_get_selection,
.set_selection = mt9m001_set_selection,
@@ -724,6 +723,10 @@ static const struct v4l2_subdev_ops mt9m001_subdev_ops = {
.pad = &mt9m001_subdev_pad_ops,
};
+static const struct v4l2_subdev_internal_ops mt9m001_internal_ops = {
+ .init_state = mt9m001_init_state,
+};
+
static int mt9m001_probe(struct i2c_client *client)
{
struct mt9m001 *mt9m001;
@@ -755,6 +758,7 @@ static int mt9m001_probe(struct i2c_client *client)
return PTR_ERR(mt9m001->reset_gpio);
v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops);
+ mt9m001->subdev.internal_ops = &mt9m001_internal_ops;
mt9m001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
v4l2_ctrl_handler_init(&mt9m001->hdl, 4);
diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c
index 1f44b72e8a..ceeeb94c38 100644
--- a/drivers/media/i2c/mt9m111.c
+++ b/drivers/media/i2c/mt9m111.c
@@ -525,7 +525,7 @@ static int mt9m111_get_fmt(struct v4l2_subdev *sd,
return -EINVAL;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ mf = v4l2_subdev_state_get_format(sd_state, format->pad);
format->format = *mf;
return 0;
}
@@ -671,7 +671,7 @@ static int mt9m111_set_fmt(struct v4l2_subdev *sd,
mf->xfer_func = V4L2_XFER_FUNC_DEFAULT;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- sd_state->pads->try_fmt = *mf;
+ *v4l2_subdev_state_get_format(sd_state, 0) = *mf;
return 0;
}
@@ -1045,18 +1045,27 @@ static const struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
#endif
};
-static int mt9m111_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int mt9m111_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
fi->interval = mt9m111->frame_interval;
return 0;
}
-static int mt9m111_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int mt9m111_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
const struct mt9m111_mode_info *mode;
@@ -1066,6 +1075,13 @@ static int mt9m111_s_frame_interval(struct v4l2_subdev *sd,
if (mt9m111->is_streaming)
return -EBUSY;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (fi->pad != 0)
return -EINVAL;
@@ -1111,11 +1127,11 @@ static int mt9m111_s_stream(struct v4l2_subdev *sd, int enable)
return 0;
}
-static int mt9m111_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int mt9m111_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_mbus_framefmt *format =
- v4l2_subdev_get_try_format(sd, sd_state, 0);
+ v4l2_subdev_state_get_format(sd_state, 0);
format->width = MT9M111_MAX_WIDTH;
format->height = MT9M111_MAX_HEIGHT;
@@ -1151,17 +1167,16 @@ static int mt9m111_get_mbus_config(struct v4l2_subdev *sd,
static const struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
.s_stream = mt9m111_s_stream,
- .g_frame_interval = mt9m111_g_frame_interval,
- .s_frame_interval = mt9m111_s_frame_interval,
};
static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = {
- .init_cfg = mt9m111_init_cfg,
.enum_mbus_code = mt9m111_enum_mbus_code,
.get_selection = mt9m111_get_selection,
.set_selection = mt9m111_set_selection,
.get_fmt = mt9m111_get_fmt,
.set_fmt = mt9m111_set_fmt,
+ .get_frame_interval = mt9m111_get_frame_interval,
+ .set_frame_interval = mt9m111_set_frame_interval,
.get_mbus_config = mt9m111_get_mbus_config,
};
@@ -1171,6 +1186,10 @@ static const struct v4l2_subdev_ops mt9m111_subdev_ops = {
.pad = &mt9m111_subdev_pad_ops,
};
+static const struct v4l2_subdev_internal_ops mt9m111_internal_ops = {
+ .init_state = mt9m111_init_state,
+};
+
/*
* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one
@@ -1275,6 +1294,7 @@ static int mt9m111_probe(struct i2c_client *client)
mt9m111->ctx = &context_b;
v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);
+ mt9m111->subdev.internal_ops = &mt9m111_internal_ops;
mt9m111->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c
index 1a535c098d..5f0b0ad8f8 100644
--- a/drivers/media/i2c/mt9m114.c
+++ b/drivers/media/i2c/mt9m114.c
@@ -796,13 +796,13 @@ static int mt9m114_configure(struct mt9m114 *sensor,
u64 read_mode;
int ret = 0;
- pa_format = v4l2_subdev_get_pad_format(&sensor->pa.sd, pa_state, 0);
- pa_crop = v4l2_subdev_get_pad_crop(&sensor->pa.sd, pa_state, 0);
+ pa_format = v4l2_subdev_state_get_format(pa_state, 0);
+ pa_crop = v4l2_subdev_state_get_crop(pa_state, 0);
- ifp_format = v4l2_subdev_get_pad_format(&sensor->ifp.sd, ifp_state, 1);
+ ifp_format = v4l2_subdev_state_get_format(ifp_state, 1);
ifp_info = mt9m114_format_info(sensor, 1, ifp_format->code);
- ifp_crop = v4l2_subdev_get_pad_crop(&sensor->ifp.sd, ifp_state, 0);
- ifp_compose = v4l2_subdev_get_pad_compose(&sensor->ifp.sd, ifp_state, 0);
+ ifp_crop = v4l2_subdev_state_get_crop(ifp_state, 0);
+ ifp_compose = v4l2_subdev_state_get_compose(ifp_state, 0);
ret = cci_read(sensor->regmap, MT9M114_CAM_SENSOR_CONTROL_READ_MODE,
&read_mode, NULL);
@@ -1045,7 +1045,7 @@ static int mt9m114_pa_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
state = v4l2_subdev_get_locked_active_state(&sensor->pa.sd);
- format = v4l2_subdev_get_pad_format(&sensor->pa.sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
switch (ctrl->id) {
case V4L2_CID_HBLANK:
@@ -1152,20 +1152,20 @@ static inline struct mt9m114 *pa_to_mt9m114(struct v4l2_subdev *sd)
return container_of(sd, struct mt9m114, pa.sd);
}
-static int mt9m114_pa_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int mt9m114_pa_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_mbus_framefmt *format;
struct v4l2_rect *crop;
- crop = v4l2_subdev_get_pad_crop(sd, state, 0);
+ crop = v4l2_subdev_state_get_crop(state, 0);
crop->left = 0;
crop->top = 0;
crop->width = MT9M114_PIXEL_ARRAY_WIDTH;
crop->height = MT9M114_PIXEL_ARRAY_HEIGHT;
- format = v4l2_subdev_get_pad_format(sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
format->width = MT9M114_PIXEL_ARRAY_WIDTH;
format->height = MT9M114_PIXEL_ARRAY_HEIGHT;
@@ -1220,8 +1220,8 @@ static int mt9m114_pa_set_fmt(struct v4l2_subdev *sd,
unsigned int hscale;
unsigned int vscale;
- crop = v4l2_subdev_get_pad_crop(sd, state, fmt->pad);
- format = v4l2_subdev_get_pad_format(sd, state, fmt->pad);
+ crop = v4l2_subdev_state_get_crop(state, fmt->pad);
+ format = v4l2_subdev_state_get_format(state, fmt->pad);
/* The sensor can bin horizontally and vertically. */
hscale = DIV_ROUND_CLOSEST(crop->width, fmt->format.width ? : 1);
@@ -1243,7 +1243,7 @@ static int mt9m114_pa_get_selection(struct v4l2_subdev *sd,
{
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
- sel->r = *v4l2_subdev_get_pad_crop(sd, state, sel->pad);
+ sel->r = *v4l2_subdev_state_get_crop(state, sel->pad);
return 0;
case V4L2_SEL_TGT_CROP_DEFAULT:
@@ -1271,8 +1271,8 @@ static int mt9m114_pa_set_selection(struct v4l2_subdev *sd,
if (sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL;
- crop = v4l2_subdev_get_pad_crop(sd, state, sel->pad);
- format = v4l2_subdev_get_pad_format(sd, state, sel->pad);
+ crop = v4l2_subdev_state_get_crop(state, sel->pad);
+ format = v4l2_subdev_state_get_format(state, sel->pad);
/*
* Clamp the crop rectangle. The vertical coordinates must be even, and
@@ -1304,7 +1304,6 @@ static int mt9m114_pa_set_selection(struct v4l2_subdev *sd,
}
static const struct v4l2_subdev_pad_ops mt9m114_pa_pad_ops = {
- .init_cfg = mt9m114_pa_init_cfg,
.enum_mbus_code = mt9m114_pa_enum_mbus_code,
.enum_frame_size = mt9m114_pa_enum_framesizes,
.get_fmt = v4l2_subdev_get_fmt,
@@ -1317,6 +1316,10 @@ static const struct v4l2_subdev_ops mt9m114_pa_ops = {
.pad = &mt9m114_pa_pad_ops,
};
+static const struct v4l2_subdev_internal_ops mt9m114_pa_internal_ops = {
+ .init_state = mt9m114_pa_init_state,
+};
+
static int mt9m114_pa_init(struct mt9m114 *sensor)
{
struct v4l2_ctrl_handler *hdl = &sensor->pa.hdl;
@@ -1329,6 +1332,7 @@ static int mt9m114_pa_init(struct mt9m114 *sensor)
/* Initialize the subdev. */
v4l2_subdev_init(sd, &mt9m114_pa_ops);
+ sd->internal_ops = &mt9m114_pa_internal_ops;
v4l2_i2c_subdev_set_name(sd, sensor->client, NULL, " pixel array");
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -1402,7 +1406,7 @@ static int mt9m114_pa_init(struct mt9m114 *sensor)
/* Update the range of the blanking controls based on the format. */
state = v4l2_subdev_lock_and_get_active_state(sd);
- format = v4l2_subdev_get_pad_format(sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
mt9m114_pa_ctrl_update_blanking(sensor, format);
v4l2_subdev_unlock_state(state);
@@ -1581,12 +1585,20 @@ static int mt9m114_ifp_s_stream(struct v4l2_subdev *sd, int enable)
return ret;
}
-static int mt9m114_ifp_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *interval)
+static int mt9m114_ifp_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *interval)
{
struct v4l2_fract *ival = &interval->interval;
struct mt9m114 *sensor = ifp_to_mt9m114(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(sensor->ifp.hdl.lock);
ival->numerator = 1;
@@ -1597,13 +1609,21 @@ static int mt9m114_ifp_g_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-static int mt9m114_ifp_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *interval)
+static int mt9m114_ifp_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *interval)
{
struct v4l2_fract *ival = &interval->interval;
struct mt9m114 *sensor = ifp_to_mt9m114(sd);
int ret = 0;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(sensor->ifp.hdl.lock);
if (ival->numerator != 0 && ival->denominator != 0)
@@ -1624,15 +1644,15 @@ static int mt9m114_ifp_s_frame_interval(struct v4l2_subdev *sd,
return ret;
}
-static int mt9m114_ifp_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int mt9m114_ifp_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct mt9m114 *sensor = ifp_to_mt9m114(sd);
struct v4l2_mbus_framefmt *format;
struct v4l2_rect *crop;
struct v4l2_rect *compose;
- format = v4l2_subdev_get_pad_format(sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
format->width = MT9M114_PIXEL_ARRAY_WIDTH;
format->height = MT9M114_PIXEL_ARRAY_HEIGHT;
@@ -1643,21 +1663,21 @@ static int mt9m114_ifp_init_cfg(struct v4l2_subdev *sd,
format->quantization = V4L2_QUANTIZATION_FULL_RANGE;
format->xfer_func = V4L2_XFER_FUNC_NONE;
- crop = v4l2_subdev_get_pad_crop(sd, state, 0);
+ crop = v4l2_subdev_state_get_crop(state, 0);
crop->left = 4;
crop->top = 4;
crop->width = format->width - 8;
crop->height = format->height - 8;
- compose = v4l2_subdev_get_pad_compose(sd, state, 0);
+ compose = v4l2_subdev_state_get_compose(state, 0);
compose->left = 0;
compose->top = 0;
compose->width = crop->width;
compose->height = crop->height;
- format = v4l2_subdev_get_pad_format(sd, state, 1);
+ format = v4l2_subdev_state_get_format(state, 1);
format->width = compose->width;
format->height = compose->height;
@@ -1738,7 +1758,7 @@ static int mt9m114_ifp_enum_framesizes(struct v4l2_subdev *sd,
} else {
const struct v4l2_rect *crop;
- crop = v4l2_subdev_get_pad_crop(sd, state, 0);
+ crop = v4l2_subdev_state_get_crop(state, 0);
fse->max_width = crop->width;
fse->max_height = crop->height;
@@ -1777,7 +1797,7 @@ static int mt9m114_ifp_set_fmt(struct v4l2_subdev *sd,
struct mt9m114 *sensor = ifp_to_mt9m114(sd);
struct v4l2_mbus_framefmt *format;
- format = v4l2_subdev_get_pad_format(sd, state, fmt->pad);
+ format = v4l2_subdev_state_get_format(state, fmt->pad);
if (fmt->pad == 0) {
/* Only the size can be changed on the sink pad. */
@@ -1797,7 +1817,7 @@ static int mt9m114_ifp_set_fmt(struct v4l2_subdev *sd,
/* If the output format is RAW10, bypass the scaler. */
if (format->code == MEDIA_BUS_FMT_SGRBG10_1X10)
- *format = *v4l2_subdev_get_pad_format(sd, state, 0);
+ *format = *v4l2_subdev_state_get_format(state, 0);
}
fmt->format = *format;
@@ -1819,7 +1839,7 @@ static int mt9m114_ifp_get_selection(struct v4l2_subdev *sd,
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
- sel->r = *v4l2_subdev_get_pad_crop(sd, state, 0);
+ sel->r = *v4l2_subdev_state_get_crop(state, 0);
break;
case V4L2_SEL_TGT_CROP_DEFAULT:
@@ -1828,7 +1848,7 @@ static int mt9m114_ifp_get_selection(struct v4l2_subdev *sd,
* The crop default and bounds are equal to the sink
* format size minus 4 pixels on each side for demosaicing.
*/
- format = v4l2_subdev_get_pad_format(sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
sel->r.left = 4;
sel->r.top = 4;
@@ -1837,7 +1857,7 @@ static int mt9m114_ifp_get_selection(struct v4l2_subdev *sd,
break;
case V4L2_SEL_TGT_COMPOSE:
- sel->r = *v4l2_subdev_get_pad_compose(sd, state, 0);
+ sel->r = *v4l2_subdev_state_get_compose(state, 0);
break;
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
@@ -1846,7 +1866,7 @@ static int mt9m114_ifp_get_selection(struct v4l2_subdev *sd,
* The compose default and bounds sizes are equal to the sink
* crop rectangle size.
*/
- crop = v4l2_subdev_get_pad_crop(sd, state, 0);
+ crop = v4l2_subdev_state_get_crop(state, 0);
sel->r.left = 0;
sel->r.top = 0;
sel->r.width = crop->width;
@@ -1877,9 +1897,9 @@ static int mt9m114_ifp_set_selection(struct v4l2_subdev *sd,
if (sel->pad != 0)
return -EINVAL;
- format = v4l2_subdev_get_pad_format(sd, state, 0);
- crop = v4l2_subdev_get_pad_crop(sd, state, 0);
- compose = v4l2_subdev_get_pad_compose(sd, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
+ crop = v4l2_subdev_state_get_crop(state, 0);
+ compose = v4l2_subdev_state_get_compose(state, 0);
if (sel->target == V4L2_SEL_TGT_CROP) {
/*
@@ -1921,7 +1941,7 @@ static int mt9m114_ifp_set_selection(struct v4l2_subdev *sd,
}
/* Propagate the compose rectangle to the source format. */
- format = v4l2_subdev_get_pad_format(sd, state, 1);
+ format = v4l2_subdev_state_get_format(state, 1);
format->width = compose->width;
format->height = compose->height;
@@ -1963,12 +1983,9 @@ static int mt9m114_ifp_registered(struct v4l2_subdev *sd)
static const struct v4l2_subdev_video_ops mt9m114_ifp_video_ops = {
.s_stream = mt9m114_ifp_s_stream,
- .g_frame_interval = mt9m114_ifp_g_frame_interval,
- .s_frame_interval = mt9m114_ifp_s_frame_interval,
};
static const struct v4l2_subdev_pad_ops mt9m114_ifp_pad_ops = {
- .init_cfg = mt9m114_ifp_init_cfg,
.enum_mbus_code = mt9m114_ifp_enum_mbus_code,
.enum_frame_size = mt9m114_ifp_enum_framesizes,
.enum_frame_interval = mt9m114_ifp_enum_frameintervals,
@@ -1976,6 +1993,8 @@ static const struct v4l2_subdev_pad_ops mt9m114_ifp_pad_ops = {
.set_fmt = mt9m114_ifp_set_fmt,
.get_selection = mt9m114_ifp_get_selection,
.set_selection = mt9m114_ifp_set_selection,
+ .get_frame_interval = mt9m114_ifp_get_frame_interval,
+ .set_frame_interval = mt9m114_ifp_set_frame_interval,
};
static const struct v4l2_subdev_ops mt9m114_ifp_ops = {
@@ -1984,6 +2003,7 @@ static const struct v4l2_subdev_ops mt9m114_ifp_ops = {
};
static const struct v4l2_subdev_internal_ops mt9m114_ifp_internal_ops = {
+ .init_state = mt9m114_ifp_init_state,
.registered = mt9m114_ifp_registered,
.unregistered = mt9m114_ifp_unregistered,
};
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
index 348f1e1098..596200d024 100644
--- a/drivers/media/i2c/mt9p031.c
+++ b/drivers/media/i2c/mt9p031.c
@@ -549,8 +549,7 @@ __mt9p031_get_pad_format(struct mt9p031 *mt9p031,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&mt9p031->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &mt9p031->format;
default:
@@ -565,8 +564,7 @@ __mt9p031_get_pad_crop(struct mt9p031 *mt9p031,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&mt9p031->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &mt9p031->crop;
default:
@@ -698,8 +696,8 @@ static int mt9p031_set_selection(struct v4l2_subdev *subdev,
return 0;
}
-static int mt9p031_init_cfg(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *sd_state)
+static int mt9p031_init_state(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state)
{
struct mt9p031 *mt9p031 = to_mt9p031(subdev);
struct v4l2_mbus_framefmt *format;
@@ -1043,7 +1041,6 @@ static const struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = {
};
static const struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
- .init_cfg = mt9p031_init_cfg,
.enum_mbus_code = mt9p031_enum_mbus_code,
.enum_frame_size = mt9p031_enum_frame_size,
.get_fmt = mt9p031_get_format,
@@ -1059,6 +1056,7 @@ static const struct v4l2_subdev_ops mt9p031_subdev_ops = {
};
static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
+ .init_state = mt9p031_init_state,
.registered = mt9p031_registered,
.open = mt9p031_open,
.close = mt9p031_close,
@@ -1191,7 +1189,7 @@ static int mt9p031_probe(struct i2c_client *client)
mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- ret = mt9p031_init_cfg(&mt9p031->subdev, NULL);
+ ret = mt9p031_init_state(&mt9p031->subdev, NULL);
if (ret)
goto done;
diff --git a/drivers/media/i2c/mt9t112.c b/drivers/media/i2c/mt9t112.c
index 93f34b7670..fb1588c57c 100644
--- a/drivers/media/i2c/mt9t112.c
+++ b/drivers/media/i2c/mt9t112.c
@@ -982,7 +982,6 @@ static int mt9t112_set_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
return mt9t112_s_fmt(sd, mf);
- sd_state->pads->try_fmt = *mf;
return 0;
}
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
index 37a634b92c..8834ff8786 100644
--- a/drivers/media/i2c/mt9v011.c
+++ b/drivers/media/i2c/mt9v011.c
@@ -356,15 +356,23 @@ static int mt9v011_set_fmt(struct v4l2_subdev *sd,
set_res(sd);
} else {
- sd_state->pads->try_fmt = *fmt;
+ *v4l2_subdev_state_get_format(sd_state, 0) = *fmt;
}
return 0;
}
-static int mt9v011_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int mt9v011_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
calc_fps(sd,
&ival->interval.numerator,
&ival->interval.denominator);
@@ -372,12 +380,20 @@ static int mt9v011_g_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-static int mt9v011_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int mt9v011_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct v4l2_fract *tpf = &ival->interval;
u16 speed;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
speed = calc_speed(sd, tpf->numerator, tpf->denominator);
mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed);
@@ -455,19 +471,15 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
#endif
};
-static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
- .g_frame_interval = mt9v011_g_frame_interval,
- .s_frame_interval = mt9v011_s_frame_interval,
-};
-
static const struct v4l2_subdev_pad_ops mt9v011_pad_ops = {
.enum_mbus_code = mt9v011_enum_mbus_code,
.set_fmt = mt9v011_set_fmt,
+ .get_frame_interval = mt9v011_get_frame_interval,
+ .set_frame_interval = mt9v011_set_frame_interval,
};
static const struct v4l2_subdev_ops mt9v011_ops = {
.core = &mt9v011_core_ops,
- .video = &mt9v011_video_ops,
.pad = &mt9v011_pad_ops,
};
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 1c6f6cea12..3ca76eeae7 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -356,8 +356,7 @@ __mt9v032_get_pad_format(struct mt9v032 *mt9v032,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&mt9v032->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &mt9v032->format;
default:
@@ -372,8 +371,7 @@ __mt9v032_get_pad_crop(struct mt9v032 *mt9v032,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&mt9v032->subdev, sd_state,
- pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &mt9v032->crop;
default:
@@ -931,13 +929,13 @@ static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
struct v4l2_mbus_framefmt *format;
struct v4l2_rect *crop;
- crop = v4l2_subdev_get_try_crop(subdev, fh->state, 0);
+ crop = v4l2_subdev_state_get_crop(fh->state, 0);
crop->left = MT9V032_COLUMN_START_DEF;
crop->top = MT9V032_ROW_START_DEF;
crop->width = MT9V032_WINDOW_WIDTH_DEF;
crop->height = MT9V032_WINDOW_HEIGHT_DEF;
- format = v4l2_subdev_get_try_format(subdev, fh->state, 0);
+ format = v4l2_subdev_state_get_format(fh->state, 0);
if (mt9v032->model->color)
format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c
index f859b49e13..b0b98ed3c1 100644
--- a/drivers/media/i2c/mt9v111.c
+++ b/drivers/media/i2c/mt9v111.c
@@ -35,7 +35,7 @@
* The IFP can produce several output image formats from the sensor core
* output. This driver currently supports only YUYV format permutations.
*
- * The driver allows manual frame rate control through s_frame_interval subdev
+ * The driver allows manual frame rate control through set_frame_interval subdev
* operation or V4L2_CID_V/HBLANK controls, but it is known that the
* auto-exposure algorithm might modify the programmed frame rate. While the
* driver initially programs the sensor with auto-exposure and
@@ -719,8 +719,9 @@ error_unlock:
return ret;
}
-static int mt9v111_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int mt9v111_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct mt9v111_dev *mt9v111 = sd_to_mt9v111(sd);
struct v4l2_fract *tpf = &ival->interval;
@@ -729,6 +730,13 @@ static int mt9v111_s_frame_interval(struct v4l2_subdev *sd,
tpf->denominator;
unsigned int max_fps;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (!tpf->numerator)
tpf->numerator = 1;
@@ -771,12 +779,20 @@ static int mt9v111_s_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-static int mt9v111_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int mt9v111_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct mt9v111_dev *mt9v111 = sd_to_mt9v111(sd);
struct v4l2_fract *tpf = &ival->interval;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&mt9v111->stream_mutex);
tpf->numerator = 1;
@@ -795,7 +811,7 @@ static struct v4l2_mbus_framefmt *__mt9v111_get_pad_format(
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&mt9v111->sd, sd_state, pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &mt9v111->fmt;
default:
@@ -948,10 +964,10 @@ done:
return 0;
}
-static int mt9v111_init_cfg(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *sd_state)
+static int mt9v111_init_state(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state)
{
- sd_state->pads->try_fmt = mt9v111_def_fmt;
+ *v4l2_subdev_state_get_format(sd_state, 0) = mt9v111_def_fmt;
return 0;
}
@@ -962,17 +978,16 @@ static const struct v4l2_subdev_core_ops mt9v111_core_ops = {
static const struct v4l2_subdev_video_ops mt9v111_video_ops = {
.s_stream = mt9v111_s_stream,
- .s_frame_interval = mt9v111_s_frame_interval,
- .g_frame_interval = mt9v111_g_frame_interval,
};
static const struct v4l2_subdev_pad_ops mt9v111_pad_ops = {
- .init_cfg = mt9v111_init_cfg,
.enum_mbus_code = mt9v111_enum_mbus_code,
.enum_frame_size = mt9v111_enum_frame_size,
.enum_frame_interval = mt9v111_enum_frame_interval,
.get_fmt = mt9v111_get_format,
.set_fmt = mt9v111_set_format,
+ .get_frame_interval = mt9v111_get_frame_interval,
+ .set_frame_interval = mt9v111_set_frame_interval,
};
static const struct v4l2_subdev_ops mt9v111_ops = {
@@ -981,6 +996,10 @@ static const struct v4l2_subdev_ops mt9v111_ops = {
.pad = &mt9v111_pad_ops,
};
+static const struct v4l2_subdev_internal_ops mt9v111_internal_ops = {
+ .init_state = mt9v111_init_state,
+};
+
static const struct media_entity_operations mt9v111_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -1194,6 +1213,7 @@ static int mt9v111_probe(struct i2c_client *client)
mt9v111->pending = true;
v4l2_i2c_subdev_init(&mt9v111->sd, client, &mt9v111_ops);
+ mt9v111->sd.internal_ops = &mt9v111_internal_ops;
mt9v111->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
mt9v111->sd.entity.ops = &mt9v111_subdev_entity_ops;
diff --git a/drivers/media/i2c/og01a1b.c b/drivers/media/i2c/og01a1b.c
index 51378ba16a..bac9597faf 100644
--- a/drivers/media/i2c/og01a1b.c
+++ b/drivers/media/i2c/og01a1b.c
@@ -769,8 +769,7 @@ static int og01a1b_set_format(struct v4l2_subdev *sd,
mutex_lock(&og01a1b->mutex);
og01a1b_update_pad_format(mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state,
- fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
} else {
og01a1b->cur_mode = mode;
__v4l2_ctrl_s_ctrl(og01a1b->link_freq, mode->link_freq_index);
@@ -803,9 +802,8 @@ static int og01a1b_get_format(struct v4l2_subdev *sd,
mutex_lock(&og01a1b->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&og01a1b->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
og01a1b_update_pad_format(og01a1b->cur_mode, &fmt->format);
@@ -850,7 +848,7 @@ static int og01a1b_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&og01a1b->mutex);
og01a1b_update_pad_format(&supported_modes[0],
- v4l2_subdev_get_try_format(sd, fh->state, 0));
+ v4l2_subdev_state_get_format(fh->state, 0));
mutex_unlock(&og01a1b->mutex);
return 0;
diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c
index 02de09edc3..5606437f37 100644
--- a/drivers/media/i2c/ov01a10.c
+++ b/drivers/media/i2c/ov01a10.c
@@ -723,14 +723,14 @@ static int ov01a10_set_format(struct v4l2_subdev *sd,
h_blank);
}
- format = v4l2_subdev_get_pad_format(sd, sd_state, fmt->stream);
+ format = v4l2_subdev_state_get_format(sd_state, fmt->stream);
*format = fmt->format;
return 0;
}
-static int ov01a10_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int ov01a10_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_TRY,
@@ -813,7 +813,6 @@ static const struct v4l2_subdev_video_ops ov01a10_video_ops = {
};
static const struct v4l2_subdev_pad_ops ov01a10_pad_ops = {
- .init_cfg = ov01a10_init_cfg,
.set_fmt = ov01a10_set_format,
.get_fmt = v4l2_subdev_get_fmt,
.get_selection = ov01a10_get_selection,
@@ -827,6 +826,10 @@ static const struct v4l2_subdev_ops ov01a10_subdev_ops = {
.pad = &ov01a10_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov01a10_internal_ops = {
+ .init_state = ov01a10_init_state,
+};
+
static const struct media_entity_operations ov01a10_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -873,6 +876,7 @@ static int ov01a10_probe(struct i2c_client *client)
return -ENOMEM;
v4l2_i2c_subdev_init(&ov01a10->sd, client, &ov01a10_subdev_ops);
+ ov01a10->sd.internal_ops = &ov01a10_internal_ops;
ret = ov01a10_identify_module(ov01a10);
if (ret)
diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c
index 848e47a464..6c30e1a0d8 100644
--- a/drivers/media/i2c/ov02a10.c
+++ b/drivers/media/i2c/ov02a10.c
@@ -315,7 +315,7 @@ static int ov02a10_set_fmt(struct v4l2_subdev *sd,
ov02a10_fill_fmt(ov02a10->cur_mode, mbus_fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- frame_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ frame_fmt = v4l2_subdev_state_get_format(sd_state, 0);
else
frame_fmt = &ov02a10->fmt;
@@ -336,8 +336,8 @@ static int ov02a10_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&ov02a10->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- fmt->format = *v4l2_subdev_get_try_format(sd, sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
} else {
fmt->format = ov02a10->fmt;
mbus_fmt->code = ov02a10->fmt.code;
@@ -511,8 +511,8 @@ static int __ov02a10_stop_stream(struct ov02a10 *ov02a10)
SC_CTRL_MODE_STANDBY);
}
-static int ov02a10_entity_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int ov02a10_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_TRY,
@@ -709,7 +709,6 @@ static const struct v4l2_subdev_video_ops ov02a10_video_ops = {
};
static const struct v4l2_subdev_pad_ops ov02a10_pad_ops = {
- .init_cfg = ov02a10_entity_init_cfg,
.enum_mbus_code = ov02a10_enum_mbus_code,
.enum_frame_size = ov02a10_enum_frame_sizes,
.get_fmt = ov02a10_get_fmt,
@@ -721,6 +720,10 @@ static const struct v4l2_subdev_ops ov02a10_subdev_ops = {
.pad = &ov02a10_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov02a10_internal_ops = {
+ .init_state = ov02a10_init_state,
+};
+
static const struct media_entity_operations ov02a10_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -869,6 +872,7 @@ static int ov02a10_probe(struct i2c_client *client)
"failed to check HW configuration\n");
v4l2_i2c_subdev_init(&ov02a10->subdev, client, &ov02a10_subdev_ops);
+ ov02a10->subdev.internal_ops = &ov02a10_internal_ops;
ov02a10->mipi_clock_voltage = OV02A10_MIPI_TX_SPEED_DEFAULT;
ov02a10->fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index 3d49e3fa8e..1bacbdfa42 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -1145,7 +1145,7 @@ static int ov08d10_set_format(struct v4l2_subdev *sd,
mutex_lock(&ov08d10->mutex);
ov08d10_update_pad_format(ov08d10, mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) =
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) =
fmt->format;
} else {
ov08d10->cur_mode = mode;
@@ -1184,9 +1184,8 @@ static int ov08d10_get_format(struct v4l2_subdev *sd,
mutex_lock(&ov08d10->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&ov08d10->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
ov08d10_update_pad_format(ov08d10, ov08d10->cur_mode,
&fmt->format);
@@ -1242,7 +1241,7 @@ static int ov08d10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&ov08d10->mutex);
ov08d10_update_pad_format(ov08d10, &ov08d10->priv_lane->sp_modes[0],
- v4l2_subdev_get_try_format(sd, fh->state, 0));
+ v4l2_subdev_state_get_format(fh->state, 0));
mutex_unlock(&ov08d10->mutex);
return 0;
diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c
index b41b6866a0..abbb0b774d 100644
--- a/drivers/media/i2c/ov08x40.c
+++ b/drivers/media/i2c/ov08x40.c
@@ -2536,7 +2536,7 @@ static int ov08x40_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
const struct ov08x40_mode *default_mode = &supported_modes[0];
struct ov08x40 *ov08x = to_ov08x40(sd);
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
mutex_lock(&ov08x->mutex);
@@ -2774,10 +2774,9 @@ static int ov08x40_do_get_pad_format(struct ov08x40 *ov08x,
struct v4l2_subdev_format *fmt)
{
struct v4l2_mbus_framefmt *framefmt;
- struct v4l2_subdev *sd = &ov08x->sd;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
ov08x40_update_pad_format(ov08x->cur_mode, fmt);
@@ -2826,7 +2825,7 @@ ov08x40_set_pad_format(struct v4l2_subdev *sd,
fmt->format.width, fmt->format.height);
ov08x40_update_pad_format(mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
ov08x->cur_mode = mode;
diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c
index 4c419014dd..09387e335d 100644
--- a/drivers/media/i2c/ov13858.c
+++ b/drivers/media/i2c/ov13858.c
@@ -1147,9 +1147,8 @@ static int ov13858_write_reg_list(struct ov13858 *ov13858,
static int ov13858_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct ov13858 *ov13858 = to_ov13858(sd);
- struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_get_try_format(sd,
- fh->state,
- 0);
+ struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_state_get_format(fh->state,
+ 0);
mutex_lock(&ov13858->mutex);
@@ -1317,10 +1316,9 @@ static int ov13858_do_get_pad_format(struct ov13858 *ov13858,
struct v4l2_subdev_format *fmt)
{
struct v4l2_mbus_framefmt *framefmt;
- struct v4l2_subdev *sd = &ov13858->sd;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
ov13858_update_pad_format(ov13858->cur_mode, fmt);
@@ -1369,7 +1367,7 @@ ov13858_set_pad_format(struct v4l2_subdev *sd,
fmt->format.width, fmt->format.height);
ov13858_update_pad_format(mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
ov13858->cur_mode = mode;
diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c
index 2793e4675c..73c844aa56 100644
--- a/drivers/media/i2c/ov13b10.c
+++ b/drivers/media/i2c/ov13b10.c
@@ -755,9 +755,8 @@ static int ov13b10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
const struct ov13b10_mode *default_mode = &supported_modes[0];
struct ov13b10 *ov13b = to_ov13b10(sd);
- struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_get_try_format(sd,
- fh->state,
- 0);
+ struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_state_get_format(fh->state,
+ 0);
mutex_lock(&ov13b->mutex);
@@ -1002,10 +1001,9 @@ static int ov13b10_do_get_pad_format(struct ov13b10 *ov13b,
struct v4l2_subdev_format *fmt)
{
struct v4l2_mbus_framefmt *framefmt;
- struct v4l2_subdev *sd = &ov13b->sd;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
ov13b10_update_pad_format(ov13b->cur_mode, fmt);
@@ -1054,7 +1052,7 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd,
fmt->format.width, fmt->format.height);
ov13b10_update_pad_format(mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
ov13b->cur_mode = mode;
diff --git a/drivers/media/i2c/ov2640.c b/drivers/media/i2c/ov2640.c
index 28a01c6eff..67c4bd2916 100644
--- a/drivers/media/i2c/ov2640.c
+++ b/drivers/media/i2c/ov2640.c
@@ -920,7 +920,7 @@ static int ov2640_get_fmt(struct v4l2_subdev *sd,
return -EINVAL;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ mf = v4l2_subdev_state_get_format(sd_state, 0);
format->format = *mf;
return 0;
}
@@ -988,7 +988,7 @@ static int ov2640_set_fmt(struct v4l2_subdev *sd,
/* select format */
priv->cfmt_code = mf->code;
} else {
- sd_state->pads->try_fmt = *mf;
+ *v4l2_subdev_state_get_format(sd_state, 0) = *mf;
}
out:
mutex_unlock(&priv->lock);
@@ -996,11 +996,11 @@ out:
return ret;
}
-static int ov2640_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int ov2640_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, sd_state, 0);
+ v4l2_subdev_state_get_format(sd_state, 0);
const struct ov2640_win_size *win =
ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT);
@@ -1125,7 +1125,6 @@ static const struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
};
static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {
- .init_cfg = ov2640_init_cfg,
.enum_mbus_code = ov2640_enum_mbus_code,
.get_selection = ov2640_get_selection,
.get_fmt = ov2640_get_fmt,
@@ -1142,6 +1141,10 @@ static const struct v4l2_subdev_ops ov2640_subdev_ops = {
.video = &ov2640_subdev_video_ops,
};
+static const struct v4l2_subdev_internal_ops ov2640_internal_ops = {
+ .init_state = ov2640_init_state,
+};
+
static int ov2640_probe_dt(struct i2c_client *client,
struct ov2640_priv *priv)
{
@@ -1211,6 +1214,7 @@ static int ov2640_probe(struct i2c_client *client)
priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
+ priv->subdev.internal_ops = &ov2640_internal_ops;
priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
mutex_init(&priv->lock);
diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c
index 2c3dbe164e..1d0ef72a64 100644
--- a/drivers/media/i2c/ov2659.c
+++ b/drivers/media/i2c/ov2659.c
@@ -1033,7 +1033,7 @@ static int ov2659_get_fmt(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *mf;
- mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ mf = v4l2_subdev_state_get_format(sd_state, 0);
mutex_lock(&ov2659->lock);
fmt->format = *mf;
mutex_unlock(&ov2659->lock);
@@ -1109,7 +1109,7 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd,
mutex_lock(&ov2659->lock);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*mf = fmt->format;
} else {
s64 val;
@@ -1304,7 +1304,7 @@ static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
dev_dbg(&client->dev, "%s:\n", __func__);
diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c
index 72bab0ff8a..39d321e2b7 100644
--- a/drivers/media/i2c/ov2680.c
+++ b/drivers/media/i2c/ov2680.c
@@ -309,7 +309,7 @@ __ov2680_get_pad_format(struct ov2680_dev *sensor,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&sensor->sd, state, pad);
+ return v4l2_subdev_state_get_format(state, pad);
return &sensor->mode.fmt;
}
@@ -321,7 +321,7 @@ __ov2680_get_pad_crop(struct ov2680_dev *sensor,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_crop(&sensor->sd, state, pad);
+ return v4l2_subdev_state_get_crop(state, pad);
return &sensor->mode.crop;
}
@@ -552,11 +552,19 @@ err_disable_regulators:
return ret;
}
-static int ov2680_s_g_frame_interval(struct v4l2_subdev *sd,
+static int ov2680_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval *fi)
{
struct ov2680_dev *sensor = to_ov2680_dev(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&sensor->lock);
fi->interval = sensor->mode.frame_interval;
mutex_unlock(&sensor->lock);
@@ -650,7 +658,7 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd,
ov2680_fill_format(sensor, &format->format, width, height);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- try_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ try_fmt = v4l2_subdev_state_get_format(sd_state, 0);
*try_fmt = format->format;
return 0;
}
@@ -755,14 +763,14 @@ static int ov2680_set_selection(struct v4l2_subdev *sd,
return 0;
}
-static int ov2680_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int ov2680_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct ov2680_dev *sensor = to_ov2680_dev(sd);
- sd_state->pads[0].try_crop = ov2680_default_crop;
+ *v4l2_subdev_state_get_crop(sd_state, 0) = ov2680_default_crop;
- ov2680_fill_format(sensor, &sd_state->pads[0].try_fmt,
+ ov2680_fill_format(sensor, v4l2_subdev_state_get_format(sd_state, 0),
OV2680_DEFAULT_WIDTH, OV2680_DEFAULT_HEIGHT);
return 0;
}
@@ -870,13 +878,10 @@ static const struct v4l2_ctrl_ops ov2680_ctrl_ops = {
};
static const struct v4l2_subdev_video_ops ov2680_video_ops = {
- .g_frame_interval = ov2680_s_g_frame_interval,
- .s_frame_interval = ov2680_s_g_frame_interval,
.s_stream = ov2680_s_stream,
};
static const struct v4l2_subdev_pad_ops ov2680_pad_ops = {
- .init_cfg = ov2680_init_cfg,
.enum_mbus_code = ov2680_enum_mbus_code,
.enum_frame_size = ov2680_enum_frame_size,
.enum_frame_interval = ov2680_enum_frame_interval,
@@ -884,6 +889,8 @@ static const struct v4l2_subdev_pad_ops ov2680_pad_ops = {
.set_fmt = ov2680_set_fmt,
.get_selection = ov2680_get_selection,
.set_selection = ov2680_set_selection,
+ .get_frame_interval = ov2680_get_frame_interval,
+ .set_frame_interval = ov2680_get_frame_interval,
};
static const struct v4l2_subdev_ops ov2680_subdev_ops = {
@@ -891,6 +898,10 @@ static const struct v4l2_subdev_ops ov2680_subdev_ops = {
.pad = &ov2680_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov2680_internal_ops = {
+ .init_state = ov2680_init_state,
+};
+
static int ov2680_mode_init(struct ov2680_dev *sensor)
{
/* set initial mode */
@@ -915,6 +926,7 @@ static int ov2680_v4l2_register(struct ov2680_dev *sensor)
int ret = 0;
v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_subdev_ops);
+ sensor->sd.internal_ops = &ov2680_internal_ops;
sensor->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c
index 396583826a..9b8481b8dc 100644
--- a/drivers/media/i2c/ov2685.c
+++ b/drivers/media/i2c/ov2685.c
@@ -404,7 +404,7 @@ __ov2685_get_pad_crop(struct ov2685 *ov2685,
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&ov2685->subdev, state, pad);
+ return v4l2_subdev_state_get_crop(state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return mode->analog_crop;
}
@@ -547,7 +547,7 @@ static int ov2685_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&ov2685->mutex);
- try_fmt = v4l2_subdev_get_try_format(sd, fh->state, 0);
+ try_fmt = v4l2_subdev_state_get_format(fh->state, 0);
/* Initialize try_fmt */
ov2685_fill_fmt(&supported_modes[0], try_fmt);
diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c
index 6be22586c3..552935ccb4 100644
--- a/drivers/media/i2c/ov2740.c
+++ b/drivers/media/i2c/ov2740.c
@@ -3,7 +3,9 @@
#include <asm/unaligned.h>
#include <linux/acpi.h>
+#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
@@ -14,6 +16,7 @@
#include <media/v4l2-fwnode.h>
#define OV2740_LINK_FREQ_360MHZ 360000000ULL
+#define OV2740_LINK_FREQ_180MHZ 180000000ULL
#define OV2740_SCLK 72000000LL
#define OV2740_MCLK 19200000
#define OV2740_DATA_LANES 2
@@ -28,9 +31,6 @@
/* vertical-timings from sensor */
#define OV2740_REG_VTS 0x380e
-#define OV2740_VTS_DEF 0x088a
-#define OV2740_VTS_MIN 0x0460
-#define OV2740_VTS_MAX 0x7fff
/* horizontal-timings from sensor */
#define OV2740_REG_HTS 0x380c
@@ -84,6 +84,7 @@ struct nvm_data {
enum {
OV2740_LINK_FREQ_360MHZ_INDEX,
+ OV2740_LINK_FREQ_180MHZ_INDEX,
};
struct ov2740_reg {
@@ -116,6 +117,9 @@ struct ov2740_mode {
/* Min vertical timining size */
u32 vts_min;
+ /* Max vertical timining size */
+ u32 vts_max;
+
/* Link frequency needed for this resolution */
u32 link_freq_index;
@@ -124,7 +128,6 @@ struct ov2740_mode {
};
static const struct ov2740_reg mipi_data_rate_720mbps[] = {
- {0x0103, 0x01},
{0x0302, 0x4b},
{0x030d, 0x4b},
{0x030e, 0x02},
@@ -132,7 +135,17 @@ static const struct ov2740_reg mipi_data_rate_720mbps[] = {
{0x0312, 0x11},
};
-static const struct ov2740_reg mode_1932x1092_regs[] = {
+static const struct ov2740_reg mipi_data_rate_360mbps[] = {
+ {0x0302, 0x4b},
+ {0x0303, 0x01},
+ {0x030d, 0x4b},
+ {0x030e, 0x02},
+ {0x030a, 0x01},
+ {0x0312, 0x11},
+ {0x4837, 0x2c},
+};
+
+static const struct ov2740_reg mode_1932x1092_regs_360mhz[] = {
{0x3000, 0x00},
{0x3018, 0x32},
{0x3031, 0x0a},
@@ -285,6 +298,159 @@ static const struct ov2740_reg mode_1932x1092_regs[] = {
{0x3813, 0x01},
};
+static const struct ov2740_reg mode_1932x1092_regs_180mhz[] = {
+ {0x3000, 0x00},
+ {0x3018, 0x32}, /* 0x32 for 2 lanes, 0x12 for 1 lane */
+ {0x3031, 0x0a},
+ {0x3080, 0x08},
+ {0x3083, 0xB4},
+ {0x3103, 0x00},
+ {0x3104, 0x01},
+ {0x3106, 0x01},
+ {0x3500, 0x00},
+ {0x3501, 0x44},
+ {0x3502, 0x40},
+ {0x3503, 0x88},
+ {0x3507, 0x00},
+ {0x3508, 0x00},
+ {0x3509, 0x80},
+ {0x350c, 0x00},
+ {0x350d, 0x80},
+ {0x3510, 0x00},
+ {0x3511, 0x00},
+ {0x3512, 0x20},
+ {0x3632, 0x00},
+ {0x3633, 0x10},
+ {0x3634, 0x10},
+ {0x3635, 0x10},
+ {0x3645, 0x13},
+ {0x3646, 0x81},
+ {0x3636, 0x10},
+ {0x3651, 0x0a},
+ {0x3656, 0x02},
+ {0x3659, 0x04},
+ {0x365a, 0xda},
+ {0x365b, 0xa2},
+ {0x365c, 0x04},
+ {0x365d, 0x1d},
+ {0x365e, 0x1a},
+ {0x3662, 0xd7},
+ {0x3667, 0x78},
+ {0x3669, 0x0a},
+ {0x366a, 0x92},
+ {0x3700, 0x54},
+ {0x3702, 0x10},
+ {0x3706, 0x42},
+ {0x3709, 0x30},
+ {0x370b, 0xc2},
+ {0x3714, 0x63},
+ {0x3715, 0x01},
+ {0x3716, 0x00},
+ {0x371a, 0x3e},
+ {0x3732, 0x0e},
+ {0x3733, 0x10},
+ {0x375f, 0x0e},
+ {0x3768, 0x30},
+ {0x3769, 0x44},
+ {0x376a, 0x22},
+ {0x377b, 0x20},
+ {0x377c, 0x00},
+ {0x377d, 0x0c},
+ {0x3798, 0x00},
+ {0x37a1, 0x55},
+ {0x37a8, 0x6d},
+ {0x37c2, 0x04},
+ {0x37c5, 0x00},
+ {0x37c8, 0x00},
+ {0x3800, 0x00},
+ {0x3801, 0x00},
+ {0x3802, 0x00},
+ {0x3803, 0x00},
+ {0x3804, 0x07},
+ {0x3805, 0x8f},
+ {0x3806, 0x04},
+ {0x3807, 0x47},
+ {0x3808, 0x07},
+ {0x3809, 0x88},
+ {0x380a, 0x04},
+ {0x380b, 0x40},
+ {0x380c, 0x08},
+ {0x380d, 0x70},
+ {0x380e, 0x04},
+ {0x380f, 0x56},
+ {0x3810, 0x00},
+ {0x3811, 0x04},
+ {0x3812, 0x00},
+ {0x3813, 0x04},
+ {0x3814, 0x01},
+ {0x3815, 0x01},
+ {0x3820, 0x80},
+ {0x3821, 0x46},
+ {0x3822, 0x84},
+ {0x3829, 0x00},
+ {0x382a, 0x01},
+ {0x382b, 0x01},
+ {0x3830, 0x04},
+ {0x3836, 0x01},
+ {0x3837, 0x08},
+ {0x3839, 0x01},
+ {0x383a, 0x00},
+ {0x383b, 0x08},
+ {0x383c, 0x00},
+ {0x3f0b, 0x00},
+ {0x4001, 0x20},
+ {0x4009, 0x07},
+ {0x4003, 0x10},
+ {0x4010, 0xe0},
+ {0x4016, 0x00},
+ {0x4017, 0x10},
+ {0x4044, 0x02},
+ {0x4304, 0x08},
+ {0x4307, 0x30},
+ {0x4320, 0x80},
+ {0x4322, 0x00},
+ {0x4323, 0x00},
+ {0x4324, 0x00},
+ {0x4325, 0x00},
+ {0x4326, 0x00},
+ {0x4327, 0x00},
+ {0x4328, 0x00},
+ {0x4329, 0x00},
+ {0x432c, 0x03},
+ {0x432d, 0x81},
+ {0x4501, 0x84},
+ {0x4502, 0x40},
+ {0x4503, 0x18},
+ {0x4504, 0x04},
+ {0x4508, 0x02},
+ {0x4601, 0x10},
+ {0x4800, 0x00},
+ {0x4816, 0x52},
+ {0x5000, 0x73}, /* 0x7f enable DPC */
+ {0x5001, 0x00},
+ {0x5005, 0x38},
+ {0x501e, 0x0d},
+ {0x5040, 0x00},
+ {0x5901, 0x00},
+ {0x3800, 0x00},
+ {0x3801, 0x00},
+ {0x3802, 0x00},
+ {0x3803, 0x00},
+ {0x3804, 0x07},
+ {0x3805, 0x8f},
+ {0x3806, 0x04},
+ {0x3807, 0x47},
+ {0x3808, 0x07},
+ {0x3809, 0x8c},
+ {0x380a, 0x04},
+ {0x380b, 0x44},
+ {0x3810, 0x00},
+ {0x3811, 0x00},
+ {0x3812, 0x00},
+ {0x3813, 0x01},
+ {0x4003, 0x40}, /* set Black level to 0x40 */
+};
+
static const char * const ov2740_test_pattern_menu[] = {
"Disabled",
"Color Bar",
@@ -295,6 +461,7 @@ static const char * const ov2740_test_pattern_menu[] = {
static const s64 link_freq_menu_items[] = {
OV2740_LINK_FREQ_360MHZ,
+ OV2740_LINK_FREQ_180MHZ,
};
static const struct ov2740_link_freq_config link_freq_configs[] = {
@@ -304,23 +471,46 @@ static const struct ov2740_link_freq_config link_freq_configs[] = {
.regs = mipi_data_rate_720mbps,
}
},
+ [OV2740_LINK_FREQ_180MHZ_INDEX] = {
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mipi_data_rate_360mbps),
+ .regs = mipi_data_rate_360mbps,
+ }
+ },
};
-static const struct ov2740_mode supported_modes[] = {
+static const struct ov2740_mode supported_modes_360mhz[] = {
{
.width = 1932,
.height = 1092,
.hts = 2160,
- .vts_def = OV2740_VTS_DEF,
- .vts_min = OV2740_VTS_MIN,
+ .vts_min = 1120,
+ .vts_def = 2186,
+ .vts_max = 32767,
.reg_list = {
- .num_of_regs = ARRAY_SIZE(mode_1932x1092_regs),
- .regs = mode_1932x1092_regs,
+ .num_of_regs = ARRAY_SIZE(mode_1932x1092_regs_360mhz),
+ .regs = mode_1932x1092_regs_360mhz,
},
.link_freq_index = OV2740_LINK_FREQ_360MHZ_INDEX,
},
};
+static const struct ov2740_mode supported_modes_180mhz[] = {
+ {
+ .width = 1932,
+ .height = 1092,
+ .hts = 2160,
+ .vts_min = 1110,
+ .vts_def = 1110,
+ .vts_max = 2047,
+ .reg_list = {
+ .num_of_regs = ARRAY_SIZE(mode_1932x1092_regs_180mhz),
+ .regs = mode_1932x1092_regs_180mhz,
+ },
+ .link_freq_index = OV2740_LINK_FREQ_180MHZ_INDEX,
+ },
+};
+
struct ov2740 {
struct v4l2_subdev sd;
struct media_pad pad;
@@ -333,12 +523,20 @@ struct ov2740 {
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *exposure;
+ /* GPIOs, clocks */
+ struct gpio_desc *reset_gpio;
+ struct clk *clk;
+
/* Current mode */
const struct ov2740_mode *cur_mode;
/* NVM data inforamtion */
struct nvm_data *nvm;
+ /* Supported modes */
+ const struct ov2740_mode *supported_modes;
+ int supported_modes_count;
+
/* True if the device has been identified */
bool identified;
};
@@ -583,7 +781,7 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
pixel_rate, 1, pixel_rate);
vblank_min = cur_mode->vts_min - cur_mode->height;
- vblank_max = OV2740_VTS_MAX - cur_mode->height;
+ vblank_max = cur_mode->vts_max - cur_mode->height;
vblank_default = cur_mode->vts_def - cur_mode->height;
ov2740->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov2740_ctrl_ops,
V4L2_CID_VBLANK, vblank_min,
@@ -735,6 +933,15 @@ static int ov2740_start_streaming(struct ov2740 *ov2740)
if (ov2740->nvm)
ov2740_load_otp_data(ov2740->nvm);
+ /* Reset the sensor */
+ ret = ov2740_write_reg(ov2740, 0x0103, 1, 0x01);
+ if (ret) {
+ dev_err(&client->dev, "failed to reset\n");
+ return ret;
+ }
+
+ usleep_range(10000, 15000);
+
link_freq_index = ov2740->cur_mode->link_freq_index;
reg_list = &link_freq_configs[link_freq_index].reg_list;
ret = ov2740_write_reg_list(ov2740, reg_list);
@@ -810,13 +1017,13 @@ static int ov2740_set_format(struct v4l2_subdev *sd,
const struct ov2740_mode *mode;
s32 vblank_def, h_blank;
- mode = v4l2_find_nearest_size(supported_modes,
- ARRAY_SIZE(supported_modes), width,
- height, fmt->format.width,
- fmt->format.height);
+ mode = v4l2_find_nearest_size(ov2740->supported_modes,
+ ov2740->supported_modes_count,
+ width, height,
+ fmt->format.width, fmt->format.height);
ov2740_update_pad_format(mode, &fmt->format);
- *v4l2_subdev_get_pad_format(sd, sd_state, fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
return 0;
@@ -830,7 +1037,7 @@ static int ov2740_set_format(struct v4l2_subdev *sd,
vblank_def = mode->vts_def - mode->height;
__v4l2_ctrl_modify_range(ov2740->vblank,
mode->vts_min - mode->height,
- OV2740_VTS_MAX - mode->height, 1, vblank_def);
+ mode->vts_max - mode->height, 1, vblank_def);
__v4l2_ctrl_s_ctrl(ov2740->vblank, vblank_def);
h_blank = mode->hts - mode->width;
__v4l2_ctrl_modify_range(ov2740->hblank, h_blank, h_blank, 1, h_blank);
@@ -854,7 +1061,10 @@ static int ov2740_enum_frame_size(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
- if (fse->index >= ARRAY_SIZE(supported_modes))
+ struct ov2740 *ov2740 = to_ov2740(sd);
+ const struct ov2740_mode *supported_modes = ov2740->supported_modes;
+
+ if (fse->index >= ov2740->supported_modes_count)
return -EINVAL;
if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
@@ -868,12 +1078,13 @@ static int ov2740_enum_frame_size(struct v4l2_subdev *sd,
return 0;
}
-static int ov2740_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int ov2740_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
- ov2740_update_pad_format(&supported_modes[0],
- v4l2_subdev_get_pad_format(sd, sd_state, 0));
+ struct ov2740 *ov2740 = to_ov2740(sd);
+ ov2740_update_pad_format(&ov2740->supported_modes[0],
+ v4l2_subdev_state_get_format(sd_state, 0));
return 0;
}
@@ -886,7 +1097,6 @@ static const struct v4l2_subdev_pad_ops ov2740_pad_ops = {
.set_fmt = ov2740_set_format,
.enum_mbus_code = ov2740_enum_mbus_code,
.enum_frame_size = ov2740_enum_frame_size,
- .init_cfg = ov2740_init_cfg,
};
static const struct v4l2_subdev_ops ov2740_subdev_ops = {
@@ -894,12 +1104,18 @@ static const struct v4l2_subdev_ops ov2740_subdev_ops = {
.pad = &ov2740_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov2740_internal_ops = {
+ .init_state = ov2740_init_state,
+};
+
static const struct media_entity_operations ov2740_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
static int ov2740_check_hwcfg(struct device *dev)
{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov2740 *ov2740 = to_ov2740(sd);
struct fwnode_handle *ep;
struct fwnode_handle *fwnode = dev_fwnode(dev);
struct v4l2_fwnode_endpoint bus_cfg = {
@@ -909,23 +1125,32 @@ static int ov2740_check_hwcfg(struct device *dev)
int ret;
unsigned int i, j;
+ /*
+ * Sometimes the fwnode graph is initialized by the bridge driver,
+ * wait for this.
+ */
+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+ if (!ep)
+ return -EPROBE_DEFER;
+
ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
- if (ret)
- return ret;
+ if (ret) {
+ fwnode_handle_put(ep);
+ return dev_err_probe(dev, ret,
+ "reading clock-frequency property\n");
+ }
- if (mclk != OV2740_MCLK)
+ if (mclk != OV2740_MCLK) {
+ fwnode_handle_put(ep);
return dev_err_probe(dev, -EINVAL,
"external clock %d is not supported\n",
mclk);
-
- ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
- if (!ep)
- return -EPROBE_DEFER;
+ }
ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
fwnode_handle_put(ep);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "parsing endpoint failed\n");
if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV2740_DATA_LANES) {
ret = dev_err_probe(dev, -EINVAL,
@@ -946,14 +1171,29 @@ static int ov2740_check_hwcfg(struct device *dev)
break;
}
- if (j == bus_cfg.nr_of_link_frequencies) {
- ret = dev_err_probe(dev, -EINVAL,
- "no link frequency %lld supported\n",
- link_freq_menu_items[i]);
- goto check_hwcfg_error;
+ if (j == bus_cfg.nr_of_link_frequencies)
+ continue;
+
+ switch (i) {
+ case OV2740_LINK_FREQ_360MHZ_INDEX:
+ ov2740->supported_modes = supported_modes_360mhz;
+ ov2740->supported_modes_count =
+ ARRAY_SIZE(supported_modes_360mhz);
+ break;
+ case OV2740_LINK_FREQ_180MHZ_INDEX:
+ ov2740->supported_modes = supported_modes_180mhz;
+ ov2740->supported_modes_count =
+ ARRAY_SIZE(supported_modes_180mhz);
+ break;
}
+
+ break; /* Prefer modes from first available link-freq */
}
+ if (!ov2740->supported_modes)
+ ret = dev_err_probe(dev, -EINVAL,
+ "no supported link frequencies\n");
+
check_hwcfg_error:
v4l2_fwnode_endpoint_free(&bus_cfg);
@@ -1047,6 +1287,32 @@ static int ov2740_register_nvmem(struct i2c_client *client,
return 0;
}
+static int ov2740_suspend(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov2740 *ov2740 = to_ov2740(sd);
+
+ gpiod_set_value_cansleep(ov2740->reset_gpio, 1);
+ clk_disable_unprepare(ov2740->clk);
+ return 0;
+}
+
+static int ov2740_resume(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov2740 *ov2740 = to_ov2740(sd);
+ int ret;
+
+ ret = clk_prepare_enable(ov2740->clk);
+ if (ret)
+ return ret;
+
+ gpiod_set_value_cansleep(ov2740->reset_gpio, 0);
+ msleep(20);
+
+ return 0;
+}
+
static int ov2740_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -1054,23 +1320,42 @@ static int ov2740_probe(struct i2c_client *client)
bool full_power;
int ret;
- ret = ov2740_check_hwcfg(&client->dev);
- if (ret)
- return dev_err_probe(dev, ret, "failed to check HW configuration\n");
-
ov2740 = devm_kzalloc(&client->dev, sizeof(*ov2740), GFP_KERNEL);
if (!ov2740)
return -ENOMEM;
v4l2_i2c_subdev_init(&ov2740->sd, client, &ov2740_subdev_ops);
+ ov2740->sd.internal_ops = &ov2740_internal_ops;
+
+ ret = ov2740_check_hwcfg(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to check HW configuration\n");
+
+ ov2740->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ov2740->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ov2740->reset_gpio),
+ "failed to get reset GPIO\n");
+
+ ov2740->clk = devm_clk_get_optional(dev, "clk");
+ if (IS_ERR(ov2740->clk))
+ return dev_err_probe(dev, PTR_ERR(ov2740->clk),
+ "failed to get clock\n");
+
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
- ret = ov2740_identify_module(ov2740);
+ /* ACPI does not always clear the reset GPIO / enable the clock */
+ ret = ov2740_resume(dev);
if (ret)
- return dev_err_probe(dev, ret, "failed to find sensor\n");
+ return dev_err_probe(dev, ret, "failed to power on sensor\n");
+
+ ret = ov2740_identify_module(ov2740);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to find sensor\n");
+ goto probe_error_power_off;
+ }
}
- ov2740->cur_mode = &supported_modes[0];
+ ov2740->cur_mode = &ov2740->supported_modes[0];
ret = ov2740_init_controls(ov2740);
if (ret) {
dev_err_probe(dev, ret, "failed to init controls\n");
@@ -1121,9 +1406,16 @@ probe_error_media_entity_cleanup:
probe_error_v4l2_ctrl_handler_free:
v4l2_ctrl_handler_free(ov2740->sd.ctrl_handler);
+probe_error_power_off:
+ if (full_power)
+ ov2740_suspend(dev);
+
return ret;
}
+static DEFINE_RUNTIME_DEV_PM_OPS(ov2740_pm_ops, ov2740_suspend, ov2740_resume,
+ NULL);
+
static const struct acpi_device_id ov2740_acpi_ids[] = {
{"INT3474"},
{}
@@ -1135,6 +1427,7 @@ static struct i2c_driver ov2740_i2c_driver = {
.driver = {
.name = "ov2740",
.acpi_match_table = ov2740_acpi_ids,
+ .pm = pm_sleep_ptr(&ov2740_pm_ops),
},
.probe = ov2740_probe,
.remove = ov2740_remove,
diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c
index 3bd972a822..4030916518 100644
--- a/drivers/media/i2c/ov4689.c
+++ b/drivers/media/i2c/ov4689.c
@@ -570,7 +570,7 @@ static int ov4689_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&ov4689->mutex);
- try_fmt = v4l2_subdev_get_try_format(sd, fh->state, 0);
+ try_fmt = v4l2_subdev_state_get_format(fh->state, 0);
/* Initialize try_fmt */
ov4689_fill_fmt(&supported_modes[OV4689_MODE_2688_1520], try_fmt);
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 40532f7bca..5162d45fe7 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -399,7 +399,7 @@ struct ov5640_mode_info {
const struct reg_value *reg_data;
u32 reg_data_size;
- /* Used by s_frame_interval only. */
+ /* Used by set_frame_interval only. */
u32 max_fps;
u32 def_fps;
};
@@ -2797,8 +2797,7 @@ static int ov5640_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&sensor->lock);
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt = v4l2_subdev_get_try_format(&sensor->sd, sd_state,
- format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
else
fmt = &sensor->fmt;
@@ -2971,7 +2970,7 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
goto out;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, 0) = *mbus_fmt;
+ *v4l2_subdev_state_get_format(sd_state, 0) = *mbus_fmt;
goto out;
}
@@ -3605,11 +3604,19 @@ static int ov5640_enum_frame_interval(
return 0;
}
-static int ov5640_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int ov5640_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct ov5640_dev *sensor = to_ov5640_dev(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&sensor->lock);
fi->interval = sensor->frame_interval;
mutex_unlock(&sensor->lock);
@@ -3617,13 +3624,21 @@ static int ov5640_g_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int ov5640_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct ov5640_dev *sensor = to_ov5640_dev(sd);
const struct ov5640_mode_info *mode;
int frame_rate, ret = 0;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (fi->pad != 0)
return -EINVAL;
@@ -3745,13 +3760,13 @@ out:
return ret;
}
-static int ov5640_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int ov5640_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct ov5640_dev *sensor = to_ov5640_dev(sd);
struct v4l2_mbus_framefmt *fmt =
- v4l2_subdev_get_try_format(sd, state, 0);
- struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, state, 0);
+ v4l2_subdev_state_get_format(state, 0);
+ struct v4l2_rect *crop = v4l2_subdev_state_get_crop(state, 0);
*fmt = ov5640_is_csi2(sensor) ? ov5640_csi2_default_fmt :
ov5640_dvp_default_fmt;
@@ -3771,17 +3786,16 @@ static const struct v4l2_subdev_core_ops ov5640_core_ops = {
};
static const struct v4l2_subdev_video_ops ov5640_video_ops = {
- .g_frame_interval = ov5640_g_frame_interval,
- .s_frame_interval = ov5640_s_frame_interval,
.s_stream = ov5640_s_stream,
};
static const struct v4l2_subdev_pad_ops ov5640_pad_ops = {
- .init_cfg = ov5640_init_cfg,
.enum_mbus_code = ov5640_enum_mbus_code,
.get_fmt = ov5640_get_fmt,
.set_fmt = ov5640_set_fmt,
.get_selection = ov5640_get_selection,
+ .get_frame_interval = ov5640_get_frame_interval,
+ .set_frame_interval = ov5640_set_frame_interval,
.enum_frame_size = ov5640_enum_frame_size,
.enum_frame_interval = ov5640_enum_frame_interval,
};
@@ -3792,6 +3806,10 @@ static const struct v4l2_subdev_ops ov5640_subdev_ops = {
.pad = &ov5640_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov5640_internal_ops = {
+ .init_state = ov5640_init_state,
+};
+
static int ov5640_get_regulators(struct ov5640_dev *sensor)
{
int i;
@@ -3906,6 +3924,7 @@ static int ov5640_probe(struct i2c_client *client)
return PTR_ERR(sensor->reset_gpio);
v4l2_i2c_subdev_init(&sensor->sd, client, &ov5640_subdev_ops);
+ sensor->sd.internal_ops = &ov5640_internal_ops;
sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
index a70db7e601..a26ac11c98 100644
--- a/drivers/media/i2c/ov5645.c
+++ b/drivers/media/i2c/ov5645.c
@@ -851,7 +851,7 @@ __ov5645_get_pad_format(struct ov5645 *ov5645,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&ov5645->sd, sd_state, pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov5645->fmt;
default:
@@ -878,7 +878,7 @@ __ov5645_get_pad_crop(struct ov5645 *ov5645,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&ov5645->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov5645->crop;
default:
@@ -934,8 +934,8 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
return 0;
}
-static int ov5645_entity_init_cfg(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *sd_state)
+static int ov5645_init_state(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_subdev_format fmt = { 0 };
@@ -1023,7 +1023,6 @@ static const struct v4l2_subdev_video_ops ov5645_video_ops = {
};
static const struct v4l2_subdev_pad_ops ov5645_subdev_pad_ops = {
- .init_cfg = ov5645_entity_init_cfg,
.enum_mbus_code = ov5645_enum_mbus_code,
.enum_frame_size = ov5645_enum_frame_size,
.get_fmt = ov5645_get_format,
@@ -1036,6 +1035,10 @@ static const struct v4l2_subdev_ops ov5645_subdev_ops = {
.pad = &ov5645_subdev_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov5645_internal_ops = {
+ .init_state = ov5645_init_state,
+};
+
static int ov5645_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -1162,6 +1165,7 @@ static int ov5645_probe(struct i2c_client *client)
}
v4l2_i2c_subdev_init(&ov5645->sd, client, &ov5645_subdev_ops);
+ ov5645->sd.internal_ops = &ov5645_internal_ops;
ov5645->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov5645->pad.flags = MEDIA_PAD_FL_SOURCE;
ov5645->sd.dev = &client->dev;
@@ -1220,7 +1224,7 @@ static int ov5645_probe(struct i2c_client *client)
pm_runtime_get_noresume(dev);
pm_runtime_enable(dev);
- ov5645_entity_init_cfg(&ov5645->sd, NULL);
+ ov5645_init_state(&ov5645->sd, NULL);
ret = v4l2_async_register_subdev(&ov5645->sd);
if (ret < 0) {
diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c
index dcfe3129c6..96c0fd4ff5 100644
--- a/drivers/media/i2c/ov5647.c
+++ b/drivers/media/i2c/ov5647.c
@@ -882,7 +882,7 @@ __ov5647_get_pad_crop(struct ov5647 *ov5647,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&ov5647->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov5647->mode->crop;
}
@@ -975,8 +975,8 @@ static int ov5647_get_pad_fmt(struct v4l2_subdev *sd,
mutex_lock(&sensor->lock);
switch (format->which) {
case V4L2_SUBDEV_FORMAT_TRY:
- sensor_format = v4l2_subdev_get_try_format(sd, sd_state,
- format->pad);
+ sensor_format = v4l2_subdev_state_get_format(sd_state,
+ format->pad);
break;
default:
sensor_format = &sensor->mode->format;
@@ -1004,7 +1004,7 @@ static int ov5647_set_pad_fmt(struct v4l2_subdev *sd,
/* Update the sensor mode and apply at it at streamon time. */
mutex_lock(&sensor->lock);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, format->pad) = mode->format;
+ *v4l2_subdev_state_get_format(sd_state, format->pad) = mode->format;
} else {
int exposure_max, exposure_def;
int hblank, vblank;
@@ -1121,8 +1121,8 @@ static int ov5647_detect(struct v4l2_subdev *sd)
static int ov5647_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *format =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
- struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
+ struct v4l2_rect *crop = v4l2_subdev_state_get_crop(fh->state, 0);
crop->left = OV5647_PIXEL_ARRAY_LEFT;
crop->top = OV5647_PIXEL_ARRAY_TOP;
diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c
index aa10eb4e39..4b86d2631b 100644
--- a/drivers/media/i2c/ov5648.c
+++ b/drivers/media/i2c/ov5648.c
@@ -2158,37 +2158,8 @@ static int ov5648_s_stream(struct v4l2_subdev *subdev, int enable)
return 0;
}
-static int ov5648_g_frame_interval(struct v4l2_subdev *subdev,
- struct v4l2_subdev_frame_interval *interval)
-{
- struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev);
- const struct ov5648_mode *mode;
- int ret = 0;
-
- mutex_lock(&sensor->mutex);
-
- mode = sensor->state.mode;
-
- switch (sensor->state.mbus_code) {
- case MEDIA_BUS_FMT_SBGGR8_1X8:
- interval->interval = mode->frame_interval[0];
- break;
- case MEDIA_BUS_FMT_SBGGR10_1X10:
- interval->interval = mode->frame_interval[1];
- break;
- default:
- ret = -EINVAL;
- }
-
- mutex_unlock(&sensor->mutex);
-
- return ret;
-}
-
static const struct v4l2_subdev_video_ops ov5648_subdev_video_ops = {
.s_stream = ov5648_s_stream,
- .g_frame_interval = ov5648_g_frame_interval,
- .s_frame_interval = ov5648_g_frame_interval,
};
/* Subdev Pad Operations */
@@ -2232,8 +2203,8 @@ static int ov5648_get_fmt(struct v4l2_subdev *subdev,
mutex_lock(&sensor->mutex);
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *mbus_format = *v4l2_subdev_get_try_format(subdev, sd_state,
- format->pad);
+ *mbus_format = *v4l2_subdev_state_get_format(sd_state,
+ format->pad);
else
ov5648_mbus_format_fill(mbus_format, sensor->state.mbus_code,
sensor->state.mode);
@@ -2285,7 +2256,7 @@ static int ov5648_set_fmt(struct v4l2_subdev *subdev,
ov5648_mbus_format_fill(mbus_format, mbus_code, mode);
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *v4l2_subdev_get_try_format(subdev, sd_state, format->pad) =
+ *v4l2_subdev_state_get_format(sd_state, format->pad) =
*mbus_format;
else if (sensor->state.mode != mode ||
sensor->state.mbus_code != mbus_code)
@@ -2297,6 +2268,41 @@ complete:
return ret;
}
+static int ov5648_get_frame_interval(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *interval)
+{
+ struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev);
+ const struct ov5648_mode *mode;
+ int ret = 0;
+
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ mutex_lock(&sensor->mutex);
+
+ mode = sensor->state.mode;
+
+ switch (sensor->state.mbus_code) {
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ interval->interval = mode->frame_interval[0];
+ break;
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ interval->interval = mode->frame_interval[1];
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ mutex_unlock(&sensor->mutex);
+
+ return ret;
+}
+
static int ov5648_enum_frame_size(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *size_enum)
@@ -2363,6 +2369,8 @@ static const struct v4l2_subdev_pad_ops ov5648_subdev_pad_ops = {
.enum_mbus_code = ov5648_enum_mbus_code,
.get_fmt = ov5648_get_fmt,
.set_fmt = ov5648_set_fmt,
+ .get_frame_interval = ov5648_get_frame_interval,
+ .set_frame_interval = ov5648_get_frame_interval,
.enum_frame_size = ov5648_enum_frame_size,
.enum_frame_interval = ov5648_enum_frame_interval,
};
diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c
index e80db3ecd4..2aee85965c 100644
--- a/drivers/media/i2c/ov5670.c
+++ b/drivers/media/i2c/ov5670.c
@@ -2196,13 +2196,13 @@ error:
return ret;
}
-static int ov5670_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int ov5670_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_mbus_framefmt *fmt =
- v4l2_subdev_get_try_format(sd, state, 0);
+ v4l2_subdev_state_get_format(state, 0);
const struct ov5670_mode *default_mode = &supported_modes[0];
- struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, state, 0);
+ struct v4l2_rect *crop = v4l2_subdev_state_get_crop(state, 0);
fmt->width = default_mode->width;
fmt->height = default_mode->height;
@@ -2263,9 +2263,8 @@ static int ov5670_do_get_pad_format(struct ov5670 *ov5670,
struct v4l2_subdev_format *fmt)
{
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&ov5670->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
ov5670_update_pad_format(ov5670->cur_mode, fmt);
@@ -2310,7 +2309,7 @@ static int ov5670_set_pad_format(struct v4l2_subdev *sd,
fmt->format.width, fmt->format.height);
ov5670_update_pad_format(mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
} else {
ov5670->cur_mode = mode;
__v4l2_ctrl_s_ctrl(ov5670->link_freq, mode->link_freq_index);
@@ -2550,7 +2549,7 @@ __ov5670_get_pad_crop(struct ov5670 *sensor, struct v4l2_subdev_state *state,
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&sensor->sd, state, pad);
+ return v4l2_subdev_state_get_crop(state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return mode->analog_crop;
}
@@ -2593,7 +2592,6 @@ static const struct v4l2_subdev_video_ops ov5670_video_ops = {
};
static const struct v4l2_subdev_pad_ops ov5670_pad_ops = {
- .init_cfg = ov5670_init_cfg,
.enum_mbus_code = ov5670_enum_mbus_code,
.get_fmt = ov5670_get_pad_format,
.set_fmt = ov5670_set_pad_format,
@@ -2613,6 +2611,10 @@ static const struct v4l2_subdev_ops ov5670_subdev_ops = {
.sensor = &ov5670_sensor_ops,
};
+static const struct v4l2_subdev_internal_ops ov5670_internal_ops = {
+ .init_state = ov5670_init_state,
+};
+
static const struct media_entity_operations ov5670_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -2676,6 +2678,7 @@ static int ov5670_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&ov5670->sd, client, &ov5670_subdev_ops);
+ ov5670->sd.internal_ops = &ov5670_internal_ops;
ret = ov5670_regulators_probe(ov5670);
if (ret)
diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c
index e63d9d402d..3641911bc7 100644
--- a/drivers/media/i2c/ov5675.c
+++ b/drivers/media/i2c/ov5675.c
@@ -1036,7 +1036,7 @@ static int ov5675_set_format(struct v4l2_subdev *sd,
mutex_lock(&ov5675->mutex);
ov5675_update_pad_format(mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
} else {
ov5675->cur_mode = mode;
__v4l2_ctrl_s_ctrl(ov5675->link_freq, mode->link_freq_index);
@@ -1069,9 +1069,8 @@ static int ov5675_get_format(struct v4l2_subdev *sd,
mutex_lock(&ov5675->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&ov5675->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
ov5675_update_pad_format(ov5675->cur_mode, &fmt->format);
@@ -1141,7 +1140,7 @@ static int ov5675_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&ov5675->mutex);
ov5675_update_pad_format(&supported_modes[0],
- v4l2_subdev_get_try_format(sd, fh->state, 0));
+ v4l2_subdev_state_get_format(fh->state, 0));
mutex_unlock(&ov5675->mutex);
return 0;
diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
index 819425e213..8deb28b559 100644
--- a/drivers/media/i2c/ov5693.c
+++ b/drivers/media/i2c/ov5693.c
@@ -775,7 +775,7 @@ __ov5693_get_pad_format(struct ov5693_device *ov5693,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&ov5693->sd, state, pad);
+ return v4l2_subdev_state_get_format(state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov5693->mode.format;
default:
@@ -790,7 +790,7 @@ __ov5693_get_pad_crop(struct ov5693_device *ov5693,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&ov5693->sd, state, pad);
+ return v4l2_subdev_state_get_crop(state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov5693->mode.crop;
}
@@ -1004,14 +1004,22 @@ err_power_down:
return ret;
}
-static int ov5693_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *interval)
+static int ov5693_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *interval)
{
struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
unsigned int framesize = OV5693_FIXED_PPL * (ov5693->mode.format.height +
ov5693->ctrls.vblank->val);
unsigned int fps = DIV_ROUND_CLOSEST(OV5693_PIXEL_RATE, framesize);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
interval->interval.numerator = 1;
interval->interval.denominator = fps;
@@ -1054,7 +1062,6 @@ static int ov5693_enum_frame_size(struct v4l2_subdev *sd,
static const struct v4l2_subdev_video_ops ov5693_video_ops = {
.s_stream = ov5693_s_stream,
- .g_frame_interval = ov5693_g_frame_interval,
};
static const struct v4l2_subdev_pad_ops ov5693_pad_ops = {
@@ -1064,6 +1071,7 @@ static const struct v4l2_subdev_pad_ops ov5693_pad_ops = {
.set_fmt = ov5693_set_fmt,
.get_selection = ov5693_get_selection,
.set_selection = ov5693_set_selection,
+ .get_frame_interval = ov5693_get_frame_interval,
};
static const struct v4l2_subdev_ops ov5693_ops = {
diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c
index c8f57ce157..663eccdfea 100644
--- a/drivers/media/i2c/ov5695.c
+++ b/drivers/media/i2c/ov5695.c
@@ -820,7 +820,7 @@ static int ov5695_set_fmt(struct v4l2_subdev *sd,
fmt->format.height = mode->height;
fmt->format.field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
} else {
ov5695->cur_mode = mode;
h_blank = mode->hts_def - mode->width;
@@ -846,8 +846,8 @@ static int ov5695_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&ov5695->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- fmt->format = *v4l2_subdev_get_try_format(sd, sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
} else {
fmt->format.width = mode->width;
fmt->format.height = mode->height;
@@ -1039,7 +1039,7 @@ static int ov5695_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct ov5695 *ov5695 = to_ov5695(sd);
struct v4l2_mbus_framefmt *try_fmt =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
const struct ov5695_mode *def_mode = &supported_modes[0];
mutex_lock(&ov5695->mutex);
diff --git a/drivers/media/i2c/ov64a40.c b/drivers/media/i2c/ov64a40.c
new file mode 100644
index 0000000000..4fba4c2cb0
--- /dev/null
+++ b/drivers/media/i2c/ov64a40.c
@@ -0,0 +1,3690 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * V4L2 sensor driver for OmniVision OV64A40
+ *
+ * Copyright (C) 2023 Ideas On Board Oy
+ * Copyright (C) 2023 Arducam
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/v4l2-cci.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-subdev.h>
+
+#define OV64A40_XCLK_FREQ 24000000
+
+#define OV64A40_NATIVE_WIDTH 9286
+#define OV64A40_NATIVE_HEIGHT 6976
+#define OV64A40_PIXEL_ARRAY_TOP 0
+#define OV64A40_PIXEL_ARRAY_LEFT 0
+#define OV64A40_PIXEL_ARRAY_WIDTH 9248
+#define OV64A40_PIXEL_ARRAY_HEIGHT 6944
+
+#define OV64A40_PIXEL_RATE 300000000
+
+#define OV64A40_LINK_FREQ_360M 360000000
+#define OV64A40_LINK_FREQ_456M 456000000
+
+#define OV64A40_PLL1_PRE_DIV0 CCI_REG8(0x0301)
+#define OV64A40_PLL1_PRE_DIV CCI_REG8(0x0303)
+#define OV64A40_PLL1_MULTIPLIER CCI_REG16(0x0304)
+#define OV64A40_PLL1_M_DIV CCI_REG8(0x0307)
+#define OV64A40_PLL2_SEL_BAK_SA1 CCI_REG8(0x0320)
+#define OV64A40_PLL2_PRE_DIV CCI_REG8(0x0323)
+#define OV64A40_PLL2_MULTIPLIER CCI_REG16(0x0324)
+#define OV64A40_PLL2_PRE_DIV0 CCI_REG8(0x0326)
+#define OV64A40_PLL2_DIVDAC CCI_REG8(0x0329)
+#define OV64A40_PLL2_DIVSP CCI_REG8(0x032d)
+#define OV64A40_PLL2_DACPREDIV CCI_REG8(0x032e)
+
+/* TODO: validate vblank_min, it's not characterized in the datasheet. */
+#define OV64A40_VBLANK_MIN 128
+#define OV64A40_VTS_MAX 0xffffff
+
+#define OV64A40_REG_MEC_LONG_EXPO CCI_REG24(0x3500)
+#define OV64A40_EXPOSURE_MIN 16
+#define OV64A40_EXPOSURE_MARGIN 32
+
+#define OV64A40_REG_MEC_LONG_GAIN CCI_REG16(0x3508)
+#define OV64A40_ANA_GAIN_MIN 0x80
+#define OV64A40_ANA_GAIN_MAX 0x7ff
+#define OV64A40_ANA_GAIN_DEFAULT 0x80
+
+#define OV64A40_REG_TIMING_CTRL0 CCI_REG16(0x3800)
+#define OV64A40_REG_TIMING_CTRL2 CCI_REG16(0x3802)
+#define OV64A40_REG_TIMING_CTRL4 CCI_REG16(0x3804)
+#define OV64A40_REG_TIMING_CTRL6 CCI_REG16(0x3806)
+#define OV64A40_REG_TIMING_CTRL8 CCI_REG16(0x3808)
+#define OV64A40_REG_TIMING_CTRLA CCI_REG16(0x380a)
+#define OV64A40_REG_TIMING_CTRLC CCI_REG16(0x380c)
+#define OV64A40_REG_TIMING_CTRLE CCI_REG16(0x380e)
+#define OV64A40_REG_TIMING_CTRL10 CCI_REG16(0x3810)
+#define OV64A40_REG_TIMING_CTRL12 CCI_REG16(0x3812)
+
+/*
+ * Careful: a typo in the datasheet calls this register
+ * OV64A40_REG_TIMING_CTRL20.
+ */
+#define OV64A40_REG_TIMING_CTRL14 CCI_REG8(0x3814)
+#define OV64A40_REG_TIMING_CTRL15 CCI_REG8(0x3815)
+#define OV64A40_ODD_INC_SHIFT 4
+#define OV64A40_SKIPPING_CONFIG(_odd, _even) \
+ (((_odd) << OV64A40_ODD_INC_SHIFT) | (_even))
+
+#define OV64A40_REG_TIMING_CTRL_20 CCI_REG8(0x3820)
+#define OV64A40_TIMING_CTRL_20_VFLIP BIT(2)
+#define OV64A40_TIMING_CTRL_20_VBIN BIT(1)
+
+#define OV64A40_REG_TIMING_CTRL_21 CCI_REG8(0x3821)
+#define OV64A40_TIMING_CTRL_21_HBIN BIT(4)
+#define OV64A40_TIMING_CTRL_21_HFLIP BIT(2)
+#define OV64A40_TIMING_CTRL_21_DSPEED BIT(0)
+#define OV64A40_TIMING_CTRL_21_HBIN_CONF \
+ (OV64A40_TIMING_CTRL_21_HBIN | \
+ OV64A40_TIMING_CTRL_21_DSPEED)
+
+#define OV64A40_REG_TIMINGS_VTS_HIGH CCI_REG8(0x3840)
+#define OV64A40_REG_TIMINGS_VTS_MID CCI_REG8(0x380e)
+#define OV64A40_REG_TIMINGS_VTS_LOW CCI_REG8(0x380f)
+
+/* The test pattern control is weirdly named PRE_ISP_2325_D2V2_TOP_1 in TRM. */
+#define OV64A40_REG_TEST_PATTERN CCI_REG8(0x50c1)
+#define OV64A40_TEST_PATTERN_DISABLED 0x00
+#define OV64A40_TEST_PATTERN_TYPE1 BIT(0)
+#define OV64A40_TEST_PATTERN_TYPE2 (BIT(4) | BIT(0))
+#define OV64A40_TEST_PATTERN_TYPE3 (BIT(5) | BIT(0))
+#define OV64A40_TEST_PATTERN_TYPE4 (BIT(5) | BIT(4) | BIT(0))
+
+#define OV64A40_REG_CHIP_ID CCI_REG24(0x300a)
+#define OV64A40_CHIP_ID 0x566441
+
+#define OV64A40_REG_SMIA CCI_REG8(0x0100)
+#define OV64A40_REG_SMIA_STREAMING BIT(0)
+
+enum ov64a40_link_freq_ids {
+ OV64A40_LINK_FREQ_456M_ID,
+ OV64A40_LINK_FREQ_360M_ID,
+ OV64A40_NUM_LINK_FREQ,
+};
+
+static const char * const ov64a40_supply_names[] = {
+ /* Supplies can be enabled in any order */
+ "avdd", /* Analog (2.8V) supply */
+ "dovdd", /* Digital Core (1.8V) supply */
+ "dvdd", /* IF (1.1V) supply */
+};
+
+static const char * const ov64a40_test_pattern_menu[] = {
+ "Disabled",
+ "Type1",
+ "Type2",
+ "Type3",
+ "Type4",
+};
+
+static const int ov64a40_test_pattern_val[] = {
+ OV64A40_TEST_PATTERN_DISABLED,
+ OV64A40_TEST_PATTERN_TYPE1,
+ OV64A40_TEST_PATTERN_TYPE2,
+ OV64A40_TEST_PATTERN_TYPE3,
+ OV64A40_TEST_PATTERN_TYPE4,
+};
+
+static const unsigned int ov64a40_mbus_codes[] = {
+ MEDIA_BUS_FMT_SBGGR10_1X10,
+ MEDIA_BUS_FMT_SGRBG10_1X10,
+ MEDIA_BUS_FMT_SGBRG10_1X10,
+ MEDIA_BUS_FMT_SRGGB10_1X10,
+};
+
+static const struct cci_reg_sequence ov64a40_init[] = {
+ { CCI_REG8(0x0103), 0x01 }, { CCI_REG8(0x0301), 0x88 },
+ { CCI_REG8(0x0304), 0x00 }, { CCI_REG8(0x0305), 0x96 },
+ { CCI_REG8(0x0306), 0x03 }, { CCI_REG8(0x0307), 0x00 },
+ { CCI_REG8(0x0345), 0x2c }, { CCI_REG8(0x034a), 0x02 },
+ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x0350), 0xc0 },
+ { CCI_REG8(0x0360), 0x09 }, { CCI_REG8(0x3012), 0x31 },
+ { CCI_REG8(0x3015), 0xf0 }, { CCI_REG8(0x3017), 0xf0 },
+ { CCI_REG8(0x301d), 0xf6 }, { CCI_REG8(0x301e), 0xf1 },
+ { CCI_REG8(0x3022), 0xf0 }, { CCI_REG8(0x3400), 0x08 },
+ { CCI_REG8(0x3608), 0x41 }, { CCI_REG8(0x3421), 0x02 },
+ { CCI_REG8(0x3500), 0x00 }, { CCI_REG8(0x3501), 0x00 },
+ { CCI_REG8(0x3502), 0x18 }, { CCI_REG8(0x3504), 0x0c },
+ { CCI_REG8(0x3508), 0x01 }, { CCI_REG8(0x3509), 0x00 },
+ { CCI_REG8(0x350a), 0x01 }, { CCI_REG8(0x350b), 0x00 },
+ { CCI_REG8(0x350b), 0x00 }, { CCI_REG8(0x3540), 0x00 },
+ { CCI_REG8(0x3541), 0x00 }, { CCI_REG8(0x3542), 0x08 },
+ { CCI_REG8(0x3548), 0x01 }, { CCI_REG8(0x3549), 0xa0 },
+ { CCI_REG8(0x3549), 0x00 }, { CCI_REG8(0x3549), 0x00 },
+ { CCI_REG8(0x3549), 0x00 }, { CCI_REG8(0x3580), 0x00 },
+ { CCI_REG8(0x3581), 0x00 }, { CCI_REG8(0x3582), 0x04 },
+ { CCI_REG8(0x3588), 0x01 }, { CCI_REG8(0x3589), 0xf0 },
+ { CCI_REG8(0x3589), 0x00 }, { CCI_REG8(0x3589), 0x00 },
+ { CCI_REG8(0x3589), 0x00 }, { CCI_REG8(0x360d), 0x83 },
+ { CCI_REG8(0x3616), 0xa0 }, { CCI_REG8(0x3617), 0x31 },
+ { CCI_REG8(0x3623), 0x10 }, { CCI_REG8(0x3633), 0x03 },
+ { CCI_REG8(0x3634), 0x03 }, { CCI_REG8(0x3635), 0x77 },
+ { CCI_REG8(0x3640), 0x19 }, { CCI_REG8(0x3641), 0x80 },
+ { CCI_REG8(0x364d), 0x0f }, { CCI_REG8(0x3680), 0x80 },
+ { CCI_REG8(0x3682), 0x00 }, { CCI_REG8(0x3683), 0x00 },
+ { CCI_REG8(0x3684), 0x07 }, { CCI_REG8(0x3688), 0x01 },
+ { CCI_REG8(0x3689), 0x08 }, { CCI_REG8(0x368a), 0x26 },
+ { CCI_REG8(0x368b), 0xc8 }, { CCI_REG8(0x368e), 0x70 },
+ { CCI_REG8(0x368f), 0x00 }, { CCI_REG8(0x3692), 0x04 },
+ { CCI_REG8(0x3693), 0x00 }, { CCI_REG8(0x3696), 0xd1 },
+ { CCI_REG8(0x3697), 0xe0 }, { CCI_REG8(0x3698), 0x80 },
+ { CCI_REG8(0x3699), 0x2b }, { CCI_REG8(0x369a), 0x00 },
+ { CCI_REG8(0x369d), 0x00 }, { CCI_REG8(0x369e), 0x14 },
+ { CCI_REG8(0x369f), 0x20 }, { CCI_REG8(0x36a5), 0x80 },
+ { CCI_REG8(0x36a6), 0x00 }, { CCI_REG8(0x36a7), 0x00 },
+ { CCI_REG8(0x36a8), 0x00 }, { CCI_REG8(0x36b5), 0x17 },
+ { CCI_REG8(0x3701), 0x30 }, { CCI_REG8(0x3706), 0x2b },
+ { CCI_REG8(0x3709), 0x8d }, { CCI_REG8(0x370b), 0x4f },
+ { CCI_REG8(0x3711), 0x00 }, { CCI_REG8(0x3712), 0x01 },
+ { CCI_REG8(0x3713), 0x00 }, { CCI_REG8(0x3720), 0x08 },
+ { CCI_REG8(0x3727), 0x22 }, { CCI_REG8(0x3728), 0x01 },
+ { CCI_REG8(0x375e), 0x00 }, { CCI_REG8(0x3760), 0x08 },
+ { CCI_REG8(0x3761), 0x10 }, { CCI_REG8(0x3762), 0x08 },
+ { CCI_REG8(0x3765), 0x10 }, { CCI_REG8(0x3766), 0x18 },
+ { CCI_REG8(0x376a), 0x08 }, { CCI_REG8(0x376b), 0x00 },
+ { CCI_REG8(0x376d), 0x1b }, { CCI_REG8(0x3791), 0x2b },
+ { CCI_REG8(0x3793), 0x2b }, { CCI_REG8(0x3795), 0x2b },
+ { CCI_REG8(0x3797), 0x4f }, { CCI_REG8(0x3799), 0x4f },
+ { CCI_REG8(0x379b), 0x4f }, { CCI_REG8(0x37a0), 0x22 },
+ { CCI_REG8(0x37da), 0x04 }, { CCI_REG8(0x37f9), 0x02 },
+ { CCI_REG8(0x37fa), 0x02 }, { CCI_REG8(0x37fb), 0x02 },
+ { CCI_REG8(0x3814), 0x11 }, { CCI_REG8(0x3815), 0x11 },
+ { CCI_REG8(0x3820), 0x40 }, { CCI_REG8(0x3821), 0x04 },
+ { CCI_REG8(0x3822), 0x00 }, { CCI_REG8(0x3823), 0x04 },
+ { CCI_REG8(0x3827), 0x08 }, { CCI_REG8(0x3828), 0x00 },
+ { CCI_REG8(0x382a), 0x81 }, { CCI_REG8(0x382e), 0x70 },
+ { CCI_REG8(0x3837), 0x10 }, { CCI_REG8(0x3839), 0x00 },
+ { CCI_REG8(0x383b), 0x00 }, { CCI_REG8(0x383c), 0x00 },
+ { CCI_REG8(0x383d), 0x10 }, { CCI_REG8(0x383f), 0x00 },
+ { CCI_REG8(0x384c), 0x02 }, { CCI_REG8(0x384d), 0x8c },
+ { CCI_REG8(0x3852), 0x00 }, { CCI_REG8(0x3856), 0x10 },
+ { CCI_REG8(0x3857), 0x10 }, { CCI_REG8(0x3858), 0x20 },
+ { CCI_REG8(0x3859), 0x20 }, { CCI_REG8(0x3894), 0x00 },
+ { CCI_REG8(0x3895), 0x00 }, { CCI_REG8(0x3896), 0x00 },
+ { CCI_REG8(0x3897), 0x00 }, { CCI_REG8(0x3900), 0x40 },
+ { CCI_REG8(0x3aed), 0x6e }, { CCI_REG8(0x3af1), 0x73 },
+ { CCI_REG8(0x3d86), 0x12 }, { CCI_REG8(0x3d87), 0x30 },
+ { CCI_REG8(0x3d8c), 0xab }, { CCI_REG8(0x3d8d), 0xb0 },
+ { CCI_REG8(0x3f00), 0x12 }, { CCI_REG8(0x3f00), 0x12 },
+ { CCI_REG8(0x3f00), 0x12 }, { CCI_REG8(0x3f01), 0x03 },
+ { CCI_REG8(0x4009), 0x01 }, { CCI_REG8(0x400e), 0xc6 },
+ { CCI_REG8(0x400f), 0x00 }, { CCI_REG8(0x4010), 0x28 },
+ { CCI_REG8(0x4011), 0x01 }, { CCI_REG8(0x4012), 0x0c },
+ { CCI_REG8(0x4015), 0x00 }, { CCI_REG8(0x4016), 0x1f },
+ { CCI_REG8(0x4017), 0x00 }, { CCI_REG8(0x4018), 0x07 },
+ { CCI_REG8(0x401a), 0x40 }, { CCI_REG8(0x4028), 0x01 },
+ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4506), 0x01 },
+ { CCI_REG8(0x4508), 0x00 }, { CCI_REG8(0x4509), 0x35 },
+ { CCI_REG8(0x450a), 0x08 }, { CCI_REG8(0x450c), 0x00 },
+ { CCI_REG8(0x450d), 0x20 }, { CCI_REG8(0x450e), 0x00 },
+ { CCI_REG8(0x450f), 0x20 }, { CCI_REG8(0x451e), 0x00 },
+ { CCI_REG8(0x451f), 0x00 }, { CCI_REG8(0x4523), 0x00 },
+ { CCI_REG8(0x4526), 0x00 }, { CCI_REG8(0x4527), 0x18 },
+ { CCI_REG8(0x4580), 0x01 }, { CCI_REG8(0x4583), 0x00 },
+ { CCI_REG8(0x4584), 0x00 }, { CCI_REG8(0x45c0), 0xa1 },
+ { CCI_REG8(0x4602), 0x08 }, { CCI_REG8(0x4603), 0x05 },
+ { CCI_REG8(0x4606), 0x12 }, { CCI_REG8(0x4607), 0x30 },
+ { CCI_REG8(0x460b), 0x00 }, { CCI_REG8(0x460d), 0x00 },
+ { CCI_REG8(0x4640), 0x00 }, { CCI_REG8(0x4641), 0x24 },
+ { CCI_REG8(0x4643), 0x08 }, { CCI_REG8(0x4645), 0x14 },
+ { CCI_REG8(0x4648), 0x0a }, { CCI_REG8(0x4649), 0x06 },
+ { CCI_REG8(0x464a), 0x00 }, { CCI_REG8(0x464b), 0x30 },
+ { CCI_REG8(0x4800), 0x04 }, { CCI_REG8(0x4802), 0x02 },
+ { CCI_REG8(0x480b), 0x10 }, { CCI_REG8(0x480c), 0x80 },
+ { CCI_REG8(0x480e), 0x04 }, { CCI_REG8(0x480f), 0x32 },
+ { CCI_REG8(0x481b), 0x12 }, { CCI_REG8(0x4833), 0x30 },
+ { CCI_REG8(0x4837), 0x08 }, { CCI_REG8(0x484b), 0x27 },
+ { CCI_REG8(0x4850), 0x42 }, { CCI_REG8(0x4851), 0xaa },
+ { CCI_REG8(0x4860), 0x01 }, { CCI_REG8(0x4861), 0xec },
+ { CCI_REG8(0x4862), 0x25 }, { CCI_REG8(0x4888), 0x00 },
+ { CCI_REG8(0x4889), 0x03 }, { CCI_REG8(0x488c), 0x60 },
+ { CCI_REG8(0x4910), 0x28 }, { CCI_REG8(0x4911), 0x01 },
+ { CCI_REG8(0x4912), 0x0c }, { CCI_REG8(0x491a), 0x40 },
+ { CCI_REG8(0x4915), 0x00 }, { CCI_REG8(0x4916), 0x0f },
+ { CCI_REG8(0x4917), 0x00 }, { CCI_REG8(0x4918), 0x07 },
+ { CCI_REG8(0x4a10), 0x28 }, { CCI_REG8(0x4a11), 0x01 },
+ { CCI_REG8(0x4a12), 0x0c }, { CCI_REG8(0x4a1a), 0x40 },
+ { CCI_REG8(0x4a15), 0x00 }, { CCI_REG8(0x4a16), 0x0f },
+ { CCI_REG8(0x4a17), 0x00 }, { CCI_REG8(0x4a18), 0x07 },
+ { CCI_REG8(0x4d00), 0x04 }, { CCI_REG8(0x4d01), 0x5a },
+ { CCI_REG8(0x4d02), 0xbb }, { CCI_REG8(0x4d03), 0x84 },
+ { CCI_REG8(0x4d04), 0xd1 }, { CCI_REG8(0x4d05), 0x68 },
+ { CCI_REG8(0xc4fa), 0x10 }, { CCI_REG8(0x3b56), 0x0a },
+ { CCI_REG8(0x3b57), 0x0a }, { CCI_REG8(0x3b58), 0x0c },
+ { CCI_REG8(0x3b59), 0x10 }, { CCI_REG8(0x3a1d), 0x30 },
+ { CCI_REG8(0x3a1e), 0x30 }, { CCI_REG8(0x3a21), 0x30 },
+ { CCI_REG8(0x3a22), 0x30 }, { CCI_REG8(0x3992), 0x02 },
+ { CCI_REG8(0x399e), 0x02 }, { CCI_REG8(0x39fb), 0x30 },
+ { CCI_REG8(0x39fc), 0x30 }, { CCI_REG8(0x39fd), 0x30 },
+ { CCI_REG8(0x39fe), 0x30 }, { CCI_REG8(0x3a6d), 0x83 },
+ { CCI_REG8(0x3a5e), 0x83 }, { CCI_REG8(0xc500), 0x12 },
+ { CCI_REG8(0xc501), 0x12 }, { CCI_REG8(0xc502), 0x12 },
+ { CCI_REG8(0xc503), 0x12 }, { CCI_REG8(0xc505), 0x12 },
+ { CCI_REG8(0xc506), 0x12 }, { CCI_REG8(0xc507), 0x12 },
+ { CCI_REG8(0xc508), 0x12 }, { CCI_REG8(0x3a77), 0x12 },
+ { CCI_REG8(0x3a73), 0x12 }, { CCI_REG8(0x3a7b), 0x12 },
+ { CCI_REG8(0x3a7f), 0x12 }, { CCI_REG8(0x3b2e), 0x13 },
+ { CCI_REG8(0x3b29), 0x13 }, { CCI_REG8(0xc439), 0x13 },
+ { CCI_REG8(0xc469), 0x13 }, { CCI_REG8(0xc41c), 0x89 },
+ { CCI_REG8(0x3618), 0x80 }, { CCI_REG8(0xc514), 0x51 },
+ { CCI_REG8(0xc515), 0x2c }, { CCI_REG8(0xc516), 0x16 },
+ { CCI_REG8(0xc517), 0x0d }, { CCI_REG8(0x3615), 0x7f },
+ { CCI_REG8(0x3632), 0x99 }, { CCI_REG8(0x3642), 0x00 },
+ { CCI_REG8(0x3645), 0x80 }, { CCI_REG8(0x3702), 0x2a },
+ { CCI_REG8(0x3703), 0x2a }, { CCI_REG8(0x3708), 0x2f },
+ { CCI_REG8(0x3721), 0x15 }, { CCI_REG8(0x3744), 0x28 },
+ { CCI_REG8(0x3991), 0x0c }, { CCI_REG8(0x371d), 0x24 },
+ { CCI_REG8(0x371f), 0x0c }, { CCI_REG8(0x374b), 0x03 },
+ { CCI_REG8(0x37d0), 0x00 }, { CCI_REG8(0x391d), 0x55 },
+ { CCI_REG8(0x391e), 0x52 }, { CCI_REG8(0x399d), 0x0c },
+ { CCI_REG8(0x3a2f), 0x01 }, { CCI_REG8(0x3a30), 0x01 },
+ { CCI_REG8(0x3a31), 0x01 }, { CCI_REG8(0x3a32), 0x01 },
+ { CCI_REG8(0x3a34), 0x01 }, { CCI_REG8(0x3a35), 0x01 },
+ { CCI_REG8(0x3a36), 0x01 }, { CCI_REG8(0x3a37), 0x01 },
+ { CCI_REG8(0x3a43), 0x01 }, { CCI_REG8(0x3a44), 0x01 },
+ { CCI_REG8(0x3a45), 0x01 }, { CCI_REG8(0x3a46), 0x01 },
+ { CCI_REG8(0x3a48), 0x01 }, { CCI_REG8(0x3a49), 0x01 },
+ { CCI_REG8(0x3a4a), 0x01 }, { CCI_REG8(0x3a4b), 0x01 },
+ { CCI_REG8(0x3a50), 0x14 }, { CCI_REG8(0x3a54), 0x14 },
+ { CCI_REG8(0x3a60), 0x20 }, { CCI_REG8(0x3a6f), 0x20 },
+ { CCI_REG8(0x3ac5), 0x01 }, { CCI_REG8(0x3ac6), 0x01 },
+ { CCI_REG8(0x3ac7), 0x01 }, { CCI_REG8(0x3ac8), 0x01 },
+ { CCI_REG8(0x3ac9), 0x01 }, { CCI_REG8(0x3aca), 0x01 },
+ { CCI_REG8(0x3acb), 0x01 }, { CCI_REG8(0x3acc), 0x01 },
+ { CCI_REG8(0x3acd), 0x01 }, { CCI_REG8(0x3ace), 0x01 },
+ { CCI_REG8(0x3acf), 0x01 }, { CCI_REG8(0x3ad0), 0x01 },
+ { CCI_REG8(0x3ad1), 0x01 }, { CCI_REG8(0x3ad2), 0x01 },
+ { CCI_REG8(0x3ad3), 0x01 }, { CCI_REG8(0x3ad4), 0x01 },
+ { CCI_REG8(0x3add), 0x1f }, { CCI_REG8(0x3adf), 0x24 },
+ { CCI_REG8(0x3aef), 0x1f }, { CCI_REG8(0x3af0), 0x24 },
+ { CCI_REG8(0x3b92), 0x08 }, { CCI_REG8(0x3b93), 0x08 },
+ { CCI_REG8(0x3b94), 0x08 }, { CCI_REG8(0x3b95), 0x08 },
+ { CCI_REG8(0x3be7), 0x1e }, { CCI_REG8(0x3be8), 0x26 },
+ { CCI_REG8(0xc44a), 0x20 }, { CCI_REG8(0xc44c), 0x20 },
+ { CCI_REG8(0xc483), 0x00 }, { CCI_REG8(0xc484), 0x00 },
+ { CCI_REG8(0xc485), 0x00 }, { CCI_REG8(0xc486), 0x00 },
+ { CCI_REG8(0xc487), 0x01 }, { CCI_REG8(0xc488), 0x01 },
+ { CCI_REG8(0xc489), 0x01 }, { CCI_REG8(0xc48a), 0x01 },
+ { CCI_REG8(0xc4c1), 0x00 }, { CCI_REG8(0xc4c2), 0x00 },
+ { CCI_REG8(0xc4c3), 0x00 }, { CCI_REG8(0xc4c4), 0x00 },
+ { CCI_REG8(0xc4c6), 0x10 }, { CCI_REG8(0xc4c7), 0x10 },
+ { CCI_REG8(0xc4c8), 0x10 }, { CCI_REG8(0xc4c9), 0x10 },
+ { CCI_REG8(0xc4ca), 0x10 }, { CCI_REG8(0xc4cb), 0x10 },
+ { CCI_REG8(0xc4cc), 0x10 }, { CCI_REG8(0xc4cd), 0x10 },
+ { CCI_REG8(0xc4ea), 0x07 }, { CCI_REG8(0xc4eb), 0x07 },
+ { CCI_REG8(0xc4ec), 0x07 }, { CCI_REG8(0xc4ed), 0x07 },
+ { CCI_REG8(0xc4ee), 0x07 }, { CCI_REG8(0xc4f6), 0x10 },
+ { CCI_REG8(0xc4f7), 0x10 }, { CCI_REG8(0xc4f8), 0x10 },
+ { CCI_REG8(0xc4f9), 0x10 }, { CCI_REG8(0xc518), 0x0e },
+ { CCI_REG8(0xc519), 0x0e }, { CCI_REG8(0xc51a), 0x0e },
+ { CCI_REG8(0xc51b), 0x0e }, { CCI_REG8(0xc51c), 0x0e },
+ { CCI_REG8(0xc51d), 0x0e }, { CCI_REG8(0xc51e), 0x0e },
+ { CCI_REG8(0xc51f), 0x0e }, { CCI_REG8(0xc520), 0x0e },
+ { CCI_REG8(0xc521), 0x0e }, { CCI_REG8(0xc522), 0x0e },
+ { CCI_REG8(0xc523), 0x0e }, { CCI_REG8(0xc524), 0x0e },
+ { CCI_REG8(0xc525), 0x0e }, { CCI_REG8(0xc526), 0x0e },
+ { CCI_REG8(0xc527), 0x0e }, { CCI_REG8(0xc528), 0x0e },
+ { CCI_REG8(0xc529), 0x0e }, { CCI_REG8(0xc52a), 0x0e },
+ { CCI_REG8(0xc52b), 0x0e }, { CCI_REG8(0xc52c), 0x0e },
+ { CCI_REG8(0xc52d), 0x0e }, { CCI_REG8(0xc52e), 0x0e },
+ { CCI_REG8(0xc52f), 0x0e }, { CCI_REG8(0xc530), 0x0e },
+ { CCI_REG8(0xc531), 0x0e }, { CCI_REG8(0xc532), 0x0e },
+ { CCI_REG8(0xc533), 0x0e }, { CCI_REG8(0xc534), 0x0e },
+ { CCI_REG8(0xc535), 0x0e }, { CCI_REG8(0xc536), 0x0e },
+ { CCI_REG8(0xc537), 0x0e }, { CCI_REG8(0xc538), 0x0e },
+ { CCI_REG8(0xc539), 0x0e }, { CCI_REG8(0xc53a), 0x0e },
+ { CCI_REG8(0xc53b), 0x0e }, { CCI_REG8(0xc53c), 0x0e },
+ { CCI_REG8(0xc53d), 0x0e }, { CCI_REG8(0xc53e), 0x0e },
+ { CCI_REG8(0xc53f), 0x0e }, { CCI_REG8(0xc540), 0x0e },
+ { CCI_REG8(0xc541), 0x0e }, { CCI_REG8(0xc542), 0x0e },
+ { CCI_REG8(0xc543), 0x0e }, { CCI_REG8(0xc544), 0x0e },
+ { CCI_REG8(0xc545), 0x0e }, { CCI_REG8(0xc546), 0x0e },
+ { CCI_REG8(0xc547), 0x0e }, { CCI_REG8(0xc548), 0x0e },
+ { CCI_REG8(0xc549), 0x0e }, { CCI_REG8(0xc57f), 0x22 },
+ { CCI_REG8(0xc580), 0x22 }, { CCI_REG8(0xc581), 0x22 },
+ { CCI_REG8(0xc582), 0x22 }, { CCI_REG8(0xc583), 0x22 },
+ { CCI_REG8(0xc584), 0x22 }, { CCI_REG8(0xc585), 0x22 },
+ { CCI_REG8(0xc586), 0x22 }, { CCI_REG8(0xc587), 0x22 },
+ { CCI_REG8(0xc588), 0x22 }, { CCI_REG8(0xc589), 0x22 },
+ { CCI_REG8(0xc58a), 0x22 }, { CCI_REG8(0xc58b), 0x22 },
+ { CCI_REG8(0xc58c), 0x22 }, { CCI_REG8(0xc58d), 0x22 },
+ { CCI_REG8(0xc58e), 0x22 }, { CCI_REG8(0xc58f), 0x22 },
+ { CCI_REG8(0xc590), 0x22 }, { CCI_REG8(0xc591), 0x22 },
+ { CCI_REG8(0xc592), 0x22 }, { CCI_REG8(0xc598), 0x22 },
+ { CCI_REG8(0xc599), 0x22 }, { CCI_REG8(0xc59a), 0x22 },
+ { CCI_REG8(0xc59b), 0x22 }, { CCI_REG8(0xc59c), 0x22 },
+ { CCI_REG8(0xc59d), 0x22 }, { CCI_REG8(0xc59e), 0x22 },
+ { CCI_REG8(0xc59f), 0x22 }, { CCI_REG8(0xc5a0), 0x22 },
+ { CCI_REG8(0xc5a1), 0x22 }, { CCI_REG8(0xc5a2), 0x22 },
+ { CCI_REG8(0xc5a3), 0x22 }, { CCI_REG8(0xc5a4), 0x22 },
+ { CCI_REG8(0xc5a5), 0x22 }, { CCI_REG8(0xc5a6), 0x22 },
+ { CCI_REG8(0xc5a7), 0x22 }, { CCI_REG8(0xc5a8), 0x22 },
+ { CCI_REG8(0xc5a9), 0x22 }, { CCI_REG8(0xc5aa), 0x22 },
+ { CCI_REG8(0xc5ab), 0x22 }, { CCI_REG8(0xc5b1), 0x2a },
+ { CCI_REG8(0xc5b2), 0x2a }, { CCI_REG8(0xc5b3), 0x2a },
+ { CCI_REG8(0xc5b4), 0x2a }, { CCI_REG8(0xc5b5), 0x2a },
+ { CCI_REG8(0xc5b6), 0x2a }, { CCI_REG8(0xc5b7), 0x2a },
+ { CCI_REG8(0xc5b8), 0x2a }, { CCI_REG8(0xc5b9), 0x2a },
+ { CCI_REG8(0xc5ba), 0x2a }, { CCI_REG8(0xc5bb), 0x2a },
+ { CCI_REG8(0xc5bc), 0x2a }, { CCI_REG8(0xc5bd), 0x2a },
+ { CCI_REG8(0xc5be), 0x2a }, { CCI_REG8(0xc5bf), 0x2a },
+ { CCI_REG8(0xc5c0), 0x2a }, { CCI_REG8(0xc5c1), 0x2a },
+ { CCI_REG8(0xc5c2), 0x2a }, { CCI_REG8(0xc5c3), 0x2a },
+ { CCI_REG8(0xc5c4), 0x2a }, { CCI_REG8(0xc5ca), 0x2a },
+ { CCI_REG8(0xc5cb), 0x2a }, { CCI_REG8(0xc5cc), 0x2a },
+ { CCI_REG8(0xc5cd), 0x2a }, { CCI_REG8(0xc5ce), 0x2a },
+ { CCI_REG8(0xc5cf), 0x2a }, { CCI_REG8(0xc5d0), 0x2a },
+ { CCI_REG8(0xc5d1), 0x2a }, { CCI_REG8(0xc5d2), 0x2a },
+ { CCI_REG8(0xc5d3), 0x2a }, { CCI_REG8(0xc5d4), 0x2a },
+ { CCI_REG8(0xc5d5), 0x2a }, { CCI_REG8(0xc5d6), 0x2a },
+ { CCI_REG8(0xc5d7), 0x2a }, { CCI_REG8(0xc5d8), 0x2a },
+ { CCI_REG8(0xc5d9), 0x2a }, { CCI_REG8(0xc5da), 0x2a },
+ { CCI_REG8(0xc5db), 0x2a }, { CCI_REG8(0xc5dc), 0x2a },
+ { CCI_REG8(0xc5dd), 0x2a }, { CCI_REG8(0xc5e8), 0x22 },
+ { CCI_REG8(0xc5ea), 0x22 }, { CCI_REG8(0x4540), 0x12 },
+ { CCI_REG8(0x4541), 0x30 }, { CCI_REG8(0x3d86), 0x12 },
+ { CCI_REG8(0x3d87), 0x30 }, { CCI_REG8(0x4606), 0x12 },
+ { CCI_REG8(0x4607), 0x30 }, { CCI_REG8(0x4648), 0x0a },
+ { CCI_REG8(0x4649), 0x06 }, { CCI_REG8(0x3220), 0x12 },
+ { CCI_REG8(0x3221), 0x30 }, { CCI_REG8(0x40c2), 0x12 },
+ { CCI_REG8(0x49c2), 0x12 }, { CCI_REG8(0x4ac2), 0x12 },
+ { CCI_REG8(0x40c3), 0x30 }, { CCI_REG8(0x49c3), 0x30 },
+ { CCI_REG8(0x4ac3), 0x30 }, { CCI_REG8(0x36b0), 0x12 },
+ { CCI_REG8(0x36b1), 0x30 }, { CCI_REG8(0x45cb), 0x12 },
+ { CCI_REG8(0x45cc), 0x30 }, { CCI_REG8(0x4585), 0x12 },
+ { CCI_REG8(0x4586), 0x30 }, { CCI_REG8(0x36b2), 0x12 },
+ { CCI_REG8(0x36b3), 0x30 }, { CCI_REG8(0x5a40), 0x75 },
+ { CCI_REG8(0x5a41), 0x75 }, { CCI_REG8(0x5a42), 0x75 },
+ { CCI_REG8(0x5a43), 0x75 }, { CCI_REG8(0x5a44), 0x75 },
+ { CCI_REG8(0x5a45), 0x75 }, { CCI_REG8(0x5a46), 0x75 },
+ { CCI_REG8(0x5a47), 0x75 }, { CCI_REG8(0x5a48), 0x75 },
+ { CCI_REG8(0x5a49), 0x75 }, { CCI_REG8(0x5a4a), 0x75 },
+ { CCI_REG8(0x5a4b), 0x75 }, { CCI_REG8(0x5a4c), 0x75 },
+ { CCI_REG8(0x5a4d), 0x75 }, { CCI_REG8(0x5a4e), 0x75 },
+ { CCI_REG8(0x5a4f), 0x75 }, { CCI_REG8(0x5a50), 0x75 },
+ { CCI_REG8(0x5a51), 0x75 }, { CCI_REG8(0x5a52), 0x75 },
+ { CCI_REG8(0x5a53), 0x75 }, { CCI_REG8(0x5a54), 0x75 },
+ { CCI_REG8(0x5a55), 0x75 }, { CCI_REG8(0x5a56), 0x75 },
+ { CCI_REG8(0x5a57), 0x75 }, { CCI_REG8(0x5a58), 0x75 },
+ { CCI_REG8(0x5a59), 0x75 }, { CCI_REG8(0x5a5a), 0x75 },
+ { CCI_REG8(0x5a5b), 0x75 }, { CCI_REG8(0x5a5c), 0x75 },
+ { CCI_REG8(0x5a5d), 0x75 }, { CCI_REG8(0x5a5e), 0x75 },
+ { CCI_REG8(0x5a5f), 0x75 }, { CCI_REG8(0x5a60), 0x75 },
+ { CCI_REG8(0x5a61), 0x75 }, { CCI_REG8(0x5a62), 0x75 },
+ { CCI_REG8(0x5a63), 0x75 }, { CCI_REG8(0x5a64), 0x75 },
+ { CCI_REG8(0x5a65), 0x75 }, { CCI_REG8(0x5a66), 0x75 },
+ { CCI_REG8(0x5a67), 0x75 }, { CCI_REG8(0x5a68), 0x75 },
+ { CCI_REG8(0x5a69), 0x75 }, { CCI_REG8(0x5a6a), 0x75 },
+ { CCI_REG8(0x5a6b), 0x75 }, { CCI_REG8(0x5a6c), 0x75 },
+ { CCI_REG8(0x5a6d), 0x75 }, { CCI_REG8(0x5a6e), 0x75 },
+ { CCI_REG8(0x5a6f), 0x75 }, { CCI_REG8(0x5a70), 0x75 },
+ { CCI_REG8(0x5a71), 0x75 }, { CCI_REG8(0x5a72), 0x75 },
+ { CCI_REG8(0x5a73), 0x75 }, { CCI_REG8(0x5a74), 0x75 },
+ { CCI_REG8(0x5a75), 0x75 }, { CCI_REG8(0x5a76), 0x75 },
+ { CCI_REG8(0x5a77), 0x75 }, { CCI_REG8(0x5a78), 0x75 },
+ { CCI_REG8(0x5a79), 0x75 }, { CCI_REG8(0x5a7a), 0x75 },
+ { CCI_REG8(0x5a7b), 0x75 }, { CCI_REG8(0x5a7c), 0x75 },
+ { CCI_REG8(0x5a7d), 0x75 }, { CCI_REG8(0x5a7e), 0x75 },
+ { CCI_REG8(0x5a7f), 0x75 }, { CCI_REG8(0x5a80), 0x75 },
+ { CCI_REG8(0x5a81), 0x75 }, { CCI_REG8(0x5a82), 0x75 },
+ { CCI_REG8(0x5a83), 0x75 }, { CCI_REG8(0x5a84), 0x75 },
+ { CCI_REG8(0x5a85), 0x75 }, { CCI_REG8(0x5a86), 0x75 },
+ { CCI_REG8(0x5a87), 0x75 }, { CCI_REG8(0x5a88), 0x75 },
+ { CCI_REG8(0x5a89), 0x75 }, { CCI_REG8(0x5a8a), 0x75 },
+ { CCI_REG8(0x5a8b), 0x75 }, { CCI_REG8(0x5a8c), 0x75 },
+ { CCI_REG8(0x5a8d), 0x75 }, { CCI_REG8(0x5a8e), 0x75 },
+ { CCI_REG8(0x5a8f), 0x75 }, { CCI_REG8(0x5a90), 0x75 },
+ { CCI_REG8(0x5a91), 0x75 }, { CCI_REG8(0x5a92), 0x75 },
+ { CCI_REG8(0x5a93), 0x75 }, { CCI_REG8(0x5a94), 0x75 },
+ { CCI_REG8(0x5a95), 0x75 }, { CCI_REG8(0x5a96), 0x75 },
+ { CCI_REG8(0x5a97), 0x75 }, { CCI_REG8(0x5a98), 0x75 },
+ { CCI_REG8(0x5a99), 0x75 }, { CCI_REG8(0x5a9a), 0x75 },
+ { CCI_REG8(0x5a9b), 0x75 }, { CCI_REG8(0x5a9c), 0x75 },
+ { CCI_REG8(0x5a9d), 0x75 }, { CCI_REG8(0x5a9e), 0x75 },
+ { CCI_REG8(0x5a9f), 0x75 }, { CCI_REG8(0x5aa0), 0x75 },
+ { CCI_REG8(0x5aa1), 0x75 }, { CCI_REG8(0x5aa2), 0x75 },
+ { CCI_REG8(0x5aa3), 0x75 }, { CCI_REG8(0x5aa4), 0x75 },
+ { CCI_REG8(0x5aa5), 0x75 }, { CCI_REG8(0x5aa6), 0x75 },
+ { CCI_REG8(0x5aa7), 0x75 }, { CCI_REG8(0x5aa8), 0x75 },
+ { CCI_REG8(0x5aa9), 0x75 }, { CCI_REG8(0x5aaa), 0x75 },
+ { CCI_REG8(0x5aab), 0x75 }, { CCI_REG8(0x5aac), 0x75 },
+ { CCI_REG8(0x5aad), 0x75 }, { CCI_REG8(0x5aae), 0x75 },
+ { CCI_REG8(0x5aaf), 0x75 }, { CCI_REG8(0x5ab0), 0x75 },
+ { CCI_REG8(0x5ab1), 0x75 }, { CCI_REG8(0x5ab2), 0x75 },
+ { CCI_REG8(0x5ab3), 0x75 }, { CCI_REG8(0x5ab4), 0x75 },
+ { CCI_REG8(0x5ab5), 0x75 }, { CCI_REG8(0x5ab6), 0x75 },
+ { CCI_REG8(0x5ab7), 0x75 }, { CCI_REG8(0x5ab8), 0x75 },
+ { CCI_REG8(0x5ab9), 0x75 }, { CCI_REG8(0x5aba), 0x75 },
+ { CCI_REG8(0x5abb), 0x75 }, { CCI_REG8(0x5abc), 0x75 },
+ { CCI_REG8(0x5abd), 0x75 }, { CCI_REG8(0x5abe), 0x75 },
+ { CCI_REG8(0x5abf), 0x75 }, { CCI_REG8(0x5ac0), 0x75 },
+ { CCI_REG8(0x5ac1), 0x75 }, { CCI_REG8(0x5ac2), 0x75 },
+ { CCI_REG8(0x5ac3), 0x75 }, { CCI_REG8(0x5ac4), 0x75 },
+ { CCI_REG8(0x5ac5), 0x75 }, { CCI_REG8(0x5ac6), 0x75 },
+ { CCI_REG8(0x5ac7), 0x75 }, { CCI_REG8(0x5ac8), 0x75 },
+ { CCI_REG8(0x5ac9), 0x75 }, { CCI_REG8(0x5aca), 0x75 },
+ { CCI_REG8(0x5acb), 0x75 }, { CCI_REG8(0x5acc), 0x75 },
+ { CCI_REG8(0x5acd), 0x75 }, { CCI_REG8(0x5ace), 0x75 },
+ { CCI_REG8(0x5acf), 0x75 }, { CCI_REG8(0x5ad0), 0x75 },
+ { CCI_REG8(0x5ad1), 0x75 }, { CCI_REG8(0x5ad2), 0x75 },
+ { CCI_REG8(0x5ad3), 0x75 }, { CCI_REG8(0x5ad4), 0x75 },
+ { CCI_REG8(0x5ad5), 0x75 }, { CCI_REG8(0x5ad6), 0x75 },
+ { CCI_REG8(0x5ad7), 0x75 }, { CCI_REG8(0x5ad8), 0x75 },
+ { CCI_REG8(0x5ad9), 0x75 }, { CCI_REG8(0x5ada), 0x75 },
+ { CCI_REG8(0x5adb), 0x75 }, { CCI_REG8(0x5adc), 0x75 },
+ { CCI_REG8(0x5add), 0x75 }, { CCI_REG8(0x5ade), 0x75 },
+ { CCI_REG8(0x5adf), 0x75 }, { CCI_REG8(0x5ae0), 0x75 },
+ { CCI_REG8(0x5ae1), 0x75 }, { CCI_REG8(0x5ae2), 0x75 },
+ { CCI_REG8(0x5ae3), 0x75 }, { CCI_REG8(0x5ae4), 0x75 },
+ { CCI_REG8(0x5ae5), 0x75 }, { CCI_REG8(0x5ae6), 0x75 },
+ { CCI_REG8(0x5ae7), 0x75 }, { CCI_REG8(0x5ae8), 0x75 },
+ { CCI_REG8(0x5ae9), 0x75 }, { CCI_REG8(0x5aea), 0x75 },
+ { CCI_REG8(0x5aeb), 0x75 }, { CCI_REG8(0x5aec), 0x75 },
+ { CCI_REG8(0x5aed), 0x75 }, { CCI_REG8(0x5aee), 0x75 },
+ { CCI_REG8(0x5aef), 0x75 }, { CCI_REG8(0x5af0), 0x75 },
+ { CCI_REG8(0x5af1), 0x75 }, { CCI_REG8(0x5af2), 0x75 },
+ { CCI_REG8(0x5af3), 0x75 }, { CCI_REG8(0x5af4), 0x75 },
+ { CCI_REG8(0x5af5), 0x75 }, { CCI_REG8(0x5af6), 0x75 },
+ { CCI_REG8(0x5af7), 0x75 }, { CCI_REG8(0x5af8), 0x75 },
+ { CCI_REG8(0x5af9), 0x75 }, { CCI_REG8(0x5afa), 0x75 },
+ { CCI_REG8(0x5afb), 0x75 }, { CCI_REG8(0x5afc), 0x75 },
+ { CCI_REG8(0x5afd), 0x75 }, { CCI_REG8(0x5afe), 0x75 },
+ { CCI_REG8(0x5aff), 0x75 }, { CCI_REG8(0x5b00), 0x75 },
+ { CCI_REG8(0x5b01), 0x75 }, { CCI_REG8(0x5b02), 0x75 },
+ { CCI_REG8(0x5b03), 0x75 }, { CCI_REG8(0x5b04), 0x75 },
+ { CCI_REG8(0x5b05), 0x75 }, { CCI_REG8(0x5b06), 0x75 },
+ { CCI_REG8(0x5b07), 0x75 }, { CCI_REG8(0x5b08), 0x75 },
+ { CCI_REG8(0x5b09), 0x75 }, { CCI_REG8(0x5b0a), 0x75 },
+ { CCI_REG8(0x5b0b), 0x75 }, { CCI_REG8(0x5b0c), 0x75 },
+ { CCI_REG8(0x5b0d), 0x75 }, { CCI_REG8(0x5b0e), 0x75 },
+ { CCI_REG8(0x5b0f), 0x75 }, { CCI_REG8(0x5b10), 0x75 },
+ { CCI_REG8(0x5b11), 0x75 }, { CCI_REG8(0x5b12), 0x75 },
+ { CCI_REG8(0x5b13), 0x75 }, { CCI_REG8(0x5b14), 0x75 },
+ { CCI_REG8(0x5b15), 0x75 }, { CCI_REG8(0x5b16), 0x75 },
+ { CCI_REG8(0x5b17), 0x75 }, { CCI_REG8(0x5b18), 0x75 },
+ { CCI_REG8(0x5b19), 0x75 }, { CCI_REG8(0x5b1a), 0x75 },
+ { CCI_REG8(0x5b1b), 0x75 }, { CCI_REG8(0x5b1c), 0x75 },
+ { CCI_REG8(0x5b1d), 0x75 }, { CCI_REG8(0x5b1e), 0x75 },
+ { CCI_REG8(0x5b1f), 0x75 }, { CCI_REG8(0x5b20), 0x75 },
+ { CCI_REG8(0x5b21), 0x75 }, { CCI_REG8(0x5b22), 0x75 },
+ { CCI_REG8(0x5b23), 0x75 }, { CCI_REG8(0x5b24), 0x75 },
+ { CCI_REG8(0x5b25), 0x75 }, { CCI_REG8(0x5b26), 0x75 },
+ { CCI_REG8(0x5b27), 0x75 }, { CCI_REG8(0x5b28), 0x75 },
+ { CCI_REG8(0x5b29), 0x75 }, { CCI_REG8(0x5b2a), 0x75 },
+ { CCI_REG8(0x5b2b), 0x75 }, { CCI_REG8(0x5b2c), 0x75 },
+ { CCI_REG8(0x5b2d), 0x75 }, { CCI_REG8(0x5b2e), 0x75 },
+ { CCI_REG8(0x5b2f), 0x75 }, { CCI_REG8(0x5b30), 0x75 },
+ { CCI_REG8(0x5b31), 0x75 }, { CCI_REG8(0x5b32), 0x75 },
+ { CCI_REG8(0x5b33), 0x75 }, { CCI_REG8(0x5b34), 0x75 },
+ { CCI_REG8(0x5b35), 0x75 }, { CCI_REG8(0x5b36), 0x75 },
+ { CCI_REG8(0x5b37), 0x75 }, { CCI_REG8(0x5b38), 0x75 },
+ { CCI_REG8(0x5b39), 0x75 }, { CCI_REG8(0x5b3a), 0x75 },
+ { CCI_REG8(0x5b3b), 0x75 }, { CCI_REG8(0x5b3c), 0x75 },
+ { CCI_REG8(0x5b3d), 0x75 }, { CCI_REG8(0x5b3e), 0x75 },
+ { CCI_REG8(0x5b3f), 0x75 }, { CCI_REG8(0x5b40), 0x75 },
+ { CCI_REG8(0x5b41), 0x75 }, { CCI_REG8(0x5b42), 0x75 },
+ { CCI_REG8(0x5b43), 0x75 }, { CCI_REG8(0x5b44), 0x75 },
+ { CCI_REG8(0x5b45), 0x75 }, { CCI_REG8(0x5b46), 0x75 },
+ { CCI_REG8(0x5b47), 0x75 }, { CCI_REG8(0x5b48), 0x75 },
+ { CCI_REG8(0x5b49), 0x75 }, { CCI_REG8(0x5b4a), 0x75 },
+ { CCI_REG8(0x5b4b), 0x75 }, { CCI_REG8(0x5b4c), 0x75 },
+ { CCI_REG8(0x5b4d), 0x75 }, { CCI_REG8(0x5b4e), 0x75 },
+ { CCI_REG8(0x5b4f), 0x75 }, { CCI_REG8(0x5b50), 0x75 },
+ { CCI_REG8(0x5b51), 0x75 }, { CCI_REG8(0x5b52), 0x75 },
+ { CCI_REG8(0x5b53), 0x75 }, { CCI_REG8(0x5b54), 0x75 },
+ { CCI_REG8(0x5b55), 0x75 }, { CCI_REG8(0x5b56), 0x75 },
+ { CCI_REG8(0x5b57), 0x75 }, { CCI_REG8(0x5b58), 0x75 },
+ { CCI_REG8(0x5b59), 0x75 }, { CCI_REG8(0x5b5a), 0x75 },
+ { CCI_REG8(0x5b5b), 0x75 }, { CCI_REG8(0x5b5c), 0x75 },
+ { CCI_REG8(0x5b5d), 0x75 }, { CCI_REG8(0x5b5e), 0x75 },
+ { CCI_REG8(0x5b5f), 0x75 }, { CCI_REG8(0x5b80), 0x75 },
+ { CCI_REG8(0x5b81), 0x75 }, { CCI_REG8(0x5b82), 0x75 },
+ { CCI_REG8(0x5b83), 0x75 }, { CCI_REG8(0x5b84), 0x75 },
+ { CCI_REG8(0x5b85), 0x75 }, { CCI_REG8(0x5b86), 0x75 },
+ { CCI_REG8(0x5b87), 0x75 }, { CCI_REG8(0x5b88), 0x75 },
+ { CCI_REG8(0x5b89), 0x75 }, { CCI_REG8(0x5b8a), 0x75 },
+ { CCI_REG8(0x5b8b), 0x75 }, { CCI_REG8(0x5b8c), 0x75 },
+ { CCI_REG8(0x5b8d), 0x75 }, { CCI_REG8(0x5b8e), 0x75 },
+ { CCI_REG8(0x5b8f), 0x75 }, { CCI_REG8(0x5b90), 0x75 },
+ { CCI_REG8(0x5b91), 0x75 }, { CCI_REG8(0x5b92), 0x75 },
+ { CCI_REG8(0x5b93), 0x75 }, { CCI_REG8(0x5b94), 0x75 },
+ { CCI_REG8(0x5b95), 0x75 }, { CCI_REG8(0x5b96), 0x75 },
+ { CCI_REG8(0x5b97), 0x75 }, { CCI_REG8(0x5b98), 0x75 },
+ { CCI_REG8(0x5b99), 0x75 }, { CCI_REG8(0x5b9a), 0x75 },
+ { CCI_REG8(0x5b9b), 0x75 }, { CCI_REG8(0x5b9c), 0x75 },
+ { CCI_REG8(0x5b9d), 0x75 }, { CCI_REG8(0x5b9e), 0x75 },
+ { CCI_REG8(0x5b9f), 0x75 }, { CCI_REG8(0x5ba0), 0x75 },
+ { CCI_REG8(0x5ba1), 0x75 }, { CCI_REG8(0x5ba2), 0x75 },
+ { CCI_REG8(0x5ba3), 0x75 }, { CCI_REG8(0x5ba4), 0x75 },
+ { CCI_REG8(0x5ba5), 0x75 }, { CCI_REG8(0x5ba6), 0x75 },
+ { CCI_REG8(0x5ba7), 0x75 }, { CCI_REG8(0x5ba8), 0x75 },
+ { CCI_REG8(0x5ba9), 0x75 }, { CCI_REG8(0x5baa), 0x75 },
+ { CCI_REG8(0x5bab), 0x75 }, { CCI_REG8(0x5bac), 0x75 },
+ { CCI_REG8(0x5bad), 0x75 }, { CCI_REG8(0x5bae), 0x75 },
+ { CCI_REG8(0x5baf), 0x75 }, { CCI_REG8(0x5bb0), 0x75 },
+ { CCI_REG8(0x5bb1), 0x75 }, { CCI_REG8(0x5bb2), 0x75 },
+ { CCI_REG8(0x5bb3), 0x75 }, { CCI_REG8(0x5bb4), 0x75 },
+ { CCI_REG8(0x5bb5), 0x75 }, { CCI_REG8(0x5bb6), 0x75 },
+ { CCI_REG8(0x5bb7), 0x75 }, { CCI_REG8(0x5bb8), 0x75 },
+ { CCI_REG8(0x5bb9), 0x75 }, { CCI_REG8(0x5bba), 0x75 },
+ { CCI_REG8(0x5bbb), 0x75 }, { CCI_REG8(0x5bbc), 0x75 },
+ { CCI_REG8(0x5bbd), 0x75 }, { CCI_REG8(0x5bbe), 0x75 },
+ { CCI_REG8(0x5bbf), 0x75 }, { CCI_REG8(0x5bc0), 0x75 },
+ { CCI_REG8(0x5bc1), 0x75 }, { CCI_REG8(0x5bc2), 0x75 },
+ { CCI_REG8(0x5bc3), 0x75 }, { CCI_REG8(0x5bc4), 0x75 },
+ { CCI_REG8(0x5bc5), 0x75 }, { CCI_REG8(0x5bc6), 0x75 },
+ { CCI_REG8(0x5bc7), 0x75 }, { CCI_REG8(0x5bc8), 0x75 },
+ { CCI_REG8(0x5bc9), 0x75 }, { CCI_REG8(0x5bca), 0x75 },
+ { CCI_REG8(0x5bcb), 0x75 }, { CCI_REG8(0x5bcc), 0x75 },
+ { CCI_REG8(0x5bcd), 0x75 }, { CCI_REG8(0x5bce), 0x75 },
+ { CCI_REG8(0x5bcf), 0x75 }, { CCI_REG8(0x5bd0), 0x75 },
+ { CCI_REG8(0x5bd1), 0x75 }, { CCI_REG8(0x5bd2), 0x75 },
+ { CCI_REG8(0x5bd3), 0x75 }, { CCI_REG8(0x5bd4), 0x75 },
+ { CCI_REG8(0x5bd5), 0x75 }, { CCI_REG8(0x5bd6), 0x75 },
+ { CCI_REG8(0x5bd7), 0x75 }, { CCI_REG8(0x5bd8), 0x75 },
+ { CCI_REG8(0x5bd9), 0x75 }, { CCI_REG8(0x5bda), 0x75 },
+ { CCI_REG8(0x5bdb), 0x75 }, { CCI_REG8(0x5bdc), 0x75 },
+ { CCI_REG8(0x5bdd), 0x75 }, { CCI_REG8(0x5bde), 0x75 },
+ { CCI_REG8(0x5bdf), 0x75 }, { CCI_REG8(0x5be0), 0x75 },
+ { CCI_REG8(0x5be1), 0x75 }, { CCI_REG8(0x5be2), 0x75 },
+ { CCI_REG8(0x5be3), 0x75 }, { CCI_REG8(0x5be4), 0x75 },
+ { CCI_REG8(0x5be5), 0x75 }, { CCI_REG8(0x5be6), 0x75 },
+ { CCI_REG8(0x5be7), 0x75 }, { CCI_REG8(0x5be8), 0x75 },
+ { CCI_REG8(0x5be9), 0x75 }, { CCI_REG8(0x5bea), 0x75 },
+ { CCI_REG8(0x5beb), 0x75 }, { CCI_REG8(0x5bec), 0x75 },
+ { CCI_REG8(0x5bed), 0x75 }, { CCI_REG8(0x5bee), 0x75 },
+ { CCI_REG8(0x5bef), 0x75 }, { CCI_REG8(0x5bf0), 0x75 },
+ { CCI_REG8(0x5bf1), 0x75 }, { CCI_REG8(0x5bf2), 0x75 },
+ { CCI_REG8(0x5bf3), 0x75 }, { CCI_REG8(0x5bf4), 0x75 },
+ { CCI_REG8(0x5bf5), 0x75 }, { CCI_REG8(0x5bf6), 0x75 },
+ { CCI_REG8(0x5bf7), 0x75 }, { CCI_REG8(0x5bf8), 0x75 },
+ { CCI_REG8(0x5bf9), 0x75 }, { CCI_REG8(0x5bfa), 0x75 },
+ { CCI_REG8(0x5bfb), 0x75 }, { CCI_REG8(0x5bfc), 0x75 },
+ { CCI_REG8(0x5bfd), 0x75 }, { CCI_REG8(0x5bfe), 0x75 },
+ { CCI_REG8(0x5bff), 0x75 }, { CCI_REG8(0x5c00), 0x75 },
+ { CCI_REG8(0x5c01), 0x75 }, { CCI_REG8(0x5c02), 0x75 },
+ { CCI_REG8(0x5c03), 0x75 }, { CCI_REG8(0x5c04), 0x75 },
+ { CCI_REG8(0x5c05), 0x75 }, { CCI_REG8(0x5c06), 0x75 },
+ { CCI_REG8(0x5c07), 0x75 }, { CCI_REG8(0x5c08), 0x75 },
+ { CCI_REG8(0x5c09), 0x75 }, { CCI_REG8(0x5c0a), 0x75 },
+ { CCI_REG8(0x5c0b), 0x75 }, { CCI_REG8(0x5c0c), 0x75 },
+ { CCI_REG8(0x5c0d), 0x75 }, { CCI_REG8(0x5c0e), 0x75 },
+ { CCI_REG8(0x5c0f), 0x75 }, { CCI_REG8(0x5c10), 0x75 },
+ { CCI_REG8(0x5c11), 0x75 }, { CCI_REG8(0x5c12), 0x75 },
+ { CCI_REG8(0x5c13), 0x75 }, { CCI_REG8(0x5c14), 0x75 },
+ { CCI_REG8(0x5c15), 0x75 }, { CCI_REG8(0x5c16), 0x75 },
+ { CCI_REG8(0x5c17), 0x75 }, { CCI_REG8(0x5c18), 0x75 },
+ { CCI_REG8(0x5c19), 0x75 }, { CCI_REG8(0x5c1a), 0x75 },
+ { CCI_REG8(0x5c1b), 0x75 }, { CCI_REG8(0x5c1c), 0x75 },
+ { CCI_REG8(0x5c1d), 0x75 }, { CCI_REG8(0x5c1e), 0x75 },
+ { CCI_REG8(0x5c1f), 0x75 }, { CCI_REG8(0x5c20), 0x75 },
+ { CCI_REG8(0x5c21), 0x75 }, { CCI_REG8(0x5c22), 0x75 },
+ { CCI_REG8(0x5c23), 0x75 }, { CCI_REG8(0x5c24), 0x75 },
+ { CCI_REG8(0x5c25), 0x75 }, { CCI_REG8(0x5c26), 0x75 },
+ { CCI_REG8(0x5c27), 0x75 }, { CCI_REG8(0x5c28), 0x75 },
+ { CCI_REG8(0x5c29), 0x75 }, { CCI_REG8(0x5c2a), 0x75 },
+ { CCI_REG8(0x5c2b), 0x75 }, { CCI_REG8(0x5c2c), 0x75 },
+ { CCI_REG8(0x5c2d), 0x75 }, { CCI_REG8(0x5c2e), 0x75 },
+ { CCI_REG8(0x5c2f), 0x75 }, { CCI_REG8(0x5c30), 0x75 },
+ { CCI_REG8(0x5c31), 0x75 }, { CCI_REG8(0x5c32), 0x75 },
+ { CCI_REG8(0x5c33), 0x75 }, { CCI_REG8(0x5c34), 0x75 },
+ { CCI_REG8(0x5c35), 0x75 }, { CCI_REG8(0x5c36), 0x75 },
+ { CCI_REG8(0x5c37), 0x75 }, { CCI_REG8(0x5c38), 0x75 },
+ { CCI_REG8(0x5c39), 0x75 }, { CCI_REG8(0x5c3a), 0x75 },
+ { CCI_REG8(0x5c3b), 0x75 }, { CCI_REG8(0x5c3c), 0x75 },
+ { CCI_REG8(0x5c3d), 0x75 }, { CCI_REG8(0x5c3e), 0x75 },
+ { CCI_REG8(0x5c3f), 0x75 }, { CCI_REG8(0x5c40), 0x75 },
+ { CCI_REG8(0x5c41), 0x75 }, { CCI_REG8(0x5c42), 0x75 },
+ { CCI_REG8(0x5c43), 0x75 }, { CCI_REG8(0x5c44), 0x75 },
+ { CCI_REG8(0x5c45), 0x75 }, { CCI_REG8(0x5c46), 0x75 },
+ { CCI_REG8(0x5c47), 0x75 }, { CCI_REG8(0x5c48), 0x75 },
+ { CCI_REG8(0x5c49), 0x75 }, { CCI_REG8(0x5c4a), 0x75 },
+ { CCI_REG8(0x5c4b), 0x75 }, { CCI_REG8(0x5c4c), 0x75 },
+ { CCI_REG8(0x5c4d), 0x75 }, { CCI_REG8(0x5c4e), 0x75 },
+ { CCI_REG8(0x5c4f), 0x75 }, { CCI_REG8(0x5c50), 0x75 },
+ { CCI_REG8(0x5c51), 0x75 }, { CCI_REG8(0x5c52), 0x75 },
+ { CCI_REG8(0x5c53), 0x75 }, { CCI_REG8(0x5c54), 0x75 },
+ { CCI_REG8(0x5c55), 0x75 }, { CCI_REG8(0x5c56), 0x75 },
+ { CCI_REG8(0x5c57), 0x75 }, { CCI_REG8(0x5c58), 0x75 },
+ { CCI_REG8(0x5c59), 0x75 }, { CCI_REG8(0x5c5a), 0x75 },
+ { CCI_REG8(0x5c5b), 0x75 }, { CCI_REG8(0x5c5c), 0x75 },
+ { CCI_REG8(0x5c5d), 0x75 }, { CCI_REG8(0x5c5e), 0x75 },
+ { CCI_REG8(0x5c5f), 0x75 }, { CCI_REG8(0x5c60), 0x75 },
+ { CCI_REG8(0x5c61), 0x75 }, { CCI_REG8(0x5c62), 0x75 },
+ { CCI_REG8(0x5c63), 0x75 }, { CCI_REG8(0x5c64), 0x75 },
+ { CCI_REG8(0x5c65), 0x75 }, { CCI_REG8(0x5c66), 0x75 },
+ { CCI_REG8(0x5c67), 0x75 }, { CCI_REG8(0x5c68), 0x75 },
+ { CCI_REG8(0x5c69), 0x75 }, { CCI_REG8(0x5c6a), 0x75 },
+ { CCI_REG8(0x5c6b), 0x75 }, { CCI_REG8(0x5c6c), 0x75 },
+ { CCI_REG8(0x5c6d), 0x75 }, { CCI_REG8(0x5c6e), 0x75 },
+ { CCI_REG8(0x5c6f), 0x75 }, { CCI_REG8(0x5c70), 0x75 },
+ { CCI_REG8(0x5c71), 0x75 }, { CCI_REG8(0x5c72), 0x75 },
+ { CCI_REG8(0x5c73), 0x75 }, { CCI_REG8(0x5c74), 0x75 },
+ { CCI_REG8(0x5c75), 0x75 }, { CCI_REG8(0x5c76), 0x75 },
+ { CCI_REG8(0x5c77), 0x75 }, { CCI_REG8(0x5c78), 0x75 },
+ { CCI_REG8(0x5c79), 0x75 }, { CCI_REG8(0x5c7a), 0x75 },
+ { CCI_REG8(0x5c7b), 0x75 }, { CCI_REG8(0x5c7c), 0x75 },
+ { CCI_REG8(0x5c7d), 0x75 }, { CCI_REG8(0x5c7e), 0x75 },
+ { CCI_REG8(0x5c7f), 0x75 }, { CCI_REG8(0x5c80), 0x75 },
+ { CCI_REG8(0x5c81), 0x75 }, { CCI_REG8(0x5c82), 0x75 },
+ { CCI_REG8(0x5c83), 0x75 }, { CCI_REG8(0x5c84), 0x75 },
+ { CCI_REG8(0x5c85), 0x75 }, { CCI_REG8(0x5c86), 0x75 },
+ { CCI_REG8(0x5c87), 0x75 }, { CCI_REG8(0x5c88), 0x75 },
+ { CCI_REG8(0x5c89), 0x75 }, { CCI_REG8(0x5c8a), 0x75 },
+ { CCI_REG8(0x5c8b), 0x75 }, { CCI_REG8(0x5c8c), 0x75 },
+ { CCI_REG8(0x5c8d), 0x75 }, { CCI_REG8(0x5c8e), 0x75 },
+ { CCI_REG8(0x5c8f), 0x75 }, { CCI_REG8(0x5c90), 0x75 },
+ { CCI_REG8(0x5c91), 0x75 }, { CCI_REG8(0x5c92), 0x75 },
+ { CCI_REG8(0x5c93), 0x75 }, { CCI_REG8(0x5c94), 0x75 },
+ { CCI_REG8(0x5c95), 0x75 }, { CCI_REG8(0x5c96), 0x75 },
+ { CCI_REG8(0x5c97), 0x75 }, { CCI_REG8(0x5c98), 0x75 },
+ { CCI_REG8(0x5c99), 0x75 }, { CCI_REG8(0x5c9a), 0x75 },
+ { CCI_REG8(0x5c9b), 0x75 }, { CCI_REG8(0x5c9c), 0x75 },
+ { CCI_REG8(0x5c9d), 0x75 }, { CCI_REG8(0x5c9e), 0x75 },
+ { CCI_REG8(0x5c9f), 0x75 }, { CCI_REG8(0x5ca0), 0x75 },
+ { CCI_REG8(0x5ca1), 0x75 }, { CCI_REG8(0x5ca2), 0x75 },
+ { CCI_REG8(0x5ca3), 0x75 }, { CCI_REG8(0x5ca4), 0x75 },
+ { CCI_REG8(0x5ca5), 0x75 }, { CCI_REG8(0x5ca6), 0x75 },
+ { CCI_REG8(0x5ca7), 0x75 }, { CCI_REG8(0x5ca8), 0x75 },
+ { CCI_REG8(0x5ca9), 0x75 }, { CCI_REG8(0x5caa), 0x75 },
+ { CCI_REG8(0x5cab), 0x75 }, { CCI_REG8(0x5cac), 0x75 },
+ { CCI_REG8(0x5cad), 0x75 }, { CCI_REG8(0x5cae), 0x75 },
+ { CCI_REG8(0x5caf), 0x75 }, { CCI_REG8(0x5cb0), 0x75 },
+ { CCI_REG8(0x5cb1), 0x75 }, { CCI_REG8(0x5cb2), 0x75 },
+ { CCI_REG8(0x5cb3), 0x75 }, { CCI_REG8(0x5cb4), 0x75 },
+ { CCI_REG8(0x5cb5), 0x75 }, { CCI_REG8(0x5cb6), 0x75 },
+ { CCI_REG8(0x5cb7), 0x75 }, { CCI_REG8(0x5cb8), 0x75 },
+ { CCI_REG8(0x5cb9), 0x75 }, { CCI_REG8(0x5cba), 0x75 },
+ { CCI_REG8(0x5cbb), 0x75 }, { CCI_REG8(0x5cbc), 0x75 },
+ { CCI_REG8(0x5cbd), 0x75 }, { CCI_REG8(0x5cbe), 0x75 },
+ { CCI_REG8(0x5cbf), 0x75 }, { CCI_REG8(0x5cc0), 0x75 },
+ { CCI_REG8(0x5cc1), 0x75 }, { CCI_REG8(0x5cc2), 0x75 },
+ { CCI_REG8(0x5cc3), 0x75 }, { CCI_REG8(0x5cc4), 0x75 },
+ { CCI_REG8(0x5cc5), 0x75 }, { CCI_REG8(0x5cc6), 0x75 },
+ { CCI_REG8(0x5cc7), 0x75 }, { CCI_REG8(0x5cc8), 0x75 },
+ { CCI_REG8(0x5cc9), 0x75 }, { CCI_REG8(0x5cca), 0x75 },
+ { CCI_REG8(0x5ccb), 0x75 }, { CCI_REG8(0x5ccc), 0x75 },
+ { CCI_REG8(0x5ccd), 0x75 }, { CCI_REG8(0x5cce), 0x75 },
+ { CCI_REG8(0x5ccf), 0x75 }, { CCI_REG8(0x5cd0), 0x75 },
+ { CCI_REG8(0x5cd1), 0x75 }, { CCI_REG8(0x5cd2), 0x75 },
+ { CCI_REG8(0x5cd3), 0x75 }, { CCI_REG8(0x5cd4), 0x75 },
+ { CCI_REG8(0x5cd5), 0x75 }, { CCI_REG8(0x5cd6), 0x75 },
+ { CCI_REG8(0x5cd7), 0x75 }, { CCI_REG8(0x5cd8), 0x75 },
+ { CCI_REG8(0x5cd9), 0x75 }, { CCI_REG8(0x5cda), 0x75 },
+ { CCI_REG8(0x5cdb), 0x75 }, { CCI_REG8(0x5cdc), 0x75 },
+ { CCI_REG8(0x5cdd), 0x75 }, { CCI_REG8(0x5cde), 0x75 },
+ { CCI_REG8(0x5cdf), 0x75 }, { CCI_REG8(0x5ce0), 0x75 },
+ { CCI_REG8(0x5ce1), 0x75 }, { CCI_REG8(0x5ce2), 0x75 },
+ { CCI_REG8(0x5ce3), 0x75 }, { CCI_REG8(0x5ce4), 0x75 },
+ { CCI_REG8(0x5ce5), 0x75 }, { CCI_REG8(0x5ce6), 0x75 },
+ { CCI_REG8(0x5ce7), 0x75 }, { CCI_REG8(0x5ce8), 0x75 },
+ { CCI_REG8(0x5ce9), 0x75 }, { CCI_REG8(0x5cea), 0x75 },
+ { CCI_REG8(0x5ceb), 0x75 }, { CCI_REG8(0x5cec), 0x75 },
+ { CCI_REG8(0x5ced), 0x75 }, { CCI_REG8(0x5cee), 0x75 },
+ { CCI_REG8(0x5cef), 0x75 }, { CCI_REG8(0x5cf0), 0x75 },
+ { CCI_REG8(0x5cf1), 0x75 }, { CCI_REG8(0x5cf2), 0x75 },
+ { CCI_REG8(0x5cf3), 0x75 }, { CCI_REG8(0x5cf4), 0x75 },
+ { CCI_REG8(0x5cf5), 0x75 }, { CCI_REG8(0x5cf6), 0x75 },
+ { CCI_REG8(0x5cf7), 0x75 }, { CCI_REG8(0x5cf8), 0x75 },
+ { CCI_REG8(0x5cf9), 0x75 }, { CCI_REG8(0x5cfa), 0x75 },
+ { CCI_REG8(0x5cfb), 0x75 }, { CCI_REG8(0x5cfc), 0x75 },
+ { CCI_REG8(0x5cfd), 0x75 }, { CCI_REG8(0x5cfe), 0x75 },
+ { CCI_REG8(0x5cff), 0x75 }, { CCI_REG8(0x5d00), 0x75 },
+ { CCI_REG8(0x5d01), 0x75 }, { CCI_REG8(0x5d02), 0x75 },
+ { CCI_REG8(0x5d03), 0x75 }, { CCI_REG8(0x5d04), 0x75 },
+ { CCI_REG8(0x5d05), 0x75 }, { CCI_REG8(0x5d06), 0x75 },
+ { CCI_REG8(0x5d07), 0x75 }, { CCI_REG8(0x5d08), 0x75 },
+ { CCI_REG8(0x5d09), 0x75 }, { CCI_REG8(0x5d0a), 0x75 },
+ { CCI_REG8(0x5d0b), 0x75 }, { CCI_REG8(0x5d0c), 0x75 },
+ { CCI_REG8(0x5d0d), 0x75 }, { CCI_REG8(0x5d0e), 0x75 },
+ { CCI_REG8(0x5d0f), 0x75 }, { CCI_REG8(0x5d10), 0x75 },
+ { CCI_REG8(0x5d11), 0x75 }, { CCI_REG8(0x5d12), 0x75 },
+ { CCI_REG8(0x5d13), 0x75 }, { CCI_REG8(0x5d14), 0x75 },
+ { CCI_REG8(0x5d15), 0x75 }, { CCI_REG8(0x5d16), 0x75 },
+ { CCI_REG8(0x5d17), 0x75 }, { CCI_REG8(0x5d18), 0x75 },
+ { CCI_REG8(0x5d19), 0x75 }, { CCI_REG8(0x5d1a), 0x75 },
+ { CCI_REG8(0x5d1b), 0x75 }, { CCI_REG8(0x5d1c), 0x75 },
+ { CCI_REG8(0x5d1d), 0x75 }, { CCI_REG8(0x5d1e), 0x75 },
+ { CCI_REG8(0x5d1f), 0x75 }, { CCI_REG8(0x5d20), 0x75 },
+ { CCI_REG8(0x5d21), 0x75 }, { CCI_REG8(0x5d22), 0x75 },
+ { CCI_REG8(0x5d23), 0x75 }, { CCI_REG8(0x5d24), 0x75 },
+ { CCI_REG8(0x5d25), 0x75 }, { CCI_REG8(0x5d26), 0x75 },
+ { CCI_REG8(0x5d27), 0x75 }, { CCI_REG8(0x5d28), 0x75 },
+ { CCI_REG8(0x5d29), 0x75 }, { CCI_REG8(0x5d2a), 0x75 },
+ { CCI_REG8(0x5d2b), 0x75 }, { CCI_REG8(0x5d2c), 0x75 },
+ { CCI_REG8(0x5d2d), 0x75 }, { CCI_REG8(0x5d2e), 0x75 },
+ { CCI_REG8(0x5d2f), 0x75 }, { CCI_REG8(0x5d30), 0x75 },
+ { CCI_REG8(0x5d31), 0x75 }, { CCI_REG8(0x5d32), 0x75 },
+ { CCI_REG8(0x5d33), 0x75 }, { CCI_REG8(0x5d34), 0x75 },
+ { CCI_REG8(0x5d35), 0x75 }, { CCI_REG8(0x5d36), 0x75 },
+ { CCI_REG8(0x5d37), 0x75 }, { CCI_REG8(0x5d38), 0x75 },
+ { CCI_REG8(0x5d39), 0x75 }, { CCI_REG8(0x5d3a), 0x75 },
+ { CCI_REG8(0x5d3b), 0x75 }, { CCI_REG8(0x5d3c), 0x75 },
+ { CCI_REG8(0x5d3d), 0x75 }, { CCI_REG8(0x5d3e), 0x75 },
+ { CCI_REG8(0x5d3f), 0x75 }, { CCI_REG8(0x5d40), 0x75 },
+ { CCI_REG8(0x5d41), 0x75 }, { CCI_REG8(0x5d42), 0x75 },
+ { CCI_REG8(0x5d43), 0x75 }, { CCI_REG8(0x5d44), 0x75 },
+ { CCI_REG8(0x5d45), 0x75 }, { CCI_REG8(0x5d46), 0x75 },
+ { CCI_REG8(0x5d47), 0x75 }, { CCI_REG8(0x5d48), 0x75 },
+ { CCI_REG8(0x5d49), 0x75 }, { CCI_REG8(0x5d4a), 0x75 },
+ { CCI_REG8(0x5d4b), 0x75 }, { CCI_REG8(0x5d4c), 0x75 },
+ { CCI_REG8(0x5d4d), 0x75 }, { CCI_REG8(0x5d4e), 0x75 },
+ { CCI_REG8(0x5d4f), 0x75 }, { CCI_REG8(0x5d50), 0x75 },
+ { CCI_REG8(0x5d51), 0x75 }, { CCI_REG8(0x5d52), 0x75 },
+ { CCI_REG8(0x5d53), 0x75 }, { CCI_REG8(0x5d54), 0x75 },
+ { CCI_REG8(0x5d55), 0x75 }, { CCI_REG8(0x5d56), 0x75 },
+ { CCI_REG8(0x5d57), 0x75 }, { CCI_REG8(0x5d58), 0x75 },
+ { CCI_REG8(0x5d59), 0x75 }, { CCI_REG8(0x5d5a), 0x75 },
+ { CCI_REG8(0x5d5b), 0x75 }, { CCI_REG8(0x5d5c), 0x75 },
+ { CCI_REG8(0x5d5d), 0x75 }, { CCI_REG8(0x5d5e), 0x75 },
+ { CCI_REG8(0x5d5f), 0x75 }, { CCI_REG8(0x5d60), 0x75 },
+ { CCI_REG8(0x5d61), 0x75 }, { CCI_REG8(0x5d62), 0x75 },
+ { CCI_REG8(0x5d63), 0x75 }, { CCI_REG8(0x5d64), 0x75 },
+ { CCI_REG8(0x5d65), 0x75 }, { CCI_REG8(0x5d66), 0x75 },
+ { CCI_REG8(0x5d67), 0x75 }, { CCI_REG8(0x5d68), 0x75 },
+ { CCI_REG8(0x5d69), 0x75 }, { CCI_REG8(0x5d6a), 0x75 },
+ { CCI_REG8(0x5d6b), 0x75 }, { CCI_REG8(0x5d6c), 0x75 },
+ { CCI_REG8(0x5d6d), 0x75 }, { CCI_REG8(0x5d6e), 0x75 },
+ { CCI_REG8(0x5d6f), 0x75 }, { CCI_REG8(0x5d70), 0x75 },
+ { CCI_REG8(0x5d71), 0x75 }, { CCI_REG8(0x5d72), 0x75 },
+ { CCI_REG8(0x5d73), 0x75 }, { CCI_REG8(0x5d74), 0x75 },
+ { CCI_REG8(0x5d75), 0x75 }, { CCI_REG8(0x5d76), 0x75 },
+ { CCI_REG8(0x5d77), 0x75 }, { CCI_REG8(0x5d78), 0x75 },
+ { CCI_REG8(0x5d79), 0x75 }, { CCI_REG8(0x5d7a), 0x75 },
+ { CCI_REG8(0x5d7b), 0x75 }, { CCI_REG8(0x5d7c), 0x75 },
+ { CCI_REG8(0x5d7d), 0x75 }, { CCI_REG8(0x5d7e), 0x75 },
+ { CCI_REG8(0x5d7f), 0x75 }, { CCI_REG8(0x5d80), 0x75 },
+ { CCI_REG8(0x5d81), 0x75 }, { CCI_REG8(0x5d82), 0x75 },
+ { CCI_REG8(0x5d83), 0x75 }, { CCI_REG8(0x5d84), 0x75 },
+ { CCI_REG8(0x5d85), 0x75 }, { CCI_REG8(0x5d86), 0x75 },
+ { CCI_REG8(0x5d87), 0x75 }, { CCI_REG8(0x5d88), 0x75 },
+ { CCI_REG8(0x5d89), 0x75 }, { CCI_REG8(0x5d8a), 0x75 },
+ { CCI_REG8(0x5d8b), 0x75 }, { CCI_REG8(0x5d8c), 0x75 },
+ { CCI_REG8(0x5d8d), 0x75 }, { CCI_REG8(0x5d8e), 0x75 },
+ { CCI_REG8(0x5d8f), 0x75 }, { CCI_REG8(0x5d90), 0x75 },
+ { CCI_REG8(0x5d91), 0x75 }, { CCI_REG8(0x5d92), 0x75 },
+ { CCI_REG8(0x5d93), 0x75 }, { CCI_REG8(0x5d94), 0x75 },
+ { CCI_REG8(0x5d95), 0x75 }, { CCI_REG8(0x5d96), 0x75 },
+ { CCI_REG8(0x5d97), 0x75 }, { CCI_REG8(0x5d98), 0x75 },
+ { CCI_REG8(0x5d99), 0x75 }, { CCI_REG8(0x5d9a), 0x75 },
+ { CCI_REG8(0x5d9b), 0x75 }, { CCI_REG8(0x5d9c), 0x75 },
+ { CCI_REG8(0x5d9d), 0x75 }, { CCI_REG8(0x5d9e), 0x75 },
+ { CCI_REG8(0x5d9f), 0x75 }, { CCI_REG8(0x5da0), 0x75 },
+ { CCI_REG8(0x5da1), 0x75 }, { CCI_REG8(0x5da2), 0x75 },
+ { CCI_REG8(0x5da3), 0x75 }, { CCI_REG8(0x5da4), 0x75 },
+ { CCI_REG8(0x5da5), 0x75 }, { CCI_REG8(0x5da6), 0x75 },
+ { CCI_REG8(0x5da7), 0x75 }, { CCI_REG8(0x5da8), 0x75 },
+ { CCI_REG8(0x5da9), 0x75 }, { CCI_REG8(0x5daa), 0x75 },
+ { CCI_REG8(0x5dab), 0x75 }, { CCI_REG8(0x5dac), 0x75 },
+ { CCI_REG8(0x5dad), 0x75 }, { CCI_REG8(0x5dae), 0x75 },
+ { CCI_REG8(0x5daf), 0x75 }, { CCI_REG8(0x5db0), 0x75 },
+ { CCI_REG8(0x5db1), 0x75 }, { CCI_REG8(0x5db2), 0x75 },
+ { CCI_REG8(0x5db3), 0x75 }, { CCI_REG8(0x5db4), 0x75 },
+ { CCI_REG8(0x5db5), 0x75 }, { CCI_REG8(0x5db6), 0x75 },
+ { CCI_REG8(0x5db7), 0x75 }, { CCI_REG8(0x5db8), 0x75 },
+ { CCI_REG8(0x5db9), 0x75 }, { CCI_REG8(0x5dba), 0x75 },
+ { CCI_REG8(0x5dbb), 0x75 }, { CCI_REG8(0x5dbc), 0x75 },
+ { CCI_REG8(0x5dbd), 0x75 }, { CCI_REG8(0x5dbe), 0x75 },
+ { CCI_REG8(0x5dbf), 0x75 }, { CCI_REG8(0x5dc0), 0x75 },
+ { CCI_REG8(0x5dc1), 0x75 }, { CCI_REG8(0x5dc2), 0x75 },
+ { CCI_REG8(0x5dc3), 0x75 }, { CCI_REG8(0x5dc4), 0x75 },
+ { CCI_REG8(0x5dc5), 0x75 }, { CCI_REG8(0x5dc6), 0x75 },
+ { CCI_REG8(0x5dc7), 0x75 }, { CCI_REG8(0x5dc8), 0x75 },
+ { CCI_REG8(0x5dc9), 0x75 }, { CCI_REG8(0x5dca), 0x75 },
+ { CCI_REG8(0x5dcb), 0x75 }, { CCI_REG8(0x5dcc), 0x75 },
+ { CCI_REG8(0x5dcd), 0x75 }, { CCI_REG8(0x5dce), 0x75 },
+ { CCI_REG8(0x5dcf), 0x75 }, { CCI_REG8(0x5dd0), 0x75 },
+ { CCI_REG8(0x5dd1), 0x75 }, { CCI_REG8(0x5dd2), 0x75 },
+ { CCI_REG8(0x5dd3), 0x75 }, { CCI_REG8(0x5dd4), 0x75 },
+ { CCI_REG8(0x5dd5), 0x75 }, { CCI_REG8(0x5dd6), 0x75 },
+ { CCI_REG8(0x5dd7), 0x75 }, { CCI_REG8(0x5dd8), 0x75 },
+ { CCI_REG8(0x5dd9), 0x75 }, { CCI_REG8(0x5dda), 0x75 },
+ { CCI_REG8(0x5ddb), 0x75 }, { CCI_REG8(0x5ddc), 0x75 },
+ { CCI_REG8(0x5ddd), 0x75 }, { CCI_REG8(0x5dde), 0x75 },
+ { CCI_REG8(0x5ddf), 0x75 }, { CCI_REG8(0x5de0), 0x75 },
+ { CCI_REG8(0x5de1), 0x75 }, { CCI_REG8(0x5de2), 0x75 },
+ { CCI_REG8(0x5de3), 0x75 }, { CCI_REG8(0x5de4), 0x75 },
+ { CCI_REG8(0x5de5), 0x75 }, { CCI_REG8(0x5de6), 0x75 },
+ { CCI_REG8(0x5de7), 0x75 }, { CCI_REG8(0x5de8), 0x75 },
+ { CCI_REG8(0x5de9), 0x75 }, { CCI_REG8(0x5dea), 0x75 },
+ { CCI_REG8(0x5deb), 0x75 }, { CCI_REG8(0x5dec), 0x75 },
+ { CCI_REG8(0x5ded), 0x75 }, { CCI_REG8(0x5dee), 0x75 },
+ { CCI_REG8(0x5def), 0x75 }, { CCI_REG8(0x5df0), 0x75 },
+ { CCI_REG8(0x5df1), 0x75 }, { CCI_REG8(0x5df2), 0x75 },
+ { CCI_REG8(0x5df3), 0x75 }, { CCI_REG8(0x5df4), 0x75 },
+ { CCI_REG8(0x5df5), 0x75 }, { CCI_REG8(0x5df6), 0x75 },
+ { CCI_REG8(0x5df7), 0x75 }, { CCI_REG8(0x5df8), 0x75 },
+ { CCI_REG8(0x5df9), 0x75 }, { CCI_REG8(0x5dfa), 0x75 },
+ { CCI_REG8(0x5dfb), 0x75 }, { CCI_REG8(0x5dfc), 0x75 },
+ { CCI_REG8(0x5dfd), 0x75 }, { CCI_REG8(0x5dfe), 0x75 },
+ { CCI_REG8(0x5dff), 0x75 }, { CCI_REG8(0x5e00), 0x75 },
+ { CCI_REG8(0x5e01), 0x75 }, { CCI_REG8(0x5e02), 0x75 },
+ { CCI_REG8(0x5e03), 0x75 }, { CCI_REG8(0x5e04), 0x75 },
+ { CCI_REG8(0x5e05), 0x75 }, { CCI_REG8(0x5e06), 0x75 },
+ { CCI_REG8(0x5e07), 0x75 }, { CCI_REG8(0x5e08), 0x75 },
+ { CCI_REG8(0x5e09), 0x75 }, { CCI_REG8(0x5e0a), 0x75 },
+ { CCI_REG8(0x5e0b), 0x75 }, { CCI_REG8(0x5e0c), 0x75 },
+ { CCI_REG8(0x5e0d), 0x75 }, { CCI_REG8(0x5e0e), 0x75 },
+ { CCI_REG8(0x5e0f), 0x75 }, { CCI_REG8(0x5e10), 0x75 },
+ { CCI_REG8(0x5e11), 0x75 }, { CCI_REG8(0x5e12), 0x75 },
+ { CCI_REG8(0x5e13), 0x75 }, { CCI_REG8(0x5e14), 0x75 },
+ { CCI_REG8(0x5e15), 0x75 }, { CCI_REG8(0x5e16), 0x75 },
+ { CCI_REG8(0x5e17), 0x75 }, { CCI_REG8(0x5e18), 0x75 },
+ { CCI_REG8(0x5e19), 0x75 }, { CCI_REG8(0x5e1a), 0x75 },
+ { CCI_REG8(0x5e1b), 0x75 }, { CCI_REG8(0x5e1c), 0x75 },
+ { CCI_REG8(0x5e1d), 0x75 }, { CCI_REG8(0x5e1e), 0x75 },
+ { CCI_REG8(0x5e1f), 0x75 }, { CCI_REG8(0x5e20), 0x75 },
+ { CCI_REG8(0x5e21), 0x75 }, { CCI_REG8(0x5e22), 0x75 },
+ { CCI_REG8(0x5e23), 0x75 }, { CCI_REG8(0x5e24), 0x75 },
+ { CCI_REG8(0x5e25), 0x75 }, { CCI_REG8(0x5e26), 0x75 },
+ { CCI_REG8(0x5e27), 0x75 }, { CCI_REG8(0x5e28), 0x75 },
+ { CCI_REG8(0x5e29), 0x75 }, { CCI_REG8(0x5e2a), 0x75 },
+ { CCI_REG8(0x5e2b), 0x75 }, { CCI_REG8(0x5e2c), 0x75 },
+ { CCI_REG8(0x5e2d), 0x75 }, { CCI_REG8(0x5e2e), 0x75 },
+ { CCI_REG8(0x5e2f), 0x75 }, { CCI_REG8(0x5e30), 0x75 },
+ { CCI_REG8(0x5e31), 0x75 }, { CCI_REG8(0x5e32), 0x75 },
+ { CCI_REG8(0x5e33), 0x75 }, { CCI_REG8(0x5e34), 0x75 },
+ { CCI_REG8(0x5e35), 0x75 }, { CCI_REG8(0x5e36), 0x75 },
+ { CCI_REG8(0x5e37), 0x75 }, { CCI_REG8(0x5e38), 0x75 },
+ { CCI_REG8(0x5e39), 0x75 }, { CCI_REG8(0x5e3a), 0x75 },
+ { CCI_REG8(0x5e3b), 0x75 }, { CCI_REG8(0x5e3c), 0x75 },
+ { CCI_REG8(0x5e3d), 0x75 }, { CCI_REG8(0x5e3e), 0x75 },
+ { CCI_REG8(0x5e3f), 0x75 }, { CCI_REG8(0x5e40), 0x75 },
+ { CCI_REG8(0x5e41), 0x75 }, { CCI_REG8(0x5e42), 0x75 },
+ { CCI_REG8(0x5e43), 0x75 }, { CCI_REG8(0x5e44), 0x75 },
+ { CCI_REG8(0x5e45), 0x75 }, { CCI_REG8(0x5e46), 0x75 },
+ { CCI_REG8(0x5e47), 0x75 }, { CCI_REG8(0x5e48), 0x75 },
+ { CCI_REG8(0x5e49), 0x75 }, { CCI_REG8(0x5e4a), 0x75 },
+ { CCI_REG8(0x5e4b), 0x75 }, { CCI_REG8(0x5e4c), 0x75 },
+ { CCI_REG8(0x5e4d), 0x75 }, { CCI_REG8(0x5e4e), 0x75 },
+ { CCI_REG8(0x5e4f), 0x75 }, { CCI_REG8(0x5e50), 0x75 },
+ { CCI_REG8(0x5e51), 0x75 }, { CCI_REG8(0x5e52), 0x75 },
+ { CCI_REG8(0x5e53), 0x75 }, { CCI_REG8(0x5e54), 0x75 },
+ { CCI_REG8(0x5e55), 0x75 }, { CCI_REG8(0x5e56), 0x75 },
+ { CCI_REG8(0x5e57), 0x75 }, { CCI_REG8(0x5e58), 0x75 },
+ { CCI_REG8(0x5e59), 0x75 }, { CCI_REG8(0x5e5a), 0x75 },
+ { CCI_REG8(0x5e5b), 0x75 }, { CCI_REG8(0x5e5c), 0x75 },
+ { CCI_REG8(0x5e5d), 0x75 }, { CCI_REG8(0x5e5e), 0x75 },
+ { CCI_REG8(0x5e5f), 0x75 }, { CCI_REG8(0x5e60), 0x75 },
+ { CCI_REG8(0x5e61), 0x75 }, { CCI_REG8(0x5e62), 0x75 },
+ { CCI_REG8(0x5e63), 0x75 }, { CCI_REG8(0x5e64), 0x75 },
+ { CCI_REG8(0x5e65), 0x75 }, { CCI_REG8(0x5e66), 0x75 },
+ { CCI_REG8(0x5e67), 0x75 }, { CCI_REG8(0x5e68), 0x75 },
+ { CCI_REG8(0x5e69), 0x75 }, { CCI_REG8(0x5e6a), 0x75 },
+ { CCI_REG8(0x5e6b), 0x75 }, { CCI_REG8(0x5e6c), 0x75 },
+ { CCI_REG8(0x5e6d), 0x75 }, { CCI_REG8(0x5e6e), 0x75 },
+ { CCI_REG8(0x5e6f), 0x75 }, { CCI_REG8(0x5e70), 0x75 },
+ { CCI_REG8(0x5e71), 0x75 }, { CCI_REG8(0x5e72), 0x75 },
+ { CCI_REG8(0x5e73), 0x75 }, { CCI_REG8(0x5e74), 0x75 },
+ { CCI_REG8(0x5e75), 0x75 }, { CCI_REG8(0x5e76), 0x75 },
+ { CCI_REG8(0x5e77), 0x75 }, { CCI_REG8(0x5e78), 0x75 },
+ { CCI_REG8(0x5e79), 0x75 }, { CCI_REG8(0x5e7a), 0x75 },
+ { CCI_REG8(0x5e7b), 0x75 }, { CCI_REG8(0x5e7c), 0x75 },
+ { CCI_REG8(0x5e7d), 0x75 }, { CCI_REG8(0x5e7e), 0x75 },
+ { CCI_REG8(0x5e7f), 0x75 }, { CCI_REG8(0x5e80), 0x75 },
+ { CCI_REG8(0x5e81), 0x75 }, { CCI_REG8(0x5e82), 0x75 },
+ { CCI_REG8(0x5e83), 0x75 }, { CCI_REG8(0x5e84), 0x75 },
+ { CCI_REG8(0x5e85), 0x75 }, { CCI_REG8(0x5e86), 0x75 },
+ { CCI_REG8(0x5e87), 0x75 }, { CCI_REG8(0x5e88), 0x75 },
+ { CCI_REG8(0x5e89), 0x75 }, { CCI_REG8(0x5e8a), 0x75 },
+ { CCI_REG8(0x5e8b), 0x75 }, { CCI_REG8(0x5e8c), 0x75 },
+ { CCI_REG8(0x5e8d), 0x75 }, { CCI_REG8(0x5e8e), 0x75 },
+ { CCI_REG8(0x5e8f), 0x75 }, { CCI_REG8(0x5e90), 0x75 },
+ { CCI_REG8(0x5e91), 0x75 }, { CCI_REG8(0x5e92), 0x75 },
+ { CCI_REG8(0x5e93), 0x75 }, { CCI_REG8(0x5e94), 0x75 },
+ { CCI_REG8(0x5e95), 0x75 }, { CCI_REG8(0x5e96), 0x75 },
+ { CCI_REG8(0x5e97), 0x75 }, { CCI_REG8(0x5e98), 0x75 },
+ { CCI_REG8(0x5e99), 0x75 }, { CCI_REG8(0x5e9a), 0x75 },
+ { CCI_REG8(0x5e9b), 0x75 }, { CCI_REG8(0x5e9c), 0x75 },
+ { CCI_REG8(0x5e9d), 0x75 }, { CCI_REG8(0x5e9e), 0x75 },
+ { CCI_REG8(0x5e9f), 0x75 }, { CCI_REG8(0x5ea0), 0x75 },
+ { CCI_REG8(0x5ea1), 0x75 }, { CCI_REG8(0x5ea2), 0x75 },
+ { CCI_REG8(0x5ea3), 0x75 }, { CCI_REG8(0x5ea4), 0x75 },
+ { CCI_REG8(0x5ea5), 0x75 }, { CCI_REG8(0x5ea6), 0x75 },
+ { CCI_REG8(0x5ea7), 0x75 }, { CCI_REG8(0x5ea8), 0x75 },
+ { CCI_REG8(0x5ea9), 0x75 }, { CCI_REG8(0x5eaa), 0x75 },
+ { CCI_REG8(0x5eab), 0x75 }, { CCI_REG8(0x5eac), 0x75 },
+ { CCI_REG8(0x5ead), 0x75 }, { CCI_REG8(0x5eae), 0x75 },
+ { CCI_REG8(0x5eaf), 0x75 }, { CCI_REG8(0x5eb0), 0x75 },
+ { CCI_REG8(0x5eb1), 0x75 }, { CCI_REG8(0x5eb2), 0x75 },
+ { CCI_REG8(0x5eb3), 0x75 }, { CCI_REG8(0x5eb4), 0x75 },
+ { CCI_REG8(0x5eb5), 0x75 }, { CCI_REG8(0x5eb6), 0x75 },
+ { CCI_REG8(0x5eb7), 0x75 }, { CCI_REG8(0x5eb8), 0x75 },
+ { CCI_REG8(0x5eb9), 0x75 }, { CCI_REG8(0x5eba), 0x75 },
+ { CCI_REG8(0x5ebb), 0x75 }, { CCI_REG8(0x5ebc), 0x75 },
+ { CCI_REG8(0x5ebd), 0x75 }, { CCI_REG8(0x5ebe), 0x75 },
+ { CCI_REG8(0x5ebf), 0x75 }, { CCI_REG8(0x5ec0), 0x75 },
+ { CCI_REG8(0x5ec1), 0x75 }, { CCI_REG8(0x5ec2), 0x75 },
+ { CCI_REG8(0x5ec3), 0x75 }, { CCI_REG8(0x5ec4), 0x75 },
+ { CCI_REG8(0x5ec5), 0x75 }, { CCI_REG8(0x5ec6), 0x75 },
+ { CCI_REG8(0x5ec7), 0x75 }, { CCI_REG8(0x5ec8), 0x75 },
+ { CCI_REG8(0x5ec9), 0x75 }, { CCI_REG8(0x5eca), 0x75 },
+ { CCI_REG8(0x5ecb), 0x75 }, { CCI_REG8(0x5ecc), 0x75 },
+ { CCI_REG8(0x5ecd), 0x75 }, { CCI_REG8(0x5ece), 0x75 },
+ { CCI_REG8(0x5ecf), 0x75 }, { CCI_REG8(0x5ed0), 0x75 },
+ { CCI_REG8(0x5ed1), 0x75 }, { CCI_REG8(0x5ed2), 0x75 },
+ { CCI_REG8(0x5ed3), 0x75 }, { CCI_REG8(0x5ed4), 0x75 },
+ { CCI_REG8(0x5ed5), 0x75 }, { CCI_REG8(0x5ed6), 0x75 },
+ { CCI_REG8(0x5ed7), 0x75 }, { CCI_REG8(0x5ed8), 0x75 },
+ { CCI_REG8(0x5ed9), 0x75 }, { CCI_REG8(0x5eda), 0x75 },
+ { CCI_REG8(0x5edb), 0x75 }, { CCI_REG8(0x5edc), 0x75 },
+ { CCI_REG8(0x5edd), 0x75 }, { CCI_REG8(0x5ede), 0x75 },
+ { CCI_REG8(0x5edf), 0x75 }, { CCI_REG8(0xfff9), 0x08 },
+ { CCI_REG8(0x1570), 0x00 }, { CCI_REG8(0x15d0), 0x00 },
+ { CCI_REG8(0x15a0), 0x02 }, { CCI_REG8(0x15a1), 0x00 },
+ { CCI_REG8(0x15a2), 0x02 }, { CCI_REG8(0x15a3), 0x76 },
+ { CCI_REG8(0x15a4), 0x03 }, { CCI_REG8(0x15a5), 0x08 },
+ { CCI_REG8(0x15a6), 0x00 }, { CCI_REG8(0x15a7), 0x60 },
+ { CCI_REG8(0x15a8), 0x01 }, { CCI_REG8(0x15a9), 0x00 },
+ { CCI_REG8(0x15aa), 0x02 }, { CCI_REG8(0x15ab), 0x00 },
+ { CCI_REG8(0x1600), 0x02 }, { CCI_REG8(0x1601), 0x00 },
+ { CCI_REG8(0x1602), 0x02 }, { CCI_REG8(0x1603), 0x76 },
+ { CCI_REG8(0x1604), 0x03 }, { CCI_REG8(0x1605), 0x08 },
+ { CCI_REG8(0x1606), 0x00 }, { CCI_REG8(0x1607), 0x60 },
+ { CCI_REG8(0x1608), 0x01 }, { CCI_REG8(0x1609), 0x00 },
+ { CCI_REG8(0x160a), 0x02 }, { CCI_REG8(0x160b), 0x00 },
+ { CCI_REG8(0x1633), 0x03 }, { CCI_REG8(0x1634), 0x01 },
+ { CCI_REG8(0x163c), 0x3a }, { CCI_REG8(0x163d), 0x01 },
+ { CCI_REG8(0x1648), 0x32 }, { CCI_REG8(0x1658), 0x01 },
+ { CCI_REG8(0x1659), 0x01 }, { CCI_REG8(0x165f), 0x01 },
+ { CCI_REG8(0x1677), 0x01 }, { CCI_REG8(0x1690), 0x08 },
+ { CCI_REG8(0x1691), 0x00 }, { CCI_REG8(0x1692), 0x20 },
+ { CCI_REG8(0x1693), 0x00 }, { CCI_REG8(0x1694), 0x10 },
+ { CCI_REG8(0x1695), 0x14 }, { CCI_REG8(0x1696), 0x10 },
+ { CCI_REG8(0x1697), 0x0e }, { CCI_REG8(0x1730), 0x01 },
+ { CCI_REG8(0x1732), 0x00 }, { CCI_REG8(0x1733), 0x10 },
+ { CCI_REG8(0x1734), 0x01 }, { CCI_REG8(0x1735), 0x00 },
+ { CCI_REG8(0x1748), 0x01 }, { CCI_REG8(0xfff9), 0x06 },
+ { CCI_REG8(0x5000), 0xff }, { CCI_REG8(0x5001), 0x3d },
+ { CCI_REG8(0x5002), 0xf5 }, { CCI_REG8(0x5004), 0x80 },
+ { CCI_REG8(0x5006), 0x04 }, { CCI_REG8(0x5061), 0x20 },
+ { CCI_REG8(0x5063), 0x20 }, { CCI_REG8(0x5064), 0x24 },
+ { CCI_REG8(0x5065), 0x00 }, { CCI_REG8(0x5066), 0x1b },
+ { CCI_REG8(0x5067), 0x00 }, { CCI_REG8(0x5068), 0x03 },
+ { CCI_REG8(0x5069), 0x10 }, { CCI_REG8(0x506a), 0x20 },
+ { CCI_REG8(0x506b), 0x04 }, { CCI_REG8(0x506c), 0x04 },
+ { CCI_REG8(0x506d), 0x0c }, { CCI_REG8(0x506e), 0x0c },
+ { CCI_REG8(0x506f), 0x04 }, { CCI_REG8(0x5070), 0x0c },
+ { CCI_REG8(0x5071), 0x14 }, { CCI_REG8(0x5072), 0x1c },
+ { CCI_REG8(0x5073), 0x01 }, { CCI_REG8(0x5074), 0x01 },
+ { CCI_REG8(0x5075), 0xbe }, { CCI_REG8(0x5083), 0x00 },
+ { CCI_REG8(0x5114), 0x03 }, { CCI_REG8(0x51b0), 0x00 },
+ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x02 },
+ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 },
+ { CCI_REG8(0x51b8), 0x00 }, { CCI_REG8(0x51b9), 0x70 },
+ { CCI_REG8(0x51ba), 0x00 }, { CCI_REG8(0x51bb), 0x10 },
+ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 },
+ { CCI_REG8(0x51d2), 0xff }, { CCI_REG8(0x51d3), 0x1c },
+ { CCI_REG8(0x5250), 0x34 }, { CCI_REG8(0x5251), 0x00 },
+ { CCI_REG8(0x525b), 0x00 }, { CCI_REG8(0x525d), 0x00 },
+ { CCI_REG8(0x527a), 0x00 }, { CCI_REG8(0x527b), 0x38 },
+ { CCI_REG8(0x527c), 0x00 }, { CCI_REG8(0x527d), 0x4b },
+ { CCI_REG8(0x5286), 0x1b }, { CCI_REG8(0x5287), 0x40 },
+ { CCI_REG8(0x5290), 0x00 }, { CCI_REG8(0x5291), 0x50 },
+ { CCI_REG8(0x5292), 0x00 }, { CCI_REG8(0x5293), 0x50 },
+ { CCI_REG8(0x5294), 0x00 }, { CCI_REG8(0x5295), 0x50 },
+ { CCI_REG8(0x5296), 0x00 }, { CCI_REG8(0x5297), 0x50 },
+ { CCI_REG8(0x5298), 0x00 }, { CCI_REG8(0x5299), 0x50 },
+ { CCI_REG8(0x529a), 0x01 }, { CCI_REG8(0x529b), 0x00 },
+ { CCI_REG8(0x529c), 0x01 }, { CCI_REG8(0x529d), 0x00 },
+ { CCI_REG8(0x529e), 0x00 }, { CCI_REG8(0x529f), 0x50 },
+ { CCI_REG8(0x52a0), 0x00 }, { CCI_REG8(0x52a1), 0x50 },
+ { CCI_REG8(0x52a2), 0x01 }, { CCI_REG8(0x52a3), 0x00 },
+ { CCI_REG8(0x52a4), 0x01 }, { CCI_REG8(0x52a5), 0x00 },
+ { CCI_REG8(0x52a6), 0x00 }, { CCI_REG8(0x52a7), 0x50 },
+ { CCI_REG8(0x52a8), 0x00 }, { CCI_REG8(0x52a9), 0x50 },
+ { CCI_REG8(0x52aa), 0x00 }, { CCI_REG8(0x52ab), 0x50 },
+ { CCI_REG8(0x52ac), 0x00 }, { CCI_REG8(0x52ad), 0x50 },
+ { CCI_REG8(0x52ae), 0x00 }, { CCI_REG8(0x52af), 0x50 },
+ { CCI_REG8(0x52b0), 0x00 }, { CCI_REG8(0x52b1), 0x50 },
+ { CCI_REG8(0x52b2), 0x00 }, { CCI_REG8(0x52b3), 0x50 },
+ { CCI_REG8(0x52b4), 0x00 }, { CCI_REG8(0x52b5), 0x50 },
+ { CCI_REG8(0x52b6), 0x00 }, { CCI_REG8(0x52b7), 0x50 },
+ { CCI_REG8(0x52b8), 0x00 }, { CCI_REG8(0x52b9), 0x50 },
+ { CCI_REG8(0x52ba), 0x01 }, { CCI_REG8(0x52bb), 0x00 },
+ { CCI_REG8(0x52bc), 0x01 }, { CCI_REG8(0x52bd), 0x00 },
+ { CCI_REG8(0x52be), 0x00 }, { CCI_REG8(0x52bf), 0x50 },
+ { CCI_REG8(0x52c0), 0x00 }, { CCI_REG8(0x52c1), 0x50 },
+ { CCI_REG8(0x52c2), 0x01 }, { CCI_REG8(0x52c3), 0x00 },
+ { CCI_REG8(0x52c4), 0x01 }, { CCI_REG8(0x52c5), 0x00 },
+ { CCI_REG8(0x52c6), 0x00 }, { CCI_REG8(0x52c7), 0x50 },
+ { CCI_REG8(0x52c8), 0x00 }, { CCI_REG8(0x52c9), 0x50 },
+ { CCI_REG8(0x52ca), 0x00 }, { CCI_REG8(0x52cb), 0x50 },
+ { CCI_REG8(0x52cc), 0x00 }, { CCI_REG8(0x52cd), 0x50 },
+ { CCI_REG8(0x52ce), 0x00 }, { CCI_REG8(0x52cf), 0x50 },
+ { CCI_REG8(0x52f0), 0x04 }, { CCI_REG8(0x52f1), 0x03 },
+ { CCI_REG8(0x52f2), 0x02 }, { CCI_REG8(0x52f3), 0x01 },
+ { CCI_REG8(0x52f4), 0x08 }, { CCI_REG8(0x52f5), 0x07 },
+ { CCI_REG8(0x52f6), 0x06 }, { CCI_REG8(0x52f7), 0x05 },
+ { CCI_REG8(0x52f8), 0x0c }, { CCI_REG8(0x52f9), 0x0b },
+ { CCI_REG8(0x52fa), 0x0a }, { CCI_REG8(0x52fb), 0x09 },
+ { CCI_REG8(0x52fc), 0x10 }, { CCI_REG8(0x52fd), 0x0f },
+ { CCI_REG8(0x52fe), 0x0e }, { CCI_REG8(0x52ff), 0x0d },
+ { CCI_REG8(0x5300), 0x14 }, { CCI_REG8(0x5301), 0x13 },
+ { CCI_REG8(0x5302), 0x12 }, { CCI_REG8(0x5303), 0x11 },
+ { CCI_REG8(0x5304), 0x18 }, { CCI_REG8(0x5305), 0x17 },
+ { CCI_REG8(0x5306), 0x16 }, { CCI_REG8(0x5307), 0x15 },
+ { CCI_REG8(0x5308), 0x1c }, { CCI_REG8(0x5309), 0x1b },
+ { CCI_REG8(0x530a), 0x1a }, { CCI_REG8(0x530b), 0x19 },
+ { CCI_REG8(0x530c), 0x20 }, { CCI_REG8(0x530d), 0x1f },
+ { CCI_REG8(0x530e), 0x1e }, { CCI_REG8(0x530f), 0x1d },
+ { CCI_REG8(0x5310), 0x03 }, { CCI_REG8(0x5311), 0xe8 },
+ { CCI_REG8(0x5331), 0x0a }, { CCI_REG8(0x5332), 0x43 },
+ { CCI_REG8(0x5333), 0x45 }, { CCI_REG8(0x5353), 0x09 },
+ { CCI_REG8(0x5354), 0x00 }, { CCI_REG8(0x5414), 0x03 },
+ { CCI_REG8(0x54b0), 0x10 }, { CCI_REG8(0x54b3), 0x0e },
+ { CCI_REG8(0x54b5), 0x02 }, { CCI_REG8(0x54b6), 0x00 },
+ { CCI_REG8(0x54b7), 0x00 }, { CCI_REG8(0x54b8), 0x00 },
+ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54ba), 0x00 },
+ { CCI_REG8(0x54bb), 0x10 }, { CCI_REG8(0x54bc), 0x00 },
+ { CCI_REG8(0x54bd), 0x00 }, { CCI_REG8(0x54d2), 0xff },
+ { CCI_REG8(0x54d3), 0x1c }, { CCI_REG8(0x5510), 0x03 },
+ { CCI_REG8(0x5511), 0xe8 }, { CCI_REG8(0x5550), 0x6c },
+ { CCI_REG8(0x5551), 0x00 }, { CCI_REG8(0x557a), 0x00 },
+ { CCI_REG8(0x557b), 0x38 }, { CCI_REG8(0x557c), 0x00 },
+ { CCI_REG8(0x557d), 0x4b }, { CCI_REG8(0x5590), 0x00 },
+ { CCI_REG8(0x5591), 0x50 }, { CCI_REG8(0x5592), 0x00 },
+ { CCI_REG8(0x5593), 0x50 }, { CCI_REG8(0x5594), 0x00 },
+ { CCI_REG8(0x5595), 0x50 }, { CCI_REG8(0x5596), 0x00 },
+ { CCI_REG8(0x5597), 0x50 }, { CCI_REG8(0x5598), 0x00 },
+ { CCI_REG8(0x5599), 0x50 }, { CCI_REG8(0x559a), 0x01 },
+ { CCI_REG8(0x559b), 0x00 }, { CCI_REG8(0x559c), 0x01 },
+ { CCI_REG8(0x559d), 0x00 }, { CCI_REG8(0x559e), 0x00 },
+ { CCI_REG8(0x559f), 0x50 }, { CCI_REG8(0x55a0), 0x00 },
+ { CCI_REG8(0x55a1), 0x50 }, { CCI_REG8(0x55a2), 0x01 },
+ { CCI_REG8(0x55a3), 0x00 }, { CCI_REG8(0x55a4), 0x01 },
+ { CCI_REG8(0x55a5), 0x00 }, { CCI_REG8(0x55a6), 0x00 },
+ { CCI_REG8(0x55a7), 0x50 }, { CCI_REG8(0x55a8), 0x00 },
+ { CCI_REG8(0x55a9), 0x50 }, { CCI_REG8(0x55aa), 0x00 },
+ { CCI_REG8(0x55ab), 0x50 }, { CCI_REG8(0x55ac), 0x00 },
+ { CCI_REG8(0x55ad), 0x50 }, { CCI_REG8(0x55ae), 0x00 },
+ { CCI_REG8(0x55af), 0x50 }, { CCI_REG8(0x55b0), 0x00 },
+ { CCI_REG8(0x55b1), 0x50 }, { CCI_REG8(0x55b2), 0x00 },
+ { CCI_REG8(0x55b3), 0x50 }, { CCI_REG8(0x55b4), 0x00 },
+ { CCI_REG8(0x55b5), 0x50 }, { CCI_REG8(0x55b6), 0x00 },
+ { CCI_REG8(0x55b7), 0x50 }, { CCI_REG8(0x55b8), 0x00 },
+ { CCI_REG8(0x55b9), 0x50 }, { CCI_REG8(0x55ba), 0x01 },
+ { CCI_REG8(0x55bb), 0x00 }, { CCI_REG8(0x55bc), 0x01 },
+ { CCI_REG8(0x55bd), 0x00 }, { CCI_REG8(0x55be), 0x00 },
+ { CCI_REG8(0x55bf), 0x50 }, { CCI_REG8(0x55c0), 0x00 },
+ { CCI_REG8(0x55c1), 0x50 }, { CCI_REG8(0x55c2), 0x01 },
+ { CCI_REG8(0x55c3), 0x00 }, { CCI_REG8(0x55c4), 0x01 },
+ { CCI_REG8(0x55c5), 0x00 }, { CCI_REG8(0x55c6), 0x00 },
+ { CCI_REG8(0x55c7), 0x50 }, { CCI_REG8(0x55c8), 0x00 },
+ { CCI_REG8(0x55c9), 0x50 }, { CCI_REG8(0x55ca), 0x00 },
+ { CCI_REG8(0x55cb), 0x50 }, { CCI_REG8(0x55cc), 0x00 },
+ { CCI_REG8(0x55cd), 0x50 }, { CCI_REG8(0x55ce), 0x00 },
+ { CCI_REG8(0x55cf), 0x50 }, { CCI_REG8(0x55f0), 0x04 },
+ { CCI_REG8(0x55f1), 0x03 }, { CCI_REG8(0x55f2), 0x02 },
+ { CCI_REG8(0x55f3), 0x01 }, { CCI_REG8(0x55f4), 0x08 },
+ { CCI_REG8(0x55f5), 0x07 }, { CCI_REG8(0x55f6), 0x06 },
+ { CCI_REG8(0x55f7), 0x05 }, { CCI_REG8(0x55f8), 0x0c },
+ { CCI_REG8(0x55f9), 0x0b }, { CCI_REG8(0x55fa), 0x0a },
+ { CCI_REG8(0x55fb), 0x09 }, { CCI_REG8(0x55fc), 0x10 },
+ { CCI_REG8(0x55fd), 0x0f }, { CCI_REG8(0x55fe), 0x0e },
+ { CCI_REG8(0x55ff), 0x0d }, { CCI_REG8(0x5600), 0x14 },
+ { CCI_REG8(0x5601), 0x13 }, { CCI_REG8(0x5602), 0x12 },
+ { CCI_REG8(0x5603), 0x11 }, { CCI_REG8(0x5604), 0x18 },
+ { CCI_REG8(0x5605), 0x17 }, { CCI_REG8(0x5606), 0x16 },
+ { CCI_REG8(0x5607), 0x15 }, { CCI_REG8(0x5608), 0x1c },
+ { CCI_REG8(0x5609), 0x1b }, { CCI_REG8(0x560a), 0x1a },
+ { CCI_REG8(0x560b), 0x19 }, { CCI_REG8(0x560c), 0x20 },
+ { CCI_REG8(0x560d), 0x1f }, { CCI_REG8(0x560e), 0x1e },
+ { CCI_REG8(0x560f), 0x1d }, { CCI_REG8(0x5631), 0x02 },
+ { CCI_REG8(0x5632), 0x42 }, { CCI_REG8(0x5633), 0x24 },
+ { CCI_REG8(0x5653), 0x09 }, { CCI_REG8(0x5654), 0x00 },
+ { CCI_REG8(0x5714), 0x03 }, { CCI_REG8(0x57b0), 0x10 },
+ { CCI_REG8(0x57b3), 0x0e }, { CCI_REG8(0x57b5), 0x02 },
+ { CCI_REG8(0x57b6), 0x00 }, { CCI_REG8(0x57b7), 0x00 },
+ { CCI_REG8(0x57b8), 0x00 }, { CCI_REG8(0x57b9), 0x70 },
+ { CCI_REG8(0x57ba), 0x00 }, { CCI_REG8(0x57bb), 0x10 },
+ { CCI_REG8(0x57bc), 0x00 }, { CCI_REG8(0x57bd), 0x00 },
+ { CCI_REG8(0x57d2), 0xff }, { CCI_REG8(0x57d3), 0x1c },
+ { CCI_REG8(0x5810), 0x03 }, { CCI_REG8(0x5811), 0xe8 },
+ { CCI_REG8(0x5850), 0x6c }, { CCI_REG8(0x5851), 0x00 },
+ { CCI_REG8(0x587a), 0x00 }, { CCI_REG8(0x587b), 0x38 },
+ { CCI_REG8(0x587c), 0x00 }, { CCI_REG8(0x587d), 0x4b },
+ { CCI_REG8(0x5890), 0x00 }, { CCI_REG8(0x5891), 0x50 },
+ { CCI_REG8(0x5892), 0x00 }, { CCI_REG8(0x5893), 0x50 },
+ { CCI_REG8(0x5894), 0x00 }, { CCI_REG8(0x5895), 0x50 },
+ { CCI_REG8(0x5896), 0x00 }, { CCI_REG8(0x5897), 0x50 },
+ { CCI_REG8(0x5898), 0x00 }, { CCI_REG8(0x5899), 0x50 },
+ { CCI_REG8(0x589a), 0x01 }, { CCI_REG8(0x589b), 0x00 },
+ { CCI_REG8(0x589c), 0x01 }, { CCI_REG8(0x589d), 0x00 },
+ { CCI_REG8(0x589e), 0x00 }, { CCI_REG8(0x589f), 0x50 },
+ { CCI_REG8(0x58a0), 0x00 }, { CCI_REG8(0x58a1), 0x50 },
+ { CCI_REG8(0x58a2), 0x01 }, { CCI_REG8(0x58a3), 0x00 },
+ { CCI_REG8(0x58a4), 0x01 }, { CCI_REG8(0x58a5), 0x00 },
+ { CCI_REG8(0x58a6), 0x00 }, { CCI_REG8(0x58a7), 0x50 },
+ { CCI_REG8(0x58a8), 0x00 }, { CCI_REG8(0x58a9), 0x50 },
+ { CCI_REG8(0x58aa), 0x00 }, { CCI_REG8(0x58ab), 0x50 },
+ { CCI_REG8(0x58ac), 0x00 }, { CCI_REG8(0x58ad), 0x50 },
+ { CCI_REG8(0x58ae), 0x00 }, { CCI_REG8(0x58af), 0x50 },
+ { CCI_REG8(0x58b0), 0x00 }, { CCI_REG8(0x58b1), 0x50 },
+ { CCI_REG8(0x58b2), 0x00 }, { CCI_REG8(0x58b3), 0x50 },
+ { CCI_REG8(0x58b4), 0x00 }, { CCI_REG8(0x58b5), 0x50 },
+ { CCI_REG8(0x58b6), 0x00 }, { CCI_REG8(0x58b7), 0x50 },
+ { CCI_REG8(0x58b8), 0x00 }, { CCI_REG8(0x58b9), 0x50 },
+ { CCI_REG8(0x58ba), 0x01 }, { CCI_REG8(0x58bb), 0x00 },
+ { CCI_REG8(0x58bc), 0x01 }, { CCI_REG8(0x58bd), 0x00 },
+ { CCI_REG8(0x58be), 0x00 }, { CCI_REG8(0x58bf), 0x50 },
+ { CCI_REG8(0x58c0), 0x00 }, { CCI_REG8(0x58c1), 0x50 },
+ { CCI_REG8(0x58c2), 0x01 }, { CCI_REG8(0x58c3), 0x00 },
+ { CCI_REG8(0x58c4), 0x01 }, { CCI_REG8(0x58c5), 0x00 },
+ { CCI_REG8(0x58c6), 0x00 }, { CCI_REG8(0x58c7), 0x50 },
+ { CCI_REG8(0x58c8), 0x00 }, { CCI_REG8(0x58c9), 0x50 },
+ { CCI_REG8(0x58ca), 0x00 }, { CCI_REG8(0x58cb), 0x50 },
+ { CCI_REG8(0x58cc), 0x00 }, { CCI_REG8(0x58cd), 0x50 },
+ { CCI_REG8(0x58ce), 0x00 }, { CCI_REG8(0x58cf), 0x50 },
+ { CCI_REG8(0x58f0), 0x04 }, { CCI_REG8(0x58f1), 0x03 },
+ { CCI_REG8(0x58f2), 0x02 }, { CCI_REG8(0x58f3), 0x01 },
+ { CCI_REG8(0x58f4), 0x08 }, { CCI_REG8(0x58f5), 0x07 },
+ { CCI_REG8(0x58f6), 0x06 }, { CCI_REG8(0x58f7), 0x05 },
+ { CCI_REG8(0x58f8), 0x0c }, { CCI_REG8(0x58f9), 0x0b },
+ { CCI_REG8(0x58fa), 0x0a }, { CCI_REG8(0x58fb), 0x09 },
+ { CCI_REG8(0x58fc), 0x10 }, { CCI_REG8(0x58fd), 0x0f },
+ { CCI_REG8(0x58fe), 0x0e }, { CCI_REG8(0x58ff), 0x0d },
+ { CCI_REG8(0x5900), 0x14 }, { CCI_REG8(0x5901), 0x13 },
+ { CCI_REG8(0x5902), 0x12 }, { CCI_REG8(0x5903), 0x11 },
+ { CCI_REG8(0x5904), 0x18 }, { CCI_REG8(0x5905), 0x17 },
+ { CCI_REG8(0x5906), 0x16 }, { CCI_REG8(0x5907), 0x15 },
+ { CCI_REG8(0x5908), 0x1c }, { CCI_REG8(0x5909), 0x1b },
+ { CCI_REG8(0x590a), 0x1a }, { CCI_REG8(0x590b), 0x19 },
+ { CCI_REG8(0x590c), 0x20 }, { CCI_REG8(0x590d), 0x1f },
+ { CCI_REG8(0x590e), 0x1e }, { CCI_REG8(0x590f), 0x1d },
+ { CCI_REG8(0x5931), 0x02 }, { CCI_REG8(0x5932), 0x42 },
+ { CCI_REG8(0x5933), 0x24 }, { CCI_REG8(0x5953), 0x09 },
+ { CCI_REG8(0x5954), 0x00 }, { CCI_REG8(0x5989), 0x84 },
+ { CCI_REG8(0x59c3), 0x04 }, { CCI_REG8(0x59c4), 0x24 },
+ { CCI_REG8(0x59c5), 0x40 }, { CCI_REG8(0x59c6), 0x1b },
+ { CCI_REG8(0x59c7), 0x40 }, { CCI_REG8(0x5a02), 0x0f },
+ { CCI_REG8(0x5f00), 0x29 }, { CCI_REG8(0x5f2d), 0x28 },
+ { CCI_REG8(0x5f2e), 0x28 }, { CCI_REG8(0x6801), 0x11 },
+ { CCI_REG8(0x6802), 0x3f }, { CCI_REG8(0x6803), 0xe7 },
+ { CCI_REG8(0x6825), 0x0f }, { CCI_REG8(0x6826), 0x20 },
+ { CCI_REG8(0x6827), 0x00 }, { CCI_REG8(0x6829), 0x16 },
+ { CCI_REG8(0x682b), 0xb3 }, { CCI_REG8(0x682c), 0x01 },
+ { CCI_REG8(0x6832), 0xff }, { CCI_REG8(0x6833), 0xff },
+ { CCI_REG8(0x6898), 0x80 }, { CCI_REG8(0x6899), 0x80 },
+ { CCI_REG8(0x689b), 0x40 }, { CCI_REG8(0x689c), 0x20 },
+ { CCI_REG8(0x689d), 0x20 }, { CCI_REG8(0x689e), 0x80 },
+ { CCI_REG8(0x689f), 0x60 }, { CCI_REG8(0x68a0), 0x40 },
+ { CCI_REG8(0x68a4), 0x40 }, { CCI_REG8(0x68a5), 0x20 },
+ { CCI_REG8(0x68a6), 0x00 }, { CCI_REG8(0x68b6), 0x80 },
+ { CCI_REG8(0x68b7), 0x80 }, { CCI_REG8(0x68b8), 0x80 },
+ { CCI_REG8(0x68bc), 0x80 }, { CCI_REG8(0x68bd), 0x80 },
+ { CCI_REG8(0x68be), 0x80 }, { CCI_REG8(0x68bf), 0x40 },
+ { CCI_REG8(0x68c2), 0x80 }, { CCI_REG8(0x68c3), 0x80 },
+ { CCI_REG8(0x68c4), 0x60 }, { CCI_REG8(0x68c5), 0x30 },
+ { CCI_REG8(0x6918), 0x80 }, { CCI_REG8(0x6919), 0x80 },
+ { CCI_REG8(0x691b), 0x40 }, { CCI_REG8(0x691c), 0x20 },
+ { CCI_REG8(0x691d), 0x20 }, { CCI_REG8(0x691e), 0x80 },
+ { CCI_REG8(0x691f), 0x60 }, { CCI_REG8(0x6920), 0x40 },
+ { CCI_REG8(0x6924), 0x40 }, { CCI_REG8(0x6925), 0x20 },
+ { CCI_REG8(0x6926), 0x00 }, { CCI_REG8(0x6936), 0x40 },
+ { CCI_REG8(0x6937), 0x40 }, { CCI_REG8(0x6938), 0x20 },
+ { CCI_REG8(0x6939), 0x20 }, { CCI_REG8(0x693a), 0x10 },
+ { CCI_REG8(0x693b), 0x10 }, { CCI_REG8(0x693c), 0x20 },
+ { CCI_REG8(0x693d), 0x20 }, { CCI_REG8(0x693e), 0x10 },
+ { CCI_REG8(0x693f), 0x10 }, { CCI_REG8(0x6940), 0x00 },
+ { CCI_REG8(0x6941), 0x00 }, { CCI_REG8(0x6942), 0x08 },
+ { CCI_REG8(0x6943), 0x08 }, { CCI_REG8(0x6944), 0x00 },
+ { CCI_REG8(0x69c2), 0x07 }, { CCI_REG8(0x6a20), 0x01 },
+ { CCI_REG8(0x6a23), 0x10 }, { CCI_REG8(0x6a26), 0x3d },
+ { CCI_REG8(0x6a27), 0x3e }, { CCI_REG8(0x6a38), 0x02 },
+ { CCI_REG8(0x6a39), 0x20 }, { CCI_REG8(0x6a3a), 0x02 },
+ { CCI_REG8(0x6a3b), 0x84 }, { CCI_REG8(0x6a3e), 0x02 },
+ { CCI_REG8(0x6a3f), 0x20 }, { CCI_REG8(0x6a47), 0x3b },
+ { CCI_REG8(0x6a63), 0x04 }, { CCI_REG8(0x6a65), 0x00 },
+ { CCI_REG8(0x6a67), 0x0f }, { CCI_REG8(0x6b22), 0x07 },
+ { CCI_REG8(0x6b23), 0xc2 }, { CCI_REG8(0x6b2f), 0x00 },
+ { CCI_REG8(0x6b60), 0x1f }, { CCI_REG8(0x6bd2), 0x5a },
+ { CCI_REG8(0x6c20), 0x50 }, { CCI_REG8(0x6c60), 0x50 },
+ { CCI_REG8(0x6c61), 0x06 }, { CCI_REG8(0x7318), 0x04 },
+ { CCI_REG8(0x7319), 0x01 }, { CCI_REG8(0x731a), 0x04 },
+ { CCI_REG8(0x731b), 0x01 }, { CCI_REG8(0x731c), 0x00 },
+ { CCI_REG8(0x731d), 0x00 }, { CCI_REG8(0x731e), 0x04 },
+ { CCI_REG8(0x731f), 0x01 }, { CCI_REG8(0x7320), 0x04 },
+ { CCI_REG8(0x7321), 0x00 }, { CCI_REG8(0x7322), 0x04 },
+ { CCI_REG8(0x7323), 0x00 }, { CCI_REG8(0x7324), 0x04 },
+ { CCI_REG8(0x7325), 0x00 }, { CCI_REG8(0x7326), 0x04 },
+ { CCI_REG8(0x7327), 0x00 }, { CCI_REG8(0x7600), 0x00 },
+ { CCI_REG8(0x7601), 0x00 }, { CCI_REG8(0x7602), 0x10 },
+ { CCI_REG8(0x7603), 0x00 }, { CCI_REG8(0x7604), 0x00 },
+ { CCI_REG8(0x7605), 0x00 }, { CCI_REG8(0x7606), 0x10 },
+ { CCI_REG8(0x7607), 0x00 }, { CCI_REG8(0x7608), 0x00 },
+ { CCI_REG8(0x7609), 0x00 }, { CCI_REG8(0x760a), 0x10 },
+ { CCI_REG8(0x760b), 0x00 }, { CCI_REG8(0x760c), 0x00 },
+ { CCI_REG8(0x760d), 0x00 }, { CCI_REG8(0x760e), 0x10 },
+ { CCI_REG8(0x760f), 0x00 }, { CCI_REG8(0x7610), 0x00 },
+ { CCI_REG8(0x7611), 0x00 }, { CCI_REG8(0x7612), 0x10 },
+ { CCI_REG8(0x7613), 0x00 }, { CCI_REG8(0x7614), 0x00 },
+ { CCI_REG8(0x7615), 0x00 }, { CCI_REG8(0x7616), 0x10 },
+ { CCI_REG8(0x7617), 0x00 }, { CCI_REG8(0x7618), 0x00 },
+ { CCI_REG8(0x7619), 0x00 }, { CCI_REG8(0x761a), 0x10 },
+ { CCI_REG8(0x761b), 0x00 }, { CCI_REG8(0x761c), 0x00 },
+ { CCI_REG8(0x761d), 0x00 }, { CCI_REG8(0x761e), 0x10 },
+ { CCI_REG8(0x761f), 0x00 }, { CCI_REG8(0x7620), 0x00 },
+ { CCI_REG8(0x7621), 0x00 }, { CCI_REG8(0x7622), 0x10 },
+ { CCI_REG8(0x7623), 0x00 }, { CCI_REG8(0x7624), 0x00 },
+ { CCI_REG8(0x7625), 0x00 }, { CCI_REG8(0x7626), 0x10 },
+ { CCI_REG8(0x7627), 0x00 }, { CCI_REG8(0x7628), 0x00 },
+ { CCI_REG8(0x7629), 0x00 }, { CCI_REG8(0x762a), 0x10 },
+ { CCI_REG8(0x762b), 0x00 }, { CCI_REG8(0x762c), 0x00 },
+ { CCI_REG8(0x762d), 0x00 }, { CCI_REG8(0x762e), 0x10 },
+ { CCI_REG8(0x762f), 0x00 }, { CCI_REG8(0x7630), 0x00 },
+ { CCI_REG8(0x7631), 0x00 }, { CCI_REG8(0x7632), 0x10 },
+ { CCI_REG8(0x7633), 0x00 }, { CCI_REG8(0x7634), 0x00 },
+ { CCI_REG8(0x7635), 0x00 }, { CCI_REG8(0x7636), 0x10 },
+ { CCI_REG8(0x7637), 0x00 }, { CCI_REG8(0x7638), 0x00 },
+ { CCI_REG8(0x7639), 0x00 }, { CCI_REG8(0x763a), 0x10 },
+ { CCI_REG8(0x763b), 0x00 }, { CCI_REG8(0x763c), 0x00 },
+ { CCI_REG8(0x763d), 0x00 }, { CCI_REG8(0x763e), 0x10 },
+ { CCI_REG8(0x763f), 0x00 }, { CCI_REG8(0x7640), 0x00 },
+ { CCI_REG8(0x7641), 0x00 }, { CCI_REG8(0x7642), 0x10 },
+ { CCI_REG8(0x7643), 0x00 }, { CCI_REG8(0x7644), 0x00 },
+ { CCI_REG8(0x7645), 0x00 }, { CCI_REG8(0x7646), 0x10 },
+ { CCI_REG8(0x7647), 0x00 }, { CCI_REG8(0x7648), 0x00 },
+ { CCI_REG8(0x7649), 0x00 }, { CCI_REG8(0x764a), 0x10 },
+ { CCI_REG8(0x764b), 0x00 }, { CCI_REG8(0x764c), 0x00 },
+ { CCI_REG8(0x764d), 0x00 }, { CCI_REG8(0x764e), 0x10 },
+ { CCI_REG8(0x764f), 0x00 }, { CCI_REG8(0x7650), 0x00 },
+ { CCI_REG8(0x7651), 0x00 }, { CCI_REG8(0x7652), 0x10 },
+ { CCI_REG8(0x7653), 0x00 }, { CCI_REG8(0x7654), 0x00 },
+ { CCI_REG8(0x7655), 0x00 }, { CCI_REG8(0x7656), 0x10 },
+ { CCI_REG8(0x7657), 0x00 }, { CCI_REG8(0x7658), 0x00 },
+ { CCI_REG8(0x7659), 0x00 }, { CCI_REG8(0x765a), 0x10 },
+ { CCI_REG8(0x765b), 0x00 }, { CCI_REG8(0x765c), 0x00 },
+ { CCI_REG8(0x765d), 0x00 }, { CCI_REG8(0x765e), 0x10 },
+ { CCI_REG8(0x765f), 0x00 }, { CCI_REG8(0x7660), 0x00 },
+ { CCI_REG8(0x7661), 0x00 }, { CCI_REG8(0x7662), 0x10 },
+ { CCI_REG8(0x7663), 0x00 }, { CCI_REG8(0x7664), 0x00 },
+ { CCI_REG8(0x7665), 0x00 }, { CCI_REG8(0x7666), 0x10 },
+ { CCI_REG8(0x7667), 0x00 }, { CCI_REG8(0x7668), 0x00 },
+ { CCI_REG8(0x7669), 0x00 }, { CCI_REG8(0x766a), 0x10 },
+ { CCI_REG8(0x766b), 0x00 }, { CCI_REG8(0x766c), 0x00 },
+ { CCI_REG8(0x766d), 0x00 }, { CCI_REG8(0x766e), 0x10 },
+ { CCI_REG8(0x766f), 0x00 }, { CCI_REG8(0x7670), 0x00 },
+ { CCI_REG8(0x7671), 0x00 }, { CCI_REG8(0x7672), 0x10 },
+ { CCI_REG8(0x7673), 0x00 }, { CCI_REG8(0x7674), 0x00 },
+ { CCI_REG8(0x7675), 0x00 }, { CCI_REG8(0x7676), 0x10 },
+ { CCI_REG8(0x7677), 0x00 }, { CCI_REG8(0x7678), 0x00 },
+ { CCI_REG8(0x7679), 0x00 }, { CCI_REG8(0x767a), 0x10 },
+ { CCI_REG8(0x767b), 0x00 }, { CCI_REG8(0x767c), 0x00 },
+ { CCI_REG8(0x767d), 0x00 }, { CCI_REG8(0x767e), 0x10 },
+ { CCI_REG8(0x767f), 0x00 }, { CCI_REG8(0x7680), 0x00 },
+ { CCI_REG8(0x7681), 0x00 }, { CCI_REG8(0x7682), 0x10 },
+ { CCI_REG8(0x7683), 0x00 }, { CCI_REG8(0x7684), 0x00 },
+ { CCI_REG8(0x7685), 0x00 }, { CCI_REG8(0x7686), 0x10 },
+ { CCI_REG8(0x7687), 0x00 }, { CCI_REG8(0x7688), 0x00 },
+ { CCI_REG8(0x7689), 0x00 }, { CCI_REG8(0x768a), 0x10 },
+ { CCI_REG8(0x768b), 0x00 }, { CCI_REG8(0x768c), 0x00 },
+ { CCI_REG8(0x768d), 0x00 }, { CCI_REG8(0x768e), 0x10 },
+ { CCI_REG8(0x768f), 0x00 }, { CCI_REG8(0x7690), 0x00 },
+ { CCI_REG8(0x7691), 0x00 }, { CCI_REG8(0x7692), 0x10 },
+ { CCI_REG8(0x7693), 0x00 }, { CCI_REG8(0x7694), 0x00 },
+ { CCI_REG8(0x7695), 0x00 }, { CCI_REG8(0x7696), 0x10 },
+ { CCI_REG8(0x7697), 0x00 }, { CCI_REG8(0x7698), 0x00 },
+ { CCI_REG8(0x7699), 0x00 }, { CCI_REG8(0x769a), 0x10 },
+ { CCI_REG8(0x769b), 0x00 }, { CCI_REG8(0x769c), 0x00 },
+ { CCI_REG8(0x769d), 0x00 }, { CCI_REG8(0x769e), 0x10 },
+ { CCI_REG8(0x769f), 0x00 }, { CCI_REG8(0x76a0), 0x00 },
+ { CCI_REG8(0x76a1), 0x00 }, { CCI_REG8(0x76a2), 0x10 },
+ { CCI_REG8(0x76a3), 0x00 }, { CCI_REG8(0x76a4), 0x00 },
+ { CCI_REG8(0x76a5), 0x00 }, { CCI_REG8(0x76a6), 0x10 },
+ { CCI_REG8(0x76a7), 0x00 }, { CCI_REG8(0x76a8), 0x00 },
+ { CCI_REG8(0x76a9), 0x00 }, { CCI_REG8(0x76aa), 0x10 },
+ { CCI_REG8(0x76ab), 0x00 }, { CCI_REG8(0x76ac), 0x00 },
+ { CCI_REG8(0x76ad), 0x00 }, { CCI_REG8(0x76ae), 0x10 },
+ { CCI_REG8(0x76af), 0x00 }, { CCI_REG8(0x76b0), 0x00 },
+ { CCI_REG8(0x76b1), 0x00 }, { CCI_REG8(0x76b2), 0x10 },
+ { CCI_REG8(0x76b3), 0x00 }, { CCI_REG8(0x76b4), 0x00 },
+ { CCI_REG8(0x76b5), 0x00 }, { CCI_REG8(0x76b6), 0x10 },
+ { CCI_REG8(0x76b7), 0x00 }, { CCI_REG8(0x76b8), 0x00 },
+ { CCI_REG8(0x76b9), 0x00 }, { CCI_REG8(0x76ba), 0x10 },
+ { CCI_REG8(0x76bb), 0x00 }, { CCI_REG8(0x76bc), 0x00 },
+ { CCI_REG8(0x76bd), 0x00 }, { CCI_REG8(0x76be), 0x10 },
+ { CCI_REG8(0x76bf), 0x00 }, { CCI_REG8(0x76c0), 0x00 },
+ { CCI_REG8(0x76c1), 0x00 }, { CCI_REG8(0x76c2), 0x10 },
+ { CCI_REG8(0x76c3), 0x00 }, { CCI_REG8(0x76c4), 0x00 },
+ { CCI_REG8(0x76c5), 0x00 }, { CCI_REG8(0x76c6), 0x10 },
+ { CCI_REG8(0x76c7), 0x00 }, { CCI_REG8(0x76c8), 0x00 },
+ { CCI_REG8(0x76c9), 0x00 }, { CCI_REG8(0x76ca), 0x10 },
+ { CCI_REG8(0x76cb), 0x00 }, { CCI_REG8(0x76cc), 0x00 },
+ { CCI_REG8(0x76cd), 0x00 }, { CCI_REG8(0x76ce), 0x10 },
+ { CCI_REG8(0x76cf), 0x00 }, { CCI_REG8(0x76d0), 0x00 },
+ { CCI_REG8(0x76d1), 0x00 }, { CCI_REG8(0x76d2), 0x10 },
+ { CCI_REG8(0x76d3), 0x00 }, { CCI_REG8(0x76d4), 0x00 },
+ { CCI_REG8(0x76d5), 0x00 }, { CCI_REG8(0x76d6), 0x10 },
+ { CCI_REG8(0x76d7), 0x00 }, { CCI_REG8(0x76d8), 0x00 },
+ { CCI_REG8(0x76d9), 0x00 }, { CCI_REG8(0x76da), 0x10 },
+ { CCI_REG8(0x76db), 0x00 }, { CCI_REG8(0x76dc), 0x00 },
+ { CCI_REG8(0x76dd), 0x00 }, { CCI_REG8(0x76de), 0x10 },
+ { CCI_REG8(0x76df), 0x00 }, { CCI_REG8(0x76e0), 0x00 },
+ { CCI_REG8(0x76e1), 0x00 }, { CCI_REG8(0x76e2), 0x10 },
+ { CCI_REG8(0x76e3), 0x00 }, { CCI_REG8(0x76e4), 0x00 },
+ { CCI_REG8(0x76e5), 0x00 }, { CCI_REG8(0x76e6), 0x10 },
+ { CCI_REG8(0x76e7), 0x00 }, { CCI_REG8(0x76e8), 0x00 },
+ { CCI_REG8(0x76e9), 0x00 }, { CCI_REG8(0x76ea), 0x10 },
+ { CCI_REG8(0x76eb), 0x00 }, { CCI_REG8(0x76ec), 0x00 },
+ { CCI_REG8(0x76ed), 0x00 }, { CCI_REG8(0x76ee), 0x10 },
+ { CCI_REG8(0x76ef), 0x00 }, { CCI_REG8(0x76f0), 0x00 },
+ { CCI_REG8(0x76f1), 0x00 }, { CCI_REG8(0x76f2), 0x10 },
+ { CCI_REG8(0x76f3), 0x00 }, { CCI_REG8(0x76f4), 0x00 },
+ { CCI_REG8(0x76f5), 0x00 }, { CCI_REG8(0x76f6), 0x10 },
+ { CCI_REG8(0x76f7), 0x00 }, { CCI_REG8(0x76f8), 0x00 },
+ { CCI_REG8(0x76f9), 0x00 }, { CCI_REG8(0x76fa), 0x10 },
+ { CCI_REG8(0x76fb), 0x00 }, { CCI_REG8(0x76fc), 0x00 },
+ { CCI_REG8(0x76fd), 0x00 }, { CCI_REG8(0x76fe), 0x10 },
+ { CCI_REG8(0x76ff), 0x00 }, { CCI_REG8(0x7700), 0x00 },
+ { CCI_REG8(0x7701), 0x00 }, { CCI_REG8(0x7702), 0x10 },
+ { CCI_REG8(0x7703), 0x00 }, { CCI_REG8(0x7704), 0x00 },
+ { CCI_REG8(0x7705), 0x00 }, { CCI_REG8(0x7706), 0x10 },
+ { CCI_REG8(0x7707), 0x00 }, { CCI_REG8(0x7708), 0x00 },
+ { CCI_REG8(0x7709), 0x00 }, { CCI_REG8(0x770a), 0x10 },
+ { CCI_REG8(0x770b), 0x00 }, { CCI_REG8(0x770c), 0x00 },
+ { CCI_REG8(0x770d), 0x00 }, { CCI_REG8(0x770e), 0x10 },
+ { CCI_REG8(0x770f), 0x00 }, { CCI_REG8(0x7710), 0x00 },
+ { CCI_REG8(0x7711), 0x00 }, { CCI_REG8(0x7712), 0x10 },
+ { CCI_REG8(0x7713), 0x00 }, { CCI_REG8(0x7714), 0x00 },
+ { CCI_REG8(0x7715), 0x00 }, { CCI_REG8(0x7716), 0x10 },
+ { CCI_REG8(0x7717), 0x00 }, { CCI_REG8(0x7718), 0x00 },
+ { CCI_REG8(0x7719), 0x00 }, { CCI_REG8(0x771a), 0x10 },
+ { CCI_REG8(0x771b), 0x00 }, { CCI_REG8(0x771c), 0x00 },
+ { CCI_REG8(0x771d), 0x00 }, { CCI_REG8(0x771e), 0x10 },
+ { CCI_REG8(0x771f), 0x00 }, { CCI_REG8(0x7720), 0x00 },
+ { CCI_REG8(0x7721), 0x00 }, { CCI_REG8(0x7722), 0x10 },
+ { CCI_REG8(0x7723), 0x00 }, { CCI_REG8(0x7724), 0x00 },
+ { CCI_REG8(0x7725), 0x00 }, { CCI_REG8(0x7726), 0x10 },
+ { CCI_REG8(0x7727), 0x00 }, { CCI_REG8(0x7728), 0x00 },
+ { CCI_REG8(0x7729), 0x00 }, { CCI_REG8(0x772a), 0x10 },
+ { CCI_REG8(0x772b), 0x00 }, { CCI_REG8(0x772c), 0x00 },
+ { CCI_REG8(0x772d), 0x00 }, { CCI_REG8(0x772e), 0x10 },
+ { CCI_REG8(0x772f), 0x00 }, { CCI_REG8(0x7730), 0x00 },
+ { CCI_REG8(0x7731), 0x00 }, { CCI_REG8(0x7732), 0x10 },
+ { CCI_REG8(0x7733), 0x00 }, { CCI_REG8(0x7734), 0x00 },
+ { CCI_REG8(0x7735), 0x00 }, { CCI_REG8(0x7736), 0x10 },
+ { CCI_REG8(0x7737), 0x00 }, { CCI_REG8(0x7738), 0x00 },
+ { CCI_REG8(0x7739), 0x00 }, { CCI_REG8(0x773a), 0x10 },
+ { CCI_REG8(0x773b), 0x00 }, { CCI_REG8(0x773c), 0x00 },
+ { CCI_REG8(0x773d), 0x00 }, { CCI_REG8(0x773e), 0x10 },
+ { CCI_REG8(0x773f), 0x00 }, { CCI_REG8(0x7740), 0x00 },
+ { CCI_REG8(0x7741), 0x00 }, { CCI_REG8(0x7742), 0x10 },
+ { CCI_REG8(0x7743), 0x00 }, { CCI_REG8(0x3421), 0x02 },
+ { CCI_REG8(0x37d0), 0x00 }, { CCI_REG8(0x3632), 0x99 },
+ { CCI_REG8(0xc518), 0x1f }, { CCI_REG8(0xc519), 0x1f },
+ { CCI_REG8(0xc51a), 0x1f }, { CCI_REG8(0xc51b), 0x1f },
+ { CCI_REG8(0xc51c), 0x1f }, { CCI_REG8(0xc51d), 0x1f },
+ { CCI_REG8(0xc51e), 0x1f }, { CCI_REG8(0xc51f), 0x1f },
+ { CCI_REG8(0xc520), 0x1f }, { CCI_REG8(0xc521), 0x1f },
+ { CCI_REG8(0x3616), 0xa0 }, { CCI_REG8(0x3615), 0xc5 },
+ { CCI_REG8(0xc4c1), 0x02 }, { CCI_REG8(0xc4c2), 0x02 },
+ { CCI_REG8(0xc4c3), 0x03 }, { CCI_REG8(0xc4c4), 0x03 },
+ { CCI_REG8(0xc4f6), 0x0a }, { CCI_REG8(0xc4f7), 0x0a },
+ { CCI_REG8(0xc4f8), 0x0a }, { CCI_REG8(0xc4f9), 0x0a },
+ { CCI_REG8(0xc4fa), 0x0a }, { CCI_REG8(0xc4c6), 0x0a },
+ { CCI_REG8(0xc4c7), 0x0a }, { CCI_REG8(0xc4c8), 0x0a },
+ { CCI_REG8(0xc4c9), 0x0a }, { CCI_REG8(0xc4ca), 0x14 },
+ { CCI_REG8(0xc4cb), 0x14 }, { CCI_REG8(0xc4cc), 0x14 },
+ { CCI_REG8(0xc4cd), 0x14 }, { CCI_REG8(0x3b92), 0x05 },
+ { CCI_REG8(0x3b93), 0x05 }, { CCI_REG8(0x3b94), 0x05 },
+ { CCI_REG8(0x3b95), 0x05 }, { CCI_REG8(0x3623), 0x10 },
+ { CCI_REG8(0xc522), 0x18 }, { CCI_REG8(0xc523), 0x12 },
+ { CCI_REG8(0xc524), 0x0e }, { CCI_REG8(0xc525), 0x0b },
+ { CCI_REG8(0xc526), 0x18 }, { CCI_REG8(0xc527), 0x12 },
+ { CCI_REG8(0xc528), 0x0c }, { CCI_REG8(0xc529), 0x08 },
+ { CCI_REG8(0xc52a), 0x18 }, { CCI_REG8(0xc52b), 0x12 },
+ { CCI_REG8(0xc52c), 0x0e }, { CCI_REG8(0xc52d), 0x0b },
+ { CCI_REG8(0xc52e), 0x18 }, { CCI_REG8(0xc52f), 0x12 },
+ { CCI_REG8(0xc530), 0x0e }, { CCI_REG8(0xc531), 0x0b },
+ { CCI_REG8(0xc532), 0x18 }, { CCI_REG8(0xc533), 0x12 },
+ { CCI_REG8(0xc534), 0x0e }, { CCI_REG8(0xc535), 0x0b },
+ { CCI_REG8(0xc536), 0x18 }, { CCI_REG8(0xc537), 0x12 },
+ { CCI_REG8(0xc538), 0x0e }, { CCI_REG8(0xc539), 0x0b },
+ { CCI_REG8(0xc53a), 0x18 }, { CCI_REG8(0xc53b), 0x12 },
+ { CCI_REG8(0xc53c), 0x0c }, { CCI_REG8(0xc53d), 0x08 },
+ { CCI_REG8(0xc53e), 0x18 }, { CCI_REG8(0xc53f), 0x12 },
+ { CCI_REG8(0xc540), 0x0e }, { CCI_REG8(0xc541), 0x0b },
+ { CCI_REG8(0xc542), 0x18 }, { CCI_REG8(0xc543), 0x12 },
+ { CCI_REG8(0xc544), 0x0e }, { CCI_REG8(0xc545), 0x0b },
+ { CCI_REG8(0xc546), 0x18 }, { CCI_REG8(0xc547), 0x12 },
+ { CCI_REG8(0xc548), 0x0e }, { CCI_REG8(0xc549), 0x0b },
+ { CCI_REG8(0x3701), 0x18 }, { CCI_REG8(0x3702), 0x38 },
+ { CCI_REG8(0x3703), 0x72 }, { CCI_REG8(0x3708), 0x26 },
+ { CCI_REG8(0x3709), 0xe6 }, { CCI_REG8(0x3a1d), 0x18 },
+ { CCI_REG8(0x3a1e), 0x18 }, { CCI_REG8(0x3a21), 0x18 },
+ { CCI_REG8(0x3a22), 0x18 }, { CCI_REG8(0x39fb), 0x18 },
+ { CCI_REG8(0x39fc), 0x18 }, { CCI_REG8(0x39fd), 0x18 },
+ { CCI_REG8(0x39fe), 0x18 }, { CCI_REG8(0xc44a), 0x08 },
+ { CCI_REG8(0xc44c), 0x08 }, { CCI_REG8(0xc5e8), 0x0a },
+ { CCI_REG8(0xc5ea), 0x0a }, { CCI_REG8(0x391d), 0x54 },
+ { CCI_REG8(0x391e), 0xca }, { CCI_REG8(0x3991), 0x0c },
+ { CCI_REG8(0x399d), 0x0c }, { CCI_REG8(0x3744), 0x24 },
+ { CCI_REG8(0x374b), 0x0c }, { CCI_REG8(0x3be7), 0x1e },
+ { CCI_REG8(0x3be8), 0x26 }, { CCI_REG8(0x3a50), 0x14 },
+ { CCI_REG8(0x3a54), 0x14 }, { CCI_REG8(0x3add), 0x1f },
+ { CCI_REG8(0x3adf), 0x24 }, { CCI_REG8(0x3aef), 0x1f },
+ { CCI_REG8(0x3af0), 0x24 }, { CCI_REG8(0xc57f), 0x30 },
+ { CCI_REG8(0xc580), 0x30 }, { CCI_REG8(0xc581), 0x30 },
+ { CCI_REG8(0xc582), 0x30 }, { CCI_REG8(0xc583), 0x30 },
+ { CCI_REG8(0xc584), 0x30 }, { CCI_REG8(0xc585), 0x30 },
+ { CCI_REG8(0xc586), 0x30 }, { CCI_REG8(0xc587), 0x30 },
+ { CCI_REG8(0xc588), 0x30 }, { CCI_REG8(0xc589), 0x30 },
+ { CCI_REG8(0xc58a), 0x30 }, { CCI_REG8(0xc58b), 0x30 },
+ { CCI_REG8(0xc58c), 0x30 }, { CCI_REG8(0xc58d), 0x30 },
+ { CCI_REG8(0xc58e), 0x30 }, { CCI_REG8(0xc58f), 0x30 },
+ { CCI_REG8(0xc590), 0x30 }, { CCI_REG8(0xc591), 0x30 },
+ { CCI_REG8(0xc592), 0x30 }, { CCI_REG8(0xc598), 0x30 },
+ { CCI_REG8(0xc599), 0x30 }, { CCI_REG8(0xc59a), 0x30 },
+ { CCI_REG8(0xc59b), 0x30 }, { CCI_REG8(0xc59c), 0x30 },
+ { CCI_REG8(0xc59d), 0x30 }, { CCI_REG8(0xc59e), 0x30 },
+ { CCI_REG8(0xc59f), 0x30 }, { CCI_REG8(0xc5a0), 0x30 },
+ { CCI_REG8(0xc5a1), 0x30 }, { CCI_REG8(0xc5a2), 0x30 },
+ { CCI_REG8(0xc5a3), 0x30 }, { CCI_REG8(0xc5a4), 0x30 },
+ { CCI_REG8(0xc5a5), 0x30 }, { CCI_REG8(0xc5a6), 0x30 },
+ { CCI_REG8(0xc5a7), 0x30 }, { CCI_REG8(0xc5a8), 0x30 },
+ { CCI_REG8(0xc5a9), 0x30 }, { CCI_REG8(0xc5aa), 0x30 },
+ { CCI_REG8(0xc5ab), 0x30 }, { CCI_REG8(0xc5b1), 0x38 },
+ { CCI_REG8(0xc5b2), 0x38 }, { CCI_REG8(0xc5b3), 0x38 },
+ { CCI_REG8(0xc5b4), 0x38 }, { CCI_REG8(0xc5b5), 0x38 },
+ { CCI_REG8(0xc5b6), 0x38 }, { CCI_REG8(0xc5b7), 0x38 },
+ { CCI_REG8(0xc5b8), 0x38 }, { CCI_REG8(0xc5b9), 0x38 },
+ { CCI_REG8(0xc5ba), 0x38 }, { CCI_REG8(0xc5bb), 0x38 },
+ { CCI_REG8(0xc5bc), 0x38 }, { CCI_REG8(0xc5bd), 0x38 },
+ { CCI_REG8(0xc5be), 0x38 }, { CCI_REG8(0xc5bf), 0x38 },
+ { CCI_REG8(0xc5c0), 0x38 }, { CCI_REG8(0xc5c1), 0x38 },
+ { CCI_REG8(0xc5c2), 0x38 }, { CCI_REG8(0xc5c3), 0x38 },
+ { CCI_REG8(0xc5c4), 0x38 }, { CCI_REG8(0xc5ca), 0x38 },
+ { CCI_REG8(0xc5cb), 0x38 }, { CCI_REG8(0xc5cc), 0x38 },
+ { CCI_REG8(0xc5cd), 0x38 }, { CCI_REG8(0xc5ce), 0x38 },
+ { CCI_REG8(0xc5cf), 0x38 }, { CCI_REG8(0xc5d0), 0x38 },
+ { CCI_REG8(0xc5d1), 0x38 }, { CCI_REG8(0xc5d2), 0x38 },
+ { CCI_REG8(0xc5d3), 0x38 }, { CCI_REG8(0xc5d4), 0x38 },
+ { CCI_REG8(0xc5d5), 0x38 }, { CCI_REG8(0xc5d6), 0x38 },
+ { CCI_REG8(0xc5d7), 0x38 }, { CCI_REG8(0xc5d8), 0x38 },
+ { CCI_REG8(0xc5d9), 0x38 }, { CCI_REG8(0xc5da), 0x38 },
+ { CCI_REG8(0xc5db), 0x38 }, { CCI_REG8(0xc5dc), 0x38 },
+ { CCI_REG8(0xc5dd), 0x38 }, { CCI_REG8(0x3a60), 0x68 },
+ { CCI_REG8(0x3a6f), 0x68 }, { CCI_REG8(0x3a5e), 0xdc },
+ { CCI_REG8(0x3a6d), 0xdc }, { CCI_REG8(0x3aed), 0x6e },
+ { CCI_REG8(0x3af1), 0x73 }, { CCI_REG8(0x3992), 0x02 },
+ { CCI_REG8(0x399e), 0x02 }, { CCI_REG8(0x371d), 0x17 },
+ { CCI_REG8(0x371f), 0x08 }, { CCI_REG8(0x3721), 0xc9 },
+ { CCI_REG8(0x401e), 0x00 }, { CCI_REG8(0x401f), 0xf8 },
+ { CCI_REG8(0x3642), 0x00 }, { CCI_REG8(0x3641), 0x7f },
+ { CCI_REG8(0x3ac5), 0x0c }, { CCI_REG8(0x3ac6), 0x09 },
+ { CCI_REG8(0x3ac7), 0x06 }, { CCI_REG8(0x3ac8), 0x02 },
+ { CCI_REG8(0x3ac9), 0x0c }, { CCI_REG8(0x3aca), 0x09 },
+ { CCI_REG8(0x3acb), 0x06 }, { CCI_REG8(0x3acc), 0x02 },
+ { CCI_REG8(0x3acd), 0x0c }, { CCI_REG8(0x3ace), 0x09 },
+ { CCI_REG8(0x3acf), 0x07 }, { CCI_REG8(0x3ad0), 0x04 },
+ { CCI_REG8(0x3ad1), 0x0c }, { CCI_REG8(0x3ad2), 0x09 },
+ { CCI_REG8(0x3ad3), 0x07 }, { CCI_REG8(0x3ad4), 0x04 },
+ { CCI_REG8(0xc483), 0x0c }, { CCI_REG8(0xc484), 0x0c },
+ { CCI_REG8(0xc485), 0x0c }, { CCI_REG8(0xc486), 0x0c },
+ { CCI_REG8(0x3a2f), 0x0c }, { CCI_REG8(0x3a30), 0x09 },
+ { CCI_REG8(0x3a31), 0x06 }, { CCI_REG8(0x3a32), 0x02 },
+ { CCI_REG8(0x3a34), 0x0c }, { CCI_REG8(0x3a35), 0x09 },
+ { CCI_REG8(0x3a36), 0x07 }, { CCI_REG8(0x3a37), 0x04 },
+ { CCI_REG8(0x3a43), 0x0c }, { CCI_REG8(0x3a44), 0x09 },
+ { CCI_REG8(0x3a45), 0x06 }, { CCI_REG8(0x3a46), 0x02 },
+ { CCI_REG8(0x3a48), 0x0c }, { CCI_REG8(0x3a49), 0x09 },
+ { CCI_REG8(0x3a4a), 0x07 }, { CCI_REG8(0x3a4b), 0x04 },
+ { CCI_REG8(0xc487), 0x0c }, { CCI_REG8(0xc488), 0x0c },
+ { CCI_REG8(0xc489), 0x0c }, { CCI_REG8(0xc48a), 0x0c },
+ { CCI_REG8(0x3645), 0xbd }, { CCI_REG8(0x373f), 0x00 },
+ { CCI_REG8(0x374f), 0x10 }, { CCI_REG8(0x3743), 0xc6 },
+ { CCI_REG8(0x3717), 0x82 }, { CCI_REG8(0x3732), 0x07 },
+ { CCI_REG8(0x3731), 0x16 }, { CCI_REG8(0x3730), 0x16 },
+ { CCI_REG8(0x3828), 0x07 }, { CCI_REG8(0x3714), 0x68 },
+ { CCI_REG8(0x371d), 0x02 }, { CCI_REG8(0x371f), 0x02 },
+ { CCI_REG8(0x37e0), 0x00 }, { CCI_REG8(0x37e1), 0x03 },
+ { CCI_REG8(0x37e2), 0x07 }, { CCI_REG8(0x3734), 0x3e },
+ { CCI_REG8(0x3736), 0x02 }, { CCI_REG8(0x37e4), 0x36 },
+ { CCI_REG8(0x37e9), 0x1c }, { CCI_REG8(0x37ea), 0x01 },
+ { CCI_REG8(0x37eb), 0x0a }, { CCI_REG8(0x37ec), 0x1c },
+ { CCI_REG8(0x37ed), 0x01 }, { CCI_REG8(0x37ee), 0x36 },
+ { CCI_REG8(0x373b), 0x1c }, { CCI_REG8(0x373c), 0x02 },
+ { CCI_REG8(0x37bb), 0x1c }, { CCI_REG8(0x37bc), 0x02 },
+ { CCI_REG8(0x37b8), 0x0c }, { CCI_REG8(0x371c), 0x01 },
+ { CCI_REG8(0x371e), 0x11 }, { CCI_REG8(0x371d), 0x01 },
+ { CCI_REG8(0x371f), 0x01 }, { CCI_REG8(0x3721), 0x01 },
+ { CCI_REG8(0x3725), 0x12 }, { CCI_REG8(0x37e3), 0x06 },
+ { CCI_REG8(0x37dd), 0x86 }, { CCI_REG8(0x37db), 0x0a },
+ { CCI_REG8(0x37dc), 0x14 }, { CCI_REG8(0x3727), 0x20 },
+ { CCI_REG8(0x37b2), 0x80 }, { CCI_REG8(0x37da), 0x04 },
+ { CCI_REG8(0x37df), 0x01 }, { CCI_REG8(0x3731), 0x11 },
+ { CCI_REG8(0x37dd), 0x86 }, { CCI_REG8(0x37df), 0x01 },
+ { CCI_REG8(0x37da), 0x03 }, { CCI_REG8(0x37b2), 0x80 },
+ { CCI_REG8(0x3727), 0x20 }, { CCI_REG8(0x4883), 0x26 },
+ { CCI_REG8(0x488b), 0x88 }, { CCI_REG8(0x3d85), 0x1f },
+ { CCI_REG8(0x3d81), 0x01 }, { CCI_REG8(0x3d84), 0x40 },
+ { CCI_REG8(0x3d88), 0x00 }, { CCI_REG8(0x3d89), 0x00 },
+ { CCI_REG8(0x3d8a), 0x0b }, { CCI_REG8(0x3d8b), 0xff },
+ { CCI_REG8(0x4d00), 0x05 }, { CCI_REG8(0x4d01), 0xc4 },
+ { CCI_REG8(0x4d02), 0xa3 }, { CCI_REG8(0x4d03), 0x8c },
+ { CCI_REG8(0x4d04), 0xfb }, { CCI_REG8(0x4d05), 0xed },
+ { CCI_REG8(0x4010), 0x28 }, { CCI_REG8(0x4030), 0x00 },
+ { CCI_REG8(0x4031), 0x00 }, { CCI_REG8(0x4032), 0x00 },
+ { CCI_REG8(0x4033), 0x00 }, { CCI_REG8(0x4034), 0x00 },
+ { CCI_REG8(0x4035), 0x00 }, { CCI_REG8(0x4036), 0x00 },
+ { CCI_REG8(0x4037), 0x00 }, { CCI_REG8(0x4040), 0x00 },
+ { CCI_REG8(0x4041), 0x00 }, { CCI_REG8(0x4042), 0x00 },
+ { CCI_REG8(0x4043), 0x00 }, { CCI_REG8(0x4044), 0x00 },
+ { CCI_REG8(0x4045), 0x00 }, { CCI_REG8(0x4046), 0x00 },
+ { CCI_REG8(0x4047), 0x00 }, { CCI_REG8(0x3400), 0x00 },
+ { CCI_REG8(0x3421), 0x23 }, { CCI_REG8(0x3422), 0xfc },
+ { CCI_REG8(0x3423), 0x07 }, { CCI_REG8(0x3424), 0x01 },
+ { CCI_REG8(0x3425), 0x04 }, { CCI_REG8(0x3426), 0x50 },
+ { CCI_REG8(0x3427), 0x55 }, { CCI_REG8(0x3428), 0x15 },
+ { CCI_REG8(0x3429), 0x00 }, { CCI_REG8(0x3025), 0x03 },
+ { CCI_REG8(0x3053), 0x00 }, { CCI_REG8(0x3054), 0x00 },
+ { CCI_REG8(0x3055), 0x00 }, { CCI_REG8(0x3056), 0x00 },
+ { CCI_REG8(0x3057), 0x00 }, { CCI_REG8(0x3058), 0x00 },
+ { CCI_REG8(0x305c), 0x00 }, { CCI_REG8(0x340c), 0x1f },
+ { CCI_REG8(0x340d), 0x00 }, { CCI_REG8(0x3501), 0x01 },
+ { CCI_REG8(0x3542), 0x48 }, { CCI_REG8(0x3582), 0x24 },
+ { CCI_REG8(0x3015), 0xf1 }, { CCI_REG8(0x3018), 0xf2 },
+ { CCI_REG8(0x301c), 0xf2 }, { CCI_REG8(0x301d), 0xf6 },
+ { CCI_REG8(0x301e), 0xf1 }, { CCI_REG8(0x0100), 0x01 },
+ { CCI_REG8(0xfff9), 0x08 }, { CCI_REG8(0x3900), 0xcd },
+ { CCI_REG8(0x3901), 0xcd }, { CCI_REG8(0x3902), 0xcd },
+ { CCI_REG8(0x3903), 0xcd }, { CCI_REG8(0x3904), 0xcd },
+ { CCI_REG8(0x3905), 0xcd }, { CCI_REG8(0x3906), 0xcd },
+ { CCI_REG8(0x3907), 0xcd }, { CCI_REG8(0x3908), 0xcd },
+ { CCI_REG8(0x3909), 0xcd }, { CCI_REG8(0x390a), 0xcd },
+ { CCI_REG8(0x390b), 0xcd }, { CCI_REG8(0x390c), 0xcd },
+ { CCI_REG8(0x390d), 0xcd }, { CCI_REG8(0x390e), 0xcd },
+ { CCI_REG8(0x390f), 0xcd }, { CCI_REG8(0x3910), 0xcd },
+ { CCI_REG8(0x3911), 0xcd }, { CCI_REG8(0x3912), 0xcd },
+ { CCI_REG8(0x3913), 0xcd }, { CCI_REG8(0x3914), 0xcd },
+ { CCI_REG8(0x3915), 0xcd }, { CCI_REG8(0x3916), 0xcd },
+ { CCI_REG8(0x3917), 0xcd }, { CCI_REG8(0x3918), 0xcd },
+ { CCI_REG8(0x3919), 0xcd }, { CCI_REG8(0x391a), 0xcd },
+ { CCI_REG8(0x391b), 0xcd }, { CCI_REG8(0x391c), 0xcd },
+ { CCI_REG8(0x391d), 0xcd }, { CCI_REG8(0x391e), 0xcd },
+ { CCI_REG8(0x391f), 0xcd }, { CCI_REG8(0x3920), 0xcd },
+ { CCI_REG8(0x3921), 0xcd }, { CCI_REG8(0x3922), 0xcd },
+ { CCI_REG8(0x3923), 0xcd }, { CCI_REG8(0x3924), 0xcd },
+ { CCI_REG8(0x3925), 0xcd }, { CCI_REG8(0x3926), 0xcd },
+ { CCI_REG8(0x3927), 0xcd }, { CCI_REG8(0x3928), 0xcd },
+ { CCI_REG8(0x3929), 0xcd }, { CCI_REG8(0x392a), 0xcd },
+ { CCI_REG8(0x392b), 0xcd }, { CCI_REG8(0x392c), 0xcd },
+ { CCI_REG8(0x392d), 0xcd }, { CCI_REG8(0x392e), 0xcd },
+ { CCI_REG8(0x392f), 0xcd }, { CCI_REG8(0x3930), 0xcd },
+ { CCI_REG8(0x3931), 0xcd }, { CCI_REG8(0x3932), 0xcd },
+ { CCI_REG8(0x3933), 0xcd }, { CCI_REG8(0x3934), 0xcd },
+ { CCI_REG8(0x3935), 0xcd }, { CCI_REG8(0x3936), 0xcd },
+ { CCI_REG8(0x3937), 0xcd }, { CCI_REG8(0x3938), 0xcd },
+ { CCI_REG8(0x3939), 0xcd }, { CCI_REG8(0x393a), 0xcd },
+ { CCI_REG8(0x393b), 0xcd }, { CCI_REG8(0x393c), 0xcd },
+ { CCI_REG8(0x393d), 0xcd }, { CCI_REG8(0x393e), 0xcd },
+ { CCI_REG8(0x393f), 0xcd }, { CCI_REG8(0x3940), 0xcd },
+ { CCI_REG8(0x3941), 0xcd }, { CCI_REG8(0x3942), 0xcd },
+ { CCI_REG8(0x3943), 0xcd }, { CCI_REG8(0x3944), 0xcd },
+ { CCI_REG8(0x3945), 0xcd }, { CCI_REG8(0x3946), 0xcd },
+ { CCI_REG8(0x3947), 0xcd }, { CCI_REG8(0x3948), 0xcd },
+ { CCI_REG8(0x3949), 0xcd }, { CCI_REG8(0x394a), 0xcd },
+ { CCI_REG8(0x394b), 0xcd }, { CCI_REG8(0x394c), 0xcd },
+ { CCI_REG8(0x394d), 0xcd }, { CCI_REG8(0x394e), 0xcd },
+ { CCI_REG8(0x394f), 0xcd }, { CCI_REG8(0x3950), 0xcd },
+ { CCI_REG8(0x3951), 0xcd }, { CCI_REG8(0x3952), 0xcd },
+ { CCI_REG8(0x3953), 0xcd }, { CCI_REG8(0x3954), 0xcd },
+ { CCI_REG8(0x3955), 0xcd }, { CCI_REG8(0x3956), 0xcd },
+ { CCI_REG8(0x3957), 0xcd }, { CCI_REG8(0x3958), 0xcd },
+ { CCI_REG8(0x3959), 0xcd }, { CCI_REG8(0x395a), 0xcd },
+ { CCI_REG8(0x395b), 0xcd }, { CCI_REG8(0x395c), 0xcd },
+ { CCI_REG8(0x395d), 0xcd }, { CCI_REG8(0x395e), 0xcd },
+ { CCI_REG8(0x395f), 0xcd }, { CCI_REG8(0x3960), 0xcd },
+ { CCI_REG8(0x3961), 0xcd }, { CCI_REG8(0x3962), 0xcd },
+ { CCI_REG8(0x3963), 0xcd }, { CCI_REG8(0x3964), 0xcd },
+ { CCI_REG8(0x3965), 0xcd }, { CCI_REG8(0x3966), 0xcd },
+ { CCI_REG8(0x3967), 0xcd }, { CCI_REG8(0x3968), 0xcd },
+ { CCI_REG8(0x3969), 0xcd }, { CCI_REG8(0x396a), 0xcd },
+ { CCI_REG8(0x396b), 0xcd }, { CCI_REG8(0x396c), 0xcd },
+ { CCI_REG8(0x396d), 0xcd }, { CCI_REG8(0x396e), 0xcd },
+ { CCI_REG8(0x396f), 0xcd }, { CCI_REG8(0x3970), 0xcd },
+ { CCI_REG8(0x3971), 0xcd }, { CCI_REG8(0x3972), 0xcd },
+ { CCI_REG8(0x3973), 0xcd }, { CCI_REG8(0x3974), 0xcd },
+ { CCI_REG8(0x3975), 0xcd }, { CCI_REG8(0x3976), 0xcd },
+ { CCI_REG8(0x3977), 0xcd }, { CCI_REG8(0x3978), 0xcd },
+ { CCI_REG8(0x3979), 0xcd }, { CCI_REG8(0x397a), 0xcd },
+ { CCI_REG8(0x397b), 0xcd }, { CCI_REG8(0x397c), 0xcd },
+ { CCI_REG8(0x397d), 0xcd }, { CCI_REG8(0x397e), 0xcd },
+ { CCI_REG8(0x397f), 0xcd }, { CCI_REG8(0x3980), 0xcd },
+ { CCI_REG8(0x3981), 0xcd }, { CCI_REG8(0x3982), 0xcd },
+ { CCI_REG8(0x3983), 0xcd }, { CCI_REG8(0x3984), 0xcd },
+ { CCI_REG8(0x3985), 0xcd }, { CCI_REG8(0x3986), 0xcd },
+ { CCI_REG8(0x3987), 0xcd }, { CCI_REG8(0x3988), 0xcd },
+ { CCI_REG8(0x3989), 0xcd }, { CCI_REG8(0x398a), 0xcd },
+ { CCI_REG8(0x398b), 0xcd }, { CCI_REG8(0x398c), 0xcd },
+ { CCI_REG8(0x398d), 0xcd }, { CCI_REG8(0x398e), 0xcd },
+ { CCI_REG8(0x398f), 0xcd }, { CCI_REG8(0x3990), 0xcd },
+ { CCI_REG8(0x3991), 0xcd }, { CCI_REG8(0x3992), 0xcd },
+ { CCI_REG8(0x3993), 0xcd }, { CCI_REG8(0x3994), 0xcd },
+ { CCI_REG8(0x3995), 0xcd }, { CCI_REG8(0x3996), 0xcd },
+ { CCI_REG8(0x3997), 0xcd }, { CCI_REG8(0x3998), 0xcd },
+ { CCI_REG8(0x3999), 0xcd }, { CCI_REG8(0x399a), 0xcd },
+ { CCI_REG8(0x399b), 0xcd }, { CCI_REG8(0x399c), 0xcd },
+ { CCI_REG8(0x399d), 0xcd }, { CCI_REG8(0x399e), 0xcd },
+ { CCI_REG8(0x399f), 0xcd }, { CCI_REG8(0x39a0), 0xcd },
+ { CCI_REG8(0x39a1), 0xcd }, { CCI_REG8(0x39a2), 0xcd },
+ { CCI_REG8(0x39a3), 0xcd }, { CCI_REG8(0x39a4), 0xcd },
+ { CCI_REG8(0x39a5), 0xcd }, { CCI_REG8(0x39a6), 0xcd },
+ { CCI_REG8(0x39a7), 0xcd }, { CCI_REG8(0x39a8), 0xcd },
+ { CCI_REG8(0x39a9), 0xcd }, { CCI_REG8(0x39aa), 0xcd },
+ { CCI_REG8(0x39ab), 0xcd }, { CCI_REG8(0x39ac), 0xcd },
+ { CCI_REG8(0x39ad), 0xcd }, { CCI_REG8(0x39ae), 0xcd },
+ { CCI_REG8(0x39af), 0xcd }, { CCI_REG8(0x39b0), 0xcd },
+ { CCI_REG8(0x39b1), 0xcd }, { CCI_REG8(0x39b2), 0xcd },
+ { CCI_REG8(0x39b3), 0xcd }, { CCI_REG8(0x39b4), 0xcd },
+ { CCI_REG8(0x39b5), 0xcd }, { CCI_REG8(0x39b6), 0xcd },
+ { CCI_REG8(0x39b7), 0xcd }, { CCI_REG8(0x39b8), 0xcd },
+ { CCI_REG8(0x39b9), 0xcd }, { CCI_REG8(0x39ba), 0xcd },
+ { CCI_REG8(0x39bb), 0xcd }, { CCI_REG8(0x39bc), 0xcd },
+ { CCI_REG8(0x39bd), 0xcd }, { CCI_REG8(0x39be), 0xcd },
+ { CCI_REG8(0x39bf), 0xcd }, { CCI_REG8(0x39c0), 0xcd },
+ { CCI_REG8(0x39c1), 0xcd }, { CCI_REG8(0x39c2), 0xcd },
+ { CCI_REG8(0x39c3), 0xcd }, { CCI_REG8(0x39c4), 0xcd },
+ { CCI_REG8(0x39c5), 0xcd }, { CCI_REG8(0x39c6), 0xcd },
+ { CCI_REG8(0x39c7), 0xcd }, { CCI_REG8(0x39c8), 0xcd },
+ { CCI_REG8(0x39c9), 0xcd }, { CCI_REG8(0x39ca), 0xcd },
+ { CCI_REG8(0x39cb), 0xcd }, { CCI_REG8(0x39cc), 0xcd },
+ { CCI_REG8(0x39cd), 0xcd }, { CCI_REG8(0x39ce), 0xcd },
+ { CCI_REG8(0x39cf), 0xcd }, { CCI_REG8(0x39d0), 0xcd },
+ { CCI_REG8(0x39d1), 0xcd }, { CCI_REG8(0x39d2), 0xcd },
+ { CCI_REG8(0x39d3), 0xcd }, { CCI_REG8(0x39d4), 0xcd },
+ { CCI_REG8(0x39d5), 0xcd }, { CCI_REG8(0x39d6), 0xcd },
+ { CCI_REG8(0x39d7), 0xcd }, { CCI_REG8(0x39d8), 0xcd },
+ { CCI_REG8(0x39d9), 0xcd }, { CCI_REG8(0x39da), 0xcd },
+ { CCI_REG8(0x39db), 0xcd }, { CCI_REG8(0x39dc), 0xcd },
+ { CCI_REG8(0x39dd), 0xcd }, { CCI_REG8(0x39de), 0xcd },
+ { CCI_REG8(0x39df), 0xcd }, { CCI_REG8(0x39e0), 0xcd },
+ { CCI_REG8(0x39e1), 0x40 }, { CCI_REG8(0x39e2), 0x40 },
+ { CCI_REG8(0x39e3), 0x40 }, { CCI_REG8(0x39e4), 0x40 },
+ { CCI_REG8(0x39e5), 0x40 }, { CCI_REG8(0x39e6), 0x40 },
+ { CCI_REG8(0x39e7), 0x40 }, { CCI_REG8(0x39e8), 0x40 },
+ { CCI_REG8(0x39e9), 0x40 }, { CCI_REG8(0x39ea), 0x40 },
+ { CCI_REG8(0x39eb), 0x40 }, { CCI_REG8(0x39ec), 0x40 },
+ { CCI_REG8(0x39ed), 0x40 }, { CCI_REG8(0x39ee), 0x40 },
+ { CCI_REG8(0x39ef), 0x40 }, { CCI_REG8(0x39f0), 0x40 },
+ { CCI_REG8(0x39f1), 0x40 }, { CCI_REG8(0x39f2), 0x40 },
+ { CCI_REG8(0x39f3), 0x40 }, { CCI_REG8(0x39f4), 0x40 },
+ { CCI_REG8(0x39f5), 0x40 }, { CCI_REG8(0x39f6), 0x40 },
+ { CCI_REG8(0x39f7), 0x40 }, { CCI_REG8(0x39f8), 0x40 },
+ { CCI_REG8(0x39f9), 0x40 }, { CCI_REG8(0x39fa), 0x40 },
+ { CCI_REG8(0x39fb), 0x40 }, { CCI_REG8(0x39fc), 0x40 },
+ { CCI_REG8(0x39fd), 0x40 }, { CCI_REG8(0x39fe), 0x40 },
+ { CCI_REG8(0x39ff), 0x40 }, { CCI_REG8(0x3a00), 0x40 },
+ { CCI_REG8(0x3a01), 0x40 }, { CCI_REG8(0x3a02), 0x40 },
+ { CCI_REG8(0x3a03), 0x40 }, { CCI_REG8(0x3a04), 0x40 },
+ { CCI_REG8(0x3a05), 0x40 }, { CCI_REG8(0x3a06), 0x40 },
+ { CCI_REG8(0x3a07), 0x40 }, { CCI_REG8(0x3a08), 0x40 },
+ { CCI_REG8(0x3a09), 0x40 }, { CCI_REG8(0x3a0a), 0x40 },
+ { CCI_REG8(0x3a0b), 0x40 }, { CCI_REG8(0x3a0c), 0x40 },
+ { CCI_REG8(0x3a0d), 0x40 }, { CCI_REG8(0x3a0e), 0x40 },
+ { CCI_REG8(0x3a0f), 0x40 }, { CCI_REG8(0x3a10), 0x40 },
+ { CCI_REG8(0x3a11), 0x40 }, { CCI_REG8(0x3a12), 0x40 },
+ { CCI_REG8(0x3a13), 0x40 }, { CCI_REG8(0x3a14), 0x40 },
+ { CCI_REG8(0x3a15), 0x40 }, { CCI_REG8(0x3a16), 0x40 },
+ { CCI_REG8(0x3a17), 0x40 }, { CCI_REG8(0x3a18), 0x40 },
+ { CCI_REG8(0x3a19), 0x40 }, { CCI_REG8(0x3a1a), 0x40 },
+ { CCI_REG8(0x3a1b), 0x40 }, { CCI_REG8(0x3a1c), 0x40 },
+ { CCI_REG8(0x3a1d), 0x40 }, { CCI_REG8(0x3a1e), 0x40 },
+ { CCI_REG8(0x3a1f), 0x40 }, { CCI_REG8(0x3a20), 0x40 },
+ { CCI_REG8(0x3a21), 0x40 }, { CCI_REG8(0x3a22), 0x40 },
+ { CCI_REG8(0x3a23), 0x40 }, { CCI_REG8(0x3a24), 0x40 },
+ { CCI_REG8(0x3a25), 0x40 }, { CCI_REG8(0x3a26), 0x40 },
+ { CCI_REG8(0x3a27), 0x40 }, { CCI_REG8(0x3a28), 0x40 },
+ { CCI_REG8(0x3a29), 0x40 }, { CCI_REG8(0x3a2a), 0x40 },
+ { CCI_REG8(0x3a2b), 0x40 }, { CCI_REG8(0x3a2c), 0x40 },
+ { CCI_REG8(0x3a2d), 0x40 }, { CCI_REG8(0x3a2e), 0x40 },
+ { CCI_REG8(0x3a2f), 0x40 }, { CCI_REG8(0x3a30), 0x40 },
+ { CCI_REG8(0x3a31), 0x40 }, { CCI_REG8(0x3a32), 0x40 },
+ { CCI_REG8(0x3a33), 0x40 }, { CCI_REG8(0x3a34), 0x40 },
+ { CCI_REG8(0x3a35), 0x40 }, { CCI_REG8(0x3a36), 0x40 },
+ { CCI_REG8(0x3a37), 0x40 }, { CCI_REG8(0x3a38), 0x40 },
+ { CCI_REG8(0x3a39), 0x40 }, { CCI_REG8(0x3a3a), 0x40 },
+ { CCI_REG8(0x3a3b), 0xcd }, { CCI_REG8(0x3a3c), 0xcd },
+ { CCI_REG8(0x3a3d), 0xcd }, { CCI_REG8(0x3a3e), 0xcd },
+ { CCI_REG8(0x3a3f), 0xcd }, { CCI_REG8(0x3a40), 0xcd },
+ { CCI_REG8(0x3a41), 0xcd }, { CCI_REG8(0x3a42), 0xcd },
+ { CCI_REG8(0x3a43), 0xcd }, { CCI_REG8(0x3a44), 0xcd },
+ { CCI_REG8(0x3a45), 0xcd }, { CCI_REG8(0x3a46), 0xcd },
+ { CCI_REG8(0x3a47), 0xcd }, { CCI_REG8(0x3a48), 0xcd },
+ { CCI_REG8(0x3a49), 0xcd }, { CCI_REG8(0x3a4a), 0xcd },
+ { CCI_REG8(0x3a4b), 0xcd }, { CCI_REG8(0x3a4c), 0xcd },
+ { CCI_REG8(0x3a4d), 0xcd }, { CCI_REG8(0x3a4e), 0xcd },
+ { CCI_REG8(0x3a4f), 0xcd }, { CCI_REG8(0x3a50), 0xcd },
+ { CCI_REG8(0x3a51), 0xcd }, { CCI_REG8(0x3a52), 0xcd },
+ { CCI_REG8(0x3a53), 0xcd }, { CCI_REG8(0x3a54), 0xcd },
+ { CCI_REG8(0x3a55), 0xcd }, { CCI_REG8(0x3a56), 0xcd },
+ { CCI_REG8(0x3a57), 0xcd }, { CCI_REG8(0x3a58), 0xcd },
+ { CCI_REG8(0x3a59), 0xcd }, { CCI_REG8(0x3a5a), 0xcd },
+ { CCI_REG8(0x3a5b), 0xcd }, { CCI_REG8(0x3a5c), 0xcd },
+ { CCI_REG8(0x3a5d), 0xcd }, { CCI_REG8(0x3a5e), 0xcd },
+ { CCI_REG8(0x3a5f), 0xcd }, { CCI_REG8(0x3a60), 0xcd },
+ { CCI_REG8(0x3a61), 0xcd }, { CCI_REG8(0x3a62), 0xcd },
+ { CCI_REG8(0x3a63), 0xcd }, { CCI_REG8(0x3a64), 0xcd },
+ { CCI_REG8(0x3a65), 0xcd }, { CCI_REG8(0x3a66), 0xcd },
+ { CCI_REG8(0x3a67), 0xcd }, { CCI_REG8(0x3a68), 0xcd },
+ { CCI_REG8(0x3a69), 0xcd }, { CCI_REG8(0x3a6a), 0xcd },
+ { CCI_REG8(0x3a6b), 0xcd }, { CCI_REG8(0x3a6c), 0xcd },
+ { CCI_REG8(0x3a6d), 0xcd }, { CCI_REG8(0x3a6e), 0xcd },
+ { CCI_REG8(0x3a6f), 0xcd }, { CCI_REG8(0x3a70), 0xcd },
+ { CCI_REG8(0x3a71), 0xcd }, { CCI_REG8(0x3a72), 0xcd },
+ { CCI_REG8(0x3a73), 0xcd }, { CCI_REG8(0x3a74), 0xcd },
+ { CCI_REG8(0x3a75), 0xcd }, { CCI_REG8(0x3a76), 0xcd },
+ { CCI_REG8(0x3a77), 0xcd }, { CCI_REG8(0x3a78), 0xcd },
+ { CCI_REG8(0x3a79), 0xcd }, { CCI_REG8(0x3a7a), 0xcd },
+ { CCI_REG8(0x3a7b), 0xcd }, { CCI_REG8(0x3a7c), 0xcd },
+ { CCI_REG8(0x3a7d), 0xcd }, { CCI_REG8(0x3a7e), 0xcd },
+ { CCI_REG8(0x3a7f), 0xcd }, { CCI_REG8(0x3a80), 0xcd },
+ { CCI_REG8(0x3a81), 0xcd }, { CCI_REG8(0x3a82), 0xcd },
+ { CCI_REG8(0x3a83), 0xcd }, { CCI_REG8(0x3a84), 0xcd },
+ { CCI_REG8(0x3a85), 0xcd }, { CCI_REG8(0x3a86), 0xcd },
+ { CCI_REG8(0x3a87), 0xcd }, { CCI_REG8(0x3a88), 0xcd },
+ { CCI_REG8(0x3a89), 0xcd }, { CCI_REG8(0x3a8a), 0xcd },
+ { CCI_REG8(0x3a8b), 0xcd }, { CCI_REG8(0x3a8c), 0xcd },
+ { CCI_REG8(0x3a8d), 0xcd }, { CCI_REG8(0x3a8e), 0xcd },
+ { CCI_REG8(0x3a8f), 0xcd }, { CCI_REG8(0x3a90), 0xcd },
+ { CCI_REG8(0x3a91), 0xcd }, { CCI_REG8(0x3a92), 0xcd },
+ { CCI_REG8(0x3a93), 0xcd }, { CCI_REG8(0x3a94), 0xcd },
+ { CCI_REG8(0x3a95), 0x40 }, { CCI_REG8(0x3a96), 0x40 },
+ { CCI_REG8(0x3a97), 0x40 }, { CCI_REG8(0x3a98), 0x40 },
+ { CCI_REG8(0x3a99), 0x40 }, { CCI_REG8(0x3a9a), 0x40 },
+ { CCI_REG8(0x3a9b), 0x40 }, { CCI_REG8(0x3a9c), 0x40 },
+ { CCI_REG8(0x3a9d), 0x40 }, { CCI_REG8(0x3a9e), 0x40 },
+ { CCI_REG8(0x3a9f), 0x40 }, { CCI_REG8(0x3aa0), 0x40 },
+ { CCI_REG8(0x3aa1), 0x40 }, { CCI_REG8(0x3aa2), 0x40 },
+ { CCI_REG8(0x3aa3), 0x40 }, { CCI_REG8(0x3aa4), 0x40 },
+ { CCI_REG8(0x3aa5), 0x40 }, { CCI_REG8(0x3aa6), 0x40 },
+ { CCI_REG8(0x3aa7), 0x40 }, { CCI_REG8(0x3aa8), 0x40 },
+ { CCI_REG8(0x3aa9), 0x40 }, { CCI_REG8(0x3aaa), 0x40 },
+ { CCI_REG8(0x3aab), 0x40 }, { CCI_REG8(0x3aac), 0x40 },
+ { CCI_REG8(0x3aad), 0x40 }, { CCI_REG8(0x3aae), 0x40 },
+ { CCI_REG8(0x3aaf), 0x40 }, { CCI_REG8(0x3ab0), 0x40 },
+ { CCI_REG8(0x3ab1), 0x40 }, { CCI_REG8(0x3ab2), 0x40 },
+ { CCI_REG8(0x3ab3), 0x40 }, { CCI_REG8(0x3ab4), 0x40 },
+ { CCI_REG8(0x3ab5), 0x40 }, { CCI_REG8(0x3ab6), 0x40 },
+ { CCI_REG8(0x3ab7), 0x40 }, { CCI_REG8(0x3ab8), 0x40 },
+ { CCI_REG8(0x3ab9), 0x40 }, { CCI_REG8(0x3aba), 0x40 },
+ { CCI_REG8(0x3abb), 0x40 }, { CCI_REG8(0x3abc), 0x40 },
+ { CCI_REG8(0x3abd), 0x40 }, { CCI_REG8(0x3abe), 0x40 },
+ { CCI_REG8(0x3abf), 0x40 }, { CCI_REG8(0x3ac0), 0x40 },
+ { CCI_REG8(0x3ac1), 0x40 }, { CCI_REG8(0x3ac2), 0x40 },
+ { CCI_REG8(0x3ac3), 0x40 }, { CCI_REG8(0x3ac4), 0x40 },
+ { CCI_REG8(0x3ac5), 0x40 }, { CCI_REG8(0x3ac6), 0x40 },
+ { CCI_REG8(0x3ac7), 0x40 }, { CCI_REG8(0x3ac8), 0x40 },
+ { CCI_REG8(0x3ac9), 0x40 }, { CCI_REG8(0x3aca), 0x40 },
+ { CCI_REG8(0x3acb), 0x40 }, { CCI_REG8(0x3acc), 0x40 },
+ { CCI_REG8(0x3acd), 0x40 }, { CCI_REG8(0x3ace), 0x40 },
+ { CCI_REG8(0x3acf), 0x40 }, { CCI_REG8(0x3ad0), 0x40 },
+ { CCI_REG8(0x3ad1), 0x40 }, { CCI_REG8(0x3ad2), 0x40 },
+ { CCI_REG8(0x3ad3), 0x40 }, { CCI_REG8(0x3ad4), 0x40 },
+ { CCI_REG8(0x3ad5), 0x40 }, { CCI_REG8(0x3ad6), 0x40 },
+ { CCI_REG8(0x3ad7), 0x40 }, { CCI_REG8(0x3ad8), 0x40 },
+ { CCI_REG8(0x3ad9), 0x40 }, { CCI_REG8(0x3ada), 0x40 },
+ { CCI_REG8(0x3adb), 0x40 }, { CCI_REG8(0x3adc), 0x40 },
+ { CCI_REG8(0x3add), 0x40 }, { CCI_REG8(0x3ade), 0x40 },
+ { CCI_REG8(0x3adf), 0x40 }, { CCI_REG8(0x3ae0), 0x40 },
+ { CCI_REG8(0x3ae1), 0x40 }, { CCI_REG8(0x3ae2), 0x40 },
+ { CCI_REG8(0x3ae3), 0x40 }, { CCI_REG8(0x3ae4), 0x40 },
+ { CCI_REG8(0x3ae5), 0x40 }, { CCI_REG8(0x3ae6), 0x40 },
+ { CCI_REG8(0x3ae7), 0x40 }, { CCI_REG8(0x3ae8), 0x40 },
+ { CCI_REG8(0x3ae9), 0x40 }, { CCI_REG8(0x3aea), 0x40 },
+ { CCI_REG8(0x3aeb), 0x40 }, { CCI_REG8(0x3aec), 0x40 },
+ { CCI_REG8(0x3aed), 0x40 }, { CCI_REG8(0x3aee), 0x40 },
+ { CCI_REG8(0x3aef), 0xcd }, { CCI_REG8(0x3af0), 0xcd },
+ { CCI_REG8(0x3af1), 0xcd }, { CCI_REG8(0x3af2), 0xcd },
+ { CCI_REG8(0x3af3), 0xcd }, { CCI_REG8(0x3af4), 0xcd },
+ { CCI_REG8(0x3af5), 0xcd }, { CCI_REG8(0x3af6), 0xcd },
+ { CCI_REG8(0x3af7), 0xcd }, { CCI_REG8(0x3af8), 0xcd },
+ { CCI_REG8(0x3af9), 0xcd }, { CCI_REG8(0x3afa), 0xcd },
+ { CCI_REG8(0x3afb), 0xcd }, { CCI_REG8(0x3afc), 0xcd },
+ { CCI_REG8(0x3afd), 0xcd }, { CCI_REG8(0x3afe), 0xcd },
+ { CCI_REG8(0x3aff), 0xcd }, { CCI_REG8(0x3b00), 0xcd },
+ { CCI_REG8(0x3b01), 0xcd }, { CCI_REG8(0x3b02), 0xcd },
+ { CCI_REG8(0x3b03), 0xcd }, { CCI_REG8(0x3b04), 0xcd },
+ { CCI_REG8(0x3b05), 0xcd }, { CCI_REG8(0x3b06), 0xcd },
+ { CCI_REG8(0x3b07), 0xcd }, { CCI_REG8(0x3b08), 0xcd },
+ { CCI_REG8(0x3b09), 0xcd }, { CCI_REG8(0x3b0a), 0xcd },
+ { CCI_REG8(0x3b0b), 0xcd }, { CCI_REG8(0x3b0c), 0xcd },
+ { CCI_REG8(0x3b0d), 0xcd }, { CCI_REG8(0x3b0e), 0xcd },
+ { CCI_REG8(0x3b0f), 0xcd }, { CCI_REG8(0x3b10), 0xcd },
+ { CCI_REG8(0x3b11), 0xcd }, { CCI_REG8(0x3b12), 0xcd },
+ { CCI_REG8(0x3b13), 0xcd }, { CCI_REG8(0x3b14), 0xcd },
+ { CCI_REG8(0x3b15), 0xcd }, { CCI_REG8(0x3b16), 0xcd },
+ { CCI_REG8(0x3b17), 0xcd }, { CCI_REG8(0x3b18), 0xcd },
+ { CCI_REG8(0x3b19), 0xcd }, { CCI_REG8(0x3b1a), 0xcd },
+ { CCI_REG8(0x3b1b), 0xcd }, { CCI_REG8(0x3b1c), 0xcd },
+ { CCI_REG8(0x3b1d), 0xcd }, { CCI_REG8(0x3b1e), 0xcd },
+ { CCI_REG8(0x3b1f), 0xcd }, { CCI_REG8(0x3b20), 0xcd },
+ { CCI_REG8(0x3b21), 0xcd }, { CCI_REG8(0x3b22), 0xcd },
+ { CCI_REG8(0x3b23), 0xcd }, { CCI_REG8(0x3b24), 0xcd },
+ { CCI_REG8(0x3b25), 0xcd }, { CCI_REG8(0x3b26), 0xcd },
+ { CCI_REG8(0x3b27), 0xcd }, { CCI_REG8(0x3b28), 0xcd },
+ { CCI_REG8(0x3b29), 0xcd }, { CCI_REG8(0x3b2a), 0xcd },
+ { CCI_REG8(0x3b2b), 0xcd }, { CCI_REG8(0x3b2c), 0xcd },
+ { CCI_REG8(0x3b2d), 0xcd }, { CCI_REG8(0x3b2e), 0xcd },
+ { CCI_REG8(0x3b2f), 0xcd }, { CCI_REG8(0x3b30), 0xcd },
+ { CCI_REG8(0x3b31), 0xcd }, { CCI_REG8(0x3b32), 0xcd },
+ { CCI_REG8(0x3b33), 0xcd }, { CCI_REG8(0x3b34), 0xcd },
+ { CCI_REG8(0x3b35), 0xcd }, { CCI_REG8(0x3b36), 0xcd },
+ { CCI_REG8(0x3b37), 0xcd }, { CCI_REG8(0x3b38), 0xcd },
+ { CCI_REG8(0x3b39), 0xcd }, { CCI_REG8(0x3b3a), 0xcd },
+ { CCI_REG8(0x3b3b), 0xcd }, { CCI_REG8(0x3b3c), 0xcd },
+ { CCI_REG8(0x3b3d), 0xcd }, { CCI_REG8(0x3b3e), 0xcd },
+ { CCI_REG8(0x3b3f), 0xcd }, { CCI_REG8(0x3b40), 0xcd },
+ { CCI_REG8(0x3b41), 0xcd }, { CCI_REG8(0x3b42), 0xcd },
+ { CCI_REG8(0x3b43), 0xcd }, { CCI_REG8(0x3b44), 0xcd },
+ { CCI_REG8(0x3b45), 0xcd }, { CCI_REG8(0x3b46), 0xcd },
+ { CCI_REG8(0x3b47), 0xcd }, { CCI_REG8(0x3b48), 0xcd },
+ { CCI_REG8(0x3b49), 0xcd }, { CCI_REG8(0x3b4a), 0xcd },
+ { CCI_REG8(0x3b4b), 0xcd }, { CCI_REG8(0x3b4c), 0xcd },
+ { CCI_REG8(0x3b4d), 0xcd }, { CCI_REG8(0x3b4e), 0xcd },
+ { CCI_REG8(0x3b4f), 0xcd }, { CCI_REG8(0x3b50), 0xcd },
+ { CCI_REG8(0x3b51), 0xcd }, { CCI_REG8(0x3b52), 0xcd },
+ { CCI_REG8(0x3b53), 0xcd }, { CCI_REG8(0x3b54), 0xcd },
+ { CCI_REG8(0x3b55), 0xcd }, { CCI_REG8(0x3b56), 0xcd },
+ { CCI_REG8(0x3b57), 0xcd }, { CCI_REG8(0x3b58), 0xcd },
+ { CCI_REG8(0x3b59), 0xcd }, { CCI_REG8(0x3b5a), 0xcd },
+ { CCI_REG8(0x3b5b), 0xcd }, { CCI_REG8(0x3b5c), 0xcd },
+ { CCI_REG8(0x3b5d), 0xcd }, { CCI_REG8(0x3b5e), 0xcd },
+ { CCI_REG8(0x3b5f), 0xcd }, { CCI_REG8(0x3b60), 0xcd },
+ { CCI_REG8(0x3b61), 0xcd }, { CCI_REG8(0x3b62), 0xcd },
+ { CCI_REG8(0x3b63), 0xcd }, { CCI_REG8(0x3b64), 0xcd },
+ { CCI_REG8(0x3b65), 0xcd }, { CCI_REG8(0x3b66), 0xcd },
+ { CCI_REG8(0x3b67), 0xcd }, { CCI_REG8(0x3b68), 0xcd },
+ { CCI_REG8(0x3b69), 0xcd }, { CCI_REG8(0x3b6a), 0xcd },
+ { CCI_REG8(0x3b6b), 0xcd }, { CCI_REG8(0x3b6c), 0xcd },
+ { CCI_REG8(0x3b6d), 0xcd }, { CCI_REG8(0x3b6e), 0xcd },
+ { CCI_REG8(0x3b6f), 0xcd }, { CCI_REG8(0x3b70), 0xcd },
+ { CCI_REG8(0x3b71), 0xcd }, { CCI_REG8(0x3b72), 0xcd },
+ { CCI_REG8(0x3b73), 0xcd }, { CCI_REG8(0x3b74), 0xcd },
+ { CCI_REG8(0x3b75), 0xcd }, { CCI_REG8(0x3b76), 0xcd },
+ { CCI_REG8(0x3b77), 0xcd }, { CCI_REG8(0x3b78), 0xcd },
+ { CCI_REG8(0x3b79), 0xcd }, { CCI_REG8(0x3b7a), 0xcd },
+ { CCI_REG8(0x3b7b), 0xcd }, { CCI_REG8(0x3b7c), 0xcd },
+ { CCI_REG8(0x3b7d), 0xcd }, { CCI_REG8(0x3b7e), 0xcd },
+ { CCI_REG8(0x3b7f), 0xcd }, { CCI_REG8(0x3b80), 0xcd },
+ { CCI_REG8(0x3b81), 0xcd }, { CCI_REG8(0x3b82), 0xcd },
+ { CCI_REG8(0x3b83), 0xcd }, { CCI_REG8(0x3b84), 0xcd },
+ { CCI_REG8(0x3b85), 0xcd }, { CCI_REG8(0x3b86), 0xcd },
+ { CCI_REG8(0x3b87), 0xcd }, { CCI_REG8(0x3b88), 0xcd },
+ { CCI_REG8(0x3b89), 0xcd }, { CCI_REG8(0x3b8a), 0xcd },
+ { CCI_REG8(0x3b8b), 0xcd }, { CCI_REG8(0x3b8c), 0xcd },
+ { CCI_REG8(0x3b8d), 0xcd }, { CCI_REG8(0x3b8e), 0xcd },
+ { CCI_REG8(0x3b8f), 0xcd }, { CCI_REG8(0x3b90), 0xcd },
+ { CCI_REG8(0x3b91), 0xcd }, { CCI_REG8(0x3b92), 0xcd },
+ { CCI_REG8(0x3b93), 0xcd }, { CCI_REG8(0x3b94), 0xcd },
+ { CCI_REG8(0x3b95), 0xcd }, { CCI_REG8(0x3b96), 0xcd },
+ { CCI_REG8(0x3b97), 0xcd }, { CCI_REG8(0x3b98), 0xcd },
+ { CCI_REG8(0x3b99), 0xcd }, { CCI_REG8(0x3b9a), 0xcd },
+ { CCI_REG8(0x3b9b), 0xcd }, { CCI_REG8(0x3b9c), 0xcd },
+ { CCI_REG8(0x3b9d), 0xcd }, { CCI_REG8(0x3b9e), 0xcd },
+ { CCI_REG8(0x3b9f), 0xcd }, { CCI_REG8(0x3ba0), 0xcd },
+ { CCI_REG8(0x3ba1), 0xcd }, { CCI_REG8(0x3ba2), 0xcd },
+ { CCI_REG8(0x3ba3), 0xcd }, { CCI_REG8(0x3ba4), 0xcd },
+ { CCI_REG8(0x3ba5), 0xcd }, { CCI_REG8(0x3ba6), 0xcd },
+ { CCI_REG8(0x3ba7), 0xcd }, { CCI_REG8(0x3ba8), 0xcd },
+ { CCI_REG8(0x3ba9), 0xcd }, { CCI_REG8(0x3baa), 0xcd },
+ { CCI_REG8(0x3bab), 0xcd }, { CCI_REG8(0x3bac), 0xcd },
+ { CCI_REG8(0x3bad), 0xcd }, { CCI_REG8(0x3bae), 0xcd },
+ { CCI_REG8(0x3baf), 0xcd }, { CCI_REG8(0x3bb0), 0xcd },
+ { CCI_REG8(0x3bb1), 0xcd }, { CCI_REG8(0x3bb2), 0xcd },
+ { CCI_REG8(0x3bb3), 0xcd }, { CCI_REG8(0x3bb4), 0xcd },
+ { CCI_REG8(0x3bb5), 0xcd }, { CCI_REG8(0x3bb6), 0xcd },
+ { CCI_REG8(0x3bb7), 0xcd }, { CCI_REG8(0x3bb8), 0xcd },
+ { CCI_REG8(0x3bb9), 0xcd }, { CCI_REG8(0x3bba), 0xcd },
+ { CCI_REG8(0x3bbb), 0xcd }, { CCI_REG8(0x3bbc), 0xcd },
+ { CCI_REG8(0x3bbd), 0xcd }, { CCI_REG8(0x3bbe), 0xcd },
+ { CCI_REG8(0x3bbf), 0xcd }, { CCI_REG8(0x3bc0), 0xcd },
+ { CCI_REG8(0x3bc1), 0xcd }, { CCI_REG8(0x3bc2), 0xcd },
+ { CCI_REG8(0x3bc3), 0xcd }, { CCI_REG8(0x3bc4), 0xcd },
+ { CCI_REG8(0x3bc5), 0xcd }, { CCI_REG8(0x3bc6), 0xcd },
+ { CCI_REG8(0x3bc7), 0xcd }, { CCI_REG8(0x3bc8), 0xcd },
+ { CCI_REG8(0x3bc9), 0xcd }, { CCI_REG8(0x3bca), 0xcd },
+ { CCI_REG8(0x3bcb), 0xcd }, { CCI_REG8(0x3bcc), 0xcd },
+ { CCI_REG8(0x3bcd), 0xcd }, { CCI_REG8(0x3bce), 0xcd },
+ { CCI_REG8(0x3bcf), 0xcd }, { CCI_REG8(0x3bd0), 0xcd },
+ { CCI_REG8(0x3bd1), 0xcd }, { CCI_REG8(0x3bd2), 0xcd },
+ { CCI_REG8(0x3bd3), 0xcd }, { CCI_REG8(0x3bd4), 0xcd },
+ { CCI_REG8(0x3bd5), 0xcd }, { CCI_REG8(0x3bd6), 0xcd },
+ { CCI_REG8(0x3bd7), 0xcd }, { CCI_REG8(0x3bd8), 0xcd },
+ { CCI_REG8(0x3bd9), 0xcd }, { CCI_REG8(0x3bda), 0xcd },
+ { CCI_REG8(0x3bdb), 0xcd }, { CCI_REG8(0x3bdc), 0xcd },
+ { CCI_REG8(0x3bdd), 0xcd }, { CCI_REG8(0x3bde), 0xcd },
+ { CCI_REG8(0x3bdf), 0xcd }, { CCI_REG8(0x3be0), 0xcd },
+ { CCI_REG8(0x3be1), 0xcd }, { CCI_REG8(0x3be2), 0xcd },
+ { CCI_REG8(0x3be3), 0xcd }, { CCI_REG8(0x3be4), 0xcd },
+ { CCI_REG8(0x3be5), 0xcd }, { CCI_REG8(0x3be6), 0xcd },
+ { CCI_REG8(0x3be7), 0xcd }, { CCI_REG8(0x3be8), 0xcd },
+ { CCI_REG8(0x3be9), 0xcd }, { CCI_REG8(0x3bea), 0xcd },
+ { CCI_REG8(0x3beb), 0xcd }, { CCI_REG8(0x3bec), 0xcd },
+ { CCI_REG8(0x3bed), 0xcd }, { CCI_REG8(0x3bee), 0xcd },
+ { CCI_REG8(0x3bef), 0xcd }, { CCI_REG8(0x3bf0), 0xcd },
+ { CCI_REG8(0x3bf1), 0xcd }, { CCI_REG8(0x3bf2), 0xcd },
+ { CCI_REG8(0x3bf3), 0xcd }, { CCI_REG8(0x3bf4), 0xcd },
+ { CCI_REG8(0x3bf5), 0xcd }, { CCI_REG8(0x3bf6), 0xcd },
+ { CCI_REG8(0x3bf7), 0xcd }, { CCI_REG8(0x3bf8), 0xcd },
+ { CCI_REG8(0x3bf9), 0xcd }, { CCI_REG8(0x3bfa), 0xcd },
+ { CCI_REG8(0x3bfb), 0xcd }, { CCI_REG8(0x3bfc), 0xcd },
+ { CCI_REG8(0x3bfd), 0xcd }, { CCI_REG8(0x3bfe), 0xcd },
+ { CCI_REG8(0x3bff), 0xcd }, { CCI_REG8(0x3c00), 0xcd },
+ { CCI_REG8(0x3c01), 0xcd }, { CCI_REG8(0x3c02), 0xcd },
+ { CCI_REG8(0x3c03), 0xcd }, { CCI_REG8(0x3c04), 0xcd },
+ { CCI_REG8(0x3c05), 0xcd }, { CCI_REG8(0x3c06), 0xcd },
+ { CCI_REG8(0x3c07), 0xcd }, { CCI_REG8(0x3c08), 0xcd },
+ { CCI_REG8(0x3c09), 0xcd }, { CCI_REG8(0x3c0a), 0xcd },
+ { CCI_REG8(0x3c0b), 0xcd }, { CCI_REG8(0x3c0c), 0xcd },
+ { CCI_REG8(0x3c0d), 0xcd }, { CCI_REG8(0x3c0e), 0xcd },
+ { CCI_REG8(0x3c0f), 0xcd }, { CCI_REG8(0x3c10), 0xcd },
+ { CCI_REG8(0x3c11), 0xcd }, { CCI_REG8(0x3c12), 0xcd },
+ { CCI_REG8(0x3c13), 0xcd }, { CCI_REG8(0x3c14), 0xcd },
+ { CCI_REG8(0x3c15), 0xcd }, { CCI_REG8(0x3c16), 0xcd },
+ { CCI_REG8(0x3c17), 0xcd }, { CCI_REG8(0x3c18), 0xcd },
+ { CCI_REG8(0x3c19), 0xcd }, { CCI_REG8(0x3c1a), 0xcd },
+ { CCI_REG8(0x3c1b), 0xcd }, { CCI_REG8(0x3c1c), 0xcd },
+ { CCI_REG8(0x3c1d), 0xcd }, { CCI_REG8(0x3c1e), 0xcd },
+ { CCI_REG8(0x3c1f), 0xcd }, { CCI_REG8(0x3c20), 0xcd },
+ { CCI_REG8(0x3c21), 0xcd }, { CCI_REG8(0x3c22), 0xcd },
+ { CCI_REG8(0x3c23), 0xcd }, { CCI_REG8(0x3c24), 0xcd },
+ { CCI_REG8(0x3c25), 0xcd }, { CCI_REG8(0x3c26), 0xcd },
+ { CCI_REG8(0x3c27), 0xcd }, { CCI_REG8(0x3c28), 0xcd },
+ { CCI_REG8(0x3c29), 0xcd }, { CCI_REG8(0x3c2a), 0xcd },
+ { CCI_REG8(0x3c2b), 0xcd }, { CCI_REG8(0x3c2c), 0xcd },
+ { CCI_REG8(0x3c2d), 0xcd }, { CCI_REG8(0x3c2e), 0xcd },
+ { CCI_REG8(0x3c2f), 0xcd }, { CCI_REG8(0x3c30), 0xcd },
+ { CCI_REG8(0x3c31), 0xcd }, { CCI_REG8(0x3c32), 0xcd },
+ { CCI_REG8(0x3c33), 0xcd }, { CCI_REG8(0x3c34), 0xcd },
+ { CCI_REG8(0x3c35), 0xcd }, { CCI_REG8(0x3c36), 0xcd },
+ { CCI_REG8(0x3c37), 0xcd }, { CCI_REG8(0x3c38), 0xcd },
+ { CCI_REG8(0x3c39), 0xcd }, { CCI_REG8(0x3c3a), 0xcd },
+ { CCI_REG8(0x3c3b), 0xcd }, { CCI_REG8(0x3c3c), 0xcd },
+ { CCI_REG8(0x3c3d), 0xcd }, { CCI_REG8(0x3c3e), 0xcd },
+ { CCI_REG8(0x3c3f), 0xcd }, { CCI_REG8(0x3c40), 0xcd },
+ { CCI_REG8(0x3c41), 0xcd }, { CCI_REG8(0x3c42), 0xcd },
+ { CCI_REG8(0x3c43), 0xcd }, { CCI_REG8(0x3c44), 0xcd },
+ { CCI_REG8(0x3c45), 0xcd }, { CCI_REG8(0x3c46), 0xcd },
+ { CCI_REG8(0x3c47), 0xcd }, { CCI_REG8(0x3c48), 0xcd },
+ { CCI_REG8(0x3c49), 0xcd }, { CCI_REG8(0x3c4a), 0xcd },
+ { CCI_REG8(0x3c4b), 0xcd }, { CCI_REG8(0x3c4c), 0xcd },
+ { CCI_REG8(0x3c4d), 0xcd }, { CCI_REG8(0x3c4e), 0xcd },
+ { CCI_REG8(0x3c4f), 0xcd }, { CCI_REG8(0x3c50), 0xcd },
+ { CCI_REG8(0x3c51), 0xcd }, { CCI_REG8(0x3c52), 0xcd },
+ { CCI_REG8(0x3c53), 0xcd }, { CCI_REG8(0x3c54), 0xcd },
+ { CCI_REG8(0x3c55), 0xcd }, { CCI_REG8(0x3c56), 0xcd },
+ { CCI_REG8(0x3c57), 0xcd }, { CCI_REG8(0x3c58), 0xcd },
+ { CCI_REG8(0x3c59), 0xcd }, { CCI_REG8(0x3c5a), 0xcd },
+ { CCI_REG8(0x3c5b), 0xcd }, { CCI_REG8(0x3c5c), 0xcd },
+ { CCI_REG8(0x3c5d), 0xcd }, { CCI_REG8(0x3c5e), 0xcd },
+ { CCI_REG8(0x3c5f), 0xcd }, { CCI_REG8(0x3c60), 0xcd },
+ { CCI_REG8(0x3c61), 0xcd }, { CCI_REG8(0x3c62), 0xcd },
+ { CCI_REG8(0x3c63), 0xcd }, { CCI_REG8(0x3c64), 0xcd },
+ { CCI_REG8(0x3c65), 0xcd }, { CCI_REG8(0x3c66), 0xcd },
+ { CCI_REG8(0x3c67), 0xcd }, { CCI_REG8(0x3c68), 0xcd },
+ { CCI_REG8(0x3c69), 0xcd }, { CCI_REG8(0x3c6a), 0xcd },
+ { CCI_REG8(0x3c6b), 0xcd }, { CCI_REG8(0x3c6c), 0xcd },
+ { CCI_REG8(0x3c6d), 0xcd }, { CCI_REG8(0x3c6e), 0xcd },
+ { CCI_REG8(0x3c6f), 0xcd }, { CCI_REG8(0x3c70), 0xcd },
+ { CCI_REG8(0x3c71), 0xcd }, { CCI_REG8(0x3c72), 0xcd },
+ { CCI_REG8(0x3c73), 0xcd }, { CCI_REG8(0x3c74), 0xcd },
+ { CCI_REG8(0x3c75), 0xcd }, { CCI_REG8(0x3c76), 0xcd },
+ { CCI_REG8(0x3c77), 0xcd }, { CCI_REG8(0x3c78), 0xcd },
+ { CCI_REG8(0x3c79), 0xcd }, { CCI_REG8(0x3c7a), 0xcd },
+ { CCI_REG8(0x3c7b), 0xcd }, { CCI_REG8(0x3c7c), 0xcd },
+ { CCI_REG8(0x3c7d), 0xcd }, { CCI_REG8(0x3c7e), 0xcd },
+ { CCI_REG8(0x3c7f), 0xcd }, { CCI_REG8(0x3c80), 0xcd },
+ { CCI_REG8(0x3c81), 0xcd }, { CCI_REG8(0x3c82), 0xcd },
+ { CCI_REG8(0x3c83), 0xcd }, { CCI_REG8(0x3c84), 0xcd },
+ { CCI_REG8(0x3c85), 0xcd }, { CCI_REG8(0x3c86), 0xcd },
+ { CCI_REG8(0x3c87), 0xcd }, { CCI_REG8(0x3c88), 0xcd },
+ { CCI_REG8(0x3c89), 0xcd }, { CCI_REG8(0x3c8a), 0xcd },
+ { CCI_REG8(0x3c8b), 0xcd }, { CCI_REG8(0x3c8c), 0xcd },
+ { CCI_REG8(0x3c8d), 0xcd }, { CCI_REG8(0x3c8e), 0xcd },
+ { CCI_REG8(0x3c8f), 0xcd }, { CCI_REG8(0x3c90), 0xcd },
+ { CCI_REG8(0x3c91), 0xcd }, { CCI_REG8(0x3c92), 0xcd },
+ { CCI_REG8(0x3c93), 0xcd }, { CCI_REG8(0x3c94), 0xcd },
+ { CCI_REG8(0x3c95), 0xcd }, { CCI_REG8(0x3c96), 0xcd },
+ { CCI_REG8(0x3c97), 0xcd }, { CCI_REG8(0x3c98), 0xcd },
+ { CCI_REG8(0x3c99), 0xcd }, { CCI_REG8(0x3c9a), 0xcd },
+ { CCI_REG8(0x3c9b), 0xcd }, { CCI_REG8(0x3c9c), 0xcd },
+ { CCI_REG8(0x3c9d), 0xcd }, { CCI_REG8(0x3c9e), 0xcd },
+ { CCI_REG8(0x3c9f), 0xcd }, { CCI_REG8(0x3ca0), 0xcd },
+ { CCI_REG8(0x3ca1), 0xcd }, { CCI_REG8(0x3ca2), 0xcd },
+ { CCI_REG8(0x3ca3), 0xcd }, { CCI_REG8(0x3ca4), 0xcd },
+ { CCI_REG8(0x3ca5), 0xcd }, { CCI_REG8(0x3ca6), 0xcd },
+ { CCI_REG8(0x3ca7), 0xcd }, { CCI_REG8(0x3ca8), 0xcd },
+ { CCI_REG8(0x3ca9), 0xcd }, { CCI_REG8(0x3caa), 0xcd },
+ { CCI_REG8(0x3cab), 0xcd }, { CCI_REG8(0x3cac), 0xcd },
+ { CCI_REG8(0x3cad), 0xcd }, { CCI_REG8(0x3cae), 0xcd },
+ { CCI_REG8(0x3caf), 0xcd }, { CCI_REG8(0x3cb0), 0xcd },
+ { CCI_REG8(0x3cb1), 0x40 }, { CCI_REG8(0x3cb2), 0x40 },
+ { CCI_REG8(0x3cb3), 0x40 }, { CCI_REG8(0x3cb4), 0x40 },
+ { CCI_REG8(0x3cb5), 0x40 }, { CCI_REG8(0x3cb6), 0x40 },
+ { CCI_REG8(0x3cb7), 0x40 }, { CCI_REG8(0x3cb8), 0x40 },
+ { CCI_REG8(0x3cb9), 0x40 }, { CCI_REG8(0x3cba), 0x40 },
+ { CCI_REG8(0x3cbb), 0x40 }, { CCI_REG8(0x3cbc), 0x40 },
+ { CCI_REG8(0x3cbd), 0x40 }, { CCI_REG8(0x3cbe), 0x40 },
+ { CCI_REG8(0x3cbf), 0x40 }, { CCI_REG8(0x3cc0), 0x40 },
+ { CCI_REG8(0x3cc1), 0x40 }, { CCI_REG8(0x3cc2), 0x40 },
+ { CCI_REG8(0x3cc3), 0x40 }, { CCI_REG8(0x3cc4), 0x40 },
+ { CCI_REG8(0x3cc5), 0x40 }, { CCI_REG8(0x3cc6), 0x40 },
+ { CCI_REG8(0x3cc7), 0x40 }, { CCI_REG8(0x3cc8), 0x40 },
+ { CCI_REG8(0x3cc9), 0x40 }, { CCI_REG8(0x3cca), 0x40 },
+ { CCI_REG8(0x3ccb), 0x40 }, { CCI_REG8(0x3ccc), 0x40 },
+ { CCI_REG8(0x3ccd), 0x40 }, { CCI_REG8(0x3cce), 0x40 },
+ { CCI_REG8(0x3ccf), 0x40 }, { CCI_REG8(0x3cd0), 0x40 },
+ { CCI_REG8(0x3cd1), 0x40 }, { CCI_REG8(0x3cd2), 0x40 },
+ { CCI_REG8(0x3cd3), 0x40 }, { CCI_REG8(0x3cd4), 0x40 },
+ { CCI_REG8(0x3cd5), 0x40 }, { CCI_REG8(0x3cd6), 0x40 },
+ { CCI_REG8(0x3cd7), 0x40 }, { CCI_REG8(0x3cd8), 0x40 },
+ { CCI_REG8(0x3cd9), 0x40 }, { CCI_REG8(0x3cda), 0x40 },
+ { CCI_REG8(0x3cdb), 0x40 }, { CCI_REG8(0x3cdc), 0x40 },
+ { CCI_REG8(0x3cdd), 0x40 }, { CCI_REG8(0x3cde), 0x40 },
+ { CCI_REG8(0x3cdf), 0x40 }, { CCI_REG8(0x3ce0), 0x40 },
+ { CCI_REG8(0x3ce1), 0x40 }, { CCI_REG8(0x3ce2), 0x40 },
+ { CCI_REG8(0x3ce3), 0x40 }, { CCI_REG8(0x3ce4), 0x40 },
+ { CCI_REG8(0x3ce5), 0x40 }, { CCI_REG8(0x3ce6), 0x40 },
+ { CCI_REG8(0x3ce7), 0x40 }, { CCI_REG8(0x3ce8), 0x40 },
+ { CCI_REG8(0x3ce9), 0x40 }, { CCI_REG8(0x3cea), 0x40 },
+ { CCI_REG8(0x3ceb), 0x40 }, { CCI_REG8(0x3cec), 0x40 },
+ { CCI_REG8(0x3ced), 0x40 }, { CCI_REG8(0x3cee), 0x40 },
+ { CCI_REG8(0x3cef), 0x40 }, { CCI_REG8(0x3cf0), 0x40 },
+ { CCI_REG8(0x3cf1), 0x40 }, { CCI_REG8(0x3cf2), 0x40 },
+ { CCI_REG8(0x3cf3), 0x40 }, { CCI_REG8(0x3cf4), 0x40 },
+ { CCI_REG8(0x3cf5), 0x40 }, { CCI_REG8(0x3cf6), 0x40 },
+ { CCI_REG8(0x3cf7), 0x40 }, { CCI_REG8(0x3cf8), 0x40 },
+ { CCI_REG8(0x3cf9), 0x40 }, { CCI_REG8(0x3cfa), 0x40 },
+ { CCI_REG8(0x3cfb), 0x40 }, { CCI_REG8(0x3cfc), 0x40 },
+ { CCI_REG8(0x3cfd), 0x40 }, { CCI_REG8(0x3cfe), 0x40 },
+ { CCI_REG8(0x3cff), 0x40 }, { CCI_REG8(0x3d00), 0x40 },
+ { CCI_REG8(0x3d01), 0x40 }, { CCI_REG8(0x3d02), 0x40 },
+ { CCI_REG8(0x3d03), 0x40 }, { CCI_REG8(0x3d04), 0x40 },
+ { CCI_REG8(0x3d05), 0x40 }, { CCI_REG8(0x3d06), 0x40 },
+ { CCI_REG8(0x3d07), 0x40 }, { CCI_REG8(0x3d08), 0x40 },
+ { CCI_REG8(0x3d09), 0x40 }, { CCI_REG8(0x3d0a), 0x40 },
+ { CCI_REG8(0x3d0b), 0xcd }, { CCI_REG8(0x3d0c), 0xcd },
+ { CCI_REG8(0x3d0d), 0xcd }, { CCI_REG8(0x3d0e), 0xcd },
+ { CCI_REG8(0x3d0f), 0xcd }, { CCI_REG8(0x3d10), 0xcd },
+ { CCI_REG8(0x3d11), 0xcd }, { CCI_REG8(0x3d12), 0xcd },
+ { CCI_REG8(0x3d13), 0xcd }, { CCI_REG8(0x3d14), 0xcd },
+ { CCI_REG8(0x3d15), 0xcd }, { CCI_REG8(0x3d16), 0xcd },
+ { CCI_REG8(0x3d17), 0xcd }, { CCI_REG8(0x3d18), 0xcd },
+ { CCI_REG8(0x3d19), 0xcd }, { CCI_REG8(0x3d1a), 0xcd },
+ { CCI_REG8(0x3d1b), 0xcd }, { CCI_REG8(0x3d1c), 0xcd },
+ { CCI_REG8(0x3d1d), 0xcd }, { CCI_REG8(0x3d1e), 0xcd },
+ { CCI_REG8(0x3d1f), 0xcd }, { CCI_REG8(0x3d20), 0xcd },
+ { CCI_REG8(0x3d21), 0xcd }, { CCI_REG8(0x3d22), 0xcd },
+ { CCI_REG8(0x3d23), 0xcd }, { CCI_REG8(0x3d24), 0xcd },
+ { CCI_REG8(0x3d25), 0xcd }, { CCI_REG8(0x3d26), 0xcd },
+ { CCI_REG8(0x3d27), 0xcd }, { CCI_REG8(0x3d28), 0xcd },
+ { CCI_REG8(0x3d29), 0xcd }, { CCI_REG8(0x3d2a), 0xcd },
+ { CCI_REG8(0x3d2b), 0xcd }, { CCI_REG8(0x3d2c), 0xcd },
+ { CCI_REG8(0x3d2d), 0xcd }, { CCI_REG8(0x3d2e), 0xcd },
+ { CCI_REG8(0x3d2f), 0xcd }, { CCI_REG8(0x3d30), 0xcd },
+ { CCI_REG8(0x3d31), 0xcd }, { CCI_REG8(0x3d32), 0xcd },
+ { CCI_REG8(0x3d33), 0xcd }, { CCI_REG8(0x3d34), 0xcd },
+ { CCI_REG8(0x3d35), 0xcd }, { CCI_REG8(0x3d36), 0xcd },
+ { CCI_REG8(0x3d37), 0xcd }, { CCI_REG8(0x3d38), 0xcd },
+ { CCI_REG8(0x3d39), 0xcd }, { CCI_REG8(0x3d3a), 0xcd },
+ { CCI_REG8(0x3d3b), 0xcd }, { CCI_REG8(0x3d3c), 0xcd },
+ { CCI_REG8(0x3d3d), 0xcd }, { CCI_REG8(0x3d3e), 0xcd },
+ { CCI_REG8(0x3d3f), 0xcd }, { CCI_REG8(0x3d40), 0xcd },
+ { CCI_REG8(0x3d41), 0xcd }, { CCI_REG8(0x3d42), 0xcd },
+ { CCI_REG8(0x3d43), 0xcd }, { CCI_REG8(0x3d44), 0xcd },
+ { CCI_REG8(0x3d45), 0xcd }, { CCI_REG8(0x3d46), 0xcd },
+ { CCI_REG8(0x3d47), 0xcd }, { CCI_REG8(0x3d48), 0xcd },
+ { CCI_REG8(0x3d49), 0xcd }, { CCI_REG8(0x3d4a), 0xcd },
+ { CCI_REG8(0x3d4b), 0xcd }, { CCI_REG8(0x3d4c), 0xcd },
+ { CCI_REG8(0x3d4d), 0xcd }, { CCI_REG8(0x3d4e), 0xcd },
+ { CCI_REG8(0x3d4f), 0xcd }, { CCI_REG8(0x3d50), 0xcd },
+ { CCI_REG8(0x3d51), 0xcd }, { CCI_REG8(0x3d52), 0xcd },
+ { CCI_REG8(0x3d53), 0xcd }, { CCI_REG8(0x3d54), 0xcd },
+ { CCI_REG8(0x3d55), 0xcd }, { CCI_REG8(0x3d56), 0xcd },
+ { CCI_REG8(0x3d57), 0xcd }, { CCI_REG8(0x3d58), 0xcd },
+ { CCI_REG8(0x3d59), 0xcd }, { CCI_REG8(0x3d5a), 0xcd },
+ { CCI_REG8(0x3d5b), 0xcd }, { CCI_REG8(0x3d5c), 0xcd },
+ { CCI_REG8(0x3d5d), 0xcd }, { CCI_REG8(0x3d5e), 0xcd },
+ { CCI_REG8(0x3d5f), 0xcd }, { CCI_REG8(0x3d60), 0xcd },
+ { CCI_REG8(0x3d61), 0xcd }, { CCI_REG8(0x3d62), 0xcd },
+ { CCI_REG8(0x3d63), 0xcd }, { CCI_REG8(0x3d64), 0xcd },
+ { CCI_REG8(0x3d65), 0x40 }, { CCI_REG8(0x3d66), 0x40 },
+ { CCI_REG8(0x3d67), 0x40 }, { CCI_REG8(0x3d68), 0x40 },
+ { CCI_REG8(0x3d69), 0x40 }, { CCI_REG8(0x3d6a), 0x40 },
+ { CCI_REG8(0x3d6b), 0x40 }, { CCI_REG8(0x3d6c), 0x40 },
+ { CCI_REG8(0x3d6d), 0x40 }, { CCI_REG8(0x3d6e), 0x40 },
+ { CCI_REG8(0x3d6f), 0x40 }, { CCI_REG8(0x3d70), 0x40 },
+ { CCI_REG8(0x3d71), 0x40 }, { CCI_REG8(0x3d72), 0x40 },
+ { CCI_REG8(0x3d73), 0x40 }, { CCI_REG8(0x3d74), 0x40 },
+ { CCI_REG8(0x3d75), 0x40 }, { CCI_REG8(0x3d76), 0x40 },
+ { CCI_REG8(0x3d77), 0x40 }, { CCI_REG8(0x3d78), 0x40 },
+ { CCI_REG8(0x3d79), 0x40 }, { CCI_REG8(0x3d7a), 0x40 },
+ { CCI_REG8(0x3d7b), 0x40 }, { CCI_REG8(0x3d7c), 0x40 },
+ { CCI_REG8(0x3d7d), 0x40 }, { CCI_REG8(0x3d7e), 0x40 },
+ { CCI_REG8(0x3d7f), 0x40 }, { CCI_REG8(0x3d80), 0x40 },
+ { CCI_REG8(0x3d81), 0x40 }, { CCI_REG8(0x3d82), 0x40 },
+ { CCI_REG8(0x3d83), 0x40 }, { CCI_REG8(0x3d84), 0x40 },
+ { CCI_REG8(0x3d85), 0x40 }, { CCI_REG8(0x3d86), 0x40 },
+ { CCI_REG8(0x3d87), 0x40 }, { CCI_REG8(0x3d88), 0x40 },
+ { CCI_REG8(0x3d89), 0x40 }, { CCI_REG8(0x3d8a), 0x40 },
+ { CCI_REG8(0x3d8b), 0x40 }, { CCI_REG8(0x3d8c), 0x40 },
+ { CCI_REG8(0x3d8d), 0x40 }, { CCI_REG8(0x3d8e), 0x40 },
+ { CCI_REG8(0x3d8f), 0x40 }, { CCI_REG8(0x3d90), 0x40 },
+ { CCI_REG8(0x3d91), 0x40 }, { CCI_REG8(0x3d92), 0x40 },
+ { CCI_REG8(0x3d93), 0x40 }, { CCI_REG8(0x3d94), 0x40 },
+ { CCI_REG8(0x3d95), 0x40 }, { CCI_REG8(0x3d96), 0x40 },
+ { CCI_REG8(0x3d97), 0x40 }, { CCI_REG8(0x3d98), 0x40 },
+ { CCI_REG8(0x3d99), 0x40 }, { CCI_REG8(0x3d9a), 0x40 },
+ { CCI_REG8(0x3d9b), 0x40 }, { CCI_REG8(0x3d9c), 0x40 },
+ { CCI_REG8(0x3d9d), 0x40 }, { CCI_REG8(0x3d9e), 0x40 },
+ { CCI_REG8(0x3d9f), 0x40 }, { CCI_REG8(0x3da0), 0x40 },
+ { CCI_REG8(0x3da1), 0x40 }, { CCI_REG8(0x3da2), 0x40 },
+ { CCI_REG8(0x3da3), 0x40 }, { CCI_REG8(0x3da4), 0x40 },
+ { CCI_REG8(0x3da5), 0x40 }, { CCI_REG8(0x3da6), 0x40 },
+ { CCI_REG8(0x3da7), 0x40 }, { CCI_REG8(0x3da8), 0x40 },
+ { CCI_REG8(0x3da9), 0x40 }, { CCI_REG8(0x3daa), 0x40 },
+ { CCI_REG8(0x3dab), 0x40 }, { CCI_REG8(0x3dac), 0x40 },
+ { CCI_REG8(0x3dad), 0x40 }, { CCI_REG8(0x3dae), 0x40 },
+ { CCI_REG8(0x3daf), 0x40 }, { CCI_REG8(0x3db0), 0x40 },
+ { CCI_REG8(0x3db1), 0x40 }, { CCI_REG8(0x3db2), 0x40 },
+ { CCI_REG8(0x3db3), 0x40 }, { CCI_REG8(0x3db4), 0x40 },
+ { CCI_REG8(0x3db5), 0x40 }, { CCI_REG8(0x3db6), 0x40 },
+ { CCI_REG8(0x3db7), 0x40 }, { CCI_REG8(0x3db8), 0x40 },
+ { CCI_REG8(0x3db9), 0x40 }, { CCI_REG8(0x3dba), 0x40 },
+ { CCI_REG8(0x3dbb), 0x40 }, { CCI_REG8(0x3dbc), 0x40 },
+ { CCI_REG8(0x3dbd), 0x40 }, { CCI_REG8(0x3dbe), 0x40 },
+ { CCI_REG8(0x3dbf), 0xcd }, { CCI_REG8(0x3dc0), 0xcd },
+ { CCI_REG8(0x3dc1), 0xcd }, { CCI_REG8(0x3dc2), 0xcd },
+ { CCI_REG8(0x3dc3), 0xcd }, { CCI_REG8(0x3dc4), 0xcd },
+ { CCI_REG8(0x3dc5), 0xcd }, { CCI_REG8(0x3dc6), 0xcd },
+ { CCI_REG8(0x3dc7), 0xcd }, { CCI_REG8(0x3dc8), 0xcd },
+ { CCI_REG8(0x3dc9), 0xcd }, { CCI_REG8(0x3dca), 0xcd },
+ { CCI_REG8(0x3dcb), 0xcd }, { CCI_REG8(0x3dcc), 0xcd },
+ { CCI_REG8(0x3dcd), 0xcd }, { CCI_REG8(0x3dce), 0xcd },
+ { CCI_REG8(0x3dcf), 0xcd }, { CCI_REG8(0x3dd0), 0xcd },
+ { CCI_REG8(0x3dd1), 0xcd }, { CCI_REG8(0x3dd2), 0xcd },
+ { CCI_REG8(0x3dd3), 0xcd }, { CCI_REG8(0x3dd4), 0xcd },
+ { CCI_REG8(0x3dd5), 0xcd }, { CCI_REG8(0x3dd6), 0xcd },
+ { CCI_REG8(0x3dd7), 0xcd }, { CCI_REG8(0x3dd8), 0xcd },
+ { CCI_REG8(0x3dd9), 0xcd }, { CCI_REG8(0x3dda), 0xcd },
+ { CCI_REG8(0x3ddb), 0xcd }, { CCI_REG8(0x3ddc), 0xcd },
+ { CCI_REG8(0x3ddd), 0xcd }, { CCI_REG8(0x3dde), 0xcd },
+ { CCI_REG8(0x3ddf), 0xcd }, { CCI_REG8(0x3de0), 0xcd },
+ { CCI_REG8(0x3de1), 0xcd }, { CCI_REG8(0x3de2), 0xcd },
+ { CCI_REG8(0x3de3), 0xcd }, { CCI_REG8(0x3de4), 0xcd },
+ { CCI_REG8(0x3de5), 0xcd }, { CCI_REG8(0x3de6), 0xcd },
+ { CCI_REG8(0x3de7), 0xcd }, { CCI_REG8(0x3de8), 0xcd },
+ { CCI_REG8(0x3de9), 0xcd }, { CCI_REG8(0x3dea), 0xcd },
+ { CCI_REG8(0x3deb), 0xcd }, { CCI_REG8(0x3dec), 0xcd },
+ { CCI_REG8(0x3ded), 0xcd }, { CCI_REG8(0x3dee), 0xcd },
+ { CCI_REG8(0x3def), 0xcd }, { CCI_REG8(0x3df0), 0xcd },
+ { CCI_REG8(0x3df1), 0xcd }, { CCI_REG8(0x3df2), 0xcd },
+ { CCI_REG8(0x3df3), 0xcd }, { CCI_REG8(0x3df4), 0xcd },
+ { CCI_REG8(0x3df5), 0xcd }, { CCI_REG8(0x3df6), 0xcd },
+ { CCI_REG8(0x3df7), 0xcd }, { CCI_REG8(0x3df8), 0xcd },
+ { CCI_REG8(0x3df9), 0xcd }, { CCI_REG8(0x3dfa), 0xcd },
+ { CCI_REG8(0x3dfb), 0xcd }, { CCI_REG8(0x3dfc), 0xcd },
+ { CCI_REG8(0x3dfd), 0xcd }, { CCI_REG8(0x3dfe), 0xcd },
+ { CCI_REG8(0x3dff), 0xcd }, { CCI_REG8(0x3e00), 0xcd },
+ { CCI_REG8(0x3e01), 0xcd }, { CCI_REG8(0x3e02), 0xcd },
+ { CCI_REG8(0x3e03), 0xcd }, { CCI_REG8(0x3e04), 0xcd },
+ { CCI_REG8(0x3e05), 0xcd }, { CCI_REG8(0x3e06), 0xcd },
+ { CCI_REG8(0x3e07), 0xcd }, { CCI_REG8(0x3e08), 0xcd },
+ { CCI_REG8(0x3e09), 0xcd }, { CCI_REG8(0x3e0a), 0xcd },
+ { CCI_REG8(0x3e0b), 0xcd }, { CCI_REG8(0x3e0c), 0xcd },
+ { CCI_REG8(0x3e0d), 0xcd }, { CCI_REG8(0x3e0e), 0xcd },
+ { CCI_REG8(0x3e0f), 0xcd }, { CCI_REG8(0x3e10), 0xcd },
+ { CCI_REG8(0x3e11), 0xcd }, { CCI_REG8(0x3e12), 0xcd },
+ { CCI_REG8(0x3e13), 0xcd }, { CCI_REG8(0x3e14), 0xcd },
+ { CCI_REG8(0x3e15), 0xcd }, { CCI_REG8(0x3e16), 0xcd },
+ { CCI_REG8(0x3e17), 0xcd }, { CCI_REG8(0x3e18), 0xcd },
+ { CCI_REG8(0x3e19), 0xcd }, { CCI_REG8(0x3e1a), 0xcd },
+ { CCI_REG8(0x3e1b), 0xcd }, { CCI_REG8(0x3e1c), 0xcd },
+ { CCI_REG8(0x3e1d), 0xcd }, { CCI_REG8(0x3e1e), 0xcd },
+ { CCI_REG8(0x3e1f), 0xcd }, { CCI_REG8(0x3e20), 0xcd },
+ { CCI_REG8(0x3e21), 0xcd }, { CCI_REG8(0x3e22), 0xcd },
+ { CCI_REG8(0x3e23), 0xcd }, { CCI_REG8(0x3e24), 0xcd },
+ { CCI_REG8(0x3e25), 0xcd }, { CCI_REG8(0x3e26), 0xcd },
+ { CCI_REG8(0x3e27), 0xcd }, { CCI_REG8(0x3e28), 0xcd },
+ { CCI_REG8(0x3e29), 0xcd }, { CCI_REG8(0x3e2a), 0xcd },
+ { CCI_REG8(0x3e2b), 0xcd }, { CCI_REG8(0x3e2c), 0xcd },
+ { CCI_REG8(0x3e2d), 0xcd }, { CCI_REG8(0x3e2e), 0xcd },
+ { CCI_REG8(0x3e2f), 0xcd }, { CCI_REG8(0x3e30), 0xcd },
+ { CCI_REG8(0x3e31), 0xcd }, { CCI_REG8(0x3e32), 0xcd },
+ { CCI_REG8(0x3e33), 0xcd }, { CCI_REG8(0x3e34), 0xcd },
+ { CCI_REG8(0x3e35), 0xcd }, { CCI_REG8(0x3e36), 0xcd },
+ { CCI_REG8(0x3e37), 0xcd }, { CCI_REG8(0x3e38), 0xcd },
+ { CCI_REG8(0x3e39), 0xcd }, { CCI_REG8(0x3e3a), 0xcd },
+ { CCI_REG8(0x3e3b), 0xcd }, { CCI_REG8(0x3e3c), 0xcd },
+ { CCI_REG8(0x3e3d), 0xcd }, { CCI_REG8(0x3e3e), 0xcd },
+ { CCI_REG8(0x3e3f), 0xcd }, { CCI_REG8(0x3e40), 0xcd },
+ { CCI_REG8(0x3e41), 0xcd }, { CCI_REG8(0x3e42), 0xcd },
+ { CCI_REG8(0x3e43), 0xcd }, { CCI_REG8(0x3e44), 0xcd },
+ { CCI_REG8(0x3e45), 0xcd }, { CCI_REG8(0x3e46), 0xcd },
+ { CCI_REG8(0x3e47), 0xcd }, { CCI_REG8(0x3e48), 0xcd },
+ { CCI_REG8(0x3e49), 0xcd }, { CCI_REG8(0x3e4a), 0xcd },
+ { CCI_REG8(0x3e4b), 0xcd }, { CCI_REG8(0x3e4c), 0xcd },
+ { CCI_REG8(0x3e4d), 0xcd }, { CCI_REG8(0x3e4e), 0xcd },
+ { CCI_REG8(0x3e4f), 0xcd }, { CCI_REG8(0x3e50), 0xcd },
+ { CCI_REG8(0x3e51), 0xcd }, { CCI_REG8(0x3e52), 0xcd },
+ { CCI_REG8(0x3e53), 0xcd }, { CCI_REG8(0x3e54), 0xcd },
+ { CCI_REG8(0x3e55), 0xcd }, { CCI_REG8(0x3e56), 0xcd },
+ { CCI_REG8(0x3e57), 0xcd }, { CCI_REG8(0x3e58), 0xcd },
+ { CCI_REG8(0x3e59), 0xcd }, { CCI_REG8(0x3e5a), 0xcd },
+ { CCI_REG8(0x3e5b), 0xcd }, { CCI_REG8(0x3e5c), 0xcd },
+ { CCI_REG8(0x3e5d), 0xcd }, { CCI_REG8(0x3e5e), 0xcd },
+ { CCI_REG8(0x3e5f), 0xcd }, { CCI_REG8(0x3e60), 0xcd },
+ { CCI_REG8(0x3e61), 0xcd }, { CCI_REG8(0x3e62), 0xcd },
+ { CCI_REG8(0x3e63), 0xcd }, { CCI_REG8(0x3e64), 0xcd },
+ { CCI_REG8(0x3e65), 0xcd }, { CCI_REG8(0x3e66), 0xcd },
+ { CCI_REG8(0x3e67), 0xcd }, { CCI_REG8(0x3e68), 0xcd },
+ { CCI_REG8(0x3e69), 0xcd }, { CCI_REG8(0x3e6a), 0xcd },
+ { CCI_REG8(0x3e6b), 0xcd }, { CCI_REG8(0x3e6c), 0xcd },
+ { CCI_REG8(0x3e6d), 0xcd }, { CCI_REG8(0x3e6e), 0xcd },
+ { CCI_REG8(0x3e6f), 0xcd }, { CCI_REG8(0x3e70), 0xcd },
+ { CCI_REG8(0x3e71), 0xcd }, { CCI_REG8(0x3e72), 0xcd },
+ { CCI_REG8(0x3e73), 0xcd }, { CCI_REG8(0x3e74), 0xcd },
+ { CCI_REG8(0x3e75), 0xcd }, { CCI_REG8(0x3e76), 0xcd },
+ { CCI_REG8(0x3e77), 0xcd }, { CCI_REG8(0x3e78), 0xcd },
+ { CCI_REG8(0x3e79), 0xcd }, { CCI_REG8(0x3e7a), 0xcd },
+ { CCI_REG8(0x3e7b), 0xcd }, { CCI_REG8(0x3e7c), 0xcd },
+ { CCI_REG8(0x3e7d), 0xcd }, { CCI_REG8(0x3e7e), 0xcd },
+ { CCI_REG8(0x3e7f), 0xcd }, { CCI_REG8(0x3e80), 0xcd },
+ { CCI_REG8(0x3e81), 0xcd }, { CCI_REG8(0x3e82), 0xcd },
+ { CCI_REG8(0x3e83), 0xcd }, { CCI_REG8(0x3e84), 0xcd },
+ { CCI_REG8(0x3e85), 0xcd }, { CCI_REG8(0x3e86), 0xcd },
+ { CCI_REG8(0x3e87), 0xcd }, { CCI_REG8(0x3e88), 0xcd },
+ { CCI_REG8(0x3e89), 0xcd }, { CCI_REG8(0x3e8a), 0xcd },
+ { CCI_REG8(0x3e8b), 0xcd }, { CCI_REG8(0x3e8c), 0xcd },
+ { CCI_REG8(0x3e8d), 0xcd }, { CCI_REG8(0x3e8e), 0xcd },
+ { CCI_REG8(0x3e8f), 0xcd }, { CCI_REG8(0x3e90), 0xcd },
+ { CCI_REG8(0x3e91), 0xcd }, { CCI_REG8(0x3e92), 0xcd },
+ { CCI_REG8(0x3e93), 0xcd }, { CCI_REG8(0x3e94), 0xcd },
+ { CCI_REG8(0x3e95), 0xcd }, { CCI_REG8(0x3e96), 0xcd },
+ { CCI_REG8(0x3e97), 0xcd }, { CCI_REG8(0x3e98), 0xcd },
+ { CCI_REG8(0x3e99), 0xcd }, { CCI_REG8(0x3e9a), 0xcd },
+ { CCI_REG8(0x3e9b), 0xcd }, { CCI_REG8(0x3e9c), 0xcd },
+ { CCI_REG8(0x3e9d), 0xcd }, { CCI_REG8(0x3e9e), 0xcd },
+ { CCI_REG8(0x3e9f), 0xcd }, { CCI_REG8(0xfff9), 0x06 },
+ { CCI_REG8(0xc03f), 0x01 }, { CCI_REG8(0xc03e), 0x08 },
+ { CCI_REG8(0xc02c), 0xff }, { CCI_REG8(0xc005), 0x06 },
+ { CCI_REG8(0xc006), 0x30 }, { CCI_REG8(0xc007), 0xc0 },
+ { CCI_REG8(0xc027), 0x01 }, { CCI_REG8(0x30c0), 0x05 },
+ { CCI_REG8(0x30c1), 0x9f }, { CCI_REG8(0x30c2), 0x06 },
+ { CCI_REG8(0x30c3), 0x5f }, { CCI_REG8(0x30c4), 0x80 },
+ { CCI_REG8(0x30c5), 0x08 }, { CCI_REG8(0x30c6), 0x39 },
+ { CCI_REG8(0x30c7), 0x00 }, { CCI_REG8(0xc046), 0x20 },
+ { CCI_REG8(0xc043), 0x01 }, { CCI_REG8(0xc04b), 0x01 },
+ { CCI_REG8(0x0102), 0x01 }, { CCI_REG8(0x0100), 0x00 },
+ { CCI_REG8(0x0102), 0x00 }, { CCI_REG8(0x3015), 0xf0 },
+ { CCI_REG8(0x3018), 0xf0 }, { CCI_REG8(0x301c), 0xf0 },
+ { CCI_REG8(0x301d), 0xf6 }, { CCI_REG8(0x301e), 0xf1 }
+};
+
+static const struct cci_reg_sequence ov64a40_9248x6944[] = {
+ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 },
+ { CCI_REG8(0x0307), 0x01 }, { CCI_REG8(0x4837), 0x1a },
+ { CCI_REG8(0x4888), 0x10 }, { CCI_REG8(0x4860), 0x00 },
+ { CCI_REG8(0x4850), 0x43 }, { CCI_REG8(0x480C), 0x92 },
+ { CCI_REG8(0x5001), 0x21 }
+};
+
+static const struct cci_reg_sequence ov64a40_8000x6000[] = {
+ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 },
+ { CCI_REG8(0x0307), 0x01 }, { CCI_REG8(0x4837), 0x1a },
+ { CCI_REG8(0x4888), 0x10 }, { CCI_REG8(0x4860), 0x00 },
+ { CCI_REG8(0x4850), 0x43 }, { CCI_REG8(0x480C), 0x92 },
+ { CCI_REG8(0x5001), 0x21 }
+};
+
+static const struct cci_reg_sequence ov64a40_4624_3472[] = {
+ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 },
+ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e },
+ { CCI_REG8(0x3712), 0x50 }, { CCI_REG8(0x3822), 0x00 },
+ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x08 },
+ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x02 },
+ { CCI_REG8(0x384d), 0xba }, { CCI_REG8(0x3852), 0x00 },
+ { CCI_REG8(0x3856), 0x08 }, { CCI_REG8(0x3857), 0x08 },
+ { CCI_REG8(0x3858), 0x10 }, { CCI_REG8(0x3859), 0x10 },
+ { CCI_REG8(0x4016), 0x0f }, { CCI_REG8(0x4018), 0x03 },
+ { CCI_REG8(0x4504), 0x1e }, { CCI_REG8(0x4523), 0x41 },
+ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x12 },
+ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4915), 0x02 },
+ { CCI_REG8(0x4916), 0x1d }, { CCI_REG8(0x4a15), 0x02 },
+ { CCI_REG8(0x4a16), 0x1d }, { CCI_REG8(0x3703), 0x72 },
+ { CCI_REG8(0x3709), 0xe6 }, { CCI_REG8(0x3a60), 0x68 },
+ { CCI_REG8(0x3a6f), 0x68 }, { CCI_REG8(0x3a5e), 0xdc },
+ { CCI_REG8(0x3a6d), 0xdc }, { CCI_REG8(0x3721), 0xc9 },
+ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 },
+ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 },
+ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 },
+ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b },
+ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 },
+ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b },
+ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 },
+ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b },
+ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x481b), 0x35 },
+ { CCI_REG8(0x4862), 0x25 }, { CCI_REG8(0x3400), 0x00 },
+ { CCI_REG8(0x3421), 0x23 }, { CCI_REG8(0x3422), 0xfc },
+ { CCI_REG8(0x3423), 0x07 }, { CCI_REG8(0x3424), 0x01 },
+ { CCI_REG8(0x3425), 0x04 }, { CCI_REG8(0x3426), 0x50 },
+ { CCI_REG8(0x3427), 0x55 }, { CCI_REG8(0x3428), 0x15 },
+ { CCI_REG8(0x3429), 0x00 }, { CCI_REG8(0x3025), 0x03 },
+ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x0305), 0x98 },
+ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 },
+ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 },
+ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 },
+ { CCI_REG8(0x480C), 0x92 }, { CCI_REG8(0x5001), 0x21 }
+};
+
+static const struct cci_reg_sequence ov64a40_3840x2160[] = {
+ { CCI_REG8(0x034a), 0x05 }, { CCI_REG8(0x034b), 0x05 },
+ { CCI_REG8(0x3504), 0x08 }, { CCI_REG8(0x360d), 0x82 },
+ { CCI_REG8(0x368a), 0x2e }, { CCI_REG8(0x3712), 0x50 },
+ { CCI_REG8(0x3822), 0x00 }, { CCI_REG8(0x3827), 0x40 },
+ { CCI_REG8(0x383d), 0x08 }, { CCI_REG8(0x383f), 0x00 },
+ { CCI_REG8(0x384c), 0x02 }, { CCI_REG8(0x384d), 0xba },
+ { CCI_REG8(0x3852), 0x00 }, { CCI_REG8(0x3856), 0x08 },
+ { CCI_REG8(0x3857), 0x08 }, { CCI_REG8(0x3858), 0x10 },
+ { CCI_REG8(0x3859), 0x10 }, { CCI_REG8(0x4016), 0x0f },
+ { CCI_REG8(0x4018), 0x03 }, { CCI_REG8(0x4504), 0x1e },
+ { CCI_REG8(0x4523), 0x41 }, { CCI_REG8(0x45c0), 0x01 },
+ { CCI_REG8(0x4641), 0x12 }, { CCI_REG8(0x4643), 0x0c },
+ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d },
+ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d },
+ { CCI_REG8(0x3703), 0x72 }, { CCI_REG8(0x3709), 0xe6 },
+ { CCI_REG8(0x3a60), 0x68 }, { CCI_REG8(0x3a6f), 0x68 },
+ { CCI_REG8(0x3a5e), 0xdc }, { CCI_REG8(0x3a6d), 0xdc },
+ { CCI_REG8(0x3721), 0xc9 }, { CCI_REG8(0x5250), 0x06 },
+ { CCI_REG8(0x527a), 0x00 }, { CCI_REG8(0x527b), 0x65 },
+ { CCI_REG8(0x527c), 0x00 }, { CCI_REG8(0x527d), 0x82 },
+ { CCI_REG8(0x5280), 0x24 }, { CCI_REG8(0x5281), 0x40 },
+ { CCI_REG8(0x5282), 0x1b }, { CCI_REG8(0x5283), 0x40 },
+ { CCI_REG8(0x5284), 0x24 }, { CCI_REG8(0x5285), 0x40 },
+ { CCI_REG8(0x5286), 0x1b }, { CCI_REG8(0x5287), 0x40 },
+ { CCI_REG8(0x5200), 0x24 }, { CCI_REG8(0x5201), 0x40 },
+ { CCI_REG8(0x5202), 0x1b }, { CCI_REG8(0x5203), 0x40 },
+ { CCI_REG8(0x481b), 0x35 }, { CCI_REG8(0x4862), 0x25 },
+ { CCI_REG8(0x3400), 0x00 }, { CCI_REG8(0x3421), 0x23 },
+ { CCI_REG8(0x3422), 0xfc }, { CCI_REG8(0x3423), 0x07 },
+ { CCI_REG8(0x3424), 0x01 }, { CCI_REG8(0x3425), 0x04 },
+ { CCI_REG8(0x3426), 0x50 }, { CCI_REG8(0x3427), 0x55 },
+ { CCI_REG8(0x3428), 0x15 }, { CCI_REG8(0x3429), 0x00 },
+ { CCI_REG8(0x3025), 0x03 }, { CCI_REG8(0x5250), 0x06 },
+ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 },
+ { CCI_REG8(0x0345), 0x90 }, { CCI_REG8(0x0307), 0x01 },
+ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 },
+ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 },
+ { CCI_REG8(0x480C), 0x92 }, { CCI_REG8(0x5001), 0x21 },
+ { CCI_REG8(0x5000), 0x01 }
+};
+
+static const struct cci_reg_sequence ov64a40_2312_1736[] = {
+ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 },
+ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e },
+ { CCI_REG8(0x3712), 0x00 }, { CCI_REG8(0x3822), 0x08 },
+ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x04 },
+ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x01 },
+ { CCI_REG8(0x384d), 0x12 }, { CCI_REG8(0x3852), 0x00 },
+ { CCI_REG8(0x3856), 0x04 }, { CCI_REG8(0x3857), 0x04 },
+ { CCI_REG8(0x3858), 0x08 }, { CCI_REG8(0x3859), 0x08 },
+ { CCI_REG8(0x4016), 0x07 }, { CCI_REG8(0x4018), 0x01 },
+ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4523), 0x00 },
+ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x24 },
+ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4837), 0x0b },
+ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d },
+ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d },
+ { CCI_REG8(0x5000), 0x55 }, { CCI_REG8(0x5001), 0x00 },
+ { CCI_REG8(0x5002), 0x35 }, { CCI_REG8(0x5004), 0xc0 },
+ { CCI_REG8(0x5068), 0x02 }, { CCI_REG8(0x3703), 0x6a },
+ { CCI_REG8(0x3709), 0xa3 }, { CCI_REG8(0x3a60), 0x60 },
+ { CCI_REG8(0x3a6f), 0x60 }, { CCI_REG8(0x3a5e), 0x99 },
+ { CCI_REG8(0x3a6d), 0x99 }, { CCI_REG8(0x3721), 0xc1 },
+ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 },
+ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 },
+ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 },
+ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b },
+ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 },
+ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b },
+ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 },
+ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b },
+ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x3684), 0x05 },
+ { CCI_REG8(0x481b), 0x20 }, { CCI_REG8(0x51b0), 0x38 },
+ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x04 },
+ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 },
+ { CCI_REG8(0x51b9), 0x70 }, { CCI_REG8(0x51bb), 0x10 },
+ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 },
+ { CCI_REG8(0x51b0), 0x38 }, { CCI_REG8(0x54b0), 0x38 },
+ { CCI_REG8(0x54b3), 0x0e }, { CCI_REG8(0x54b5), 0x04 },
+ { CCI_REG8(0x54b6), 0x00 }, { CCI_REG8(0x54b7), 0x00 },
+ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54bb), 0x10 },
+ { CCI_REG8(0x54bc), 0x00 }, { CCI_REG8(0x54bd), 0x00 },
+ { CCI_REG8(0x57b0), 0x38 }, { CCI_REG8(0x57b3), 0x0e },
+ { CCI_REG8(0x57b5), 0x04 }, { CCI_REG8(0x57b6), 0x00 },
+ { CCI_REG8(0x57b7), 0x00 }, { CCI_REG8(0x57b9), 0x70 },
+ { CCI_REG8(0x57bb), 0x10 }, { CCI_REG8(0x57bc), 0x00 },
+ { CCI_REG8(0x57bd), 0x00 }, { CCI_REG8(0x0305), 0x98 },
+ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 },
+ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 },
+ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 },
+ { CCI_REG8(0x480C), 0x92 }
+};
+
+static const struct cci_reg_sequence ov64a40_1920x1080[] = {
+ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 },
+ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e },
+ { CCI_REG8(0x3712), 0x00 }, { CCI_REG8(0x3822), 0x08 },
+ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x04 },
+ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x01 },
+ { CCI_REG8(0x384d), 0x12 }, { CCI_REG8(0x3852), 0x00 },
+ { CCI_REG8(0x3856), 0x04 }, { CCI_REG8(0x3857), 0x04 },
+ { CCI_REG8(0x3858), 0x08 }, { CCI_REG8(0x3859), 0x08 },
+ { CCI_REG8(0x4016), 0x07 }, { CCI_REG8(0x4018), 0x01 },
+ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4523), 0x00 },
+ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x24 },
+ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4837), 0x0b },
+ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d },
+ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d },
+ { CCI_REG8(0x5000), 0x55 }, { CCI_REG8(0x5001), 0x00 },
+ { CCI_REG8(0x5002), 0x35 }, { CCI_REG8(0x5004), 0xc0 },
+ { CCI_REG8(0x5068), 0x02 }, { CCI_REG8(0x3703), 0x6a },
+ { CCI_REG8(0x3709), 0xa3 }, { CCI_REG8(0x3a60), 0x60 },
+ { CCI_REG8(0x3a6f), 0x60 }, { CCI_REG8(0x3a5e), 0x99 },
+ { CCI_REG8(0x3a6d), 0x99 }, { CCI_REG8(0x3721), 0xc1 },
+ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 },
+ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 },
+ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 },
+ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b },
+ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 },
+ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b },
+ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 },
+ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b },
+ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x3684), 0x05 },
+ { CCI_REG8(0x481b), 0x20 }, { CCI_REG8(0x51b0), 0x38 },
+ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x04 },
+ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 },
+ { CCI_REG8(0x51b9), 0x70 }, { CCI_REG8(0x51bb), 0x10 },
+ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 },
+ { CCI_REG8(0x51b0), 0x38 }, { CCI_REG8(0x54b0), 0x38 },
+ { CCI_REG8(0x54b3), 0x0e }, { CCI_REG8(0x54b5), 0x04 },
+ { CCI_REG8(0x54b6), 0x00 }, { CCI_REG8(0x54b7), 0x00 },
+ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54bb), 0x10 },
+ { CCI_REG8(0x54bc), 0x00 }, { CCI_REG8(0x54bd), 0x00 },
+ { CCI_REG8(0x57b0), 0x38 }, { CCI_REG8(0x57b3), 0x0e },
+ { CCI_REG8(0x57b5), 0x04 }, { CCI_REG8(0x57b6), 0x00 },
+ { CCI_REG8(0x57b7), 0x00 }, { CCI_REG8(0x57b9), 0x70 },
+ { CCI_REG8(0x57bb), 0x10 }, { CCI_REG8(0x57bc), 0x00 },
+ { CCI_REG8(0x57bd), 0x00 }, { CCI_REG8(0x0305), 0x98 },
+ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 },
+ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 },
+ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 },
+ { CCI_REG8(0x480C), 0x92 }
+};
+
+/* 456MHz MIPI link frequency with 24MHz input clock. */
+static const struct cci_reg_sequence ov64a40_pll_config[] = {
+ { OV64A40_PLL1_PRE_DIV0, 0x88 },
+ { OV64A40_PLL1_PRE_DIV, 0x02 },
+ { OV64A40_PLL1_MULTIPLIER, 0x0098 },
+ { OV64A40_PLL1_M_DIV, 0x01 },
+ { OV64A40_PLL2_SEL_BAK_SA1, 0x00 },
+ { OV64A40_PLL2_PRE_DIV, 0x12 },
+ { OV64A40_PLL2_MULTIPLIER, 0x0190 },
+ { OV64A40_PLL2_PRE_DIV0, 0xd7 },
+ { OV64A40_PLL2_DIVSP, 0x00 },
+ { OV64A40_PLL2_DIVDAC, 0x00 },
+ { OV64A40_PLL2_DACPREDIV, 0x00 }
+};
+
+struct ov64a40_reglist {
+ unsigned int num_regs;
+ const struct cci_reg_sequence *regvals;
+};
+
+struct ov64a40_subsampling {
+ unsigned int x_odd_inc;
+ unsigned int x_even_inc;
+ unsigned int y_odd_inc;
+ unsigned int y_even_inc;
+ bool vbin;
+ bool hbin;
+};
+
+static struct ov64a40_mode {
+ unsigned int width;
+ unsigned int height;
+ struct ov64a40_timings {
+ unsigned int vts;
+ unsigned int ppl;
+ } timings_default[OV64A40_NUM_LINK_FREQ];
+ const struct ov64a40_reglist reglist;
+ struct v4l2_rect analogue_crop;
+ struct v4l2_rect digital_crop;
+ struct ov64a40_subsampling subsampling;
+} ov64a40_modes[] = {
+ /* Full resolution */
+ {
+ .width = 9248,
+ .height = 6944,
+ .timings_default = {
+ /* 2.6 FPS */
+ [OV64A40_LINK_FREQ_456M_ID] = {
+ .vts = 7072,
+ .ppl = 4072,
+ },
+ /* 2 FPS */
+ [OV64A40_LINK_FREQ_360M_ID] = {
+ .vts = 7072,
+ .ppl = 5248,
+ },
+ },
+ .reglist = {
+ .num_regs = ARRAY_SIZE(ov64a40_9248x6944),
+ .regvals = ov64a40_9248x6944,
+ },
+ .analogue_crop = {
+ .left = 0,
+ .top = 0,
+ .width = 9280,
+ .height = 6976,
+ },
+ .digital_crop = {
+ .left = 17,
+ .top = 16,
+ .width = 9248,
+ .height = 6944,
+ },
+ .subsampling = {
+ .x_odd_inc = 1,
+ .x_even_inc = 1,
+ .y_odd_inc = 1,
+ .y_even_inc = 1,
+ .vbin = false,
+ .hbin = false,
+ },
+ },
+ /* Analogue crop + digital crop */
+ {
+ .width = 8000,
+ .height = 6000,
+ .timings_default = {
+ /* 3.0 FPS */
+ [OV64A40_LINK_FREQ_456M_ID] = {
+ .vts = 6400,
+ .ppl = 3848,
+ },
+ /* 2.5 FPS */
+ [OV64A40_LINK_FREQ_360M_ID] = {
+ .vts = 6304,
+ .ppl = 4736,
+ },
+ },
+ .reglist = {
+ .num_regs = ARRAY_SIZE(ov64a40_8000x6000),
+ .regvals = ov64a40_8000x6000,
+ },
+ .analogue_crop = {
+ .left = 624,
+ .top = 472,
+ .width = 8048,
+ .height = 6032,
+ },
+ .digital_crop = {
+ .left = 17,
+ .top = 16,
+ .width = 8000,
+ .height = 6000,
+ },
+ .subsampling = {
+ .x_odd_inc = 1,
+ .x_even_inc = 1,
+ .y_odd_inc = 1,
+ .y_even_inc = 1,
+ .vbin = false,
+ .hbin = false,
+ },
+ },
+ /* 2x2 downscaled */
+ {
+ .width = 4624,
+ .height = 3472,
+ .timings_default = {
+ /* 10 FPS */
+ [OV64A40_LINK_FREQ_456M_ID] = {
+ .vts = 3533,
+ .ppl = 2112,
+ },
+ /* 7 FPS */
+ [OV64A40_LINK_FREQ_360M_ID] = {
+ .vts = 3939,
+ .ppl = 2720,
+ },
+ },
+ .reglist = {
+ .num_regs = ARRAY_SIZE(ov64a40_4624_3472),
+ .regvals = ov64a40_4624_3472,
+ },
+ .analogue_crop = {
+ .left = 0,
+ .top = 0,
+ .width = 9280,
+ .height = 6976,
+ },
+ .digital_crop = {
+ .left = 9,
+ .top = 8,
+ .width = 4624,
+ .height = 3472,
+ },
+ .subsampling = {
+ .x_odd_inc = 3,
+ .x_even_inc = 1,
+ .y_odd_inc = 1,
+ .y_even_inc = 1,
+ .vbin = true,
+ .hbin = false,
+ },
+ },
+ /* Analogue crop + 2x2 downscale + digital crop */
+ {
+ .width = 3840,
+ .height = 2160,
+ .timings_default = {
+ /* 20 FPS */
+ [OV64A40_LINK_FREQ_456M_ID] = {
+ .vts = 2218,
+ .ppl = 1690,
+ },
+ /* 15 FPS */
+ [OV64A40_LINK_FREQ_360M_ID] = {
+ .vts = 2270,
+ .ppl = 2202,
+ },
+ },
+ .reglist = {
+ .num_regs = ARRAY_SIZE(ov64a40_3840x2160),
+ .regvals = ov64a40_3840x2160,
+ },
+ .analogue_crop = {
+ .left = 784,
+ .top = 1312,
+ .width = 7712,
+ .height = 4352,
+ },
+ .digital_crop = {
+ .left = 9,
+ .top = 8,
+ .width = 3840,
+ .height = 2160,
+ },
+ .subsampling = {
+ .x_odd_inc = 3,
+ .x_even_inc = 1,
+ .y_odd_inc = 1,
+ .y_even_inc = 1,
+ .vbin = true,
+ .hbin = false,
+ },
+ },
+ /* 4x4 downscaled */
+ {
+ .width = 2312,
+ .height = 1736,
+ .timings_default = {
+ /* 30 FPS */
+ [OV64A40_LINK_FREQ_456M_ID] = {
+ .vts = 1998,
+ .ppl = 1248,
+ },
+ /* 25 FPS */
+ [OV64A40_LINK_FREQ_360M_ID] = {
+ .vts = 1994,
+ .ppl = 1504,
+ },
+ },
+ .reglist = {
+ .num_regs = ARRAY_SIZE(ov64a40_2312_1736),
+ .regvals = ov64a40_2312_1736,
+ },
+ .analogue_crop = {
+ .left = 0,
+ .top = 0,
+ .width = 9280,
+ .height = 6976,
+ },
+ .digital_crop = {
+ .left = 5,
+ .top = 4,
+ .width = 2312,
+ .height = 1736,
+ },
+ .subsampling = {
+ .x_odd_inc = 3,
+ .x_even_inc = 1,
+ .y_odd_inc = 3,
+ .y_even_inc = 1,
+ .vbin = true,
+ .hbin = true,
+ },
+ },
+ /* Analogue crop + 4x4 downscale + digital crop */
+ {
+ .width = 1920,
+ .height = 1080,
+ .timings_default = {
+ /* 60 FPS */
+ [OV64A40_LINK_FREQ_456M_ID] = {
+ .vts = 1397,
+ .ppl = 880,
+ },
+ /* 45 FPS */
+ [OV64A40_LINK_FREQ_360M_ID] = {
+ .vts = 1216,
+ .ppl = 1360,
+ },
+ },
+ .reglist = {
+ .num_regs = ARRAY_SIZE(ov64a40_1920x1080),
+ .regvals = ov64a40_1920x1080,
+ },
+ .analogue_crop = {
+ .left = 784,
+ .top = 1312,
+ .width = 7712,
+ .height = 4352,
+ },
+ .digital_crop = {
+ .left = 7,
+ .top = 6,
+ .width = 1920,
+ .height = 1080,
+ },
+ .subsampling = {
+ .x_odd_inc = 3,
+ .x_even_inc = 1,
+ .y_odd_inc = 3,
+ .y_even_inc = 1,
+ .vbin = true,
+ .hbin = true,
+ },
+ },
+};
+
+struct ov64a40 {
+ struct device *dev;
+
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+
+ struct regmap *cci;
+
+ struct ov64a40_mode *mode;
+
+ struct clk *xclk;
+
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(ov64a40_supply_names)];
+
+ s64 *link_frequencies;
+ unsigned int num_link_frequencies;
+
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *exposure;
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *vflip;
+ struct v4l2_ctrl *hflip;
+};
+
+static inline struct ov64a40 *sd_to_ov64a40(struct v4l2_subdev *sd)
+{
+ return container_of_const(sd, struct ov64a40, sd);
+}
+
+static const struct ov64a40_timings *
+ov64a40_get_timings(struct ov64a40 *ov64a40, unsigned int link_freq_index)
+{
+ s64 link_freq = ov64a40->link_frequencies[link_freq_index];
+ unsigned int timings_index = link_freq == OV64A40_LINK_FREQ_360M
+ ? OV64A40_LINK_FREQ_360M_ID
+ : OV64A40_LINK_FREQ_456M_ID;
+
+ return &ov64a40->mode->timings_default[timings_index];
+}
+
+static int ov64a40_program_geometry(struct ov64a40 *ov64a40)
+{
+ struct ov64a40_mode *mode = ov64a40->mode;
+ struct v4l2_rect *anacrop = &mode->analogue_crop;
+ struct v4l2_rect *digicrop = &mode->digital_crop;
+ const struct ov64a40_timings *timings;
+ int ret = 0;
+
+ /* Analogue crop. */
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL0,
+ anacrop->left, &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL2,
+ anacrop->top, &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL4,
+ anacrop->width + anacrop->left - 1, &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL6,
+ anacrop->height + anacrop->top - 1, &ret);
+
+ /* ISP windowing. */
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL10,
+ digicrop->left, &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL12,
+ digicrop->top, &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL8,
+ digicrop->width, &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLA,
+ digicrop->height, &ret);
+
+ /* Total timings. */
+ timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLC, timings->ppl, &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLE, timings->vts, &ret);
+
+ return ret;
+}
+
+static int ov64a40_program_subsampling(struct ov64a40 *ov64a40)
+{
+ struct ov64a40_subsampling *subsampling = &ov64a40->mode->subsampling;
+ int ret = 0;
+
+ /* Skipping configuration */
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL14,
+ OV64A40_SKIPPING_CONFIG(subsampling->x_odd_inc,
+ subsampling->x_even_inc), &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL15,
+ OV64A40_SKIPPING_CONFIG(subsampling->y_odd_inc,
+ subsampling->y_even_inc), &ret);
+
+ /* Binning configuration */
+ cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20,
+ OV64A40_TIMING_CTRL_20_VBIN,
+ subsampling->vbin ? OV64A40_TIMING_CTRL_20_VBIN : 0,
+ &ret);
+ cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21,
+ OV64A40_TIMING_CTRL_21_HBIN_CONF,
+ subsampling->hbin ?
+ OV64A40_TIMING_CTRL_21_HBIN_CONF : 0, &ret);
+
+ return ret;
+}
+
+static int ov64a40_start_streaming(struct ov64a40 *ov64a40,
+ struct v4l2_subdev_state *state)
+{
+ const struct ov64a40_reglist *reglist = &ov64a40->mode->reglist;
+ const struct ov64a40_timings *timings;
+ unsigned long delay;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(ov64a40->dev);
+ if (ret < 0)
+ return ret;
+
+ ret = cci_multi_reg_write(ov64a40->cci, ov64a40_init,
+ ARRAY_SIZE(ov64a40_init), NULL);
+ if (ret)
+ goto error_power_off;
+
+ ret = cci_multi_reg_write(ov64a40->cci, reglist->regvals,
+ reglist->num_regs, NULL);
+ if (ret)
+ goto error_power_off;
+
+ ret = ov64a40_program_geometry(ov64a40);
+ if (ret)
+ goto error_power_off;
+
+ ret = ov64a40_program_subsampling(ov64a40);
+ if (ret)
+ goto error_power_off;
+
+ ret = __v4l2_ctrl_handler_setup(&ov64a40->ctrl_handler);
+ if (ret)
+ goto error_power_off;
+
+ ret = cci_write(ov64a40->cci, OV64A40_REG_SMIA,
+ OV64A40_REG_SMIA_STREAMING, NULL);
+ if (ret)
+ goto error_power_off;
+
+ /* Link frequency and flips cannot change while streaming. */
+ __v4l2_ctrl_grab(ov64a40->link_freq, true);
+ __v4l2_ctrl_grab(ov64a40->vflip, true);
+ __v4l2_ctrl_grab(ov64a40->hflip, true);
+
+ /* delay: max(4096 xclk pulses, 150usec) + exposure time */
+ timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val);
+ delay = DIV_ROUND_UP(4096, OV64A40_XCLK_FREQ / 1000 / 1000);
+ delay = max(delay, 150ul);
+
+ /* The sensor has an internal x4 multiplier on the line length. */
+ delay += DIV_ROUND_UP(timings->ppl * 4 * ov64a40->exposure->cur.val,
+ OV64A40_PIXEL_RATE / 1000 / 1000);
+ fsleep(delay);
+
+ return 0;
+
+error_power_off:
+ pm_runtime_mark_last_busy(ov64a40->dev);
+ pm_runtime_put_autosuspend(ov64a40->dev);
+
+ return ret;
+}
+
+static int ov64a40_stop_streaming(struct ov64a40 *ov64a40,
+ struct v4l2_subdev_state *state)
+{
+ cci_update_bits(ov64a40->cci, OV64A40_REG_SMIA, BIT(0), 0, NULL);
+ pm_runtime_mark_last_busy(ov64a40->dev);
+ pm_runtime_put_autosuspend(ov64a40->dev);
+
+ __v4l2_ctrl_grab(ov64a40->link_freq, false);
+ __v4l2_ctrl_grab(ov64a40->vflip, false);
+ __v4l2_ctrl_grab(ov64a40->hflip, false);
+
+ return 0;
+}
+
+static int ov64a40_set_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
+ struct v4l2_subdev_state *state;
+ int ret;
+
+ state = v4l2_subdev_lock_and_get_active_state(sd);
+ if (enable)
+ ret = ov64a40_start_streaming(ov64a40, state);
+ else
+ ret = ov64a40_stop_streaming(ov64a40, state);
+ v4l2_subdev_unlock_state(state);
+
+ return ret;
+}
+
+static const struct v4l2_subdev_video_ops ov64a40_video_ops = {
+ .s_stream = ov64a40_set_stream,
+};
+
+static u32 ov64a40_mbus_code(struct ov64a40 *ov64a40)
+{
+ unsigned int index = ov64a40->hflip->val << 1 | ov64a40->vflip->val;
+
+ return ov64a40_mbus_codes[index];
+}
+
+static void ov64a40_update_pad_fmt(struct ov64a40 *ov64a40,
+ struct ov64a40_mode *mode,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->code = ov64a40_mbus_code(ov64a40);
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_RAW;
+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ fmt->xfer_func = V4L2_XFER_FUNC_NONE;
+ fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
+}
+
+static int ov64a40_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *crop;
+
+ format = v4l2_subdev_state_get_format(state, 0);
+ ov64a40_update_pad_fmt(ov64a40, &ov64a40_modes[0], format);
+
+ crop = v4l2_subdev_state_get_crop(state, 0);
+ crop->top = OV64A40_PIXEL_ARRAY_TOP;
+ crop->left = OV64A40_PIXEL_ARRAY_LEFT;
+ crop->width = OV64A40_PIXEL_ARRAY_WIDTH;
+ crop->height = OV64A40_PIXEL_ARRAY_HEIGHT;
+
+ return 0;
+}
+
+static int ov64a40_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
+
+ if (code->index)
+ return -EINVAL;
+
+ code->code = ov64a40_mbus_code(ov64a40);
+
+ return 0;
+}
+
+static int ov64a40_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
+ struct ov64a40_mode *mode;
+ u32 code;
+
+ if (fse->index >= ARRAY_SIZE(ov64a40_modes))
+ return -EINVAL;
+
+ code = ov64a40_mbus_code(ov64a40);
+ if (fse->code != code)
+ return -EINVAL;
+
+ mode = &ov64a40_modes[fse->index];
+ fse->min_width = mode->width;
+ fse->max_width = mode->width;
+ fse->min_height = mode->height;
+ fse->max_height = mode->height;
+
+ return 0;
+}
+
+static int ov64a40_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_selection *sel)
+{
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP:
+ sel->r = *v4l2_subdev_state_get_crop(state, 0);
+
+ return 0;
+
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = OV64A40_NATIVE_WIDTH;
+ sel->r.height = OV64A40_NATIVE_HEIGHT;
+
+ return 0;
+
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = OV64A40_PIXEL_ARRAY_TOP;
+ sel->r.left = OV64A40_PIXEL_ARRAY_LEFT;
+ sel->r.width = OV64A40_PIXEL_ARRAY_WIDTH;
+ sel->r.height = OV64A40_PIXEL_ARRAY_HEIGHT;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int ov64a40_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
+ struct v4l2_mbus_framefmt *format;
+ struct ov64a40_mode *mode;
+
+ mode = v4l2_find_nearest_size(ov64a40_modes,
+ ARRAY_SIZE(ov64a40_modes),
+ width, height,
+ fmt->format.width, fmt->format.height);
+
+ ov64a40_update_pad_fmt(ov64a40, mode, &fmt->format);
+
+ format = v4l2_subdev_state_get_format(state, 0);
+ if (ov64a40->mode == mode && format->code == fmt->format.code)
+ return 0;
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ const struct ov64a40_timings *timings;
+ int vblank_max, vblank_def;
+ int hblank_val;
+ int exp_max;
+
+ ov64a40->mode = mode;
+ *v4l2_subdev_state_get_crop(state, 0) = mode->analogue_crop;
+
+ /* Update control limits according to the new mode. */
+ timings = ov64a40_get_timings(ov64a40,
+ ov64a40->link_freq->cur.val);
+ vblank_max = OV64A40_VTS_MAX - mode->height;
+ vblank_def = timings->vts - mode->height;
+ __v4l2_ctrl_modify_range(ov64a40->vblank, OV64A40_VBLANK_MIN,
+ vblank_max, 1, vblank_def);
+ __v4l2_ctrl_s_ctrl(ov64a40->vblank, vblank_def);
+
+ exp_max = timings->vts - OV64A40_EXPOSURE_MARGIN;
+ __v4l2_ctrl_modify_range(ov64a40->exposure,
+ OV64A40_EXPOSURE_MIN, exp_max,
+ 1, OV64A40_EXPOSURE_MIN);
+
+ hblank_val = timings->ppl * 4 - mode->width;
+ __v4l2_ctrl_modify_range(ov64a40->hblank,
+ hblank_val, hblank_val, 1, hblank_val);
+ }
+
+ *format = fmt->format;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_pad_ops ov64a40_pad_ops = {
+ .enum_mbus_code = ov64a40_enum_mbus_code,
+ .enum_frame_size = ov64a40_enum_frame_size,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = ov64a40_set_format,
+ .get_selection = ov64a40_get_selection,
+};
+
+static const struct v4l2_subdev_core_ops ov64a40_core_ops = {
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_ops ov64a40_subdev_ops = {
+ .core = &ov64a40_core_ops,
+ .video = &ov64a40_video_ops,
+ .pad = &ov64a40_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops ov64a40_internal_ops = {
+ .init_state = ov64a40_init_state,
+};
+
+static int ov64a40_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
+ int ret;
+
+ ret = clk_prepare_enable(ov64a40->xclk);
+ if (ret)
+ return ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ov64a40_supply_names),
+ ov64a40->supplies);
+ if (ret) {
+ clk_disable_unprepare(ov64a40->xclk);
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ gpiod_set_value_cansleep(ov64a40->reset_gpio, 0);
+
+ fsleep(5000);
+
+ return 0;
+}
+
+static int ov64a40_power_off(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
+
+ gpiod_set_value_cansleep(ov64a40->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(ov64a40_supply_names),
+ ov64a40->supplies);
+ clk_disable_unprepare(ov64a40->xclk);
+
+ return 0;
+}
+
+static int ov64a40_link_freq_config(struct ov64a40 *ov64a40, int link_freq_id)
+{
+ s64 link_frequency;
+ int ret = 0;
+
+ /* Default 456MHz with 24MHz input clock. */
+ cci_multi_reg_write(ov64a40->cci, ov64a40_pll_config,
+ ARRAY_SIZE(ov64a40_pll_config), &ret);
+
+ /* Decrease the PLL1 multiplier to obtain 360MHz mipi link frequency. */
+ link_frequency = ov64a40->link_frequencies[link_freq_id];
+ if (link_frequency == OV64A40_LINK_FREQ_360M)
+ cci_write(ov64a40->cci, OV64A40_PLL1_MULTIPLIER, 0x0078, &ret);
+
+ return ret;
+}
+
+static int ov64a40_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct ov64a40 *ov64a40 = container_of(ctrl->handler, struct ov64a40,
+ ctrl_handler);
+ int pm_status;
+ int ret = 0;
+
+ if (ctrl->id == V4L2_CID_VBLANK) {
+ int exp_max = ov64a40->mode->height + ctrl->val
+ - OV64A40_EXPOSURE_MARGIN;
+ int exp_val = min(ov64a40->exposure->cur.val, exp_max);
+
+ __v4l2_ctrl_modify_range(ov64a40->exposure,
+ ov64a40->exposure->minimum,
+ exp_max, 1, exp_val);
+ }
+
+ pm_status = pm_runtime_get_if_active(ov64a40->dev, true);
+ if (!pm_status)
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_EXPO,
+ ctrl->val, NULL);
+ break;
+ case V4L2_CID_ANALOGUE_GAIN:
+ ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_GAIN,
+ ctrl->val << 1, NULL);
+ break;
+ case V4L2_CID_VBLANK: {
+ int vts = ctrl->val + ov64a40->mode->height;
+
+ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_LOW, vts, &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_MID,
+ (vts >> 8), &ret);
+ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_HIGH,
+ (vts >> 16), &ret);
+ break;
+ }
+ case V4L2_CID_VFLIP:
+ ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20,
+ OV64A40_TIMING_CTRL_20_VFLIP,
+ ctrl->val << 2,
+ NULL);
+ break;
+ case V4L2_CID_HFLIP:
+ ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21,
+ OV64A40_TIMING_CTRL_21_HFLIP,
+ ctrl->val ? 0
+ : OV64A40_TIMING_CTRL_21_HFLIP,
+ NULL);
+ break;
+ case V4L2_CID_TEST_PATTERN:
+ ret = cci_write(ov64a40->cci, OV64A40_REG_TEST_PATTERN,
+ ov64a40_test_pattern_val[ctrl->val], NULL);
+ break;
+ case V4L2_CID_LINK_FREQ:
+ ret = ov64a40_link_freq_config(ov64a40, ctrl->val);
+ break;
+ default:
+ dev_err(ov64a40->dev, "Unhandled control: %#x\n", ctrl->id);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (pm_status > 0) {
+ pm_runtime_mark_last_busy(ov64a40->dev);
+ pm_runtime_put_autosuspend(ov64a40->dev);
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops ov64a40_ctrl_ops = {
+ .s_ctrl = ov64a40_set_ctrl,
+};
+
+static int ov64a40_init_controls(struct ov64a40 *ov64a40)
+{
+ int exp_max, hblank_val, vblank_max, vblank_def;
+ struct v4l2_ctrl_handler *hdlr = &ov64a40->ctrl_handler;
+ struct v4l2_fwnode_device_properties props;
+ const struct ov64a40_timings *timings;
+ int ret;
+
+ ret = v4l2_ctrl_handler_init(hdlr, 11);
+ if (ret)
+ return ret;
+
+ v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, V4L2_CID_PIXEL_RATE,
+ OV64A40_PIXEL_RATE, OV64A40_PIXEL_RATE, 1,
+ OV64A40_PIXEL_RATE);
+
+ ov64a40->link_freq =
+ v4l2_ctrl_new_int_menu(hdlr, &ov64a40_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ ov64a40->num_link_frequencies - 1,
+ 0, ov64a40->link_frequencies);
+
+ v4l2_ctrl_new_std_menu_items(hdlr, &ov64a40_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(ov64a40_test_pattern_menu) - 1,
+ 0, 0, ov64a40_test_pattern_menu);
+
+ timings = ov64a40_get_timings(ov64a40, 0);
+ exp_max = timings->vts - OV64A40_EXPOSURE_MARGIN;
+ ov64a40->exposure = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ OV64A40_EXPOSURE_MIN, exp_max, 1,
+ OV64A40_EXPOSURE_MIN);
+
+ hblank_val = timings->ppl * 4 - ov64a40->mode->width;
+ ov64a40->hblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
+ V4L2_CID_HBLANK, hblank_val,
+ hblank_val, 1, hblank_val);
+ if (ov64a40->hblank)
+ ov64a40->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ vblank_def = timings->vts - ov64a40->mode->height;
+ vblank_max = OV64A40_VTS_MAX - ov64a40->mode->height;
+ ov64a40->vblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
+ V4L2_CID_VBLANK, OV64A40_VBLANK_MIN,
+ vblank_max, 1, vblank_def);
+
+ v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ OV64A40_ANA_GAIN_MIN, OV64A40_ANA_GAIN_MAX, 1,
+ OV64A40_ANA_GAIN_DEFAULT);
+
+ ov64a40->hflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ if (ov64a40->hflip)
+ ov64a40->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+
+ ov64a40->vflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+ if (ov64a40->vflip)
+ ov64a40->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+
+ if (hdlr->error) {
+ ret = hdlr->error;
+ dev_err(ov64a40->dev, "control init failed: %d\n", ret);
+ goto error_free_hdlr;
+ }
+
+ ret = v4l2_fwnode_device_parse(ov64a40->dev, &props);
+ if (ret)
+ goto error_free_hdlr;
+
+ ret = v4l2_ctrl_new_fwnode_properties(hdlr, &ov64a40_ctrl_ops,
+ &props);
+ if (ret)
+ goto error_free_hdlr;
+
+ ov64a40->sd.ctrl_handler = hdlr;
+
+ return 0;
+
+error_free_hdlr:
+ v4l2_ctrl_handler_free(hdlr);
+ return ret;
+}
+
+static int ov64a40_identify(struct ov64a40 *ov64a40)
+{
+ int ret;
+ u64 id;
+
+ ret = cci_read(ov64a40->cci, OV64A40_REG_CHIP_ID, &id, NULL);
+ if (ret) {
+ dev_err(ov64a40->dev, "Failed to read chip id: %d\n", ret);
+ return ret;
+ }
+
+ if (id != OV64A40_CHIP_ID) {
+ dev_err(ov64a40->dev, "chip id mismatch: %#llx\n", id);
+ return -ENODEV;
+ }
+
+ dev_dbg(ov64a40->dev, "OV64A40 chip identified: %#llx\n", id);
+
+ return 0;
+}
+
+static int ov64a40_parse_dt(struct ov64a40 *ov64a40)
+{
+ struct v4l2_fwnode_endpoint v4l2_fwnode = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
+ struct fwnode_handle *endpoint;
+ unsigned int i;
+ int ret;
+
+ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(ov64a40->dev),
+ NULL);
+ if (!endpoint) {
+ dev_err(ov64a40->dev, "Failed to find endpoint\n");
+ return -EINVAL;
+ }
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &v4l2_fwnode);
+ fwnode_handle_put(endpoint);
+ if (ret) {
+ dev_err(ov64a40->dev, "Failed to parse endpoint\n");
+ return ret;
+ }
+
+ if (v4l2_fwnode.bus.mipi_csi2.num_data_lanes != 2) {
+ dev_err(ov64a40->dev, "Unsupported number of data lanes: %u\n",
+ v4l2_fwnode.bus.mipi_csi2.num_data_lanes);
+ v4l2_fwnode_endpoint_free(&v4l2_fwnode);
+ return -EINVAL;
+ }
+
+ if (!v4l2_fwnode.nr_of_link_frequencies) {
+ dev_warn(ov64a40->dev, "no link frequencies defined\n");
+ v4l2_fwnode_endpoint_free(&v4l2_fwnode);
+ return -EINVAL;
+ }
+
+ if (v4l2_fwnode.nr_of_link_frequencies > 2) {
+ dev_warn(ov64a40->dev,
+ "Unsupported number of link frequencies\n");
+ v4l2_fwnode_endpoint_free(&v4l2_fwnode);
+ return -EINVAL;
+ }
+
+ ov64a40->link_frequencies =
+ devm_kcalloc(ov64a40->dev, v4l2_fwnode.nr_of_link_frequencies,
+ sizeof(v4l2_fwnode.link_frequencies[0]),
+ GFP_KERNEL);
+ if (!ov64a40->link_frequencies) {
+ v4l2_fwnode_endpoint_free(&v4l2_fwnode);
+ return -ENOMEM;
+ }
+ ov64a40->num_link_frequencies = v4l2_fwnode.nr_of_link_frequencies;
+
+ for (i = 0; i < v4l2_fwnode.nr_of_link_frequencies; ++i) {
+ if (v4l2_fwnode.link_frequencies[i] != OV64A40_LINK_FREQ_360M &&
+ v4l2_fwnode.link_frequencies[i] != OV64A40_LINK_FREQ_456M) {
+ dev_err(ov64a40->dev,
+ "Unsupported link frequency %lld\n",
+ v4l2_fwnode.link_frequencies[i]);
+ v4l2_fwnode_endpoint_free(&v4l2_fwnode);
+ return -EINVAL;
+ }
+
+ ov64a40->link_frequencies[i] = v4l2_fwnode.link_frequencies[i];
+ }
+
+ v4l2_fwnode_endpoint_free(&v4l2_fwnode);
+
+ return 0;
+}
+
+static int ov64a40_get_regulators(struct ov64a40 *ov64a40)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&ov64a40->sd);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(ov64a40_supply_names); i++)
+ ov64a40->supplies[i].supply = ov64a40_supply_names[i];
+
+ return devm_regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(ov64a40_supply_names),
+ ov64a40->supplies);
+}
+
+static int ov64a40_probe(struct i2c_client *client)
+{
+ struct ov64a40 *ov64a40;
+ u32 xclk_freq;
+ int ret;
+
+ ov64a40 = devm_kzalloc(&client->dev, sizeof(*ov64a40), GFP_KERNEL);
+ if (!ov64a40)
+ return -ENOMEM;
+
+ ov64a40->dev = &client->dev;
+ v4l2_i2c_subdev_init(&ov64a40->sd, client, &ov64a40_subdev_ops);
+
+ ov64a40->cci = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(ov64a40->cci)) {
+ dev_err(&client->dev, "Failed to initialize CCI\n");
+ return PTR_ERR(ov64a40->cci);
+ }
+
+ ov64a40->xclk = devm_clk_get(&client->dev, NULL);
+ if (IS_ERR(ov64a40->xclk))
+ return dev_err_probe(&client->dev, PTR_ERR(ov64a40->xclk),
+ "Failed to get clock\n");
+
+ xclk_freq = clk_get_rate(ov64a40->xclk);
+ if (xclk_freq != OV64A40_XCLK_FREQ) {
+ dev_err(&client->dev, "Unsupported xclk frequency %u\n",
+ xclk_freq);
+ return -EINVAL;
+ }
+
+ ret = ov64a40_get_regulators(ov64a40);
+ if (ret)
+ return ret;
+
+ ov64a40->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ov64a40->reset_gpio))
+ return dev_err_probe(&client->dev, PTR_ERR(ov64a40->reset_gpio),
+ "Failed to get reset gpio\n");
+
+ ret = ov64a40_parse_dt(ov64a40);
+ if (ret)
+ return ret;
+
+ ret = ov64a40_power_on(&client->dev);
+ if (ret)
+ return ret;
+
+ ret = ov64a40_identify(ov64a40);
+ if (ret)
+ goto error_poweroff;
+
+ ov64a40->mode = &ov64a40_modes[0];
+
+ pm_runtime_set_active(&client->dev);
+ pm_runtime_get_noresume(&client->dev);
+ pm_runtime_enable(&client->dev);
+ pm_runtime_set_autosuspend_delay(&client->dev, 1000);
+ pm_runtime_use_autosuspend(&client->dev);
+
+ ret = ov64a40_init_controls(ov64a40);
+ if (ret)
+ goto error_poweroff;
+
+ /* Initialize subdev */
+ ov64a40->sd.internal_ops = &ov64a40_internal_ops;
+ ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE
+ | V4L2_SUBDEV_FL_HAS_EVENTS;
+ ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE;
+ ret = media_entity_pads_init(&ov64a40->sd.entity, 1, &ov64a40->pad);
+ if (ret) {
+ dev_err(&client->dev, "failed to init entity pads: %d\n", ret);
+ goto error_handler_free;
+ }
+
+ ov64a40->sd.state_lock = ov64a40->ctrl_handler.lock;
+ ret = v4l2_subdev_init_finalize(&ov64a40->sd);
+ if (ret < 0) {
+ dev_err(&client->dev, "subdev init error: %d\n", ret);
+ goto error_media_entity;
+ }
+
+ ret = v4l2_async_register_subdev_sensor(&ov64a40->sd);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "failed to register sensor sub-device: %d\n", ret);
+ goto error_subdev_cleanup;
+ }
+
+ pm_runtime_mark_last_busy(&client->dev);
+ pm_runtime_put_autosuspend(&client->dev);
+
+ return 0;
+
+error_subdev_cleanup:
+ v4l2_subdev_cleanup(&ov64a40->sd);
+error_media_entity:
+ media_entity_cleanup(&ov64a40->sd.entity);
+error_handler_free:
+ v4l2_ctrl_handler_free(ov64a40->sd.ctrl_handler);
+error_poweroff:
+ ov64a40_power_off(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+
+ return ret;
+}
+
+static void ov64a40_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+ v4l2_async_unregister_subdev(sd);
+ v4l2_subdev_cleanup(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev))
+ ov64a40_power_off(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+}
+
+static const struct of_device_id ov64a40_of_ids[] = {
+ { .compatible = "ovti,ov64a40" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ov64a40_of_ids);
+
+static const struct dev_pm_ops ov64a40_pm_ops = {
+ SET_RUNTIME_PM_OPS(ov64a40_power_off, ov64a40_power_on, NULL)
+};
+
+static struct i2c_driver ov64a40_i2c_driver = {
+ .driver = {
+ .name = "ov64a40",
+ .of_match_table = ov64a40_of_ids,
+ .pm = &ov64a40_pm_ops,
+ },
+ .probe = ov64a40_probe,
+ .remove = ov64a40_remove,
+};
+
+module_i2c_driver(ov64a40_i2c_driver);
+
+MODULE_AUTHOR("Jacopo Mondi <jacopo.mondi@ideasonboard.com>");
+MODULE_DESCRIPTION("OmniVision OV64A40 sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c
index 1ad07935f0..b65befb22a 100644
--- a/drivers/media/i2c/ov6650.c
+++ b/drivers/media/i2c/ov6650.c
@@ -197,7 +197,7 @@ struct ov6650 {
struct clk *clk;
bool half_scale; /* scale down output by 2 */
struct v4l2_rect rect; /* sensor cropping window */
- struct v4l2_fract tpf; /* as requested with s_frame_interval */
+ struct v4l2_fract tpf; /* as requested with set_frame_interval */
u32 code;
};
@@ -476,7 +476,7 @@ static int ov6650_get_selection(struct v4l2_subdev *sd,
if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
/* pre-select try crop rectangle */
- rect = &sd_state->pads->try_crop;
+ rect = v4l2_subdev_state_get_crop(sd_state, 0);
} else {
/* pre-select active crop rectangle */
@@ -531,8 +531,10 @@ static int ov6650_set_selection(struct v4l2_subdev *sd,
ov6650_bind_align_crop_rectangle(&sel->r);
if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
- struct v4l2_rect *crop = &sd_state->pads->try_crop;
- struct v4l2_mbus_framefmt *mf = &sd_state->pads->try_fmt;
+ struct v4l2_rect *crop =
+ v4l2_subdev_state_get_crop(sd_state, 0);
+ struct v4l2_mbus_framefmt *mf =
+ v4l2_subdev_state_get_format(sd_state, 0);
/* detect current pad config scaling factor */
bool half_scale = !is_unscaled_ok(mf->width, mf->height, crop);
@@ -588,9 +590,12 @@ static int ov6650_get_fmt(struct v4l2_subdev *sd,
/* update media bus format code and frame size */
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf->width = sd_state->pads->try_fmt.width;
- mf->height = sd_state->pads->try_fmt.height;
- mf->code = sd_state->pads->try_fmt.code;
+ struct v4l2_mbus_framefmt *try_fmt =
+ v4l2_subdev_state_get_format(sd_state, 0);
+
+ mf->width = try_fmt->width;
+ mf->height = try_fmt->height;
+ mf->code = try_fmt->code;
} else {
mf->width = priv->rect.width >> priv->half_scale;
@@ -717,23 +722,26 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd,
}
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- crop = &sd_state->pads->try_crop;
+ crop = v4l2_subdev_state_get_crop(sd_state, 0);
else
crop = &priv->rect;
half_scale = !is_unscaled_ok(mf->width, mf->height, crop);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *try_fmt =
+ v4l2_subdev_state_get_format(sd_state, 0);
+
/* store new mbus frame format code and size in pad config */
- sd_state->pads->try_fmt.width = crop->width >> half_scale;
- sd_state->pads->try_fmt.height = crop->height >> half_scale;
- sd_state->pads->try_fmt.code = mf->code;
+ try_fmt->width = crop->width >> half_scale;
+ try_fmt->height = crop->height >> half_scale;
+ try_fmt->code = mf->code;
/* return default mbus frame format updated with pad config */
*mf = ov6650_def_fmt;
- mf->width = sd_state->pads->try_fmt.width;
- mf->height = sd_state->pads->try_fmt.height;
- mf->code = sd_state->pads->try_fmt.code;
+ mf->width = try_fmt->width;
+ mf->height = try_fmt->height;
+ mf->code = try_fmt->code;
} else {
int ret = 0;
@@ -791,12 +799,20 @@ static int ov6650_enum_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-static int ov6650_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int ov6650_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov6650 *priv = to_ov6650(client);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
ival->interval = priv->tpf;
dev_dbg(&client->dev, "Frame interval: %u/%u s\n",
@@ -805,14 +821,22 @@ static int ov6650_g_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-static int ov6650_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int ov6650_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov6650 *priv = to_ov6650(client);
struct v4l2_fract *tpf = &ival->interval;
int div, ret;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (tpf->numerator == 0 || tpf->denominator == 0)
div = 1; /* Reset to full rate */
else
@@ -998,8 +1022,6 @@ static int ov6650_get_mbus_config(struct v4l2_subdev *sd,
static const struct v4l2_subdev_video_ops ov6650_video_ops = {
.s_stream = ov6650_s_stream,
- .g_frame_interval = ov6650_g_frame_interval,
- .s_frame_interval = ov6650_s_frame_interval,
};
static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
@@ -1009,6 +1031,8 @@ static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
.set_selection = ov6650_set_selection,
.get_fmt = ov6650_get_fmt,
.set_fmt = ov6650_set_fmt,
+ .get_frame_interval = ov6650_get_frame_interval,
+ .set_frame_interval = ov6650_set_frame_interval,
.get_mbus_config = ov6650_get_mbus_config,
};
diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c
index 6582cc0e23..30f61e04ec 100644
--- a/drivers/media/i2c/ov7251.c
+++ b/drivers/media/i2c/ov7251.c
@@ -1139,7 +1139,7 @@ __ov7251_get_pad_format(struct ov7251 *ov7251,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_format(&ov7251->sd, sd_state, pad);
+ return v4l2_subdev_state_get_format(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov7251->fmt;
default:
@@ -1169,7 +1169,7 @@ __ov7251_get_pad_crop(struct ov7251 *ov7251,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&ov7251->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov7251->crop;
default:
@@ -1282,8 +1282,8 @@ exit:
return ret;
}
-static int ov7251_entity_init_cfg(struct v4l2_subdev *subdev,
- struct v4l2_subdev_state *sd_state)
+static int ov7251_init_state(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state)
{
struct v4l2_subdev_format fmt = {
.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY
@@ -1386,10 +1386,18 @@ err_power_down:
}
static int ov7251_get_frame_interval(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval *fi)
{
struct ov7251 *ov7251 = to_ov7251(subdev);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&ov7251->lock);
fi->interval = ov7251->current_mode->timeperframe;
mutex_unlock(&ov7251->lock);
@@ -1398,12 +1406,20 @@ static int ov7251_get_frame_interval(struct v4l2_subdev *subdev,
}
static int ov7251_set_frame_interval(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval *fi)
{
struct ov7251 *ov7251 = to_ov7251(subdev);
const struct ov7251_mode_info *new_mode;
int ret = 0;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&ov7251->lock);
new_mode = ov7251_find_mode_by_ival(ov7251, &fi->interval);
@@ -1436,18 +1452,17 @@ exit:
static const struct v4l2_subdev_video_ops ov7251_video_ops = {
.s_stream = ov7251_s_stream,
- .g_frame_interval = ov7251_get_frame_interval,
- .s_frame_interval = ov7251_set_frame_interval,
};
static const struct v4l2_subdev_pad_ops ov7251_subdev_pad_ops = {
- .init_cfg = ov7251_entity_init_cfg,
.enum_mbus_code = ov7251_enum_mbus_code,
.enum_frame_size = ov7251_enum_frame_size,
.enum_frame_interval = ov7251_enum_frame_ival,
.get_fmt = ov7251_get_format,
.set_fmt = ov7251_set_format,
.get_selection = ov7251_get_selection,
+ .get_frame_interval = ov7251_get_frame_interval,
+ .set_frame_interval = ov7251_set_frame_interval,
};
static const struct v4l2_subdev_ops ov7251_subdev_ops = {
@@ -1455,6 +1470,10 @@ static const struct v4l2_subdev_ops ov7251_subdev_ops = {
.pad = &ov7251_subdev_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov7251_internal_ops = {
+ .init_state = ov7251_init_state,
+};
+
static int ov7251_check_hwcfg(struct ov7251 *ov7251)
{
struct fwnode_handle *fwnode = dev_fwnode(ov7251->dev);
@@ -1693,6 +1712,7 @@ static int ov7251_probe(struct i2c_client *client)
}
v4l2_i2c_subdev_init(&ov7251->sd, client, &ov7251_subdev_ops);
+ ov7251->sd.internal_ops = &ov7251_internal_ops;
ov7251->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov7251->pad.flags = MEDIA_PAD_FL_SOURCE;
ov7251->sd.dev = &client->dev;
@@ -1750,7 +1770,7 @@ static int ov7251_probe(struct i2c_client *client)
goto free_entity;
}
- ov7251_entity_init_cfg(&ov7251->sd, NULL);
+ ov7251_init_state(&ov7251->sd, NULL);
return 0;
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index 172483597c..0cb96b6c99 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -1112,8 +1112,7 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd,
ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL);
if (ret)
return ret;
- mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state,
- format->pad);
+ mbus_fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
*mbus_fmt = format->format;
return 0;
}
@@ -1141,7 +1140,7 @@ static int ov7670_get_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *mbus_fmt;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ mbus_fmt = v4l2_subdev_state_get_format(sd_state, 0);
format->format = *mbus_fmt;
return 0;
} else {
@@ -1155,23 +1154,37 @@ static int ov7670_get_fmt(struct v4l2_subdev *sd,
* Implement G/S_PARM. There is a "high quality" mode we could try
* to do someday; for now, we just do the frame rate tweak.
*/
-static int ov7670_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int ov7670_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct ov7670_info *info = to_state(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
info->devtype->get_framerate(sd, &ival->interval);
return 0;
}
-static int ov7670_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int ov7670_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct v4l2_fract *tpf = &ival->interval;
struct ov7670_info *info = to_state(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
return info->devtype->set_framerate(sd, tpf);
}
@@ -1707,7 +1720,7 @@ static void ov7670_get_default_format(struct v4l2_subdev *sd,
static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *format =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
ov7670_get_default_format(sd, format);
@@ -1729,22 +1742,18 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = {
#endif
};
-static const struct v4l2_subdev_video_ops ov7670_video_ops = {
- .s_frame_interval = ov7670_s_frame_interval,
- .g_frame_interval = ov7670_g_frame_interval,
-};
-
static const struct v4l2_subdev_pad_ops ov7670_pad_ops = {
.enum_frame_interval = ov7670_enum_frame_interval,
.enum_frame_size = ov7670_enum_frame_size,
.enum_mbus_code = ov7670_enum_mbus_code,
.get_fmt = ov7670_get_fmt,
.set_fmt = ov7670_set_fmt,
+ .get_frame_interval = ov7670_get_frame_interval,
+ .set_frame_interval = ov7670_set_frame_interval,
};
static const struct v4l2_subdev_ops ov7670_ops = {
.core = &ov7670_core_ops,
- .video = &ov7670_video_ops,
.pad = &ov7670_pad_ops,
};
diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
index 7618b58a7a..3e36a55274 100644
--- a/drivers/media/i2c/ov772x.c
+++ b/drivers/media/i2c/ov772x.c
@@ -717,26 +717,42 @@ static int ov772x_set_frame_rate(struct ov772x_priv *priv,
return 0;
}
-static int ov772x_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int ov772x_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct ov772x_priv *priv = to_ov772x(sd);
struct v4l2_fract *tpf = &ival->interval;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
tpf->numerator = 1;
tpf->denominator = priv->fps;
return 0;
}
-static int ov772x_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+static int ov772x_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct ov772x_priv *priv = to_ov772x(sd);
struct v4l2_fract *tpf = &ival->interval;
unsigned int fps;
int ret = 0;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&priv->lock);
if (priv->streaming) {
@@ -1220,7 +1236,7 @@ static int ov772x_set_fmt(struct v4l2_subdev *sd,
mf->xfer_func = V4L2_XFER_FUNC_DEFAULT;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- sd_state->pads->try_fmt = *mf;
+ *v4l2_subdev_state_get_format(sd_state, 0) = *mf;
return 0;
}
@@ -1349,8 +1365,6 @@ static int ov772x_enum_mbus_code(struct v4l2_subdev *sd,
static const struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
.s_stream = ov772x_s_stream,
- .s_frame_interval = ov772x_s_frame_interval,
- .g_frame_interval = ov772x_g_frame_interval,
};
static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = {
@@ -1359,6 +1373,8 @@ static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = {
.get_selection = ov772x_get_selection,
.get_fmt = ov772x_get_fmt,
.set_fmt = ov772x_set_fmt,
+ .get_frame_interval = ov772x_get_frame_interval,
+ .set_frame_interval = ov772x_set_frame_interval,
};
static const struct v4l2_subdev_ops ov772x_subdev_ops = {
diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c
index 356a45e65b..47b1b14d87 100644
--- a/drivers/media/i2c/ov7740.c
+++ b/drivers/media/i2c/ov7740.c
@@ -638,34 +638,8 @@ err_unlock:
return ret;
}
-static int ov7740_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
-{
- struct v4l2_fract *tpf = &ival->interval;
-
-
- tpf->numerator = 1;
- tpf->denominator = 60;
-
- return 0;
-}
-
-static int ov7740_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
-{
- struct v4l2_fract *tpf = &ival->interval;
-
-
- tpf->numerator = 1;
- tpf->denominator = 60;
-
- return 0;
-}
-
static const struct v4l2_subdev_video_ops ov7740_subdev_video_ops = {
.s_stream = ov7740_set_stream,
- .s_frame_interval = ov7740_s_frame_interval,
- .g_frame_interval = ov7740_g_frame_interval,
};
static const struct reg_sequence ov7740_format_yuyv[] = {
@@ -812,8 +786,7 @@ static int ov7740_set_fmt(struct v4l2_subdev *sd,
if (ret)
goto error;
- mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state,
- format->pad);
+ mbus_fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
*mbus_fmt = format->format;
mutex_unlock(&ov7740->mutex);
return 0;
@@ -843,7 +816,7 @@ static int ov7740_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&ov7740->mutex);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ mbus_fmt = v4l2_subdev_state_get_format(sd_state, 0);
format->format = *mbus_fmt;
} else {
format->format = ov7740->format;
@@ -853,12 +826,26 @@ static int ov7740_get_fmt(struct v4l2_subdev *sd,
return 0;
}
+static int ov7740_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
+{
+ struct v4l2_fract *tpf = &ival->interval;
+
+ tpf->numerator = 1;
+ tpf->denominator = 60;
+
+ return 0;
+}
+
static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = {
.enum_frame_interval = ov7740_enum_frame_interval,
.enum_frame_size = ov7740_enum_frame_size,
.enum_mbus_code = ov7740_enum_mbus_code,
.get_fmt = ov7740_get_fmt,
.set_fmt = ov7740_set_fmt,
+ .get_frame_interval = ov7740_get_frame_interval,
+ .set_frame_interval = ov7740_get_frame_interval,
};
static const struct v4l2_subdev_ops ov7740_subdev_ops = {
@@ -883,7 +870,7 @@ static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
struct v4l2_mbus_framefmt *format =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
mutex_lock(&ov7740->mutex);
ov7740_get_default_format(sd, format);
diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c
index a0f673a24e..6ffe10e57b 100644
--- a/drivers/media/i2c/ov8856.c
+++ b/drivers/media/i2c/ov8856.c
@@ -2134,7 +2134,7 @@ static int ov8856_set_format(struct v4l2_subdev *sd,
mutex_lock(&ov8856->mutex);
ov8856_update_pad_format(ov8856, mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
} else {
ov8856->cur_mode = mode;
__v4l2_ctrl_s_ctrl(ov8856->link_freq, mode->link_freq_index);
@@ -2172,9 +2172,8 @@ static int ov8856_get_format(struct v4l2_subdev *sd,
mutex_lock(&ov8856->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&ov8856->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
ov8856_update_pad_format(ov8856, ov8856->cur_mode, &fmt->format);
@@ -2225,7 +2224,7 @@ static int ov8856_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&ov8856->mutex);
ov8856_update_pad_format(ov8856, &ov8856->priv_lane->supported_modes[0],
- v4l2_subdev_get_try_format(sd, fh->state, 0));
+ v4l2_subdev_state_get_format(fh->state, 0));
mutex_unlock(&ov8856->mutex);
return 0;
diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c
index 4d9fd76e2f..174c65f768 100644
--- a/drivers/media/i2c/ov8858.c
+++ b/drivers/media/i2c/ov8858.c
@@ -1333,7 +1333,7 @@ static int ov8858_start_stream(struct ov8858 *ov8858,
if (ret)
return ret;
- format = v4l2_subdev_get_pad_format(&ov8858->subdev, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
mode = v4l2_find_nearest_size(ov8858_modes, ARRAY_SIZE(ov8858_modes),
width, height, format->width,
format->height);
@@ -1428,7 +1428,7 @@ static int ov8858_set_fmt(struct v4l2_subdev *sd,
fmt->format.field = V4L2_FIELD_NONE;
/* Store the format in the current subdev state. */
- *v4l2_subdev_get_pad_format(sd, state, 0) = fmt->format;
+ *v4l2_subdev_state_get_format(state, 0) = fmt->format;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
return 0;
@@ -1476,8 +1476,8 @@ static int ov8858_enum_mbus_code(struct v4l2_subdev *sd,
return 0;
}
-static int ov8858_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int ov8858_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
const struct ov8858_mode *def_mode = &ov8858_modes[0];
struct v4l2_subdev_format fmt = {
@@ -1494,7 +1494,6 @@ static int ov8858_init_cfg(struct v4l2_subdev *sd,
}
static const struct v4l2_subdev_pad_ops ov8858_pad_ops = {
- .init_cfg = ov8858_init_cfg,
.enum_mbus_code = ov8858_enum_mbus_code,
.enum_frame_size = ov8858_enum_frame_sizes,
.get_fmt = v4l2_subdev_get_fmt,
@@ -1512,6 +1511,10 @@ static const struct v4l2_subdev_ops ov8858_subdev_ops = {
.pad = &ov8858_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov8858_internal_ops = {
+ .init_state = ov8858_init_state,
+};
+
/* ----------------------------------------------------------------------------
* Controls handling
*/
@@ -1547,7 +1550,7 @@ static int ov8858_set_ctrl(struct v4l2_ctrl *ctrl)
* - by the driver when s_ctrl is called in the s_stream(1) call path
*/
state = v4l2_subdev_get_locked_active_state(&ov8858->subdev);
- format = v4l2_subdev_get_pad_format(&ov8858->subdev, state, 0);
+ format = v4l2_subdev_state_get_format(state, 0);
/* Propagate change of current control to all related controls */
switch (ctrl->id) {
@@ -1899,6 +1902,7 @@ static int ov8858_probe(struct i2c_client *client)
"Failed to get powerdown gpio\n");
v4l2_i2c_subdev_init(&ov8858->subdev, client, &ov8858_subdev_ops);
+ ov8858->subdev.internal_ops = &ov8858_internal_ops;
ret = ov8858_configure_regulators(ov8858);
if (ret)
diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c
index f2213c6158..95ffe7536a 100644
--- a/drivers/media/i2c/ov8865.c
+++ b/drivers/media/i2c/ov8865.c
@@ -2640,33 +2640,8 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev, int enable)
return 0;
}
-static int ov8865_g_frame_interval(struct v4l2_subdev *subdev,
- struct v4l2_subdev_frame_interval *interval)
-{
- struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);
- const struct ov8865_mode *mode;
- unsigned int framesize;
- unsigned int fps;
-
- mutex_lock(&sensor->mutex);
-
- mode = sensor->state.mode;
- framesize = mode->hts * (mode->output_size_y +
- sensor->ctrls.vblank->val);
- fps = DIV_ROUND_CLOSEST(sensor->ctrls.pixel_rate->val, framesize);
-
- interval->interval.numerator = 1;
- interval->interval.denominator = fps;
-
- mutex_unlock(&sensor->mutex);
-
- return 0;
-}
-
static const struct v4l2_subdev_video_ops ov8865_subdev_video_ops = {
.s_stream = ov8865_s_stream,
- .g_frame_interval = ov8865_g_frame_interval,
- .s_frame_interval = ov8865_g_frame_interval,
};
/* Subdev Pad Operations */
@@ -2710,8 +2685,8 @@ static int ov8865_get_fmt(struct v4l2_subdev *subdev,
mutex_lock(&sensor->mutex);
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *mbus_format = *v4l2_subdev_get_try_format(subdev, sd_state,
- format->pad);
+ *mbus_format = *v4l2_subdev_state_get_format(sd_state,
+ format->pad);
else
ov8865_mbus_format_fill(mbus_format, sensor->state.mbus_code,
sensor->state.mode);
@@ -2765,7 +2740,7 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev,
ov8865_mbus_format_fill(mbus_format, mbus_code, mode);
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- *v4l2_subdev_get_try_format(subdev, sd_state, format->pad) =
+ *v4l2_subdev_state_get_format(sd_state, format->pad) =
*mbus_format;
else if (sensor->state.mode != mode ||
sensor->state.mbus_code != mbus_code)
@@ -2818,7 +2793,7 @@ __ov8865_get_pad_crop(struct ov8865_sensor *sensor,
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- *r = *v4l2_subdev_get_try_crop(&sensor->subdev, state, pad);
+ *r = *v4l2_subdev_state_get_crop(state, pad);
break;
case V4L2_SUBDEV_FORMAT_ACTIVE:
r->height = mode->output_size_y;
@@ -2862,6 +2837,37 @@ static int ov8865_get_selection(struct v4l2_subdev *subdev,
return 0;
}
+static int ov8865_get_frame_interval(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *interval)
+{
+ struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);
+ const struct ov8865_mode *mode;
+ unsigned int framesize;
+ unsigned int fps;
+
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ mutex_lock(&sensor->mutex);
+
+ mode = sensor->state.mode;
+ framesize = mode->hts * (mode->output_size_y +
+ sensor->ctrls.vblank->val);
+ fps = DIV_ROUND_CLOSEST(sensor->ctrls.pixel_rate->val, framesize);
+
+ interval->interval.numerator = 1;
+ interval->interval.denominator = fps;
+
+ mutex_unlock(&sensor->mutex);
+
+ return 0;
+}
+
static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = {
.enum_mbus_code = ov8865_enum_mbus_code,
.get_fmt = ov8865_get_fmt,
@@ -2869,6 +2875,8 @@ static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = {
.enum_frame_size = ov8865_enum_frame_size,
.get_selection = ov8865_get_selection,
.set_selection = ov8865_get_selection,
+ .get_frame_interval = ov8865_get_frame_interval,
+ .set_frame_interval = ov8865_get_frame_interval,
};
static const struct v4l2_subdev_ops ov8865_subdev_ops = {
diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
index bf6dfce1b5..251a4b5349 100644
--- a/drivers/media/i2c/ov9282.c
+++ b/drivers/media/i2c/ov9282.c
@@ -814,7 +814,7 @@ static int ov9282_get_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
ov9282_fill_pad_format(ov9282, ov9282->cur_mode, ov9282->code,
@@ -860,7 +860,7 @@ static int ov9282_set_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
ret = ov9282_update_controls(ov9282, mode, fmt);
@@ -876,14 +876,14 @@ static int ov9282_set_pad_format(struct v4l2_subdev *sd,
}
/**
- * ov9282_init_pad_cfg() - Initialize sub-device pad configuration
+ * ov9282_init_state() - Initialize sub-device state
* @sd: pointer to ov9282 V4L2 sub-device structure
* @sd_state: V4L2 sub-device configuration
*
* Return: 0 if successful, error code otherwise.
*/
-static int ov9282_init_pad_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int ov9282_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct ov9282 *ov9282 = to_ov9282(sd);
struct v4l2_subdev_format fmt = { 0 };
@@ -902,7 +902,7 @@ __ov9282_get_pad_crop(struct ov9282 *ov9282,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&ov9282->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov9282->cur_mode->crop;
}
@@ -1192,7 +1192,6 @@ static const struct v4l2_subdev_video_ops ov9282_video_ops = {
};
static const struct v4l2_subdev_pad_ops ov9282_pad_ops = {
- .init_cfg = ov9282_init_pad_cfg,
.enum_mbus_code = ov9282_enum_mbus_code,
.enum_frame_size = ov9282_enum_frame_size,
.get_fmt = ov9282_get_pad_format,
@@ -1206,6 +1205,10 @@ static const struct v4l2_subdev_ops ov9282_subdev_ops = {
.pad = &ov9282_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov9282_internal_ops = {
+ .init_state = ov9282_init_state,
+};
+
/**
* ov9282_power_on() - Sensor power on sequence
* @dev: pointer to i2c device
@@ -1394,6 +1397,7 @@ static int ov9282_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&ov9282->sd, client, &ov9282_subdev_ops);
+ ov9282->sd.internal_ops = &ov9282_internal_ops;
v4l2_i2c_subdev_set_name(&ov9282->sd, client,
device_get_match_data(ov9282->dev), NULL);
diff --git a/drivers/media/i2c/ov9640.c b/drivers/media/i2c/ov9640.c
index cbaea04953..e9a52a8a9d 100644
--- a/drivers/media/i2c/ov9640.c
+++ b/drivers/media/i2c/ov9640.c
@@ -547,8 +547,6 @@ static int ov9640_set_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
return ov9640_s_fmt(sd, mf);
- sd_state->pads->try_fmt = *mf;
-
return 0;
}
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c
index da1ab5135e..66cd0e9ddc 100644
--- a/drivers/media/i2c/ov9650.c
+++ b/drivers/media/i2c/ov9650.c
@@ -1101,11 +1101,19 @@ static int ov965x_enum_frame_sizes(struct v4l2_subdev *sd,
return 0;
}
-static int ov965x_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int ov965x_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct ov965x *ov965x = to_ov965x(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&ov965x->lock);
fi->interval = ov965x->fiv->interval;
mutex_unlock(&ov965x->lock);
@@ -1148,12 +1156,20 @@ static int __ov965x_set_frame_interval(struct ov965x *ov965x,
return 0;
}
-static int ov965x_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int ov965x_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct ov965x *ov965x = to_ov965x(sd);
int ret;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
fi->interval.numerator, fi->interval.denominator);
@@ -1172,7 +1188,7 @@ static int ov965x_get_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *mf;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ mf = v4l2_subdev_state_get_format(sd_state, 0);
fmt->format = *mf;
return 0;
}
@@ -1233,8 +1249,7 @@ static int ov965x_set_fmt(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
if (sd_state) {
- mf = v4l2_subdev_get_try_format(sd, sd_state,
- fmt->pad);
+ mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*mf = fmt->format;
}
} else {
@@ -1363,7 +1378,7 @@ static int ov965x_s_stream(struct v4l2_subdev *sd, int on)
static int ov965x_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *mf =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
ov965x_get_default_format(mf);
return 0;
@@ -1374,12 +1389,12 @@ static const struct v4l2_subdev_pad_ops ov965x_pad_ops = {
.enum_frame_size = ov965x_enum_frame_sizes,
.get_fmt = ov965x_get_fmt,
.set_fmt = ov965x_set_fmt,
+ .get_frame_interval = ov965x_get_frame_interval,
+ .set_frame_interval = ov965x_set_frame_interval,
};
static const struct v4l2_subdev_video_ops ov965x_video_ops = {
.s_stream = ov965x_s_stream,
- .g_frame_interval = ov965x_g_frame_interval,
- .s_frame_interval = ov965x_s_frame_interval,
};
diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c
index f1377c305b..d997285974 100644
--- a/drivers/media/i2c/ov9734.c
+++ b/drivers/media/i2c/ov9734.c
@@ -697,7 +697,7 @@ static int ov9734_set_format(struct v4l2_subdev *sd,
mutex_lock(&ov9734->mutex);
ov9734_update_pad_format(mode, &fmt->format);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
} else {
ov9734->cur_mode = mode;
__v4l2_ctrl_s_ctrl(ov9734->link_freq, mode->link_freq_index);
@@ -730,9 +730,8 @@ static int ov9734_get_format(struct v4l2_subdev *sd,
mutex_lock(&ov9734->mutex);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt->format = *v4l2_subdev_get_try_format(&ov9734->sd,
- sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
else
ov9734_update_pad_format(ov9734->cur_mode, &fmt->format);
@@ -777,7 +776,7 @@ static int ov9734_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&ov9734->mutex);
ov9734_update_pad_format(&supported_modes[0],
- v4l2_subdev_get_try_format(sd, fh->state, 0));
+ v4l2_subdev_state_get_format(fh->state, 0));
mutex_unlock(&ov9734->mutex);
return 0;
diff --git a/drivers/media/i2c/rj54n1cb0c.c b/drivers/media/i2c/rj54n1cb0c.c
index b430046f9e..a59db10153 100644
--- a/drivers/media/i2c/rj54n1cb0c.c
+++ b/drivers/media/i2c/rj54n1cb0c.c
@@ -1008,10 +1008,8 @@ static int rj54n1_set_fmt(struct v4l2_subdev *sd,
v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align,
&mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0);
- if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- sd_state->pads->try_fmt = *mf;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
return 0;
- }
/*
* Verify if the sensor has just been powered on. TODO: replace this
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index ed5b10731a..af8d01f78c 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -819,7 +819,6 @@ static void s5c73m3_oif_try_format(struct s5c73m3 *state,
struct v4l2_subdev_format *fmt,
const struct s5c73m3_frame_size **fs)
{
- struct v4l2_subdev *sd = &state->sensor_sd;
u32 code;
switch (fmt->pad) {
@@ -841,10 +840,8 @@ static void s5c73m3_oif_try_format(struct s5c73m3 *state,
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
*fs = state->oif_pix_size[RES_ISP];
else
- *fs = s5c73m3_find_frame_size(
- v4l2_subdev_get_try_format(sd, sd_state,
- OIF_ISP_PAD),
- RES_ISP);
+ *fs = s5c73m3_find_frame_size(v4l2_subdev_state_get_format(sd_state, OIF_ISP_PAD),
+ RES_ISP);
break;
}
@@ -869,11 +866,19 @@ static void s5c73m3_try_format(struct s5c73m3 *state,
s5c73m3_fill_mbus_fmt(&fmt->format, *fs, code);
}
-static int s5c73m3_oif_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int s5c73m3_oif_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (fi->pad != OIF_SOURCE_PAD)
return -EINVAL;
@@ -918,12 +923,20 @@ static int __s5c73m3_set_frame_interval(struct s5c73m3 *state,
return 0;
}
-static int s5c73m3_oif_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int s5c73m3_oif_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);
int ret;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
if (fi->pad != OIF_SOURCE_PAD)
return -EINVAL;
@@ -990,8 +1003,8 @@ static int s5c73m3_get_fmt(struct v4l2_subdev *sd,
u32 code;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- fmt->format = *v4l2_subdev_get_try_format(sd, sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
return 0;
}
@@ -1025,8 +1038,8 @@ static int s5c73m3_oif_get_fmt(struct v4l2_subdev *sd,
u32 code;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- fmt->format = *v4l2_subdev_get_try_format(sd, sd_state,
- fmt->pad);
+ fmt->format = *v4l2_subdev_state_get_format(sd_state,
+ fmt->pad);
return 0;
}
@@ -1069,7 +1082,7 @@ static int s5c73m3_set_fmt(struct v4l2_subdev *sd,
s5c73m3_try_format(state, sd_state, fmt, &frame_size);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*mf = fmt->format;
} else {
switch (fmt->pad) {
@@ -1108,11 +1121,11 @@ static int s5c73m3_oif_set_fmt(struct v4l2_subdev *sd,
s5c73m3_oif_try_format(state, sd_state, fmt, &frame_size);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*mf = fmt->format;
if (fmt->pad == OIF_ISP_PAD) {
- mf = v4l2_subdev_get_try_format(sd, sd_state,
- OIF_SOURCE_PAD);
+ mf = v4l2_subdev_state_get_format(sd_state,
+ OIF_SOURCE_PAD);
mf->width = fmt->format.width;
mf->height = fmt->format.height;
}
@@ -1260,8 +1273,8 @@ static int s5c73m3_oif_enum_frame_size(struct v4l2_subdev *sd,
if (fse->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *mf;
- mf = v4l2_subdev_get_try_format(sd, sd_state,
- OIF_ISP_PAD);
+ mf = v4l2_subdev_state_get_format(sd_state,
+ OIF_ISP_PAD);
w = mf->width;
h = mf->height;
@@ -1316,11 +1329,11 @@ static int s5c73m3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *mf;
- mf = v4l2_subdev_get_try_format(sd, fh->state, S5C73M3_ISP_PAD);
+ mf = v4l2_subdev_state_get_format(fh->state, S5C73M3_ISP_PAD);
s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],
S5C73M3_ISP_FMT);
- mf = v4l2_subdev_get_try_format(sd, fh->state, S5C73M3_JPEG_PAD);
+ mf = v4l2_subdev_state_get_format(fh->state, S5C73M3_JPEG_PAD);
s5c73m3_fill_mbus_fmt(mf, &s5c73m3_jpeg_resolutions[1],
S5C73M3_JPEG_FMT);
@@ -1331,15 +1344,15 @@ static int s5c73m3_oif_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *mf;
- mf = v4l2_subdev_get_try_format(sd, fh->state, OIF_ISP_PAD);
+ mf = v4l2_subdev_state_get_format(fh->state, OIF_ISP_PAD);
s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],
S5C73M3_ISP_FMT);
- mf = v4l2_subdev_get_try_format(sd, fh->state, OIF_JPEG_PAD);
+ mf = v4l2_subdev_state_get_format(fh->state, OIF_JPEG_PAD);
s5c73m3_fill_mbus_fmt(mf, &s5c73m3_jpeg_resolutions[1],
S5C73M3_JPEG_FMT);
- mf = v4l2_subdev_get_try_format(sd, fh->state, OIF_SOURCE_PAD);
+ mf = v4l2_subdev_state_get_format(fh->state, OIF_SOURCE_PAD);
s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],
S5C73M3_ISP_FMT);
return 0;
@@ -1500,6 +1513,8 @@ static const struct v4l2_subdev_pad_ops s5c73m3_oif_pad_ops = {
.enum_frame_interval = s5c73m3_oif_enum_frame_interval,
.get_fmt = s5c73m3_oif_get_fmt,
.set_fmt = s5c73m3_oif_set_fmt,
+ .get_frame_interval = s5c73m3_oif_get_frame_interval,
+ .set_frame_interval = s5c73m3_oif_set_frame_interval,
.get_frame_desc = s5c73m3_oif_get_frame_desc,
.set_frame_desc = s5c73m3_oif_set_frame_desc,
};
@@ -1511,8 +1526,6 @@ static const struct v4l2_subdev_core_ops s5c73m3_oif_core_ops = {
static const struct v4l2_subdev_video_ops s5c73m3_oif_video_ops = {
.s_stream = s5c73m3_oif_s_stream,
- .g_frame_interval = s5c73m3_oif_g_frame_interval,
- .s_frame_interval = s5c73m3_oif_s_frame_interval,
};
static const struct v4l2_subdev_ops oif_subdev_ops = {
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 67da2045f5..de079d2c92 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -1118,11 +1118,19 @@ out:
return ret;
}
-static int s5k5baf_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int s5k5baf_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct s5k5baf *state = to_s5k5baf(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&state->lock);
fi->interval.numerator = state->fiv;
fi->interval.denominator = 10000;
@@ -1131,8 +1139,8 @@ static int s5k5baf_g_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-static void s5k5baf_set_frame_interval(struct s5k5baf *state,
- struct v4l2_subdev_frame_interval *fi)
+static void __s5k5baf_set_frame_interval(struct s5k5baf *state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct v4l2_fract *i = &fi->interval;
@@ -1155,13 +1163,21 @@ static void s5k5baf_set_frame_interval(struct s5k5baf *state,
state->fiv);
}
-static int s5k5baf_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+static int s5k5baf_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
{
struct s5k5baf *state = to_s5k5baf(sd);
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
mutex_lock(&state->lock);
- s5k5baf_set_frame_interval(state, fi);
+ __s5k5baf_set_frame_interval(state, fi);
mutex_unlock(&state->lock);
return 0;
}
@@ -1273,7 +1289,7 @@ static int s5k5baf_get_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *mf;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *mf;
return 0;
}
@@ -1307,7 +1323,7 @@ static int s5k5baf_set_fmt(struct v4l2_subdev *sd,
mf->field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = *mf;
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = *mf;
return 0;
}
@@ -1379,11 +1395,11 @@ static int s5k5baf_get_selection(struct v4l2_subdev *sd,
if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
if (rtype == R_COMPOSE)
- sel->r = *v4l2_subdev_get_try_compose(sd, sd_state,
- sel->pad);
+ sel->r = *v4l2_subdev_state_get_compose(sd_state,
+ sel->pad);
else
- sel->r = *v4l2_subdev_get_try_crop(sd, sd_state,
- sel->pad);
+ sel->r = *v4l2_subdev_state_get_crop(sd_state,
+ sel->pad);
return 0;
}
@@ -1472,14 +1488,11 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
rects = (struct v4l2_rect * []) {
- &s5k5baf_cis_rect,
- v4l2_subdev_get_try_crop(sd, sd_state,
- PAD_CIS),
- v4l2_subdev_get_try_compose(sd, sd_state,
- PAD_CIS),
- v4l2_subdev_get_try_crop(sd, sd_state,
- PAD_OUT)
- };
+ &s5k5baf_cis_rect,
+ v4l2_subdev_state_get_crop(sd_state, PAD_CIS),
+ v4l2_subdev_state_get_compose(sd_state, PAD_CIS),
+ v4l2_subdev_state_get_crop(sd_state, PAD_OUT)
+ };
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
}
@@ -1529,11 +1542,11 @@ static const struct v4l2_subdev_pad_ops s5k5baf_pad_ops = {
.set_fmt = s5k5baf_set_fmt,
.get_selection = s5k5baf_get_selection,
.set_selection = s5k5baf_set_selection,
+ .get_frame_interval = s5k5baf_get_frame_interval,
+ .set_frame_interval = s5k5baf_set_frame_interval,
};
static const struct v4l2_subdev_video_ops s5k5baf_video_ops = {
- .g_frame_interval = s5k5baf_g_frame_interval,
- .s_frame_interval = s5k5baf_s_frame_interval,
.s_stream = s5k5baf_s_stream,
};
@@ -1696,22 +1709,22 @@ static int s5k5baf_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *mf;
- mf = v4l2_subdev_get_try_format(sd, fh->state, PAD_CIS);
+ mf = v4l2_subdev_state_get_format(fh->state, PAD_CIS);
s5k5baf_try_cis_format(mf);
if (s5k5baf_is_cis_subdev(sd))
return 0;
- mf = v4l2_subdev_get_try_format(sd, fh->state, PAD_OUT);
+ mf = v4l2_subdev_state_get_format(fh->state, PAD_OUT);
mf->colorspace = s5k5baf_formats[0].colorspace;
mf->code = s5k5baf_formats[0].code;
mf->width = s5k5baf_cis_rect.width;
mf->height = s5k5baf_cis_rect.height;
mf->field = V4L2_FIELD_NONE;
- *v4l2_subdev_get_try_crop(sd, fh->state, PAD_CIS) = s5k5baf_cis_rect;
- *v4l2_subdev_get_try_compose(sd, fh->state, PAD_CIS) = s5k5baf_cis_rect;
- *v4l2_subdev_get_try_crop(sd, fh->state, PAD_OUT) = s5k5baf_cis_rect;
+ *v4l2_subdev_state_get_crop(fh->state, PAD_CIS) = s5k5baf_cis_rect;
+ *v4l2_subdev_state_get_compose(fh->state, PAD_CIS) = s5k5baf_cis_rect;
+ *v4l2_subdev_state_get_crop(fh->state, PAD_OUT) = s5k5baf_cis_rect;
return 0;
}
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
index b3560c8f8b..0c2674115b 100644
--- a/drivers/media/i2c/s5k6a3.c
+++ b/drivers/media/i2c/s5k6a3.c
@@ -127,8 +127,7 @@ static struct v4l2_mbus_framefmt *__s5k6a3_get_format(
u32 pad, enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
- return sd_state ? v4l2_subdev_get_try_format(&sensor->subdev,
- sd_state, pad) : NULL;
+ return sd_state ? v4l2_subdev_state_get_format(sd_state, pad) : NULL;
return &sensor->format;
}
@@ -174,9 +173,8 @@ static const struct v4l2_subdev_pad_ops s5k6a3_pad_ops = {
static int s5k6a3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
- struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
- fh->state,
- 0);
+ struct v4l2_mbus_framefmt *format = v4l2_subdev_state_get_format(fh->state,
+ 0);
*format = s5k6a3_formats[0];
format->width = S5K6A3_DEFAULT_WIDTH;
diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c
index c106e7a7d1..897eaa669b 100644
--- a/drivers/media/i2c/saa6752hs.c
+++ b/drivers/media/i2c/saa6752hs.c
@@ -594,10 +594,8 @@ static int saa6752hs_set_fmt(struct v4l2_subdev *sd,
f->field = V4L2_FIELD_INTERLACED;
f->colorspace = V4L2_COLORSPACE_SMPTE170M;
- if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- sd_state->pads->try_fmt = *f;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
return 0;
- }
/*
FIXME: translate and round width/height into EMPRESS
diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
index dab1478711..f250640729 100644
--- a/drivers/media/i2c/st-mipid02.c
+++ b/drivers/media/i2c/st-mipid02.c
@@ -16,25 +16,27 @@
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
+#include <media/mipi-csi2.h>
#include <media/v4l2-async.h>
+#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
-#define MIPID02_CLK_LANE_WR_REG1 0x01
-#define MIPID02_CLK_LANE_REG1 0x02
-#define MIPID02_CLK_LANE_REG3 0x04
-#define MIPID02_DATA_LANE0_REG1 0x05
-#define MIPID02_DATA_LANE0_REG2 0x06
-#define MIPID02_DATA_LANE1_REG1 0x09
-#define MIPID02_DATA_LANE1_REG2 0x0a
-#define MIPID02_MODE_REG1 0x14
-#define MIPID02_MODE_REG2 0x15
-#define MIPID02_DATA_ID_RREG 0x17
-#define MIPID02_DATA_SELECTION_CTRL 0x19
-#define MIPID02_PIX_WIDTH_CTRL 0x1e
-#define MIPID02_PIX_WIDTH_CTRL_EMB 0x1f
+#define MIPID02_CLK_LANE_WR_REG1 CCI_REG8(0x01)
+#define MIPID02_CLK_LANE_REG1 CCI_REG8(0x02)
+#define MIPID02_CLK_LANE_REG3 CCI_REG8(0x04)
+#define MIPID02_DATA_LANE0_REG1 CCI_REG8(0x05)
+#define MIPID02_DATA_LANE0_REG2 CCI_REG8(0x06)
+#define MIPID02_DATA_LANE1_REG1 CCI_REG8(0x09)
+#define MIPID02_DATA_LANE1_REG2 CCI_REG8(0x0a)
+#define MIPID02_MODE_REG1 CCI_REG8(0x14)
+#define MIPID02_MODE_REG2 CCI_REG8(0x15)
+#define MIPID02_DATA_ID_RREG CCI_REG8(0x17)
+#define MIPID02_DATA_SELECTION_CTRL CCI_REG8(0x19)
+#define MIPID02_PIX_WIDTH_CTRL CCI_REG8(0x1e)
+#define MIPID02_PIX_WIDTH_CTRL_EMB CCI_REG8(0x1f)
/* Bits definition for MIPID02_CLK_LANE_REG1 */
#define CLK_ENABLE BIT(0)
@@ -68,7 +70,7 @@ static const u32 mipid02_supported_fmt_codes[] = {
MEDIA_BUS_FMT_RGB565_2X8_LE, MEDIA_BUS_FMT_RGB565_2X8_BE,
MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YVYU8_2X8,
MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_VYUY8_2X8,
- MEDIA_BUS_FMT_JPEG_1X8
+ MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_JPEG_1X8
};
/* regulator supplies */
@@ -88,12 +90,12 @@ struct mipid02_dev {
struct i2c_client *i2c_client;
struct regulator_bulk_data supplies[MIPID02_NUM_SUPPLIES];
struct v4l2_subdev sd;
+ struct regmap *regmap;
struct media_pad pad[MIPID02_PAD_NB];
struct clk *xclk;
struct gpio_desc *reset_gpio;
/* endpoints info */
struct v4l2_fwnode_endpoint rx;
- u64 link_frequency;
struct v4l2_fwnode_endpoint tx;
/* remote source */
struct v4l2_async_notifier notifier;
@@ -110,10 +112,6 @@ struct mipid02_dev {
u8 pix_width_ctrl;
u8 pix_width_ctrl_emb;
} r;
- /* lock to protect all members below */
- struct mutex lock;
- bool streaming;
- struct v4l2_mbus_framefmt fmt;
};
static int bpp_from_code(__u32 code)
@@ -123,6 +121,7 @@ static int bpp_from_code(__u32 code)
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
+ case MEDIA_BUS_FMT_Y8_1X8:
return 8;
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
@@ -160,17 +159,18 @@ static u8 data_type_from_code(__u32 code)
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
- return 0x2a;
+ case MEDIA_BUS_FMT_Y8_1X8:
+ return MIPI_CSI2_DT_RAW8;
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
- return 0x2b;
+ return MIPI_CSI2_DT_RAW10;
case MEDIA_BUS_FMT_SBGGR12_1X12:
case MEDIA_BUS_FMT_SGBRG12_1X12:
case MEDIA_BUS_FMT_SGRBG12_1X12:
case MEDIA_BUS_FMT_SRGGB12_1X12:
- return 0x2c;
+ return MIPI_CSI2_DT_RAW12;
case MEDIA_BUS_FMT_YUYV8_1X16:
case MEDIA_BUS_FMT_YVYU8_1X16:
case MEDIA_BUS_FMT_UYVY8_1X16:
@@ -179,30 +179,18 @@ static u8 data_type_from_code(__u32 code)
case MEDIA_BUS_FMT_YVYU8_2X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
- return 0x1e;
+ return MIPI_CSI2_DT_YUV422_8B;
case MEDIA_BUS_FMT_BGR888_1X24:
- return 0x24;
+ return MIPI_CSI2_DT_RGB888;
case MEDIA_BUS_FMT_RGB565_1X16:
case MEDIA_BUS_FMT_RGB565_2X8_LE:
case MEDIA_BUS_FMT_RGB565_2X8_BE:
- return 0x22;
+ return MIPI_CSI2_DT_RGB565;
default:
return 0;
}
}
-static void init_format(struct v4l2_mbus_framefmt *fmt)
-{
- fmt->code = MEDIA_BUS_FMT_SBGGR8_1X8;
- fmt->field = V4L2_FIELD_NONE;
- fmt->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB);
- fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
- fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB);
- fmt->width = 640;
- fmt->height = 480;
-}
-
static __u32 get_fmt_code(__u32 code)
{
unsigned int i;
@@ -238,62 +226,6 @@ static inline struct mipid02_dev *to_mipid02_dev(struct v4l2_subdev *sd)
return container_of(sd, struct mipid02_dev, sd);
}
-static int mipid02_read_reg(struct mipid02_dev *bridge, u16 reg, u8 *val)
-{
- struct i2c_client *client = bridge->i2c_client;
- struct i2c_msg msg[2];
- u8 buf[2];
- int ret;
-
- buf[0] = reg >> 8;
- buf[1] = reg & 0xff;
-
- msg[0].addr = client->addr;
- msg[0].flags = client->flags;
- msg[0].buf = buf;
- msg[0].len = sizeof(buf);
-
- msg[1].addr = client->addr;
- msg[1].flags = client->flags | I2C_M_RD;
- msg[1].buf = val;
- msg[1].len = 1;
-
- ret = i2c_transfer(client->adapter, msg, 2);
- if (ret < 0) {
- dev_dbg(&client->dev, "%s: %x i2c_transfer, reg: %x => %d\n",
- __func__, client->addr, reg, ret);
- return ret;
- }
-
- return 0;
-}
-
-static int mipid02_write_reg(struct mipid02_dev *bridge, u16 reg, u8 val)
-{
- struct i2c_client *client = bridge->i2c_client;
- struct i2c_msg msg;
- u8 buf[3];
- int ret;
-
- buf[0] = reg >> 8;
- buf[1] = reg & 0xff;
- buf[2] = val;
-
- msg.addr = client->addr;
- msg.flags = client->flags;
- msg.buf = buf;
- msg.len = sizeof(buf);
-
- ret = i2c_transfer(client->adapter, &msg, 1);
- if (ret < 0) {
- dev_dbg(&client->dev, "%s: i2c_transfer, reg: %x => %d\n",
- __func__, reg, ret);
- return ret;
- }
-
- return 0;
-}
-
static int mipid02_get_regulators(struct mipid02_dev *bridge)
{
unsigned int i;
@@ -358,73 +290,44 @@ static void mipid02_set_power_off(struct mipid02_dev *bridge)
static int mipid02_detect(struct mipid02_dev *bridge)
{
- u8 reg;
+ u64 reg;
/*
* There is no version registers. Just try to read register
* MIPID02_CLK_LANE_WR_REG1.
*/
- return mipid02_read_reg(bridge, MIPID02_CLK_LANE_WR_REG1, &reg);
-}
-
-static u32 mipid02_get_link_freq_from_cid_link_freq(struct mipid02_dev *bridge,
- struct v4l2_subdev *subdev)
-{
- struct v4l2_querymenu qm = {.id = V4L2_CID_LINK_FREQ, };
- struct v4l2_ctrl *ctrl;
- int ret;
-
- ctrl = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_LINK_FREQ);
- if (!ctrl)
- return 0;
- qm.index = v4l2_ctrl_g_ctrl(ctrl);
-
- ret = v4l2_querymenu(subdev->ctrl_handler, &qm);
- if (ret)
- return 0;
-
- return qm.value;
-}
-
-static u32 mipid02_get_link_freq_from_cid_pixel_rate(struct mipid02_dev *bridge,
- struct v4l2_subdev *subdev)
-{
- struct v4l2_fwnode_endpoint *ep = &bridge->rx;
- struct v4l2_ctrl *ctrl;
- u32 pixel_clock;
- u32 bpp = bpp_from_code(bridge->fmt.code);
-
- ctrl = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_PIXEL_RATE);
- if (!ctrl)
- return 0;
- pixel_clock = v4l2_ctrl_g_ctrl_int64(ctrl);
-
- return pixel_clock * bpp / (2 * ep->bus.mipi_csi2.num_data_lanes);
+ return cci_read(bridge->regmap, MIPID02_CLK_LANE_WR_REG1, &reg, NULL);
}
/*
* We need to know link frequency to setup clk_lane_reg1 timings. Link frequency
- * will be computed using connected device V4L2_CID_PIXEL_RATE, bit per pixel
+ * will be retrieve from connected device via v4l2_get_link_freq, bit per pixel
* and number of lanes.
*/
-static int mipid02_configure_from_rx_speed(struct mipid02_dev *bridge)
+static int mipid02_configure_from_rx_speed(struct mipid02_dev *bridge,
+ struct v4l2_mbus_framefmt *fmt)
{
struct i2c_client *client = bridge->i2c_client;
struct v4l2_subdev *subdev = bridge->s_subdev;
- u32 link_freq;
-
- link_freq = mipid02_get_link_freq_from_cid_link_freq(bridge, subdev);
- if (!link_freq) {
- link_freq = mipid02_get_link_freq_from_cid_pixel_rate(bridge,
- subdev);
- if (!link_freq) {
- dev_err(&client->dev, "Failed to get link frequency");
- return -EINVAL;
- }
+ struct v4l2_fwnode_endpoint *ep = &bridge->rx;
+ u32 bpp = bpp_from_code(fmt->code);
+ /*
+ * clk_lane_reg1 requires 4 times the unit interval time, and bitrate
+ * is twice the link frequency, hence ui_4 = 1000000000 * 4 / 2
+ */
+ u64 ui_4 = 2000000000;
+ s64 link_freq;
+
+ link_freq = v4l2_get_link_freq(subdev->ctrl_handler, bpp,
+ 2 * ep->bus.mipi_csi2.num_data_lanes);
+ if (link_freq < 0) {
+ dev_err(&client->dev, "Failed to get link frequency");
+ return -EINVAL;
}
- dev_dbg(&client->dev, "detect link_freq = %d Hz", link_freq);
- bridge->r.clk_lane_reg1 |= (2000000000 / link_freq) << 2;
+ dev_dbg(&client->dev, "detect link_freq = %lld Hz", link_freq);
+ do_div(ui_4, link_freq);
+ bridge->r.clk_lane_reg1 |= ui_4 << 2;
return 0;
}
@@ -479,7 +382,8 @@ static int mipid02_configure_data1_lane(struct mipid02_dev *bridge, int nb,
return 0;
}
-static int mipid02_configure_from_rx(struct mipid02_dev *bridge)
+static int mipid02_configure_from_rx(struct mipid02_dev *bridge,
+ struct v4l2_mbus_framefmt *fmt)
{
struct v4l2_fwnode_endpoint *ep = &bridge->rx;
bool are_lanes_swap = ep->bus.mipi_csi2.data_lanes[0] == 2;
@@ -504,7 +408,7 @@ static int mipid02_configure_from_rx(struct mipid02_dev *bridge)
bridge->r.mode_reg1 |= are_lanes_swap ? MODE_DATA_SWAP : 0;
bridge->r.mode_reg1 |= (nb - 1) << 1;
- return mipid02_configure_from_rx_speed(bridge);
+ return mipid02_configure_from_rx_speed(bridge, fmt);
}
static int mipid02_configure_from_tx(struct mipid02_dev *bridge)
@@ -524,16 +428,17 @@ static int mipid02_configure_from_tx(struct mipid02_dev *bridge)
return 0;
}
-static int mipid02_configure_from_code(struct mipid02_dev *bridge)
+static int mipid02_configure_from_code(struct mipid02_dev *bridge,
+ struct v4l2_mbus_framefmt *fmt)
{
u8 data_type;
bridge->r.data_id_rreg = 0;
- if (bridge->fmt.code != MEDIA_BUS_FMT_JPEG_1X8) {
+ if (fmt->code != MEDIA_BUS_FMT_JPEG_1X8) {
bridge->r.data_selection_ctrl |= SELECTION_MANUAL_DATA;
- data_type = data_type_from_code(bridge->fmt.code);
+ data_type = data_type_from_code(fmt->code);
if (!data_type)
return -EINVAL;
bridge->r.data_id_rreg = data_type;
@@ -555,13 +460,9 @@ static int mipid02_stream_disable(struct mipid02_dev *bridge)
goto error;
/* Disable all lanes */
- ret = mipid02_write_reg(bridge, MIPID02_CLK_LANE_REG1, 0);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE0_REG1, 0);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE1_REG1, 0);
+ cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1, 0, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1, 0, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1, 0, &ret);
if (ret)
goto error;
error:
@@ -574,69 +475,52 @@ error:
static int mipid02_stream_enable(struct mipid02_dev *bridge)
{
struct i2c_client *client = bridge->i2c_client;
+ struct v4l2_subdev_state *state;
+ struct v4l2_mbus_framefmt *fmt;
int ret = -EINVAL;
if (!bridge->s_subdev)
goto error;
memset(&bridge->r, 0, sizeof(bridge->r));
+
+ state = v4l2_subdev_lock_and_get_active_state(&bridge->sd);
+ fmt = v4l2_subdev_state_get_format(state, MIPID02_SINK_0);
+
/* build registers content */
- ret = mipid02_configure_from_rx(bridge);
+ ret = mipid02_configure_from_rx(bridge, fmt);
if (ret)
goto error;
ret = mipid02_configure_from_tx(bridge);
if (ret)
goto error;
- ret = mipid02_configure_from_code(bridge);
+ ret = mipid02_configure_from_code(bridge, fmt);
if (ret)
goto error;
+ v4l2_subdev_unlock_state(state);
+
/* write mipi registers */
- ret = mipid02_write_reg(bridge, MIPID02_CLK_LANE_REG1,
- bridge->r.clk_lane_reg1);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_CLK_LANE_REG3, CLK_MIPI_CSI);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE0_REG1,
- bridge->r.data_lane0_reg1);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE0_REG2,
- DATA_MIPI_CSI);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE1_REG1,
- bridge->r.data_lane1_reg1);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE1_REG2,
- DATA_MIPI_CSI);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_MODE_REG1,
- MODE_NO_BYPASS | bridge->r.mode_reg1);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_MODE_REG2,
- bridge->r.mode_reg2);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_DATA_ID_RREG,
- bridge->r.data_id_rreg);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_DATA_SELECTION_CTRL,
- bridge->r.data_selection_ctrl);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_PIX_WIDTH_CTRL,
- bridge->r.pix_width_ctrl);
- if (ret)
- goto error;
- ret = mipid02_write_reg(bridge, MIPID02_PIX_WIDTH_CTRL_EMB,
- bridge->r.pix_width_ctrl_emb);
+ cci_write(bridge->regmap, MIPID02_CLK_LANE_REG1,
+ bridge->r.clk_lane_reg1, &ret);
+ cci_write(bridge->regmap, MIPID02_CLK_LANE_REG3, CLK_MIPI_CSI, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG1,
+ bridge->r.data_lane0_reg1, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_LANE0_REG2, DATA_MIPI_CSI, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG1,
+ bridge->r.data_lane1_reg1, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_LANE1_REG2, DATA_MIPI_CSI, &ret);
+ cci_write(bridge->regmap, MIPID02_MODE_REG1,
+ MODE_NO_BYPASS | bridge->r.mode_reg1, &ret);
+ cci_write(bridge->regmap, MIPID02_MODE_REG2, bridge->r.mode_reg2, &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_ID_RREG, bridge->r.data_id_rreg,
+ &ret);
+ cci_write(bridge->regmap, MIPID02_DATA_SELECTION_CTRL,
+ bridge->r.data_selection_ctrl, &ret);
+ cci_write(bridge->regmap, MIPID02_PIX_WIDTH_CTRL,
+ bridge->r.pix_width_ctrl, &ret);
+ cci_write(bridge->regmap, MIPID02_PIX_WIDTH_CTRL_EMB,
+ bridge->r.pix_width_ctrl_emb, &ret);
if (ret)
goto error;
@@ -659,31 +543,43 @@ static int mipid02_s_stream(struct v4l2_subdev *sd, int enable)
struct i2c_client *client = bridge->i2c_client;
int ret = 0;
- dev_dbg(&client->dev, "%s : requested %d / current = %d", __func__,
- enable, bridge->streaming);
- mutex_lock(&bridge->lock);
-
- if (bridge->streaming == enable)
- goto out;
+ dev_dbg(&client->dev, "%s : requested %d\n", __func__, enable);
ret = enable ? mipid02_stream_enable(bridge) :
mipid02_stream_disable(bridge);
- if (!ret)
- bridge->streaming = enable;
-
-out:
- dev_dbg(&client->dev, "%s current now = %d / %d", __func__,
- bridge->streaming, ret);
- mutex_unlock(&bridge->lock);
+ if (ret)
+ dev_err(&client->dev, "failed to stream %s (%d)\n",
+ enable ? "enable" : "disable", ret);
return ret;
}
+static const struct v4l2_mbus_framefmt default_fmt = {
+ .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT,
+ .quantization = V4L2_QUANTIZATION_FULL_RANGE,
+ .xfer_func = V4L2_XFER_FUNC_DEFAULT,
+ .width = 640,
+ .height = 480,
+};
+
+static int mipid02_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ *v4l2_subdev_state_get_format(state, MIPID02_SINK_0) = default_fmt;
+ /* MIPID02_SINK_1 isn't supported yet */
+ *v4l2_subdev_state_get_format(state, MIPID02_SOURCE) = default_fmt;
+
+ return 0;
+}
+
static int mipid02_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
- struct mipid02_dev *bridge = to_mipid02_dev(sd);
+ struct v4l2_mbus_framefmt *sink_fmt;
int ret = 0;
switch (code->pad) {
@@ -694,10 +590,13 @@ static int mipid02_enum_mbus_code(struct v4l2_subdev *sd,
code->code = mipid02_supported_fmt_codes[code->index];
break;
case MIPID02_SOURCE:
- if (code->index == 0)
- code->code = serial_to_parallel_code(bridge->fmt.code);
- else
+ if (code->index == 0) {
+ sink_fmt = v4l2_subdev_state_get_format(sd_state,
+ MIPID02_SINK_0);
+ code->code = serial_to_parallel_code(sink_fmt->code);
+ } else {
ret = -EINVAL;
+ }
break;
default:
ret = -EINVAL;
@@ -706,122 +605,38 @@ static int mipid02_enum_mbus_code(struct v4l2_subdev *sd,
return ret;
}
-static int mipid02_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *format)
-{
- struct v4l2_mbus_framefmt *mbus_fmt = &format->format;
- struct mipid02_dev *bridge = to_mipid02_dev(sd);
- struct i2c_client *client = bridge->i2c_client;
- struct v4l2_mbus_framefmt *fmt;
-
- dev_dbg(&client->dev, "%s probe %d", __func__, format->pad);
-
- if (format->pad >= MIPID02_PAD_NB)
- return -EINVAL;
- /* second CSI-2 pad not yet supported */
- if (format->pad == MIPID02_SINK_1)
- return -EINVAL;
-
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt = v4l2_subdev_get_try_format(&bridge->sd, sd_state,
- format->pad);
- else
- fmt = &bridge->fmt;
-
- mutex_lock(&bridge->lock);
-
- *mbus_fmt = *fmt;
- /* code may need to be converted for source */
- if (format->pad == MIPID02_SOURCE)
- mbus_fmt->code = serial_to_parallel_code(mbus_fmt->code);
-
- mutex_unlock(&bridge->lock);
-
- return 0;
-}
-
-static void mipid02_set_fmt_source(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *format)
-{
- struct mipid02_dev *bridge = to_mipid02_dev(sd);
-
- /* source pad mirror sink pad */
- if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
- format->format = bridge->fmt;
- else
- format->format = *v4l2_subdev_get_try_format(sd, sd_state,
- MIPID02_SINK_0);
-
- /* but code may need to be converted */
- format->format.code = serial_to_parallel_code(format->format.code);
-
- /* only apply format for V4L2_SUBDEV_FORMAT_TRY case */
- if (format->which != V4L2_SUBDEV_FORMAT_TRY)
- return;
-
- *v4l2_subdev_get_try_format(sd, sd_state, MIPID02_SOURCE) =
- format->format;
-}
-
-static void mipid02_set_fmt_sink(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *format)
-{
- struct mipid02_dev *bridge = to_mipid02_dev(sd);
- struct v4l2_subdev_format source_fmt;
- struct v4l2_mbus_framefmt *fmt;
-
- format->format.code = get_fmt_code(format->format.code);
-
- if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
- else
- fmt = &bridge->fmt;
-
- *fmt = format->format;
-
- /*
- * Propagate the format change to the source pad, taking
- * care not to update the format pointer given back to user
- */
- source_fmt = *format;
- mipid02_set_fmt_source(sd, sd_state, &source_fmt);
-}
-
static int mipid02_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *format)
+ struct v4l2_subdev_format *fmt)
{
struct mipid02_dev *bridge = to_mipid02_dev(sd);
struct i2c_client *client = bridge->i2c_client;
- int ret = 0;
+ struct v4l2_mbus_framefmt *pad_fmt;
- dev_dbg(&client->dev, "%s for %d", __func__, format->pad);
+ dev_dbg(&client->dev, "%s for %d", __func__, fmt->pad);
- if (format->pad >= MIPID02_PAD_NB)
- return -EINVAL;
/* second CSI-2 pad not yet supported */
- if (format->pad == MIPID02_SINK_1)
+ if (fmt->pad == MIPID02_SINK_1)
return -EINVAL;
- mutex_lock(&bridge->lock);
+ pad_fmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
+ fmt->format.code = get_fmt_code(fmt->format.code);
- if (bridge->streaming) {
- ret = -EBUSY;
- goto error;
- }
+ /* code may need to be converted */
+ if (fmt->pad == MIPID02_SOURCE)
+ fmt->format.code = serial_to_parallel_code(fmt->format.code);
- if (format->pad == MIPID02_SOURCE)
- mipid02_set_fmt_source(sd, sd_state, format);
- else
- mipid02_set_fmt_sink(sd, sd_state, format);
+ *pad_fmt = fmt->format;
-error:
- mutex_unlock(&bridge->lock);
+ /* Propagate the format to the source pad in case of sink pad update */
+ if (fmt->pad == MIPID02_SINK_0) {
+ pad_fmt = v4l2_subdev_state_get_format(sd_state,
+ MIPID02_SOURCE);
+ *pad_fmt = fmt->format;
+ pad_fmt->code = serial_to_parallel_code(fmt->format.code);
+ }
- return ret;
+ return 0;
}
static const struct v4l2_subdev_video_ops mipid02_video_ops = {
@@ -830,7 +645,7 @@ static const struct v4l2_subdev_video_ops mipid02_video_ops = {
static const struct v4l2_subdev_pad_ops mipid02_pad_ops = {
.enum_mbus_code = mipid02_enum_mbus_code,
- .get_fmt = mipid02_get_fmt,
+ .get_fmt = v4l2_subdev_get_fmt,
.set_fmt = mipid02_set_fmt,
};
@@ -839,6 +654,10 @@ static const struct v4l2_subdev_ops mipid02_subdev_ops = {
.pad = &mipid02_pad_ops,
};
+static const struct v4l2_subdev_internal_ops mipid02_subdev_internal_ops = {
+ .init_state = mipid02_init_state,
+};
+
static const struct media_entity_operations mipid02_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -998,8 +817,6 @@ static int mipid02_probe(struct i2c_client *client)
if (!bridge)
return -ENOMEM;
- init_format(&bridge->fmt);
-
bridge->i2c_client = client;
v4l2_i2c_subdev_init(&bridge->sd, client, &mipid02_subdev_ops);
@@ -1031,9 +848,15 @@ static int mipid02_probe(struct i2c_client *client)
return ret;
}
- mutex_init(&bridge->lock);
+ /* Initialise the regmap for further cci access */
+ bridge->regmap = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(bridge->regmap))
+ return dev_err_probe(dev, PTR_ERR(bridge->regmap),
+ "failed to get cci regmap\n");
+
bridge->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
bridge->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+ bridge->sd.internal_ops = &mipid02_subdev_internal_ops;
bridge->sd.entity.ops = &mipid02_subdev_entity_ops;
bridge->pad[0].flags = MEDIA_PAD_FL_SINK;
bridge->pad[1].flags = MEDIA_PAD_FL_SINK;
@@ -1042,7 +865,13 @@ static int mipid02_probe(struct i2c_client *client)
bridge->pad);
if (ret) {
dev_err(&client->dev, "pads init failed %d", ret);
- goto mutex_cleanup;
+ return ret;
+ }
+
+ ret = v4l2_subdev_init_finalize(&bridge->sd);
+ if (ret < 0) {
+ dev_err(dev, "subdev init error: %d\n", ret);
+ goto entity_cleanup;
}
/* enable clock, power and reset device if available */
@@ -1086,8 +915,6 @@ power_off:
mipid02_set_power_off(bridge);
entity_cleanup:
media_entity_cleanup(&bridge->sd.entity);
-mutex_cleanup:
- mutex_destroy(&bridge->lock);
return ret;
}
@@ -1102,7 +929,6 @@ static void mipid02_remove(struct i2c_client *client)
v4l2_async_unregister_subdev(&bridge->sd);
mipid02_set_power_off(bridge);
media_entity_cleanup(&bridge->sd.entity);
- mutex_destroy(&bridge->lock);
}
static const struct of_device_id mipid02_dt_ids[] = {
diff --git a/drivers/media/i2c/st-vgxy61.c b/drivers/media/i2c/st-vgxy61.c
index 5dbfb04b31..e4d37a1977 100644
--- a/drivers/media/i2c/st-vgxy61.c
+++ b/drivers/media/i2c/st-vgxy61.c
@@ -21,6 +21,7 @@
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
@@ -780,8 +781,7 @@ static int vgxy61_get_fmt(struct v4l2_subdev *sd,
mutex_lock(&sensor->lock);
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
- fmt = v4l2_subdev_get_try_format(&sensor->sd, sd_state,
- format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
else
fmt = &sensor->fmt;
@@ -1289,7 +1289,7 @@ static int vgxy61_set_fmt(struct v4l2_subdev *sd,
goto out;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
*fmt = format->format;
} else if (sensor->current_mode != new_mode ||
sensor->fmt.code != format->format.code) {
@@ -1323,8 +1323,8 @@ out:
return ret;
}
-static int vgxy61_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int vgxy61_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
struct v4l2_subdev_format fmt = { 0 };
@@ -1403,6 +1403,7 @@ static int vgxy61_init_controls(struct vgxy61_dev *sensor)
const struct v4l2_ctrl_ops *ops = &vgxy61_ctrl_ops;
struct v4l2_ctrl_handler *hdl = &sensor->ctrl_handler;
const struct vgxy61_mode_info *cur_mode = sensor->current_mode;
+ struct v4l2_fwnode_device_properties props;
struct v4l2_ctrl *ctrl;
int ret;
@@ -1457,6 +1458,14 @@ static int vgxy61_init_controls(struct vgxy61_dev *sensor)
goto free_ctrls;
}
+ ret = v4l2_fwnode_device_parse(&sensor->i2c_client->dev, &props);
+ if (ret)
+ goto free_ctrls;
+
+ ret = v4l2_ctrl_new_fwnode_properties(hdl, ops, &props);
+ if (ret)
+ goto free_ctrls;
+
sensor->sd.ctrl_handler = hdl;
return 0;
@@ -1465,12 +1474,16 @@ free_ctrls:
return ret;
}
+static const struct v4l2_subdev_core_ops vgxy61_core_ops = {
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
static const struct v4l2_subdev_video_ops vgxy61_video_ops = {
.s_stream = vgxy61_s_stream,
};
static const struct v4l2_subdev_pad_ops vgxy61_pad_ops = {
- .init_cfg = vgxy61_init_cfg,
.enum_mbus_code = vgxy61_enum_mbus_code,
.get_fmt = vgxy61_get_fmt,
.set_fmt = vgxy61_set_fmt,
@@ -1479,10 +1492,15 @@ static const struct v4l2_subdev_pad_ops vgxy61_pad_ops = {
};
static const struct v4l2_subdev_ops vgxy61_subdev_ops = {
+ .core = &vgxy61_core_ops,
.video = &vgxy61_video_ops,
.pad = &vgxy61_pad_ops,
};
+static const struct v4l2_subdev_internal_ops vgxy61_internal_ops = {
+ .init_state = vgxy61_init_state,
+};
+
static const struct media_entity_operations vgxy61_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
@@ -1843,7 +1861,9 @@ static int vgxy61_probe(struct i2c_client *client)
device_property_read_bool(dev, "st,strobe-gpios-polarity");
v4l2_i2c_subdev_init(&sensor->sd, client, &vgxy61_subdev_ops);
- sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ sensor->sd.internal_ops = &vgxy61_internal_ops;
+ sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+ V4L2_SUBDEV_FL_HAS_EVENTS;
sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
sensor->sd.entity.ops = &vgxy61_subdev_entity_ops;
sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c
index ce612a47ba..106de4271d 100644
--- a/drivers/media/i2c/tc358746.c
+++ b/drivers/media/i2c/tc358746.c
@@ -427,7 +427,7 @@ static int tc358746_apply_misc_config(struct tc358746 *tc358746)
sink_state = v4l2_subdev_lock_and_get_active_state(sd);
- mbusfmt = v4l2_subdev_get_pad_format(sd, sink_state, TC358746_SINK);
+ mbusfmt = v4l2_subdev_state_get_format(sink_state, TC358746_SINK);
fmt = tc358746_get_format_by_code(TC358746_SINK, mbusfmt->code);
/* Self defined CSI user data type id's are not supported yet */
@@ -740,15 +740,15 @@ err_out:
return v4l2_subdev_call(src, video, s_stream, 0);
}
-static int tc358746_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+static int tc358746_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
{
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_pad_format(sd, state, TC358746_SINK);
+ fmt = v4l2_subdev_state_get_format(state, TC358746_SINK);
*fmt = tc358746_def_fmt;
- fmt = v4l2_subdev_get_pad_format(sd, state, TC358746_SOURCE);
+ fmt = v4l2_subdev_state_get_format(state, TC358746_SOURCE);
*fmt = tc358746_def_fmt;
fmt->code = tc358746_src_mbus_code(tc358746_def_fmt.code);
@@ -781,7 +781,7 @@ static int tc358746_set_fmt(struct v4l2_subdev *sd,
if (format->pad == TC358746_SOURCE)
return v4l2_subdev_get_fmt(sd, sd_state, format);
- sink_fmt = v4l2_subdev_get_pad_format(sd, sd_state, TC358746_SINK);
+ sink_fmt = v4l2_subdev_state_get_format(sd_state, TC358746_SINK);
fmt = tc358746_get_format_by_code(format->pad, format->format.code);
if (IS_ERR(fmt)) {
@@ -800,7 +800,7 @@ static int tc358746_set_fmt(struct v4l2_subdev *sd,
*sink_fmt = format->format;
- src_fmt = v4l2_subdev_get_pad_format(sd, sd_state, TC358746_SOURCE);
+ src_fmt = v4l2_subdev_state_get_format(sd_state, TC358746_SOURCE);
*src_fmt = *sink_fmt;
src_fmt->code = tc358746_src_mbus_code(sink_fmt->code);
@@ -905,7 +905,7 @@ tc358746_link_validate(struct v4l2_subdev *sd, struct media_link *link,
return err;
sink_state = v4l2_subdev_lock_and_get_active_state(sd);
- mbusfmt = v4l2_subdev_get_pad_format(sd, sink_state, TC358746_SINK);
+ mbusfmt = v4l2_subdev_state_get_format(sink_state, TC358746_SINK);
/* Check the FIFO settings */
fmt = tc358746_get_format_by_code(TC358746_SINK, mbusfmt->code);
@@ -1038,7 +1038,6 @@ static const struct v4l2_subdev_video_ops tc358746_video_ops = {
};
static const struct v4l2_subdev_pad_ops tc358746_pad_ops = {
- .init_cfg = tc358746_init_cfg,
.enum_mbus_code = tc358746_enum_mbus_code,
.set_fmt = tc358746_set_fmt,
.get_fmt = v4l2_subdev_get_fmt,
@@ -1052,6 +1051,10 @@ static const struct v4l2_subdev_ops tc358746_ops = {
.pad = &tc358746_pad_ops,
};
+static const struct v4l2_subdev_internal_ops tc358746_internal_ops = {
+ .init_state = tc358746_init_state,
+};
+
static const struct media_entity_operations tc358746_entity_ops = {
.get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
.link_validate = v4l2_subdev_link_validate,
@@ -1282,6 +1285,7 @@ tc358746_init_subdev(struct tc358746 *tc358746, struct i2c_client *client)
int err;
v4l2_i2c_subdev_init(sd, client, &tc358746_ops);
+ sd->internal_ops = &tc358746_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
sd->entity.ops = &tc358746_entity_ops;
diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c
index 325e991259..1ea703a990 100644
--- a/drivers/media/i2c/tda1997x.c
+++ b/drivers/media/i2c/tda1997x.c
@@ -1734,13 +1734,13 @@ static const struct v4l2_subdev_video_ops tda1997x_video_ops = {
* v4l2_subdev_pad_ops
*/
-static int tda1997x_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int tda1997x_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct tda1997x_state *state = to_state(sd);
struct v4l2_mbus_framefmt *mf;
- mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
+ mf = v4l2_subdev_state_get_format(sd_state, 0);
mf->code = state->mbus_codes[0];
return 0;
@@ -1792,7 +1792,7 @@ static int tda1997x_get_format(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
format->format.code = fmt->code;
} else
format->format.code = state->mbus_code;
@@ -1826,7 +1826,7 @@ static int tda1997x_set_format(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
- fmt = v4l2_subdev_get_try_format(sd, sd_state, format->pad);
+ fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
*fmt = format->format;
} else {
int ret = tda1997x_setup_format(state, format->format.code);
@@ -1925,7 +1925,6 @@ static int tda1997x_enum_dv_timings(struct v4l2_subdev *sd,
}
static const struct v4l2_subdev_pad_ops tda1997x_pad_ops = {
- .init_cfg = tda1997x_init_cfg,
.enum_mbus_code = tda1997x_enum_mbus_code,
.get_fmt = tda1997x_get_format,
.set_fmt = tda1997x_set_format,
@@ -2047,6 +2046,10 @@ static const struct v4l2_subdev_ops tda1997x_subdev_ops = {
.pad = &tda1997x_pad_ops,
};
+static const struct v4l2_subdev_internal_ops tda1997x_internal_ops = {
+ .init_state = tda1997x_init_state,
+};
+
/* -----------------------------------------------------------------------------
* v4l2_controls
*/
@@ -2588,6 +2591,7 @@ static int tda1997x_probe(struct i2c_client *client)
/* initialize subdev */
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &tda1997x_subdev_ops);
+ sd->internal_ops = &tda1997x_internal_ops;
snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
id->name, i2c_adapter_id(client->adapter),
client->addr);
diff --git a/drivers/media/i2c/thp7312.c b/drivers/media/i2c/thp7312.c
new file mode 100644
index 0000000000..2806887514
--- /dev/null
+++ b/drivers/media/i2c/thp7312.c
@@ -0,0 +1,2256 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 THine Electronics, Inc.
+ * Copyright (C) 2023 Ideas on Board Oy
+ */
+
+#include <asm/unaligned.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-cci.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#include <uapi/linux/thp7312.h>
+
+/* ISP registers */
+
+#define THP7312_REG_FIRMWARE_VERSION_1 CCI_REG8(0xf000)
+#define THP7312_REG_CAMERA_STATUS CCI_REG8(0xf001)
+#define THP7312_REG_FIRMWARE_VERSION_2 CCI_REG8(0xf005)
+#define THP7312_REG_SET_OUTPUT_ENABLE CCI_REG8(0xf008)
+#define THP7312_OUTPUT_ENABLE 0x01
+#define THP7312_OUTPUT_DISABLE 0x00
+#define THP7312_REG_SET_OUTPUT_COLOR_COMPRESSION CCI_REG8(0xf009)
+#define THP7312_REG_SET_OUTPUT_COLOR_UYVY 0x00
+#define THP7312_REG_SET_OUTPUT_COLOR_YUY2 0x04
+#define THP7312_REG_FLIP_MIRROR CCI_REG8(0xf00c)
+#define THP7312_REG_FLIP_MIRROR_FLIP BIT(0)
+#define THP7312_REG_FLIP_MIRROR_MIRROR BIT(1)
+#define THP7312_REG_VIDEO_IMAGE_SIZE CCI_REG8(0xf00d)
+#define THP7312_VIDEO_IMAGE_SIZE_640x360 0x52
+#define THP7312_VIDEO_IMAGE_SIZE_640x460 0x03
+#define THP7312_VIDEO_IMAGE_SIZE_1280x720 0x0a
+#define THP7312_VIDEO_IMAGE_SIZE_1920x1080 0x0b
+#define THP7312_VIDEO_IMAGE_SIZE_3840x2160 0x0d
+#define THP7312_VIDEO_IMAGE_SIZE_4160x3120 0x14
+#define THP7312_VIDEO_IMAGE_SIZE_2016x1512 0x20
+#define THP7312_VIDEO_IMAGE_SIZE_2048x1536 0x21
+#define THP7312_REG_VIDEO_FRAME_RATE_MODE CCI_REG8(0xf00f)
+#define THP7312_VIDEO_FRAME_RATE_MODE1 0x80
+#define THP7312_VIDEO_FRAME_RATE_MODE2 0x81
+#define THP7312_VIDEO_FRAME_RATE_MODE3 0x82
+#define THP7312_REG_SET_DRIVING_MODE CCI_REG8(0xf010)
+#define THP7312_REG_DRIVING_MODE_STATUS CCI_REG8(0xf011)
+#define THP7312_REG_JPEG_COMPRESSION_FACTOR CCI_REG8(0xf01b)
+#define THP7312_REG_AE_EXPOSURE_COMPENSATION CCI_REG8(0xf022)
+#define THP7312_REG_AE_FLICKER_MODE CCI_REG8(0xf023)
+#define THP7312_AE_FLICKER_MODE_50 0x00
+#define THP7312_AE_FLICKER_MODE_60 0x01
+#define THP7312_AE_FLICKER_MODE_DISABLE 0x80
+#define THP7312_REG_AE_FIX_FRAME_RATE CCI_REG8(0xf02e)
+#define THP7312_REG_MANUAL_WB_RED_GAIN CCI_REG8(0xf036)
+#define THP7312_REG_MANUAL_WB_BLUE_GAIN CCI_REG8(0xf037)
+#define THP7312_REG_WB_MODE CCI_REG8(0xf039)
+#define THP7312_WB_MODE_AUTO 0x00
+#define THP7312_WB_MODE_MANUAL 0x11
+#define THP7312_REG_MANUAL_FOCUS_POSITION CCI_REG16(0xf03c)
+#define THP7312_REG_AF_CONTROL CCI_REG8(0xf040)
+#define THP7312_REG_AF_CONTROL_AF 0x01
+#define THP7312_REG_AF_CONTROL_MANUAL 0x10
+#define THP7312_REG_AF_CONTROL_LOCK 0x80
+#define THP7312_REG_AF_SETTING CCI_REG8(0xf041)
+#define THP7312_REG_AF_SETTING_ONESHOT_CONTRAST 0x00
+#define THP7312_REG_AF_SETTING_ONESHOT_PDAF 0x40
+#define THP7312_REG_AF_SETTING_ONESHOT_HYBRID 0x80
+#define THP7312_REG_AF_SETTING_CONTINUOUS_CONTRAST 0x30
+#define THP7312_REG_AF_SETTING_CONTINUOUS_PDAF 0x70
+#define THP7312_REG_AF_SETTING_CONTINUOUS_HYBRID 0xf0
+#define THP7312_REG_AF_SUPPORT CCI_REG8(0xf043)
+#define THP7312_AF_SUPPORT_PDAF BIT(1)
+#define THP7312_AF_SUPPORT_CONTRAST BIT(0)
+#define THP7312_REG_SATURATION CCI_REG8(0xf052)
+#define THP7312_REG_SHARPNESS CCI_REG8(0xf053)
+#define THP7312_REG_BRIGHTNESS CCI_REG8(0xf056)
+#define THP7312_REG_CONTRAST CCI_REG8(0xf057)
+#define THP7312_REG_NOISE_REDUCTION CCI_REG8(0xf059)
+#define THP7312_REG_NOISE_REDUCTION_FIXED BIT(7)
+
+#define TH7312_REG_CUSTOM_MIPI_SET CCI_REG8(0xf0f6)
+#define TH7312_REG_CUSTOM_MIPI_STATUS CCI_REG8(0xf0f7)
+#define TH7312_REG_CUSTOM_MIPI_RD CCI_REG8(0xf0f8)
+#define TH7312_REG_CUSTOM_MIPI_TD CCI_REG8(0xf0f9)
+
+/*
+ * Firmware update registers. Those use a different address space than the
+ * normal operation ISP registers.
+ */
+
+#define THP7312_REG_FW_DRIVABILITY CCI_REG32(0xd65c)
+#define THP7312_REG_FW_DEST_BANK_ADDR CCI_REG32(0xff08)
+#define THP7312_REG_FW_VERIFY_RESULT CCI_REG8(0xff60)
+#define THP7312_REG_FW_RESET_FLASH CCI_REG8(0xff61)
+#define THP7312_REG_FW_MEMORY_IO_SETTING CCI_REG8(0xff62)
+#define THP7312_FW_MEMORY_IO_GPIO0 1
+#define THP7312_FW_MEMORY_IO_GPIO1 0
+#define THP7312_REG_FW_CRC_RESULT CCI_REG32(0xff64)
+#define THP7312_REG_FW_STATUS CCI_REG8(0xfffc)
+
+#define THP7312_FW_VERSION(major, minor) (((major) << 8) | (minor))
+#define THP7312_FW_VERSION_MAJOR(v) ((v) >> 8)
+#define THP7312_FW_VERSION_MINOR(v) ((v) & 0xff)
+
+enum thp7312_focus_method {
+ THP7312_FOCUS_METHOD_CONTRAST,
+ THP7312_FOCUS_METHOD_PDAF,
+ THP7312_FOCUS_METHOD_HYBRID,
+};
+
+/*
+ * enum thp7312_focus_state - State of the focus handler
+ *
+ * @THP7312_FOCUS_STATE_MANUAL: Manual focus, controlled through the
+ * V4L2_CID_FOCUS_ABSOLUTE control
+ * @THP7312_FOCUS_STATE_AUTO: Continuous auto-focus
+ * @THP7312_FOCUS_STATE_LOCKED: Lock the focus to a fixed position. This state
+ * is entered when switching from auto to manual mode.
+ * @THP7312_FOCUS_STATE_ONESHOT: One-shot auto-focus
+ *
+ * Valid transitions are as follow:
+ *
+ * digraph fsm {
+ * node [shape=circle];
+ *
+ * manual [label="MANUAL"];
+ * auto [label="AUTO"];
+ * locked [label="LOCKED"];
+ * oneshot [label="ONESHOT"];
+ *
+ * manual -> auto [label="FOCUS_AUTO <- true"]
+ * locked -> auto [label="FOCUS_AUTO <- true"]
+ * oneshot -> auto [label="FOCUS_AUTO <- true"]
+ * auto -> locked [label="FOCUS_AUTO <- false"]
+ *
+ * locked -> manual [label="FOCUS_ABSOLUTE <- *"]
+ * oneshot -> manual [label="FOCUS_ABSOLUTE <- *"]
+ *
+ * manual -> oneshot [label="FOCUS_START <- *"]
+ * locked -> oneshot [label="FOCUS_START <- *"]
+ * }
+ */
+enum thp7312_focus_state {
+ THP7312_FOCUS_STATE_MANUAL,
+ THP7312_FOCUS_STATE_AUTO,
+ THP7312_FOCUS_STATE_LOCKED,
+ THP7312_FOCUS_STATE_ONESHOT,
+};
+
+enum thp7312_boot_mode {
+ THP7312_BOOT_MODE_2WIRE_SLAVE = 0,
+ THP7312_BOOT_MODE_SPI_MASTER = 1,
+};
+
+struct thp7312_frame_rate {
+ u32 fps;
+ u32 link_freq;
+ u8 reg_frame_rate_mode;
+};
+
+struct thp7312_mode_info {
+ u32 width;
+ u32 height;
+ u8 reg_image_size;
+ const struct thp7312_frame_rate *rates;
+};
+
+static const u32 thp7312_colour_fmts[] = {
+ MEDIA_BUS_FMT_YUYV8_1X16,
+};
+
+/* regulator supplies */
+static const char * const thp7312_supply_name[] = {
+ "vddcore",
+ "vhtermrx",
+ "vddtx",
+ "vddhost",
+ "vddcmos",
+ "vddgpio-0",
+ "vddgpio-1",
+};
+
+static const struct thp7312_mode_info thp7312_mode_info_data[] = {
+ {
+ .width = 1920,
+ .height = 1080,
+ .reg_image_size = THP7312_VIDEO_IMAGE_SIZE_1920x1080,
+ .rates = (const struct thp7312_frame_rate[]) {
+ { 30, 300000000, 0x81 },
+ { 60, 387500000, 0x82 },
+ { 0 }
+ },
+ }, {
+ .width = 2048,
+ .height = 1536,
+ .reg_image_size = THP7312_VIDEO_IMAGE_SIZE_2048x1536,
+ .rates = (const struct thp7312_frame_rate[]) {
+ { 30, 300000000, 0x81 },
+ { 0 }
+ }
+ }, {
+ .width = 3840,
+ .height = 2160,
+ .reg_image_size = THP7312_VIDEO_IMAGE_SIZE_3840x2160,
+ .rates = (const struct thp7312_frame_rate[]) {
+ { 30, 600000000, 0x81 },
+ { 0 }
+ },
+ }, {
+ .width = 4160,
+ .height = 3120,
+ .reg_image_size = THP7312_VIDEO_IMAGE_SIZE_4160x3120,
+ .rates = (const struct thp7312_frame_rate[]) {
+ { 20, 600000000, 0x81 },
+ { 0 }
+ },
+ },
+};
+
+struct thp7312_device;
+
+struct thp7312_sensor_info {
+ const char *model;
+};
+
+struct thp7312_sensor {
+ const struct thp7312_sensor_info *info;
+ u8 lane_remap;
+};
+
+struct thp7312_device {
+ struct device *dev;
+ struct regmap *regmap;
+
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(thp7312_supply_name)];
+ struct clk *iclk;
+
+ u8 lane_remap;
+
+ struct thp7312_sensor sensors[1];
+
+ enum thp7312_boot_mode boot_mode;
+
+ struct v4l2_ctrl_handler ctrl_handler;
+ bool ctrls_applied;
+
+ s64 link_freq;
+
+ struct {
+ struct v4l2_ctrl *hflip;
+ struct v4l2_ctrl *vflip;
+ };
+
+ struct {
+ struct v4l2_ctrl *focus_auto;
+ struct v4l2_ctrl *focus_absolute;
+ struct v4l2_ctrl *focus_start;
+ struct v4l2_ctrl *focus_method;
+ };
+
+ enum thp7312_focus_state focus_state;
+
+ struct {
+ struct v4l2_ctrl *noise_reduction_auto;
+ struct v4l2_ctrl *noise_reduction_absolute;
+ };
+
+ /* Lock to protect fw_cancel */
+ struct mutex fw_lock;
+ struct fw_upload *fwl;
+ u8 *fw_write_buf;
+ bool fw_cancel;
+
+ u16 fw_version;
+};
+
+static const struct thp7312_sensor_info thp7312_sensor_info[] = {
+ {
+ .model = "sony,imx258",
+ },
+};
+
+static inline struct thp7312_device *to_thp7312_dev(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct thp7312_device, sd);
+}
+
+static const struct thp7312_mode_info *
+thp7312_find_mode(unsigned int width, unsigned int height, bool nearest)
+{
+ const struct thp7312_mode_info *mode;
+
+ mode = v4l2_find_nearest_size(thp7312_mode_info_data,
+ ARRAY_SIZE(thp7312_mode_info_data),
+ width, height, width, height);
+
+ if (!nearest && (mode->width != width || mode->height != height))
+ return NULL;
+
+ return mode;
+}
+
+static const struct thp7312_frame_rate *
+thp7312_find_rate(const struct thp7312_mode_info *mode, unsigned int fps,
+ bool nearest)
+{
+ const struct thp7312_frame_rate *best_rate = NULL;
+ const struct thp7312_frame_rate *rate;
+ unsigned int best_delta = UINT_MAX;
+
+ if (!mode)
+ return NULL;
+
+ for (rate = mode->rates; rate->fps && best_delta; ++rate) {
+ unsigned int delta = abs(rate->fps - fps);
+
+ if (delta <= best_delta) {
+ best_delta = delta;
+ best_rate = rate;
+ }
+ }
+
+ if (!nearest && best_delta)
+ return NULL;
+
+ return best_rate;
+}
+
+/* -----------------------------------------------------------------------------
+ * Device Access & Configuration
+ */
+
+#define thp7312_read_poll_timeout(dev, addr, val, cond, sleep_us, timeout_us) \
+({ \
+ int __ret, __err; \
+ __ret = read_poll_timeout(cci_read, __err, __err || (cond), sleep_us, \
+ timeout_us, false, (dev)->regmap, addr, \
+ &(val), NULL); \
+ __ret ? : __err; \
+})
+
+static int thp7312_map_data_lanes(u8 *lane_remap, const u8 *lanes, u8 num_lanes)
+{
+ u8 used_lanes = 0;
+ u8 val = 0;
+ unsigned int i;
+
+ /*
+ * The value that we write to the register is the index in the
+ * data-lanes array, so we need to do a conversion. Do this in the same
+ * pass as validating data-lanes.
+ */
+ for (i = 0; i < num_lanes; i++) {
+ if (lanes[i] < 1 || lanes[i] > 4)
+ return -EINVAL;
+
+ if (used_lanes & (BIT(lanes[i])))
+ return -EINVAL;
+
+ used_lanes |= BIT(lanes[i]);
+
+ /*
+ * data-lanes is 1-indexed while the field position in the
+ * register is 0-indexed.
+ */
+ val |= i << ((lanes[i] - 1) * 2);
+ }
+
+ *lane_remap = val;
+
+ return 0;
+}
+
+static int thp7312_set_mipi_lanes(struct thp7312_device *thp7312)
+{
+ struct device *dev = thp7312->dev;
+ int ret = 0;
+ u64 val;
+
+ cci_write(thp7312->regmap, TH7312_REG_CUSTOM_MIPI_RD,
+ thp7312->sensors[0].lane_remap, &ret);
+ cci_write(thp7312->regmap, TH7312_REG_CUSTOM_MIPI_TD,
+ thp7312->lane_remap, &ret);
+ cci_write(thp7312->regmap, TH7312_REG_CUSTOM_MIPI_SET, 1, &ret);
+
+ if (ret)
+ return ret;
+
+ ret = thp7312_read_poll_timeout(thp7312, TH7312_REG_CUSTOM_MIPI_STATUS,
+ val, val == 0x00, 100000, 2000000);
+ if (ret) {
+ dev_err(dev, "Failed to poll MIPI lane status: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int thp7312_change_mode(struct thp7312_device *thp7312,
+ const struct thp7312_mode_info *mode,
+ const struct thp7312_frame_rate *rate)
+{
+ struct device *dev = thp7312->dev;
+ u64 val = 0;
+ int ret;
+
+ ret = thp7312_read_poll_timeout(thp7312, THP7312_REG_CAMERA_STATUS, val,
+ val == 0x80, 20000, 200000);
+ if (ret < 0) {
+ dev_err(dev, "%s(): failed to poll ISP: %d\n", __func__, ret);
+ return ret;
+ }
+
+ cci_write(thp7312->regmap, THP7312_REG_VIDEO_IMAGE_SIZE,
+ mode->reg_image_size, &ret);
+ cci_write(thp7312->regmap, THP7312_REG_VIDEO_FRAME_RATE_MODE,
+ rate->reg_frame_rate_mode, &ret);
+ cci_write(thp7312->regmap, THP7312_REG_JPEG_COMPRESSION_FACTOR, 0x5e,
+ &ret);
+ cci_write(thp7312->regmap, THP7312_REG_SET_DRIVING_MODE, 0x01, &ret);
+
+ if (ret)
+ return ret;
+
+ ret = thp7312_read_poll_timeout(thp7312, THP7312_REG_DRIVING_MODE_STATUS,
+ val, val == 0x01, 20000, 100000);
+ if (ret < 0) {
+ dev_err(dev, "%s(): failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int thp7312_set_framefmt(struct thp7312_device *thp7312,
+ struct v4l2_mbus_framefmt *format)
+{
+ u8 val;
+
+ switch (format->code) {
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ /* YUV422, UYVY */
+ val = THP7312_REG_SET_OUTPUT_COLOR_UYVY;
+ break;
+ case MEDIA_BUS_FMT_YUYV8_1X16:
+ /* YUV422, YUYV */
+ val = THP7312_REG_SET_OUTPUT_COLOR_YUY2;
+ break;
+ default:
+ /* Should never happen */
+ return -EINVAL;
+ }
+
+ return cci_write(thp7312->regmap,
+ THP7312_REG_SET_OUTPUT_COLOR_COMPRESSION, val, NULL);
+}
+
+static int thp7312_init_mode(struct thp7312_device *thp7312,
+ struct v4l2_subdev_state *sd_state)
+{
+ const struct thp7312_mode_info *mode;
+ const struct thp7312_frame_rate *rate;
+ struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_fract *interval;
+ int ret;
+
+ /*
+ * TODO: The mode and rate should be cached in the subdev state, once
+ * support for extending states will be available.
+ */
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
+ interval = v4l2_subdev_state_get_interval(sd_state, 0);
+
+ mode = thp7312_find_mode(fmt->width, fmt->height, false);
+ rate = thp7312_find_rate(mode, interval->denominator, false);
+
+ if (WARN_ON(!mode || !rate))
+ return -EINVAL;
+
+ ret = thp7312_set_framefmt(thp7312, fmt);
+ if (ret)
+ return ret;
+
+ return thp7312_change_mode(thp7312, mode, rate);
+}
+
+static int thp7312_stream_enable(struct thp7312_device *thp7312, bool enable)
+{
+ return cci_write(thp7312->regmap, THP7312_REG_SET_OUTPUT_ENABLE,
+ enable ? THP7312_OUTPUT_ENABLE : THP7312_OUTPUT_DISABLE,
+ NULL);
+}
+
+static int thp7312_check_status_stream_mode(struct thp7312_device *thp7312)
+{
+ struct device *dev = thp7312->dev;
+ u64 status = 0;
+ int ret;
+
+ while (status != 0x80) {
+ ret = cci_read(thp7312->regmap, THP7312_REG_CAMERA_STATUS,
+ &status, NULL);
+ if (ret)
+ return ret;
+
+ if (status == 0x80) {
+ dev_dbg(dev, "Camera initialization done\n");
+ return 0;
+ }
+
+ if (status != 0x00) {
+ dev_err(dev, "Invalid camera status %llx\n", status);
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "Camera initializing...\n");
+ usleep_range(70000, 80000);
+ }
+
+ return 0;
+}
+
+static void thp7312_reset(struct thp7312_device *thp7312)
+{
+ unsigned long rate;
+
+ gpiod_set_value_cansleep(thp7312->reset_gpio, 1);
+
+ /*
+ * The minimum reset duration is 8 clock cycles, make it 10 to provide
+ * a safety margin.
+ */
+ rate = clk_get_rate(thp7312->iclk);
+ fsleep(DIV_ROUND_UP(10 * USEC_PER_SEC, rate));
+
+ gpiod_set_value_cansleep(thp7312->reset_gpio, 0);
+
+ /*
+ * TODO: The documentation states that the device needs 2ms to
+ * initialize after reset is deasserted. It then proceeds to load the
+ * firmware from the flash memory, which takes an unspecified amount of
+ * time. Check if this delay could be reduced.
+ */
+ fsleep(300000);
+}
+
+/* -----------------------------------------------------------------------------
+ * Power Management
+ */
+
+static void __thp7312_power_off(struct thp7312_device *thp7312)
+{
+ regulator_bulk_disable(ARRAY_SIZE(thp7312->supplies), thp7312->supplies);
+ clk_disable_unprepare(thp7312->iclk);
+}
+
+static void thp7312_power_off(struct thp7312_device *thp7312)
+{
+ __thp7312_power_off(thp7312);
+}
+
+static int __thp7312_power_on(struct thp7312_device *thp7312)
+{
+ struct device *dev = thp7312->dev;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(thp7312->supplies),
+ thp7312->supplies);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_prepare_enable(thp7312->iclk);
+ if (ret < 0) {
+ dev_err(dev, "clk prepare enable failed\n");
+ regulator_bulk_disable(ARRAY_SIZE(thp7312->supplies),
+ thp7312->supplies);
+ return ret;
+ }
+
+ /*
+ * We cannot assume that turning off and on again will reset, so do a
+ * software reset on power up.
+ */
+ thp7312_reset(thp7312);
+
+ return 0;
+}
+
+static int thp7312_power_on(struct thp7312_device *thp7312)
+{
+ int ret;
+
+ ret = __thp7312_power_on(thp7312);
+ if (ret < 0)
+ return ret;
+
+ ret = thp7312_check_status_stream_mode(thp7312);
+ if (ret < 0)
+ goto error;
+
+ ret = thp7312_set_mipi_lanes(thp7312);
+ if (ret)
+ goto error;
+
+ return 0;
+
+error:
+ thp7312_power_off(thp7312);
+ return ret;
+}
+
+static int __maybe_unused thp7312_pm_runtime_suspend(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct thp7312_device *thp7312 = to_thp7312_dev(sd);
+
+ thp7312_power_off(thp7312);
+
+ thp7312->ctrls_applied = false;
+
+ return 0;
+}
+
+static int __maybe_unused thp7312_pm_runtime_resume(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct thp7312_device *thp7312 = to_thp7312_dev(sd);
+
+ return thp7312_power_on(thp7312);
+}
+
+static const struct dev_pm_ops thp7312_pm_ops = {
+ SET_RUNTIME_PM_OPS(thp7312_pm_runtime_suspend,
+ thp7312_pm_runtime_resume, NULL)
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdev Operations
+ */
+
+static bool thp7312_find_bus_code(u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(thp7312_colour_fmts); ++i) {
+ if (thp7312_colour_fmts[i] == code)
+ return true;
+ }
+
+ return false;
+}
+
+static int thp7312_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index >= ARRAY_SIZE(thp7312_colour_fmts))
+ return -EINVAL;
+
+ code->code = thp7312_colour_fmts[code->index];
+
+ return 0;
+}
+
+static int thp7312_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (!thp7312_find_bus_code(fse->code))
+ return -EINVAL;
+
+ if (fse->index >= ARRAY_SIZE(thp7312_mode_info_data))
+ return -EINVAL;
+
+ fse->min_width = thp7312_mode_info_data[fse->index].width;
+ fse->max_width = fse->min_width;
+ fse->min_height = thp7312_mode_info_data[fse->index].height;
+ fse->max_height = fse->min_height;
+
+ return 0;
+}
+
+static int thp7312_enum_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval_enum *fie)
+{
+ const struct thp7312_frame_rate *rate;
+ const struct thp7312_mode_info *mode;
+ unsigned int index = fie->index;
+
+ if (!thp7312_find_bus_code(fie->code))
+ return -EINVAL;
+
+ mode = thp7312_find_mode(fie->width, fie->height, false);
+ if (!mode)
+ return -EINVAL;
+
+ for (rate = mode->rates; rate->fps; ++rate, --index) {
+ if (!index) {
+ fie->interval.numerator = 1;
+ fie->interval.denominator = rate->fps;
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int thp7312_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *format)
+{
+ struct thp7312_device *thp7312 = to_thp7312_dev(sd);
+ struct v4l2_mbus_framefmt *mbus_fmt = &format->format;
+ struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_fract *interval;
+ const struct thp7312_mode_info *mode;
+
+ if (!thp7312_find_bus_code(mbus_fmt->code))
+ mbus_fmt->code = thp7312_colour_fmts[0];
+
+ mode = thp7312_find_mode(mbus_fmt->width, mbus_fmt->height, true);
+
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
+
+ fmt->code = mbus_fmt->code;
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
+
+ *mbus_fmt = *fmt;
+
+ interval = v4l2_subdev_state_get_interval(sd_state, 0);
+ interval->numerator = 1;
+ interval->denominator = mode->rates[0].fps;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ thp7312->link_freq = mode->rates[0].link_freq;
+
+ return 0;
+}
+
+static int thp7312_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *fi)
+{
+ struct thp7312_device *thp7312 = to_thp7312_dev(sd);
+ const struct thp7312_mode_info *mode;
+ const struct thp7312_frame_rate *rate;
+ const struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_fract *interval;
+ unsigned int fps;
+
+ /* Avoid divisions by 0, pick the highest frame if the interval is 0. */
+ fps = fi->interval.numerator
+ ? DIV_ROUND_CLOSEST(fi->interval.denominator, fi->interval.numerator)
+ : UINT_MAX;
+
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
+ mode = thp7312_find_mode(fmt->width, fmt->height, false);
+ rate = thp7312_find_rate(mode, fps, true);
+
+ interval = v4l2_subdev_state_get_interval(sd_state, 0);
+ interval->numerator = 1;
+ interval->denominator = rate->fps;
+
+ if (fi->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ thp7312->link_freq = rate->link_freq;
+
+ fi->interval = *interval;
+
+ return 0;
+}
+
+static int thp7312_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct thp7312_device *thp7312 = to_thp7312_dev(sd);
+ struct v4l2_subdev_state *sd_state;
+ int ret;
+
+ sd_state = v4l2_subdev_lock_and_get_active_state(sd);
+
+ if (!enable) {
+ thp7312_stream_enable(thp7312, false);
+
+ pm_runtime_mark_last_busy(thp7312->dev);
+ pm_runtime_put_autosuspend(thp7312->dev);
+
+ v4l2_subdev_unlock_state(sd_state);
+
+ return 0;
+ }
+
+ ret = pm_runtime_resume_and_get(thp7312->dev);
+ if (ret)
+ goto finish_unlock;
+
+ ret = thp7312_init_mode(thp7312, sd_state);
+ if (ret)
+ goto finish_pm;
+
+ if (!thp7312->ctrls_applied) {
+ ret = __v4l2_ctrl_handler_setup(&thp7312->ctrl_handler);
+ if (ret)
+ goto finish_pm;
+
+ thp7312->ctrls_applied = true;
+ }
+
+ ret = thp7312_stream_enable(thp7312, true);
+ if (ret)
+ goto finish_pm;
+
+ goto finish_unlock;
+
+finish_pm:
+ pm_runtime_mark_last_busy(thp7312->dev);
+ pm_runtime_put_autosuspend(thp7312->dev);
+finish_unlock:
+ v4l2_subdev_unlock_state(sd_state);
+
+ return ret;
+}
+
+static int thp7312_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
+{
+ const struct thp7312_mode_info *default_mode = &thp7312_mode_info_data[0];
+ struct v4l2_mbus_framefmt *fmt;
+ struct v4l2_fract *interval;
+
+ fmt = v4l2_subdev_state_get_format(sd_state, 0);
+ interval = v4l2_subdev_state_get_interval(sd_state, 0);
+
+ /*
+ * default init sequence initialize thp7312 to
+ * YUV422 YUYV VGA@30fps
+ */
+ fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
+ fmt->width = default_mode->width;
+ fmt->height = default_mode->height;
+ fmt->field = V4L2_FIELD_NONE;
+
+ interval->numerator = 1;
+ interval->denominator = default_mode->rates[0].fps;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops thp7312_core_ops = {
+ .log_status = v4l2_ctrl_subdev_log_status,
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops thp7312_video_ops = {
+ .s_stream = thp7312_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops thp7312_pad_ops = {
+ .enum_mbus_code = thp7312_enum_mbus_code,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = thp7312_set_fmt,
+ .get_frame_interval = v4l2_subdev_get_frame_interval,
+ .set_frame_interval = thp7312_set_frame_interval,
+ .enum_frame_size = thp7312_enum_frame_size,
+ .enum_frame_interval = thp7312_enum_frame_interval,
+};
+
+static const struct v4l2_subdev_ops thp7312_subdev_ops = {
+ .core = &thp7312_core_ops,
+ .video = &thp7312_video_ops,
+ .pad = &thp7312_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops thp7312_internal_ops = {
+ .init_state = thp7312_init_state,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Control Operations
+ */
+
+static inline struct thp7312_device *to_thp7312_from_ctrl(struct v4l2_ctrl *ctrl)
+{
+ return container_of(ctrl->handler, struct thp7312_device, ctrl_handler);
+}
+
+/* 0: 3000cm, 18: 8cm */
+static const u16 thp7312_focus_values[] = {
+ 3000, 1000, 600, 450, 350,
+ 290, 240, 200, 170, 150,
+ 140, 130, 120, 110, 100,
+ 93, 87, 83, 80,
+};
+
+static int thp7312_set_focus(struct thp7312_device *thp7312)
+{
+ enum thp7312_focus_state new_state = thp7312->focus_state;
+ bool continuous;
+ u8 af_control;
+ u8 af_setting;
+ int ret = 0;
+
+ /* Start by programming the manual focus position if it has changed. */
+ if (thp7312->focus_absolute->is_new) {
+ unsigned int value;
+
+ value = thp7312_focus_values[thp7312->focus_absolute->val];
+
+ ret = cci_write(thp7312->regmap,
+ THP7312_REG_MANUAL_FOCUS_POSITION, value, NULL);
+ if (ret)
+ return ret;
+ }
+
+ /* Calculate the new focus state. */
+ switch (thp7312->focus_state) {
+ case THP7312_FOCUS_STATE_MANUAL:
+ default:
+ if (thp7312->focus_auto->val)
+ new_state = THP7312_FOCUS_STATE_AUTO;
+ else if (thp7312->focus_start->is_new)
+ new_state = THP7312_FOCUS_STATE_ONESHOT;
+ break;
+
+ case THP7312_FOCUS_STATE_AUTO:
+ if (!thp7312->focus_auto->val)
+ new_state = THP7312_FOCUS_STATE_LOCKED;
+ break;
+
+ case THP7312_FOCUS_STATE_LOCKED:
+ if (thp7312->focus_auto->val)
+ new_state = THP7312_FOCUS_STATE_AUTO;
+ else if (thp7312->focus_start->is_new)
+ new_state = THP7312_FOCUS_STATE_ONESHOT;
+ else if (thp7312->focus_absolute->is_new)
+ new_state = THP7312_FOCUS_STATE_MANUAL;
+ break;
+
+ case THP7312_FOCUS_STATE_ONESHOT:
+ if (thp7312->focus_auto->val)
+ new_state = THP7312_FOCUS_STATE_AUTO;
+ else if (thp7312->focus_start->is_new)
+ new_state = THP7312_FOCUS_STATE_ONESHOT;
+ else if (thp7312->focus_absolute->is_new)
+ new_state = THP7312_FOCUS_STATE_MANUAL;
+ break;
+ }
+
+ /*
+ * If neither the state nor the focus method has changed, and no new
+ * one-shot focus is requested, there's nothing new to program to the
+ * hardware.
+ */
+ if (thp7312->focus_state == new_state &&
+ !thp7312->focus_method->is_new && !thp7312->focus_start->is_new)
+ return 0;
+
+ continuous = new_state == THP7312_FOCUS_STATE_MANUAL ||
+ new_state == THP7312_FOCUS_STATE_ONESHOT;
+
+ switch (thp7312->focus_method->val) {
+ case THP7312_FOCUS_METHOD_CONTRAST:
+ default:
+ af_setting = continuous
+ ? THP7312_REG_AF_SETTING_CONTINUOUS_CONTRAST
+ : THP7312_REG_AF_SETTING_ONESHOT_CONTRAST;
+ break;
+ case THP7312_FOCUS_METHOD_PDAF:
+ af_setting = continuous
+ ? THP7312_REG_AF_SETTING_CONTINUOUS_PDAF
+ : THP7312_REG_AF_SETTING_ONESHOT_PDAF;
+ break;
+ case THP7312_FOCUS_METHOD_HYBRID:
+ af_setting = continuous
+ ? THP7312_REG_AF_SETTING_CONTINUOUS_HYBRID
+ : THP7312_REG_AF_SETTING_ONESHOT_HYBRID;
+ break;
+ }
+
+ switch (new_state) {
+ case THP7312_FOCUS_STATE_MANUAL:
+ default:
+ af_control = THP7312_REG_AF_CONTROL_MANUAL;
+ break;
+ case THP7312_FOCUS_STATE_AUTO:
+ case THP7312_FOCUS_STATE_ONESHOT:
+ af_control = THP7312_REG_AF_CONTROL_AF;
+ break;
+ case THP7312_FOCUS_STATE_LOCKED:
+ af_control = THP7312_REG_AF_CONTROL_LOCK;
+ break;
+ }
+
+ cci_write(thp7312->regmap, THP7312_REG_AF_SETTING, af_setting, &ret);
+
+ if (new_state == THP7312_FOCUS_STATE_MANUAL &&
+ (thp7312->focus_state == THP7312_FOCUS_STATE_AUTO ||
+ thp7312->focus_state == THP7312_FOCUS_STATE_ONESHOT)) {
+ /* When switching to manual state, lock AF first. */
+ cci_write(thp7312->regmap, THP7312_REG_AF_CONTROL,
+ THP7312_REG_AF_CONTROL_LOCK, &ret);
+ }
+
+ cci_write(thp7312->regmap, THP7312_REG_AF_CONTROL, af_control, &ret);
+
+ if (ret)
+ return ret;
+
+ thp7312->focus_state = new_state;
+
+ return 0;
+}
+
+static int thp7312_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct thp7312_device *thp7312 = to_thp7312_from_ctrl(ctrl);
+ int ret = 0;
+ u8 value;
+
+ if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+ return -EINVAL;
+
+ if (!pm_runtime_get_if_active(thp7312->dev, true))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ cci_write(thp7312->regmap, THP7312_REG_BRIGHTNESS,
+ ctrl->val + 10, &ret);
+ break;
+
+ case V4L2_CID_THP7312_LOW_LIGHT_COMPENSATION:
+ /* 0 = Auto adjust frame rate, 1 = Fix frame rate */
+ cci_write(thp7312->regmap, THP7312_REG_AE_FIX_FRAME_RATE,
+ ctrl->val ? 0 : 1, &ret);
+ break;
+
+ case V4L2_CID_FOCUS_AUTO:
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ case V4L2_CID_AUTO_FOCUS_START:
+ case V4L2_CID_THP7312_AUTO_FOCUS_METHOD:
+ ret = thp7312_set_focus(thp7312);
+ break;
+
+ case V4L2_CID_HFLIP:
+ case V4L2_CID_VFLIP:
+ value = (thp7312->hflip->val ? THP7312_REG_FLIP_MIRROR_MIRROR : 0)
+ | (thp7312->vflip->val ? THP7312_REG_FLIP_MIRROR_FLIP : 0);
+
+ cci_write(thp7312->regmap, THP7312_REG_FLIP_MIRROR, value, &ret);
+ break;
+
+ case V4L2_CID_THP7312_NOISE_REDUCTION_AUTO:
+ case V4L2_CID_THP7312_NOISE_REDUCTION_ABSOLUTE:
+ value = thp7312->noise_reduction_auto->val ? 0
+ : THP7312_REG_NOISE_REDUCTION_FIXED |
+ thp7312->noise_reduction_absolute->val;
+
+ cci_write(thp7312->regmap, THP7312_REG_NOISE_REDUCTION, value,
+ &ret);
+ break;
+
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ value = ctrl->val ? THP7312_WB_MODE_AUTO : THP7312_WB_MODE_MANUAL;
+
+ cci_write(thp7312->regmap, THP7312_REG_WB_MODE, value, &ret);
+ break;
+
+ case V4L2_CID_RED_BALANCE:
+ cci_write(thp7312->regmap, THP7312_REG_MANUAL_WB_RED_GAIN,
+ ctrl->val, &ret);
+ break;
+
+ case V4L2_CID_BLUE_BALANCE:
+ cci_write(thp7312->regmap, THP7312_REG_MANUAL_WB_BLUE_GAIN,
+ ctrl->val, &ret);
+ break;
+
+ case V4L2_CID_AUTO_EXPOSURE_BIAS:
+ cci_write(thp7312->regmap, THP7312_REG_AE_EXPOSURE_COMPENSATION,
+ ctrl->val, &ret);
+ break;
+
+ case V4L2_CID_POWER_LINE_FREQUENCY:
+ if (ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ) {
+ value = THP7312_AE_FLICKER_MODE_60;
+ } else if (ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_50HZ) {
+ value = THP7312_AE_FLICKER_MODE_50;
+ } else {
+ if (thp7312->fw_version == THP7312_FW_VERSION(40, 3)) {
+ /* THP7312_AE_FLICKER_MODE_DISABLE is not supported */
+ value = THP7312_AE_FLICKER_MODE_50;
+ } else {
+ value = THP7312_AE_FLICKER_MODE_DISABLE;
+ }
+ }
+
+ cci_write(thp7312->regmap, THP7312_REG_AE_FLICKER_MODE,
+ value, &ret);
+ break;
+
+ case V4L2_CID_SATURATION:
+ cci_write(thp7312->regmap, THP7312_REG_SATURATION,
+ ctrl->val, &ret);
+ break;
+
+ case V4L2_CID_CONTRAST:
+ cci_write(thp7312->regmap, THP7312_REG_CONTRAST,
+ ctrl->val, &ret);
+ break;
+
+ case V4L2_CID_SHARPNESS:
+ cci_write(thp7312->regmap, THP7312_REG_SHARPNESS,
+ ctrl->val, &ret);
+ break;
+
+ default:
+ break;
+ }
+
+ pm_runtime_mark_last_busy(thp7312->dev);
+ pm_runtime_put_autosuspend(thp7312->dev);
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops thp7312_ctrl_ops = {
+ .s_ctrl = thp7312_s_ctrl,
+};
+
+/*
+ * Refer to Documentation/userspace-api/media/drivers/thp7312.rst for details.
+ */
+static const struct v4l2_ctrl_config thp7312_ctrl_focus_method_cdaf = {
+ .ops = &thp7312_ctrl_ops,
+ .id = V4L2_CID_THP7312_AUTO_FOCUS_METHOD,
+ .name = "Auto-Focus Method",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = THP7312_FOCUS_METHOD_CONTRAST,
+ .def = THP7312_FOCUS_METHOD_CONTRAST,
+ .max = THP7312_FOCUS_METHOD_CONTRAST,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config thp7312_ctrl_focus_method_pdaf = {
+ .ops = &thp7312_ctrl_ops,
+ .id = V4L2_CID_THP7312_AUTO_FOCUS_METHOD,
+ .name = "Auto-Focus Method",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = THP7312_FOCUS_METHOD_CONTRAST,
+ .def = THP7312_FOCUS_METHOD_HYBRID,
+ .max = THP7312_FOCUS_METHOD_HYBRID,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config thp7312_v4l2_ctrls_custom[] = {
+ {
+ .ops = &thp7312_ctrl_ops,
+ .id = V4L2_CID_THP7312_LOW_LIGHT_COMPENSATION,
+ .name = "Low Light Compensation",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .def = 1,
+ .max = 1,
+ .step = 1,
+ }, {
+ .ops = &thp7312_ctrl_ops,
+ .id = V4L2_CID_THP7312_NOISE_REDUCTION_AUTO,
+ .name = "Noise Reduction Auto",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .def = 1,
+ .max = 1,
+ .step = 1,
+ }, {
+ .ops = &thp7312_ctrl_ops,
+ .id = V4L2_CID_THP7312_NOISE_REDUCTION_ABSOLUTE,
+ .name = "Noise Reduction Level",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .def = 0,
+ .max = 10,
+ .step = 1,
+ },
+};
+
+static const s64 exp_bias_qmenu[] = {
+ -2000, -1667, -1333, -1000, -667, -333, 0, 333, 667, 1000, 1333, 1667, 2000
+};
+
+static int thp7312_init_controls(struct thp7312_device *thp7312)
+{
+ struct v4l2_ctrl_handler *hdl = &thp7312->ctrl_handler;
+ struct device *dev = thp7312->dev;
+ struct v4l2_fwnode_device_properties props;
+ struct v4l2_ctrl *link_freq;
+ unsigned int num_controls;
+ unsigned int i;
+ u8 af_support;
+ int ret;
+
+ /*
+ * Check what auto-focus methods the connected sensor supports, if any.
+ * Firmwares before v90.03 didn't expose the AF_SUPPORT register,
+ * consider both CDAF and PDAF as supported in that case.
+ */
+ if (thp7312->fw_version >= THP7312_FW_VERSION(90, 3)) {
+ u64 val;
+
+ ret = cci_read(thp7312->regmap, THP7312_REG_AF_SUPPORT, &val,
+ NULL);
+ if (ret)
+ return ret;
+
+ af_support = val & (THP7312_AF_SUPPORT_PDAF |
+ THP7312_AF_SUPPORT_CONTRAST);
+ } else {
+ af_support = THP7312_AF_SUPPORT_PDAF
+ | THP7312_AF_SUPPORT_CONTRAST;
+ }
+
+ num_controls = 14 + ARRAY_SIZE(thp7312_v4l2_ctrls_custom)
+ + (af_support ? 4 : 0);
+
+ v4l2_ctrl_handler_init(hdl, num_controls);
+
+ if (af_support) {
+ const struct v4l2_ctrl_config *af_method;
+
+ af_method = af_support & THP7312_AF_SUPPORT_PDAF
+ ? &thp7312_ctrl_focus_method_pdaf
+ : &thp7312_ctrl_focus_method_cdaf;
+
+ thp7312->focus_state = THP7312_FOCUS_STATE_MANUAL;
+
+ thp7312->focus_auto =
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops,
+ V4L2_CID_FOCUS_AUTO,
+ 0, 1, 1, 1);
+ thp7312->focus_absolute =
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops,
+ V4L2_CID_FOCUS_ABSOLUTE,
+ 0, ARRAY_SIZE(thp7312_focus_values),
+ 1, 0);
+ thp7312->focus_method =
+ v4l2_ctrl_new_custom(hdl, af_method, NULL);
+ thp7312->focus_start =
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops,
+ V4L2_CID_AUTO_FOCUS_START,
+ 1, 1, 1, 1);
+
+ v4l2_ctrl_cluster(4, &thp7312->focus_auto);
+ }
+
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE,
+ 0, 1, 1, 1);
+ /* 32: 1x, 255: 7.95x */
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops, V4L2_CID_RED_BALANCE,
+ 32, 255, 1, 64);
+ /* 32: 1x, 255: 7.95x */
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops, V4L2_CID_BLUE_BALANCE,
+ 32, 255, 1, 50);
+
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops, V4L2_CID_BRIGHTNESS,
+ -10, 10, 1, 0);
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops, V4L2_CID_SATURATION,
+ 0, 31, 1, 10);
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops, V4L2_CID_CONTRAST,
+ 0, 20, 1, 10);
+ v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops, V4L2_CID_SHARPNESS,
+ 0, 31, 1, 8);
+
+ thp7312->hflip = v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ thp7312->vflip = v4l2_ctrl_new_std(hdl, &thp7312_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+ v4l2_ctrl_cluster(2, &thp7312->hflip);
+
+ v4l2_ctrl_new_int_menu(hdl, &thp7312_ctrl_ops,
+ V4L2_CID_AUTO_EXPOSURE_BIAS,
+ ARRAY_SIZE(exp_bias_qmenu) - 1,
+ ARRAY_SIZE(exp_bias_qmenu) / 2, exp_bias_qmenu);
+
+ v4l2_ctrl_new_std_menu(hdl, &thp7312_ctrl_ops,
+ V4L2_CID_POWER_LINE_FREQUENCY,
+ V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
+ V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
+
+ thp7312->link_freq = thp7312_mode_info_data[0].rates[0].link_freq;
+
+ link_freq = v4l2_ctrl_new_int_menu(hdl, &thp7312_ctrl_ops,
+ V4L2_CID_LINK_FREQ, 0, 0,
+ &thp7312->link_freq);
+
+ /* Set properties from fwnode (e.g. rotation, orientation). */
+ ret = v4l2_fwnode_device_parse(dev, &props);
+ if (ret) {
+ dev_err(dev, "Failed to parse fwnode: %d\n", ret);
+ goto error;
+ }
+
+ ret = v4l2_ctrl_new_fwnode_properties(hdl, &thp7312_ctrl_ops, &props);
+ if (ret) {
+ dev_err(dev, "Failed to create new v4l2 ctrl for fwnode properties: %d\n", ret);
+ goto error;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(thp7312_v4l2_ctrls_custom); i++) {
+ const struct v4l2_ctrl_config *ctrl_cfg =
+ &thp7312_v4l2_ctrls_custom[i];
+ struct v4l2_ctrl *ctrl;
+
+ ctrl = v4l2_ctrl_new_custom(hdl, ctrl_cfg, NULL);
+
+ if (ctrl_cfg->id == V4L2_CID_THP7312_NOISE_REDUCTION_AUTO)
+ thp7312->noise_reduction_auto = ctrl;
+ else if (ctrl_cfg->id == V4L2_CID_THP7312_NOISE_REDUCTION_ABSOLUTE)
+ thp7312->noise_reduction_absolute = ctrl;
+ }
+
+ v4l2_ctrl_cluster(2, &thp7312->noise_reduction_auto);
+
+ if (hdl->error) {
+ dev_err(dev, "v4l2_ctrl_handler error\n");
+ ret = hdl->error;
+ goto error;
+ }
+
+ link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ return ret;
+
+error:
+ v4l2_ctrl_handler_free(hdl);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Firmware Update
+ */
+
+/*
+ * The firmware data is made of 128kB of RAM firmware, followed by a
+ * variable-size "header". Both are stored in flash memory.
+ */
+#define THP7312_FW_RAM_SIZE (128 * 1024)
+#define THP7312_FW_MIN_SIZE (THP7312_FW_RAM_SIZE + 4)
+#define THP7312_FW_MAX_SIZE (THP7312_FW_RAM_SIZE + 64 * 1024)
+
+/*
+ * Data is first uploaded to the THP7312 128kB SRAM, and then written to flash.
+ * The SRAM is exposed over I2C as 32kB banks, and up to 4kB of data can be
+ * transferred in a single I2C write.
+ */
+#define THP7312_RAM_BANK_SIZE (32 * 1024)
+#define THP7312_FW_DOWNLOAD_UNIT (4 * 1024)
+
+#define THP7312_FLASH_MEMORY_ERASE_TIMEOUT 40
+
+#define THP7312_FLASH_MAX_REG_READ_SIZE 10
+#define THP7312_FLASH_MAX_REG_DATA_SIZE 10
+
+static const u8 thp7312_cmd_config_flash_mem_if[] = {
+ 0xd5, 0x18, 0x00, 0x00, 0x00, 0x80
+};
+
+static const u8 thp7312_cmd_write_to_reg[] = {
+ 0xd5, 0x0c, 0x80, 0x00, 0x00, 0x00
+};
+
+static const u8 thp7312_cmd_read_reg[] = {
+ 0xd5, 0x04
+};
+
+/*
+ * THP7312 Write data from RAM to Flash Memory
+ * Command ID FF700F
+ * Format: FF700F AA AA AA BB BB BB
+ * AA AA AA: destination start address
+ * BB BB BB: (write size - 1)
+ * Source address always starts from 0
+ */
+static const u8 thp7312_cmd_write_ram_to_flash[] = { 0xff, 0x70, 0x0f };
+
+/*
+ * THP7312 Calculate CRC command
+ * Command ID: FF70 09
+ * Format: FF70 09 AA AA AA BB BB BB
+ * AA AA AA: Start address of calculation
+ * BB BB BB: (calculate size - 1)
+ */
+static const u8 thp7312_cmd_calc_crc[] = { 0xff, 0x70, 0x09 };
+
+static const u8 thp7312_jedec_rdid[] = { SPINOR_OP_RDID, 0x00, 0x00, 0x00 };
+static const u8 thp7312_jedec_rdsr[] = { SPINOR_OP_RDSR, 0x00, 0x00, 0x00 };
+static const u8 thp7312_jedec_wen[] = { SPINOR_OP_WREN };
+
+static int thp7312_read_firmware_version(struct thp7312_device *thp7312)
+{
+ u64 val = 0;
+ int ret = 0;
+ u8 major;
+ u8 minor;
+
+ cci_read(thp7312->regmap, THP7312_REG_FIRMWARE_VERSION_1, &val, &ret);
+ major = val;
+
+ cci_read(thp7312->regmap, THP7312_REG_FIRMWARE_VERSION_2, &val, &ret);
+ minor = val;
+
+ thp7312->fw_version = THP7312_FW_VERSION(major, minor);
+ return ret;
+}
+
+static int thp7312_write_buf(struct thp7312_device *thp7312,
+ const u8 *write_buf, u16 write_size)
+{
+ struct i2c_client *client = to_i2c_client(thp7312->dev);
+ int ret;
+
+ ret = i2c_master_send(client, write_buf, write_size);
+ return ret >= 0 ? 0 : ret;
+}
+
+static int __thp7312_flash_reg_write(struct thp7312_device *thp7312,
+ const u8 *write_buf, u16 write_size)
+{
+ struct device *dev = thp7312->dev;
+ u8 temp_write_buf[THP7312_FLASH_MAX_REG_DATA_SIZE + 2];
+ int ret;
+
+ if (write_size > THP7312_FLASH_MAX_REG_DATA_SIZE) {
+ dev_err(dev, "%s: Write size error size = %d\n",
+ __func__, write_size);
+ return -EINVAL;
+ }
+
+ ret = thp7312_write_buf(thp7312, thp7312_cmd_config_flash_mem_if,
+ sizeof(thp7312_cmd_config_flash_mem_if));
+ if (ret < 0) {
+ dev_err(dev, "%s: Failed to config flash memory IF: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ temp_write_buf[0] = 0xd5;
+ temp_write_buf[1] = 0x00;
+ memcpy((temp_write_buf + 2), write_buf, write_size);
+ ret = thp7312_write_buf(thp7312, temp_write_buf, write_size + 2);
+ if (ret < 0)
+ return ret;
+
+ thp7312_write_buf(thp7312, thp7312_cmd_write_to_reg,
+ sizeof(thp7312_cmd_write_to_reg));
+
+ return 0;
+}
+
+static int __thp7312_flash_reg_read(struct thp7312_device *thp7312,
+ const u8 *write_buf, u16 write_size,
+ u8 *read_buf, u16 read_size)
+{
+ struct i2c_client *client = to_i2c_client(thp7312->dev);
+ struct i2c_msg msgs[2];
+ int ret;
+
+ ret = __thp7312_flash_reg_write(thp7312, write_buf, write_size);
+ if (ret)
+ return ret;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = 0;
+ msgs[0].len = sizeof(thp7312_cmd_read_reg),
+ msgs[0].buf = (u8 *)thp7312_cmd_read_reg;
+
+ msgs[1].addr = client->addr;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = read_size;
+ msgs[1].buf = read_buf;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ return ret >= 0 ? 0 : ret;
+}
+
+#define thp7312_flash_reg_write(thp7312, wrbuf) \
+ __thp7312_flash_reg_write(thp7312, wrbuf, sizeof(wrbuf))
+
+#define thp7312_flash_reg_read(thp7312, wrbuf, rdbuf) \
+ __thp7312_flash_reg_read(thp7312, wrbuf, sizeof(wrbuf), \
+ rdbuf, sizeof(rdbuf))
+
+static enum fw_upload_err thp7312_fw_prepare_config(struct thp7312_device *thp7312)
+{
+ struct device *dev = thp7312->dev;
+ int ret;
+
+ ret = cci_write(thp7312->regmap, THP7312_REG_FW_MEMORY_IO_SETTING,
+ THP7312_FW_MEMORY_IO_GPIO0, NULL);
+ if (ret) {
+ dev_err(dev, "Failed to set flash memory I/O\n");
+ return FW_UPLOAD_ERR_HW_ERROR;
+ }
+
+ /* Set max drivability. */
+ ret = cci_write(thp7312->regmap, THP7312_REG_FW_DRIVABILITY, 0x00777777,
+ NULL);
+ if (ret) {
+ dev_err(dev, "Failed to set drivability: %d\n", ret);
+ return FW_UPLOAD_ERR_HW_ERROR;
+ }
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err thp7312_fw_prepare_check(struct thp7312_device *thp7312)
+{
+ struct device *dev = thp7312->dev;
+ u8 read_buf[3] = { 0 };
+ int ret;
+
+ /* Get JEDEC ID */
+ ret = thp7312_flash_reg_read(thp7312, thp7312_jedec_rdid, read_buf);
+ if (ret) {
+ dev_err(dev, "Failed to get JEDEC ID: %d\n", ret);
+ return FW_UPLOAD_ERR_HW_ERROR;
+ }
+
+ dev_dbg(dev, "Flash Memory: JEDEC ID = 0x%x 0x%x 0x%x\n",
+ read_buf[0], read_buf[1], read_buf[2]);
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err thp7312_fw_prepare_reset(struct thp7312_device *thp7312)
+{
+ struct device *dev = thp7312->dev;
+ int ret;
+
+ ret = cci_write(thp7312->regmap, THP7312_REG_FW_RESET_FLASH, 0x81, NULL);
+ if (ret) {
+ dev_err(dev, "Failed to reset flash memory: %d\n", ret);
+ return FW_UPLOAD_ERR_HW_ERROR;
+ }
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+/* TODO: Erase only the amount of blocks necessary */
+static enum fw_upload_err thp7312_flash_erase(struct thp7312_device *thp7312)
+{
+ struct device *dev = thp7312->dev;
+ u8 read_buf[1] = { 0 };
+ unsigned int i;
+ u8 block;
+ int ret;
+
+ for (block = 0; block < 3; block++) {
+ const u8 jedec_se[] = { SPINOR_OP_SE, block, 0x00, 0x00 };
+
+ ret = thp7312_flash_reg_write(thp7312, thp7312_jedec_wen);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable flash for writing\n");
+ return FW_UPLOAD_ERR_RW_ERROR;
+ }
+
+ ret = thp7312_flash_reg_write(thp7312, jedec_se);
+ if (ret < 0) {
+ dev_err(dev, "Failed to erase flash sector\n");
+ return FW_UPLOAD_ERR_RW_ERROR;
+ }
+
+ for (i = 0; i < THP7312_FLASH_MEMORY_ERASE_TIMEOUT; i++) {
+ usleep_range(100000, 101000);
+ thp7312_flash_reg_read(thp7312, thp7312_jedec_rdsr,
+ read_buf);
+
+ /* Check Busy bit. Busy == 0x0 means erase complete. */
+ if (!(read_buf[0] & SR_WIP))
+ break;
+ }
+
+ if (i == THP7312_FLASH_MEMORY_ERASE_TIMEOUT)
+ return FW_UPLOAD_ERR_TIMEOUT;
+ }
+
+ thp7312_flash_reg_read(thp7312, thp7312_jedec_rdsr, read_buf);
+
+ /* Check WEL bit. */
+ if (read_buf[0] & SR_WEL)
+ return FW_UPLOAD_ERR_HW_ERROR;
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err
+thp7312_write_download_data_by_unit(struct thp7312_device *thp7312,
+ unsigned int addr, const u8 *data,
+ unsigned int size)
+{
+ struct device *dev = thp7312->dev;
+ u8 *write_buf = thp7312->fw_write_buf;
+ int ret;
+
+ dev_dbg(dev, "%s: addr = 0x%04x, data = 0x%p, size = %u\n",
+ __func__, addr, data, size);
+
+ write_buf[0] = (addr >> 8) & 0xff;
+ write_buf[1] = (addr >> 0) & 0xff;
+ memcpy(&write_buf[2], data, size);
+
+ /*
+ * THP7312 Firmware download to RAM
+ * Command ID (address to download): 0x0000 - 0x7fff
+ * Format:: 0000 XX XX XX ........ XX
+ */
+ ret = thp7312_write_buf(thp7312, write_buf, size + 2);
+ if (ret < 0)
+ dev_err(dev, "Unit transfer ERROR %s(): ret = %d\n", __func__, ret);
+
+ return ret >= 0 ? FW_UPLOAD_ERR_NONE : FW_UPLOAD_ERR_RW_ERROR;
+}
+
+static enum fw_upload_err thp7312_fw_load_to_ram(struct thp7312_device *thp7312,
+ const u8 *data, u32 size)
+{
+ struct device *dev = thp7312->dev;
+ enum fw_upload_err ret;
+ unsigned int num_banks;
+ unsigned int i, j;
+
+ num_banks = DIV_ROUND_UP(size, THP7312_RAM_BANK_SIZE);
+
+ dev_dbg(dev, "%s: loading %u bytes in SRAM (%u banks)\n", __func__,
+ size, num_banks);
+
+ for (i = 0; i < num_banks; i++) {
+ const u32 bank_addr = 0x10000000 | (i * THP7312_RAM_BANK_SIZE);
+ unsigned int bank_size;
+ unsigned int num_chunks;
+
+ ret = cci_write(thp7312->regmap, THP7312_REG_FW_DEST_BANK_ADDR,
+ bank_addr, NULL);
+ if (ret)
+ return FW_UPLOAD_ERR_HW_ERROR;
+
+ bank_size = min_t(u32, size, THP7312_RAM_BANK_SIZE);
+ num_chunks = DIV_ROUND_UP(bank_size, THP7312_FW_DOWNLOAD_UNIT);
+
+ dev_dbg(dev, "%s: loading %u bytes in SRAM bank %u (%u chunks)\n",
+ __func__, bank_size, i, num_chunks);
+
+ for (j = 0 ; j < num_chunks; j++) {
+ unsigned int chunk_addr;
+ unsigned int chunk_size;
+
+ chunk_addr = j * THP7312_FW_DOWNLOAD_UNIT;
+ chunk_size = min_t(u32, size, THP7312_FW_DOWNLOAD_UNIT);
+
+ ret = thp7312_write_download_data_by_unit(thp7312, chunk_addr,
+ data, chunk_size);
+ if (ret != FW_UPLOAD_ERR_NONE) {
+ dev_err(dev, "Unit transfer ERROR at bank transfer %s(): %d\n",
+ __func__, j);
+ return ret;
+ }
+
+ data += chunk_size;
+ size -= chunk_size;
+ }
+ }
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err thp7312_fw_write_to_flash(struct thp7312_device *thp7312,
+ u32 dest, u32 write_size)
+{
+ u8 command[sizeof(thp7312_cmd_write_ram_to_flash) + 6];
+ static const u32 cmd_size = sizeof(thp7312_cmd_write_ram_to_flash);
+ u64 val;
+ int ret;
+
+ memcpy(command, thp7312_cmd_write_ram_to_flash, cmd_size);
+
+ command[cmd_size] = (dest & 0xff0000) >> 16;
+ command[cmd_size + 1] = (dest & 0x00ff00) >> 8;
+ command[cmd_size + 2] = (dest & 0x0000ff);
+ command[cmd_size + 3] = ((write_size - 1) & 0xff0000) >> 16;
+ command[cmd_size + 4] = ((write_size - 1) & 0x00ff00) >> 8;
+ command[cmd_size + 5] = ((write_size - 1) & 0x0000ff);
+
+ ret = thp7312_write_buf(thp7312, command, sizeof(command));
+ if (ret < 0)
+ return FW_UPLOAD_ERR_RW_ERROR;
+
+ usleep_range(8000000, 8100000);
+
+ ret = cci_read(thp7312->regmap, THP7312_REG_FW_VERIFY_RESULT, &val,
+ NULL);
+ if (ret < 0)
+ return FW_UPLOAD_ERR_RW_ERROR;
+
+ return val ? FW_UPLOAD_ERR_HW_ERROR : FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err thp7312_fw_check_crc(struct thp7312_device *thp7312,
+ const u8 *fw_data, u32 fw_size)
+{
+ struct device *dev = thp7312->dev;
+ u16 header_size = fw_size - THP7312_FW_RAM_SIZE;
+ u8 command[sizeof(thp7312_cmd_calc_crc) + 6];
+ static const u32 cmd_size = sizeof(thp7312_cmd_calc_crc);
+ u32 size = THP7312_FW_RAM_SIZE - 4;
+ u32 fw_crc;
+ u64 crc;
+ int ret;
+
+ memcpy(command, thp7312_cmd_calc_crc, cmd_size);
+
+ command[cmd_size] = 0;
+ command[cmd_size + 1] = (header_size >> 8) & 0xff;
+ command[cmd_size + 2] = header_size & 0xff;
+
+ command[cmd_size + 3] = (size >> 16) & 0xff;
+ command[cmd_size + 4] = (size >> 8) & 0xff;
+ command[cmd_size + 5] = size & 0xff;
+
+ ret = thp7312_write_buf(thp7312, command, sizeof(command));
+ if (ret < 0)
+ return FW_UPLOAD_ERR_RW_ERROR;
+
+ usleep_range(2000000, 2100000);
+
+ fw_crc = get_unaligned_be32(&fw_data[fw_size - 4]);
+
+ ret = cci_read(thp7312->regmap, THP7312_REG_FW_CRC_RESULT, &crc, NULL);
+ if (ret < 0)
+ return FW_UPLOAD_ERR_RW_ERROR;
+
+ if (fw_crc != crc) {
+ dev_err(dev, "CRC mismatch: firmware 0x%08x, flash 0x%08llx\n",
+ fw_crc, crc);
+ return FW_UPLOAD_ERR_HW_ERROR;
+ }
+
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err thp7312_fw_prepare(struct fw_upload *fw_upload,
+ const u8 *data, u32 size)
+{
+ struct thp7312_device *thp7312 = fw_upload->dd_handle;
+ struct device *dev = thp7312->dev;
+ enum fw_upload_err ret;
+
+ mutex_lock(&thp7312->fw_lock);
+ thp7312->fw_cancel = false;
+ mutex_unlock(&thp7312->fw_lock);
+
+ if (size < THP7312_FW_MIN_SIZE || size > THP7312_FW_MAX_SIZE) {
+ dev_err(dev, "%s: Invalid firmware size %d; must be between %d and %d\n",
+ __func__, size, THP7312_FW_MIN_SIZE, THP7312_FW_MAX_SIZE);
+ return FW_UPLOAD_ERR_INVALID_SIZE;
+ }
+
+ ret = thp7312_fw_prepare_config(thp7312);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ ret = thp7312_fw_prepare_check(thp7312);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ ret = thp7312_fw_prepare_reset(thp7312);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ mutex_lock(&thp7312->fw_lock);
+ ret = thp7312->fw_cancel ? FW_UPLOAD_ERR_CANCELED : FW_UPLOAD_ERR_NONE;
+ mutex_unlock(&thp7312->fw_lock);
+
+ return ret;
+}
+
+static enum fw_upload_err thp7312_fw_write(struct fw_upload *fw_upload,
+ const u8 *data, u32 offset,
+ u32 size, u32 *written)
+{
+ struct thp7312_device *thp7312 = fw_upload->dd_handle;
+ struct device *dev = thp7312->dev;
+ u16 header_size = size - THP7312_FW_RAM_SIZE;
+ enum fw_upload_err ret;
+ bool cancel;
+
+ mutex_lock(&thp7312->fw_lock);
+ cancel = thp7312->fw_cancel;
+ mutex_unlock(&thp7312->fw_lock);
+
+ if (cancel)
+ return FW_UPLOAD_ERR_CANCELED;
+
+ ret = thp7312_flash_erase(thp7312);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ ret = thp7312_fw_load_to_ram(thp7312, data, THP7312_FW_RAM_SIZE);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ ret = thp7312_fw_write_to_flash(thp7312, 0, 0x1ffff);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ ret = thp7312_fw_load_to_ram(thp7312, data + THP7312_FW_RAM_SIZE, header_size);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ ret = thp7312_fw_write_to_flash(thp7312, 0x20000, header_size - 1);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ ret = thp7312_fw_check_crc(thp7312, data, size);
+ if (ret != FW_UPLOAD_ERR_NONE)
+ return ret;
+
+ dev_info(dev, "Successfully wrote firmware\n");
+
+ *written = size;
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err thp7312_fw_poll_complete(struct fw_upload *fw_upload)
+{
+ return FW_UPLOAD_ERR_NONE;
+}
+
+/*
+ * This may be called asynchronously with an on-going update. All other
+ * functions are called sequentially in a single thread. To avoid contention on
+ * register accesses, only update the cancel_request flag. Other functions will
+ * check this flag and handle the cancel request synchronously.
+ */
+static void thp7312_fw_cancel(struct fw_upload *fw_upload)
+{
+ struct thp7312_device *thp7312 = fw_upload->dd_handle;
+
+ mutex_lock(&thp7312->fw_lock);
+ thp7312->fw_cancel = true;
+ mutex_unlock(&thp7312->fw_lock);
+}
+
+static const struct fw_upload_ops thp7312_fw_upload_ops = {
+ .prepare = thp7312_fw_prepare,
+ .write = thp7312_fw_write,
+ .poll_complete = thp7312_fw_poll_complete,
+ .cancel = thp7312_fw_cancel,
+};
+
+static int thp7312_register_flash_mode(struct thp7312_device *thp7312)
+{
+ struct device *dev = thp7312->dev;
+ struct fw_upload *fwl;
+ u64 val;
+ int ret;
+
+ dev_info(dev, "booted in flash mode\n");
+
+ mutex_init(&thp7312->fw_lock);
+
+ thp7312->fw_write_buf = devm_kzalloc(dev, THP7312_FW_DOWNLOAD_UNIT + 2,
+ GFP_KERNEL);
+ if (!thp7312->fw_write_buf)
+ return -ENOMEM;
+
+ ret = __thp7312_power_on(thp7312);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to power on\n");
+
+ ret = cci_read(thp7312->regmap, THP7312_REG_FW_STATUS, &val, NULL);
+ if (ret) {
+ dev_err_probe(dev, ret, "Camera status read failed\n");
+ goto error;
+ }
+
+ fwl = firmware_upload_register(THIS_MODULE, dev, "thp7312-firmware",
+ &thp7312_fw_upload_ops, thp7312);
+ if (IS_ERR(fwl)) {
+ ret = PTR_ERR(fwl);
+ dev_err_probe(dev, ret, "Failed to register firmware upload\n");
+ goto error;
+ }
+
+ thp7312->fwl = fwl;
+ return 0;
+
+error:
+ __thp7312_power_off(thp7312);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Probe & Remove
+ */
+
+static int thp7312_get_regulators(struct thp7312_device *thp7312)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(thp7312->supplies); i++)
+ thp7312->supplies[i].supply = thp7312_supply_name[i];
+
+ return devm_regulator_bulk_get(thp7312->dev,
+ ARRAY_SIZE(thp7312->supplies),
+ thp7312->supplies);
+}
+
+static int thp7312_sensor_parse_dt(struct thp7312_device *thp7312,
+ struct fwnode_handle *node)
+{
+ struct device *dev = thp7312->dev;
+ struct thp7312_sensor *sensor;
+ const char *model;
+ u8 data_lanes[4];
+ u32 values[4];
+ unsigned int i;
+ u32 reg;
+ int ret;
+
+ /* Retrieve the sensor index from the reg property. */
+ ret = fwnode_property_read_u32(node, "reg", &reg);
+ if (ret < 0) {
+ dev_err(dev, "'reg' property missing in sensor node\n");
+ return -EINVAL;
+ }
+
+ if (reg >= ARRAY_SIZE(thp7312->sensors)) {
+ dev_err(dev, "Out-of-bounds 'reg' value %u\n", reg);
+ return -EINVAL;
+ }
+
+ sensor = &thp7312->sensors[reg];
+ if (sensor->info) {
+ dev_err(dev, "Duplicate entry for sensor %u\n", reg);
+ return -EINVAL;
+ }
+
+ ret = fwnode_property_read_string(node, "thine,model", &model);
+ if (ret < 0) {
+ dev_err(dev, "'thine,model' property missing in sensor node\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(thp7312_sensor_info); i++) {
+ const struct thp7312_sensor_info *info =
+ &thp7312_sensor_info[i];
+
+ if (!strcmp(info->model, model)) {
+ sensor->info = info;
+ break;
+ }
+ }
+
+ if (!sensor->info) {
+ dev_err(dev, "Unsupported sensor model %s\n", model);
+ return -EINVAL;
+ }
+
+ ret = fwnode_property_read_u32_array(node, "data-lanes", values,
+ ARRAY_SIZE(values));
+ if (ret < 0) {
+ dev_err(dev, "Failed to read property data-lanes: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(data_lanes); ++i)
+ data_lanes[i] = values[i];
+
+ ret = thp7312_map_data_lanes(&sensor->lane_remap, data_lanes,
+ ARRAY_SIZE(data_lanes));
+ if (ret) {
+ dev_err(dev, "Invalid sensor@%u data-lanes value\n", reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int thp7312_parse_dt(struct thp7312_device *thp7312)
+{
+ struct v4l2_fwnode_endpoint ep = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY,
+ };
+ struct device *dev = thp7312->dev;
+ struct fwnode_handle *endpoint;
+ struct fwnode_handle *sensors;
+ unsigned int num_sensors = 0;
+ struct fwnode_handle *node;
+ int ret;
+
+ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
+ if (!endpoint)
+ return dev_err_probe(dev, -EINVAL, "Endpoint node not found\n");
+
+ ret = v4l2_fwnode_endpoint_parse(endpoint, &ep);
+ fwnode_handle_put(endpoint);
+ if (ret)
+ return dev_err_probe(dev, ret, "Could not parse endpoint\n");
+
+ ret = thp7312_map_data_lanes(&thp7312->lane_remap,
+ ep.bus.mipi_csi2.data_lanes,
+ ep.bus.mipi_csi2.num_data_lanes);
+ if (ret) {
+ dev_err(dev, "Invalid data-lanes value\n");
+ return ret;
+ }
+
+ /*
+ * The thine,boot-mode property is optional and default to
+ * THP7312_BOOT_MODE_SPI_MASTER (1).
+ */
+ thp7312->boot_mode = THP7312_BOOT_MODE_SPI_MASTER;
+ ret = device_property_read_u32(dev, "thine,boot-mode",
+ &thp7312->boot_mode);
+ if (ret && ret != -EINVAL)
+ return dev_err_probe(dev, ret, "Property '%s' is invalid\n",
+ "thine,boot-mode");
+
+ if (thp7312->boot_mode != THP7312_BOOT_MODE_2WIRE_SLAVE &&
+ thp7312->boot_mode != THP7312_BOOT_MODE_SPI_MASTER)
+ return dev_err_probe(dev, -EINVAL, "Invalid '%s' value %u\n",
+ "thine,boot-mode", thp7312->boot_mode);
+
+ /* Sensors */
+ sensors = device_get_named_child_node(dev, "sensors");
+ if (!sensors) {
+ dev_err(dev, "'sensors' child node not found\n");
+ return -EINVAL;
+ }
+
+ fwnode_for_each_available_child_node(sensors, node) {
+ if (fwnode_name_eq(node, "sensor")) {
+ if (!thp7312_sensor_parse_dt(thp7312, node))
+ num_sensors++;
+ }
+ }
+
+ fwnode_handle_put(sensors);
+
+ if (!num_sensors) {
+ dev_err(dev, "No sensor found\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int thp7312_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct thp7312_device *thp7312;
+ int ret;
+
+ thp7312 = devm_kzalloc(dev, sizeof(*thp7312), GFP_KERNEL);
+ if (!thp7312)
+ return -ENOMEM;
+
+ thp7312->dev = dev;
+
+ thp7312->regmap = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(thp7312->regmap))
+ return dev_err_probe(dev, PTR_ERR(thp7312->regmap),
+ "Unable to initialize I2C\n");
+
+ ret = thp7312_parse_dt(thp7312);
+ if (ret < 0)
+ return ret;
+
+ ret = thp7312_get_regulators(thp7312);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+ thp7312->iclk = devm_clk_get(dev, NULL);
+ if (IS_ERR(thp7312->iclk))
+ return dev_err_probe(dev, PTR_ERR(thp7312->iclk),
+ "Failed to get iclk\n");
+
+ thp7312->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(thp7312->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(thp7312->reset_gpio),
+ "Failed to get reset gpio\n");
+
+ if (thp7312->boot_mode == THP7312_BOOT_MODE_2WIRE_SLAVE)
+ return thp7312_register_flash_mode(thp7312);
+
+ v4l2_i2c_subdev_init(&thp7312->sd, client, &thp7312_subdev_ops);
+ thp7312->sd.internal_ops = &thp7312_internal_ops;
+ thp7312->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+ thp7312->pad.flags = MEDIA_PAD_FL_SOURCE;
+ thp7312->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+ ret = media_entity_pads_init(&thp7312->sd.entity, 1, &thp7312->pad);
+ if (ret)
+ return ret;
+
+ /*
+ * Enable power management. The driver supports runtime PM, but needs to
+ * work when runtime PM is disabled in the kernel. To that end, power
+ * the device manually here.
+ */
+ ret = thp7312_power_on(thp7312);
+ if (ret)
+ goto err_entity_cleanup;
+
+ ret = thp7312_read_firmware_version(thp7312);
+ if (ret < 0) {
+ dev_err(dev, "Camera is not found\n");
+ goto err_power_off;
+ }
+
+ ret = thp7312_init_controls(thp7312);
+ if (ret) {
+ dev_err(dev, "Failed to initialize controls\n");
+ goto err_power_off;
+ }
+
+ thp7312->sd.ctrl_handler = &thp7312->ctrl_handler;
+ thp7312->sd.state_lock = thp7312->ctrl_handler.lock;
+
+ ret = v4l2_subdev_init_finalize(&thp7312->sd);
+ if (ret < 0) {
+ dev_err(dev, "Subdev active state initialization failed\n");
+ goto err_free_ctrls;
+ }
+
+ /*
+ * Enable runtime PM with autosuspend. As the device has been powered
+ * manually, mark it as active, and increase the usage count without
+ * resuming the device.
+ */
+ pm_runtime_set_active(dev);
+ pm_runtime_get_noresume(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(dev, 1000);
+ pm_runtime_use_autosuspend(dev);
+
+ ret = v4l2_async_register_subdev(&thp7312->sd);
+ if (ret < 0) {
+ dev_err(dev, "Subdev registration failed\n");
+ goto err_pm;
+ }
+
+ /*
+ * Decrease the PM usage count. The device will get suspended after the
+ * autosuspend delay, turning the power off.
+ */
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ dev_info(dev, "THP7312 firmware version %02u.%02u\n",
+ THP7312_FW_VERSION_MAJOR(thp7312->fw_version),
+ THP7312_FW_VERSION_MINOR(thp7312->fw_version));
+
+ return 0;
+
+err_pm:
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
+ v4l2_subdev_cleanup(&thp7312->sd);
+err_free_ctrls:
+ v4l2_ctrl_handler_free(&thp7312->ctrl_handler);
+err_power_off:
+ thp7312_power_off(thp7312);
+err_entity_cleanup:
+ media_entity_cleanup(&thp7312->sd.entity);
+ return ret;
+}
+
+static void thp7312_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct thp7312_device *thp7312 = to_thp7312_dev(sd);
+
+ if (thp7312->boot_mode == THP7312_BOOT_MODE_2WIRE_SLAVE) {
+ firmware_upload_unregister(thp7312->fwl);
+ __thp7312_power_off(thp7312);
+ return;
+ }
+
+ v4l2_async_unregister_subdev(&thp7312->sd);
+ v4l2_subdev_cleanup(&thp7312->sd);
+ media_entity_cleanup(&thp7312->sd.entity);
+ v4l2_ctrl_handler_free(&thp7312->ctrl_handler);
+
+ /*
+ * Disable runtime PM. In case runtime PM is disabled in the kernel,
+ * make sure to turn power off manually.
+ */
+ pm_runtime_disable(thp7312->dev);
+ if (!pm_runtime_status_suspended(thp7312->dev))
+ thp7312_power_off(thp7312);
+ pm_runtime_set_suspended(thp7312->dev);
+}
+
+static const struct of_device_id thp7312_dt_ids[] = {
+ { .compatible = "thine,thp7312" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, thp7312_dt_ids);
+
+static struct i2c_driver thp7312_i2c_driver = {
+ .driver = {
+ .name = "thp7312",
+ .pm = &thp7312_pm_ops,
+ .of_match_table = thp7312_dt_ids,
+ },
+ .probe = thp7312_probe,
+ .remove = thp7312_remove,
+};
+
+module_i2c_driver(thp7312_i2c_driver);
+
+MODULE_DESCRIPTION("THP7312 MIPI Camera Subdev Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index c37f605cb7..5a561e5bf6 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -738,20 +738,20 @@ static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl)
return err;
}
-/**
- * tvp514x_g_frame_interval() - V4L2 decoder interface handler
- * @sd: pointer to standard V4L2 sub-device structure
- * @ival: pointer to a v4l2_subdev_frame_interval structure
- *
- * Returns the decoder's video CAPTURE parameters.
- */
static int
-tvp514x_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+tvp514x_get_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct tvp514x_decoder *decoder = to_decoder(sd);
enum tvp514x_std current_std;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
/* get the current standard */
current_std = decoder->current_std;
@@ -762,22 +762,21 @@ tvp514x_g_frame_interval(struct v4l2_subdev *sd,
return 0;
}
-/**
- * tvp514x_s_frame_interval() - V4L2 decoder interface handler
- * @sd: pointer to standard V4L2 sub-device structure
- * @ival: pointer to a v4l2_subdev_frame_interval structure
- *
- * Configures the decoder to use the input parameters, if possible. If
- * not possible, returns the appropriate error code.
- */
static int
-tvp514x_s_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *ival)
+tvp514x_set_frame_interval(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_interval *ival)
{
struct tvp514x_decoder *decoder = to_decoder(sd);
struct v4l2_fract *timeperframe;
enum tvp514x_std current_std;
+ /*
+ * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
+ * subdev active state API.
+ */
+ if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
timeperframe = &ival->interval;
@@ -940,8 +939,6 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = {
.s_std = tvp514x_s_std,
.s_routing = tvp514x_s_routing,
.querystd = tvp514x_querystd,
- .g_frame_interval = tvp514x_g_frame_interval,
- .s_frame_interval = tvp514x_s_frame_interval,
.s_stream = tvp514x_s_stream,
};
@@ -949,6 +946,8 @@ static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = {
.enum_mbus_code = tvp514x_enum_mbus_code,
.get_fmt = tvp514x_get_pad_format,
.set_fmt = tvp514x_set_pad_format,
+ .get_frame_interval = tvp514x_get_frame_interval,
+ .set_frame_interval = tvp514x_set_frame_interval,
};
static const struct v4l2_subdev_ops tvp514x_ops = {
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index e543b3f7a4..9fc586cfdc 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1035,7 +1035,7 @@ tvp5150_get_pad_crop(struct tvp5150 *decoder,
return &decoder->rect;
case V4L2_SUBDEV_FORMAT_TRY:
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
- return v4l2_subdev_get_try_crop(&decoder->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
#else
return ERR_PTR(-EINVAL);
#endif
@@ -1209,8 +1209,8 @@ static int tvp5150_get_mbus_config(struct v4l2_subdev *sd,
/****************************************************************************
V4L2 subdev pad ops
****************************************************************************/
-static int tvp5150_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int tvp5150_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct tvp5150 *decoder = to_tvp5150(sd);
v4l2_std_id std;
@@ -1722,7 +1722,6 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
};
static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
- .init_cfg = tvp5150_init_cfg,
.enum_mbus_code = tvp5150_enum_mbus_code,
.enum_frame_size = tvp5150_enum_frame_size,
.set_fmt = tvp5150_fill_fmt,
@@ -1741,6 +1740,7 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
};
static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
+ .init_state = tvp5150_init_state,
.registered = tvp5150_registered,
.open = tvp5150_open,
.close = tvp5150_close,
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index a2d7bc7998..30831b4b56 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -791,7 +791,7 @@ static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = {
/*
* tvp7002_enum_mbus_code() - Enum supported digital video format on pad
* @sd: pointer to standard V4L2 sub-device structure
- * @cfg: pad configuration
+ * @sd_state: V4L2 subdev state
* @code: pointer to subdev enum mbus code struct
*
* Enumerate supported digital video formats for pad.
@@ -813,7 +813,7 @@ tvp7002_enum_mbus_code(struct v4l2_subdev *sd,
/*
* tvp7002_get_pad_format() - get video format on pad
* @sd: pointer to standard V4L2 sub-device structure
- * @cfg: pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to subdev format struct
*
* get video format for pad.
@@ -837,7 +837,7 @@ tvp7002_get_pad_format(struct v4l2_subdev *sd,
/*
* tvp7002_set_pad_format() - set video format on pad
* @sd: pointer to standard V4L2 sub-device structure
- * @cfg: pad configuration
+ * @sd_state: V4L2 subdev state
* @fmt: pointer to subdev format struct
*
* set video format for pad.
diff --git a/drivers/media/i2c/tw9900.c b/drivers/media/i2c/tw9900.c
new file mode 100644
index 0000000000..bc7623ec46
--- /dev/null
+++ b/drivers/media/i2c/tw9900.c
@@ -0,0 +1,781 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the Techwell TW9900 multi-standard video decoder.
+ *
+ * Copyright (C) 2018 Fuzhou Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2020 Maxime Chevallier <maxime.chevallier@bootlin.com>
+ * Copyright (C) 2023 Mehdi Djait <mehdi.djait@bootlin.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <media/media-entity.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-subdev.h>
+
+#define TW9900_REG_CHIP_ID 0x00
+#define TW9900_REG_CHIP_STATUS 0x01
+#define TW9900_REG_CHIP_STATUS_VDLOSS BIT(7)
+#define TW9900_REG_CHIP_STATUS_HLOCK BIT(6)
+#define TW9900_REG_OUT_FMT_CTL 0x03
+#define TW9900_REG_OUT_FMT_CTL_STANDBY 0xA7
+#define TW9900_REG_OUT_FMT_CTL_STREAMING 0xA0
+#define TW9900_REG_CKHY_HSDLY 0x04
+#define TW9900_REG_OUT_CTRL_I 0x05
+#define TW9900_REG_ANALOG_CTL 0x06
+#define TW9900_REG_CROP_HI 0x07
+#define TW9900_REG_VDELAY_LO 0x08
+#define TW9900_REG_VACTIVE_LO 0x09
+#define TW9900_REG_HACTIVE_LO 0x0B
+#define TW9900_REG_CNTRL1 0x0C
+#define TW9900_REG_BRIGHT_CTL 0x10
+#define TW9900_REG_CONTRAST_CTL 0x11
+#define TW9900_REG_VBI_CNTL 0x19
+#define TW9900_REG_ANAL_CTL_II 0x1A
+#define TW9900_REG_OUT_CTRL_II 0x1B
+#define TW9900_REG_STD 0x1C
+#define TW9900_REG_STD_AUTO_PROGRESS BIT(7)
+#define TW9900_STDNOW_MASK GENMASK(6, 4)
+#define TW9900_REG_STDR 0x1D
+#define TW9900_REG_MISSCNT 0x26
+#define TW9900_REG_MISC_CTL_II 0x2F
+#define TW9900_REG_VVBI 0x55
+
+#define TW9900_CHIP_ID 0x00
+#define TW9900_STD_NTSC_M 0
+#define TW9900_STD_PAL_BDGHI 1
+#define TW9900_STD_AUTO 7
+
+#define TW9900_VIDEO_POLL_TRIES 20
+
+struct regval {
+ u8 addr;
+ u8 val;
+};
+
+struct tw9900_mode {
+ u32 width;
+ u32 height;
+ u32 std;
+ const struct regval *reg_list;
+ int n_regs;
+};
+
+struct tw9900 {
+ struct i2c_client *client;
+ struct gpio_desc *reset_gpio;
+ struct regulator *regulator;
+
+ struct v4l2_subdev subdev;
+ struct v4l2_ctrl_handler hdl;
+ struct media_pad pad;
+
+ /* Serialize access to hardware and global state. */
+ struct mutex mutex;
+
+ bool streaming;
+ const struct tw9900_mode *cur_mode;
+};
+
+#define to_tw9900(sd) container_of(sd, struct tw9900, subdev)
+
+static const struct regval tw9900_init_regs[] = {
+ { TW9900_REG_MISC_CTL_II, 0xE6 },
+ { TW9900_REG_MISSCNT, 0x24 },
+ { TW9900_REG_OUT_FMT_CTL, 0xA7 },
+ { TW9900_REG_ANAL_CTL_II, 0x0A },
+ { TW9900_REG_VDELAY_LO, 0x19 },
+ { TW9900_REG_STD, 0x00 },
+ { TW9900_REG_VACTIVE_LO, 0xF0 },
+ { TW9900_REG_STD, 0x07 },
+ { TW9900_REG_CKHY_HSDLY, 0x00 },
+ { TW9900_REG_ANALOG_CTL, 0x80 },
+ { TW9900_REG_CNTRL1, 0xDC },
+ { TW9900_REG_OUT_CTRL_I, 0x98 },
+};
+
+static const struct regval tw9900_pal_regs[] = {
+ { TW9900_REG_STD, 0x01 },
+};
+
+static const struct regval tw9900_ntsc_regs[] = {
+ { TW9900_REG_OUT_FMT_CTL, 0xA4 },
+ { TW9900_REG_VDELAY_LO, 0x12 },
+ { TW9900_REG_VACTIVE_LO, 0xF0 },
+ { TW9900_REG_CROP_HI, 0x02 },
+ { TW9900_REG_HACTIVE_LO, 0xD0 },
+ { TW9900_REG_VBI_CNTL, 0x01 },
+ { TW9900_REG_STD, 0x00 },
+};
+
+static const struct tw9900_mode supported_modes[] = {
+ {
+ .width = 720,
+ .height = 480,
+ .std = V4L2_STD_NTSC,
+ .reg_list = tw9900_ntsc_regs,
+ .n_regs = ARRAY_SIZE(tw9900_ntsc_regs),
+ },
+ {
+ .width = 720,
+ .height = 576,
+ .std = V4L2_STD_PAL,
+ .reg_list = tw9900_pal_regs,
+ .n_regs = ARRAY_SIZE(tw9900_pal_regs),
+ },
+};
+
+static int tw9900_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, reg, val);
+ if (ret < 0)
+ dev_err(&client->dev, "write reg error: %d\n", ret);
+
+ return ret;
+}
+
+static int tw9900_write_array(struct i2c_client *client,
+ const struct regval *regs, int n_regs)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < n_regs; i++) {
+ ret = tw9900_write_reg(client, regs[i].addr, regs[i].val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tw9900_read_reg(struct i2c_client *client, u8 reg)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0)
+ dev_err(&client->dev, "read reg error: %d\n", ret);
+
+ return ret;
+}
+
+static void tw9900_fill_fmt(const struct tw9900_mode *mode,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
+ fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SMPTE170M);
+ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SMPTE170M);
+}
+
+static int tw9900_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct tw9900 *tw9900 = to_tw9900(sd);
+ struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format;
+
+ mutex_lock(&tw9900->mutex);
+ tw9900_fill_fmt(tw9900->cur_mode, mbus_fmt);
+ mutex_unlock(&tw9900->mutex);
+
+ return 0;
+}
+
+static int tw9900_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct tw9900 *tw9900 = to_tw9900(sd);
+ struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format;
+
+ mutex_lock(&tw9900->mutex);
+
+ if (tw9900->streaming) {
+ mutex_unlock(&tw9900->mutex);
+ return -EBUSY;
+ }
+
+ tw9900_fill_fmt(tw9900->cur_mode, mbus_fmt);
+
+ mutex_unlock(&tw9900->mutex);
+
+ return 0;
+}
+
+static int tw9900_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
+
+ return 0;
+}
+
+static int tw9900_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct tw9900 *tw9900 = container_of(ctrl->handler, struct tw9900, hdl);
+ int ret;
+
+ if (pm_runtime_suspended(&tw9900->client->dev))
+ return 0;
+
+ /* v4l2_ctrl_lock() locks tw9900->mutex. */
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ret = tw9900_write_reg(tw9900->client, TW9900_REG_BRIGHT_CTL,
+ (u8)ctrl->val);
+ break;
+ case V4L2_CID_CONTRAST:
+ ret = tw9900_write_reg(tw9900->client, TW9900_REG_CONTRAST_CTL,
+ (u8)ctrl->val);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int tw9900_s_stream(struct v4l2_subdev *sd, int on)
+{
+ struct tw9900 *tw9900 = to_tw9900(sd);
+ struct i2c_client *client = tw9900->client;
+ int ret;
+
+ mutex_lock(&tw9900->mutex);
+
+ if (tw9900->streaming == on) {
+ mutex_unlock(&tw9900->mutex);
+ return 0;
+ }
+
+ mutex_unlock(&tw9900->mutex);
+
+ if (on) {
+ ret = pm_runtime_resume_and_get(&client->dev);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&tw9900->mutex);
+
+ ret = __v4l2_ctrl_handler_setup(sd->ctrl_handler);
+ if (ret)
+ goto err_unlock;
+
+ ret = tw9900_write_array(tw9900->client,
+ tw9900->cur_mode->reg_list,
+ tw9900->cur_mode->n_regs);
+ if (ret)
+ goto err_unlock;
+
+ ret = tw9900_write_reg(client, TW9900_REG_OUT_FMT_CTL,
+ TW9900_REG_OUT_FMT_CTL_STREAMING);
+ if (ret)
+ goto err_unlock;
+
+ tw9900->streaming = on;
+
+ mutex_unlock(&tw9900->mutex);
+
+ } else {
+ mutex_lock(&tw9900->mutex);
+
+ ret = tw9900_write_reg(client, TW9900_REG_OUT_FMT_CTL,
+ TW9900_REG_OUT_FMT_CTL_STANDBY);
+ if (ret)
+ goto err_unlock;
+
+ tw9900->streaming = on;
+
+ mutex_unlock(&tw9900->mutex);
+
+ pm_runtime_put(&client->dev);
+ }
+
+ return 0;
+
+err_unlock:
+ mutex_unlock(&tw9900->mutex);
+ pm_runtime_put(&client->dev);
+
+ return ret;
+}
+
+static int tw9900_subscribe_event(struct v4l2_subdev *sd,
+ struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ switch (sub->type) {
+ case V4L2_EVENT_SOURCE_CHANGE:
+ return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
+ case V4L2_EVENT_CTRL:
+ return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int tw9900_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+ struct tw9900 *tw9900 = to_tw9900(sd);
+ const struct tw9900_mode *mode = NULL;
+ int i;
+
+ if (!(std & (V4L2_STD_NTSC | V4L2_STD_PAL)))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(supported_modes); i++)
+ if (supported_modes[i].std & std)
+ mode = &supported_modes[i];
+ if (!mode)
+ return -EINVAL;
+
+ mutex_lock(&tw9900->mutex);
+ tw9900->cur_mode = mode;
+ mutex_unlock(&tw9900->mutex);
+
+ return 0;
+}
+
+static int tw9900_get_stream_std(struct tw9900 *tw9900,
+ v4l2_std_id *std)
+{
+ int cur_std, ret;
+
+ lockdep_assert_held(&tw9900->mutex);
+
+ ret = tw9900_read_reg(tw9900->client, TW9900_REG_STD);
+ if (ret < 0) {
+ *std = V4L2_STD_UNKNOWN;
+ return ret;
+ }
+
+ cur_std = FIELD_GET(TW9900_STDNOW_MASK, ret);
+ switch (cur_std) {
+ case TW9900_STD_NTSC_M:
+ *std = V4L2_STD_NTSC;
+ break;
+ case TW9900_STD_PAL_BDGHI:
+ *std = V4L2_STD_PAL;
+ break;
+ case TW9900_STD_AUTO:
+ *std = V4L2_STD_UNKNOWN;
+ break;
+ default:
+ *std = V4L2_STD_UNKNOWN;
+ break;
+ }
+
+ return 0;
+}
+
+static int tw9900_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ struct tw9900 *tw9900 = to_tw9900(sd);
+
+ mutex_lock(&tw9900->mutex);
+ *std = tw9900->cur_mode->std;
+ mutex_unlock(&tw9900->mutex);
+
+ return 0;
+}
+
+static int tw9900_start_autodetect(struct tw9900 *tw9900)
+{
+ int ret;
+
+ lockdep_assert_held(&tw9900->mutex);
+
+ ret = tw9900_write_reg(tw9900->client, TW9900_REG_STDR,
+ BIT(TW9900_STD_NTSC_M) |
+ BIT(TW9900_STD_PAL_BDGHI));
+ if (ret)
+ return ret;
+
+ ret = tw9900_write_reg(tw9900->client, TW9900_REG_STD,
+ TW9900_STD_AUTO);
+ if (ret)
+ return ret;
+
+ ret = tw9900_write_reg(tw9900->client, TW9900_REG_STDR,
+ BIT(TW9900_STD_NTSC_M) |
+ BIT(TW9900_STD_PAL_BDGHI) |
+ BIT(TW9900_STD_AUTO));
+ if (ret)
+ return ret;
+
+ /*
+ * Autodetect takes a while to start, and during the starting sequence
+ * the autodetection status is reported as done.
+ */
+ msleep(30);
+
+ return 0;
+}
+
+static int tw9900_detect_done(struct tw9900 *tw9900, bool *done)
+{
+ int ret;
+
+ lockdep_assert_held(&tw9900->mutex);
+
+ ret = tw9900_read_reg(tw9900->client, TW9900_REG_STD);
+ if (ret < 0)
+ return ret;
+
+ *done = !(ret & TW9900_REG_STD_AUTO_PROGRESS);
+
+ return 0;
+}
+
+static int tw9900_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ struct tw9900 *tw9900 = to_tw9900(sd);
+ bool done = false;
+ int i, ret;
+
+ mutex_lock(&tw9900->mutex);
+
+ if (tw9900->streaming) {
+ mutex_unlock(&tw9900->mutex);
+ return -EBUSY;
+ }
+
+ mutex_unlock(&tw9900->mutex);
+
+ ret = pm_runtime_resume_and_get(&tw9900->client->dev);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&tw9900->mutex);
+
+ ret = tw9900_start_autodetect(tw9900);
+ if (ret)
+ goto out_unlock;
+
+ for (i = 0; i < TW9900_VIDEO_POLL_TRIES; i++) {
+ ret = tw9900_detect_done(tw9900, &done);
+ if (ret)
+ goto out_unlock;
+
+ if (done)
+ break;
+
+ msleep(20);
+ }
+
+ if (!done) {
+ ret = -ETIMEDOUT;
+ goto out_unlock;
+ }
+
+ ret = tw9900_get_stream_std(tw9900, std);
+
+out_unlock:
+ mutex_unlock(&tw9900->mutex);
+ pm_runtime_put(&tw9900->client->dev);
+
+ return ret;
+}
+
+static int tw9900_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ *std = V4L2_STD_NTSC | V4L2_STD_PAL;
+
+ return 0;
+}
+
+static int tw9900_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+ struct tw9900 *tw9900 = to_tw9900(sd);
+ int ret;
+
+ mutex_lock(&tw9900->mutex);
+
+ if (tw9900->streaming) {
+ mutex_unlock(&tw9900->mutex);
+ return -EBUSY;
+ }
+
+ mutex_unlock(&tw9900->mutex);
+
+ *status = V4L2_IN_ST_NO_SIGNAL;
+
+ ret = pm_runtime_resume_and_get(&tw9900->client->dev);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&tw9900->mutex);
+ ret = tw9900_read_reg(tw9900->client, TW9900_REG_CHIP_STATUS);
+ mutex_unlock(&tw9900->mutex);
+
+ pm_runtime_put(&tw9900->client->dev);
+
+ if (ret < 0)
+ return ret;
+
+ *status = ret & TW9900_REG_CHIP_STATUS_HLOCK ? 0 : V4L2_IN_ST_NO_SIGNAL;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops tw9900_core_ops = {
+ .subscribe_event = tw9900_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops tw9900_video_ops = {
+ .s_std = tw9900_s_std,
+ .g_std = tw9900_g_std,
+ .querystd = tw9900_querystd,
+ .g_tvnorms = tw9900_g_tvnorms,
+ .g_input_status = tw9900_g_input_status,
+ .s_stream = tw9900_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops tw9900_pad_ops = {
+ .enum_mbus_code = tw9900_enum_mbus_code,
+ .get_fmt = tw9900_get_fmt,
+ .set_fmt = tw9900_set_fmt,
+};
+
+static const struct v4l2_subdev_ops tw9900_subdev_ops = {
+ .core = &tw9900_core_ops,
+ .video = &tw9900_video_ops,
+ .pad = &tw9900_pad_ops,
+};
+
+static const struct v4l2_ctrl_ops tw9900_ctrl_ops = {
+ .s_ctrl = tw9900_s_ctrl,
+};
+
+static int tw9900_check_id(struct tw9900 *tw9900,
+ struct i2c_client *client)
+{
+ struct device *dev = &tw9900->client->dev;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(&tw9900->client->dev);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&tw9900->mutex);
+ ret = tw9900_read_reg(client, TW9900_CHIP_ID);
+ mutex_unlock(&tw9900->mutex);
+
+ pm_runtime_put(&tw9900->client->dev);
+
+ if (ret < 0)
+ return ret;
+
+ if (ret != TW9900_CHIP_ID) {
+ dev_err(dev, "Unexpected decoder id %#x\n", ret);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int tw9900_runtime_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct tw9900 *tw9900 = to_tw9900(sd);
+ int ret;
+
+ mutex_lock(&tw9900->mutex);
+
+ if (tw9900->reset_gpio)
+ gpiod_set_value_cansleep(tw9900->reset_gpio, 1);
+
+ ret = regulator_enable(tw9900->regulator);
+ if (ret < 0) {
+ mutex_unlock(&tw9900->mutex);
+ return ret;
+ }
+
+ usleep_range(50000, 52000);
+
+ if (tw9900->reset_gpio)
+ gpiod_set_value_cansleep(tw9900->reset_gpio, 0);
+
+ usleep_range(1000, 2000);
+
+ ret = tw9900_write_array(tw9900->client, tw9900_init_regs,
+ ARRAY_SIZE(tw9900_init_regs));
+
+ mutex_unlock(&tw9900->mutex);
+
+ /* This sleep is needed for the Horizontal Sync PLL to lock. */
+ msleep(300);
+
+ return ret;
+}
+
+static int tw9900_runtime_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct tw9900 *tw9900 = to_tw9900(sd);
+
+ mutex_lock(&tw9900->mutex);
+
+ if (tw9900->reset_gpio)
+ gpiod_set_value_cansleep(tw9900->reset_gpio, 1);
+
+ regulator_disable(tw9900->regulator);
+
+ mutex_unlock(&tw9900->mutex);
+
+ return 0;
+}
+
+static int tw9900_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct v4l2_ctrl_handler *hdl;
+ struct tw9900 *tw9900;
+ int ret = 0;
+
+ tw9900 = devm_kzalloc(dev, sizeof(*tw9900), GFP_KERNEL);
+ if (!tw9900)
+ return -ENOMEM;
+
+ tw9900->client = client;
+ tw9900->cur_mode = &supported_modes[0];
+
+ tw9900->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(tw9900->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(tw9900->reset_gpio),
+ "Failed to get reset gpio\n");
+
+ tw9900->regulator = devm_regulator_get(&tw9900->client->dev, "vdd");
+ if (IS_ERR(tw9900->regulator))
+ return dev_err_probe(dev, PTR_ERR(tw9900->regulator),
+ "Failed to get power regulator\n");
+
+ v4l2_i2c_subdev_init(&tw9900->subdev, client, &tw9900_subdev_ops);
+ tw9900->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+ V4L2_SUBDEV_FL_HAS_EVENTS;
+
+ mutex_init(&tw9900->mutex);
+
+ hdl = &tw9900->hdl;
+
+ ret = v4l2_ctrl_handler_init(hdl, 2);
+ if (ret)
+ goto err_destory_mutex;
+
+ hdl->lock = &tw9900->mutex;
+
+ v4l2_ctrl_new_std(hdl, &tw9900_ctrl_ops, V4L2_CID_BRIGHTNESS,
+ -128, 127, 1, 0);
+ v4l2_ctrl_new_std(hdl, &tw9900_ctrl_ops, V4L2_CID_CONTRAST,
+ 0, 255, 1, 0x60);
+
+ tw9900->subdev.ctrl_handler = hdl;
+ if (hdl->error) {
+ ret = hdl->error;
+ goto err_free_handler;
+ }
+
+ tw9900->pad.flags = MEDIA_PAD_FL_SOURCE;
+ tw9900->subdev.entity.function = MEDIA_ENT_F_DV_DECODER;
+
+ ret = media_entity_pads_init(&tw9900->subdev.entity, 1, &tw9900->pad);
+ if (ret < 0)
+ goto err_free_handler;
+
+ pm_runtime_set_suspended(dev);
+ pm_runtime_enable(dev);
+
+ ret = tw9900_check_id(tw9900, client);
+ if (ret)
+ goto err_disable_pm;
+
+ ret = v4l2_async_register_subdev(&tw9900->subdev);
+ if (ret) {
+ dev_err(dev, "v4l2 async register subdev failed\n");
+ goto err_disable_pm;
+ }
+
+ return 0;
+
+err_disable_pm:
+ pm_runtime_disable(dev);
+ media_entity_cleanup(&tw9900->subdev.entity);
+err_free_handler:
+ v4l2_ctrl_handler_free(hdl);
+err_destory_mutex:
+ mutex_destroy(&tw9900->mutex);
+
+ return ret;
+}
+
+static void tw9900_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct tw9900 *tw9900 = to_tw9900(sd);
+
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
+
+ pm_runtime_disable(&client->dev);
+
+ mutex_destroy(&tw9900->mutex);
+}
+
+static const struct dev_pm_ops tw9900_pm_ops = {
+ .runtime_suspend = tw9900_runtime_suspend,
+ .runtime_resume = tw9900_runtime_resume,
+};
+
+static const struct i2c_device_id tw9900_id[] = {
+ { "tw9900", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tw9900_id);
+
+static const struct of_device_id tw9900_of_match[] = {
+ { .compatible = "techwell,tw9900" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tw9900_of_match);
+
+static struct i2c_driver tw9900_i2c_driver = {
+ .driver = {
+ .name = "tw9900",
+ .pm = &tw9900_pm_ops,
+ .of_match_table = tw9900_of_match,
+ },
+ .probe = tw9900_probe,
+ .remove = tw9900_remove,
+ .id_table = tw9900_id,
+};
+
+module_i2c_driver(tw9900_i2c_driver);
+
+MODULE_DESCRIPTION("tw9900 decoder driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/tw9910.c b/drivers/media/i2c/tw9910.c
index 477a64d8f8..905af98c7d 100644
--- a/drivers/media/i2c/tw9910.c
+++ b/drivers/media/i2c/tw9910.c
@@ -829,8 +829,6 @@ static int tw9910_set_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
return tw9910_s_fmt(sd, mf);
- sd_state->pads->try_fmt = *mf;
-
return 0;
}
diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c
index 178bd06cc2..56dbe07a1c 100644
--- a/drivers/media/i2c/video-i2c.c
+++ b/drivers/media/i2c/video-i2c.c
@@ -405,9 +405,10 @@ static int queue_setup(struct vb2_queue *vq,
{
struct video_i2c_data *data = vb2_get_drv_priv(vq);
unsigned int size = data->chip->buffer_size;
+ unsigned int q_num_bufs = vb2_get_num_buffers(vq);
- if (vq->num_buffers + *nbuffers < 2)
- *nbuffers = 2;
+ if (q_num_bufs + *nbuffers < 2)
+ *nbuffers = 2 - q_num_bufs;
if (*nplanes)
return sizes[0] < size ? -EINVAL : 0;
@@ -794,7 +795,7 @@ static int video_i2c_probe(struct i2c_client *client)
queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
queue->drv_priv = data;
queue->buf_struct_size = sizeof(struct video_i2c_buffer);
- queue->min_buffers_needed = 1;
+ queue->min_queued_buffers = 1;
queue->ops = &video_i2c_video_qops;
queue->mem_ops = &vb2_vmalloc_memops;