1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2025-2026 Pengutronix e.K. 4 * Author: Sven Püschel <s.pueschel@pengutronix.de> 5 */ 6 7 #include <linux/pm_runtime.h> 8 #include <linux/bitfield.h> 9 #include <linux/delay.h> 10 #include <linux/printk.h> 11 12 #include <media/v4l2-common.h> 13 14 #include "rga3-hw.h" 15 #include "rga.h" 16 17 static unsigned int rga3_get_scaling(unsigned int src, unsigned int dst) 18 { 19 /* 20 * RGA3 scaling factor calculation as described in chapter 5.4.7 Resize 21 * of the TRM Part 2. The resulting scaling factor is a 16-bit value 22 * and therefore normalized with 2^16. 23 * 24 * While the TRM also mentions (dst-1)/(src-1) for the up-scaling case, 25 * it didn't work as the value always exceeds 16 bit. Flipping the 26 * factors results in a correct up-scaling. This is possible as the 27 * RGA3 has the RGA3_WIN_SCALE_XXX_UP bit to determine if it does 28 * an up or downscale. 29 * 30 * The scaling factor can potentially cause a slightly larger scaling 31 * (e.g. 1/2px larger scale and then cropped to the destination size). 32 * This can be seen when scaling 128x128px RGBA to 256x256px RGBA. 33 * The RGA2 scaling factor calculation (without the various +/-1 34 * doesn't work for the RGA3. It's assumed that this is an hardware 35 * accuracy limitation, as the vendor kernel driver uses the same 36 * scaling factor calculation. 37 * 38 * With a scaling factor of 1.0 the calculation technically also 39 * overflows 16 bit. This isn't relevant, as in this case the 40 * RGA3_WIN_SCALE_XXX_BYPASS bit completely skips the scaling operation. 41 */ 42 if (dst > src) { 43 if (((src - 1) << 16) % (dst - 1) == 0) 44 return ((src - 1) << 16) / (dst - 1) - 1; 45 else 46 return ((src - 1) << 16) / (dst - 1); 47 } else { 48 return ((dst - 1) << 16) / (src - 1) + 1; 49 } 50 } 51 52 /* 53 * Check if the given format can be captured, as the RGA3 doesn't support all 54 * input formats also on it's output. 55 */ 56 static bool rga3_can_capture(const struct rga3_fmt *fmt) 57 { 58 return fmt->hw_format <= RGA3_COLOR_FMT_LAST_OUTPUT; 59 } 60 61 /* 62 * Map the transformations to the RGA3 command buffer. 63 * Currently this is just the scaling settings and a fixed alpha value. 64 */ 65 static void rga3_cmd_set_trans_info(struct rga_ctx *ctx) 66 { 67 u32 *cmd = ctx->cmdbuf_virt; 68 unsigned int src_h, src_w, dst_h, dst_w; 69 unsigned int reg; 70 u16 hor_scl_fac, ver_scl_fac; 71 const struct rga3_fmt *in = ctx->in.fmt; 72 73 /* Support basic input cropping to support 1088px inputs */ 74 src_h = ctx->in.crop.height; 75 src_w = ctx->in.crop.width; 76 dst_h = ctx->out.pix.height; 77 dst_w = ctx->out.pix.width; 78 79 reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG; 80 cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_SCALE_HOR_UP, dst_w > src_w) 81 | FIELD_PREP(RGA3_WIN_SCALE_HOR_BYPASS, dst_w == src_w) 82 | FIELD_PREP(RGA3_WIN_SCALE_VER_UP, dst_h > src_h) 83 | FIELD_PREP(RGA3_WIN_SCALE_VER_BYPASS, dst_h == src_h); 84 85 hor_scl_fac = rga3_get_scaling(src_w, dst_w); 86 ver_scl_fac = rga3_get_scaling(src_h, dst_h); 87 reg = RGA3_WIN0_SCL_FAC - RGA3_FIRST_CMD_REG; 88 cmd[reg >> 2] = FIELD_PREP(RGA3_SCALE_HOR_FAC, hor_scl_fac) 89 | FIELD_PREP(RGA3_SCALE_VER_FAC, ver_scl_fac); 90 91 if (v4l2_format_info(in->fourcc)->has_alpha) { 92 /* copy alpha from input */ 93 reg = RGA3_OVLP_TOP_ALPHA - RGA3_FIRST_CMD_REG; 94 cmd[reg >> 2] = FIELD_PREP(RGA3_ALPHA_SELECT_MODE, 1) 95 | FIELD_PREP(RGA3_ALPHA_BLEND_MODE, 1); 96 reg = RGA3_OVLP_BOT_ALPHA - RGA3_FIRST_CMD_REG; 97 cmd[reg >> 2] = FIELD_PREP(RGA3_ALPHA_SELECT_MODE, 1) 98 | FIELD_PREP(RGA3_ALPHA_BLEND_MODE, 1); 99 } else { 100 /* just use a 255 alpha value */ 101 reg = RGA3_OVLP_TOP_CTRL - RGA3_FIRST_CMD_REG; 102 cmd[reg >> 2] = FIELD_PREP(RGA3_OVLP_GLOBAL_ALPHA, 0xff) 103 | FIELD_PREP(RGA3_OVLP_COLOR_MODE, 1); 104 reg = RGA3_OVLP_BOT_CTRL - RGA3_FIRST_CMD_REG; 105 cmd[reg >> 2] = FIELD_PREP(RGA3_OVLP_GLOBAL_ALPHA, 0xff) 106 | FIELD_PREP(RGA3_OVLP_COLOR_MODE, 1); 107 } 108 } 109 110 static void rga3_cmd_set_win0_addr(struct rga_ctx *ctx, 111 const struct rga_addrs *addrs) 112 { 113 u32 *cmd = ctx->cmdbuf_virt; 114 unsigned int reg; 115 116 reg = RGA3_WIN0_Y_BASE - RGA3_FIRST_CMD_REG; 117 cmd[reg >> 2] = addrs->y_addr; 118 reg = RGA3_WIN0_U_BASE - RGA3_FIRST_CMD_REG; 119 cmd[reg >> 2] = addrs->u_addr; 120 } 121 122 static void rga3_cmd_set_wr_addr(struct rga_ctx *ctx, 123 const struct rga_addrs *addrs) 124 { 125 u32 *cmd = ctx->cmdbuf_virt; 126 unsigned int reg; 127 128 reg = RGA3_WR_Y_BASE - RGA3_FIRST_CMD_REG; 129 cmd[reg >> 2] = addrs->y_addr; 130 reg = RGA3_WR_U_BASE - RGA3_FIRST_CMD_REG; 131 cmd[reg >> 2] = addrs->u_addr; 132 } 133 134 /* Map the input pixel format to win0 of the comamnd buffer. */ 135 static void rga3_cmd_set_win0_format(struct rga_ctx *ctx) 136 { 137 u32 *cmd = ctx->cmdbuf_virt; 138 const struct rga3_fmt *in = ctx->in.fmt; 139 const struct rga3_fmt *out = ctx->out.fmt; 140 const struct v4l2_format_info *in_fmt, *out_fmt; 141 unsigned int act_h, act_w, src_h, src_w; 142 bool r2y, y2r; 143 u8 rd_format; 144 const struct v4l2_pix_format_mplane *csc_pix; 145 u8 csc_mode; 146 unsigned int reg; 147 148 act_h = ctx->in.pix.height; 149 act_w = ctx->in.pix.width; 150 /* Support basic input cropping to support 1088px inputs */ 151 src_h = ctx->in.crop.height; 152 src_w = ctx->in.crop.width; 153 154 in_fmt = v4l2_format_info(in->fourcc); 155 out_fmt = v4l2_format_info(out->fourcc); 156 r2y = v4l2_is_format_rgb(in_fmt) && v4l2_is_format_yuv(out_fmt); 157 y2r = v4l2_is_format_yuv(in_fmt) && v4l2_is_format_rgb(out_fmt); 158 159 /* The Hardware only supports formats with 1/2 planes */ 160 if (in_fmt->comp_planes == 2) 161 rd_format = RGA3_RDWR_FORMAT_SEMI_PLANAR; 162 else 163 rd_format = RGA3_RDWR_FORMAT_INTERLEAVED; 164 165 /* set pixel format and CSC */ 166 csc_pix = r2y ? &ctx->out.pix : &ctx->in.pix; 167 switch (csc_pix->ycbcr_enc) { 168 case V4L2_YCBCR_ENC_BT2020: 169 csc_mode = RGA3_WIN_CSC_MODE_BT2020_L; 170 break; 171 case V4L2_YCBCR_ENC_709: 172 csc_mode = RGA3_WIN_CSC_MODE_BT709_L; 173 break; 174 default: /* should be fixed to BT601 in adjust_and_map_format */ 175 if (csc_pix->quantization == V4L2_QUANTIZATION_LIM_RANGE) 176 csc_mode = RGA3_WIN_CSC_MODE_BT601_L; 177 else 178 csc_mode = RGA3_WIN_CSC_MODE_BT601_F; 179 break; 180 } 181 182 reg = RGA3_WIN0_RD_CTRL - RGA3_FIRST_CMD_REG; 183 cmd[reg >> 2] |= FIELD_PREP(RGA3_WIN_ENABLE, 1) 184 | FIELD_PREP(RGA3_WIN_PIC_FORMAT, in->hw_format) 185 | FIELD_PREP(RGA3_WIN_YC_SWAP, in->yc_swap) 186 | FIELD_PREP(RGA3_WIN_RBUV_SWAP, in->rbuv_swap) 187 | FIELD_PREP(RGA3_WIN_RD_FORMAT, rd_format) 188 | FIELD_PREP(RGA3_WIN_R2Y, r2y) 189 | FIELD_PREP(RGA3_WIN_Y2R, y2r) 190 | FIELD_PREP(RGA3_WIN_CSC_MODE, csc_mode); 191 192 /* set stride */ 193 reg = RGA3_WIN0_VIR_STRIDE - RGA3_FIRST_CMD_REG; 194 /* stride needs to be in words */ 195 cmd[reg >> 2] = ctx->in.pix.plane_fmt[0].bytesperline >> 2; 196 reg = RGA3_WIN0_UV_VIR_STRIDE - RGA3_FIRST_CMD_REG; 197 /* The Hardware only supports formats with 1/2 planes */ 198 if (ctx->in.pix.num_planes == 2) 199 cmd[reg >> 2] = ctx->in.pix.plane_fmt[1].bytesperline >> 2; 200 else 201 cmd[reg >> 2] = ctx->in.pix.plane_fmt[0].bytesperline >> 2; 202 203 /* set size */ 204 reg = RGA3_WIN0_ACT_SIZE - RGA3_FIRST_CMD_REG; 205 cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, act_w) 206 | FIELD_PREP(RGA3_HEIGHT, act_h); 207 reg = RGA3_WIN0_SRC_SIZE - RGA3_FIRST_CMD_REG; 208 cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, src_w) 209 | FIELD_PREP(RGA3_HEIGHT, src_h); 210 } 211 212 /* Map the output pixel format to the command buffer */ 213 static void rga3_cmd_set_wr_format(struct rga_ctx *ctx) 214 { 215 u32 *cmd = ctx->cmdbuf_virt; 216 const struct rga3_fmt *out = ctx->out.fmt; 217 const struct v4l2_format_info *out_fmt; 218 unsigned int dst_h, dst_w; 219 u8 wr_format; 220 unsigned int reg; 221 222 dst_h = ctx->out.pix.height; 223 dst_w = ctx->out.pix.width; 224 225 out_fmt = v4l2_format_info(out->fourcc); 226 227 /* The Hardware only supports formats with 1/2 planes */ 228 if (out_fmt->comp_planes == 2) 229 wr_format = RGA3_RDWR_FORMAT_SEMI_PLANAR; 230 else 231 wr_format = RGA3_RDWR_FORMAT_INTERLEAVED; 232 233 /* set pixel format */ 234 reg = RGA3_WR_CTRL - RGA3_FIRST_CMD_REG; 235 cmd[reg >> 2] = FIELD_PREP(RGA3_WR_PIC_FORMAT, out->hw_format) 236 | FIELD_PREP(RGA3_WR_YC_SWAP, out->yc_swap) 237 | FIELD_PREP(RGA3_WR_RBUV_SWAP, out->rbuv_swap) 238 | FIELD_PREP(RGA3_WR_FORMAT, wr_format) 239 /* Use the max value to avoid limiting the write speed */ 240 | FIELD_PREP(RGA3_WR_SW_OUTSTANDING_MAX, 63); 241 242 /* set stride */ 243 reg = RGA3_WR_VIR_STRIDE - RGA3_FIRST_CMD_REG; 244 /* stride needs to be in words */ 245 cmd[reg >> 2] = ctx->out.pix.plane_fmt[0].bytesperline >> 2; 246 reg = RGA3_WR_PL_VIR_STRIDE - RGA3_FIRST_CMD_REG; 247 /* The Hardware only supports formats with 1/2 planes */ 248 if (ctx->out.pix.num_planes == 2) 249 cmd[reg >> 2] = ctx->out.pix.plane_fmt[1].bytesperline >> 2; 250 else 251 cmd[reg >> 2] = ctx->out.pix.plane_fmt[0].bytesperline >> 2; 252 253 /* Set size. 254 * As two inputs are not supported, we don't use win1. 255 * Therefore only set the size for win0. 256 */ 257 reg = RGA3_WIN0_DST_SIZE - RGA3_FIRST_CMD_REG; 258 cmd[reg >> 2] = FIELD_PREP(RGA3_WIDTH, dst_w) 259 | FIELD_PREP(RGA3_HEIGHT, dst_h); 260 } 261 262 static void rga3_hw_setup_cmdbuf(struct rga_ctx *ctx) 263 { 264 memset(ctx->cmdbuf_virt, 0, RGA3_CMDBUF_SIZE); 265 266 rga3_cmd_set_win0_format(ctx); 267 rga3_cmd_set_trans_info(ctx); 268 rga3_cmd_set_wr_format(ctx); 269 } 270 271 static void rga3_hw_start(struct rockchip_rga *rga, 272 struct rga_vb_buffer *src, struct rga_vb_buffer *dst) 273 { 274 struct rga_ctx *ctx = rga->curr; 275 276 rga3_cmd_set_win0_addr(ctx, &src->dma_addrs); 277 rga3_cmd_set_wr_addr(ctx, &dst->dma_addrs); 278 279 rga_write(rga, RGA3_CMD_ADDR, ctx->cmdbuf_phy); 280 281 /* sync CMD buf for RGA */ 282 dma_sync_single_for_device(rga->dev, ctx->cmdbuf_phy, 283 PAGE_SIZE, DMA_BIDIRECTIONAL); 284 285 /* set to master mode and start the conversion */ 286 rga_write(rga, RGA3_SYS_CTRL, 287 FIELD_PREP(RGA3_CMD_MODE, RGA3_CMD_MODE_MASTER)); 288 rga_write(rga, RGA3_INT_EN, FIELD_PREP(RGA3_INT_FRM_DONE, 1)); 289 rga_write(rga, RGA3_CMD_CTRL, 290 FIELD_PREP(RGA3_CMD_LINE_START_PULSE, 1)); 291 } 292 293 static bool rga3_handle_irq(struct rockchip_rga *rga) 294 { 295 u32 intr; 296 297 intr = rga_read(rga, RGA3_INT_RAW); 298 /* clear all interrupts */ 299 rga_write(rga, RGA3_INT_CLR, intr); 300 301 return FIELD_GET(RGA3_INT_FRM_DONE, intr); 302 } 303 304 static void rga3_get_version(struct rockchip_rga *rga) 305 { 306 u32 version = rga_read(rga, RGA3_VERSION_NUM); 307 308 rga->version.major = FIELD_GET(RGA3_VERSION_NUM_MAJOR, version); 309 rga->version.minor = FIELD_GET(RGA3_VERSION_NUM_MINOR, version); 310 } 311 312 static struct rga3_fmt rga3_formats[] = { 313 { 314 .fourcc = V4L2_PIX_FMT_RGB24, 315 .hw_format = RGA3_COLOR_FMT_BGR888, 316 .rbuv_swap = 1, 317 }, 318 { 319 .fourcc = V4L2_PIX_FMT_BGR24, 320 .hw_format = RGA3_COLOR_FMT_BGR888, 321 }, 322 { 323 .fourcc = V4L2_PIX_FMT_ABGR32, 324 .hw_format = RGA3_COLOR_FMT_BGRA8888, 325 }, 326 { 327 .fourcc = V4L2_PIX_FMT_RGBA32, 328 .hw_format = RGA3_COLOR_FMT_BGRA8888, 329 .rbuv_swap = 1, 330 }, 331 { 332 .fourcc = V4L2_PIX_FMT_XBGR32, 333 .hw_format = RGA3_COLOR_FMT_BGRA8888, 334 }, 335 { 336 .fourcc = V4L2_PIX_FMT_RGBX32, 337 .hw_format = RGA3_COLOR_FMT_BGRA8888, 338 .rbuv_swap = 1, 339 }, 340 { 341 .fourcc = V4L2_PIX_FMT_RGB565, 342 .hw_format = RGA3_COLOR_FMT_BGR565, 343 .rbuv_swap = 1, 344 }, 345 { 346 .fourcc = V4L2_PIX_FMT_NV12M, 347 .hw_format = RGA3_COLOR_FMT_YUV420, 348 }, 349 { 350 .fourcc = V4L2_PIX_FMT_NV12, 351 .hw_format = RGA3_COLOR_FMT_YUV420, 352 }, 353 { 354 .fourcc = V4L2_PIX_FMT_NV21M, 355 .hw_format = RGA3_COLOR_FMT_YUV420, 356 .rbuv_swap = 1, 357 }, 358 { 359 .fourcc = V4L2_PIX_FMT_NV21, 360 .hw_format = RGA3_COLOR_FMT_YUV420, 361 .rbuv_swap = 1, 362 }, 363 { 364 .fourcc = V4L2_PIX_FMT_NV16M, 365 .hw_format = RGA3_COLOR_FMT_YUV422, 366 }, 367 { 368 .fourcc = V4L2_PIX_FMT_NV16, 369 .hw_format = RGA3_COLOR_FMT_YUV422, 370 }, 371 { 372 .fourcc = V4L2_PIX_FMT_NV61M, 373 .hw_format = RGA3_COLOR_FMT_YUV422, 374 .rbuv_swap = 1, 375 }, 376 { 377 .fourcc = V4L2_PIX_FMT_NV61, 378 .hw_format = RGA3_COLOR_FMT_YUV422, 379 .rbuv_swap = 1, 380 }, 381 { 382 .fourcc = V4L2_PIX_FMT_YUYV, 383 .hw_format = RGA3_COLOR_FMT_YUV422, 384 .yc_swap = 1, 385 }, 386 { 387 .fourcc = V4L2_PIX_FMT_YVYU, 388 .hw_format = RGA3_COLOR_FMT_YUV422, 389 .yc_swap = 1, 390 .rbuv_swap = 1, 391 }, 392 { 393 .fourcc = V4L2_PIX_FMT_UYVY, 394 .hw_format = RGA3_COLOR_FMT_YUV422, 395 }, 396 { 397 .fourcc = V4L2_PIX_FMT_VYUY, 398 .hw_format = RGA3_COLOR_FMT_YUV422, 399 .rbuv_swap = 1, 400 }, 401 /* Input only formats last to keep rga3_enum_format simple */ 402 { 403 .fourcc = V4L2_PIX_FMT_ARGB32, 404 .hw_format = RGA3_COLOR_FMT_ABGR8888, 405 .rbuv_swap = 1, 406 }, 407 { 408 .fourcc = V4L2_PIX_FMT_BGRA32, 409 .hw_format = RGA3_COLOR_FMT_ABGR8888, 410 }, 411 { 412 .fourcc = V4L2_PIX_FMT_XRGB32, 413 .hw_format = RGA3_COLOR_FMT_ABGR8888, 414 .rbuv_swap = 1, 415 }, 416 { 417 .fourcc = V4L2_PIX_FMT_BGRX32, 418 .hw_format = RGA3_COLOR_FMT_ABGR8888, 419 }, 420 }; 421 422 static int rga3_enum_format(struct v4l2_fmtdesc *f) 423 { 424 struct rga3_fmt *fmt; 425 426 if (f->index >= ARRAY_SIZE(rga3_formats)) 427 return -EINVAL; 428 429 fmt = &rga3_formats[f->index]; 430 if (V4L2_TYPE_IS_CAPTURE(f->type) && !rga3_can_capture(fmt)) 431 return -EINVAL; 432 433 f->pixelformat = fmt->fourcc; 434 return 0; 435 } 436 437 static void *rga3_adjust_and_map_format(struct rga_ctx *ctx, 438 struct v4l2_pix_format_mplane *format, 439 bool is_output) 440 { 441 unsigned int i; 442 const struct v4l2_format_info *format_info; 443 const struct v4l2_pix_format_mplane *other_format; 444 const struct v4l2_format_info *other_format_info; 445 446 if (!format) 447 return &rga3_formats[0]; 448 449 format_info = v4l2_format_info(format->pixelformat); 450 other_format = is_output ? &ctx->out.pix : &ctx->in.pix; 451 other_format_info = v4l2_format_info(other_format->pixelformat); 452 453 /* 454 * Only apply the quantization restrictions when we need to 455 * convert between RGB and YUV. Otherwise there is no point 456 * to limit the quantization for operations like scaling or 457 * rotations. 458 */ 459 if (v4l2_is_format_yuv(format_info) && 460 v4l2_is_format_rgb(other_format_info)) { 461 /* 462 * The RGA3 only supports BT601, BT709 and BT2020 RGB<->YUV conversions 463 * Additionally BT709 and BT2020 only support limited range YUV. 464 */ 465 switch (format->ycbcr_enc) { 466 case V4L2_YCBCR_ENC_601: 467 /* supports full and limited range */ 468 break; 469 case V4L2_YCBCR_ENC_709: 470 case V4L2_YCBCR_ENC_BT2020: 471 format->quantization = V4L2_QUANTIZATION_LIM_RANGE; 472 break; 473 default: 474 format->ycbcr_enc = V4L2_YCBCR_ENC_601; 475 format->quantization = V4L2_QUANTIZATION_FULL_RANGE; 476 break; 477 } 478 } 479 480 for (i = 0; i < ARRAY_SIZE(rga3_formats); i++) { 481 if (!is_output && !rga3_can_capture(&rga3_formats[i])) 482 continue; 483 484 if (rga3_formats[i].fourcc == format->pixelformat) 485 return &rga3_formats[i]; 486 } 487 488 format->pixelformat = rga3_formats[0].fourcc; 489 return &rga3_formats[0]; 490 } 491 492 const struct rga_hw rga3_hw = { 493 .card_type = "rga3", 494 .has_internal_iommu = false, 495 .cmdbuf_size = RGA3_CMDBUF_SIZE, 496 .min_width = RGA3_MIN_WIDTH, 497 .min_height = RGA3_MIN_HEIGHT, 498 /* use output size, as it's a bit smaller than the input size */ 499 .max_width = RGA3_MAX_OUTPUT_WIDTH, 500 .max_height = RGA3_MAX_OUTPUT_HEIGHT, 501 .max_scaling_factor = RGA3_MAX_SCALING_FACTOR, 502 .stride_alignment = 16, 503 .features = 0, 504 505 .setup_cmdbuf = rga3_hw_setup_cmdbuf, 506 .start = rga3_hw_start, 507 .handle_irq = rga3_handle_irq, 508 .get_version = rga3_get_version, 509 .enum_format = rga3_enum_format, 510 .adjust_and_map_format = rga3_adjust_and_map_format, 511 }; 512