mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-03 20:06:41 +07:00
drm/i915: Add support for CHV pipe B sprite CSC
CHV has a programmable CSC unit on the pipe B sprites. Program the unit appropriately for BT.601 limited range YCbCr to full range RGB color conversion. This matches the programming we currently do for sprites on the other pipes and on other platforms. It seems the CSC only works when the input data is YCbCr. For RGB pixel formats it doesn't matter what we program into the CSC registers. Doesn't make much sense to me especially since the register names give the impression that RGB input data would also work. But that's how it behaves here. In the review discussions there's been some nice math to explain the values obtained here. First about the YCbCr->RGB matrix: "I had the RGB->YCbCr matrix, inverted it and the values came out. But they should match the wikipedia article. Also keep in mind that the coefficients are in .12 in fixed point format, hence we need a 1<<12 factor. So let's try it: Kb=.114 Kr=.299 (1<<12) * 255/219 ~= 4769 -(1<<12) * 255/112*(1-Kb)*Kb/(1-Kb-Kr) ~= -1605 -(1<<12) * 255/112*(1-Kr)*Kr/(1-Kb-Kr) ~= -3330 (1<<12) * 255/112*(1-Kr) ~= 6537 (1<<12) * 255/112*(1-Kb) ~= 8263 "Looks like the same values to me." And then about the limits used for clamping: "> where did you get these min/max? "The hardware apparently deals in 10bit values, so we need to multiply everything by 4 when we start with the 8bit min/max values. Y = [16:235] * 4 = [64:940] CbCr = ([16:240] - 128) * 4 = [-112:112] * 4 = [-448:448] "The -128 being the -0.5 bias that the hardware already applied before the data entered the CSC unit." Raw data is also supplied in 10bpc in the registers. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by Rodrigo Vivi <rodrigo.vivi@intel.com> [danvet: Copypaste explanations&math from the review discussion.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
efee833a2d
commit
6ca2aeb27b
@ -4565,6 +4565,39 @@ enum punit_power_well {
|
||||
#define SPCONSTALPHA(pipe, plane) _PIPE(pipe * 2 + plane, _SPACONSTALPHA, _SPBCONSTALPHA)
|
||||
#define SPGAMC(pipe, plane) _PIPE(pipe * 2 + plane, _SPAGAMC, _SPBGAMC)
|
||||
|
||||
/*
|
||||
* CHV pipe B sprite CSC
|
||||
*
|
||||
* |cr| |c0 c1 c2| |cr + cr_ioff| |cr_ooff|
|
||||
* |yg| = |c3 c4 c5| x |yg + yg_ioff| + |yg_ooff|
|
||||
* |cb| |c6 c7 c8| |cb + cr_ioff| |cb_ooff|
|
||||
*/
|
||||
#define SPCSCYGOFF(sprite) (VLV_DISPLAY_BASE + 0x6d900 + (sprite) * 0x1000)
|
||||
#define SPCSCCBOFF(sprite) (VLV_DISPLAY_BASE + 0x6d904 + (sprite) * 0x1000)
|
||||
#define SPCSCCROFF(sprite) (VLV_DISPLAY_BASE + 0x6d908 + (sprite) * 0x1000)
|
||||
#define SPCSC_OOFF(x) (((x) & 0x7ff) << 16) /* s11 */
|
||||
#define SPCSC_IOFF(x) (((x) & 0x7ff) << 0) /* s11 */
|
||||
|
||||
#define SPCSCC01(sprite) (VLV_DISPLAY_BASE + 0x6d90c + (sprite) * 0x1000)
|
||||
#define SPCSCC23(sprite) (VLV_DISPLAY_BASE + 0x6d910 + (sprite) * 0x1000)
|
||||
#define SPCSCC45(sprite) (VLV_DISPLAY_BASE + 0x6d914 + (sprite) * 0x1000)
|
||||
#define SPCSCC67(sprite) (VLV_DISPLAY_BASE + 0x6d918 + (sprite) * 0x1000)
|
||||
#define SPCSCC8(sprite) (VLV_DISPLAY_BASE + 0x6d91c + (sprite) * 0x1000)
|
||||
#define SPCSC_C1(x) (((x) & 0x7fff) << 16) /* s3.12 */
|
||||
#define SPCSC_C0(x) (((x) & 0x7fff) << 0) /* s3.12 */
|
||||
|
||||
#define SPCSCYGICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d920 + (sprite) * 0x1000)
|
||||
#define SPCSCCBICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d924 + (sprite) * 0x1000)
|
||||
#define SPCSCCRICLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d928 + (sprite) * 0x1000)
|
||||
#define SPCSC_IMAX(x) (((x) & 0x7ff) << 16) /* s11 */
|
||||
#define SPCSC_IMIN(x) (((x) & 0x7ff) << 0) /* s11 */
|
||||
|
||||
#define SPCSCYGOCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d92c + (sprite) * 0x1000)
|
||||
#define SPCSCCBOCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d930 + (sprite) * 0x1000)
|
||||
#define SPCSCCROCLAMP(sprite) (VLV_DISPLAY_BASE + 0x6d934 + (sprite) * 0x1000)
|
||||
#define SPCSC_OMAX(x) ((x) << 16) /* u10 */
|
||||
#define SPCSC_OMIN(x) ((x) << 0) /* u10 */
|
||||
|
||||
/* Skylake plane registers */
|
||||
|
||||
#define _PLANE_CTL_1_A 0x70180
|
||||
|
@ -37,6 +37,20 @@
|
||||
#include <drm/i915_drm.h>
|
||||
#include "i915_drv.h"
|
||||
|
||||
static bool
|
||||
format_is_yuv(uint32_t format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_YUYV:
|
||||
case DRM_FORMAT_UYVY:
|
||||
case DRM_FORMAT_VYUY:
|
||||
case DRM_FORMAT_YVYU:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
|
||||
{
|
||||
/* paranoia */
|
||||
@ -319,6 +333,45 @@ skl_get_colorkey(struct drm_plane *drm_plane,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private;
|
||||
int plane = intel_plane->plane;
|
||||
|
||||
/* Seems RGB data bypasses the CSC always */
|
||||
if (!format_is_yuv(format))
|
||||
return;
|
||||
|
||||
/*
|
||||
* BT.601 limited range YCbCr -> full range RGB
|
||||
*
|
||||
* |r| | 6537 4769 0| |cr |
|
||||
* |g| = |-3330 4769 -1605| x |y-64|
|
||||
* |b| | 0 4769 8263| |cb |
|
||||
*
|
||||
* Cb and Cr apparently come in as signed already, so no
|
||||
* need for any offset. For Y we need to remove the offset.
|
||||
*/
|
||||
I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
|
||||
I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
|
||||
I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
|
||||
|
||||
I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537));
|
||||
I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0));
|
||||
I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769));
|
||||
I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0));
|
||||
I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263));
|
||||
|
||||
I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64));
|
||||
I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
|
||||
I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
|
||||
|
||||
I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
}
|
||||
|
||||
static void
|
||||
vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
@ -430,6 +483,9 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
|
||||
|
||||
intel_update_primary_plane(intel_crtc);
|
||||
|
||||
if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
|
||||
chv_update_csc(intel_plane, fb->pixel_format);
|
||||
|
||||
I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
|
||||
I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
|
||||
|
||||
@ -1004,20 +1060,6 @@ ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
|
||||
key->flags = I915_SET_COLORKEY_NONE;
|
||||
}
|
||||
|
||||
static bool
|
||||
format_is_yuv(uint32_t format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_YUYV:
|
||||
case DRM_FORMAT_UYVY:
|
||||
case DRM_FORMAT_VYUY:
|
||||
case DRM_FORMAT_YVYU:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool colorkey_enabled(struct intel_plane *intel_plane)
|
||||
{
|
||||
struct drm_intel_sprite_colorkey key;
|
||||
|
Loading…
Reference in New Issue
Block a user