hc
2024-05-16 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb
kernel/drivers/gpu/ipu-v3/ipu-ic.c
....@@ -1,13 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2012-2014 Mentor Graphics Inc.
34 * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
4
- *
5
- * The code contained herein is licensed under the GNU General Public
6
- * License. You may obtain a copy of the GNU General Public License
7
- * Version 2 or later at the following locations:
8
- *
9
- * http://www.opensource.org/licenses/gpl-license.html
10
- * http://www.gnu.org/copyleft/gpl.html
115 */
126
137 #include <linux/types.h>
....@@ -146,8 +140,10 @@
146140 const struct ic_task_regoffs *reg;
147141 const struct ic_task_bitfields *bit;
148142
149
- enum ipu_color_space in_cs, g_in_cs;
150
- enum ipu_color_space out_cs;
143
+ struct ipu_ic_colorspace in_cs;
144
+ struct ipu_ic_colorspace g_in_cs;
145
+ struct ipu_ic_colorspace out_cs;
146
+
151147 bool graphics;
152148 bool rotation;
153149 bool in_use;
....@@ -175,60 +171,11 @@
175171 writel(value, ic->priv->base + offset);
176172 }
177173
178
-struct ic_csc_params {
179
- s16 coeff[3][3]; /* signed 9-bit integer coefficients */
180
- s16 offset[3]; /* signed 11+2-bit fixed point offset */
181
- u8 scale:2; /* scale coefficients * 2^(scale-1) */
182
- bool sat:1; /* saturate to (16, 235(Y) / 240(U, V)) */
183
-};
184
-
185
-/*
186
- * Y = R * .299 + G * .587 + B * .114;
187
- * U = R * -.169 + G * -.332 + B * .500 + 128.;
188
- * V = R * .500 + G * -.419 + B * -.0813 + 128.;
189
- */
190
-static const struct ic_csc_params ic_csc_rgb2ycbcr = {
191
- .coeff = {
192
- { 77, 150, 29 },
193
- { 469, 427, 128 },
194
- { 128, 405, 491 },
195
- },
196
- .offset = { 0, 512, 512 },
197
- .scale = 1,
198
-};
199
-
200
-/* transparent RGB->RGB matrix for graphics combining */
201
-static const struct ic_csc_params ic_csc_rgb2rgb = {
202
- .coeff = {
203
- { 128, 0, 0 },
204
- { 0, 128, 0 },
205
- { 0, 0, 128 },
206
- },
207
- .scale = 2,
208
-};
209
-
210
-/*
211
- * R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
212
- * G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
213
- * B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128);
214
- */
215
-static const struct ic_csc_params ic_csc_ycbcr2rgb = {
216
- .coeff = {
217
- { 149, 0, 204 },
218
- { 149, 462, 408 },
219
- { 149, 255, 0 },
220
- },
221
- .offset = { -446, 266, -554 },
222
- .scale = 2,
223
-};
224
-
225174 static int init_csc(struct ipu_ic *ic,
226
- enum ipu_color_space inf,
227
- enum ipu_color_space outf,
175
+ const struct ipu_ic_csc *csc,
228176 int csc_index)
229177 {
230178 struct ipu_ic_priv *priv = ic->priv;
231
- const struct ic_csc_params *params;
232179 u32 __iomem *base;
233180 const u16 (*c)[3];
234181 const u16 *a;
....@@ -237,27 +184,16 @@
237184 base = (u32 __iomem *)
238185 (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
239186
240
- if (inf == IPUV3_COLORSPACE_YUV && outf == IPUV3_COLORSPACE_RGB)
241
- params = &ic_csc_ycbcr2rgb;
242
- else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_YUV)
243
- params = &ic_csc_rgb2ycbcr;
244
- else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_RGB)
245
- params = &ic_csc_rgb2rgb;
246
- else {
247
- dev_err(priv->ipu->dev, "Unsupported color space conversion\n");
248
- return -EINVAL;
249
- }
250
-
251187 /* Cast to unsigned */
252
- c = (const u16 (*)[3])params->coeff;
253
- a = (const u16 *)params->offset;
188
+ c = (const u16 (*)[3])csc->params.coeff;
189
+ a = (const u16 *)csc->params.offset;
254190
255191 param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
256192 ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
257193 writel(param, base++);
258194
259
- param = ((a[0] & 0x1fe0) >> 5) | (params->scale << 8) |
260
- (params->sat << 10);
195
+ param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
196
+ (csc->params.sat << 10);
261197 writel(param, base++);
262198
263199 param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
....@@ -344,14 +280,14 @@
344280 if (ic->rotation)
345281 ic_conf |= ic->bit->ic_conf_rot_en;
346282
347
- if (ic->in_cs != ic->out_cs)
283
+ if (ic->in_cs.cs != ic->out_cs.cs)
348284 ic_conf |= ic->bit->ic_conf_csc1_en;
349285
350286 if (ic->graphics) {
351287 ic_conf |= ic->bit->ic_conf_cmb_en;
352288 ic_conf |= ic->bit->ic_conf_csc1_en;
353289
354
- if (ic->g_in_cs != ic->out_cs)
290
+ if (ic->g_in_cs.cs != ic->out_cs.cs)
355291 ic_conf |= ic->bit->ic_conf_csc2_en;
356292 }
357293
....@@ -386,11 +322,12 @@
386322 EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
387323
388324 int ipu_ic_task_graphics_init(struct ipu_ic *ic,
389
- enum ipu_color_space in_g_cs,
325
+ const struct ipu_ic_colorspace *g_in_cs,
390326 bool galpha_en, u32 galpha,
391327 bool colorkey_en, u32 colorkey)
392328 {
393329 struct ipu_ic_priv *priv = ic->priv;
330
+ struct ipu_ic_csc csc2;
394331 unsigned long flags;
395332 u32 reg, ic_conf;
396333 int ret = 0;
....@@ -403,20 +340,35 @@
403340 ic_conf = ipu_ic_read(ic, IC_CONF);
404341
405342 if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
343
+ struct ipu_ic_csc csc1;
344
+
345
+ ret = ipu_ic_calc_csc(&csc1,
346
+ V4L2_YCBCR_ENC_601,
347
+ V4L2_QUANTIZATION_FULL_RANGE,
348
+ IPUV3_COLORSPACE_RGB,
349
+ V4L2_YCBCR_ENC_601,
350
+ V4L2_QUANTIZATION_FULL_RANGE,
351
+ IPUV3_COLORSPACE_RGB);
352
+ if (ret)
353
+ goto unlock;
354
+
406355 /* need transparent CSC1 conversion */
407
- ret = init_csc(ic, IPUV3_COLORSPACE_RGB,
408
- IPUV3_COLORSPACE_RGB, 0);
356
+ ret = init_csc(ic, &csc1, 0);
409357 if (ret)
410358 goto unlock;
411359 }
412360
413
- ic->g_in_cs = in_g_cs;
361
+ ic->g_in_cs = *g_in_cs;
362
+ csc2.in_cs = ic->g_in_cs;
363
+ csc2.out_cs = ic->out_cs;
414364
415
- if (ic->g_in_cs != ic->out_cs) {
416
- ret = init_csc(ic, ic->g_in_cs, ic->out_cs, 1);
417
- if (ret)
418
- goto unlock;
419
- }
365
+ ret = __ipu_ic_calc_csc(&csc2);
366
+ if (ret)
367
+ goto unlock;
368
+
369
+ ret = init_csc(ic, &csc2, 1);
370
+ if (ret)
371
+ goto unlock;
420372
421373 if (galpha_en) {
422374 ic_conf |= IC_CONF_IC_GLB_LOC_A;
....@@ -442,51 +394,59 @@
442394 }
443395 EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
444396
445
-int ipu_ic_task_init(struct ipu_ic *ic,
446
- int in_width, int in_height,
447
- int out_width, int out_height,
448
- enum ipu_color_space in_cs,
449
- enum ipu_color_space out_cs)
397
+int ipu_ic_task_init_rsc(struct ipu_ic *ic,
398
+ const struct ipu_ic_csc *csc,
399
+ int in_width, int in_height,
400
+ int out_width, int out_height,
401
+ u32 rsc)
450402 {
451403 struct ipu_ic_priv *priv = ic->priv;
452
- u32 reg, downsize_coeff, resize_coeff;
404
+ u32 downsize_coeff, resize_coeff;
453405 unsigned long flags;
454406 int ret = 0;
455407
456
- /* Setup vertical resizing */
457
- ret = calc_resize_coeffs(ic, in_height, out_height,
458
- &resize_coeff, &downsize_coeff);
459
- if (ret)
460
- return ret;
408
+ if (!rsc) {
409
+ /* Setup vertical resizing */
461410
462
- reg = (downsize_coeff << 30) | (resize_coeff << 16);
411
+ ret = calc_resize_coeffs(ic, in_height, out_height,
412
+ &resize_coeff, &downsize_coeff);
413
+ if (ret)
414
+ return ret;
463415
464
- /* Setup horizontal resizing */
465
- ret = calc_resize_coeffs(ic, in_width, out_width,
466
- &resize_coeff, &downsize_coeff);
467
- if (ret)
468
- return ret;
416
+ rsc = (downsize_coeff << 30) | (resize_coeff << 16);
469417
470
- reg |= (downsize_coeff << 14) | resize_coeff;
418
+ /* Setup horizontal resizing */
419
+ ret = calc_resize_coeffs(ic, in_width, out_width,
420
+ &resize_coeff, &downsize_coeff);
421
+ if (ret)
422
+ return ret;
423
+
424
+ rsc |= (downsize_coeff << 14) | resize_coeff;
425
+ }
471426
472427 spin_lock_irqsave(&priv->lock, flags);
473428
474
- ipu_ic_write(ic, reg, ic->reg->rsc);
429
+ ipu_ic_write(ic, rsc, ic->reg->rsc);
475430
476431 /* Setup color space conversion */
477
- ic->in_cs = in_cs;
478
- ic->out_cs = out_cs;
432
+ ic->in_cs = csc->in_cs;
433
+ ic->out_cs = csc->out_cs;
479434
480
- if (ic->in_cs != ic->out_cs) {
481
- ret = init_csc(ic, ic->in_cs, ic->out_cs, 0);
482
- if (ret)
483
- goto unlock;
484
- }
435
+ ret = init_csc(ic, csc, 0);
485436
486
-unlock:
487437 spin_unlock_irqrestore(&priv->lock, flags);
488438 return ret;
489439 }
440
+
441
+int ipu_ic_task_init(struct ipu_ic *ic,
442
+ const struct ipu_ic_csc *csc,
443
+ int in_width, int in_height,
444
+ int out_width, int out_height)
445
+{
446
+ return ipu_ic_task_init_rsc(ic, csc,
447
+ in_width, in_height,
448
+ out_width, out_height, 0);
449
+}
490450 EXPORT_SYMBOL_GPL(ipu_ic_task_init);
491451
492452 int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,