drm/vc4: hvs: Populate YUV to RGB matrices for GEN_6D

All the matrix entries for the YUV to RGB conversion matrices were
being filled with the same coefficients.
Compute the values for the BT601, BT709, and BT2020 matrices in
both full and limited range, and program those into the hardware.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
This commit is contained in:
Dave Stevenson
2025-09-11 15:44:02 +01:00
committed by Dom Cobley
parent e688e39b67
commit 0f1065e1bb

View File

@@ -1845,9 +1845,71 @@ static const struct vc6_csc_coeff_entry csc_coeffs[2][3] = {
}
};
/*
* GEN_6D has a 3x3 matrix of signed 3p12 fixed point values, signed 13bit
* offset, and high and low clamp values. The offset can be applied before or
* after the multiply - for use here for YUV to RGB conversion it is easier to
* put it before.
* Clamp values are always set to max 0xfff and min 0, and the conversion always
* has the offset before the multiply.
*/
struct vc6_d0_csc_coeff_entry {
u32 csc[3][2];
};
static const struct vc6_d0_csc_coeff_entry vc6_d0_csc_coeffs[2][3] = {
[DRM_COLOR_YCBCR_LIMITED_RANGE] = {
[DRM_COLOR_YCBCR_BT601] = {
.csc = {
{ 0x1f002543, 0x00003313 },
{ 0x18002543, 0xf377e5fc },
{ 0x18002543, 0x408d0000 }
}
},
[DRM_COLOR_YCBCR_BT709] = {
.csc = {
{ 0x1f002543, 0x0000395e },
{ 0x18002543, 0xf92deef2 },
{ 0x18002543, 0x43990000 }
}
},
[DRM_COLOR_YCBCR_BT2020] = {
.csc = {
{ 0x1f002543, 0x000035a0 },
{ 0x18002543, 0xfa00eb20 },
{ 0x18002543, 0x44800000 }
}
}
},
[DRM_COLOR_YCBCR_FULL_RANGE] = {
[DRM_COLOR_YCBCR_BT601] = {
.csc = {
{ 0x00002000, 0x00002cdd },
{ 0x18002000, 0xf4fde926 },
{ 0x18002000, 0x38b40000 }
}
},
[DRM_COLOR_YCBCR_BT709] = {
.csc = {
{ 0x00002000, 0x00003265 },
{ 0x18002000, 0xfa01f105 },
{ 0x18002000, 0x3b610000 }
}
},
[DRM_COLOR_YCBCR_BT2020] = {
.csc = {
{ 0x00002000, 0x00002f30 },
{ 0x18002000, 0xfabcedb7 },
{ 0x18002000, 0x3c340000 }
}
}
}
};
static int vc6_hvs_hw_init(struct vc4_hvs *hvs)
{
const struct vc6_csc_coeff_entry *coeffs;
const struct vc6_d0_csc_coeff_entry *d0_coeffs;
unsigned int i;
HVS_WRITE(SCALER6_CONTROL,
@@ -1884,16 +1946,17 @@ static int vc6_hvs_hw_init(struct vc4_hvs *hvs)
HVS_WRITE(CFC1_N_NL_CSC_CTRL(i), BIT(15));
}
} else {
for (i = 0; i < 8; i++) {
HVS_WRITE(SCALER_PI_CMP_CSC_RED0(i), 0x1f002566);
HVS_WRITE(SCALER_PI_CMP_CSC_RED1(i), 0x3994);
for (i = 0; i < 6; i++) {
d0_coeffs = &vc6_d0_csc_coeffs[i / 3][i % 3];
HVS_WRITE(SCALER_PI_CMP_CSC_RED0(i), d0_coeffs->csc[0][0]);
HVS_WRITE(SCALER_PI_CMP_CSC_RED1(i), d0_coeffs->csc[0][1]);
HVS_WRITE(SCALER_PI_CMP_CSC_RED_CLAMP(i), 0xfff00000);
HVS_WRITE(SCALER_PI_CMP_CSC_CFG(i), 0x1);
HVS_WRITE(SCALER_PI_CMP_CSC_GREEN0(i), 0x18002566);
HVS_WRITE(SCALER_PI_CMP_CSC_GREEN1(i), 0xf927eee2);
HVS_WRITE(SCALER_PI_CMP_CSC_CFG(i), 1);
HVS_WRITE(SCALER_PI_CMP_CSC_GREEN0(i), d0_coeffs->csc[1][0]);
HVS_WRITE(SCALER_PI_CMP_CSC_GREEN1(i), d0_coeffs->csc[1][1]);
HVS_WRITE(SCALER_PI_CMP_CSC_GREEN_CLAMP(i), 0xfff00000);
HVS_WRITE(SCALER_PI_CMP_CSC_BLUE0(i), 0x18002566);
HVS_WRITE(SCALER_PI_CMP_CSC_BLUE1(i), 0x43d80000);
HVS_WRITE(SCALER_PI_CMP_CSC_BLUE0(i), d0_coeffs->csc[2][0]);
HVS_WRITE(SCALER_PI_CMP_CSC_BLUE1(i), d0_coeffs->csc[2][1]);
HVS_WRITE(SCALER_PI_CMP_CSC_BLUE_CLAMP(i), 0xfff00000);
}
}