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