mirror of https://github.com/torvalds/linux.git
Merge tag 'topic/drm-intel-plane-color-pipeline-2025-12-04' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next
drm/i915 topic pull request for v6.19: Features and functionality: - Add plane color management support (Uma, Chaitanya) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Jani Nikula <jani.nikula@intel.com> Link: https://patch.msgid.link/e7129c6afd6208719d2f5124da86e810505e7a7b@intel.com
This commit is contained in:
commit
c7685d1110
|
|
@ -239,6 +239,8 @@ i915-y += \
|
||||||
display/intel_cdclk.o \
|
display/intel_cdclk.o \
|
||||||
display/intel_cmtg.o \
|
display/intel_cmtg.o \
|
||||||
display/intel_color.o \
|
display/intel_color.o \
|
||||||
|
display/intel_colorop.o \
|
||||||
|
display/intel_color_pipeline.o \
|
||||||
display/intel_combo_phy.o \
|
display/intel_combo_phy.o \
|
||||||
display/intel_connector.o \
|
display/intel_connector.o \
|
||||||
display/intel_crtc.o \
|
display/intel_crtc.o \
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@
|
||||||
#include "intel_display_utils.h"
|
#include "intel_display_utils.h"
|
||||||
#include "intel_dsb.h"
|
#include "intel_dsb.h"
|
||||||
#include "intel_vrr.h"
|
#include "intel_vrr.h"
|
||||||
|
#include "skl_universal_plane.h"
|
||||||
|
#include "skl_universal_plane_regs.h"
|
||||||
|
|
||||||
struct intel_color_funcs {
|
struct intel_color_funcs {
|
||||||
int (*color_check)(struct intel_atomic_state *state,
|
int (*color_check)(struct intel_atomic_state *state,
|
||||||
|
|
@ -87,6 +89,14 @@ struct intel_color_funcs {
|
||||||
* Read config other than LUTs and CSCs, before them. Optional.
|
* Read config other than LUTs and CSCs, before them. Optional.
|
||||||
*/
|
*/
|
||||||
void (*get_config)(struct intel_crtc_state *crtc_state);
|
void (*get_config)(struct intel_crtc_state *crtc_state);
|
||||||
|
|
||||||
|
/* Plane CSC*/
|
||||||
|
void (*load_plane_csc_matrix)(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state);
|
||||||
|
|
||||||
|
/* Plane Pre/Post CSC */
|
||||||
|
void (*load_plane_luts)(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CTM_COEFF_SIGN (1ULL << 63)
|
#define CTM_COEFF_SIGN (1ULL << 63)
|
||||||
|
|
@ -609,6 +619,8 @@ static u16 ctm_to_twos_complement(u64 coeff, int int_bits, int frac_bits)
|
||||||
if (CTM_COEFF_NEGATIVE(coeff))
|
if (CTM_COEFF_NEGATIVE(coeff))
|
||||||
c = -c;
|
c = -c;
|
||||||
|
|
||||||
|
int_bits = max(int_bits, 1);
|
||||||
|
|
||||||
c = clamp(c, -(s64)BIT(int_bits + frac_bits - 1),
|
c = clamp(c, -(s64)BIT(int_bits + frac_bits - 1),
|
||||||
(s64)(BIT(int_bits + frac_bits - 1) - 1));
|
(s64)(BIT(int_bits + frac_bits - 1) - 1));
|
||||||
|
|
||||||
|
|
@ -3836,6 +3848,266 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xelpd_load_plane_csc_matrix(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(plane_state);
|
||||||
|
const struct drm_plane_state *state = &plane_state->uapi;
|
||||||
|
enum pipe pipe = to_intel_plane(state->plane)->pipe;
|
||||||
|
enum plane_id plane = to_intel_plane(state->plane)->id;
|
||||||
|
const struct drm_property_blob *blob = plane_state->hw.ctm;
|
||||||
|
struct drm_color_ctm_3x4 *ctm;
|
||||||
|
const u64 *input;
|
||||||
|
u16 coeffs[9] = {};
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!icl_is_hdr_plane(display, plane) || !blob)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ctm = blob->data;
|
||||||
|
input = ctm->matrix;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert fixed point S31.32 input to format supported by the
|
||||||
|
* hardware.
|
||||||
|
*/
|
||||||
|
for (i = 0, j = 0; i < ARRAY_SIZE(coeffs); i++) {
|
||||||
|
u64 abs_coeff = ((1ULL << 63) - 1) & input[j];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clamp input value to min/max supported by
|
||||||
|
* hardware.
|
||||||
|
*/
|
||||||
|
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
|
||||||
|
|
||||||
|
/* sign bit */
|
||||||
|
if (CTM_COEFF_NEGATIVE(input[j]))
|
||||||
|
coeffs[i] |= 1 << 15;
|
||||||
|
|
||||||
|
if (abs_coeff < CTM_COEFF_0_125)
|
||||||
|
coeffs[i] |= (3 << 12) |
|
||||||
|
ILK_CSC_COEFF_FP(abs_coeff, 12);
|
||||||
|
else if (abs_coeff < CTM_COEFF_0_25)
|
||||||
|
coeffs[i] |= (2 << 12) |
|
||||||
|
ILK_CSC_COEFF_FP(abs_coeff, 11);
|
||||||
|
else if (abs_coeff < CTM_COEFF_0_5)
|
||||||
|
coeffs[i] |= (1 << 12) |
|
||||||
|
ILK_CSC_COEFF_FP(abs_coeff, 10);
|
||||||
|
else if (abs_coeff < CTM_COEFF_1_0)
|
||||||
|
coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
|
||||||
|
else if (abs_coeff < CTM_COEFF_2_0)
|
||||||
|
coeffs[i] |= (7 << 12) |
|
||||||
|
ILK_CSC_COEFF_FP(abs_coeff, 8);
|
||||||
|
else
|
||||||
|
coeffs[i] |= (6 << 12) |
|
||||||
|
ILK_CSC_COEFF_FP(abs_coeff, 7);
|
||||||
|
|
||||||
|
/* Skip postoffs */
|
||||||
|
if (!((j + 2) % 4))
|
||||||
|
j += 2;
|
||||||
|
else
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 0),
|
||||||
|
coeffs[0] << 16 | coeffs[1]);
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 1),
|
||||||
|
coeffs[2] << 16);
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 2),
|
||||||
|
coeffs[3] << 16 | coeffs[4]);
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 3),
|
||||||
|
coeffs[5] << 16);
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 4),
|
||||||
|
coeffs[6] << 16 | coeffs[7]);
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 5),
|
||||||
|
coeffs[8] << 16);
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane, 0), 0);
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane, 1), 0);
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane, 2), 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Conversion from S31.32 to S0.12. BIT[12] is the signed bit
|
||||||
|
*/
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_CSC_POSTOFF(pipe, plane, 0),
|
||||||
|
ctm_to_twos_complement(input[3], 0, 12));
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_CSC_POSTOFF(pipe, plane, 1),
|
||||||
|
ctm_to_twos_complement(input[7], 0, 12));
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_CSC_POSTOFF(pipe, plane, 2),
|
||||||
|
ctm_to_twos_complement(input[11], 0, 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xelpd_program_plane_pre_csc_lut(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(plane_state);
|
||||||
|
const struct drm_plane_state *state = &plane_state->uapi;
|
||||||
|
enum pipe pipe = to_intel_plane(state->plane)->pipe;
|
||||||
|
enum plane_id plane = to_intel_plane(state->plane)->id;
|
||||||
|
const struct drm_color_lut32 *pre_csc_lut = plane_state->hw.degamma_lut->data;
|
||||||
|
u32 i, lut_size;
|
||||||
|
|
||||||
|
if (icl_is_hdr_plane(display, plane)) {
|
||||||
|
lut_size = 128;
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0),
|
||||||
|
PLANE_PAL_PREC_AUTO_INCREMENT);
|
||||||
|
|
||||||
|
if (pre_csc_lut) {
|
||||||
|
for (i = 0; i < lut_size; i++) {
|
||||||
|
u32 lut_val = drm_color_lut32_extract(pre_csc_lut[i].green, 24);
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
|
||||||
|
lut_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Program the max register to clamp values > 1.0. */
|
||||||
|
/* TODO: Restrict to 0x7ffffff */
|
||||||
|
do {
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
|
||||||
|
(1 << 24));
|
||||||
|
} while (i++ > 130);
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < lut_size; i++) {
|
||||||
|
u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1);
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
|
||||||
|
1 << 24);
|
||||||
|
} while (i++ < 130);
|
||||||
|
}
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(plane_state);
|
||||||
|
const struct drm_plane_state *state = &plane_state->uapi;
|
||||||
|
enum pipe pipe = to_intel_plane(state->plane)->pipe;
|
||||||
|
enum plane_id plane = to_intel_plane(state->plane)->id;
|
||||||
|
const struct drm_color_lut32 *post_csc_lut = plane_state->hw.gamma_lut->data;
|
||||||
|
u32 i, lut_size, lut_val;
|
||||||
|
|
||||||
|
if (icl_is_hdr_plane(display, plane)) {
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0),
|
||||||
|
PLANE_PAL_PREC_AUTO_INCREMENT);
|
||||||
|
/* TODO: Add macro */
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, 0),
|
||||||
|
PLANE_PAL_PREC_AUTO_INCREMENT);
|
||||||
|
if (post_csc_lut) {
|
||||||
|
lut_size = 32;
|
||||||
|
for (i = 0; i < lut_size; i++) {
|
||||||
|
lut_val = drm_color_lut32_extract(post_csc_lut[i].green, 24);
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0),
|
||||||
|
lut_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Segment 2 */
|
||||||
|
do {
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0),
|
||||||
|
(1 << 24));
|
||||||
|
} while (i++ < 34);
|
||||||
|
} else {
|
||||||
|
/*TODO: Add for segment 0 */
|
||||||
|
lut_size = 32;
|
||||||
|
for (i = 0; i < lut_size; i++) {
|
||||||
|
u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1);
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0),
|
||||||
|
1 << 24);
|
||||||
|
} while (i++ < 34);
|
||||||
|
}
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0);
|
||||||
|
intel_de_write_dsb(display, dsb,
|
||||||
|
PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, 0), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xelpd_plane_load_luts(struct intel_dsb *dsb, const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
if (plane_state->hw.degamma_lut)
|
||||||
|
xelpd_program_plane_pre_csc_lut(dsb, plane_state);
|
||||||
|
|
||||||
|
if (plane_state->hw.gamma_lut)
|
||||||
|
xelpd_program_plane_post_csc_lut(dsb, plane_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 glk_3dlut_10(const struct drm_color_lut32 *color)
|
||||||
|
{
|
||||||
|
return REG_FIELD_PREP(LUT_3D_DATA_RED_MASK, drm_color_lut32_extract(color->red, 10)) |
|
||||||
|
REG_FIELD_PREP(LUT_3D_DATA_GREEN_MASK, drm_color_lut32_extract(color->green, 10)) |
|
||||||
|
REG_FIELD_PREP(LUT_3D_DATA_BLUE_MASK, drm_color_lut32_extract(color->blue, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void glk_load_lut_3d(struct intel_dsb *dsb,
|
||||||
|
struct intel_crtc *crtc,
|
||||||
|
const struct drm_property_blob *blob)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(crtc->base.dev);
|
||||||
|
const struct drm_color_lut32 *lut = blob->data;
|
||||||
|
int i, lut_size = drm_color_lut32_size(blob);
|
||||||
|
enum pipe pipe = crtc->pipe;
|
||||||
|
|
||||||
|
if (!dsb && intel_de_read(display, LUT_3D_CTL(pipe)) & LUT_3D_READY) {
|
||||||
|
drm_err(display->drm, "[CRTC:%d:%s] 3D LUT not ready, not loading LUTs\n",
|
||||||
|
crtc->base.base.id, crtc->base.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb, LUT_3D_INDEX(pipe), LUT_3D_AUTO_INCREMENT);
|
||||||
|
for (i = 0; i < lut_size; i++)
|
||||||
|
intel_de_write_dsb(display, dsb, LUT_3D_DATA(pipe), glk_3dlut_10(&lut[i]));
|
||||||
|
intel_de_write_dsb(display, dsb, LUT_3D_INDEX(pipe), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void glk_lut_3d_commit(struct intel_dsb *dsb, struct intel_crtc *crtc, bool enable)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(crtc);
|
||||||
|
enum pipe pipe = crtc->pipe;
|
||||||
|
u32 val = 0;
|
||||||
|
|
||||||
|
if (!dsb && intel_de_read(display, LUT_3D_CTL(pipe)) & LUT_3D_READY) {
|
||||||
|
drm_err(display->drm, "[CRTC:%d:%s] 3D LUT not ready, not committing change\n",
|
||||||
|
crtc->base.base.id, crtc->base.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
val = LUT_3D_ENABLE | LUT_3D_READY | LUT_3D_BIND_PLANE_1;
|
||||||
|
|
||||||
|
intel_de_write_dsb(display, dsb, LUT_3D_CTL(pipe), val);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct intel_color_funcs chv_color_funcs = {
|
static const struct intel_color_funcs chv_color_funcs = {
|
||||||
.color_check = chv_color_check,
|
.color_check = chv_color_check,
|
||||||
.color_commit_arm = i9xx_color_commit_arm,
|
.color_commit_arm = i9xx_color_commit_arm,
|
||||||
|
|
@ -3883,6 +4155,8 @@ static const struct intel_color_funcs tgl_color_funcs = {
|
||||||
.lut_equal = icl_lut_equal,
|
.lut_equal = icl_lut_equal,
|
||||||
.read_csc = icl_read_csc,
|
.read_csc = icl_read_csc,
|
||||||
.get_config = skl_get_config,
|
.get_config = skl_get_config,
|
||||||
|
.load_plane_csc_matrix = xelpd_load_plane_csc_matrix,
|
||||||
|
.load_plane_luts = xelpd_plane_load_luts,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct intel_color_funcs icl_color_funcs = {
|
static const struct intel_color_funcs icl_color_funcs = {
|
||||||
|
|
@ -3963,6 +4237,67 @@ static const struct intel_color_funcs ilk_color_funcs = {
|
||||||
.get_config = ilk_get_config,
|
.get_config = ilk_get_config,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void intel_color_plane_commit_arm(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(plane_state);
|
||||||
|
struct intel_crtc *crtc = to_intel_crtc(plane_state->uapi.crtc);
|
||||||
|
|
||||||
|
if (crtc && intel_color_crtc_has_3dlut(display, crtc->pipe))
|
||||||
|
glk_lut_3d_commit(dsb, crtc, !!plane_state->hw.lut_3d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
intel_color_load_plane_csc_matrix(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(plane_state);
|
||||||
|
|
||||||
|
if (display->funcs.color->load_plane_csc_matrix)
|
||||||
|
display->funcs.color->load_plane_csc_matrix(dsb, plane_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
intel_color_load_plane_luts(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(plane_state);
|
||||||
|
|
||||||
|
if (display->funcs.color->load_plane_luts)
|
||||||
|
display->funcs.color->load_plane_luts(dsb, plane_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
intel_color_crtc_has_3dlut(struct intel_display *display, enum pipe pipe)
|
||||||
|
{
|
||||||
|
if (DISPLAY_VER(display) >= 12)
|
||||||
|
return pipe == PIPE_A || pipe == PIPE_B;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
intel_color_load_3dlut(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
struct intel_display *display = to_intel_display(plane_state);
|
||||||
|
struct intel_crtc *crtc = to_intel_crtc(plane_state->uapi.crtc);
|
||||||
|
|
||||||
|
if (crtc && intel_color_crtc_has_3dlut(display, crtc->pipe))
|
||||||
|
glk_load_lut_3d(dsb, crtc, plane_state->hw.lut_3d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void intel_color_plane_program_pipeline(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state)
|
||||||
|
{
|
||||||
|
if (plane_state->hw.ctm)
|
||||||
|
intel_color_load_plane_csc_matrix(dsb, plane_state);
|
||||||
|
if (plane_state->hw.degamma_lut || plane_state->hw.gamma_lut)
|
||||||
|
intel_color_load_plane_luts(dsb, plane_state);
|
||||||
|
if (plane_state->hw.lut_3d)
|
||||||
|
intel_color_load_3dlut(dsb, plane_state);
|
||||||
|
}
|
||||||
|
|
||||||
void intel_color_crtc_init(struct intel_crtc *crtc)
|
void intel_color_crtc_init(struct intel_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct intel_display *display = to_intel_display(crtc);
|
struct intel_display *display = to_intel_display(crtc);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ struct intel_crtc_state;
|
||||||
struct intel_crtc;
|
struct intel_crtc;
|
||||||
struct intel_display;
|
struct intel_display;
|
||||||
struct intel_dsb;
|
struct intel_dsb;
|
||||||
|
struct intel_plane_state;
|
||||||
struct drm_property_blob;
|
struct drm_property_blob;
|
||||||
|
enum pipe;
|
||||||
|
|
||||||
void intel_color_init_hooks(struct intel_display *display);
|
void intel_color_init_hooks(struct intel_display *display);
|
||||||
int intel_color_init(struct intel_display *display);
|
int intel_color_init(struct intel_display *display);
|
||||||
|
|
@ -40,5 +42,9 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
|
||||||
const struct drm_property_blob *blob2,
|
const struct drm_property_blob *blob2,
|
||||||
bool is_pre_csc_lut);
|
bool is_pre_csc_lut);
|
||||||
void intel_color_assert_luts(const struct intel_crtc_state *crtc_state);
|
void intel_color_assert_luts(const struct intel_crtc_state *crtc_state);
|
||||||
|
void intel_color_plane_program_pipeline(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state);
|
||||||
|
void intel_color_plane_commit_arm(struct intel_dsb *dsb,
|
||||||
|
const struct intel_plane_state *plane_state);
|
||||||
|
bool intel_color_crtc_has_3dlut(struct intel_display *display, enum pipe pipe);
|
||||||
#endif /* __INTEL_COLOR_H__ */
|
#endif /* __INTEL_COLOR_H__ */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
/*
|
||||||
|
* Copyright © 2025 Intel Corporation
|
||||||
|
*/
|
||||||
|
#include "intel_color.h"
|
||||||
|
#include "intel_colorop.h"
|
||||||
|
#include "intel_color_pipeline.h"
|
||||||
|
#include "intel_de.h"
|
||||||
|
#include "intel_display_types.h"
|
||||||
|
#include "skl_universal_plane.h"
|
||||||
|
|
||||||
|
#define MAX_COLOR_PIPELINES 1
|
||||||
|
#define PLANE_DEGAMMA_SIZE 128
|
||||||
|
#define PLANE_GAMMA_SIZE 32
|
||||||
|
|
||||||
|
static
|
||||||
|
int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_enum_list *list,
|
||||||
|
enum pipe pipe)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = plane->dev;
|
||||||
|
struct intel_display *display = to_intel_display(dev);
|
||||||
|
struct drm_colorop *prev_op;
|
||||||
|
struct intel_colorop *colorop;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
colorop = intel_colorop_create(INTEL_PLANE_CB_PRE_CSC_LUT);
|
||||||
|
|
||||||
|
ret = drm_plane_colorop_curve_1d_lut_init(dev, &colorop->base, plane,
|
||||||
|
PLANE_DEGAMMA_SIZE,
|
||||||
|
DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
|
||||||
|
DRM_COLOROP_FLAG_ALLOW_BYPASS);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
list->type = colorop->base.base.id;
|
||||||
|
list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", colorop->base.base.id);
|
||||||
|
|
||||||
|
/* TODO: handle failures and clean up */
|
||||||
|
prev_op = &colorop->base;
|
||||||
|
|
||||||
|
if (DISPLAY_VER(display) >= 35 &&
|
||||||
|
intel_color_crtc_has_3dlut(display, pipe) &&
|
||||||
|
plane->type == DRM_PLANE_TYPE_PRIMARY) {
|
||||||
|
colorop = intel_colorop_create(INTEL_PLANE_CB_3DLUT);
|
||||||
|
|
||||||
|
ret = drm_plane_colorop_3dlut_init(dev, &colorop->base, plane, 17,
|
||||||
|
DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL,
|
||||||
|
true);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
drm_colorop_set_next_property(prev_op, &colorop->base);
|
||||||
|
|
||||||
|
prev_op = &colorop->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
colorop = intel_colorop_create(INTEL_PLANE_CB_CSC);
|
||||||
|
ret = drm_plane_colorop_ctm_3x4_init(dev, &colorop->base, plane,
|
||||||
|
DRM_COLOROP_FLAG_ALLOW_BYPASS);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
drm_colorop_set_next_property(prev_op, &colorop->base);
|
||||||
|
prev_op = &colorop->base;
|
||||||
|
|
||||||
|
colorop = intel_colorop_create(INTEL_PLANE_CB_POST_CSC_LUT);
|
||||||
|
ret = drm_plane_colorop_curve_1d_lut_init(dev, &colorop->base, plane,
|
||||||
|
PLANE_GAMMA_SIZE,
|
||||||
|
DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
|
||||||
|
DRM_COLOROP_FLAG_ALLOW_BYPASS);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
drm_colorop_set_next_property(prev_op, &colorop->base);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = plane->dev;
|
||||||
|
struct intel_display *display = to_intel_display(dev);
|
||||||
|
struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
|
||||||
|
int len = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Currently expose pipeline only for HDR planes */
|
||||||
|
if (!icl_is_hdr_plane(display, to_intel_plane(plane)->id))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Add pipeline consisting of transfer functions */
|
||||||
|
ret = _intel_color_pipeline_plane_init(plane, &pipelines[len], pipe);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
len++;
|
||||||
|
|
||||||
|
return drm_plane_create_color_pipeline_property(plane, pipelines, len);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* Copyright © 2025 Intel Corporation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __INTEL_COLOR_PIPELINE_H__
|
||||||
|
#define __INTEL_COLOR_PIPELINE_H__
|
||||||
|
|
||||||
|
struct drm_plane;
|
||||||
|
enum pipe;
|
||||||
|
|
||||||
|
int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe);
|
||||||
|
|
||||||
|
#endif /* __INTEL_COLOR_PIPELINE_H__ */
|
||||||
|
|
@ -316,4 +316,33 @@
|
||||||
#define SKL_BOTTOM_COLOR_CSC_ENABLE REG_BIT(30)
|
#define SKL_BOTTOM_COLOR_CSC_ENABLE REG_BIT(30)
|
||||||
#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE(pipe, _SKL_BOTTOM_COLOR_A, _SKL_BOTTOM_COLOR_B)
|
#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE(pipe, _SKL_BOTTOM_COLOR_A, _SKL_BOTTOM_COLOR_B)
|
||||||
|
|
||||||
|
/* 3D LUT */
|
||||||
|
#define _LUT_3D_CTL_A 0x490A4
|
||||||
|
#define _LUT_3D_CTL_B 0x491A4
|
||||||
|
#define LUT_3D_CTL(pipe) _MMIO_PIPE(pipe, _LUT_3D_CTL_A, _LUT_3D_CTL_B)
|
||||||
|
#define LUT_3D_ENABLE REG_BIT(31)
|
||||||
|
#define LUT_3D_READY REG_BIT(30)
|
||||||
|
#define LUT_3D_BINDING_MASK REG_GENMASK(23, 22)
|
||||||
|
#define LUT_3D_BIND_PIPE REG_FIELD_PREP(LUT_3D_BINDING_MASK, 0)
|
||||||
|
#define LUT_3D_BIND_PLANE_1 REG_FIELD_PREP(LUT_3D_BINDING_MASK, 1)
|
||||||
|
#define LUT_3D_BIND_PLANE_2 REG_FIELD_PREP(LUT_3D_BINDING_MASK, 2)
|
||||||
|
#define LUT_3D_BIND_PLANE_3 REG_FIELD_PREP(LUT_3D_BINDING_MASK, 3)
|
||||||
|
|
||||||
|
#define _LUT_3D_INDEX_A 0x490A8
|
||||||
|
#define _LUT_3D_INDEX_B 0x491A8
|
||||||
|
#define LUT_3D_INDEX(pipe) _MMIO_PIPE(pipe, _LUT_3D_INDEX_A, _LUT_3D_INDEX_B)
|
||||||
|
#define LUT_3D_AUTO_INCREMENT REG_BIT(13)
|
||||||
|
#define LUT_3D_INDEX_VALUE_MASK REG_GENMASK(12, 0)
|
||||||
|
#define LUT_3D_INDEX_VALUE(x) REG_FIELD_PREP(LUT_3D_INDEX_VALUE_MASK, (x))
|
||||||
|
|
||||||
|
#define _LUT_3D_DATA_A 0x490AC
|
||||||
|
#define _LUT_3D_DATA_B 0x491AC
|
||||||
|
#define LUT_3D_DATA(pipe) _MMIO_PIPE(pipe, _LUT_3D_DATA_A, _LUT_3D_DATA_B)
|
||||||
|
#define LUT_3D_DATA_RED_MASK REG_GENMASK(29, 20)
|
||||||
|
#define LUT_3D_DATA_GREEN_MASK REG_GENMASK(19, 10)
|
||||||
|
#define LUT_3D_DATA_BLUE_MASK REG_GENMASK(9, 0)
|
||||||
|
#define LUT_3D_DATA_RED(x) REG_FIELD_PREP(LUT_3D_DATA_RED_MASK, (x))
|
||||||
|
#define LUT_3D_DATA_GREEN(x) REG_FIELD_PREP(LUT_3D_DATA_GREEN_MASK, (x))
|
||||||
|
#define LUT_3D_DATA_BLUE(x) REG_FIELD_PREP(LUT_3D_DATA_BLUE_MASK, (x))
|
||||||
|
|
||||||
#endif /* __INTEL_COLOR_REGS_H__ */
|
#endif /* __INTEL_COLOR_REGS_H__ */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
/*
|
||||||
|
* Copyright © 2025 Intel Corporation
|
||||||
|
*/
|
||||||
|
#include "intel_colorop.h"
|
||||||
|
|
||||||
|
struct intel_colorop *to_intel_colorop(struct drm_colorop *colorop)
|
||||||
|
{
|
||||||
|
return container_of(colorop, struct intel_colorop, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct intel_colorop *intel_colorop_alloc(void)
|
||||||
|
{
|
||||||
|
struct intel_colorop *colorop;
|
||||||
|
|
||||||
|
colorop = kzalloc(sizeof(*colorop), GFP_KERNEL);
|
||||||
|
if (!colorop)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
return colorop;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct intel_colorop *intel_colorop_create(enum intel_color_block id)
|
||||||
|
{
|
||||||
|
struct intel_colorop *colorop;
|
||||||
|
|
||||||
|
colorop = intel_colorop_alloc();
|
||||||
|
|
||||||
|
if (IS_ERR(colorop))
|
||||||
|
return colorop;
|
||||||
|
|
||||||
|
colorop->id = id;
|
||||||
|
|
||||||
|
return colorop;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* Copyright © 2025 Intel Corporation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __INTEL_COLOROP_H__
|
||||||
|
#define __INTEL_COLOROP_H__
|
||||||
|
|
||||||
|
#include "intel_display_types.h"
|
||||||
|
|
||||||
|
struct intel_colorop *to_intel_colorop(struct drm_colorop *colorop);
|
||||||
|
struct intel_colorop *intel_colorop_alloc(void);
|
||||||
|
struct intel_colorop *intel_colorop_create(enum intel_color_block id);
|
||||||
|
|
||||||
|
#endif /* __INTEL_COLOROP_H__ */
|
||||||
|
|
@ -7296,6 +7296,7 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
|
||||||
struct intel_display *display = to_intel_display(state);
|
struct intel_display *display = to_intel_display(state);
|
||||||
struct intel_crtc_state *new_crtc_state =
|
struct intel_crtc_state *new_crtc_state =
|
||||||
intel_atomic_get_new_crtc_state(state, crtc);
|
intel_atomic_get_new_crtc_state(state, crtc);
|
||||||
|
unsigned int size = new_crtc_state->plane_color_changed ? 8192 : 1024;
|
||||||
|
|
||||||
if (!new_crtc_state->use_flipq &&
|
if (!new_crtc_state->use_flipq &&
|
||||||
!new_crtc_state->use_dsb &&
|
!new_crtc_state->use_dsb &&
|
||||||
|
|
@ -7306,10 +7307,12 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
|
||||||
* Rough estimate:
|
* Rough estimate:
|
||||||
* ~64 registers per each plane * 8 planes = 512
|
* ~64 registers per each plane * 8 planes = 512
|
||||||
* Double that for pipe stuff and other overhead.
|
* Double that for pipe stuff and other overhead.
|
||||||
|
* ~4913 registers for 3DLUT
|
||||||
|
* ~200 color registers * 3 HDR planes
|
||||||
*/
|
*/
|
||||||
new_crtc_state->dsb_commit = intel_dsb_prepare(state, crtc, INTEL_DSB_0,
|
new_crtc_state->dsb_commit = intel_dsb_prepare(state, crtc, INTEL_DSB_0,
|
||||||
new_crtc_state->use_dsb ||
|
new_crtc_state->use_dsb ||
|
||||||
new_crtc_state->use_flipq ? 1024 : 16);
|
new_crtc_state->use_flipq ? size : 16);
|
||||||
if (!new_crtc_state->dsb_commit) {
|
if (!new_crtc_state->dsb_commit) {
|
||||||
new_crtc_state->use_flipq = false;
|
new_crtc_state->use_flipq = false;
|
||||||
new_crtc_state->use_dsb = false;
|
new_crtc_state->use_dsb = false;
|
||||||
|
|
|
||||||
|
|
@ -138,4 +138,13 @@ enum hpd_pin {
|
||||||
HPD_NUM_PINS
|
HPD_NUM_PINS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum intel_color_block {
|
||||||
|
INTEL_PLANE_CB_PRE_CSC_LUT,
|
||||||
|
INTEL_PLANE_CB_CSC,
|
||||||
|
INTEL_PLANE_CB_POST_CSC_LUT,
|
||||||
|
INTEL_PLANE_CB_3DLUT,
|
||||||
|
|
||||||
|
INTEL_CB_MAX
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* __INTEL_DISPLAY_LIMITS_H__ */
|
#endif /* __INTEL_DISPLAY_LIMITS_H__ */
|
||||||
|
|
|
||||||
|
|
@ -646,6 +646,7 @@ struct intel_plane_state {
|
||||||
enum drm_color_encoding color_encoding;
|
enum drm_color_encoding color_encoding;
|
||||||
enum drm_color_range color_range;
|
enum drm_color_range color_range;
|
||||||
enum drm_scaling_filter scaling_filter;
|
enum drm_scaling_filter scaling_filter;
|
||||||
|
struct drm_property_blob *ctm, *degamma_lut, *gamma_lut, *lut_3d;
|
||||||
} hw;
|
} hw;
|
||||||
|
|
||||||
struct i915_vma *ggtt_vma;
|
struct i915_vma *ggtt_vma;
|
||||||
|
|
@ -1391,6 +1392,9 @@ struct intel_crtc_state {
|
||||||
u8 silence_period_sym_clocks;
|
u8 silence_period_sym_clocks;
|
||||||
u8 lfps_half_cycle_num_of_syms;
|
u8 lfps_half_cycle_num_of_syms;
|
||||||
} alpm_state;
|
} alpm_state;
|
||||||
|
|
||||||
|
/* to track changes in plane color blocks */
|
||||||
|
bool plane_color_changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum intel_pipe_crc_source {
|
enum intel_pipe_crc_source {
|
||||||
|
|
@ -1985,6 +1989,11 @@ struct intel_dp_mst_encoder {
|
||||||
struct intel_connector *connector;
|
struct intel_connector *connector;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct intel_colorop {
|
||||||
|
struct drm_colorop base;
|
||||||
|
enum intel_color_block id;
|
||||||
|
};
|
||||||
|
|
||||||
static inline struct intel_encoder *
|
static inline struct intel_encoder *
|
||||||
intel_attached_encoder(struct intel_connector *connector)
|
intel_attached_encoder(struct intel_connector *connector)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include "i9xx_plane_regs.h"
|
#include "i9xx_plane_regs.h"
|
||||||
#include "intel_cdclk.h"
|
#include "intel_cdclk.h"
|
||||||
#include "intel_cursor.h"
|
#include "intel_cursor.h"
|
||||||
|
#include "intel_colorop.h"
|
||||||
#include "intel_display_rps.h"
|
#include "intel_display_rps.h"
|
||||||
#include "intel_display_trace.h"
|
#include "intel_display_trace.h"
|
||||||
#include "intel_display_types.h"
|
#include "intel_display_types.h"
|
||||||
|
|
@ -336,6 +337,58 @@ intel_plane_copy_uapi_plane_damage(struct intel_plane_state *new_plane_state,
|
||||||
*damage = drm_plane_state_src(&new_uapi_plane_state->uapi);
|
*damage = drm_plane_state_src(&new_uapi_plane_state->uapi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
intel_plane_colorop_replace_blob(struct intel_plane_state *plane_state,
|
||||||
|
struct intel_colorop *intel_colorop,
|
||||||
|
struct drm_property_blob *blob)
|
||||||
|
{
|
||||||
|
if (intel_colorop->id == INTEL_PLANE_CB_CSC)
|
||||||
|
return drm_property_replace_blob(&plane_state->hw.ctm, blob);
|
||||||
|
else if (intel_colorop->id == INTEL_PLANE_CB_PRE_CSC_LUT)
|
||||||
|
return drm_property_replace_blob(&plane_state->hw.degamma_lut, blob);
|
||||||
|
else if (intel_colorop->id == INTEL_PLANE_CB_POST_CSC_LUT)
|
||||||
|
return drm_property_replace_blob(&plane_state->hw.gamma_lut, blob);
|
||||||
|
else if (intel_colorop->id == INTEL_PLANE_CB_3DLUT)
|
||||||
|
return drm_property_replace_blob(&plane_state->hw.lut_3d, blob);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
intel_plane_color_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
|
||||||
|
const struct intel_plane_state *from_plane_state,
|
||||||
|
struct intel_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct drm_colorop *iter_colorop, *colorop;
|
||||||
|
struct drm_colorop_state *new_colorop_state;
|
||||||
|
struct drm_atomic_state *state = plane_state->uapi.state;
|
||||||
|
struct intel_colorop *intel_colorop;
|
||||||
|
struct drm_property_blob *blob;
|
||||||
|
struct intel_atomic_state *intel_atomic_state = to_intel_atomic_state(state);
|
||||||
|
struct intel_crtc_state *new_crtc_state = intel_atomic_state ?
|
||||||
|
intel_atomic_get_new_crtc_state(intel_atomic_state, crtc) : NULL;
|
||||||
|
bool changed = false;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
iter_colorop = plane_state->uapi.color_pipeline;
|
||||||
|
|
||||||
|
while (iter_colorop) {
|
||||||
|
for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
|
||||||
|
if (new_colorop_state->colorop == iter_colorop) {
|
||||||
|
blob = new_colorop_state->bypass ? NULL : new_colorop_state->data;
|
||||||
|
intel_colorop = to_intel_colorop(colorop);
|
||||||
|
changed |= intel_plane_colorop_replace_blob(plane_state,
|
||||||
|
intel_colorop,
|
||||||
|
blob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iter_colorop = iter_colorop->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_crtc_state && changed)
|
||||||
|
new_crtc_state->plane_color_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
|
void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
|
||||||
const struct intel_plane_state *from_plane_state,
|
const struct intel_plane_state *from_plane_state,
|
||||||
struct intel_crtc *crtc)
|
struct intel_crtc *crtc)
|
||||||
|
|
@ -364,6 +417,8 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
|
||||||
|
|
||||||
plane_state->uapi.src = drm_plane_state_src(&from_plane_state->uapi);
|
plane_state->uapi.src = drm_plane_state_src(&from_plane_state->uapi);
|
||||||
plane_state->uapi.dst = drm_plane_state_dest(&from_plane_state->uapi);
|
plane_state->uapi.dst = drm_plane_state_dest(&from_plane_state->uapi);
|
||||||
|
|
||||||
|
intel_plane_color_copy_uapi_to_hw_state(plane_state, from_plane_state, crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void intel_plane_copy_hw_state(struct intel_plane_state *plane_state,
|
void intel_plane_copy_hw_state(struct intel_plane_state *plane_state,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "pxp/intel_pxp.h"
|
#include "pxp/intel_pxp.h"
|
||||||
#include "intel_bo.h"
|
#include "intel_bo.h"
|
||||||
|
#include "intel_color.h"
|
||||||
|
#include "intel_color_pipeline.h"
|
||||||
#include "intel_de.h"
|
#include "intel_de.h"
|
||||||
#include "intel_display_irq.h"
|
#include "intel_display_irq.h"
|
||||||
#include "intel_display_regs.h"
|
#include "intel_display_regs.h"
|
||||||
|
|
@ -1275,6 +1277,18 @@ static u32 glk_plane_color_ctl(const struct intel_plane_state *plane_state)
|
||||||
if (plane_state->force_black)
|
if (plane_state->force_black)
|
||||||
plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
|
plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
|
||||||
|
|
||||||
|
if (plane_state->hw.degamma_lut)
|
||||||
|
plane_color_ctl |= PLANE_COLOR_PRE_CSC_GAMMA_ENABLE;
|
||||||
|
|
||||||
|
if (plane_state->hw.ctm)
|
||||||
|
plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
|
||||||
|
|
||||||
|
if (plane_state->hw.gamma_lut) {
|
||||||
|
plane_color_ctl &= ~PLANE_COLOR_PLANE_GAMMA_DISABLE;
|
||||||
|
if (drm_color_lut32_size(plane_state->hw.gamma_lut) != 32)
|
||||||
|
plane_color_ctl |= PLANE_COLOR_POST_CSC_GAMMA_MULTSEG_ENABLE;
|
||||||
|
}
|
||||||
|
|
||||||
return plane_color_ctl;
|
return plane_color_ctl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1556,6 +1570,8 @@ icl_plane_update_noarm(struct intel_dsb *dsb,
|
||||||
plane_color_ctl = plane_state->color_ctl |
|
plane_color_ctl = plane_state->color_ctl |
|
||||||
glk_plane_color_ctl_crtc(crtc_state);
|
glk_plane_color_ctl_crtc(crtc_state);
|
||||||
|
|
||||||
|
intel_color_plane_program_pipeline(dsb, plane_state);
|
||||||
|
|
||||||
/* The scaler will handle the output position */
|
/* The scaler will handle the output position */
|
||||||
if (plane_state->scaler_id >= 0) {
|
if (plane_state->scaler_id >= 0) {
|
||||||
crtc_x = 0;
|
crtc_x = 0;
|
||||||
|
|
@ -1657,6 +1673,8 @@ icl_plane_update_arm(struct intel_dsb *dsb,
|
||||||
|
|
||||||
icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
|
icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
|
||||||
|
|
||||||
|
intel_color_plane_commit_arm(dsb, plane_state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In order to have FBC for fp16 formats pixel normalizer block must be
|
* In order to have FBC for fp16 formats pixel normalizer block must be
|
||||||
* active. Check if pixel normalizer block need to be enabled for FBC.
|
* active. Check if pixel normalizer block need to be enabled for FBC.
|
||||||
|
|
@ -3001,6 +3019,9 @@ skl_universal_plane_create(struct intel_display *display,
|
||||||
DRM_COLOR_YCBCR_BT709,
|
DRM_COLOR_YCBCR_BT709,
|
||||||
DRM_COLOR_YCBCR_LIMITED_RANGE);
|
DRM_COLOR_YCBCR_LIMITED_RANGE);
|
||||||
|
|
||||||
|
if (DISPLAY_VER(display) >= 12)
|
||||||
|
intel_color_pipeline_plane_init(&plane->base, pipe);
|
||||||
|
|
||||||
drm_plane_create_alpha_property(&plane->base);
|
drm_plane_create_alpha_property(&plane->base);
|
||||||
drm_plane_create_blend_mode_property(&plane->base,
|
drm_plane_create_blend_mode_property(&plane->base,
|
||||||
BIT(DRM_MODE_BLEND_PIXEL_NONE) |
|
BIT(DRM_MODE_BLEND_PIXEL_NONE) |
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,8 @@
|
||||||
#define PLANE_COLOR_PIPE_CSC_ENABLE REG_BIT(23) /* Pre-ICL */
|
#define PLANE_COLOR_PIPE_CSC_ENABLE REG_BIT(23) /* Pre-ICL */
|
||||||
#define PLANE_COLOR_PLANE_CSC_ENABLE REG_BIT(21) /* ICL+ */
|
#define PLANE_COLOR_PLANE_CSC_ENABLE REG_BIT(21) /* ICL+ */
|
||||||
#define PLANE_COLOR_INPUT_CSC_ENABLE REG_BIT(20) /* ICL+ */
|
#define PLANE_COLOR_INPUT_CSC_ENABLE REG_BIT(20) /* ICL+ */
|
||||||
|
#define PLANE_COLOR_POST_CSC_GAMMA_MULTSEG_ENABLE REG_BIT(15) /* TGL+ */
|
||||||
|
#define PLANE_COLOR_PRE_CSC_GAMMA_ENABLE REG_BIT(14)
|
||||||
#define PLANE_COLOR_CSC_MODE_MASK REG_GENMASK(19, 17)
|
#define PLANE_COLOR_CSC_MODE_MASK REG_GENMASK(19, 17)
|
||||||
#define PLANE_COLOR_CSC_MODE_BYPASS REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 0)
|
#define PLANE_COLOR_CSC_MODE_BYPASS REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 0)
|
||||||
#define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 1)
|
#define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601 REG_FIELD_PREP(PLANE_COLOR_CSC_MODE_MASK, 1)
|
||||||
|
|
@ -290,6 +292,119 @@
|
||||||
_PLANE_INPUT_CSC_POSTOFF_HI_1_A, _PLANE_INPUT_CSC_POSTOFF_HI_1_B, \
|
_PLANE_INPUT_CSC_POSTOFF_HI_1_A, _PLANE_INPUT_CSC_POSTOFF_HI_1_B, \
|
||||||
_PLANE_INPUT_CSC_POSTOFF_HI_2_A, _PLANE_INPUT_CSC_POSTOFF_HI_2_B)
|
_PLANE_INPUT_CSC_POSTOFF_HI_2_A, _PLANE_INPUT_CSC_POSTOFF_HI_2_B)
|
||||||
|
|
||||||
|
#define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4)
|
||||||
|
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A 0x70160
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B 0x71160
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A 0x70260
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B 0x71260
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1_B)
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2_B)
|
||||||
|
#define PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_1(pipe), \
|
||||||
|
_PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH_2(pipe))
|
||||||
|
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A 0x70164
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B 0x71164
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A 0x70264
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B 0x71264
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1_B)
|
||||||
|
#define _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2_B)
|
||||||
|
#define PLANE_POST_CSC_GAMC_SEG0_DATA_ENH(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_1(pipe), \
|
||||||
|
_PLANE_POST_CSC_GAMC_SEG0_DATA_ENH_2(pipe))
|
||||||
|
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A 0x701d8
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1_B 0x711d8
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A 0x702d8
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2_B 0x712d8
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_1_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_INDEX_ENH_1_B)
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_ENH_2_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_INDEX_ENH_2_B)
|
||||||
|
#define PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_ENH_1(pipe), \
|
||||||
|
_PLANE_POST_CSC_GAMC_INDEX_ENH_2(pipe))
|
||||||
|
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_A 0x701dc
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_ENH_1_B 0x711dc
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_A 0x702dc
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_ENH_2_B 0x712dc
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_1_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_DATA_ENH_1_B)
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_ENH_2_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_DATA_ENH_2_B)
|
||||||
|
#define PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_DATA_ENH_1(pipe), \
|
||||||
|
_PLANE_POST_CSC_GAMC_DATA_ENH_2(pipe))
|
||||||
|
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_1_A 0x704d8
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_1_B 0x714d8
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_2_A 0x705d8
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_2_B 0x715d8
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_1_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_INDEX_1_B)
|
||||||
|
#define _PLANE_POST_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_INDEX_2_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_INDEX_2_B)
|
||||||
|
#define PLANE_POST_CSC_GAMC_INDEX(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_INDEX_1(pipe), \
|
||||||
|
_PLANE_POST_CSC_GAMC_INDEX_2(pipe))
|
||||||
|
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_1_A 0x704dc
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_1_B 0x714dc
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_2_A 0x705dc
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_2_B 0x715dc
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_1_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_DATA_1_B)
|
||||||
|
#define _PLANE_POST_CSC_GAMC_DATA_2(pipe) _PIPE(pipe, _PLANE_POST_CSC_GAMC_DATA_2_A, \
|
||||||
|
_PLANE_POST_CSC_GAMC_DATA_2_B)
|
||||||
|
#define PLANE_POST_CSC_GAMC_DATA(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_POST_CSC_GAMC_DATA_1(pipe), \
|
||||||
|
_PLANE_POST_CSC_GAMC_DATA_2(pipe))
|
||||||
|
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A 0x701d0
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B 0x711d0
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A 0x702d0
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B 0x712d0
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1_A, \
|
||||||
|
_PLANE_PRE_CSC_GAMC_INDEX_ENH_1_B)
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_ENH_2_A, \
|
||||||
|
_PLANE_PRE_CSC_GAMC_INDEX_ENH_2_B)
|
||||||
|
#define PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_ENH_1(pipe), \
|
||||||
|
_PLANE_PRE_CSC_GAMC_INDEX_ENH_2(pipe))
|
||||||
|
#define PLANE_PAL_PREC_AUTO_INCREMENT REG_BIT(10)
|
||||||
|
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A 0x701d4
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1_B 0x711d4
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A 0x702d4
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2_B 0x712d4
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_1_A, \
|
||||||
|
_PLANE_PRE_CSC_GAMC_DATA_ENH_1_B)
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_ENH_2_A, \
|
||||||
|
_PLANE_PRE_CSC_GAMC_DATA_ENH_2_B)
|
||||||
|
#define PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_ENH_1(pipe), \
|
||||||
|
_PLANE_PRE_CSC_GAMC_DATA_ENH_2(pipe))
|
||||||
|
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_1_A 0x704d0
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_1_B 0x714d0
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_2_A 0x705d0
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_2_B 0x715d0
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_1_A, \
|
||||||
|
_PLANE_PRE_CSC_GAMC_INDEX_1_B)
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_INDEX_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_INDEX_2_A, \
|
||||||
|
_PLANE_PRE_CSC_GAMC_INDEX_2_B)
|
||||||
|
#define PLANE_PRE_CSC_GAMC_INDEX(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_INDEX_1(pipe), \
|
||||||
|
_PLANE_PRE_CSC_GAMC_INDEX_2(pipe))
|
||||||
|
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_1_A 0x704d4
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_1_B 0x714d4
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_2_A 0x705d4
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_2_B 0x715d4
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_1(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_1_A, \
|
||||||
|
_PLANE_PRE_CSC_GAMC_DATA_1_B)
|
||||||
|
#define _PLANE_PRE_CSC_GAMC_DATA_2(pipe) _PIPE(pipe, _PLANE_PRE_CSC_GAMC_DATA_2_A, \
|
||||||
|
_PLANE_PRE_CSC_GAMC_DATA_2_B)
|
||||||
|
#define PLANE_PRE_CSC_GAMC_DATA(pipe, plane, i) _MMIO_PLANE_GAMC(plane, i, _PLANE_PRE_CSC_GAMC_DATA_1(pipe), \
|
||||||
|
_PLANE_PRE_CSC_GAMC_DATA_2(pipe))
|
||||||
|
|
||||||
#define _PLANE_CSC_RY_GY_1_A 0x70210
|
#define _PLANE_CSC_RY_GY_1_A 0x70210
|
||||||
#define _PLANE_CSC_RY_GY_2_A 0x70310
|
#define _PLANE_CSC_RY_GY_2_A 0x70310
|
||||||
#define _PLANE_CSC_RY_GY_1_B 0x71210
|
#define _PLANE_CSC_RY_GY_1_B 0x71210
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,8 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
|
||||||
i915-display/intel_cdclk.o \
|
i915-display/intel_cdclk.o \
|
||||||
i915-display/intel_cmtg.o \
|
i915-display/intel_cmtg.o \
|
||||||
i915-display/intel_color.o \
|
i915-display/intel_color.o \
|
||||||
|
i915-display/intel_colorop.o \
|
||||||
|
i915-display/intel_color_pipeline.o \
|
||||||
i915-display/intel_combo_phy.o \
|
i915-display/intel_combo_phy.o \
|
||||||
i915-display/intel_connector.o \
|
i915-display/intel_connector.o \
|
||||||
i915-display/intel_crtc.o \
|
i915-display/intel_crtc.o \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue