Skip to content

Commit deb879f

Browse files
committed
Merge tag 'drm-next-2025-12-05' of https://gitlab.freedesktop.org/drm/kernel
Pull more drm updates from Dave Airlie: "There was some additional intel code for color operations we wanted to land. However I discovered I missed a pull for the xe vfio driver which I had sorted into 6.20 in my brain, until Thomas mentioned it. This contains the xe vfio code, a bunch of xe fixes that were waiting and the i915 color management support. I'd like to include it as part of keeping the two main vendors on the same page and giving a good cross-driver experience for userspace when it starts using it. vfio: - add a vfio_pci variant driver for Intel xe/i915 display: - add plane color management support xe: - Add scope-based cleanup helper for runtime PM - vfio xe driver prerequisites and exports - fix vfio link error - Fix a memory leak - Fix a 64-bit division - vf migration fix - LRC pause fix" * tag 'drm-next-2025-12-05' of https://gitlab.freedesktop.org/drm/kernel: (25 commits) drm/i915/color: Enable Plane Color Pipelines drm/i915/color: Add 3D LUT to color pipeline drm/i915/color: Add registers for 3D LUT drm/i915/color: Program Plane Post CSC Registers drm/i915/color: Program Pre-CSC registers drm/i915/color: Add framework to program PRE/POST CSC LUT drm/i915: Add register definitions for Plane Post CSC drm/i915: Add register definitions for Plane Degamma drm/i915/color: Add plane CTM callback for D12 and beyond drm/i915/color: Preserve sign bit when int_bits is Zero drm/i915/color: Add framework to program CSC drm/i915/color: Create a transfer function color pipeline drm/i915/color: Add helper to create intel colorop drm/i915: Add intel_color_op drm/i915/display: Add identifiers for driver specific blocks drm/xe/pf: fix VFIO link error drm/xe: Protect against unset LRC when pausing submissions drm/xe/vf: Start re-emission from first unsignaled job during VF migration drm/xe/pf: Use div_u64 when calculating GGTT profile drm/xe: Fix memory leak when handling pagefault vma ...
2 parents 028bd4a + c7685d1 commit deb879f

36 files changed

Lines changed: 1713 additions & 32 deletions

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27221,6 +27221,13 @@ L: virtualization@lists.linux.dev
2722127221
S: Maintained
2722227222
F: drivers/vfio/pci/virtio
2722327223

27224+
VFIO XE PCI DRIVER
27225+
M: Michał Winiarski <michal.winiarski@intel.com>
27226+
L: kvm@vger.kernel.org
27227+
L: intel-xe@lists.freedesktop.org
27228+
S: Supported
27229+
F: drivers/vfio/pci/xe
27230+
2722427231
VGA_SWITCHEROO
2722527232
R: Lukas Wunner <lukas@wunner.de>
2722627233
S: Maintained

drivers/gpu/drm/i915/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ i915-y += \
239239
display/intel_cdclk.o \
240240
display/intel_cmtg.o \
241241
display/intel_color.o \
242+
display/intel_colorop.o \
243+
display/intel_color_pipeline.o \
242244
display/intel_combo_phy.o \
243245
display/intel_connector.o \
244246
display/intel_crtc.o \

drivers/gpu/drm/i915/display/intel_color.c

Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include "intel_display_utils.h"
3333
#include "intel_dsb.h"
3434
#include "intel_vrr.h"
35+
#include "skl_universal_plane.h"
36+
#include "skl_universal_plane_regs.h"
3537

3638
struct intel_color_funcs {
3739
int (*color_check)(struct intel_atomic_state *state,
@@ -87,6 +89,14 @@ struct intel_color_funcs {
8789
* Read config other than LUTs and CSCs, before them. Optional.
8890
*/
8991
void (*get_config)(struct intel_crtc_state *crtc_state);
92+
93+
/* Plane CSC*/
94+
void (*load_plane_csc_matrix)(struct intel_dsb *dsb,
95+
const struct intel_plane_state *plane_state);
96+
97+
/* Plane Pre/Post CSC */
98+
void (*load_plane_luts)(struct intel_dsb *dsb,
99+
const struct intel_plane_state *plane_state);
90100
};
91101

92102
#define CTM_COEFF_SIGN (1ULL << 63)
@@ -609,6 +619,8 @@ static u16 ctm_to_twos_complement(u64 coeff, int int_bits, int frac_bits)
609619
if (CTM_COEFF_NEGATIVE(coeff))
610620
c = -c;
611621

622+
int_bits = max(int_bits, 1);
623+
612624
c = clamp(c, -(s64)BIT(int_bits + frac_bits - 1),
613625
(s64)(BIT(int_bits + frac_bits - 1) - 1));
614626

@@ -3836,6 +3848,266 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state)
38363848
}
38373849
}
38383850

3851+
static void
3852+
xelpd_load_plane_csc_matrix(struct intel_dsb *dsb,
3853+
const struct intel_plane_state *plane_state)
3854+
{
3855+
struct intel_display *display = to_intel_display(plane_state);
3856+
const struct drm_plane_state *state = &plane_state->uapi;
3857+
enum pipe pipe = to_intel_plane(state->plane)->pipe;
3858+
enum plane_id plane = to_intel_plane(state->plane)->id;
3859+
const struct drm_property_blob *blob = plane_state->hw.ctm;
3860+
struct drm_color_ctm_3x4 *ctm;
3861+
const u64 *input;
3862+
u16 coeffs[9] = {};
3863+
int i, j;
3864+
3865+
if (!icl_is_hdr_plane(display, plane) || !blob)
3866+
return;
3867+
3868+
ctm = blob->data;
3869+
input = ctm->matrix;
3870+
3871+
/*
3872+
* Convert fixed point S31.32 input to format supported by the
3873+
* hardware.
3874+
*/
3875+
for (i = 0, j = 0; i < ARRAY_SIZE(coeffs); i++) {
3876+
u64 abs_coeff = ((1ULL << 63) - 1) & input[j];
3877+
3878+
/*
3879+
* Clamp input value to min/max supported by
3880+
* hardware.
3881+
*/
3882+
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
3883+
3884+
/* sign bit */
3885+
if (CTM_COEFF_NEGATIVE(input[j]))
3886+
coeffs[i] |= 1 << 15;
3887+
3888+
if (abs_coeff < CTM_COEFF_0_125)
3889+
coeffs[i] |= (3 << 12) |
3890+
ILK_CSC_COEFF_FP(abs_coeff, 12);
3891+
else if (abs_coeff < CTM_COEFF_0_25)
3892+
coeffs[i] |= (2 << 12) |
3893+
ILK_CSC_COEFF_FP(abs_coeff, 11);
3894+
else if (abs_coeff < CTM_COEFF_0_5)
3895+
coeffs[i] |= (1 << 12) |
3896+
ILK_CSC_COEFF_FP(abs_coeff, 10);
3897+
else if (abs_coeff < CTM_COEFF_1_0)
3898+
coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
3899+
else if (abs_coeff < CTM_COEFF_2_0)
3900+
coeffs[i] |= (7 << 12) |
3901+
ILK_CSC_COEFF_FP(abs_coeff, 8);
3902+
else
3903+
coeffs[i] |= (6 << 12) |
3904+
ILK_CSC_COEFF_FP(abs_coeff, 7);
3905+
3906+
/* Skip postoffs */
3907+
if (!((j + 2) % 4))
3908+
j += 2;
3909+
else
3910+
j++;
3911+
}
3912+
3913+
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 0),
3914+
coeffs[0] << 16 | coeffs[1]);
3915+
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 1),
3916+
coeffs[2] << 16);
3917+
3918+
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 2),
3919+
coeffs[3] << 16 | coeffs[4]);
3920+
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 3),
3921+
coeffs[5] << 16);
3922+
3923+
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 4),
3924+
coeffs[6] << 16 | coeffs[7]);
3925+
intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane, 5),
3926+
coeffs[8] << 16);
3927+
3928+
intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane, 0), 0);
3929+
intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane, 1), 0);
3930+
intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane, 2), 0);
3931+
3932+
/*
3933+
* Conversion from S31.32 to S0.12. BIT[12] is the signed bit
3934+
*/
3935+
intel_de_write_dsb(display, dsb,
3936+
PLANE_CSC_POSTOFF(pipe, plane, 0),
3937+
ctm_to_twos_complement(input[3], 0, 12));
3938+
intel_de_write_dsb(display, dsb,
3939+
PLANE_CSC_POSTOFF(pipe, plane, 1),
3940+
ctm_to_twos_complement(input[7], 0, 12));
3941+
intel_de_write_dsb(display, dsb,
3942+
PLANE_CSC_POSTOFF(pipe, plane, 2),
3943+
ctm_to_twos_complement(input[11], 0, 12));
3944+
}
3945+
3946+
static void
3947+
xelpd_program_plane_pre_csc_lut(struct intel_dsb *dsb,
3948+
const struct intel_plane_state *plane_state)
3949+
{
3950+
struct intel_display *display = to_intel_display(plane_state);
3951+
const struct drm_plane_state *state = &plane_state->uapi;
3952+
enum pipe pipe = to_intel_plane(state->plane)->pipe;
3953+
enum plane_id plane = to_intel_plane(state->plane)->id;
3954+
const struct drm_color_lut32 *pre_csc_lut = plane_state->hw.degamma_lut->data;
3955+
u32 i, lut_size;
3956+
3957+
if (icl_is_hdr_plane(display, plane)) {
3958+
lut_size = 128;
3959+
3960+
intel_de_write_dsb(display, dsb,
3961+
PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0),
3962+
PLANE_PAL_PREC_AUTO_INCREMENT);
3963+
3964+
if (pre_csc_lut) {
3965+
for (i = 0; i < lut_size; i++) {
3966+
u32 lut_val = drm_color_lut32_extract(pre_csc_lut[i].green, 24);
3967+
3968+
intel_de_write_dsb(display, dsb,
3969+
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
3970+
lut_val);
3971+
}
3972+
3973+
/* Program the max register to clamp values > 1.0. */
3974+
/* TODO: Restrict to 0x7ffffff */
3975+
do {
3976+
intel_de_write_dsb(display, dsb,
3977+
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
3978+
(1 << 24));
3979+
} while (i++ > 130);
3980+
} else {
3981+
for (i = 0; i < lut_size; i++) {
3982+
u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1);
3983+
3984+
intel_de_write_dsb(display, dsb,
3985+
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0), v);
3986+
}
3987+
3988+
do {
3989+
intel_de_write_dsb(display, dsb,
3990+
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
3991+
1 << 24);
3992+
} while (i++ < 130);
3993+
}
3994+
3995+
intel_de_write_dsb(display, dsb, PLANE_PRE_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0);
3996+
}
3997+
}
3998+
3999+
static void
4000+
xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb,
4001+
const struct intel_plane_state *plane_state)
4002+
{
4003+
struct intel_display *display = to_intel_display(plane_state);
4004+
const struct drm_plane_state *state = &plane_state->uapi;
4005+
enum pipe pipe = to_intel_plane(state->plane)->pipe;
4006+
enum plane_id plane = to_intel_plane(state->plane)->id;
4007+
const struct drm_color_lut32 *post_csc_lut = plane_state->hw.gamma_lut->data;
4008+
u32 i, lut_size, lut_val;
4009+
4010+
if (icl_is_hdr_plane(display, plane)) {
4011+
intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0),
4012+
PLANE_PAL_PREC_AUTO_INCREMENT);
4013+
/* TODO: Add macro */
4014+
intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, 0),
4015+
PLANE_PAL_PREC_AUTO_INCREMENT);
4016+
if (post_csc_lut) {
4017+
lut_size = 32;
4018+
for (i = 0; i < lut_size; i++) {
4019+
lut_val = drm_color_lut32_extract(post_csc_lut[i].green, 24);
4020+
4021+
intel_de_write_dsb(display, dsb,
4022+
PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0),
4023+
lut_val);
4024+
}
4025+
4026+
/* Segment 2 */
4027+
do {
4028+
intel_de_write_dsb(display, dsb,
4029+
PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0),
4030+
(1 << 24));
4031+
} while (i++ < 34);
4032+
} else {
4033+
/*TODO: Add for segment 0 */
4034+
lut_size = 32;
4035+
for (i = 0; i < lut_size; i++) {
4036+
u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1);
4037+
4038+
intel_de_write_dsb(display, dsb,
4039+
PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0), v);
4040+
}
4041+
4042+
do {
4043+
intel_de_write_dsb(display, dsb,
4044+
PLANE_POST_CSC_GAMC_DATA_ENH(pipe, plane, 0),
4045+
1 << 24);
4046+
} while (i++ < 34);
4047+
}
4048+
4049+
intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0);
4050+
intel_de_write_dsb(display, dsb,
4051+
PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, 0), 0);
4052+
}
4053+
}
4054+
4055+
static void
4056+
xelpd_plane_load_luts(struct intel_dsb *dsb, const struct intel_plane_state *plane_state)
4057+
{
4058+
if (plane_state->hw.degamma_lut)
4059+
xelpd_program_plane_pre_csc_lut(dsb, plane_state);
4060+
4061+
if (plane_state->hw.gamma_lut)
4062+
xelpd_program_plane_post_csc_lut(dsb, plane_state);
4063+
}
4064+
4065+
static u32 glk_3dlut_10(const struct drm_color_lut32 *color)
4066+
{
4067+
return REG_FIELD_PREP(LUT_3D_DATA_RED_MASK, drm_color_lut32_extract(color->red, 10)) |
4068+
REG_FIELD_PREP(LUT_3D_DATA_GREEN_MASK, drm_color_lut32_extract(color->green, 10)) |
4069+
REG_FIELD_PREP(LUT_3D_DATA_BLUE_MASK, drm_color_lut32_extract(color->blue, 10));
4070+
}
4071+
4072+
static void glk_load_lut_3d(struct intel_dsb *dsb,
4073+
struct intel_crtc *crtc,
4074+
const struct drm_property_blob *blob)
4075+
{
4076+
struct intel_display *display = to_intel_display(crtc->base.dev);
4077+
const struct drm_color_lut32 *lut = blob->data;
4078+
int i, lut_size = drm_color_lut32_size(blob);
4079+
enum pipe pipe = crtc->pipe;
4080+
4081+
if (!dsb && intel_de_read(display, LUT_3D_CTL(pipe)) & LUT_3D_READY) {
4082+
drm_err(display->drm, "[CRTC:%d:%s] 3D LUT not ready, not loading LUTs\n",
4083+
crtc->base.base.id, crtc->base.name);
4084+
return;
4085+
}
4086+
4087+
intel_de_write_dsb(display, dsb, LUT_3D_INDEX(pipe), LUT_3D_AUTO_INCREMENT);
4088+
for (i = 0; i < lut_size; i++)
4089+
intel_de_write_dsb(display, dsb, LUT_3D_DATA(pipe), glk_3dlut_10(&lut[i]));
4090+
intel_de_write_dsb(display, dsb, LUT_3D_INDEX(pipe), 0);
4091+
}
4092+
4093+
static void glk_lut_3d_commit(struct intel_dsb *dsb, struct intel_crtc *crtc, bool enable)
4094+
{
4095+
struct intel_display *display = to_intel_display(crtc);
4096+
enum pipe pipe = crtc->pipe;
4097+
u32 val = 0;
4098+
4099+
if (!dsb && intel_de_read(display, LUT_3D_CTL(pipe)) & LUT_3D_READY) {
4100+
drm_err(display->drm, "[CRTC:%d:%s] 3D LUT not ready, not committing change\n",
4101+
crtc->base.base.id, crtc->base.name);
4102+
return;
4103+
}
4104+
4105+
if (enable)
4106+
val = LUT_3D_ENABLE | LUT_3D_READY | LUT_3D_BIND_PLANE_1;
4107+
4108+
intel_de_write_dsb(display, dsb, LUT_3D_CTL(pipe), val);
4109+
}
4110+
38394111
static const struct intel_color_funcs chv_color_funcs = {
38404112
.color_check = chv_color_check,
38414113
.color_commit_arm = i9xx_color_commit_arm,
@@ -3883,6 +4155,8 @@ static const struct intel_color_funcs tgl_color_funcs = {
38834155
.lut_equal = icl_lut_equal,
38844156
.read_csc = icl_read_csc,
38854157
.get_config = skl_get_config,
4158+
.load_plane_csc_matrix = xelpd_load_plane_csc_matrix,
4159+
.load_plane_luts = xelpd_plane_load_luts,
38864160
};
38874161

38884162
static const struct intel_color_funcs icl_color_funcs = {
@@ -3963,6 +4237,67 @@ static const struct intel_color_funcs ilk_color_funcs = {
39634237
.get_config = ilk_get_config,
39644238
};
39654239

4240+
void intel_color_plane_commit_arm(struct intel_dsb *dsb,
4241+
const struct intel_plane_state *plane_state)
4242+
{
4243+
struct intel_display *display = to_intel_display(plane_state);
4244+
struct intel_crtc *crtc = to_intel_crtc(plane_state->uapi.crtc);
4245+
4246+
if (crtc && intel_color_crtc_has_3dlut(display, crtc->pipe))
4247+
glk_lut_3d_commit(dsb, crtc, !!plane_state->hw.lut_3d);
4248+
}
4249+
4250+
static void
4251+
intel_color_load_plane_csc_matrix(struct intel_dsb *dsb,
4252+
const struct intel_plane_state *plane_state)
4253+
{
4254+
struct intel_display *display = to_intel_display(plane_state);
4255+
4256+
if (display->funcs.color->load_plane_csc_matrix)
4257+
display->funcs.color->load_plane_csc_matrix(dsb, plane_state);
4258+
}
4259+
4260+
static void
4261+
intel_color_load_plane_luts(struct intel_dsb *dsb,
4262+
const struct intel_plane_state *plane_state)
4263+
{
4264+
struct intel_display *display = to_intel_display(plane_state);
4265+
4266+
if (display->funcs.color->load_plane_luts)
4267+
display->funcs.color->load_plane_luts(dsb, plane_state);
4268+
}
4269+
4270+
bool
4271+
intel_color_crtc_has_3dlut(struct intel_display *display, enum pipe pipe)
4272+
{
4273+
if (DISPLAY_VER(display) >= 12)
4274+
return pipe == PIPE_A || pipe == PIPE_B;
4275+
else
4276+
return false;
4277+
}
4278+
4279+
static void
4280+
intel_color_load_3dlut(struct intel_dsb *dsb,
4281+
const struct intel_plane_state *plane_state)
4282+
{
4283+
struct intel_display *display = to_intel_display(plane_state);
4284+
struct intel_crtc *crtc = to_intel_crtc(plane_state->uapi.crtc);
4285+
4286+
if (crtc && intel_color_crtc_has_3dlut(display, crtc->pipe))
4287+
glk_load_lut_3d(dsb, crtc, plane_state->hw.lut_3d);
4288+
}
4289+
4290+
void intel_color_plane_program_pipeline(struct intel_dsb *dsb,
4291+
const struct intel_plane_state *plane_state)
4292+
{
4293+
if (plane_state->hw.ctm)
4294+
intel_color_load_plane_csc_matrix(dsb, plane_state);
4295+
if (plane_state->hw.degamma_lut || plane_state->hw.gamma_lut)
4296+
intel_color_load_plane_luts(dsb, plane_state);
4297+
if (plane_state->hw.lut_3d)
4298+
intel_color_load_3dlut(dsb, plane_state);
4299+
}
4300+
39664301
void intel_color_crtc_init(struct intel_crtc *crtc)
39674302
{
39684303
struct intel_display *display = to_intel_display(crtc);

0 commit comments

Comments
 (0)