1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Driver for STM32 Digital Camera Memory Interface Pixel Processor 4 * 5 * Copyright (C) STMicroelectronics SA 2023 6 * Authors: Hugues Fruchet <hugues.fruchet@foss.st.com> 7 * Alain Volmat <alain.volmat@foss.st.com> 8 * for STMicroelectronics. 9 */ 10 11 #include <linux/vmalloc.h> 12 #include <linux/v4l2-mediabus.h> 13 #include <media/v4l2-rect.h> 14 #include <media/v4l2-subdev.h> 15 16 #include "dcmipp-common.h" 17 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) 35 36 #define IS_SINK(pad) (!(pad)) 37 #define IS_SRC(pad) ((pad)) 38 39 struct dcmipp_byteproc_pix_map { 40 unsigned int code; 41 unsigned int bpp; 42 }; 43 44 #define PIXMAP_MBUS_BPP(mbus, byteperpixel) \ 45 { \ 46 .code = MEDIA_BUS_FMT_##mbus, \ 47 .bpp = byteperpixel, \ 48 } 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(YUYV8_2X8, 2), 52 PIXMAP_MBUS_BPP(YVYU8_2X8, 2), 53 PIXMAP_MBUS_BPP(UYVY8_2X8, 2), 54 PIXMAP_MBUS_BPP(VYUY8_2X8, 2), 55 PIXMAP_MBUS_BPP(Y8_1X8, 1), 56 PIXMAP_MBUS_BPP(SBGGR8_1X8, 1), 57 PIXMAP_MBUS_BPP(SGBRG8_1X8, 1), 58 PIXMAP_MBUS_BPP(SGRBG8_1X8, 1), 59 PIXMAP_MBUS_BPP(SRGGB8_1X8, 1), 60 PIXMAP_MBUS_BPP(JPEG_1X8, 1), 61 }; 62 63 static const struct dcmipp_byteproc_pix_map * 64 dcmipp_byteproc_pix_map_by_code(u32 code) 65 { 66 unsigned int i; 67 68 for (i = 0; i < ARRAY_SIZE(dcmipp_byteproc_pix_map_list); i++) { 69 if (dcmipp_byteproc_pix_map_list[i].code == code) 70 return &dcmipp_byteproc_pix_map_list[i]; 71 } 72 73 return NULL; 74 } 75 76 struct dcmipp_byteproc_device { 77 struct dcmipp_ent_device ved; 78 struct v4l2_subdev sd; 79 struct device *dev; 80 void __iomem *regs; 81 bool streaming; 82 }; 83 84 static const struct v4l2_mbus_framefmt fmt_default = { 85 .width = DCMIPP_FMT_WIDTH_DEFAULT, 86 .height = DCMIPP_FMT_HEIGHT_DEFAULT, 87 .code = MEDIA_BUS_FMT_RGB565_2X8_LE, 88 .field = V4L2_FIELD_NONE, 89 .colorspace = DCMIPP_COLORSPACE_DEFAULT, 90 .ycbcr_enc = DCMIPP_YCBCR_ENC_DEFAULT, 91 .quantization = DCMIPP_QUANTIZATION_DEFAULT, 92 .xfer_func = DCMIPP_XFER_FUNC_DEFAULT, 93 }; 94 95 static const struct v4l2_rect crop_min = { 96 .width = DCMIPP_FRAME_MIN_WIDTH, 97 .height = DCMIPP_FRAME_MIN_HEIGHT, 98 .top = 0, 99 .left = 0, 100 }; 101 102 static void dcmipp_byteproc_adjust_crop(struct v4l2_rect *r, 103 struct v4l2_rect *compose) 104 { 105 /* Disallow rectangles smaller than the minimal one. */ 106 v4l2_rect_set_min_size(r, &crop_min); 107 v4l2_rect_map_inside(r, compose); 108 } 109 110 static void dcmipp_byteproc_adjust_compose(struct v4l2_rect *r, 111 const struct v4l2_mbus_framefmt *fmt) 112 { 113 r->top = 0; 114 r->left = 0; 115 116 /* Compose is not possible for JPEG or Bayer formats */ 117 if (fmt->code == MEDIA_BUS_FMT_JPEG_1X8 || 118 fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 || 119 fmt->code == MEDIA_BUS_FMT_SGBRG8_1X8 || 120 fmt->code == MEDIA_BUS_FMT_SGRBG8_1X8 || 121 fmt->code == MEDIA_BUS_FMT_SRGGB8_1X8) { 122 r->width = fmt->width; 123 r->height = fmt->height; 124 return; 125 } 126 127 /* Adjust height - we can only perform 1/2 decimation */ 128 if (r->height <= (fmt->height / 2)) 129 r->height = fmt->height / 2; 130 else 131 r->height = fmt->height; 132 133 /* Adjust width /2 or /4 for 8bits formats and /2 for 16bits formats */ 134 if (fmt->code == MEDIA_BUS_FMT_Y8_1X8 && r->width <= (fmt->width / 4)) 135 r->width = fmt->width / 4; 136 else if (r->width <= (fmt->width / 2)) 137 r->width = fmt->width / 2; 138 else 139 r->width = fmt->width; 140 } 141 142 static void dcmipp_byteproc_adjust_fmt(struct v4l2_mbus_framefmt *fmt) 143 { 144 const struct dcmipp_byteproc_pix_map *vpix; 145 146 /* Only accept code in the pix map table */ 147 vpix = dcmipp_byteproc_pix_map_by_code(fmt->code); 148 if (!vpix) 149 fmt->code = fmt_default.code; 150 151 fmt->width = clamp_t(u32, fmt->width, DCMIPP_FRAME_MIN_WIDTH, 152 DCMIPP_FRAME_MAX_WIDTH) & ~1; 153 fmt->height = clamp_t(u32, fmt->height, DCMIPP_FRAME_MIN_HEIGHT, 154 DCMIPP_FRAME_MAX_HEIGHT) & ~1; 155 156 if (fmt->field == V4L2_FIELD_ANY || fmt->field == V4L2_FIELD_ALTERNATE) 157 fmt->field = fmt_default.field; 158 159 dcmipp_colorimetry_clamp(fmt); 160 } 161 162 static int dcmipp_byteproc_init_state(struct v4l2_subdev *sd, 163 struct v4l2_subdev_state *sd_state) 164 { 165 unsigned int i; 166 167 for (i = 0; i < sd->entity.num_pads; i++) { 168 struct v4l2_mbus_framefmt *mf; 169 struct v4l2_rect *r; 170 171 mf = v4l2_subdev_state_get_format(sd_state, i); 172 *mf = fmt_default; 173 174 if (IS_SINK(i)) 175 r = v4l2_subdev_state_get_compose(sd_state, i); 176 else 177 r = v4l2_subdev_state_get_crop(sd_state, i); 178 179 r->top = 0; 180 r->left = 0; 181 r->width = DCMIPP_FMT_WIDTH_DEFAULT; 182 r->height = DCMIPP_FMT_HEIGHT_DEFAULT; 183 } 184 185 return 0; 186 } 187 188 static int 189 dcmipp_byteproc_enum_mbus_code(struct v4l2_subdev *sd, 190 struct v4l2_subdev_state *sd_state, 191 struct v4l2_subdev_mbus_code_enum *code) 192 { 193 const struct dcmipp_byteproc_pix_map *vpix; 194 struct v4l2_mbus_framefmt *sink_fmt; 195 196 if (IS_SINK(code->pad)) { 197 if (code->index >= ARRAY_SIZE(dcmipp_byteproc_pix_map_list)) 198 return -EINVAL; 199 vpix = &dcmipp_byteproc_pix_map_list[code->index]; 200 code->code = vpix->code; 201 } else { 202 /* byteproc doesn't support transformation on format */ 203 if (code->index > 0) 204 return -EINVAL; 205 206 sink_fmt = v4l2_subdev_state_get_format(sd_state, 0); 207 code->code = sink_fmt->code; 208 } 209 210 return 0; 211 } 212 213 static int 214 dcmipp_byteproc_enum_frame_size(struct v4l2_subdev *sd, 215 struct v4l2_subdev_state *sd_state, 216 struct v4l2_subdev_frame_size_enum *fse) 217 { 218 struct v4l2_rect *compose; 219 220 if (fse->index) 221 return -EINVAL; 222 223 fse->min_width = DCMIPP_FRAME_MIN_WIDTH; 224 fse->min_height = DCMIPP_FRAME_MIN_HEIGHT; 225 226 if (IS_SINK(fse->pad)) { 227 fse->max_width = DCMIPP_FRAME_MAX_WIDTH; 228 fse->max_height = DCMIPP_FRAME_MAX_HEIGHT; 229 } else { 230 compose = v4l2_subdev_state_get_compose(sd_state, 0); 231 fse->max_width = compose->width; 232 fse->max_height = compose->height; 233 } 234 235 return 0; 236 } 237 238 static int dcmipp_byteproc_set_fmt(struct v4l2_subdev *sd, 239 struct v4l2_subdev_state *sd_state, 240 struct v4l2_subdev_format *fmt) 241 { 242 struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd); 243 struct v4l2_mbus_framefmt *mf; 244 struct v4l2_rect *crop, *compose; 245 246 if (byteproc->streaming) 247 return -EBUSY; 248 249 mf = v4l2_subdev_state_get_format(sd_state, fmt->pad); 250 251 crop = v4l2_subdev_state_get_crop(sd_state, 1); 252 compose = v4l2_subdev_state_get_compose(sd_state, 0); 253 254 if (IS_SRC(fmt->pad)) { 255 fmt->format = *v4l2_subdev_state_get_format(sd_state, 0); 256 fmt->format.width = crop->width; 257 fmt->format.height = crop->height; 258 } else { 259 dcmipp_byteproc_adjust_fmt(&fmt->format); 260 crop->top = 0; 261 crop->left = 0; 262 crop->width = fmt->format.width; 263 crop->height = fmt->format.height; 264 *compose = *crop; 265 /* Set the same format on SOURCE pad as well */ 266 *v4l2_subdev_state_get_format(sd_state, 1) = fmt->format; 267 } 268 *mf = fmt->format; 269 270 return 0; 271 } 272 273 static int dcmipp_byteproc_get_selection(struct v4l2_subdev *sd, 274 struct v4l2_subdev_state *sd_state, 275 struct v4l2_subdev_selection *s) 276 { 277 struct v4l2_mbus_framefmt *sink_fmt; 278 struct v4l2_rect *crop, *compose; 279 280 /* 281 * In the HW, the decimation block is located prior to the crop hence: 282 * Compose is done on the sink pad 283 * Crop is done on the src pad 284 */ 285 if (IS_SINK(s->pad) && 286 (s->target == V4L2_SEL_TGT_CROP || 287 s->target == V4L2_SEL_TGT_CROP_BOUNDS || 288 s->target == V4L2_SEL_TGT_CROP_DEFAULT)) 289 return -EINVAL; 290 291 if (IS_SRC(s->pad) && 292 (s->target == V4L2_SEL_TGT_COMPOSE || 293 s->target == V4L2_SEL_TGT_COMPOSE_BOUNDS || 294 s->target == V4L2_SEL_TGT_COMPOSE_DEFAULT)) 295 return -EINVAL; 296 297 sink_fmt = v4l2_subdev_state_get_format(sd_state, 0); 298 crop = v4l2_subdev_state_get_crop(sd_state, 1); 299 compose = v4l2_subdev_state_get_compose(sd_state, 0); 300 301 switch (s->target) { 302 case V4L2_SEL_TGT_CROP: 303 s->r = *crop; 304 break; 305 case V4L2_SEL_TGT_CROP_BOUNDS: 306 case V4L2_SEL_TGT_CROP_DEFAULT: 307 s->r = *compose; 308 break; 309 case V4L2_SEL_TGT_COMPOSE: 310 s->r = *compose; 311 break; 312 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 313 case V4L2_SEL_TGT_COMPOSE_DEFAULT: 314 s->r.top = 0; 315 s->r.left = 0; 316 s->r.width = sink_fmt->width; 317 s->r.height = sink_fmt->height; 318 break; 319 default: 320 return -EINVAL; 321 } 322 323 return 0; 324 } 325 326 static int dcmipp_byteproc_set_selection(struct v4l2_subdev *sd, 327 struct v4l2_subdev_state *sd_state, 328 struct v4l2_subdev_selection *s) 329 { 330 struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd); 331 struct v4l2_mbus_framefmt *mf; 332 struct v4l2_rect *crop, *compose; 333 334 /* 335 * In the HW, the decimation block is located prior to the crop hence: 336 * Compose is done on the sink pad 337 * Crop is done on the src pad 338 */ 339 if ((s->target == V4L2_SEL_TGT_CROP || 340 s->target == V4L2_SEL_TGT_CROP_BOUNDS || 341 s->target == V4L2_SEL_TGT_CROP_DEFAULT) && IS_SINK(s->pad)) 342 return -EINVAL; 343 344 if ((s->target == V4L2_SEL_TGT_COMPOSE || 345 s->target == V4L2_SEL_TGT_COMPOSE_BOUNDS || 346 s->target == V4L2_SEL_TGT_COMPOSE_DEFAULT) && IS_SRC(s->pad)) 347 return -EINVAL; 348 349 crop = v4l2_subdev_state_get_crop(sd_state, 1); 350 compose = v4l2_subdev_state_get_compose(sd_state, 0); 351 352 switch (s->target) { 353 case V4L2_SEL_TGT_CROP: 354 dcmipp_byteproc_adjust_crop(&s->r, compose); 355 356 *crop = s->r; 357 mf = v4l2_subdev_state_get_format(sd_state, 1); 358 mf->width = s->r.width; 359 mf->height = s->r.height; 360 361 dev_dbg(byteproc->dev, "s_selection: crop %ux%u@(%u,%u)\n", 362 crop->width, crop->height, crop->left, crop->top); 363 break; 364 case V4L2_SEL_TGT_COMPOSE: 365 mf = v4l2_subdev_state_get_format(sd_state, 0); 366 dcmipp_byteproc_adjust_compose(&s->r, mf); 367 *compose = s->r; 368 *crop = s->r; 369 370 mf = v4l2_subdev_state_get_format(sd_state, 1); 371 mf->width = s->r.width; 372 mf->height = s->r.height; 373 374 dev_dbg(byteproc->dev, "s_selection: compose %ux%u@(%u,%u)\n", 375 compose->width, compose->height, 376 compose->left, compose->top); 377 break; 378 default: 379 return -EINVAL; 380 } 381 382 return 0; 383 } 384 385 static const struct v4l2_subdev_pad_ops dcmipp_byteproc_pad_ops = { 386 .enum_mbus_code = dcmipp_byteproc_enum_mbus_code, 387 .enum_frame_size = dcmipp_byteproc_enum_frame_size, 388 .get_fmt = v4l2_subdev_get_fmt, 389 .set_fmt = dcmipp_byteproc_set_fmt, 390 .get_selection = dcmipp_byteproc_get_selection, 391 .set_selection = dcmipp_byteproc_set_selection, 392 }; 393 394 static int dcmipp_byteproc_configure_scale_crop 395 (struct dcmipp_byteproc_device *byteproc) 396 { 397 const struct dcmipp_byteproc_pix_map *vpix; 398 struct v4l2_subdev_state *state; 399 struct v4l2_mbus_framefmt *sink_fmt; 400 u32 hprediv, vprediv; 401 struct v4l2_rect *compose, *crop; 402 u32 val = 0; 403 404 state = v4l2_subdev_lock_and_get_active_state(&byteproc->sd); 405 sink_fmt = v4l2_subdev_state_get_format(state, 0); 406 compose = v4l2_subdev_state_get_compose(state, 0); 407 crop = v4l2_subdev_state_get_crop(state, 1); 408 v4l2_subdev_unlock_state(state); 409 410 /* find output format bpp */ 411 vpix = dcmipp_byteproc_pix_map_by_code(sink_fmt->code); 412 if (!vpix) 413 return -EINVAL; 414 415 /* clear decimation/crop */ 416 reg_clear(byteproc, DCMIPP_P0PPCR, DCMIPP_P0PPCR_BSM_MASK); 417 reg_clear(byteproc, DCMIPP_P0PPCR, DCMIPP_P0PPCR_LSM); 418 reg_write(byteproc, DCMIPP_P0SCSTR, 0); 419 reg_write(byteproc, DCMIPP_P0SCSZR, 0); 420 421 /* Ignore decimation/crop with JPEG */ 422 if (vpix->code == MEDIA_BUS_FMT_JPEG_1X8) 423 return 0; 424 425 /* decimation */ 426 hprediv = sink_fmt->width / compose->width; 427 if (hprediv == 4) 428 val |= DCMIPP_P0PPCR_BSM_1_4 << DCMIPP_P0PPCR_BSM_SHIFT; 429 else if ((vpix->code == MEDIA_BUS_FMT_Y8_1X8) && (hprediv == 2)) 430 val |= DCMIPP_P0PPCR_BSM_1_2 << DCMIPP_P0PPCR_BSM_SHIFT; 431 else if (hprediv == 2) 432 val |= DCMIPP_P0PPCR_BSM_2_4 << DCMIPP_P0PPCR_BSM_SHIFT; 433 434 vprediv = sink_fmt->height / compose->height; 435 if (vprediv == 2) 436 val |= DCMIPP_P0PPCR_LSM | DCMIPP_P0PPCR_OELS; 437 438 /* decimate using bytes and lines skipping */ 439 if (val) { 440 reg_set(byteproc, DCMIPP_P0PPCR, val); 441 442 dev_dbg(byteproc->dev, "decimate to %dx%d [prediv=%dx%d]\n", 443 compose->width, compose->height, 444 hprediv, vprediv); 445 } 446 447 dev_dbg(byteproc->dev, "crop to %dx%d\n", crop->width, crop->height); 448 449 /* expressed in 32-bits words on X axis, lines on Y axis */ 450 reg_write(byteproc, DCMIPP_P0SCSTR, 451 (((crop->left * vpix->bpp) / 4) << 452 DCMIPP_P0SCSTR_HSTART_SHIFT) | 453 (crop->top << DCMIPP_P0SCSTR_VSTART_SHIFT)); 454 reg_write(byteproc, DCMIPP_P0SCSZR, 455 DCMIPP_P0SCSZR_ENABLE | 456 (((crop->width * vpix->bpp) / 4) << 457 DCMIPP_P0SCSZR_HSIZE_SHIFT) | 458 (crop->height << DCMIPP_P0SCSZR_VSIZE_SHIFT)); 459 460 return 0; 461 } 462 463 static int dcmipp_byteproc_s_stream(struct v4l2_subdev *sd, int enable) 464 { 465 struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd); 466 struct v4l2_subdev *s_subdev; 467 struct media_pad *pad; 468 int ret = 0; 469 470 /* Get source subdev */ 471 pad = media_pad_remote_pad_first(&sd->entity.pads[0]); 472 if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) 473 return -EINVAL; 474 s_subdev = media_entity_to_v4l2_subdev(pad->entity); 475 476 if (enable) { 477 ret = dcmipp_byteproc_configure_scale_crop(byteproc); 478 if (ret) 479 return ret; 480 481 ret = v4l2_subdev_call(s_subdev, video, s_stream, enable); 482 if (ret < 0) { 483 dev_err(byteproc->dev, 484 "failed to start source subdev streaming (%d)\n", 485 ret); 486 return ret; 487 } 488 } else { 489 ret = v4l2_subdev_call(s_subdev, video, s_stream, enable); 490 if (ret < 0) { 491 dev_err(byteproc->dev, 492 "failed to stop source subdev streaming (%d)\n", 493 ret); 494 return ret; 495 } 496 } 497 498 byteproc->streaming = enable; 499 500 return 0; 501 } 502 503 static const struct v4l2_subdev_video_ops dcmipp_byteproc_video_ops = { 504 .s_stream = dcmipp_byteproc_s_stream, 505 }; 506 507 static const struct v4l2_subdev_ops dcmipp_byteproc_ops = { 508 .pad = &dcmipp_byteproc_pad_ops, 509 .video = &dcmipp_byteproc_video_ops, 510 }; 511 512 static void dcmipp_byteproc_release(struct v4l2_subdev *sd) 513 { 514 struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd); 515 516 kfree(byteproc); 517 } 518 519 static const struct v4l2_subdev_internal_ops dcmipp_byteproc_int_ops = { 520 .init_state = dcmipp_byteproc_init_state, 521 .release = dcmipp_byteproc_release, 522 }; 523 524 void dcmipp_byteproc_ent_release(struct dcmipp_ent_device *ved) 525 { 526 struct dcmipp_byteproc_device *byteproc = 527 container_of(ved, struct dcmipp_byteproc_device, ved); 528 529 dcmipp_ent_sd_unregister(ved, &byteproc->sd); 530 } 531 532 struct dcmipp_ent_device * 533 dcmipp_byteproc_ent_init(struct device *dev, const char *entity_name, 534 struct v4l2_device *v4l2_dev, void __iomem *regs) 535 { 536 struct dcmipp_byteproc_device *byteproc; 537 const unsigned long pads_flag[] = { 538 MEDIA_PAD_FL_SINK, MEDIA_PAD_FL_SOURCE, 539 }; 540 int ret; 541 542 /* Allocate the byteproc struct */ 543 byteproc = kzalloc(sizeof(*byteproc), GFP_KERNEL); 544 if (!byteproc) 545 return ERR_PTR(-ENOMEM); 546 547 byteproc->regs = regs; 548 549 /* Initialize ved and sd */ 550 ret = dcmipp_ent_sd_register(&byteproc->ved, &byteproc->sd, 551 v4l2_dev, entity_name, 552 MEDIA_ENT_F_PROC_VIDEO_SCALER, 553 ARRAY_SIZE(pads_flag), pads_flag, 554 &dcmipp_byteproc_int_ops, 555 &dcmipp_byteproc_ops, 556 NULL, NULL); 557 if (ret) { 558 kfree(byteproc); 559 return ERR_PTR(ret); 560 } 561 562 byteproc->dev = dev; 563 564 return &byteproc->ved; 565 } 566