1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for STM32 Digital Camera Memory Interface Pixel Processor
5 * Copyright (C) STMicroelectronics SA 2023
8 * for STMicroelectronics.
11 #include <linux/vmalloc.h>
12 #include <linux/v4l2-mediabus.h>
13 #include <media/v4l2-rect.h>
14 #include <media/v4l2-subdev.h>
16 #include "dcmipp-common.h"
18 #define DCMIPP_P0FCTCR 0x500
19 #define DCMIPP_P0FCTCR_FRATE_MASK GENMASK(1, 0)
20 #define DCMIPP_P0SCSTR 0x504
21 #define DCMIPP_P0SCSTR_HSTART_SHIFT 0
22 #define DCMIPP_P0SCSTR_VSTART_SHIFT 16
23 #define DCMIPP_P0SCSZR 0x508
24 #define DCMIPP_P0SCSZR_ENABLE BIT(31)
25 #define DCMIPP_P0SCSZR_HSIZE_SHIFT 0
26 #define DCMIPP_P0SCSZR_VSIZE_SHIFT 16
27 #define DCMIPP_P0PPCR 0x5c0
28 #define DCMIPP_P0PPCR_BSM_1_2 0x1
29 #define DCMIPP_P0PPCR_BSM_1_4 0x2
30 #define DCMIPP_P0PPCR_BSM_2_4 0x3
31 #define DCMIPP_P0PPCR_BSM_MASK GENMASK(8, 7)
32 #define DCMIPP_P0PPCR_BSM_SHIFT 0x7
33 #define DCMIPP_P0PPCR_LSM BIT(10)
34 #define DCMIPP_P0PPCR_OELS BIT(11)
36 #define IS_SINK(pad) (!(pad))
37 #define IS_SRC(pad) ((pad))
39 struct dcmipp_byteproc_pix_map {
44 #define PIXMAP_MBUS_BPP(mbus, byteperpixel) \
46 .code = MEDIA_BUS_FMT_##mbus, \
47 .bpp = byteperpixel, \
49 static const struct dcmipp_byteproc_pix_map dcmipp_byteproc_pix_map_list[] = {
50 PIXMAP_MBUS_BPP(RGB565_2X8_LE, 2),
51 PIXMAP_MBUS_BPP(RGB565_1X16, 2),
52 PIXMAP_MBUS_BPP(YUYV8_2X8, 2),
53 PIXMAP_MBUS_BPP(YUYV8_1X16, 2),
54 PIXMAP_MBUS_BPP(YVYU8_2X8, 2),
55 PIXMAP_MBUS_BPP(YVYU8_1X16, 2),
56 PIXMAP_MBUS_BPP(UYVY8_2X8, 2),
57 PIXMAP_MBUS_BPP(UYVY8_1X16, 2),
58 PIXMAP_MBUS_BPP(VYUY8_2X8, 2),
59 PIXMAP_MBUS_BPP(VYUY8_1X16, 2),
60 PIXMAP_MBUS_BPP(Y8_1X8, 1),
61 PIXMAP_MBUS_BPP(SBGGR8_1X8, 1),
62 PIXMAP_MBUS_BPP(SGBRG8_1X8, 1),
63 PIXMAP_MBUS_BPP(SGRBG8_1X8, 1),
64 PIXMAP_MBUS_BPP(SRGGB8_1X8, 1),
65 PIXMAP_MBUS_BPP(SBGGR10_1X10, 2),
66 PIXMAP_MBUS_BPP(SGBRG10_1X10, 2),
67 PIXMAP_MBUS_BPP(SGRBG10_1X10, 2),
68 PIXMAP_MBUS_BPP(SRGGB10_1X10, 2),
69 PIXMAP_MBUS_BPP(SBGGR12_1X12, 2),
70 PIXMAP_MBUS_BPP(SGBRG12_1X12, 2),
71 PIXMAP_MBUS_BPP(SGRBG12_1X12, 2),
72 PIXMAP_MBUS_BPP(SRGGB12_1X12, 2),
73 PIXMAP_MBUS_BPP(SBGGR14_1X14, 2),
74 PIXMAP_MBUS_BPP(SGBRG14_1X14, 2),
75 PIXMAP_MBUS_BPP(SGRBG14_1X14, 2),
76 PIXMAP_MBUS_BPP(SRGGB14_1X14, 2),
77 PIXMAP_MBUS_BPP(JPEG_1X8, 1),
80 static const struct dcmipp_byteproc_pix_map *
81 dcmipp_byteproc_pix_map_by_code(u32 code)
85 for (i = 0; i < ARRAY_SIZE(dcmipp_byteproc_pix_map_list); i++) {
86 if (dcmipp_byteproc_pix_map_list[i].code == code)
87 return &dcmipp_byteproc_pix_map_list[i];
93 struct dcmipp_byteproc_device {
94 struct dcmipp_ent_device ved;
95 struct v4l2_subdev sd;
100 static const struct v4l2_mbus_framefmt fmt_default = {
101 .width = DCMIPP_FMT_WIDTH_DEFAULT,
102 .height = DCMIPP_FMT_HEIGHT_DEFAULT,
103 .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
104 .field = V4L2_FIELD_NONE,
105 .colorspace = DCMIPP_COLORSPACE_DEFAULT,
106 .ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT,
107 .quantization = DCMIPP_QUANTIZATION_DEFAULT,
108 .xfer_func = DCMIPP_XFER_FUNC_DEFAULT,
111 static const struct v4l2_rect crop_min = {
112 .width = DCMIPP_FRAME_MIN_WIDTH,
113 .height = DCMIPP_FRAME_MIN_HEIGHT,
118 static void dcmipp_byteproc_adjust_crop(struct v4l2_rect *r,
119 struct v4l2_rect *compose)
121 /* Disallow rectangles smaller than the minimal one. */
122 v4l2_rect_set_min_size(r, &crop_min);
123 v4l2_rect_map_inside(r, compose);
126 static void dcmipp_byteproc_adjust_compose(struct v4l2_rect *r,
127 const struct v4l2_mbus_framefmt *fmt)
132 /* Compose is not possible for JPEG or Bayer formats */
133 if (fmt->code == MEDIA_BUS_FMT_JPEG_1X8 ||
134 fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
135 fmt->code == MEDIA_BUS_FMT_SGBRG8_1X8 ||
136 fmt->code == MEDIA_BUS_FMT_SGRBG8_1X8 ||
137 fmt->code == MEDIA_BUS_FMT_SRGGB8_1X8) {
138 r->width = fmt->width;
139 r->height = fmt->height;
143 /* Adjust height - we can only perform 1/2 decimation */
144 if (r->height <= (fmt->height / 2))
145 r->height = fmt->height / 2;
147 r->height = fmt->height;
149 /* Adjust width /2 or /4 for 8bits formats and /2 for 16bits formats */
150 if (fmt->code == MEDIA_BUS_FMT_Y8_1X8 && r->width <= (fmt->width / 4))
151 r->width = fmt->width / 4;
152 else if (r->width <= (fmt->width / 2))
153 r->width = fmt->width / 2;
155 r->width = fmt->width;
158 static void dcmipp_byteproc_adjust_fmt(struct v4l2_mbus_framefmt *fmt)
160 const struct dcmipp_byteproc_pix_map *vpix;
162 /* Only accept code in the pix map table */
163 vpix = dcmipp_byteproc_pix_map_by_code(fmt->code);
165 fmt->code = fmt_default.code;
167 fmt->width = clamp_t(u32, fmt->width, DCMIPP_FRAME_MIN_WIDTH,
168 DCMIPP_FRAME_MAX_WIDTH) & ~1;
169 fmt->height = clamp_t(u32, fmt->height, DCMIPP_FRAME_MIN_HEIGHT,
170 DCMIPP_FRAME_MAX_HEIGHT) & ~1;
172 if (fmt->field == V4L2_FIELD_ANY || fmt->field == V4L2_FIELD_ALTERNATE)
173 fmt->field = fmt_default.field;
175 dcmipp_colorimetry_clamp(fmt);
178 static int dcmipp_byteproc_init_state(struct v4l2_subdev *sd,
179 struct v4l2_subdev_state *sd_state)
183 for (i = 0; i < sd->entity.num_pads; i++) {
184 struct v4l2_mbus_framefmt *mf;
187 mf = v4l2_subdev_state_get_format(sd_state, i);
191 r = v4l2_subdev_state_get_compose(sd_state, i);
193 r = v4l2_subdev_state_get_crop(sd_state, i);
197 r->width = DCMIPP_FMT_WIDTH_DEFAULT;
198 r->height = DCMIPP_FMT_HEIGHT_DEFAULT;
205 dcmipp_byteproc_enum_mbus_code(struct v4l2_subdev *sd,
206 struct v4l2_subdev_state *sd_state,
207 struct v4l2_subdev_mbus_code_enum *code)
209 const struct dcmipp_byteproc_pix_map *vpix;
210 struct v4l2_mbus_framefmt *sink_fmt;
212 if (IS_SINK(code->pad)) {
213 if (code->index >= ARRAY_SIZE(dcmipp_byteproc_pix_map_list))
215 vpix = &dcmipp_byteproc_pix_map_list[code->index];
216 code->code = vpix->code;
218 /* byteproc doesn't support transformation on format */
222 sink_fmt = v4l2_subdev_state_get_format(sd_state, 0);
223 code->code = sink_fmt->code;
230 dcmipp_byteproc_enum_frame_size(struct v4l2_subdev *sd,
231 struct v4l2_subdev_state *sd_state,
232 struct v4l2_subdev_frame_size_enum *fse)
234 struct v4l2_rect *compose;
239 fse->min_width = DCMIPP_FRAME_MIN_WIDTH;
240 fse->min_height = DCMIPP_FRAME_MIN_HEIGHT;
242 if (IS_SINK(fse->pad)) {
243 fse->max_width = DCMIPP_FRAME_MAX_WIDTH;
244 fse->max_height = DCMIPP_FRAME_MAX_HEIGHT;
246 compose = v4l2_subdev_state_get_compose(sd_state, 0);
247 fse->max_width = compose->width;
248 fse->max_height = compose->height;
254 static int dcmipp_byteproc_set_fmt(struct v4l2_subdev *sd,
255 struct v4l2_subdev_state *sd_state,
256 struct v4l2_subdev_format *fmt)
258 struct v4l2_mbus_framefmt *mf;
259 struct v4l2_rect *crop, *compose;
261 if (v4l2_subdev_is_streaming(sd))
264 mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
266 crop = v4l2_subdev_state_get_crop(sd_state, 1);
267 compose = v4l2_subdev_state_get_compose(sd_state, 0);
269 if (IS_SRC(fmt->pad)) {
270 fmt->format = *v4l2_subdev_state_get_format(sd_state, 0);
271 fmt->format.width = crop->width;
272 fmt->format.height = crop->height;
274 dcmipp_byteproc_adjust_fmt(&fmt->format);
277 crop->width = fmt->format.width;
278 crop->height = fmt->format.height;
280 /* Set the same format on SOURCE pad as well */
281 *v4l2_subdev_state_get_format(sd_state, 1) = fmt->format;
288 static int dcmipp_byteproc_get_selection(struct v4l2_subdev *sd,
289 struct v4l2_subdev_state *sd_state,
290 struct v4l2_subdev_selection *s)
292 struct v4l2_mbus_framefmt *sink_fmt;
293 struct v4l2_rect *crop, *compose;
296 * In the HW, the decimation block is located prior to the crop hence:
297 * Compose is done on the sink pad
298 * Crop is done on the src pad
300 if (IS_SINK(s->pad) &&
301 (s->target == V4L2_SEL_TGT_CROP ||
302 s->target == V4L2_SEL_TGT_CROP_BOUNDS ||
303 s->target == V4L2_SEL_TGT_CROP_DEFAULT))
306 if (IS_SRC(s->pad) &&
307 (s->target == V4L2_SEL_TGT_COMPOSE ||
308 s->target == V4L2_SEL_TGT_COMPOSE_BOUNDS ||
309 s->target == V4L2_SEL_TGT_COMPOSE_DEFAULT))
312 sink_fmt = v4l2_subdev_state_get_format(sd_state, 0);
313 crop = v4l2_subdev_state_get_crop(sd_state, 1);
314 compose = v4l2_subdev_state_get_compose(sd_state, 0);
317 case V4L2_SEL_TGT_CROP:
320 case V4L2_SEL_TGT_CROP_BOUNDS:
321 case V4L2_SEL_TGT_CROP_DEFAULT:
324 case V4L2_SEL_TGT_COMPOSE:
327 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
328 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
331 s->r.width = sink_fmt->width;
332 s->r.height = sink_fmt->height;
341 static int dcmipp_byteproc_set_selection(struct v4l2_subdev *sd,
342 struct v4l2_subdev_state *sd_state,
343 struct v4l2_subdev_selection *s)
345 struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd);
346 struct v4l2_mbus_framefmt *mf;
347 struct v4l2_rect *crop, *compose;
350 * In the HW, the decimation block is located prior to the crop hence:
351 * Compose is done on the sink pad
352 * Crop is done on the src pad
354 if ((s->target == V4L2_SEL_TGT_CROP ||
355 s->target == V4L2_SEL_TGT_CROP_BOUNDS ||
356 s->target == V4L2_SEL_TGT_CROP_DEFAULT) && IS_SINK(s->pad))
359 if ((s->target == V4L2_SEL_TGT_COMPOSE ||
360 s->target == V4L2_SEL_TGT_COMPOSE_BOUNDS ||
361 s->target == V4L2_SEL_TGT_COMPOSE_DEFAULT) && IS_SRC(s->pad))
364 crop = v4l2_subdev_state_get_crop(sd_state, 1);
365 compose = v4l2_subdev_state_get_compose(sd_state, 0);
368 case V4L2_SEL_TGT_CROP:
369 dcmipp_byteproc_adjust_crop(&s->r, compose);
372 mf = v4l2_subdev_state_get_format(sd_state, 1);
373 mf->width = s->r.width;
374 mf->height = s->r.height;
376 dev_dbg(byteproc->dev, "s_selection: crop %ux%u@(%u,%u)\n",
377 crop->width, crop->height, crop->left, crop->top);
379 case V4L2_SEL_TGT_COMPOSE:
380 mf = v4l2_subdev_state_get_format(sd_state, 0);
381 dcmipp_byteproc_adjust_compose(&s->r, mf);
385 mf = v4l2_subdev_state_get_format(sd_state, 1);
386 mf->width = s->r.width;
387 mf->height = s->r.height;
389 dev_dbg(byteproc->dev, "s_selection: compose %ux%u@(%u,%u)\n",
390 compose->width, compose->height,
391 compose->left, compose->top);
400 static int dcmipp_byteproc_configure_scale_crop
401 (struct dcmipp_byteproc_device *byteproc,
402 struct v4l2_subdev_state *state)
404 const struct dcmipp_byteproc_pix_map *vpix;
405 struct v4l2_mbus_framefmt *sink_fmt;
406 u32 hprediv, vprediv;
407 struct v4l2_rect *compose, *crop;
410 sink_fmt = v4l2_subdev_state_get_format(state, 0);
411 compose = v4l2_subdev_state_get_compose(state, 0);
412 crop = v4l2_subdev_state_get_crop(state, 1);
414 /* find output format bpp */
415 vpix = dcmipp_byteproc_pix_map_by_code(sink_fmt->code);
419 /* clear decimation/crop */
420 reg_clear(byteproc, DCMIPP_P0PPCR, DCMIPP_P0PPCR_BSM_MASK);
421 reg_clear(byteproc, DCMIPP_P0PPCR, DCMIPP_P0PPCR_LSM);
422 reg_write(byteproc, DCMIPP_P0SCSTR, 0);
423 reg_write(byteproc, DCMIPP_P0SCSZR, 0);
425 /* Ignore decimation/crop with JPEG */
426 if (vpix->code == MEDIA_BUS_FMT_JPEG_1X8)
430 hprediv = sink_fmt->width / compose->width;
432 val |= DCMIPP_P0PPCR_BSM_1_4 << DCMIPP_P0PPCR_BSM_SHIFT;
433 else if ((vpix->code == MEDIA_BUS_FMT_Y8_1X8) && (hprediv == 2))
434 val |= DCMIPP_P0PPCR_BSM_1_2 << DCMIPP_P0PPCR_BSM_SHIFT;
435 else if (hprediv == 2)
436 val |= DCMIPP_P0PPCR_BSM_2_4 << DCMIPP_P0PPCR_BSM_SHIFT;
438 vprediv = sink_fmt->height / compose->height;
440 val |= DCMIPP_P0PPCR_LSM | DCMIPP_P0PPCR_OELS;
442 /* decimate using bytes and lines skipping */
444 reg_set(byteproc, DCMIPP_P0PPCR, val);
446 dev_dbg(byteproc->dev, "decimate to %dx%d [prediv=%dx%d]\n",
447 compose->width, compose->height,
451 dev_dbg(byteproc->dev, "crop to %dx%d\n", crop->width, crop->height);
453 /* expressed in 32-bits words on X axis, lines on Y axis */
454 reg_write(byteproc, DCMIPP_P0SCSTR,
455 (((crop->left * vpix->bpp) / 4) <<
456 DCMIPP_P0SCSTR_HSTART_SHIFT) |
457 (crop->top << DCMIPP_P0SCSTR_VSTART_SHIFT));
458 reg_write(byteproc, DCMIPP_P0SCSZR,
459 DCMIPP_P0SCSZR_ENABLE |
460 (((crop->width * vpix->bpp) / 4) <<
461 DCMIPP_P0SCSZR_HSIZE_SHIFT) |
462 (crop->height << DCMIPP_P0SCSZR_VSIZE_SHIFT));
467 static int dcmipp_byteproc_enable_streams(struct v4l2_subdev *sd,
468 struct v4l2_subdev_state *state,
469 u32 pad, u64 streams_mask)
471 struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd);
472 struct v4l2_subdev *s_subdev;
473 struct media_pad *s_pad;
476 /* Get source subdev */
477 s_pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
478 if (!s_pad || !is_media_entity_v4l2_subdev(s_pad->entity))
480 s_subdev = media_entity_to_v4l2_subdev(s_pad->entity);
482 ret = dcmipp_byteproc_configure_scale_crop(byteproc, state);
486 ret = v4l2_subdev_enable_streams(s_subdev, s_pad->index, BIT_ULL(0));
488 dev_err(byteproc->dev,
489 "failed to start source subdev streaming (%d)\n", ret);
496 static int dcmipp_byteproc_disable_streams(struct v4l2_subdev *sd,
497 struct v4l2_subdev_state *state,
498 u32 pad, u64 streams_mask)
500 struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd);
501 struct v4l2_subdev *s_subdev;
502 struct media_pad *s_pad;
505 /* Get source subdev */
506 s_pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
507 if (!s_pad || !is_media_entity_v4l2_subdev(s_pad->entity))
509 s_subdev = media_entity_to_v4l2_subdev(s_pad->entity);
511 ret = v4l2_subdev_disable_streams(s_subdev, s_pad->index, BIT_ULL(0));
513 dev_err(byteproc->dev,
514 "failed to start source subdev streaming (%d)\n", ret);
521 static const struct v4l2_subdev_pad_ops dcmipp_byteproc_pad_ops = {
522 .enum_mbus_code = dcmipp_byteproc_enum_mbus_code,
523 .enum_frame_size = dcmipp_byteproc_enum_frame_size,
524 .get_fmt = v4l2_subdev_get_fmt,
525 .set_fmt = dcmipp_byteproc_set_fmt,
526 .get_selection = dcmipp_byteproc_get_selection,
527 .set_selection = dcmipp_byteproc_set_selection,
528 .enable_streams = dcmipp_byteproc_enable_streams,
529 .disable_streams = dcmipp_byteproc_disable_streams,
532 static const struct v4l2_subdev_video_ops dcmipp_byteproc_video_ops = {
533 .s_stream = v4l2_subdev_s_stream_helper,
536 static const struct v4l2_subdev_ops dcmipp_byteproc_ops = {
537 .pad = &dcmipp_byteproc_pad_ops,
538 .video = &dcmipp_byteproc_video_ops,
541 static void dcmipp_byteproc_release(struct v4l2_subdev *sd)
543 struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd);
548 static const struct v4l2_subdev_internal_ops dcmipp_byteproc_int_ops = {
549 .init_state = dcmipp_byteproc_init_state,
550 .release = dcmipp_byteproc_release,
553 void dcmipp_byteproc_ent_release(struct dcmipp_ent_device *ved)
555 struct dcmipp_byteproc_device *byteproc =
556 container_of(ved, struct dcmipp_byteproc_device, ved);
558 dcmipp_ent_sd_unregister(ved, &byteproc->sd);
561 struct dcmipp_ent_device *
562 dcmipp_byteproc_ent_init(struct device *dev, const char *entity_name,
563 struct v4l2_device *v4l2_dev, void __iomem *regs)
565 struct dcmipp_byteproc_device *byteproc;
566 const unsigned long pads_flag[] = {
567 MEDIA_PAD_FL_SINK, MEDIA_PAD_FL_SOURCE,
571 /* Allocate the byteproc struct */
572 byteproc = kzalloc(sizeof(*byteproc), GFP_KERNEL);
574 return ERR_PTR(-ENOMEM);
576 byteproc->regs = regs;
578 /* Initialize ved and sd */
579 ret = dcmipp_ent_sd_register(&byteproc->ved, &byteproc->sd,
580 v4l2_dev, entity_name,
581 MEDIA_ENT_F_PROC_VIDEO_SCALER,
582 ARRAY_SIZE(pads_flag), pads_flag,
583 &dcmipp_byteproc_int_ops,
584 &dcmipp_byteproc_ops,
593 return &byteproc->ved;