1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * i.MX Pixel Pipeline (PXP) mem-to-mem scaler/CSC/rotator driver 4 * 5 * Copyright (c) 2018 Pengutronix, Philipp Zabel 6 * 7 * based on vim2m 8 * 9 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. 10 * Pawel Osciak, <pawel@osciak.com> 11 * Marek Szyprowski, <m.szyprowski@samsung.com> 12 */ 13 #include <linux/bitfield.h> 14 #include <linux/clk.h> 15 #include <linux/delay.h> 16 #include <linux/dma-mapping.h> 17 #include <linux/interrupt.h> 18 #include <linux/io.h> 19 #include <linux/iopoll.h> 20 #include <linux/module.h> 21 #include <linux/of.h> 22 #include <linux/of_device.h> 23 #include <linux/platform_device.h> 24 #include <linux/regmap.h> 25 #include <linux/sched.h> 26 #include <linux/slab.h> 27 28 #include <media/media-device.h> 29 #include <media/v4l2-ctrls.h> 30 #include <media/v4l2-device.h> 31 #include <media/v4l2-event.h> 32 #include <media/v4l2-ioctl.h> 33 #include <media/v4l2-mem2mem.h> 34 #include <media/videobuf2-dma-contig.h> 35 36 #include "imx-pxp.h" 37 38 static unsigned int debug; 39 module_param(debug, uint, 0644); 40 MODULE_PARM_DESC(debug, "activates debug info"); 41 42 #define MIN_W 8 43 #define MIN_H 8 44 #define MAX_W 4096 45 #define MAX_H 4096 46 #define ALIGN_W 3 /* 8x8 pixel blocks */ 47 #define ALIGN_H 3 48 49 /* Flags that indicate a format can be used for capture/output */ 50 #define MEM2MEM_CAPTURE (1 << 0) 51 #define MEM2MEM_OUTPUT (1 << 1) 52 53 #define MEM2MEM_NAME "pxp" 54 55 /* Flags that indicate processing mode */ 56 #define MEM2MEM_HFLIP (1 << 0) 57 #define MEM2MEM_VFLIP (1 << 1) 58 59 #define PXP_VERSION_MAJOR(version) \ 60 FIELD_GET(BM_PXP_VERSION_MAJOR, version) 61 #define PXP_VERSION_MINOR(version) \ 62 FIELD_GET(BM_PXP_VERSION_MINOR, version) 63 64 #define dprintk(dev, fmt, arg...) \ 65 v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) 66 67 struct pxp_fmt { 68 u32 fourcc; 69 int depth; 70 /* Types the format can be used for */ 71 u32 types; 72 }; 73 74 static struct pxp_fmt formats[] = { 75 { 76 .fourcc = V4L2_PIX_FMT_XBGR32, 77 .depth = 32, 78 /* Both capture and output format */ 79 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 80 }, { 81 .fourcc = V4L2_PIX_FMT_ABGR32, 82 .depth = 32, 83 /* Capture-only format */ 84 .types = MEM2MEM_CAPTURE, 85 }, { 86 .fourcc = V4L2_PIX_FMT_BGR24, 87 .depth = 24, 88 .types = MEM2MEM_CAPTURE, 89 }, { 90 .fourcc = V4L2_PIX_FMT_RGB565, 91 .depth = 16, 92 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 93 }, { 94 .fourcc = V4L2_PIX_FMT_RGB555, 95 .depth = 16, 96 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 97 }, { 98 .fourcc = V4L2_PIX_FMT_RGB444, 99 .depth = 16, 100 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 101 }, { 102 .fourcc = V4L2_PIX_FMT_VUYA32, 103 .depth = 32, 104 .types = MEM2MEM_CAPTURE, 105 }, { 106 .fourcc = V4L2_PIX_FMT_VUYX32, 107 .depth = 32, 108 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 109 }, { 110 .fourcc = V4L2_PIX_FMT_UYVY, 111 .depth = 16, 112 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 113 }, { 114 .fourcc = V4L2_PIX_FMT_YUYV, 115 .depth = 16, 116 /* Output-only format */ 117 .types = MEM2MEM_OUTPUT, 118 }, { 119 .fourcc = V4L2_PIX_FMT_VYUY, 120 .depth = 16, 121 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 122 }, { 123 .fourcc = V4L2_PIX_FMT_YVYU, 124 .depth = 16, 125 .types = MEM2MEM_OUTPUT, 126 }, { 127 .fourcc = V4L2_PIX_FMT_GREY, 128 .depth = 8, 129 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 130 }, { 131 .fourcc = V4L2_PIX_FMT_Y4, 132 .depth = 4, 133 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 134 }, { 135 .fourcc = V4L2_PIX_FMT_NV16, 136 .depth = 16, 137 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 138 }, { 139 .fourcc = V4L2_PIX_FMT_NV12, 140 .depth = 12, 141 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 142 }, { 143 .fourcc = V4L2_PIX_FMT_NV21, 144 .depth = 12, 145 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 146 }, { 147 .fourcc = V4L2_PIX_FMT_NV61, 148 .depth = 16, 149 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, 150 }, { 151 .fourcc = V4L2_PIX_FMT_YUV422P, 152 .depth = 16, 153 .types = MEM2MEM_OUTPUT, 154 }, { 155 .fourcc = V4L2_PIX_FMT_YUV420, 156 .depth = 12, 157 .types = MEM2MEM_OUTPUT, 158 }, 159 }; 160 161 #define NUM_FORMATS ARRAY_SIZE(formats) 162 163 /* Per-queue, driver-specific private data */ 164 struct pxp_q_data { 165 unsigned int width; 166 unsigned int height; 167 unsigned int bytesperline; 168 unsigned int sizeimage; 169 unsigned int sequence; 170 struct pxp_fmt *fmt; 171 enum v4l2_ycbcr_encoding ycbcr_enc; 172 enum v4l2_quantization quant; 173 }; 174 175 enum { 176 V4L2_M2M_SRC = 0, 177 V4L2_M2M_DST = 1, 178 }; 179 180 static const struct regmap_config pxp_regmap_config = { 181 .reg_bits = 32, 182 .reg_stride = 4, 183 .val_bits = 32, 184 .max_register = HW_PXP_VERSION, 185 }; 186 187 static struct pxp_fmt *find_format(unsigned int pixelformat) 188 { 189 struct pxp_fmt *fmt; 190 unsigned int k; 191 192 for (k = 0; k < NUM_FORMATS; k++) { 193 fmt = &formats[k]; 194 if (fmt->fourcc == pixelformat) 195 break; 196 } 197 198 if (k == NUM_FORMATS) 199 return NULL; 200 201 return &formats[k]; 202 } 203 204 struct pxp_ctx; 205 206 struct pxp_pdata { 207 u32 (*data_path_ctrl0)(struct pxp_ctx *ctx); 208 }; 209 210 struct pxp_dev { 211 struct v4l2_device v4l2_dev; 212 struct video_device vfd; 213 #ifdef CONFIG_MEDIA_CONTROLLER 214 struct media_device mdev; 215 #endif 216 217 struct clk *clk; 218 struct regmap *regmap; 219 220 const struct pxp_pdata *pdata; 221 222 atomic_t num_inst; 223 struct mutex dev_mutex; 224 spinlock_t irqlock; 225 226 struct v4l2_m2m_dev *m2m_dev; 227 }; 228 229 struct pxp_ctx { 230 struct v4l2_fh fh; 231 struct pxp_dev *dev; 232 233 struct v4l2_ctrl_handler hdl; 234 235 /* Abort requested by m2m */ 236 int aborting; 237 238 /* Processing mode */ 239 int mode; 240 u8 alpha_component; 241 u8 rotation; 242 243 enum v4l2_colorspace colorspace; 244 enum v4l2_xfer_func xfer_func; 245 246 /* Source and destination queue data */ 247 struct pxp_q_data q_data[2]; 248 }; 249 250 static inline struct pxp_ctx *file2ctx(struct file *file) 251 { 252 return container_of(file->private_data, struct pxp_ctx, fh); 253 } 254 255 static struct pxp_q_data *get_q_data(struct pxp_ctx *ctx, 256 enum v4l2_buf_type type) 257 { 258 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 259 return &ctx->q_data[V4L2_M2M_SRC]; 260 else 261 return &ctx->q_data[V4L2_M2M_DST]; 262 } 263 264 static inline u32 pxp_read(struct pxp_dev *dev, u32 reg) 265 { 266 u32 value; 267 268 regmap_read(dev->regmap, reg, &value); 269 270 return value; 271 } 272 273 static inline void pxp_write(struct pxp_dev *dev, u32 reg, u32 value) 274 { 275 regmap_write(dev->regmap, reg, value); 276 } 277 278 static u32 pxp_v4l2_pix_fmt_to_ps_format(u32 v4l2_pix_fmt) 279 { 280 switch (v4l2_pix_fmt) { 281 case V4L2_PIX_FMT_XBGR32: return BV_PXP_PS_CTRL_FORMAT__RGB888; 282 case V4L2_PIX_FMT_RGB555: return BV_PXP_PS_CTRL_FORMAT__RGB555; 283 case V4L2_PIX_FMT_RGB444: return BV_PXP_PS_CTRL_FORMAT__RGB444; 284 case V4L2_PIX_FMT_RGB565: return BV_PXP_PS_CTRL_FORMAT__RGB565; 285 case V4L2_PIX_FMT_VUYX32: return BV_PXP_PS_CTRL_FORMAT__YUV1P444; 286 case V4L2_PIX_FMT_UYVY: return BV_PXP_PS_CTRL_FORMAT__UYVY1P422; 287 case V4L2_PIX_FMT_YUYV: return BM_PXP_PS_CTRL_WB_SWAP | 288 BV_PXP_PS_CTRL_FORMAT__UYVY1P422; 289 case V4L2_PIX_FMT_VYUY: return BV_PXP_PS_CTRL_FORMAT__VYUY1P422; 290 case V4L2_PIX_FMT_YVYU: return BM_PXP_PS_CTRL_WB_SWAP | 291 BV_PXP_PS_CTRL_FORMAT__VYUY1P422; 292 case V4L2_PIX_FMT_GREY: return BV_PXP_PS_CTRL_FORMAT__Y8; 293 default: 294 case V4L2_PIX_FMT_Y4: return BV_PXP_PS_CTRL_FORMAT__Y4; 295 case V4L2_PIX_FMT_NV16: return BV_PXP_PS_CTRL_FORMAT__YUV2P422; 296 case V4L2_PIX_FMT_NV12: return BV_PXP_PS_CTRL_FORMAT__YUV2P420; 297 case V4L2_PIX_FMT_NV21: return BV_PXP_PS_CTRL_FORMAT__YVU2P420; 298 case V4L2_PIX_FMT_NV61: return BV_PXP_PS_CTRL_FORMAT__YVU2P422; 299 case V4L2_PIX_FMT_YUV422P: return BV_PXP_PS_CTRL_FORMAT__YUV422; 300 case V4L2_PIX_FMT_YUV420: return BV_PXP_PS_CTRL_FORMAT__YUV420; 301 } 302 } 303 304 static u32 pxp_v4l2_pix_fmt_to_out_format(u32 v4l2_pix_fmt) 305 { 306 switch (v4l2_pix_fmt) { 307 case V4L2_PIX_FMT_XBGR32: return BV_PXP_OUT_CTRL_FORMAT__RGB888; 308 case V4L2_PIX_FMT_ABGR32: return BV_PXP_OUT_CTRL_FORMAT__ARGB8888; 309 case V4L2_PIX_FMT_BGR24: return BV_PXP_OUT_CTRL_FORMAT__RGB888P; 310 /* Missing V4L2 pixel formats for ARGB1555 and ARGB4444 */ 311 case V4L2_PIX_FMT_RGB555: return BV_PXP_OUT_CTRL_FORMAT__RGB555; 312 case V4L2_PIX_FMT_RGB444: return BV_PXP_OUT_CTRL_FORMAT__RGB444; 313 case V4L2_PIX_FMT_RGB565: return BV_PXP_OUT_CTRL_FORMAT__RGB565; 314 case V4L2_PIX_FMT_VUYA32: 315 case V4L2_PIX_FMT_VUYX32: return BV_PXP_OUT_CTRL_FORMAT__YUV1P444; 316 case V4L2_PIX_FMT_UYVY: return BV_PXP_OUT_CTRL_FORMAT__UYVY1P422; 317 case V4L2_PIX_FMT_VYUY: return BV_PXP_OUT_CTRL_FORMAT__VYUY1P422; 318 case V4L2_PIX_FMT_GREY: return BV_PXP_OUT_CTRL_FORMAT__Y8; 319 default: 320 case V4L2_PIX_FMT_Y4: return BV_PXP_OUT_CTRL_FORMAT__Y4; 321 case V4L2_PIX_FMT_NV16: return BV_PXP_OUT_CTRL_FORMAT__YUV2P422; 322 case V4L2_PIX_FMT_NV12: return BV_PXP_OUT_CTRL_FORMAT__YUV2P420; 323 case V4L2_PIX_FMT_NV61: return BV_PXP_OUT_CTRL_FORMAT__YVU2P422; 324 case V4L2_PIX_FMT_NV21: return BV_PXP_OUT_CTRL_FORMAT__YVU2P420; 325 } 326 } 327 328 static bool pxp_v4l2_pix_fmt_is_yuv(u32 v4l2_pix_fmt) 329 { 330 switch (v4l2_pix_fmt) { 331 case V4L2_PIX_FMT_VUYA32: 332 case V4L2_PIX_FMT_VUYX32: 333 case V4L2_PIX_FMT_UYVY: 334 case V4L2_PIX_FMT_YUYV: 335 case V4L2_PIX_FMT_VYUY: 336 case V4L2_PIX_FMT_YVYU: 337 case V4L2_PIX_FMT_NV16: 338 case V4L2_PIX_FMT_NV12: 339 case V4L2_PIX_FMT_NV61: 340 case V4L2_PIX_FMT_NV21: 341 case V4L2_PIX_FMT_YUV420: 342 case V4L2_PIX_FMT_YUV422P: 343 case V4L2_PIX_FMT_GREY: 344 case V4L2_PIX_FMT_Y4: 345 return true; 346 default: 347 return false; 348 } 349 } 350 351 static void pxp_setup_csc(struct pxp_ctx *ctx) 352 { 353 struct pxp_dev *dev = ctx->dev; 354 enum v4l2_ycbcr_encoding ycbcr_enc; 355 enum v4l2_quantization quantization; 356 357 if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) && 358 !pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) { 359 /* 360 * CSC1 YUV/YCbCr to RGB conversion is implemented as follows: 361 * 362 * |R| |C0 0 C1| |Y + Yoffset | 363 * |G| = |C0 C3 C2| * |Cb + UVoffset| 364 * |B| |C0 C4 0 | |Cr + UVoffset| 365 * 366 * Results are clamped to 0..255. 367 * 368 * BT.601 limited range: 369 * 370 * |R| |1.1644 0.0000 1.5960| |Y - 16 | 371 * |G| = |1.1644 -0.3917 -0.8129| * |Cb - 128| 372 * |B| |1.1644 2.0172 0.0000| |Cr - 128| 373 */ 374 static const u32 csc1_coef_bt601_lim[3] = { 375 BM_PXP_CSC1_COEF0_YCBCR_MODE | 376 BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */ 377 BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | 378 BF_PXP_CSC1_COEF0_Y_OFFSET(-16), 379 BF_PXP_CSC1_COEF1_C1(0x198) | /* 1.5938 (-0.23 %) */ 380 BF_PXP_CSC1_COEF1_C4(0x204), /* 2.0156 (-0.16 %) */ 381 BF_PXP_CSC1_COEF2_C2(0x730) | /* -0.8125 (+0.04 %) */ 382 BF_PXP_CSC1_COEF2_C3(0x79c), /* -0.3906 (+0.11 %) */ 383 }; 384 /* 385 * BT.601 full range: 386 * 387 * |R| |1.0000 0.0000 1.4020| |Y + 0 | 388 * |G| = |1.0000 -0.3441 -0.7141| * |Cb - 128| 389 * |B| |1.0000 1.7720 0.0000| |Cr - 128| 390 */ 391 static const u32 csc1_coef_bt601_full[3] = { 392 BM_PXP_CSC1_COEF0_YCBCR_MODE | 393 BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */ 394 BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | 395 BF_PXP_CSC1_COEF0_Y_OFFSET(0), 396 BF_PXP_CSC1_COEF1_C1(0x166) | /* 1.3984 (-0.36 %) */ 397 BF_PXP_CSC1_COEF1_C4(0x1c5), /* 1.7695 (-0.25 %) */ 398 BF_PXP_CSC1_COEF2_C2(0x74a) | /* -0.7109 (+0.32 %) */ 399 BF_PXP_CSC1_COEF2_C3(0x7a8), /* -0.3438 (+0.04 %) */ 400 }; 401 /* 402 * Rec.709 limited range: 403 * 404 * |R| |1.1644 0.0000 1.7927| |Y - 16 | 405 * |G| = |1.1644 -0.2132 -0.5329| * |Cb - 128| 406 * |B| |1.1644 2.1124 0.0000| |Cr - 128| 407 */ 408 static const u32 csc1_coef_rec709_lim[3] = { 409 BM_PXP_CSC1_COEF0_YCBCR_MODE | 410 BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */ 411 BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | 412 BF_PXP_CSC1_COEF0_Y_OFFSET(-16), 413 BF_PXP_CSC1_COEF1_C1(0x1ca) | /* 1.7891 (-0.37 %) */ 414 BF_PXP_CSC1_COEF1_C4(0x21c), /* 2.1094 (-0.30 %) */ 415 BF_PXP_CSC1_COEF2_C2(0x778) | /* -0.5312 (+0.16 %) */ 416 BF_PXP_CSC1_COEF2_C3(0x7ca), /* -0.2109 (+0.23 %) */ 417 }; 418 /* 419 * Rec.709 full range: 420 * 421 * |R| |1.0000 0.0000 1.5748| |Y + 0 | 422 * |G| = |1.0000 -0.1873 -0.4681| * |Cb - 128| 423 * |B| |1.0000 1.8556 0.0000| |Cr - 128| 424 */ 425 static const u32 csc1_coef_rec709_full[3] = { 426 BM_PXP_CSC1_COEF0_YCBCR_MODE | 427 BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */ 428 BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | 429 BF_PXP_CSC1_COEF0_Y_OFFSET(0), 430 BF_PXP_CSC1_COEF1_C1(0x193) | /* 1.5742 (-0.06 %) */ 431 BF_PXP_CSC1_COEF1_C4(0x1db), /* 1.8555 (-0.01 %) */ 432 BF_PXP_CSC1_COEF2_C2(0x789) | /* -0.4648 (+0.33 %) */ 433 BF_PXP_CSC1_COEF2_C3(0x7d1), /* -0.1836 (+0.37 %) */ 434 }; 435 /* 436 * BT.2020 limited range: 437 * 438 * |R| |1.1644 0.0000 1.6787| |Y - 16 | 439 * |G| = |1.1644 -0.1874 -0.6505| * |Cb - 128| 440 * |B| |1.1644 2.1418 0.0000| |Cr - 128| 441 */ 442 static const u32 csc1_coef_bt2020_lim[3] = { 443 BM_PXP_CSC1_COEF0_YCBCR_MODE | 444 BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */ 445 BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | 446 BF_PXP_CSC1_COEF0_Y_OFFSET(-16), 447 BF_PXP_CSC1_COEF1_C1(0x1ad) | /* 1.6758 (-0.29 %) */ 448 BF_PXP_CSC1_COEF1_C4(0x224), /* 2.1406 (-0.11 %) */ 449 BF_PXP_CSC1_COEF2_C2(0x75a) | /* -0.6484 (+0.20 %) */ 450 BF_PXP_CSC1_COEF2_C3(0x7d1), /* -0.1836 (+0.38 %) */ 451 }; 452 /* 453 * BT.2020 full range: 454 * 455 * |R| |1.0000 0.0000 1.4746| |Y + 0 | 456 * |G| = |1.0000 -0.1646 -0.5714| * |Cb - 128| 457 * |B| |1.0000 1.8814 0.0000| |Cr - 128| 458 */ 459 static const u32 csc1_coef_bt2020_full[3] = { 460 BM_PXP_CSC1_COEF0_YCBCR_MODE | 461 BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */ 462 BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | 463 BF_PXP_CSC1_COEF0_Y_OFFSET(0), 464 BF_PXP_CSC1_COEF1_C1(0x179) | /* 1.4727 (-0.19 %) */ 465 BF_PXP_CSC1_COEF1_C4(0x1e1), /* 1.8789 (-0.25 %) */ 466 BF_PXP_CSC1_COEF2_C2(0x76e) | /* -0.5703 (+0.11 %) */ 467 BF_PXP_CSC1_COEF2_C3(0x7d6), /* -0.1641 (+0.05 %) */ 468 }; 469 /* 470 * SMPTE 240m limited range: 471 * 472 * |R| |1.1644 0.0000 1.7937| |Y - 16 | 473 * |G| = |1.1644 -0.2565 -0.5427| * |Cb - 128| 474 * |B| |1.1644 2.0798 0.0000| |Cr - 128| 475 */ 476 static const u32 csc1_coef_smpte240m_lim[3] = { 477 BM_PXP_CSC1_COEF0_YCBCR_MODE | 478 BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */ 479 BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | 480 BF_PXP_CSC1_COEF0_Y_OFFSET(-16), 481 BF_PXP_CSC1_COEF1_C1(0x1cb) | /* 1.7930 (-0.07 %) */ 482 BF_PXP_CSC1_COEF1_C4(0x214), /* 2.0781 (-0.17 %) */ 483 BF_PXP_CSC1_COEF2_C2(0x776) | /* -0.5391 (+0.36 %) */ 484 BF_PXP_CSC1_COEF2_C3(0x7bf), /* -0.2539 (+0.26 %) */ 485 }; 486 /* 487 * SMPTE 240m full range: 488 * 489 * |R| |1.0000 0.0000 1.5756| |Y + 0 | 490 * |G| = |1.0000 -0.2253 -0.4767| * |Cb - 128| 491 * |B| |1.0000 1.8270 0.0000| |Cr - 128| 492 */ 493 static const u32 csc1_coef_smpte240m_full[3] = { 494 BM_PXP_CSC1_COEF0_YCBCR_MODE | 495 BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */ 496 BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | 497 BF_PXP_CSC1_COEF0_Y_OFFSET(0), 498 BF_PXP_CSC1_COEF1_C1(0x193) | /* 1.5742 (-0.14 %) */ 499 BF_PXP_CSC1_COEF1_C4(0x1d3), /* 1.8242 (-0.28 %) */ 500 BF_PXP_CSC1_COEF2_C2(0x786) | /* -0.4766 (+0.01 %) */ 501 BF_PXP_CSC1_COEF2_C3(0x7c7), /* -0.2227 (+0.26 %) */ 502 }; 503 const u32 *csc1_coef; 504 505 ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc; 506 quantization = ctx->q_data[V4L2_M2M_SRC].quant; 507 508 if (ycbcr_enc == V4L2_YCBCR_ENC_601) { 509 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) 510 csc1_coef = csc1_coef_bt601_full; 511 else 512 csc1_coef = csc1_coef_bt601_lim; 513 } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) { 514 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) 515 csc1_coef = csc1_coef_rec709_full; 516 else 517 csc1_coef = csc1_coef_rec709_lim; 518 } else if (ycbcr_enc == V4L2_YCBCR_ENC_BT2020) { 519 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) 520 csc1_coef = csc1_coef_bt2020_full; 521 else 522 csc1_coef = csc1_coef_bt2020_lim; 523 } else { 524 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) 525 csc1_coef = csc1_coef_smpte240m_full; 526 else 527 csc1_coef = csc1_coef_smpte240m_lim; 528 } 529 530 pxp_write(dev, HW_PXP_CSC1_COEF0, csc1_coef[0]); 531 pxp_write(dev, HW_PXP_CSC1_COEF1, csc1_coef[1]); 532 pxp_write(dev, HW_PXP_CSC1_COEF2, csc1_coef[2]); 533 } else { 534 pxp_write(dev, HW_PXP_CSC1_COEF0, BM_PXP_CSC1_COEF0_BYPASS); 535 } 536 537 if (!pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) && 538 pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) { 539 /* 540 * CSC2 RGB to YUV/YCbCr conversion is implemented as follows: 541 * 542 * |Y | |A1 A2 A3| |R| |D1| 543 * |Cb| = |B1 B2 B3| * |G| + |D2| 544 * |Cr| |C1 C2 C3| |B| |D3| 545 * 546 * Results are clamped to 0..255. 547 * 548 * BT.601 limited range: 549 * 550 * |Y | | 0.2568 0.5041 0.0979| |R| |16 | 551 * |Cb| = |-0.1482 -0.2910 0.4392| * |G| + |128| 552 * |Cr| | 0.4392 0.4392 -0.3678| |B| |128| 553 */ 554 static const u32 csc2_coef_bt601_lim[6] = { 555 BF_PXP_CSC2_COEF0_A2(0x081) | /* 0.5039 (-0.02 %) */ 556 BF_PXP_CSC2_COEF0_A1(0x041), /* 0.2539 (-0.29 %) */ 557 BF_PXP_CSC2_COEF1_B1(0x7db) | /* -0.1445 (+0.37 %) */ 558 BF_PXP_CSC2_COEF1_A3(0x019), /* 0.0977 (-0.02 %) */ 559 BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */ 560 BF_PXP_CSC2_COEF2_B2(0x7b6), /* -0.2891 (+0.20 %) */ 561 BF_PXP_CSC2_COEF3_C2(0x7a2) | /* -0.3672 (+0.06 %) */ 562 BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */ 563 BF_PXP_CSC2_COEF4_D1(16) | 564 BF_PXP_CSC2_COEF4_C3(0x7ee), /* -0.0703 (+0.11 %) */ 565 BF_PXP_CSC2_COEF5_D3(128) | 566 BF_PXP_CSC2_COEF5_D2(128), 567 }; 568 /* 569 * BT.601 full range: 570 * 571 * |Y | | 0.2990 0.5870 0.1140| |R| |0 | 572 * |Cb| = |-0.1687 -0.3313 0.5000| * |G| + |128| 573 * |Cr| | 0.5000 0.5000 -0.4187| |B| |128| 574 */ 575 static const u32 csc2_coef_bt601_full[6] = { 576 BF_PXP_CSC2_COEF0_A2(0x096) | /* 0.5859 (-0.11 %) */ 577 BF_PXP_CSC2_COEF0_A1(0x04c), /* 0.2969 (-0.21 %) */ 578 BF_PXP_CSC2_COEF1_B1(0x7d5) | /* -0.1680 (+0.07 %) */ 579 BF_PXP_CSC2_COEF1_A3(0x01d), /* 0.1133 (-0.07 %) */ 580 BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */ 581 BF_PXP_CSC2_COEF2_B2(0x7ac), /* -0.3281 (+0.32 %) */ 582 BF_PXP_CSC2_COEF3_C2(0x795) | /* -0.4180 (+0.07 %) */ 583 BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */ 584 BF_PXP_CSC2_COEF4_D1(0) | 585 BF_PXP_CSC2_COEF4_C3(0x7ec), /* -0.0781 (+0.32 %) */ 586 BF_PXP_CSC2_COEF5_D3(128) | 587 BF_PXP_CSC2_COEF5_D2(128), 588 }; 589 /* 590 * Rec.709 limited range: 591 * 592 * |Y | | 0.1826 0.6142 0.0620| |R| |16 | 593 * |Cb| = |-0.1007 -0.3385 0.4392| * |G| + |128| 594 * |Cr| | 0.4392 0.4392 -0.3990| |B| |128| 595 */ 596 static const u32 csc2_coef_rec709_lim[6] = { 597 BF_PXP_CSC2_COEF0_A2(0x09d) | /* 0.6133 (-0.09 %) */ 598 BF_PXP_CSC2_COEF0_A1(0x02e), /* 0.1797 (-0.29 %) */ 599 BF_PXP_CSC2_COEF1_B1(0x7e7) | /* -0.0977 (+0.30 %) */ 600 BF_PXP_CSC2_COEF1_A3(0x00f), /* 0.0586 (-0.34 %) */ 601 BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */ 602 BF_PXP_CSC2_COEF2_B2(0x7aa), /* -0.3359 (+0.26 %) */ 603 BF_PXP_CSC2_COEF3_C2(0x79a) | /* -0.3984 (+0.05 %) */ 604 BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */ 605 BF_PXP_CSC2_COEF4_D1(16) | 606 BF_PXP_CSC2_COEF4_C3(0x7f6), /* -0.0391 (+0.12 %) */ 607 BF_PXP_CSC2_COEF5_D3(128) | 608 BF_PXP_CSC2_COEF5_D2(128), 609 }; 610 /* 611 * Rec.709 full range: 612 * 613 * |Y | | 0.2126 0.7152 0.0722| |R| |0 | 614 * |Cb| = |-0.1146 -0.3854 0.5000| * |G| + |128| 615 * |Cr| | 0.5000 0.5000 -0.4542| |B| |128| 616 */ 617 static const u32 csc2_coef_rec709_full[6] = { 618 BF_PXP_CSC2_COEF0_A2(0x0b7) | /* 0.7148 (-0.04 %) */ 619 BF_PXP_CSC2_COEF0_A1(0x036), /* 0.2109 (-0.17 %) */ 620 BF_PXP_CSC2_COEF1_B1(0x7e3) | /* -0.1133 (+0.13 %) */ 621 BF_PXP_CSC2_COEF1_A3(0x012), /* 0.0703 (-0.19 %) */ 622 BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */ 623 BF_PXP_CSC2_COEF2_B2(0x79e), /* -0.3828 (+0.26 %) */ 624 BF_PXP_CSC2_COEF3_C2(0x78c) | /* -0.4531 (+0.11 %) */ 625 BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */ 626 BF_PXP_CSC2_COEF4_D1(0) | 627 BF_PXP_CSC2_COEF4_C3(0x7f5), /* -0.0430 (+0.28 %) */ 628 BF_PXP_CSC2_COEF5_D3(128) | 629 BF_PXP_CSC2_COEF5_D2(128), 630 }; 631 /* 632 * BT.2020 limited range: 633 * 634 * |Y | | 0.2256 0.5823 0.0509| |R| |16 | 635 * |Cb| = |-0.1226 -0.3166 0.4392| * |G| + |128| 636 * |Cr| | 0.4392 0.4392 -0.4039| |B| |128| 637 */ 638 static const u32 csc2_coef_bt2020_lim[6] = { 639 BF_PXP_CSC2_COEF0_A2(0x095) | /* 0.5820 (-0.03 %) */ 640 BF_PXP_CSC2_COEF0_A1(0x039), /* 0.2227 (-0.30 %) */ 641 BF_PXP_CSC2_COEF1_B1(0x7e1) | /* -0.1211 (+0.15 %) */ 642 BF_PXP_CSC2_COEF1_A3(0x00d), /* 0.0508 (-0.01 %) */ 643 BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */ 644 BF_PXP_CSC2_COEF2_B2(0x7af), /* -0.3164 (+0.02 %) */ 645 BF_PXP_CSC2_COEF3_C2(0x799) | /* -0.4023 (+0.16 %) */ 646 BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */ 647 BF_PXP_CSC2_COEF4_D1(16) | 648 BF_PXP_CSC2_COEF4_C3(0x7f7), /* -0.0352 (+0.02 %) */ 649 BF_PXP_CSC2_COEF5_D3(128) | 650 BF_PXP_CSC2_COEF5_D2(128), 651 }; 652 /* 653 * BT.2020 full range: 654 * 655 * |Y | | 0.2627 0.6780 0.0593| |R| |0 | 656 * |Cb| = |-0.1396 -0.3604 0.5000| * |G| + |128| 657 * |Cr| | 0.5000 0.5000 -0.4598| |B| |128| 658 */ 659 static const u32 csc2_coef_bt2020_full[6] = { 660 BF_PXP_CSC2_COEF0_A2(0x0ad) | /* 0.6758 (-0.22 %) */ 661 BF_PXP_CSC2_COEF0_A1(0x043), /* 0.2617 (-0.10 %) */ 662 BF_PXP_CSC2_COEF1_B1(0x7dd) | /* -0.1367 (+0.29 %) */ 663 BF_PXP_CSC2_COEF1_A3(0x00f), /* 0.0586 (-0.07 %) */ 664 BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */ 665 BF_PXP_CSC2_COEF2_B2(0x7a4), /* -0.3594 (+0.10 %) */ 666 BF_PXP_CSC2_COEF3_C2(0x78b) | /* -0.4570 (+0.28 %) */ 667 BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */ 668 BF_PXP_CSC2_COEF4_D1(0) | 669 BF_PXP_CSC2_COEF4_C3(0x7f6), /* -0.0391 (+0.11 %) */ 670 BF_PXP_CSC2_COEF5_D3(128) | 671 BF_PXP_CSC2_COEF5_D2(128), 672 }; 673 /* 674 * SMPTE 240m limited range: 675 * 676 * |Y | | 0.1821 0.6020 0.0747| |R| |16 | 677 * |Cb| = |-0.1019 -0.3373 0.4392| * |G| + |128| 678 * |Cr| | 0.4392 0.4392 -0.3909| |B| |128| 679 */ 680 static const u32 csc2_coef_smpte240m_lim[6] = { 681 BF_PXP_CSC2_COEF0_A2(0x09a) | /* 0.6016 (-0.05 %) */ 682 BF_PXP_CSC2_COEF0_A1(0x02e), /* 0.1797 (-0.24 %) */ 683 BF_PXP_CSC2_COEF1_B1(0x7e6) | /* -0.1016 (+0.03 %) */ 684 BF_PXP_CSC2_COEF1_A3(0x013), /* 0.0742 (-0.05 %) */ 685 BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */ 686 BF_PXP_CSC2_COEF2_B2(0x7aa), /* -0.3359 (+0.14 %) */ 687 BF_PXP_CSC2_COEF3_C2(0x79c) | /* -0.3906 (+0.03 %) */ 688 BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */ 689 BF_PXP_CSC2_COEF4_D1(16) | 690 BF_PXP_CSC2_COEF4_C3(0x7f4), /* -0.0469 (+0.14 %) */ 691 BF_PXP_CSC2_COEF5_D3(128) | 692 BF_PXP_CSC2_COEF5_D2(128), 693 }; 694 /* 695 * SMPTE 240m full range: 696 * 697 * |Y | | 0.2120 0.7010 0.0870| |R| |0 | 698 * |Cb| = |-0.1160 -0.3840 0.5000| * |G| + |128| 699 * |Cr| | 0.5000 0.5000 -0.4450| |B| |128| 700 */ 701 static const u32 csc2_coef_smpte240m_full[6] = { 702 BF_PXP_CSC2_COEF0_A2(0x0b3) | /* 0.6992 (-0.18 %) */ 703 BF_PXP_CSC2_COEF0_A1(0x036), /* 0.2109 (-0.11 %) */ 704 BF_PXP_CSC2_COEF1_B1(0x7e3) | /* -0.1133 (+0.27 %) */ 705 BF_PXP_CSC2_COEF1_A3(0x016), /* 0.0859 (-0.11 %) */ 706 BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */ 707 BF_PXP_CSC2_COEF2_B2(0x79e), /* -0.3828 (+0.12 %) */ 708 BF_PXP_CSC2_COEF3_C2(0x78f) | /* -0.4414 (+0.36 %) */ 709 BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */ 710 BF_PXP_CSC2_COEF4_D1(0) | 711 BF_PXP_CSC2_COEF4_C3(0x7f2), /* -0.0547 (+0.03 %) */ 712 BF_PXP_CSC2_COEF5_D3(128) | 713 BF_PXP_CSC2_COEF5_D2(128), 714 }; 715 const u32 *csc2_coef; 716 u32 csc2_ctrl; 717 718 ycbcr_enc = ctx->q_data[V4L2_M2M_DST].ycbcr_enc; 719 quantization = ctx->q_data[V4L2_M2M_DST].quant; 720 721 if (ycbcr_enc == V4L2_YCBCR_ENC_601) { 722 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) 723 csc2_coef = csc2_coef_bt601_full; 724 else 725 csc2_coef = csc2_coef_bt601_lim; 726 } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) { 727 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) 728 csc2_coef = csc2_coef_rec709_full; 729 else 730 csc2_coef = csc2_coef_rec709_lim; 731 } else if (ycbcr_enc == V4L2_YCBCR_ENC_BT2020) { 732 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) 733 csc2_coef = csc2_coef_bt2020_full; 734 else 735 csc2_coef = csc2_coef_bt2020_lim; 736 } else { 737 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) 738 csc2_coef = csc2_coef_smpte240m_full; 739 else 740 csc2_coef = csc2_coef_smpte240m_lim; 741 } 742 if (quantization == V4L2_QUANTIZATION_FULL_RANGE) { 743 csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV << 744 BP_PXP_CSC2_CTRL_CSC_MODE; 745 } else { 746 csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr << 747 BP_PXP_CSC2_CTRL_CSC_MODE; 748 } 749 750 pxp_write(dev, HW_PXP_CSC2_CTRL, csc2_ctrl); 751 pxp_write(dev, HW_PXP_CSC2_COEF0, csc2_coef[0]); 752 pxp_write(dev, HW_PXP_CSC2_COEF1, csc2_coef[1]); 753 pxp_write(dev, HW_PXP_CSC2_COEF2, csc2_coef[2]); 754 pxp_write(dev, HW_PXP_CSC2_COEF3, csc2_coef[3]); 755 pxp_write(dev, HW_PXP_CSC2_COEF4, csc2_coef[4]); 756 pxp_write(dev, HW_PXP_CSC2_COEF5, csc2_coef[5]); 757 } else { 758 pxp_write(dev, HW_PXP_CSC2_CTRL, BM_PXP_CSC2_CTRL_BYPASS); 759 } 760 } 761 762 static u32 pxp_imx6ull_data_path_ctrl0(struct pxp_ctx *ctx) 763 { 764 u32 ctrl0; 765 766 ctrl0 = 0; 767 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(3); 768 /* Bypass Dithering x3CH */ 769 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1); 770 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(3); 771 /* Select Rotation */ 772 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(0); 773 /* Bypass LUT */ 774 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(1); 775 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(3); 776 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(3); 777 /* Select CSC 2 */ 778 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0); 779 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(3); 780 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(3); 781 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(3); 782 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(3); 783 /* Bypass Rotation 2 */ 784 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0); 785 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(3); 786 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(3); 787 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(3); 788 789 return ctrl0; 790 } 791 792 static u32 pxp_imx7d_data_path_ctrl0(struct pxp_ctx *ctx) 793 { 794 u32 ctrl0; 795 796 ctrl0 = 0; 797 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(3); 798 /* Select Rotation 0 */ 799 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(0); 800 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(3); 801 /* Select MUX11 for Rotation 0 */ 802 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(1); 803 /* Bypass LUT */ 804 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(1); 805 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(3); 806 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(3); 807 /* Select CSC 2 */ 808 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0); 809 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(3); 810 /* Select Composite Alpha Blending/Color Key 0 for CSC 2 */ 811 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(1); 812 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(3); 813 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(3); 814 /* Bypass Rotation 1 */ 815 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0); 816 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(3); 817 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(3); 818 ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(3); 819 820 return ctrl0; 821 } 822 823 static void pxp_set_data_path(struct pxp_ctx *ctx) 824 { 825 struct pxp_dev *dev = ctx->dev; 826 u32 ctrl0; 827 u32 ctrl1; 828 829 ctrl0 = dev->pdata->data_path_ctrl0(ctx); 830 831 ctrl1 = 0; 832 ctrl1 |= BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(3); 833 ctrl1 |= BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(3); 834 835 pxp_write(dev, HW_PXP_DATA_PATH_CTRL0, ctrl0); 836 pxp_write(dev, HW_PXP_DATA_PATH_CTRL1, ctrl1); 837 } 838 839 static int pxp_start(struct pxp_ctx *ctx, struct vb2_v4l2_buffer *in_vb, 840 struct vb2_v4l2_buffer *out_vb) 841 { 842 struct pxp_dev *dev = ctx->dev; 843 struct pxp_q_data *q_data; 844 u32 src_width, src_height, src_stride, src_fourcc; 845 u32 dst_width, dst_height, dst_stride, dst_fourcc; 846 dma_addr_t p_in, p_out; 847 u32 ctrl, out_ctrl, out_buf, out_buf2, out_pitch, out_lrc, out_ps_ulc; 848 u32 out_ps_lrc; 849 u32 ps_ctrl, ps_buf, ps_ubuf, ps_vbuf, ps_pitch, ps_scale, ps_offset; 850 u32 as_ulc, as_lrc; 851 u32 y_size; 852 u32 decx, decy, xscale, yscale; 853 854 q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); 855 856 src_width = ctx->q_data[V4L2_M2M_SRC].width; 857 dst_width = ctx->q_data[V4L2_M2M_DST].width; 858 src_height = ctx->q_data[V4L2_M2M_SRC].height; 859 dst_height = ctx->q_data[V4L2_M2M_DST].height; 860 src_stride = ctx->q_data[V4L2_M2M_SRC].bytesperline; 861 dst_stride = ctx->q_data[V4L2_M2M_DST].bytesperline; 862 src_fourcc = ctx->q_data[V4L2_M2M_SRC].fmt->fourcc; 863 dst_fourcc = ctx->q_data[V4L2_M2M_DST].fmt->fourcc; 864 865 p_in = vb2_dma_contig_plane_dma_addr(&in_vb->vb2_buf, 0); 866 p_out = vb2_dma_contig_plane_dma_addr(&out_vb->vb2_buf, 0); 867 868 if (!p_in || !p_out) { 869 v4l2_err(&dev->v4l2_dev, 870 "Acquiring DMA addresses of buffers failed\n"); 871 return -EFAULT; 872 } 873 874 out_vb->sequence = 875 get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++; 876 in_vb->sequence = q_data->sequence++; 877 out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp; 878 879 if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE) 880 out_vb->timecode = in_vb->timecode; 881 out_vb->field = in_vb->field; 882 out_vb->flags = in_vb->flags & 883 (V4L2_BUF_FLAG_TIMECODE | 884 V4L2_BUF_FLAG_KEYFRAME | 885 V4L2_BUF_FLAG_PFRAME | 886 V4L2_BUF_FLAG_BFRAME | 887 V4L2_BUF_FLAG_TSTAMP_SRC_MASK); 888 889 /* 8x8 block size */ 890 ctrl = BF_PXP_CTRL_VFLIP0(!!(ctx->mode & MEM2MEM_VFLIP)) | 891 BF_PXP_CTRL_HFLIP0(!!(ctx->mode & MEM2MEM_HFLIP)) | 892 BF_PXP_CTRL_ROTATE0(ctx->rotation); 893 /* Always write alpha value as V4L2_CID_ALPHA_COMPONENT */ 894 out_ctrl = BF_PXP_OUT_CTRL_ALPHA(ctx->alpha_component) | 895 BF_PXP_OUT_CTRL_ALPHA_OUTPUT(1) | 896 pxp_v4l2_pix_fmt_to_out_format(dst_fourcc); 897 out_buf = p_out; 898 899 if (ctx->rotation == BV_PXP_CTRL_ROTATE0__ROT_90 || 900 ctx->rotation == BV_PXP_CTRL_ROTATE0__ROT_270) 901 swap(dst_width, dst_height); 902 903 switch (dst_fourcc) { 904 case V4L2_PIX_FMT_NV12: 905 case V4L2_PIX_FMT_NV21: 906 case V4L2_PIX_FMT_NV16: 907 case V4L2_PIX_FMT_NV61: 908 out_buf2 = out_buf + dst_stride * dst_height; 909 break; 910 default: 911 out_buf2 = 0; 912 } 913 914 out_pitch = BF_PXP_OUT_PITCH_PITCH(dst_stride); 915 out_lrc = BF_PXP_OUT_LRC_X(dst_width - 1) | 916 BF_PXP_OUT_LRC_Y(dst_height - 1); 917 /* PS covers whole output */ 918 out_ps_ulc = BF_PXP_OUT_PS_ULC_X(0) | BF_PXP_OUT_PS_ULC_Y(0); 919 out_ps_lrc = BF_PXP_OUT_PS_LRC_X(dst_width - 1) | 920 BF_PXP_OUT_PS_LRC_Y(dst_height - 1); 921 /* no AS */ 922 as_ulc = BF_PXP_OUT_AS_ULC_X(1) | BF_PXP_OUT_AS_ULC_Y(1); 923 as_lrc = BF_PXP_OUT_AS_LRC_X(0) | BF_PXP_OUT_AS_LRC_Y(0); 924 925 decx = (src_width <= dst_width) ? 0 : ilog2(src_width / dst_width); 926 decy = (src_height <= dst_height) ? 0 : ilog2(src_height / dst_height); 927 ps_ctrl = BF_PXP_PS_CTRL_DECX(decx) | BF_PXP_PS_CTRL_DECY(decy) | 928 pxp_v4l2_pix_fmt_to_ps_format(src_fourcc); 929 ps_buf = p_in; 930 y_size = src_stride * src_height; 931 switch (src_fourcc) { 932 case V4L2_PIX_FMT_YUV420: 933 ps_ubuf = ps_buf + y_size; 934 ps_vbuf = ps_ubuf + y_size / 4; 935 break; 936 case V4L2_PIX_FMT_YUV422P: 937 ps_ubuf = ps_buf + y_size; 938 ps_vbuf = ps_ubuf + y_size / 2; 939 break; 940 case V4L2_PIX_FMT_NV12: 941 case V4L2_PIX_FMT_NV21: 942 case V4L2_PIX_FMT_NV16: 943 case V4L2_PIX_FMT_NV61: 944 ps_ubuf = ps_buf + y_size; 945 ps_vbuf = 0; 946 break; 947 case V4L2_PIX_FMT_GREY: 948 case V4L2_PIX_FMT_Y4: 949 ps_ubuf = 0; 950 /* In grayscale mode, ps_vbuf contents are reused as CbCr */ 951 ps_vbuf = 0x8080; 952 break; 953 default: 954 ps_ubuf = 0; 955 ps_vbuf = 0; 956 break; 957 } 958 ps_pitch = BF_PXP_PS_PITCH_PITCH(src_stride); 959 if (decx) { 960 xscale = (src_width >> decx) * 0x1000 / dst_width; 961 } else { 962 switch (src_fourcc) { 963 case V4L2_PIX_FMT_UYVY: 964 case V4L2_PIX_FMT_YUYV: 965 case V4L2_PIX_FMT_VYUY: 966 case V4L2_PIX_FMT_YVYU: 967 case V4L2_PIX_FMT_NV16: 968 case V4L2_PIX_FMT_NV12: 969 case V4L2_PIX_FMT_NV21: 970 case V4L2_PIX_FMT_NV61: 971 case V4L2_PIX_FMT_YUV422P: 972 case V4L2_PIX_FMT_YUV420: 973 /* 974 * This avoids sampling past the right edge for 975 * horizontally chroma subsampled formats. 976 */ 977 xscale = (src_width - 2) * 0x1000 / (dst_width - 1); 978 break; 979 default: 980 xscale = (src_width - 1) * 0x1000 / (dst_width - 1); 981 break; 982 } 983 } 984 if (decy) 985 yscale = (src_height >> decy) * 0x1000 / dst_height; 986 else 987 yscale = (src_height - 1) * 0x1000 / (dst_height - 1); 988 ps_scale = BF_PXP_PS_SCALE_YSCALE(yscale) | 989 BF_PXP_PS_SCALE_XSCALE(xscale); 990 ps_offset = BF_PXP_PS_OFFSET_YOFFSET(0) | BF_PXP_PS_OFFSET_XOFFSET(0); 991 992 pxp_write(dev, HW_PXP_CTRL, ctrl); 993 /* skip STAT */ 994 pxp_write(dev, HW_PXP_OUT_CTRL, out_ctrl); 995 pxp_write(dev, HW_PXP_OUT_BUF, out_buf); 996 pxp_write(dev, HW_PXP_OUT_BUF2, out_buf2); 997 pxp_write(dev, HW_PXP_OUT_PITCH, out_pitch); 998 pxp_write(dev, HW_PXP_OUT_LRC, out_lrc); 999 pxp_write(dev, HW_PXP_OUT_PS_ULC, out_ps_ulc); 1000 pxp_write(dev, HW_PXP_OUT_PS_LRC, out_ps_lrc); 1001 pxp_write(dev, HW_PXP_OUT_AS_ULC, as_ulc); 1002 pxp_write(dev, HW_PXP_OUT_AS_LRC, as_lrc); 1003 pxp_write(dev, HW_PXP_PS_CTRL, ps_ctrl); 1004 pxp_write(dev, HW_PXP_PS_BUF, ps_buf); 1005 pxp_write(dev, HW_PXP_PS_UBUF, ps_ubuf); 1006 pxp_write(dev, HW_PXP_PS_VBUF, ps_vbuf); 1007 pxp_write(dev, HW_PXP_PS_PITCH, ps_pitch); 1008 pxp_write(dev, HW_PXP_PS_BACKGROUND_0, 0x00ffffff); 1009 pxp_write(dev, HW_PXP_PS_SCALE, ps_scale); 1010 pxp_write(dev, HW_PXP_PS_OFFSET, ps_offset); 1011 /* disable processed surface color keying */ 1012 pxp_write(dev, HW_PXP_PS_CLRKEYLOW_0, 0x00ffffff); 1013 pxp_write(dev, HW_PXP_PS_CLRKEYHIGH_0, 0x00000000); 1014 1015 /* disable alpha surface color keying */ 1016 pxp_write(dev, HW_PXP_AS_CLRKEYLOW_0, 0x00ffffff); 1017 pxp_write(dev, HW_PXP_AS_CLRKEYHIGH_0, 0x00000000); 1018 1019 /* setup CSC */ 1020 pxp_setup_csc(ctx); 1021 1022 /* bypass LUT */ 1023 pxp_write(dev, HW_PXP_LUT_CTRL, BM_PXP_LUT_CTRL_BYPASS); 1024 1025 pxp_set_data_path(ctx); 1026 1027 pxp_write(dev, HW_PXP_IRQ_MASK, 0xffff); 1028 1029 /* ungate, enable PS/AS/OUT and PXP operation */ 1030 pxp_write(dev, HW_PXP_CTRL_SET, BM_PXP_CTRL_IRQ_ENABLE); 1031 pxp_write(dev, HW_PXP_CTRL_SET, 1032 BM_PXP_CTRL_ENABLE | BM_PXP_CTRL_ENABLE_CSC2 | 1033 BM_PXP_CTRL_ENABLE_ROTATE0 | BM_PXP_CTRL_ENABLE_PS_AS_OUT); 1034 1035 return 0; 1036 } 1037 1038 static void pxp_job_finish(struct pxp_dev *dev) 1039 { 1040 struct pxp_ctx *curr_ctx; 1041 struct vb2_v4l2_buffer *src_vb, *dst_vb; 1042 unsigned long flags; 1043 1044 curr_ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); 1045 1046 if (curr_ctx == NULL) { 1047 pr_err("Instance released before the end of transaction\n"); 1048 return; 1049 } 1050 1051 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); 1052 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); 1053 1054 spin_lock_irqsave(&dev->irqlock, flags); 1055 v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); 1056 v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); 1057 spin_unlock_irqrestore(&dev->irqlock, flags); 1058 1059 dprintk(curr_ctx->dev, "Finishing transaction\n"); 1060 v4l2_m2m_job_finish(dev->m2m_dev, curr_ctx->fh.m2m_ctx); 1061 } 1062 1063 /* 1064 * mem2mem callbacks 1065 */ 1066 static void pxp_device_run(void *priv) 1067 { 1068 struct pxp_ctx *ctx = priv; 1069 struct vb2_v4l2_buffer *src_buf, *dst_buf; 1070 1071 src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 1072 dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); 1073 1074 pxp_start(ctx, src_buf, dst_buf); 1075 } 1076 1077 static int pxp_job_ready(void *priv) 1078 { 1079 struct pxp_ctx *ctx = priv; 1080 1081 if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < 1 || 1082 v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < 1) { 1083 dprintk(ctx->dev, "Not enough buffers available\n"); 1084 return 0; 1085 } 1086 1087 return 1; 1088 } 1089 1090 static void pxp_job_abort(void *priv) 1091 { 1092 struct pxp_ctx *ctx = priv; 1093 1094 /* Will cancel the transaction in the next interrupt handler */ 1095 ctx->aborting = 1; 1096 } 1097 1098 /* 1099 * interrupt handler 1100 */ 1101 static irqreturn_t pxp_irq_handler(int irq, void *dev_id) 1102 { 1103 struct pxp_dev *dev = dev_id; 1104 u32 stat; 1105 1106 stat = pxp_read(dev, HW_PXP_STAT); 1107 1108 if (stat & BM_PXP_STAT_IRQ0) { 1109 /* we expect x = 0, y = height, irq0 = 1 */ 1110 if (stat & ~(BM_PXP_STAT_BLOCKX | BM_PXP_STAT_BLOCKY | 1111 BM_PXP_STAT_IRQ0)) 1112 dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat); 1113 pxp_write(dev, HW_PXP_STAT_CLR, BM_PXP_STAT_IRQ0); 1114 1115 pxp_job_finish(dev); 1116 } else { 1117 u32 irq = pxp_read(dev, HW_PXP_IRQ); 1118 1119 dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat); 1120 dprintk(dev, "%s: irq = 0x%08x\n", __func__, irq); 1121 1122 pxp_write(dev, HW_PXP_IRQ_CLR, irq); 1123 } 1124 1125 return IRQ_HANDLED; 1126 } 1127 1128 /* 1129 * video ioctls 1130 */ 1131 static int pxp_querycap(struct file *file, void *priv, 1132 struct v4l2_capability *cap) 1133 { 1134 strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); 1135 strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); 1136 return 0; 1137 } 1138 1139 static int pxp_enum_fmt(struct v4l2_fmtdesc *f, u32 type) 1140 { 1141 int i, num; 1142 struct pxp_fmt *fmt; 1143 1144 num = 0; 1145 1146 for (i = 0; i < NUM_FORMATS; ++i) { 1147 if (formats[i].types & type) { 1148 /* index-th format of type type found ? */ 1149 if (num == f->index) 1150 break; 1151 /* 1152 * Correct type but haven't reached our index yet, 1153 * just increment per-type index 1154 */ 1155 ++num; 1156 } 1157 } 1158 1159 if (i < NUM_FORMATS) { 1160 /* Format found */ 1161 fmt = &formats[i]; 1162 f->pixelformat = fmt->fourcc; 1163 return 0; 1164 } 1165 1166 /* Format not found */ 1167 return -EINVAL; 1168 } 1169 1170 static int pxp_enum_fmt_vid_cap(struct file *file, void *priv, 1171 struct v4l2_fmtdesc *f) 1172 { 1173 return pxp_enum_fmt(f, MEM2MEM_CAPTURE); 1174 } 1175 1176 static int pxp_enum_fmt_vid_out(struct file *file, void *priv, 1177 struct v4l2_fmtdesc *f) 1178 { 1179 return pxp_enum_fmt(f, MEM2MEM_OUTPUT); 1180 } 1181 1182 static int pxp_g_fmt(struct pxp_ctx *ctx, struct v4l2_format *f) 1183 { 1184 struct vb2_queue *vq; 1185 struct pxp_q_data *q_data; 1186 1187 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 1188 if (!vq) 1189 return -EINVAL; 1190 1191 q_data = get_q_data(ctx, f->type); 1192 1193 f->fmt.pix.width = q_data->width; 1194 f->fmt.pix.height = q_data->height; 1195 f->fmt.pix.field = V4L2_FIELD_NONE; 1196 f->fmt.pix.pixelformat = q_data->fmt->fourcc; 1197 f->fmt.pix.bytesperline = q_data->bytesperline; 1198 f->fmt.pix.sizeimage = q_data->sizeimage; 1199 f->fmt.pix.colorspace = ctx->colorspace; 1200 f->fmt.pix.xfer_func = ctx->xfer_func; 1201 f->fmt.pix.ycbcr_enc = q_data->ycbcr_enc; 1202 f->fmt.pix.quantization = q_data->quant; 1203 1204 return 0; 1205 } 1206 1207 static int pxp_g_fmt_vid_out(struct file *file, void *priv, 1208 struct v4l2_format *f) 1209 { 1210 return pxp_g_fmt(file2ctx(file), f); 1211 } 1212 1213 static int pxp_g_fmt_vid_cap(struct file *file, void *priv, 1214 struct v4l2_format *f) 1215 { 1216 return pxp_g_fmt(file2ctx(file), f); 1217 } 1218 1219 static inline u32 pxp_bytesperline(struct pxp_fmt *fmt, u32 width) 1220 { 1221 switch (fmt->fourcc) { 1222 case V4L2_PIX_FMT_YUV420: 1223 case V4L2_PIX_FMT_NV12: 1224 case V4L2_PIX_FMT_NV21: 1225 case V4L2_PIX_FMT_YUV422P: 1226 case V4L2_PIX_FMT_NV16: 1227 case V4L2_PIX_FMT_NV61: 1228 return width; 1229 default: 1230 return (width * fmt->depth) >> 3; 1231 } 1232 } 1233 1234 static inline u32 pxp_sizeimage(struct pxp_fmt *fmt, u32 width, u32 height) 1235 { 1236 return (fmt->depth * width * height) >> 3; 1237 } 1238 1239 static int pxp_try_fmt(struct v4l2_format *f, struct pxp_fmt *fmt) 1240 { 1241 v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ALIGN_W, 1242 &f->fmt.pix.height, MIN_H, MAX_H, ALIGN_H, 0); 1243 1244 f->fmt.pix.bytesperline = pxp_bytesperline(fmt, f->fmt.pix.width); 1245 f->fmt.pix.sizeimage = pxp_sizeimage(fmt, f->fmt.pix.width, 1246 f->fmt.pix.height); 1247 f->fmt.pix.field = V4L2_FIELD_NONE; 1248 1249 return 0; 1250 } 1251 1252 static void 1253 pxp_fixup_colorimetry_cap(struct pxp_ctx *ctx, u32 dst_fourcc, 1254 enum v4l2_ycbcr_encoding *ycbcr_enc, 1255 enum v4l2_quantization *quantization) 1256 { 1257 bool dst_is_yuv = pxp_v4l2_pix_fmt_is_yuv(dst_fourcc); 1258 1259 if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) == 1260 dst_is_yuv) { 1261 /* 1262 * There is no support for conversion between different YCbCr 1263 * encodings or between RGB limited and full range. 1264 */ 1265 *ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc; 1266 *quantization = ctx->q_data[V4L2_M2M_SRC].quant; 1267 } else { 1268 *ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(ctx->colorspace); 1269 *quantization = V4L2_MAP_QUANTIZATION_DEFAULT(!dst_is_yuv, 1270 ctx->colorspace, 1271 *ycbcr_enc); 1272 } 1273 } 1274 1275 static int pxp_try_fmt_vid_cap(struct file *file, void *priv, 1276 struct v4l2_format *f) 1277 { 1278 struct pxp_fmt *fmt; 1279 struct pxp_ctx *ctx = file2ctx(file); 1280 1281 fmt = find_format(f->fmt.pix.pixelformat); 1282 if (!fmt) { 1283 f->fmt.pix.pixelformat = formats[0].fourcc; 1284 fmt = find_format(f->fmt.pix.pixelformat); 1285 } 1286 if (!(fmt->types & MEM2MEM_CAPTURE)) { 1287 v4l2_err(&ctx->dev->v4l2_dev, 1288 "Fourcc format (0x%08x) invalid.\n", 1289 f->fmt.pix.pixelformat); 1290 return -EINVAL; 1291 } 1292 1293 f->fmt.pix.colorspace = ctx->colorspace; 1294 f->fmt.pix.xfer_func = ctx->xfer_func; 1295 1296 pxp_fixup_colorimetry_cap(ctx, fmt->fourcc, 1297 &f->fmt.pix.ycbcr_enc, 1298 &f->fmt.pix.quantization); 1299 1300 return pxp_try_fmt(f, fmt); 1301 } 1302 1303 static int pxp_try_fmt_vid_out(struct file *file, void *priv, 1304 struct v4l2_format *f) 1305 { 1306 struct pxp_fmt *fmt; 1307 struct pxp_ctx *ctx = file2ctx(file); 1308 1309 fmt = find_format(f->fmt.pix.pixelformat); 1310 if (!fmt) { 1311 f->fmt.pix.pixelformat = formats[0].fourcc; 1312 fmt = find_format(f->fmt.pix.pixelformat); 1313 } 1314 if (!(fmt->types & MEM2MEM_OUTPUT)) { 1315 v4l2_err(&ctx->dev->v4l2_dev, 1316 "Fourcc format (0x%08x) invalid.\n", 1317 f->fmt.pix.pixelformat); 1318 return -EINVAL; 1319 } 1320 1321 if (!f->fmt.pix.colorspace) 1322 f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; 1323 1324 return pxp_try_fmt(f, fmt); 1325 } 1326 1327 static int pxp_s_fmt(struct pxp_ctx *ctx, struct v4l2_format *f) 1328 { 1329 struct pxp_q_data *q_data; 1330 struct vb2_queue *vq; 1331 1332 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 1333 if (!vq) 1334 return -EINVAL; 1335 1336 q_data = get_q_data(ctx, f->type); 1337 if (!q_data) 1338 return -EINVAL; 1339 1340 if (vb2_is_busy(vq)) { 1341 v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); 1342 return -EBUSY; 1343 } 1344 1345 q_data->fmt = find_format(f->fmt.pix.pixelformat); 1346 q_data->width = f->fmt.pix.width; 1347 q_data->height = f->fmt.pix.height; 1348 q_data->bytesperline = f->fmt.pix.bytesperline; 1349 q_data->sizeimage = f->fmt.pix.sizeimage; 1350 1351 dprintk(ctx->dev, 1352 "Setting format for type %d, wxh: %dx%d, fmt: %d\n", 1353 f->type, q_data->width, q_data->height, q_data->fmt->fourcc); 1354 1355 return 0; 1356 } 1357 1358 static int pxp_s_fmt_vid_cap(struct file *file, void *priv, 1359 struct v4l2_format *f) 1360 { 1361 struct pxp_ctx *ctx = file2ctx(file); 1362 int ret; 1363 1364 ret = pxp_try_fmt_vid_cap(file, priv, f); 1365 if (ret) 1366 return ret; 1367 1368 ret = pxp_s_fmt(file2ctx(file), f); 1369 if (ret) 1370 return ret; 1371 1372 ctx->q_data[V4L2_M2M_DST].ycbcr_enc = f->fmt.pix.ycbcr_enc; 1373 ctx->q_data[V4L2_M2M_DST].quant = f->fmt.pix.quantization; 1374 1375 return 0; 1376 } 1377 1378 static int pxp_s_fmt_vid_out(struct file *file, void *priv, 1379 struct v4l2_format *f) 1380 { 1381 struct pxp_ctx *ctx = file2ctx(file); 1382 int ret; 1383 1384 ret = pxp_try_fmt_vid_out(file, priv, f); 1385 if (ret) 1386 return ret; 1387 1388 ret = pxp_s_fmt(file2ctx(file), f); 1389 if (ret) 1390 return ret; 1391 1392 ctx->colorspace = f->fmt.pix.colorspace; 1393 ctx->xfer_func = f->fmt.pix.xfer_func; 1394 ctx->q_data[V4L2_M2M_SRC].ycbcr_enc = f->fmt.pix.ycbcr_enc; 1395 ctx->q_data[V4L2_M2M_SRC].quant = f->fmt.pix.quantization; 1396 1397 pxp_fixup_colorimetry_cap(ctx, ctx->q_data[V4L2_M2M_DST].fmt->fourcc, 1398 &ctx->q_data[V4L2_M2M_DST].ycbcr_enc, 1399 &ctx->q_data[V4L2_M2M_DST].quant); 1400 1401 return 0; 1402 } 1403 1404 static int pxp_enum_framesizes(struct file *file, void *fh, 1405 struct v4l2_frmsizeenum *fsize) 1406 { 1407 if (fsize->index > 0) 1408 return -EINVAL; 1409 1410 if (!find_format(fsize->pixel_format)) 1411 return -EINVAL; 1412 1413 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 1414 fsize->stepwise.min_width = MIN_W; 1415 fsize->stepwise.max_width = MAX_W; 1416 fsize->stepwise.step_width = 1 << ALIGN_W; 1417 fsize->stepwise.min_height = MIN_H; 1418 fsize->stepwise.max_height = MAX_H; 1419 fsize->stepwise.step_height = 1 << ALIGN_H; 1420 1421 return 0; 1422 } 1423 1424 static u8 pxp_degrees_to_rot_mode(u32 degrees) 1425 { 1426 switch (degrees) { 1427 case 90: 1428 return BV_PXP_CTRL_ROTATE0__ROT_90; 1429 case 180: 1430 return BV_PXP_CTRL_ROTATE0__ROT_180; 1431 case 270: 1432 return BV_PXP_CTRL_ROTATE0__ROT_270; 1433 case 0: 1434 default: 1435 return BV_PXP_CTRL_ROTATE0__ROT_0; 1436 } 1437 } 1438 1439 static int pxp_s_ctrl(struct v4l2_ctrl *ctrl) 1440 { 1441 struct pxp_ctx *ctx = 1442 container_of(ctrl->handler, struct pxp_ctx, hdl); 1443 1444 switch (ctrl->id) { 1445 case V4L2_CID_HFLIP: 1446 if (ctrl->val) 1447 ctx->mode |= MEM2MEM_HFLIP; 1448 else 1449 ctx->mode &= ~MEM2MEM_HFLIP; 1450 break; 1451 1452 case V4L2_CID_VFLIP: 1453 if (ctrl->val) 1454 ctx->mode |= MEM2MEM_VFLIP; 1455 else 1456 ctx->mode &= ~MEM2MEM_VFLIP; 1457 break; 1458 1459 case V4L2_CID_ROTATE: 1460 ctx->rotation = pxp_degrees_to_rot_mode(ctrl->val); 1461 break; 1462 1463 case V4L2_CID_ALPHA_COMPONENT: 1464 ctx->alpha_component = ctrl->val; 1465 break; 1466 1467 default: 1468 v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n"); 1469 return -EINVAL; 1470 } 1471 1472 return 0; 1473 } 1474 1475 static const struct v4l2_ctrl_ops pxp_ctrl_ops = { 1476 .s_ctrl = pxp_s_ctrl, 1477 }; 1478 1479 static const struct v4l2_ioctl_ops pxp_ioctl_ops = { 1480 .vidioc_querycap = pxp_querycap, 1481 1482 .vidioc_enum_fmt_vid_cap = pxp_enum_fmt_vid_cap, 1483 .vidioc_g_fmt_vid_cap = pxp_g_fmt_vid_cap, 1484 .vidioc_try_fmt_vid_cap = pxp_try_fmt_vid_cap, 1485 .vidioc_s_fmt_vid_cap = pxp_s_fmt_vid_cap, 1486 1487 .vidioc_enum_fmt_vid_out = pxp_enum_fmt_vid_out, 1488 .vidioc_g_fmt_vid_out = pxp_g_fmt_vid_out, 1489 .vidioc_try_fmt_vid_out = pxp_try_fmt_vid_out, 1490 .vidioc_s_fmt_vid_out = pxp_s_fmt_vid_out, 1491 1492 .vidioc_enum_framesizes = pxp_enum_framesizes, 1493 1494 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 1495 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 1496 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 1497 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 1498 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 1499 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 1500 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 1501 1502 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 1503 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 1504 1505 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 1506 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1507 }; 1508 1509 /* 1510 * Queue operations 1511 */ 1512 static int pxp_queue_setup(struct vb2_queue *vq, 1513 unsigned int *nbuffers, unsigned int *nplanes, 1514 unsigned int sizes[], struct device *alloc_devs[]) 1515 { 1516 struct pxp_ctx *ctx = vb2_get_drv_priv(vq); 1517 struct pxp_q_data *q_data; 1518 unsigned int size, count = *nbuffers; 1519 1520 q_data = get_q_data(ctx, vq->type); 1521 1522 size = q_data->sizeimage; 1523 1524 *nbuffers = count; 1525 1526 if (*nplanes) 1527 return sizes[0] < size ? -EINVAL : 0; 1528 1529 *nplanes = 1; 1530 sizes[0] = size; 1531 1532 dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size); 1533 1534 return 0; 1535 } 1536 1537 static int pxp_buf_prepare(struct vb2_buffer *vb) 1538 { 1539 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1540 struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 1541 struct pxp_dev *dev = ctx->dev; 1542 struct pxp_q_data *q_data; 1543 1544 dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); 1545 1546 q_data = get_q_data(ctx, vb->vb2_queue->type); 1547 if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { 1548 if (vbuf->field == V4L2_FIELD_ANY) 1549 vbuf->field = V4L2_FIELD_NONE; 1550 if (vbuf->field != V4L2_FIELD_NONE) { 1551 dprintk(dev, "%s field isn't supported\n", __func__); 1552 return -EINVAL; 1553 } 1554 } 1555 1556 if (vb2_plane_size(vb, 0) < q_data->sizeimage) { 1557 dprintk(dev, "%s data will not fit into plane (%lu < %lu)\n", 1558 __func__, vb2_plane_size(vb, 0), 1559 (long)q_data->sizeimage); 1560 return -EINVAL; 1561 } 1562 1563 vb2_set_plane_payload(vb, 0, q_data->sizeimage); 1564 1565 return 0; 1566 } 1567 1568 static void pxp_buf_queue(struct vb2_buffer *vb) 1569 { 1570 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1571 struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 1572 1573 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 1574 } 1575 1576 static int pxp_start_streaming(struct vb2_queue *q, unsigned int count) 1577 { 1578 struct pxp_ctx *ctx = vb2_get_drv_priv(q); 1579 struct pxp_q_data *q_data = get_q_data(ctx, q->type); 1580 1581 q_data->sequence = 0; 1582 return 0; 1583 } 1584 1585 static void pxp_stop_streaming(struct vb2_queue *q) 1586 { 1587 struct pxp_ctx *ctx = vb2_get_drv_priv(q); 1588 struct vb2_v4l2_buffer *vbuf; 1589 unsigned long flags; 1590 1591 for (;;) { 1592 if (V4L2_TYPE_IS_OUTPUT(q->type)) 1593 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 1594 else 1595 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 1596 if (vbuf == NULL) 1597 return; 1598 spin_lock_irqsave(&ctx->dev->irqlock, flags); 1599 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); 1600 spin_unlock_irqrestore(&ctx->dev->irqlock, flags); 1601 } 1602 } 1603 1604 static const struct vb2_ops pxp_qops = { 1605 .queue_setup = pxp_queue_setup, 1606 .buf_prepare = pxp_buf_prepare, 1607 .buf_queue = pxp_buf_queue, 1608 .start_streaming = pxp_start_streaming, 1609 .stop_streaming = pxp_stop_streaming, 1610 .wait_prepare = vb2_ops_wait_prepare, 1611 .wait_finish = vb2_ops_wait_finish, 1612 }; 1613 1614 static int queue_init(void *priv, struct vb2_queue *src_vq, 1615 struct vb2_queue *dst_vq) 1616 { 1617 struct pxp_ctx *ctx = priv; 1618 int ret; 1619 1620 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 1621 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 1622 src_vq->drv_priv = ctx; 1623 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 1624 src_vq->ops = &pxp_qops; 1625 src_vq->mem_ops = &vb2_dma_contig_memops; 1626 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 1627 src_vq->lock = &ctx->dev->dev_mutex; 1628 src_vq->dev = ctx->dev->v4l2_dev.dev; 1629 1630 ret = vb2_queue_init(src_vq); 1631 if (ret) 1632 return ret; 1633 1634 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1635 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 1636 dst_vq->drv_priv = ctx; 1637 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 1638 dst_vq->ops = &pxp_qops; 1639 dst_vq->mem_ops = &vb2_dma_contig_memops; 1640 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 1641 dst_vq->lock = &ctx->dev->dev_mutex; 1642 dst_vq->dev = ctx->dev->v4l2_dev.dev; 1643 1644 return vb2_queue_init(dst_vq); 1645 } 1646 1647 /* 1648 * File operations 1649 */ 1650 static int pxp_open(struct file *file) 1651 { 1652 struct pxp_dev *dev = video_drvdata(file); 1653 struct pxp_ctx *ctx = NULL; 1654 struct v4l2_ctrl_handler *hdl; 1655 int rc = 0; 1656 1657 if (mutex_lock_interruptible(&dev->dev_mutex)) 1658 return -ERESTARTSYS; 1659 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 1660 if (!ctx) { 1661 rc = -ENOMEM; 1662 goto open_unlock; 1663 } 1664 1665 v4l2_fh_init(&ctx->fh, video_devdata(file)); 1666 file->private_data = &ctx->fh; 1667 ctx->dev = dev; 1668 hdl = &ctx->hdl; 1669 v4l2_ctrl_handler_init(hdl, 4); 1670 v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); 1671 v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); 1672 v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0); 1673 v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, 1674 0, 255, 1, 255); 1675 if (hdl->error) { 1676 rc = hdl->error; 1677 v4l2_ctrl_handler_free(hdl); 1678 kfree(ctx); 1679 goto open_unlock; 1680 } 1681 ctx->fh.ctrl_handler = hdl; 1682 v4l2_ctrl_handler_setup(hdl); 1683 1684 ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0]; 1685 ctx->q_data[V4L2_M2M_SRC].width = 640; 1686 ctx->q_data[V4L2_M2M_SRC].height = 480; 1687 ctx->q_data[V4L2_M2M_SRC].bytesperline = 1688 pxp_bytesperline(&formats[0], 640); 1689 ctx->q_data[V4L2_M2M_SRC].sizeimage = 1690 pxp_sizeimage(&formats[0], 640, 480); 1691 ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC]; 1692 ctx->colorspace = V4L2_COLORSPACE_REC709; 1693 1694 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); 1695 1696 if (IS_ERR(ctx->fh.m2m_ctx)) { 1697 rc = PTR_ERR(ctx->fh.m2m_ctx); 1698 1699 v4l2_ctrl_handler_free(hdl); 1700 v4l2_fh_exit(&ctx->fh); 1701 kfree(ctx); 1702 goto open_unlock; 1703 } 1704 1705 v4l2_fh_add(&ctx->fh); 1706 atomic_inc(&dev->num_inst); 1707 1708 dprintk(dev, "Created instance: %p, m2m_ctx: %p\n", 1709 ctx, ctx->fh.m2m_ctx); 1710 1711 open_unlock: 1712 mutex_unlock(&dev->dev_mutex); 1713 return rc; 1714 } 1715 1716 static int pxp_release(struct file *file) 1717 { 1718 struct pxp_dev *dev = video_drvdata(file); 1719 struct pxp_ctx *ctx = file2ctx(file); 1720 1721 dprintk(dev, "Releasing instance %p\n", ctx); 1722 1723 v4l2_fh_del(&ctx->fh); 1724 v4l2_fh_exit(&ctx->fh); 1725 v4l2_ctrl_handler_free(&ctx->hdl); 1726 mutex_lock(&dev->dev_mutex); 1727 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); 1728 mutex_unlock(&dev->dev_mutex); 1729 kfree(ctx); 1730 1731 atomic_dec(&dev->num_inst); 1732 1733 return 0; 1734 } 1735 1736 static const struct v4l2_file_operations pxp_fops = { 1737 .owner = THIS_MODULE, 1738 .open = pxp_open, 1739 .release = pxp_release, 1740 .poll = v4l2_m2m_fop_poll, 1741 .unlocked_ioctl = video_ioctl2, 1742 .mmap = v4l2_m2m_fop_mmap, 1743 }; 1744 1745 static const struct video_device pxp_videodev = { 1746 .name = MEM2MEM_NAME, 1747 .vfl_dir = VFL_DIR_M2M, 1748 .fops = &pxp_fops, 1749 .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING, 1750 .ioctl_ops = &pxp_ioctl_ops, 1751 .minor = -1, 1752 .release = video_device_release_empty, 1753 }; 1754 1755 static const struct v4l2_m2m_ops m2m_ops = { 1756 .device_run = pxp_device_run, 1757 .job_ready = pxp_job_ready, 1758 .job_abort = pxp_job_abort, 1759 }; 1760 1761 static int pxp_soft_reset(struct pxp_dev *dev) 1762 { 1763 int ret; 1764 u32 val; 1765 1766 pxp_write(dev, HW_PXP_CTRL_CLR, BM_PXP_CTRL_SFTRST); 1767 pxp_write(dev, HW_PXP_CTRL_CLR, BM_PXP_CTRL_CLKGATE); 1768 1769 pxp_write(dev, HW_PXP_CTRL_SET, BM_PXP_CTRL_SFTRST); 1770 1771 ret = regmap_read_poll_timeout(dev->regmap, HW_PXP_CTRL, val, 1772 val & BM_PXP_CTRL_CLKGATE, 0, 100); 1773 if (ret < 0) 1774 return ret; 1775 1776 pxp_write(dev, HW_PXP_CTRL_CLR, BM_PXP_CTRL_SFTRST); 1777 pxp_write(dev, HW_PXP_CTRL_CLR, BM_PXP_CTRL_CLKGATE); 1778 1779 return 0; 1780 } 1781 1782 static int pxp_probe(struct platform_device *pdev) 1783 { 1784 struct pxp_dev *dev; 1785 struct video_device *vfd; 1786 u32 hw_version; 1787 int irq; 1788 int ret; 1789 void __iomem *mmio; 1790 1791 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 1792 if (!dev) 1793 return -ENOMEM; 1794 1795 dev->pdata = of_device_get_match_data(&pdev->dev); 1796 1797 dev->clk = devm_clk_get(&pdev->dev, "axi"); 1798 if (IS_ERR(dev->clk)) { 1799 ret = PTR_ERR(dev->clk); 1800 dev_err(&pdev->dev, "Failed to get clk: %d\n", ret); 1801 return ret; 1802 } 1803 1804 mmio = devm_platform_ioremap_resource(pdev, 0); 1805 if (IS_ERR(mmio)) 1806 return PTR_ERR(mmio); 1807 dev->regmap = devm_regmap_init_mmio(&pdev->dev, mmio, 1808 &pxp_regmap_config); 1809 1810 irq = platform_get_irq(pdev, 0); 1811 if (irq < 0) 1812 return irq; 1813 1814 spin_lock_init(&dev->irqlock); 1815 1816 ret = devm_request_irq(&pdev->dev, irq, pxp_irq_handler, 0, 1817 dev_name(&pdev->dev), dev); 1818 if (ret < 0) { 1819 dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); 1820 return ret; 1821 } 1822 1823 ret = clk_prepare_enable(dev->clk); 1824 if (ret < 0) 1825 return ret; 1826 1827 ret = pxp_soft_reset(dev); 1828 if (ret < 0) { 1829 dev_err(&pdev->dev, "PXP reset timeout: %d\n", ret); 1830 goto err_clk; 1831 } 1832 1833 hw_version = pxp_read(dev, HW_PXP_VERSION); 1834 dev_dbg(&pdev->dev, "PXP Version %u.%u\n", 1835 PXP_VERSION_MAJOR(hw_version), PXP_VERSION_MINOR(hw_version)); 1836 1837 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); 1838 if (ret) 1839 goto err_clk; 1840 1841 atomic_set(&dev->num_inst, 0); 1842 mutex_init(&dev->dev_mutex); 1843 1844 dev->vfd = pxp_videodev; 1845 vfd = &dev->vfd; 1846 vfd->lock = &dev->dev_mutex; 1847 vfd->v4l2_dev = &dev->v4l2_dev; 1848 1849 video_set_drvdata(vfd, dev); 1850 snprintf(vfd->name, sizeof(vfd->name), "%s", pxp_videodev.name); 1851 v4l2_info(&dev->v4l2_dev, 1852 "Device registered as /dev/video%d\n", vfd->num); 1853 1854 platform_set_drvdata(pdev, dev); 1855 1856 dev->m2m_dev = v4l2_m2m_init(&m2m_ops); 1857 if (IS_ERR(dev->m2m_dev)) { 1858 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); 1859 ret = PTR_ERR(dev->m2m_dev); 1860 goto err_v4l2; 1861 } 1862 1863 ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); 1864 if (ret) { 1865 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); 1866 goto err_m2m; 1867 } 1868 1869 #ifdef CONFIG_MEDIA_CONTROLLER 1870 dev->mdev.dev = &pdev->dev; 1871 strscpy(dev->mdev.model, MEM2MEM_NAME, sizeof(dev->mdev.model)); 1872 media_device_init(&dev->mdev); 1873 dev->v4l2_dev.mdev = &dev->mdev; 1874 1875 ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, 1876 MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER); 1877 if (ret) { 1878 dev_err(&pdev->dev, "Failed to initialize media device\n"); 1879 goto err_vfd; 1880 } 1881 1882 ret = media_device_register(&dev->mdev); 1883 if (ret) { 1884 dev_err(&pdev->dev, "Failed to register media device\n"); 1885 goto err_m2m_mc; 1886 } 1887 #endif 1888 1889 return 0; 1890 1891 #ifdef CONFIG_MEDIA_CONTROLLER 1892 err_m2m_mc: 1893 v4l2_m2m_unregister_media_controller(dev->m2m_dev); 1894 err_vfd: 1895 video_unregister_device(vfd); 1896 #endif 1897 err_m2m: 1898 v4l2_m2m_release(dev->m2m_dev); 1899 err_v4l2: 1900 v4l2_device_unregister(&dev->v4l2_dev); 1901 err_clk: 1902 clk_disable_unprepare(dev->clk); 1903 1904 return ret; 1905 } 1906 1907 static void pxp_remove(struct platform_device *pdev) 1908 { 1909 struct pxp_dev *dev = platform_get_drvdata(pdev); 1910 1911 pxp_write(dev, HW_PXP_CTRL_SET, BM_PXP_CTRL_CLKGATE); 1912 pxp_write(dev, HW_PXP_CTRL_SET, BM_PXP_CTRL_SFTRST); 1913 1914 clk_disable_unprepare(dev->clk); 1915 1916 v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME); 1917 1918 #ifdef CONFIG_MEDIA_CONTROLLER 1919 media_device_unregister(&dev->mdev); 1920 v4l2_m2m_unregister_media_controller(dev->m2m_dev); 1921 #endif 1922 video_unregister_device(&dev->vfd); 1923 v4l2_m2m_release(dev->m2m_dev); 1924 v4l2_device_unregister(&dev->v4l2_dev); 1925 } 1926 1927 static const struct pxp_pdata pxp_imx6ull_pdata = { 1928 .data_path_ctrl0 = pxp_imx6ull_data_path_ctrl0, 1929 }; 1930 1931 static const struct pxp_pdata pxp_imx7d_pdata = { 1932 .data_path_ctrl0 = pxp_imx7d_data_path_ctrl0, 1933 }; 1934 1935 static const struct of_device_id pxp_dt_ids[] = { 1936 { .compatible = "fsl,imx6ull-pxp", .data = &pxp_imx6ull_pdata }, 1937 { .compatible = "fsl,imx7d-pxp", .data = &pxp_imx7d_pdata }, 1938 { }, 1939 }; 1940 MODULE_DEVICE_TABLE(of, pxp_dt_ids); 1941 1942 static struct platform_driver pxp_driver = { 1943 .probe = pxp_probe, 1944 .remove_new = pxp_remove, 1945 .driver = { 1946 .name = MEM2MEM_NAME, 1947 .of_match_table = pxp_dt_ids, 1948 }, 1949 }; 1950 1951 module_platform_driver(pxp_driver); 1952 1953 MODULE_DESCRIPTION("i.MX PXP mem2mem scaler/CSC/rotator"); 1954 MODULE_AUTHOR("Philipp Zabel <kernel@pengutronix.de>"); 1955 MODULE_LICENSE("GPL"); 1956