Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpu: ipu-v3: ipu-ic-csc: Add support for Rec.709 encoding

Add support for Rec.709 encoding and inverse encoding.

Reported-by: Tim Harvey <tharvey@gateworks.com>
Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

authored by

Steve Longerbeam and committed by
Philipp Zabel
614014cf e3e4820d

+134 -5
+134 -5
drivers/gpu/ipu-v3/ipu-ic-csc.c
··· 230 230 &yuvl2rgbl_601, 231 231 }; 232 232 233 + /* 234 + * REC.709 encoding from RGB full range to YUV full range: 235 + * 236 + * Y = .2126 * R + .7152 * G + .0722 * B 237 + * U = -.1146 * R - .3854 * G + .5000 * B + 128 238 + * V = .5000 * R - .4542 * G - .0458 * B + 128 239 + */ 240 + static const struct ipu_ic_csc_params rgbf2yuvf_709 = { 241 + .coeff = { 242 + { 54, 183, 19 }, 243 + { -29, -99, 128 }, 244 + { 128, -116, -12 }, 245 + }, 246 + .offset = { 0, 512, 512 }, 247 + .scale = 1, 248 + }; 249 + 250 + /* Rec.709 RGB full-range to YUV limited-range */ 251 + static const struct ipu_ic_csc_params rgbf2yuvl_709 = { 252 + .coeff = { 253 + { 47, 157, 16, }, 254 + { -26, -87, 112, }, 255 + { 112, -102, -10, }, 256 + }, 257 + .offset = { 64, 512, 512, }, 258 + .scale = 1, 259 + .sat = true, 260 + }; 261 + 262 + /* Rec.709 RGB limited-range to YUV full-range */ 263 + static const struct ipu_ic_csc_params rgbl2yuvf_709 = { 264 + .coeff = { 265 + { 63, 213, 22, }, 266 + { -34, -115, 149, }, 267 + { 149, -135, -14, }, 268 + }, 269 + .offset = { -75, 512, 512, }, 270 + .scale = 1, 271 + }; 272 + 273 + /* Rec.709 RGB limited-range to YUV limited-range */ 274 + static const struct ipu_ic_csc_params rgbl2yuvl_709 = { 275 + .coeff = { 276 + { 54, 183, 18, }, 277 + { -30, -101, 131, }, 278 + { 131, -119, -12, }, 279 + }, 280 + .offset = { 0, 512, 512, }, 281 + .scale = 1, 282 + .sat = true, 283 + }; 284 + 285 + /* 286 + * Inverse REC.709 encoding from YUV full range to RGB full range: 287 + * 288 + * R = 1. * Y + 0 * (Cb - 128) + 1.5748 * (Cr - 128) 289 + * G = 1. * Y - .1873 * (Cb - 128) - .4681 * (Cr - 128) 290 + * B = 1. * Y + 1.8556 * (Cb - 128) + 0 * (Cr - 128) 291 + * 292 + * equivalently (factoring out the offsets): 293 + * 294 + * R = 1. * Y + 0 * Cb + 1.5748 * Cr - 201.574 295 + * G = 1. * Y - .1873 * Cb - .4681 * Cr + 83.891 296 + * B = 1. * Y + 1.8556 * Cb + 0 * Cr - 237.517 297 + */ 298 + static const struct ipu_ic_csc_params yuvf2rgbf_709 = { 299 + .coeff = { 300 + { 128, 0, 202 }, 301 + { 128, -24, -60 }, 302 + { 128, 238, 0 }, 303 + }, 304 + .offset = { -403, 168, -475 }, 305 + .scale = 2, 306 + }; 307 + 308 + /* Rec.709 YUV full-range to RGB limited-range */ 309 + static const struct ipu_ic_csc_params yuvf2rgbl_709 = { 310 + .coeff = { 311 + { 110, 0, 173, }, 312 + { 110, -21, -51, }, 313 + { 110, 204, 0, }, 314 + }, 315 + .offset = { -314, 176, -376, }, 316 + .scale = 2, 317 + }; 318 + 319 + /* Rec.709 YUV limited-range to RGB full-range */ 320 + static const struct ipu_ic_csc_params yuvl2rgbf_709 = { 321 + .coeff = { 322 + { 75, 0, 115, }, 323 + { 75, -14, -34, }, 324 + { 75, 135, 0, }, 325 + }, 326 + .offset = { -248, 77, -289, }, 327 + .scale = 3, 328 + }; 329 + 330 + /* Rec.709 YUV limited-range to RGB limited-range */ 331 + static const struct ipu_ic_csc_params yuvl2rgbl_709 = { 332 + .coeff = { 333 + { 128, 0, 197, }, 334 + { 128, -23, -59, }, 335 + { 128, 232, 0, }, 336 + }, 337 + .offset = { -394, 164, -464, }, 338 + .scale = 2, 339 + }; 340 + 341 + static const struct ipu_ic_csc_params *rgb2yuv_709[] = { 342 + &rgbf2yuvf_709, 343 + &rgbf2yuvl_709, 344 + &rgbl2yuvf_709, 345 + &rgbl2yuvl_709, 346 + }; 347 + 348 + static const struct ipu_ic_csc_params *yuv2rgb_709[] = { 349 + &yuvf2rgbf_709, 350 + &yuvf2rgbl_709, 351 + &yuvl2rgbf_709, 352 + &yuvl2rgbl_709, 353 + }; 354 + 233 355 static int calc_csc_coeffs(struct ipu_ic_csc *csc) 234 356 { 235 357 const struct ipu_ic_csc_params **params_tbl; 236 358 int tbl_idx; 237 - 238 - if (csc->out_cs.enc != V4L2_YCBCR_ENC_601) 239 - return -ENOTSUPP; 240 359 241 360 tbl_idx = (QUANT_MAP(csc->in_cs.quant) << 1) | 242 361 QUANT_MAP(csc->out_cs.quant); ··· 369 250 370 251 /* YUV <-> RGB encoding is required */ 371 252 372 - params_tbl = (csc->in_cs.cs == IPUV3_COLORSPACE_YUV) ? 373 - yuv2rgb_601 : rgb2yuv_601; 253 + switch (csc->out_cs.enc) { 254 + case V4L2_YCBCR_ENC_601: 255 + params_tbl = (csc->in_cs.cs == IPUV3_COLORSPACE_YUV) ? 256 + yuv2rgb_601 : rgb2yuv_601; 257 + break; 258 + case V4L2_YCBCR_ENC_709: 259 + params_tbl = (csc->in_cs.cs == IPUV3_COLORSPACE_YUV) ? 260 + yuv2rgb_709 : rgb2yuv_709; 261 + break; 262 + default: 263 + return -ENOTSUPP; 264 + } 374 265 375 266 csc->params = *params_tbl[tbl_idx]; 376 267