199c4961e867b8f4b6596af51847d4aac3560cc8
[openwrt/staging/981213.git] /
1 From 5ae0488f5fc682877ae2a5d454f70884e62120ef Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Thu, 3 Oct 2019 13:35:01 +0100
4 Subject: [PATCH] media: bcm2835-unicam: Support unpacking CSI format
5 to 16bpp
6
7 The CSI packed formats are not the easiest to work with, and
8 the peripheral supports unpacking them to 16bpp (but NOT
9 shifting the data up into the MSBs).
10 Where V4L2 exposes a pixfmt for both packed and unpacked
11 formats advertise both as being supported, and unpack the
12 data in the peripheral.
13
14 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
15 ---
16 .../media/platform/bcm2835/bcm2835-unicam.c | 102 +++++++++---------
17 1 file changed, 51 insertions(+), 51 deletions(-)
18
19 --- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
20 +++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
21 @@ -15,12 +15,15 @@
22 *
23 * This driver directly controls the Unicam peripheral - there is no
24 * involvement with the VideoCore firmware. Unicam receives CSI-2 or
25 - * CCP2 data and writes it into SDRAM. The only potential processing options are
26 - * to repack Bayer data into an alternate format, and applying windowing.
27 - * The repacking does not shift the data, so could repack V4L2_PIX_FMT_Sxxxx10P
28 + * CCP2 data and writes it into SDRAM.
29 + * The only potential processing options are to repack Bayer data into an
30 + * alternate format, and applying windowing.
31 + * The repacking does not shift the data, so can repack V4L2_PIX_FMT_Sxxxx10P
32 * to V4L2_PIX_FMT_Sxxxx10, or V4L2_PIX_FMT_Sxxxx12P to V4L2_PIX_FMT_Sxxxx12,
33 - * but not generically up to V4L2_PIX_FMT_Sxxxx16.
34 - * Adding support for repacking and windowing may be added later.
35 + * but not generically up to V4L2_PIX_FMT_Sxxxx16. The driver will add both
36 + * formats where the relevant formats are defined, and will automatically
37 + * configure the repacking as required.
38 + * Support for windowing may be added later.
39 *
40 * It should be possible to connect this driver to any sensor with a
41 * suitable output interface and V4L2 subdevice driver.
42 @@ -122,13 +125,16 @@ MODULE_PARM_DESC(debug, "Debug level 0-3
43
44 /*
45 * struct unicam_fmt - Unicam media bus format information
46 - * @pixelformat: V4L2 pixel format FCC identifier.
47 + * @pixelformat: V4L2 pixel format FCC identifier. 0 if n/a.
48 + * @repacked_fourcc: V4L2 pixel format FCC identifier if the data is expanded
49 + * out to 16bpp. 0 if n/a.
50 * @code: V4L2 media bus format code.
51 - * @depth: Bits per pixel (when stored in memory).
52 + * @depth: Bits per pixel as delivered from the source.
53 * @csi_dt: CSI data type.
54 */
55 struct unicam_fmt {
56 u32 fourcc;
57 + u32 repacked_fourcc;
58 u32 code;
59 u8 depth;
60 u8 csi_dt;
61 @@ -235,41 +241,49 @@ static const struct unicam_fmt formats[]
62 .csi_dt = 0x2a,
63 }, {
64 .fourcc = V4L2_PIX_FMT_SBGGR10P,
65 + .repacked_fourcc = V4L2_PIX_FMT_SBGGR10,
66 .code = MEDIA_BUS_FMT_SBGGR10_1X10,
67 .depth = 10,
68 .csi_dt = 0x2b,
69 }, {
70 .fourcc = V4L2_PIX_FMT_SGBRG10P,
71 + .repacked_fourcc = V4L2_PIX_FMT_SGBRG10,
72 .code = MEDIA_BUS_FMT_SGBRG10_1X10,
73 .depth = 10,
74 .csi_dt = 0x2b,
75 }, {
76 .fourcc = V4L2_PIX_FMT_SGRBG10P,
77 + .repacked_fourcc = V4L2_PIX_FMT_SGRBG10,
78 .code = MEDIA_BUS_FMT_SGRBG10_1X10,
79 .depth = 10,
80 .csi_dt = 0x2b,
81 }, {
82 .fourcc = V4L2_PIX_FMT_SRGGB10P,
83 + .repacked_fourcc = V4L2_PIX_FMT_SRGGB10,
84 .code = MEDIA_BUS_FMT_SRGGB10_1X10,
85 .depth = 10,
86 .csi_dt = 0x2b,
87 }, {
88 .fourcc = V4L2_PIX_FMT_SBGGR12P,
89 + .repacked_fourcc = V4L2_PIX_FMT_SBGGR12,
90 .code = MEDIA_BUS_FMT_SBGGR12_1X12,
91 .depth = 12,
92 .csi_dt = 0x2c,
93 }, {
94 .fourcc = V4L2_PIX_FMT_SGBRG12P,
95 + .repacked_fourcc = V4L2_PIX_FMT_SGBRG12,
96 .code = MEDIA_BUS_FMT_SGBRG12_1X12,
97 .depth = 12,
98 .csi_dt = 0x2c,
99 }, {
100 .fourcc = V4L2_PIX_FMT_SGRBG12P,
101 + .repacked_fourcc = V4L2_PIX_FMT_SGRBG12,
102 .code = MEDIA_BUS_FMT_SGRBG12_1X12,
103 .depth = 12,
104 .csi_dt = 0x2c,
105 }, {
106 .fourcc = V4L2_PIX_FMT_SRGGB12P,
107 + .repacked_fourcc = V4L2_PIX_FMT_SRGGB12,
108 .code = MEDIA_BUS_FMT_SRGGB12_1X12,
109 .depth = 12,
110 .csi_dt = 0x2c,
111 @@ -439,20 +453,6 @@ static inline void unicam_runtime_put(st
112 }
113
114 /* Format setup functions */
115 -static int find_mbus_depth_by_code(u32 code)
116 -{
117 - const struct unicam_fmt *fmt;
118 - unsigned int k;
119 -
120 - for (k = 0; k < ARRAY_SIZE(formats); k++) {
121 - fmt = &formats[k];
122 - if (fmt->code == code)
123 - return fmt->depth;
124 - }
125 -
126 - return 0;
127 -}
128 -
129 static const struct unicam_fmt *find_format_by_code(u32 code)
130 {
131 unsigned int k;
132 @@ -470,7 +470,8 @@ static const struct unicam_fmt *find_for
133 unsigned int k;
134
135 for (k = 0; k < ARRAY_SIZE(formats); k++) {
136 - if (formats[k].fourcc == pixelformat)
137 + if (formats[k].fourcc == pixelformat ||
138 + formats[k].repacked_fourcc == pixelformat)
139 return &formats[k];
140 }
141
142 @@ -478,9 +479,14 @@ static const struct unicam_fmt *find_for
143 }
144
145 static inline unsigned int bytes_per_line(u32 width,
146 - const struct unicam_fmt *fmt)
147 + const struct unicam_fmt *fmt,
148 + u32 v4l2_fourcc)
149 {
150 - return ALIGN((width * fmt->depth) >> 3, BPL_ALIGNMENT);
151 + if (v4l2_fourcc == fmt->repacked_fourcc)
152 + /* Repacking always goes to 16bpp */
153 + return ALIGN(width << 1, BPL_ALIGNMENT);
154 + else
155 + return ALIGN((width * fmt->depth) >> 3, BPL_ALIGNMENT);
156 }
157
158 static int __subdev_get_format(struct unicam_device *dev,
159 @@ -538,7 +544,8 @@ static int unicam_calc_format_size_bpl(s
160 &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0,
161 0);
162
163 - min_bytesperline = bytes_per_line(f->fmt.pix.width, fmt);
164 + min_bytesperline = bytes_per_line(f->fmt.pix.width, fmt,
165 + f->fmt.pix.pixelformat);
166
167 if (f->fmt.pix.bytesperline > min_bytesperline &&
168 f->fmt.pix.bytesperline <= MAX_BYTESPERLINE)
169 @@ -738,6 +745,13 @@ static int unicam_enum_fmt_vid_cap(struc
170 }
171 index++;
172 }
173 + if (fmt->repacked_fourcc) {
174 + if (index == f->index) {
175 + f->pixelformat = fmt->repacked_fourcc;
176 + break;
177 + }
178 + index++;
179 + }
180 }
181 }
182
183 @@ -858,7 +872,10 @@ static int unicam_try_fmt_vid_cap(struct
184 }
185 }
186
187 - f->fmt.pix.pixelformat = fmt->fourcc;
188 + if (fmt->fourcc)
189 + f->fmt.pix.pixelformat = fmt->fourcc;
190 + else
191 + f->fmt.pix.pixelformat = fmt->repacked_fourcc;
192 }
193
194 return unicam_calc_format_size_bpl(dev, fmt, f);
195 @@ -998,16 +1015,14 @@ static void unicam_wr_dma_config(struct
196
197 static void unicam_set_packing_config(struct unicam_device *dev)
198 {
199 - int mbus_depth = find_mbus_depth_by_code(dev->fmt->code);
200 - int v4l2_depth = dev->fmt->depth;
201 int pack, unpack;
202 u32 val;
203
204 - if (mbus_depth == v4l2_depth) {
205 + if (dev->v_fmt.fmt.pix.pixelformat == dev->fmt->fourcc) {
206 unpack = UNICAM_PUM_NONE;
207 pack = UNICAM_PPM_NONE;
208 } else {
209 - switch (mbus_depth) {
210 + switch (dev->fmt->depth) {
211 case 8:
212 unpack = UNICAM_PUM_UNPACK8;
213 break;
214 @@ -1028,26 +1043,8 @@ static void unicam_set_packing_config(st
215 break;
216 }
217
218 - switch (v4l2_depth) {
219 - case 8:
220 - pack = UNICAM_PPM_PACK8;
221 - break;
222 - case 10:
223 - pack = UNICAM_PPM_PACK10;
224 - break;
225 - case 12:
226 - pack = UNICAM_PPM_PACK12;
227 - break;
228 - case 14:
229 - pack = UNICAM_PPM_PACK14;
230 - break;
231 - case 16:
232 - pack = UNICAM_PPM_PACK16;
233 - break;
234 - default:
235 - pack = UNICAM_PPM_NONE;
236 - break;
237 - }
238 + /* Repacking is always to 16bpp */
239 + pack = UNICAM_PPM_PACK16;
240 }
241
242 val = 0;
243 @@ -1893,7 +1890,10 @@ static int unicam_probe_complete(struct
244 }
245
246 unicam->fmt = fmt;
247 - unicam->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
248 + if (fmt->fourcc)
249 + unicam->v_fmt.fmt.pix.pixelformat = fmt->fourcc;
250 + else
251 + unicam->v_fmt.fmt.pix.pixelformat = fmt->repacked_fourcc;
252
253 /* Read current subdev format */
254 unicam_reset_format(unicam);