cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ipu-ic-csc.c (9097B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (C) 2019 Mentor Graphics Inc.
      4 */
      5
      6#include <linux/types.h>
      7#include <linux/init.h>
      8#include <linux/errno.h>
      9#include <linux/err.h>
     10#include <linux/sizes.h>
     11#include "ipu-prv.h"
     12
     13#define QUANT_MAP(q)					\
     14	((q) == V4L2_QUANTIZATION_FULL_RANGE ||		\
     15	 (q) == V4L2_QUANTIZATION_DEFAULT ? 0 : 1)
     16
     17/* identity matrix */
     18static const struct ipu_ic_csc_params identity = {
     19	.coeff = {
     20		{  128,    0,    0, },
     21		{    0,  128,    0, },
     22		{    0,    0,  128, },
     23	},
     24	.offset = { 0, 0, 0, },
     25	.scale = 2,
     26};
     27
     28/*
     29 * RGB full-range to RGB limited-range
     30 *
     31 * R_lim = 0.8588 * R_full + 16
     32 * G_lim = 0.8588 * G_full + 16
     33 * B_lim = 0.8588 * B_full + 16
     34 */
     35static const struct ipu_ic_csc_params rgbf2rgbl = {
     36	.coeff = {
     37		{  220,    0,    0, },
     38		{    0,  220,    0, },
     39		{    0,    0,  220, },
     40	},
     41	.offset = { 64, 64, 64, },
     42	.scale = 1,
     43};
     44
     45/*
     46 * RGB limited-range to RGB full-range
     47 *
     48 * R_full = 1.1644 * (R_lim - 16)
     49 * G_full = 1.1644 * (G_lim - 16)
     50 * B_full = 1.1644 * (B_lim - 16)
     51 */
     52static const struct ipu_ic_csc_params rgbl2rgbf = {
     53	.coeff = {
     54		{  149,    0,    0, },
     55		{    0,  149,    0, },
     56		{    0,    0,  149, },
     57	},
     58	.offset = { -37, -37, -37, },
     59	.scale = 2,
     60};
     61
     62/*
     63 * YUV full-range to YUV limited-range
     64 *
     65 * Y_lim  = 0.8588 * Y_full + 16
     66 * Cb_lim = 0.8784 * (Cb_full - 128) + 128
     67 * Cr_lim = 0.8784 * (Cr_full - 128) + 128
     68 */
     69static const struct ipu_ic_csc_params yuvf2yuvl = {
     70	.coeff = {
     71		{  220,    0,    0, },
     72		{    0,  225,    0, },
     73		{    0,    0,  225, },
     74	},
     75	.offset = { 64, 62, 62, },
     76	.scale = 1,
     77	.sat = true,
     78};
     79
     80/*
     81 * YUV limited-range to YUV full-range
     82 *
     83 * Y_full  = 1.1644 * (Y_lim - 16)
     84 * Cb_full = 1.1384 * (Cb_lim - 128) + 128
     85 * Cr_full = 1.1384 * (Cr_lim - 128) + 128
     86 */
     87static const struct ipu_ic_csc_params yuvl2yuvf = {
     88	.coeff = {
     89		{  149,    0,    0, },
     90		{    0,  146,    0, },
     91		{    0,    0,  146, },
     92	},
     93	.offset = { -37, -35, -35, },
     94	.scale = 2,
     95};
     96
     97static const struct ipu_ic_csc_params *rgb2rgb[] = {
     98	&identity,
     99	&rgbf2rgbl,
    100	&rgbl2rgbf,
    101	&identity,
    102};
    103
    104static const struct ipu_ic_csc_params *yuv2yuv[] = {
    105	&identity,
    106	&yuvf2yuvl,
    107	&yuvl2yuvf,
    108	&identity,
    109};
    110
    111/*
    112 * BT.601 RGB full-range to YUV full-range
    113 *
    114 * Y =  .2990 * R + .5870 * G + .1140 * B
    115 * U = -.1687 * R - .3313 * G + .5000 * B + 128
    116 * V =  .5000 * R - .4187 * G - .0813 * B + 128
    117 */
    118static const struct ipu_ic_csc_params rgbf2yuvf_601 = {
    119	.coeff = {
    120		{   77,  150,   29, },
    121		{  -43,  -85,  128, },
    122		{  128, -107,  -21, },
    123	},
    124	.offset = { 0, 512, 512, },
    125	.scale = 1,
    126};
    127
    128/* BT.601 RGB full-range to YUV limited-range */
    129static const struct ipu_ic_csc_params rgbf2yuvl_601 = {
    130	.coeff = {
    131		{   66,  129,   25, },
    132		{  -38,  -74,  112, },
    133		{  112,  -94,  -18, },
    134	},
    135	.offset = { 64, 512, 512, },
    136	.scale = 1,
    137	.sat = true,
    138};
    139
    140/* BT.601 RGB limited-range to YUV full-range */
    141static const struct ipu_ic_csc_params rgbl2yuvf_601 = {
    142	.coeff = {
    143		{   89,  175,   34, },
    144		{  -50,  -99,  149, },
    145		{  149, -125,  -24, },
    146	},
    147	.offset = { -75, 512, 512, },
    148	.scale = 1,
    149};
    150
    151/* BT.601 RGB limited-range to YUV limited-range */
    152static const struct ipu_ic_csc_params rgbl2yuvl_601 = {
    153	.coeff = {
    154		{   77,  150,   29, },
    155		{  -44,  -87,  131, },
    156		{  131, -110,  -21, },
    157	},
    158	.offset = { 0, 512, 512, },
    159	.scale = 1,
    160	.sat = true,
    161};
    162
    163/*
    164 * BT.601 YUV full-range to RGB full-range
    165 *
    166 * R = 1. * Y +      0 * (Cb - 128) + 1.4020 * (Cr - 128)
    167 * G = 1. * Y -  .3441 * (Cb - 128) -  .7141 * (Cr - 128)
    168 * B = 1. * Y + 1.7720 * (Cb - 128) +      0 * (Cr - 128)
    169 *
    170 * equivalently (factoring out the offsets):
    171 *
    172 * R = 1. * Y  +      0 * Cb + 1.4020 * Cr - 179.456
    173 * G = 1. * Y  -  .3441 * Cb -  .7141 * Cr + 135.450
    174 * B = 1. * Y  + 1.7720 * Cb +      0 * Cr - 226.816
    175 */
    176static const struct ipu_ic_csc_params yuvf2rgbf_601 = {
    177	.coeff = {
    178		{  128,    0,  179, },
    179		{  128,  -44,  -91, },
    180		{  128,  227,    0, },
    181	},
    182	.offset = { -359, 271, -454, },
    183	.scale = 2,
    184};
    185
    186/* BT.601 YUV full-range to RGB limited-range */
    187static const struct ipu_ic_csc_params yuvf2rgbl_601 = {
    188	.coeff = {
    189		{  110,    0,  154, },
    190		{  110,  -38,  -78, },
    191		{  110,  195,    0, },
    192	},
    193	.offset = { -276, 265, -358, },
    194	.scale = 2,
    195};
    196
    197/* BT.601 YUV limited-range to RGB full-range */
    198static const struct ipu_ic_csc_params yuvl2rgbf_601 = {
    199	.coeff = {
    200		{   75,    0,  102, },
    201		{   75,  -25,  -52, },
    202		{   75,  129,    0, },
    203	},
    204	.offset = { -223, 136, -277, },
    205	.scale = 3,
    206};
    207
    208/* BT.601 YUV limited-range to RGB limited-range */
    209static const struct ipu_ic_csc_params yuvl2rgbl_601 = {
    210	.coeff = {
    211		{  128,    0,  175, },
    212		{  128,  -43,  -89, },
    213		{  128,  222,    0, },
    214	},
    215	.offset = { -351, 265, -443, },
    216	.scale = 2,
    217};
    218
    219static const struct ipu_ic_csc_params *rgb2yuv_601[] = {
    220	&rgbf2yuvf_601,
    221	&rgbf2yuvl_601,
    222	&rgbl2yuvf_601,
    223	&rgbl2yuvl_601,
    224};
    225
    226static const struct ipu_ic_csc_params *yuv2rgb_601[] = {
    227	&yuvf2rgbf_601,
    228	&yuvf2rgbl_601,
    229	&yuvl2rgbf_601,
    230	&yuvl2rgbl_601,
    231};
    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 */
    240static 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 */
    251static 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 */
    263static 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 */
    274static 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 */
    298static 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 */
    309static 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 */
    320static 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 */
    331static 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
    341static const struct ipu_ic_csc_params *rgb2yuv_709[] = {
    342	&rgbf2yuvf_709,
    343	&rgbf2yuvl_709,
    344	&rgbl2yuvf_709,
    345	&rgbl2yuvl_709,
    346};
    347
    348static const struct ipu_ic_csc_params *yuv2rgb_709[] = {
    349	&yuvf2rgbf_709,
    350	&yuvf2rgbl_709,
    351	&yuvl2rgbf_709,
    352	&yuvl2rgbl_709,
    353};
    354
    355static int calc_csc_coeffs(struct ipu_ic_csc *csc)
    356{
    357	const struct ipu_ic_csc_params **params_tbl;
    358	int tbl_idx;
    359
    360	tbl_idx = (QUANT_MAP(csc->in_cs.quant) << 1) |
    361		QUANT_MAP(csc->out_cs.quant);
    362
    363	if (csc->in_cs.cs == csc->out_cs.cs) {
    364		csc->params = (csc->in_cs.cs == IPUV3_COLORSPACE_YUV) ?
    365			*yuv2yuv[tbl_idx] : *rgb2rgb[tbl_idx];
    366
    367		return 0;
    368	}
    369
    370	/* YUV <-> RGB encoding is required */
    371
    372	switch (csc->out_cs.enc) {
    373	case V4L2_YCBCR_ENC_601:
    374		params_tbl = (csc->in_cs.cs == IPUV3_COLORSPACE_YUV) ?
    375			yuv2rgb_601 : rgb2yuv_601;
    376		break;
    377	case V4L2_YCBCR_ENC_709:
    378		params_tbl = (csc->in_cs.cs == IPUV3_COLORSPACE_YUV) ?
    379			yuv2rgb_709 : rgb2yuv_709;
    380		break;
    381	default:
    382		return -ENOTSUPP;
    383	}
    384
    385	csc->params = *params_tbl[tbl_idx];
    386
    387	return 0;
    388}
    389
    390int __ipu_ic_calc_csc(struct ipu_ic_csc *csc)
    391{
    392	return calc_csc_coeffs(csc);
    393}
    394EXPORT_SYMBOL_GPL(__ipu_ic_calc_csc);
    395
    396int ipu_ic_calc_csc(struct ipu_ic_csc *csc,
    397		    enum v4l2_ycbcr_encoding in_enc,
    398		    enum v4l2_quantization in_quant,
    399		    enum ipu_color_space in_cs,
    400		    enum v4l2_ycbcr_encoding out_enc,
    401		    enum v4l2_quantization out_quant,
    402		    enum ipu_color_space out_cs)
    403{
    404	ipu_ic_fill_colorspace(&csc->in_cs, in_enc, in_quant, in_cs);
    405	ipu_ic_fill_colorspace(&csc->out_cs, out_enc, out_quant, out_cs);
    406
    407	return __ipu_ic_calc_csc(csc);
    408}
    409EXPORT_SYMBOL_GPL(ipu_ic_calc_csc);