bcm27xx: 6.1: add kernel patches
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-6.1 / 950-0629-media-i2c-imx290-Add-crop-selection-targets-support.patch
1 From 663ffc173ab99d9cb9165cb91393783b7ac40c1f Mon Sep 17 00:00:00 2001
2 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 Date: Sun, 16 Oct 2022 09:15:22 +0300
4 Subject: [PATCH] media: i2c: imx290: Add crop selection targets
5 support
6
7 Upstream commit b4ab57b07c5b.
8
9 Implement read-only access to crop selection rectangles to expose the
10 analogue crop rectangle. The public (leaked) IMX290 documentation is not
11 very clear on how cropping is implemented and configured exactly, so
12 the margins may not be entirely accurate.
13
14 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
15 Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
16 ---
17 drivers/media/i2c/imx290.c | 94 ++++++++++++++++++++++++++++++++++++++
18 1 file changed, 94 insertions(+)
19
20 --- a/drivers/media/i2c/imx290.c
21 +++ b/drivers/media/i2c/imx290.c
22 @@ -105,6 +105,53 @@
23
24 #define IMX290_VMAX_DEFAULT 1125
25
26 +
27 +/*
28 + * The IMX290 pixel array is organized as follows:
29 + *
30 + * +------------------------------------+
31 + * | Optical Black | } Vertical effective optical black (10)
32 + * +---+------------------------------------+---+
33 + * | | | | } Effective top margin (8)
34 + * | | +----------------------------+ | | \
35 + * | | | | | | |
36 + * | | | | | | |
37 + * | | | | | | |
38 + * | | | Recording Pixel Area | | | | Recommended height (1080)
39 + * | | | | | | |
40 + * | | | | | | |
41 + * | | | | | | |
42 + * | | +----------------------------+ | | /
43 + * | | | | } Effective bottom margin (9)
44 + * +---+------------------------------------+---+
45 + * <-> <-> <--------------------------> <-> <->
46 + * \---- Ignored right margin (4)
47 + * \-------- Effective right margin (9)
48 + * \------------------------- Recommended width (1920)
49 + * \----------------------------------------- Effective left margin (8)
50 + * \--------------------------------------------- Ignored left margin (4)
51 + *
52 + * The optical black lines are output over CSI-2 with a separate data type.
53 + *
54 + * The pixel array is meant to have 1920x1080 usable pixels after image
55 + * processing in an ISP. It has 8 (9) extra active pixels usable for color
56 + * processing in the ISP on the top and left (bottom and right) sides of the
57 + * image. In addition, 4 additional pixels are present on the left and right
58 + * sides of the image, documented as "ignored area".
59 + *
60 + * As far as is understood, all pixels of the pixel array (ignored area, color
61 + * processing margins and recording area) can be output by the sensor.
62 + */
63 +
64 +#define IMX290_PIXEL_ARRAY_WIDTH 1945
65 +#define IMX290_PIXEL_ARRAY_HEIGHT 1097
66 +#define IMX920_PIXEL_ARRAY_MARGIN_LEFT 12
67 +#define IMX920_PIXEL_ARRAY_MARGIN_RIGHT 13
68 +#define IMX920_PIXEL_ARRAY_MARGIN_TOP 8
69 +#define IMX920_PIXEL_ARRAY_MARGIN_BOTTOM 9
70 +#define IMX290_PIXEL_ARRAY_RECORDING_WIDTH 1920
71 +#define IMX290_PIXEL_ARRAY_RECORDING_HEIGHT 1080
72 +
73 static const char * const imx290_supply_name[] = {
74 "vdda",
75 "vddd",
76 @@ -667,6 +714,52 @@ static int imx290_set_fmt(struct v4l2_su
77 return 0;
78 }
79
80 +static int imx290_get_selection(struct v4l2_subdev *sd,
81 + struct v4l2_subdev_state *sd_state,
82 + struct v4l2_subdev_selection *sel)
83 +{
84 + struct imx290 *imx290 = to_imx290(sd);
85 + struct v4l2_mbus_framefmt *format;
86 +
87 + switch (sel->target) {
88 + case V4L2_SEL_TGT_CROP: {
89 + format = imx290_get_pad_format(imx290, sd_state, sel->which);
90 +
91 + mutex_lock(&imx290->lock);
92 +
93 + sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP
94 + + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2;
95 + sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT
96 + + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2;
97 + sel->r.width = format->width;
98 + sel->r.height = format->height;
99 +
100 + mutex_unlock(&imx290->lock);
101 + return 0;
102 + }
103 +
104 + case V4L2_SEL_TGT_NATIVE_SIZE:
105 + case V4L2_SEL_TGT_CROP_BOUNDS:
106 + sel->r.top = 0;
107 + sel->r.left = 0;
108 + sel->r.width = IMX290_PIXEL_ARRAY_WIDTH;
109 + sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT;
110 +
111 + return 0;
112 +
113 + case V4L2_SEL_TGT_CROP_DEFAULT:
114 + sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP;
115 + sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT;
116 + sel->r.width = IMX290_PIXEL_ARRAY_RECORDING_WIDTH;
117 + sel->r.height = IMX290_PIXEL_ARRAY_RECORDING_HEIGHT;
118 +
119 + return 0;
120 +
121 + default:
122 + return -EINVAL;
123 + }
124 +}
125 +
126 static int imx290_entity_init_cfg(struct v4l2_subdev *subdev,
127 struct v4l2_subdev_state *sd_state)
128 {
129 @@ -883,6 +976,7 @@ static const struct v4l2_subdev_pad_ops
130 .enum_frame_size = imx290_enum_frame_size,
131 .get_fmt = imx290_get_fmt,
132 .set_fmt = imx290_set_fmt,
133 + .get_selection = imx290_get_selection,
134 };
135
136 static const struct v4l2_subdev_ops imx290_subdev_ops = {