d4b8305b4a2d798e3564c7bc53fb2bcc5859f114
[openwrt/staging/neocturne.git] /
1 From 6e8b94f48ce58e2b9c09000eb77642f3633a6b0b Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Wed, 23 Mar 2022 15:48:49 +0000
4 Subject: [PATCH] media: i2c: imx258: Add get_selection for pixel array
5 information
6
7 Libcamera requires the cropping information for each mode, so
8 add this information to the driver.
9
10 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
11 ---
12 drivers/media/i2c/imx258.c | 90 ++++++++++++++++++++++++++++++++++++++
13 1 file changed, 90 insertions(+)
14
15 --- a/drivers/media/i2c/imx258.c
16 +++ b/drivers/media/i2c/imx258.c
17 @@ -78,6 +78,14 @@
18 #define REG_CONFIG_MIRROR_VFLIP 0x02
19 #define REG_CONFIG_FLIP_TEST_PATTERN 0x02
20
21 +/* IMX258 native and active pixel array size. */
22 +#define IMX258_NATIVE_WIDTH 4224U
23 +#define IMX258_NATIVE_HEIGHT 3192U
24 +#define IMX258_PIXEL_ARRAY_LEFT 8U
25 +#define IMX258_PIXEL_ARRAY_TOP 16U
26 +#define IMX258_PIXEL_ARRAY_WIDTH 4208U
27 +#define IMX258_PIXEL_ARRAY_HEIGHT 3120U
28 +
29 struct imx258_reg {
30 u16 address;
31 u8 val;
32 @@ -116,6 +124,9 @@ struct imx258_mode {
33 u32 link_freq_index;
34 /* Default register values */
35 struct imx258_reg_list reg_list;
36 +
37 + /* Analog crop rectangle. */
38 + struct v4l2_rect crop;
39 };
40
41 /* 4208x3120 needs 1267Mbps/lane, 4 lanes. Use that rate on 2 lanes as well */
42 @@ -774,6 +785,12 @@ static const struct imx258_mode supporte
43 .regs = mode_4208x3120_regs,
44 },
45 .link_freq_index = IMX258_LINK_FREQ_1267MBPS,
46 + .crop = {
47 + .left = IMX258_PIXEL_ARRAY_LEFT,
48 + .top = IMX258_PIXEL_ARRAY_TOP,
49 + .width = 4208,
50 + .height = 3120,
51 + },
52 },
53 {
54 .width = 2104,
55 @@ -785,6 +802,12 @@ static const struct imx258_mode supporte
56 .regs = mode_2104_1560_regs,
57 },
58 .link_freq_index = IMX258_LINK_FREQ_640MBPS,
59 + .crop = {
60 + .left = IMX258_PIXEL_ARRAY_LEFT,
61 + .top = IMX258_PIXEL_ARRAY_TOP,
62 + .width = 4208,
63 + .height = 3120,
64 + },
65 },
66 {
67 .width = 1048,
68 @@ -796,6 +819,12 @@ static const struct imx258_mode supporte
69 .regs = mode_1048_780_regs,
70 },
71 .link_freq_index = IMX258_LINK_FREQ_640MBPS,
72 + .crop = {
73 + .left = IMX258_PIXEL_ARRAY_LEFT,
74 + .top = IMX258_PIXEL_ARRAY_TOP,
75 + .width = 4208,
76 + .height = 3120,
77 + },
78 },
79 };
80
81 @@ -930,6 +959,7 @@ static int imx258_open(struct v4l2_subde
82 struct imx258 *imx258 = to_imx258(sd);
83 struct v4l2_mbus_framefmt *try_fmt =
84 v4l2_subdev_get_try_format(sd, fh->state, 0);
85 + struct v4l2_rect *try_crop;
86
87 /* Initialize try_fmt */
88 try_fmt->width = supported_modes[0].width;
89 @@ -937,6 +967,13 @@ static int imx258_open(struct v4l2_subde
90 try_fmt->code = imx258_get_format_code(imx258);
91 try_fmt->field = V4L2_FIELD_NONE;
92
93 + /* Initialize try_crop */
94 + try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
95 + try_crop->left = IMX258_PIXEL_ARRAY_LEFT;
96 + try_crop->top = IMX258_PIXEL_ARRAY_TOP;
97 + try_crop->width = IMX258_PIXEL_ARRAY_WIDTH;
98 + try_crop->height = IMX258_PIXEL_ARRAY_HEIGHT;
99 +
100 return 0;
101 }
102
103 @@ -1193,6 +1230,58 @@ static int imx258_set_pad_format(struct
104 return 0;
105 }
106
107 +static const struct v4l2_rect *
108 +__imx258_get_pad_crop(struct imx258 *imx258,
109 + struct v4l2_subdev_state *sd_state,
110 + unsigned int pad, enum v4l2_subdev_format_whence which)
111 +{
112 + switch (which) {
113 + case V4L2_SUBDEV_FORMAT_TRY:
114 + return v4l2_subdev_get_try_crop(&imx258->sd, sd_state, pad);
115 + case V4L2_SUBDEV_FORMAT_ACTIVE:
116 + return &imx258->cur_mode->crop;
117 + }
118 +
119 + return NULL;
120 +}
121 +
122 +static int imx258_get_selection(struct v4l2_subdev *sd,
123 + struct v4l2_subdev_state *sd_state,
124 + struct v4l2_subdev_selection *sel)
125 +{
126 + switch (sel->target) {
127 + case V4L2_SEL_TGT_CROP: {
128 + struct imx258 *imx258 = to_imx258(sd);
129 +
130 + mutex_lock(&imx258->mutex);
131 + sel->r = *__imx258_get_pad_crop(imx258, sd_state, sel->pad,
132 + sel->which);
133 + mutex_unlock(&imx258->mutex);
134 +
135 + return 0;
136 + }
137 +
138 + case V4L2_SEL_TGT_NATIVE_SIZE:
139 + sel->r.left = 0;
140 + sel->r.top = 0;
141 + sel->r.width = IMX258_NATIVE_WIDTH;
142 + sel->r.height = IMX258_NATIVE_HEIGHT;
143 +
144 + return 0;
145 +
146 + case V4L2_SEL_TGT_CROP_DEFAULT:
147 + case V4L2_SEL_TGT_CROP_BOUNDS:
148 + sel->r.left = IMX258_PIXEL_ARRAY_LEFT;
149 + sel->r.top = IMX258_PIXEL_ARRAY_TOP;
150 + sel->r.width = IMX258_PIXEL_ARRAY_WIDTH;
151 + sel->r.height = IMX258_PIXEL_ARRAY_HEIGHT;
152 +
153 + return 0;
154 + }
155 +
156 + return -EINVAL;
157 +}
158 +
159 /* Start streaming */
160 static int imx258_start_streaming(struct imx258 *imx258)
161 {
162 @@ -1389,6 +1478,7 @@ static const struct v4l2_subdev_pad_ops
163 .get_fmt = imx258_get_pad_format,
164 .set_fmt = imx258_set_pad_format,
165 .enum_frame_size = imx258_enum_frame_size,
166 + .get_selection = imx258_get_selection,
167 };
168
169 static const struct v4l2_subdev_ops imx258_subdev_ops = {