bcm27xx: add support for linux v5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.15 / 950-0365-media-i2c-ov9281-Add-support-for-8-bit-readout.patch
1 From 86e3f6d35527608611176b6591bc6a80bfc0f7cf Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Tue, 7 Jul 2020 18:29:10 +0100
4 Subject: [PATCH] media: i2c: ov9281: Add support for 8 bit readout
5
6 The sensor supports 8 bit mode as well as 10bit, so add the
7 relevant code to allow selection of this.
8
9 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
10 ---
11 drivers/media/i2c/ov9281.c | 66 ++++++++++++++++++++++++++++++--------
12 1 file changed, 52 insertions(+), 14 deletions(-)
13
14 --- a/drivers/media/i2c/ov9281.c
15 +++ b/drivers/media/i2c/ov9281.c
16 @@ -29,11 +29,12 @@
17
18 #define OV9281_LINK_FREQ_400MHZ 400000000
19 #define OV9281_LANES 2
20 -#define OV9281_BITS_PER_SAMPLE 10
21
22 /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
23 -#define OV9281_PIXEL_RATE (OV9281_LINK_FREQ_400MHZ * 2 * \
24 - OV9281_LANES / OV9281_BITS_PER_SAMPLE)
25 +#define OV9281_PIXEL_RATE_10BIT (OV9281_LINK_FREQ_400MHZ * 2 * \
26 + OV9281_LANES / 10)
27 +#define OV9281_PIXEL_RATE_8BIT (OV9281_LINK_FREQ_400MHZ * 2 * \
28 + OV9281_LANES / 8)
29 #define OV9281_XVCLK_FREQ 24000000
30
31 #define CHIP_ID 0x9281
32 @@ -122,24 +123,25 @@ struct ov9281 {
33 struct v4l2_ctrl *digi_gain;
34 struct v4l2_ctrl *hblank;
35 struct v4l2_ctrl *vblank;
36 + struct v4l2_ctrl *pixel_rate;
37 struct v4l2_ctrl *test_pattern;
38 struct mutex mutex;
39 bool streaming;
40 bool power_on;
41 const struct ov9281_mode *cur_mode;
42 + u32 code;
43 };
44
45 #define to_ov9281(sd) container_of(sd, struct ov9281, subdev)
46
47 /*
48 * Xclk 24Mhz
49 - * max_framerate 120fps
50 + * max_framerate 120fps for 10 bit, 144fps for 8 bit.
51 * mipi_datarate per lane 800Mbps
52 */
53 static const struct regval ov9281_1280x800_regs[] = {
54 {0x0103, 0x01},
55 {0x0302, 0x32},
56 - {0x030d, 0x50},
57 {0x030e, 0x02},
58 {0x3001, 0x00},
59 {0x3004, 0x00},
60 @@ -168,7 +170,6 @@ static const struct regval ov9281_1280x8
61 {0x3620, 0x6f},
62 {0x3632, 0x56},
63 {0x3633, 0x78},
64 - {0x3662, 0x05},
65 {0x3666, 0x00},
66 {0x366f, 0x5a},
67 {0x3680, 0x84},
68 @@ -235,6 +236,18 @@ static const struct regval ov9281_1280x8
69 {REG_NULL, 0x00},
70 };
71
72 +static const struct regval op_10bit[] = {
73 + {0x030d, 0x50},
74 + {0x3662, 0x05},
75 + {REG_NULL, 0x00},
76 +};
77 +
78 +static const struct regval op_8bit[] = {
79 + {0x030d, 0x60},
80 + {0x3662, 0x07},
81 + {REG_NULL, 0x00},
82 +};
83 +
84 static const struct ov9281_mode supported_modes[] = {
85 {
86 .width = 1280,
87 @@ -374,12 +387,13 @@ static int ov9281_set_fmt(struct v4l2_su
88 {
89 struct ov9281 *ov9281 = to_ov9281(sd);
90 const struct ov9281_mode *mode;
91 - s64 h_blank, vblank_def;
92 + s64 h_blank, vblank_def, pixel_rate;
93
94 mutex_lock(&ov9281->mutex);
95
96 mode = ov9281_find_best_fit(fmt);
97 - fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
98 + if (fmt->format.code != MEDIA_BUS_FMT_Y8_1X8)
99 + fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
100 fmt->format.width = mode->width;
101 fmt->format.height = mode->height;
102 fmt->format.field = V4L2_FIELD_NONE;
103 @@ -396,6 +410,7 @@ static int ov9281_set_fmt(struct v4l2_su
104 *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
105 } else {
106 ov9281->cur_mode = mode;
107 + ov9281->code = fmt->format.code;
108 h_blank = mode->hts_def - mode->width;
109 __v4l2_ctrl_modify_range(ov9281->hblank, h_blank,
110 h_blank, 1, h_blank);
111 @@ -405,6 +420,11 @@ static int ov9281_set_fmt(struct v4l2_su
112 OV9281_VTS_MAX - mode->height,
113 1, vblank_def);
114 __v4l2_ctrl_s_ctrl(ov9281->vblank, vblank_def);
115 +
116 + pixel_rate = (fmt->format.code == MEDIA_BUS_FMT_Y10_1X10) ?
117 + OV9281_PIXEL_RATE_10BIT : OV9281_PIXEL_RATE_8BIT;
118 + __v4l2_ctrl_modify_range(ov9281->pixel_rate, pixel_rate,
119 + pixel_rate, 1, pixel_rate);
120 }
121
122 mutex_unlock(&ov9281->mutex);
123 @@ -425,7 +445,7 @@ static int ov9281_get_fmt(struct v4l2_su
124 } else {
125 fmt->format.width = mode->width;
126 fmt->format.height = mode->height;
127 - fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
128 + fmt->format.code = ov9281->code;
129 fmt->format.field = V4L2_FIELD_NONE;
130 fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
131 fmt->format.ycbcr_enc =
132 @@ -446,9 +466,16 @@ static int ov9281_enum_mbus_code(struct
133 struct v4l2_subdev_pad_config *cfg,
134 struct v4l2_subdev_mbus_code_enum *code)
135 {
136 - if (code->index)
137 + switch (code->index) {
138 + default:
139 return -EINVAL;
140 - code->code = MEDIA_BUS_FMT_Y10_1X10;
141 + case 0:
142 + code->code = MEDIA_BUS_FMT_Y10_1X10;
143 + break;
144 + case 1:
145 + code->code = MEDIA_BUS_FMT_Y8_1X8;
146 + break;
147 + }
148
149 return 0;
150 }
151 @@ -460,7 +487,8 @@ static int ov9281_enum_frame_sizes(struc
152 if (fse->index >= ARRAY_SIZE(supported_modes))
153 return -EINVAL;
154
155 - if (fse->code != MEDIA_BUS_FMT_Y10_1X10)
156 + if (fse->code != MEDIA_BUS_FMT_Y10_1X10 &&
157 + fse->code != MEDIA_BUS_FMT_Y8_1X8)
158 return -EINVAL;
159
160 fse->min_width = supported_modes[fse->index].width;
161 @@ -543,6 +571,13 @@ static int __ov9281_start_stream(struct
162 if (ret)
163 return ret;
164
165 + if (ov9281->code == MEDIA_BUS_FMT_Y10_1X10)
166 + ret = ov9281_write_array(ov9281->client, op_10bit);
167 + else
168 + ret = ov9281_write_array(ov9281->client, op_8bit);
169 + if (ret)
170 + return ret;
171 +
172 /* In case these controls are set before streaming */
173 mutex_unlock(&ov9281->mutex);
174 ret = v4l2_ctrl_handler_setup(&ov9281->ctrl_handler);
175 @@ -849,8 +884,11 @@ static int ov9281_initialize_controls(st
176 if (ctrl)
177 ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
178
179 - v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
180 - 0, OV9281_PIXEL_RATE, 1, OV9281_PIXEL_RATE);
181 + ov9281->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
182 + V4L2_CID_PIXEL_RATE,
183 + OV9281_PIXEL_RATE_10BIT,
184 + OV9281_PIXEL_RATE_10BIT, 1,
185 + OV9281_PIXEL_RATE_10BIT);
186
187 h_blank = mode->hts_def - mode->width;
188 ov9281->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,