[PATCH v2 6/6] drm/i915/bios: Extract soc/intel_rom.c

2024-09-23 Thread Ville Syrjala
From: Ville Syrjälä 

Abstract away the nuts and bolts of the SPI vs. PCI ROM
stuff, and hide it all in soc/intel_rom.c so that the
VBT code doesn't have to care about this stuff.

This leaves intel_bios.c with a single codepath that
can focus on the details related to the VBT layout.

This should have no functional changes.

v2: Rebase due to vbt_signature changes
Drop unnecessary cast (Jani)

Reviewed-by: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/Makefile |   3 +-
 drivers/gpu/drm/i915/display/intel_bios.c | 149 +++-
 drivers/gpu/drm/i915/soc/intel_rom.c  | 160 ++
 drivers/gpu/drm/i915/soc/intel_rom.h  |  25 +++
 drivers/gpu/drm/xe/Makefile   |   3 +-
 .../xe/compat-i915-headers/soc/intel_rom.h|   6 +
 6 files changed, 223 insertions(+), 123 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/soc/intel_rom.c
 create mode 100644 drivers/gpu/drm/i915/soc/intel_rom.h
 create mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 70771e521b1c..e033bcaef4f3 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -51,7 +51,8 @@ i915-y += \
 i915-y += \
soc/intel_dram.o \
soc/intel_gmch.o \
-   soc/intel_pch.o
+   soc/intel_pch.o \
+   soc/intel_rom.o
 
 # core library code
 i915-y += \
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index c57426940cf8..9967b65e3cf6 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -33,12 +33,12 @@
 #include 
 #include 
 
+#include "soc/intel_rom.h"
+
 #include "i915_drv.h"
-#include "i915_reg.h"
 #include "intel_display.h"
 #include "intel_display_types.h"
 #include "intel_gmbus.h"
-#include "intel_uncore.h"
 
 #define _INTEL_BIOS_PRIVATE
 #include "intel_vbt_defs.h"
@@ -3056,152 +3056,59 @@ static struct vbt_header *firmware_get_vbt(struct 
intel_display *display,
return vbt;
 }
 
-static u32 intel_spi_read32(struct intel_uncore *uncore, u32 offset)
+static struct vbt_header *oprom_get_vbt(struct intel_display *display,
+   struct intel_rom *rom,
+   size_t *size, const char *type)
 {
-   intel_uncore_write(uncore, PRIMARY_SPI_ADDRESS, offset);
+   struct vbt_header *vbt;
+   size_t vbt_size;
+   loff_t offset;
 
-   return intel_uncore_read(uncore, PRIMARY_SPI_TRIGGER);
-}
-
-static u16 intel_spi_read16(struct intel_uncore *uncore, u32 offset)
-{
-   return intel_spi_read32(uncore, offset) & 0x;
-}
-
-static struct vbt_header *spi_oprom_get_vbt(struct intel_display *display,
-   size_t *size)
-{
-   struct drm_i915_private *i915 = to_i915(display->drm);
-   u32 count, data, found, store = 0;
-   u32 static_region, oprom_offset;
-   u32 oprom_size = 0x20;
-   u16 vbt_size;
-   u32 *vbt;
-
-   static_region = intel_uncore_read(&i915->uncore, SPI_STATIC_REGIONS);
-   static_region &= OPTIONROM_SPI_REGIONID_MASK;
-   intel_uncore_write(&i915->uncore, PRIMARY_SPI_REGIONID, static_region);
-
-   oprom_offset = intel_uncore_read(&i915->uncore, OROM_OFFSET);
-   oprom_offset &= OROM_OFFSET_MASK;
+   if (!rom)
+   return NULL;
 
BUILD_BUG_ON(vbt_signature_len != sizeof(vbt_signature) - 1);
BUILD_BUG_ON(vbt_signature_len != sizeof(u32));
 
-   for (count = 0; count < oprom_size; count += 4) {
-   data = intel_spi_read32(&i915->uncore, oprom_offset + count);
-   if (data == *((const u32 *)vbt_signature)) {
-   found = oprom_offset + count;
-   break;
-   }
-   }
+   offset = intel_rom_find(rom, *(const u32 *)vbt_signature);
+   if (offset < 0)
+   goto err_free_rom;
 
-   if (count >= oprom_size)
-   goto err_not_found;
-
-   if (sizeof(struct vbt_header) > oprom_size - count) {
+   if (sizeof(struct vbt_header) > intel_rom_size(rom) - offset) {
drm_dbg_kms(display->drm, "VBT header incomplete\n");
-   goto err_not_found;
+   goto err_free_rom;
}
 
-   /* Get VBT size and allocate space for the VBT */
-   vbt_size = intel_spi_read16(&i915->uncore,
-   found + offsetof(struct vbt_header, 
vbt_size));
+   BUILD_BUG_ON(sizeof(vbt->vbt_size) != sizeof(u16));
 
-   if (vbt_size > oprom_size - count) {
-   drm_dbg_kms(display->drm,
-   "VBT incomplete (vbt_size overflows)\n");
-   goto err_not_found;
+   vbt_size = intel_rom_read16(rom, offset + offsetof(struct vbt_header, 
vbt_size));
+   if (vbt_size > intel_rom_size(rom) - o

[PATCH v2 5/6] drm/i915/bios: Extract vbt_signature[]

2024-09-23 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the three hand rolled "$VBT"s with a vbt_signature[]
to avoid accidents.

v2: Include terminating '\0' for safety (Jani)

Reviewed-by: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index 38ea92b4ff13..c57426940cf8 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -2964,6 +2964,9 @@ static const struct bdb_header *get_bdb_header(const 
struct vbt_header *vbt)
return _vbt + vbt->bdb_offset;
 }
 
+static const char vbt_signature[] = "$VBT";
+static const int vbt_signature_len = 4;
+
 /**
  * intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
  * @display:   display device
@@ -2986,7 +2989,7 @@ bool intel_bios_is_valid_vbt(struct intel_display 
*display,
return false;
}
 
-   if (memcmp(vbt->signature, "$VBT", 4)) {
+   if (memcmp(vbt->signature, vbt_signature, vbt_signature_len)) {
drm_dbg_kms(display->drm, "VBT invalid signature\n");
return false;
}
@@ -3082,9 +3085,12 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
oprom_offset = intel_uncore_read(&i915->uncore, OROM_OFFSET);
oprom_offset &= OROM_OFFSET_MASK;
 
+   BUILD_BUG_ON(vbt_signature_len != sizeof(vbt_signature) - 1);
+   BUILD_BUG_ON(vbt_signature_len != sizeof(u32));
+
for (count = 0; count < oprom_size; count += 4) {
data = intel_spi_read32(&i915->uncore, oprom_offset + count);
-   if (data == *((const u32 *)"$VBT")) {
+   if (data == *((const u32 *)vbt_signature)) {
found = oprom_offset + count;
break;
}
@@ -3144,9 +3150,12 @@ static struct vbt_header *oprom_get_vbt(struct 
intel_display *display,
if (!oprom)
return NULL;
 
+   BUILD_BUG_ON(vbt_signature_len != sizeof(vbt_signature) - 1);
+   BUILD_BUG_ON(vbt_signature_len != sizeof(u32));
+
/* Scour memory looking for the VBT signature. */
for (i = 0; i + 4 < size; i += 4) {
-   if (ioread32(oprom + i) != *((const u32 *)"$VBT"))
+   if (ioread32(oprom + i) != *((const u32 *)vbt_signature))
continue;
 
p = oprom + i;
-- 
2.44.2



[PATCH v2 4/6] drm/i915/bios: Extract intel_spi_read16()

2024-09-23 Thread Ville Syrjala
From: Ville Syrjälä 

The SPI VBT codepath only knows how to read 4 bytes at a time.
So to read the 2 byte vbt_size it masks out the unwanted msbs.
Hide that little implementation detail inside a new intel_spi_read16()
helper. Alse rename the existing intel_spi_read() to intel_spi_read32()
to make it clear what it does.

Reviewed-by: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index d4281234773c..38ea92b4ff13 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -3053,13 +3053,18 @@ static struct vbt_header *firmware_get_vbt(struct 
intel_display *display,
return vbt;
 }
 
-static u32 intel_spi_read(struct intel_uncore *uncore, u32 offset)
+static u32 intel_spi_read32(struct intel_uncore *uncore, u32 offset)
 {
intel_uncore_write(uncore, PRIMARY_SPI_ADDRESS, offset);
 
return intel_uncore_read(uncore, PRIMARY_SPI_TRIGGER);
 }
 
+static u16 intel_spi_read16(struct intel_uncore *uncore, u32 offset)
+{
+   return intel_spi_read32(uncore, offset) & 0x;
+}
+
 static struct vbt_header *spi_oprom_get_vbt(struct intel_display *display,
size_t *size)
 {
@@ -3078,7 +3083,7 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
oprom_offset &= OROM_OFFSET_MASK;
 
for (count = 0; count < oprom_size; count += 4) {
-   data = intel_spi_read(&i915->uncore, oprom_offset + count);
+   data = intel_spi_read32(&i915->uncore, oprom_offset + count);
if (data == *((const u32 *)"$VBT")) {
found = oprom_offset + count;
break;
@@ -3094,9 +3099,8 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
}
 
/* Get VBT size and allocate space for the VBT */
-   vbt_size = intel_spi_read(&i915->uncore,
- found + offsetof(struct vbt_header, 
vbt_size));
-   vbt_size &= 0x;
+   vbt_size = intel_spi_read16(&i915->uncore,
+   found + offsetof(struct vbt_header, 
vbt_size));
 
if (vbt_size > oprom_size - count) {
drm_dbg_kms(display->drm,
@@ -3109,7 +3113,7 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
goto err_not_found;
 
for (count = 0; count < vbt_size; count += 4)
-   *(vbt + store++) = intel_spi_read(&i915->uncore, found + count);
+   *(vbt + store++) = intel_spi_read32(&i915->uncore, found + 
count);
 
if (!intel_bios_is_valid_vbt(display, vbt, vbt_size))
goto err_free_vbt;
-- 
2.44.2



[PATCH v2 3/6] drm/i915/bios: Round PCI ROM VBT allocation to multiple of 4

2024-09-23 Thread Ville Syrjala
From: Ville Syrjälä 

The SPI code rounds the VBT allocation to a multiple of four bytes
(presumably because it reads the VBT 4 bytes at a time). Do the
same for the PCI ROM side to eliminate pointless differences between
the two codepaths. This will make no functional difference.

Reviewed-by: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index 37f30bb76e08..d4281234773c 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -3166,7 +3166,7 @@ static struct vbt_header *oprom_get_vbt(struct 
intel_display *display,
}
 
/* The rest will be validated by intel_bios_is_valid_vbt() */
-   vbt = kmalloc(vbt_size, GFP_KERNEL);
+   vbt = kmalloc(round_up(vbt_size, 4), GFP_KERNEL);
if (!vbt)
goto err_unmap_oprom;
 
-- 
2.44.2



[PATCH v2 2/6] drm/i915/bios: Add some size checks to SPI VBT read

2024-09-23 Thread Ville Syrjala
From: Ville Syrjälä 

Unify the SPI vs. PCI ROM VBT read codepaths a bit by
pulling some size overflow checks from the PCI side
into the SPI side.

v2: s/drm_dbg()/drm_dbg_kms()/

Reviewed-by: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index b00aad23d6c2..37f30bb76e08 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -3088,11 +3088,22 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
if (count >= oprom_size)
goto err_not_found;
 
+   if (sizeof(struct vbt_header) > oprom_size - count) {
+   drm_dbg_kms(display->drm, "VBT header incomplete\n");
+   goto err_not_found;
+   }
+
/* Get VBT size and allocate space for the VBT */
vbt_size = intel_spi_read(&i915->uncore,
  found + offsetof(struct vbt_header, 
vbt_size));
vbt_size &= 0x;
 
+   if (vbt_size > oprom_size - count) {
+   drm_dbg_kms(display->drm,
+   "VBT incomplete (vbt_size overflows)\n");
+   goto err_not_found;
+   }
+
vbt = kzalloc(round_up(vbt_size, 4), GFP_KERNEL);
if (!vbt)
goto err_not_found;
-- 
2.44.2



[PATCH v2 1/6] drm/i915/bios: Use drm_dbg_kms() consistently

2024-09-23 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the few oddball drm_dbg() calls in VBT related code
with drm_dbg_kms() as that is what we generally use for all
display code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index daa4b9535123..b00aad23d6c2 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -1706,8 +1706,8 @@ parse_mipi_config(struct intel_display *display,
return;
}
 
-   drm_dbg(display->drm, "Found MIPI Config block, panel index = %d\n",
-   panel_type);
+   drm_dbg_kms(display->drm, "Found MIPI Config block, panel index = %d\n",
+   panel_type);
 
/*
 * get hold of the correct configuration block and pps data as per
@@ -2067,8 +2067,8 @@ parse_mipi_sequence(struct intel_display *display,
return;
}
 
-   drm_dbg(display->drm, "Found MIPI sequence block v%u\n",
-   sequence->version);
+   drm_dbg_kms(display->drm, "Found MIPI sequence block v%u\n",
+   sequence->version);
 
seq_data = find_panel_sequence_block(display, sequence, panel_type, 
&seq_size);
if (!seq_data)
@@ -2114,7 +2114,7 @@ parse_mipi_sequence(struct intel_display *display,
 
fixup_mipi_sequences(display, panel);
 
-   drm_dbg(display->drm, "MIPI related VBT parsing complete\n");
+   drm_dbg_kms(display->drm, "MIPI related VBT parsing complete\n");
return;
 
 err:
@@ -2771,9 +2771,9 @@ static bool child_device_size_valid(struct intel_display 
*display, int size)
expected_size = child_device_expected_size(display->vbt.version);
if (expected_size < 0) {
expected_size = sizeof(struct child_device_config);
-   drm_dbg(display->drm,
-   "Expected child device config size for VBT version %u 
not known; assuming %d\n",
-   display->vbt.version, expected_size);
+   drm_dbg_kms(display->drm,
+   "Expected child device config size for VBT version 
%u not known; assuming %d\n",
+   display->vbt.version, expected_size);
}
 
/* Flag an error for unexpected size, but continue anyway. */
@@ -3143,14 +3143,14 @@ static struct vbt_header *oprom_get_vbt(struct 
intel_display *display,
goto err_unmap_oprom;
 
if (sizeof(struct vbt_header) > size) {
-   drm_dbg(display->drm, "VBT header incomplete\n");
+   drm_dbg_kms(display->drm, "VBT header incomplete\n");
goto err_unmap_oprom;
}
 
vbt_size = ioread16(p + offsetof(struct vbt_header, vbt_size));
if (vbt_size > size) {
-   drm_dbg(display->drm,
-   "VBT incomplete (vbt_size overflows)\n");
+   drm_dbg_kms(display->drm,
+   "VBT incomplete (vbt_size overflows)\n");
goto err_unmap_oprom;
}
 
-- 
2.44.2



[PATCH v2 0/6] drm/i915/bios: Refactor ROM access

2024-09-23 Thread Ville Syrjala
From: Ville Syrjälä 

Unify the behaviour of the PCI ROM vs. SPI flash VBT
read codepaths, and relocate out the low level nuts details
from intel_bios.c into a new soc/intel_rom.c file.

v2: Sort out the drm_dbg() vs. drm_dbg_kms() mess
Include terminating '\0' in vbt_signature[]
Drop an unneccesry cast

Ville Syrjälä (6):
  drm/i915/bios: Use drm_dbg_kms() consistently
  drm/i915/bios: Add some size checks to SPI VBT read
  drm/i915/bios: Round PCI ROM VBT allocation to multiple of 4
  drm/i915/bios: Extract intel_spi_read16()
  drm/i915/bios: Extract vbt_signature[]
  drm/i915/bios: Extract soc/intel_rom.c

 drivers/gpu/drm/i915/Makefile |   3 +-
 drivers/gpu/drm/i915/display/intel_bios.c | 157 +
 drivers/gpu/drm/i915/soc/intel_rom.c  | 160 ++
 drivers/gpu/drm/i915/soc/intel_rom.h  |  25 +++
 drivers/gpu/drm/xe/Makefile   |   3 +-
 .../xe/compat-i915-headers/soc/intel_rom.h|   6 +
 6 files changed, 239 insertions(+), 115 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/soc/intel_rom.c
 create mode 100644 drivers/gpu/drm/i915/soc/intel_rom.h
 create mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h

-- 
2.44.2



[PATCH 3/3] drm/i915/dp: Extract intel_edp_set_sink_rates()

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

Declutter intel_edp_init_dpcd() a bit by extracting the sink
rates probing into its own function.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 76 +
 1 file changed, 40 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 6a1b0e93a1fc..ae3f242fa925 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4066,6 +4066,45 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp)
intel_dp->mso_pixel_overlap = mso ? info->mso_pixel_overlap : 0;
 }
 
+static void
+intel_edp_set_sink_rates(struct intel_dp *intel_dp)
+{
+   intel_dp->num_sink_rates = 0;
+
+   if (intel_dp->edp_dpcd[0] >= DP_EDP_14) {
+   __le16 sink_rates[DP_MAX_SUPPORTED_RATES];
+   int i;
+
+   drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
+sink_rates, sizeof(sink_rates));
+
+   for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
+   int val = le16_to_cpu(sink_rates[i]);
+
+   if (val == 0)
+   break;
+
+   /* Value read multiplied by 200kHz gives the per-lane
+* link rate in kHz. The source rates are, however,
+* stored in terms of LS_Clk kHz. The full conversion
+* back to symbols is
+* (val * 200kHz)*(8/10 ch. encoding)*(1/8 bit to Byte)
+*/
+   intel_dp->sink_rates[i] = (val * 200) / 10;
+   }
+   intel_dp->num_sink_rates = i;
+   }
+
+   /*
+* Use DP_LINK_RATE_SET if DP_SUPPORTED_LINK_RATES are available,
+* default to DP_MAX_LINK_RATE and DP_LINK_BW_SET otherwise.
+*/
+   if (intel_dp->num_sink_rates)
+   intel_dp->use_rate_select = true;
+   else
+   intel_dp_set_sink_rates(intel_dp);
+}
+
 static bool
 intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector 
*connector)
 {
@@ -4110,42 +4149,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct 
intel_connector *connector
 */
intel_psr_init_dpcd(intel_dp);
 
-   /* Clear the default sink rates */
-   intel_dp->num_sink_rates = 0;
-
-   /* Read the eDP 1.4+ supported link rates. */
-   if (intel_dp->edp_dpcd[0] >= DP_EDP_14) {
-   __le16 sink_rates[DP_MAX_SUPPORTED_RATES];
-   int i;
-
-   drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
-   sink_rates, sizeof(sink_rates));
-
-   for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
-   int val = le16_to_cpu(sink_rates[i]);
-
-   if (val == 0)
-   break;
-
-   /* Value read multiplied by 200kHz gives the per-lane
-* link rate in kHz. The source rates are, however,
-* stored in terms of LS_Clk kHz. The full conversion
-* back to symbols is
-* (val * 200kHz)*(8/10 ch. encoding)*(1/8 bit to Byte)
-*/
-   intel_dp->sink_rates[i] = (val * 200) / 10;
-   }
-   intel_dp->num_sink_rates = i;
-   }
-
-   /*
-* Use DP_LINK_RATE_SET if DP_SUPPORTED_LINK_RATES are available,
-* default to DP_MAX_LINK_RATE and DP_LINK_BW_SET otherwise.
-*/
-   if (intel_dp->num_sink_rates)
-   intel_dp->use_rate_select = true;
-   else
-   intel_dp_set_sink_rates(intel_dp);
+   intel_edp_set_sink_rates(intel_dp);
intel_dp_set_max_sink_lane_count(intel_dp);
 
/* Read the eDP DSC DPCD registers */
-- 
2.44.2



[PATCH 1/3] drm/i915/dp: Fix colorimetry detection

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

intel_dp_init_connector() is no place for detecting stuff via
DPCD (except perhaps for eDP). Move the colorimetry stuff into
a more appropriate place.

Cc: Jouni Högander 
Fixes: 00076671a648 ("drm/i915/display: Move colorimetry_support from intel_psr 
to intel_dp")
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 19f78432cc8f..f44951d8a0f8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4082,6 +4082,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct 
intel_connector *connector
 drm_dp_is_branch(intel_dp->dpcd));
intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
 
+   intel_dp->colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+
/*
 * Read the eDP display control registers.
 *
@@ -4195,6 +4198,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 
intel_init_dpcd_quirks(intel_dp, &intel_dp->desc.ident);
 
+   intel_dp->colorimetry_support =
+   intel_dp_get_colorimetry_status(intel_dp);
+
intel_dp_update_sink_caps(intel_dp);
}
 
@@ -6946,9 +6952,6 @@ intel_dp_init_connector(struct intel_digital_port 
*dig_port,
"HDCP init failed, skipping.\n");
}
 
-   intel_dp->colorimetry_support =
-   intel_dp_get_colorimetry_status(intel_dp);
-
intel_dp->frl.is_trained = false;
intel_dp->frl.trained_rate_gbps = 0;
 
-- 
2.44.2



[PATCH 2/3] drm/i915/dp: Make intel_dp_get_colorimetry_status() static

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

intel_dp_get_colorimetry_status() is not used outside of
intel_dp.c. Make it static.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
 drivers/gpu/drm/i915/display/intel_dp.h | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index f44951d8a0f8..6a1b0e93a1fc 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3915,7 +3915,7 @@ void intel_dp_configure_protocol_converter(struct 
intel_dp *intel_dp,
str_enable_disable(tmp));
 }
 
-bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
+static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
 {
u8 dprx = 0;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index a0a31fb64716..d1436face8b2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -117,7 +117,6 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int 
port_clock,
 bool intel_dp_source_supports_tps3(struct drm_i915_private *i915);
 bool intel_dp_source_supports_tps4(struct drm_i915_private *i915);
 
-bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
 int intel_dp_link_required(int pixel_clock, int bpp);
 int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
 int bw_overhead);
-- 
2.44.2



[PATCH 3/7] drm/i915: Enable 10bpc + CCS on TGL+

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

TGL+ support 10bpc compressed scanout. Enable it.

v2: Set .depth=30 for all variants to match drm_fourcc.c
Set clear color block size to 0x0

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fb.c   | 36 +++
 .../drm/i915/display/skl_universal_plane.c|  8 ++---
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
b/drivers/gpu/drm/i915/display/intel_fb.c
index bcf0d016f499..9b9da4f71f73 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -67,6 +67,18 @@ static const struct drm_format_info gen12_ccs_formats[] = {
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 2,
  .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_YUYV, .num_planes = 2,
  .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
  .hsub = 2, .vsub = 1, .is_yuv = true },
@@ -113,6 +125,18 @@ static const struct drm_format_info gen12_ccs_cc_formats[] 
= {
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 3,
  .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 3,
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 3,
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 3,
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 3,
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
 static const struct drm_format_info gen12_flat_ccs_cc_formats[] = {
@@ -128,6 +152,18 @@ static const struct drm_format_info 
gen12_flat_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 2,
  .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
 struct intel_modifier_desc {
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 17d4c880ecc4..9f34df60b112 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2315,6 +2315,10 @@ static bool gen12_plane_format_mod_supported(struct 
drm_plane *_plane,
case DRM_FORMAT_XBGR:
case DRM_FORMAT_ARGB:
case DRM_FORMAT_ABGR:
+   case DRM_FORMAT_XRGB2101010:
+   case DRM_FORMAT_XBGR2101010:
+   case DRM_FORMAT_ARGB2101010:
+   case DRM_FORMAT_ABGR2101010:
if (intel_fb_is_ccs_modifier(modifier))
return true;
fallthrough;
@@ -2331,10 +2335,6 @@ static bool gen12_plane_format_mod_su

[PATCH 5/7] drm/i915: Enable fp16 + CCS on TGL+

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

TGL+ support compressed fp16 scanout. Enable it.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fb.c   | 36 +++
 .../drm/i915/display/skl_universal_plane.c|  8 ++---
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
b/drivers/gpu/drm/i915/display/intel_fb.c
index 83495e165da7..2d384092416e 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -87,6 +87,18 @@ static const struct drm_format_info gen12_ccs_formats[] = {
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
  .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 2,
+ .char_per_block = { 8, 1 }, .block_w = { 1, 1 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 2,
+ .char_per_block = { 8, 1 }, .block_w = { 1, 1 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 2,
+ .char_per_block = { 8, 1 }, .block_w = { 1, 1 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 2,
+ .char_per_block = { 8, 1 }, .block_w = { 1, 1 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_YUYV, .num_planes = 2,
  .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
  .hsub = 2, .vsub = 1, .is_yuv = true },
@@ -145,6 +157,18 @@ static const struct drm_format_info gen12_ccs_cc_formats[] 
= {
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 3,
  .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 3,
+ .char_per_block = { 8, 1, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 
1, 1, 0 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 3,
+ .char_per_block = { 8, 1, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 
1, 1, 0 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 3,
+ .char_per_block = { 8, 1, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 
1, 1, 0 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 3,
+ .char_per_block = { 8, 1, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 
1, 1, 0 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
 static const struct drm_format_info gen12_flat_ccs_cc_formats[] = {
@@ -172,6 +196,18 @@ static const struct drm_format_info 
gen12_flat_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
  .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 2,
+ .char_per_block = { 8, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 2,
+ .char_per_block = { 8, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 2,
+ .char_per_block = { 8, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 2,
+ .char_per_block = { 8, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
 struct intel_modifier_desc {
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 8817758ef10d..afaa92a6d91c 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2373,6 +2373,10 @@ static bool gen12_plane_format_mod_supported(struct 
drm_plane *_plane,
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
+   case DRM_FORMAT_XBGR16161616F:
+   case DRM_FORMAT_ABGR16161616F:
+   case DRM_FORMAT_XRGB16161616F:
+   case DRM_FORMAT_ARGB16161616F:
if (intel_fb_is_ccs_modifier(modifier))
return true;
fallthrough;
@@ -2391,10 +2395,6 @@ static bool gen12_plane_format_mod_supported(struct 
drm_plane *_plane,
case DRM_FORMAT_

[PATCH 7/7] drm/i915: s/gen12/tgl/ in the universal plane code

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

Using "gen12" in display code is not desirable. Replace
it with "tgl" to match how we talk about other platforms
in the same code.

Signed-off-by: Ville Syrjälä 
---
 .../gpu/drm/i915/display/skl_universal_plane.c   | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index f56d679b0143..a82297fb4213 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2355,8 +2355,8 @@ static bool icl_plane_format_mod_supported(struct 
drm_plane *_plane,
}
 }
 
-static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
-u32 format, u64 modifier)
+static bool tgl_plane_format_mod_supported(struct drm_plane *_plane,
+  u32 format, u64 modifier)
 {
struct intel_plane *plane = to_intel_plane(_plane);
 
@@ -2425,13 +2425,13 @@ static const struct drm_plane_funcs icl_plane_funcs = {
.format_mod_supported = icl_plane_format_mod_supported,
 };
 
-static const struct drm_plane_funcs gen12_plane_funcs = {
+static const struct drm_plane_funcs tgl_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = intel_plane_destroy,
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
-   .format_mod_supported = gen12_plane_format_mod_supported,
+   .format_mod_supported = tgl_plane_format_mod_supported,
 };
 
 static void
@@ -2473,8 +2473,8 @@ static bool skl_plane_has_rc_ccs(struct drm_i915_private 
*i915,
(plane_id == PLANE_1 || plane_id == PLANE_2);
 }
 
-static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915,
-  enum plane_id plane_id)
+static bool tgl_plane_has_mc_ccs(struct drm_i915_private *i915,
+enum plane_id plane_id)
 {
if (DISPLAY_VER(i915) < 12)
return false;
@@ -2512,7 +2512,7 @@ static u8 skl_get_plane_caps(struct drm_i915_private 
*i915,
caps |= INTEL_PLANE_CAP_CCS_RC_CC;
}
 
-   if (gen12_plane_has_mc_ccs(i915, plane_id))
+   if (tgl_plane_has_mc_ccs(i915, plane_id))
caps |= INTEL_PLANE_CAP_CCS_MC;
 
if (DISPLAY_VER(i915) >= 14 && IS_DGFX(i915))
@@ -2603,7 +2603,7 @@ skl_universal_plane_create(struct drm_i915_private 
*dev_priv,
plane_id, &num_formats);
 
if (DISPLAY_VER(dev_priv) >= 12)
-   plane_funcs = &gen12_plane_funcs;
+   plane_funcs = &tgl_plane_funcs;
else if (DISPLAY_VER(dev_priv) == 11)
plane_funcs = &icl_plane_funcs;
else
-- 
2.44.2



[PATCH 6/7] drm/i915: Drop GEN12_MC_CCS check from skl_plane_max_width()

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS is tgl+ only, so checking for
in skl_plane_max_width() (which only applies to pre-glk hardware)
is pointless.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/skl_universal_plane.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index afaa92a6d91c..f56d679b0143 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -349,7 +349,6 @@ static int skl_plane_max_width(const struct drm_framebuffer 
*fb,
return 5120;
case I915_FORMAT_MOD_Y_TILED_CCS:
case I915_FORMAT_MOD_Yf_TILED_CCS:
-   case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
/* FIXME AUX plane? */
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Yf_TILED:
-- 
2.44.2



[PATCH 4/7] drm/i915: Enable 10bpc + CCS on ICL

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

ICL also supports compressed 10bpc scanout. Enable it.

v2: Set .depth=30 for all variants to match drm_fourcc.c

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fb.c   |  8 +++
 .../drm/i915/display/skl_universal_plane.c| 65 +++
 2 files changed, 73 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
b/drivers/gpu/drm/i915/display/intel_fb.c
index 9b9da4f71f73..83495e165da7 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -45,6 +45,14 @@ static const struct drm_format_info skl_ccs_formats[] = {
  .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 2,
  .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
+   { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
+ .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
+   { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
+ .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
+   { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2,
+ .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
+   { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
+ .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
 };
 
 /*
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 9f34df60b112..8817758ef10d 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2302,6 +2302,60 @@ static bool skl_plane_format_mod_supported(struct 
drm_plane *_plane,
}
 }
 
+static bool icl_plane_format_mod_supported(struct drm_plane *_plane,
+  u32 format, u64 modifier)
+{
+   struct intel_plane *plane = to_intel_plane(_plane);
+
+   if (!intel_fb_plane_supports_modifier(plane, modifier))
+   return false;
+
+   switch (format) {
+   case DRM_FORMAT_XRGB:
+   case DRM_FORMAT_XBGR:
+   case DRM_FORMAT_ARGB:
+   case DRM_FORMAT_ABGR:
+   case DRM_FORMAT_XRGB2101010:
+   case DRM_FORMAT_XBGR2101010:
+   case DRM_FORMAT_ARGB2101010:
+   case DRM_FORMAT_ABGR2101010:
+   if (intel_fb_is_ccs_modifier(modifier))
+   return true;
+   fallthrough;
+   case DRM_FORMAT_RGB565:
+   case DRM_FORMAT_YUYV:
+   case DRM_FORMAT_YVYU:
+   case DRM_FORMAT_UYVY:
+   case DRM_FORMAT_VYUY:
+   case DRM_FORMAT_NV12:
+   case DRM_FORMAT_XYUV:
+   case DRM_FORMAT_P010:
+   case DRM_FORMAT_P012:
+   case DRM_FORMAT_P016:
+   case DRM_FORMAT_XVYU2101010:
+   if (modifier == I915_FORMAT_MOD_Yf_TILED)
+   return true;
+   fallthrough;
+   case DRM_FORMAT_C8:
+   case DRM_FORMAT_XBGR16161616F:
+   case DRM_FORMAT_ABGR16161616F:
+   case DRM_FORMAT_XRGB16161616F:
+   case DRM_FORMAT_ARGB16161616F:
+   case DRM_FORMAT_Y210:
+   case DRM_FORMAT_Y212:
+   case DRM_FORMAT_Y216:
+   case DRM_FORMAT_XVYU12_16161616:
+   case DRM_FORMAT_XVYU16161616:
+   if (modifier == DRM_FORMAT_MOD_LINEAR ||
+   modifier == I915_FORMAT_MOD_X_TILED ||
+   modifier == I915_FORMAT_MOD_Y_TILED)
+   return true;
+   fallthrough;
+   default:
+   return false;
+   }
+}
+
 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
 u32 format, u64 modifier)
 {
@@ -2363,6 +2417,15 @@ static const struct drm_plane_funcs skl_plane_funcs = {
.format_mod_supported = skl_plane_format_mod_supported,
 };
 
+static const struct drm_plane_funcs icl_plane_funcs = {
+   .update_plane = drm_atomic_helper_update_plane,
+   .disable_plane = drm_atomic_helper_disable_plane,
+   .destroy = intel_plane_destroy,
+   .atomic_duplicate_state = intel_plane_duplicate_state,
+   .atomic_destroy_state = intel_plane_destroy_state,
+   .format_mod_supported = icl_plane_format_mod_supported,
+};
+
 static const struct drm_plane_funcs gen12_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
@@ -2542,6 +2605,8 @@ skl_universal_plane_create(struct drm_i915_private 
*dev_priv,
 
if (DISPLAY_VER(dev_priv) >= 12)
plane_funcs = &gen12_plane_funcs;
+   else if (DISPLAY_VER(dev_priv) == 11)
+   plane_funcs = &icl_plane_funcs;
else
plane_funcs = &skl_plane_funcs;
 
-- 
2.44.2



[PATCH 2/7] drm/i915: Disable compression tricks on JSL

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

Bspec asks us to disable some compression trick on JSL. While the
bspec description is pretty vague it looks like this is some extra
trick for 10bpc+ CCS which presumably the ICL derived display engine
doesn't support.

Note that we aren't currently exposing 10bpc CCS scanout support,
but once that gets added this presumably becomes an issue.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/gt/intel_gt_regs.h | 1 +
 drivers/gpu/drm/i915/gt/intel_workarounds.c | 9 +
 2 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h 
b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
index 57a3c83d3655..67c47c8b75fb 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
@@ -432,6 +432,7 @@
 #define XEHPG_INSTDONE_GEOM_SVGMCR_REG(0x666c)
 
 #define CACHE_MODE_0_GEN7  _MMIO(0x7000) /* IVB+ */
+#define   DISABLE_REPACKING_FOR_COMPRESSIONREG_BIT(15) /* jsl+ */
 #define   RC_OP_FLUSH_ENABLE   (1 << 0)
 #define   HIZ_RAW_STALL_OPT_DISABLE(1 << 2)
 #define CACHE_MODE_1   _MMIO(0x7004) /* IVB+ */
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index e539a656cfc3..6972525fe6be 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -2299,6 +2299,15 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, 
struct i915_wa_list *wal)
 GEN8_RC_SEMA_IDLE_MSG_DISABLE);
}
 
+   if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) {
+   /*
+* "Disable Repacking for Compression (masked R/W access)
+*  before rendering compressed surfaces for display."
+*/
+   wa_masked_en(wal, CACHE_MODE_0_GEN7,
+DISABLE_REPACKING_FOR_COMPRESSION);
+   }
+
if (GRAPHICS_VER(i915) == 11) {
/* This is not an Wa. Enable for better image quality */
wa_masked_en(wal,
-- 
2.44.2



[PATCH 1/7] drm/i915: Set clear color block size to 0x0

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

We don't use the block size information for the clear color
plane. Technically the entire fb is the single block for the
single 64B clear color surface, so there is just no way to
delcare that as a constant since the fb size can be anything.

Define the clear color block size as 0x0 to make things less
confusing. We already declared that cpp/chars_per_block=0 for
the clear color as well. That also causes the drm core code
to mostly ignore the clear color plane, which is exactly
what we want since that code doesn't know how to deal with
the clear color plane.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fb.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
b/drivers/gpu/drm/i915/display/intel_fb.c
index d2ff21e98545..bcf0d016f499 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -102,31 +102,31 @@ static const struct drm_format_info gen12_ccs_formats[] = 
{
  */
 static const struct drm_format_info gen12_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_XRGB, .depth = 24, .num_planes = 3,
- .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
  .hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR, .depth = 24, .num_planes = 3,
- .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
  .hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB, .depth = 32, .num_planes = 3,
- .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 3,
- .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 
1, 1, 0 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
 static const struct drm_format_info gen12_flat_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_XRGB, .depth = 24, .num_planes = 2,
- .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
  .hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR, .depth = 24, .num_planes = 2,
- .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
  .hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB, .depth = 32, .num_planes = 2,
- .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 2,
- .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
-- 
2.44.2



[PATCH 0/7] drm/i915: 10bpc/fp16 + CCS support

2024-09-18 Thread Ville Syrjala
From: Ville Syrjälä 

Enable 10bpc+CCS scanout support for ICL+, and fp16+CCS
scanout for TGL+, and toss in a couple of drive-by
cleanups in the end for good measure.

Test-with: 20240918120518.30258-1-ville.syrj...@linux.intel.com

Ville Syrjälä (7):
  drm/i915: Set clear color block size to 0x0
  drm/i915: Disable compression tricks on JSL
  drm/i915: Enable 10bpc + CCS on TGL+
  drm/i915: Enable 10bpc + CCS on ICL
  drm/i915: Enable fp16 + CCS on TGL+
  drm/i915: Drop GEN12_MC_CCS check from skl_plane_max_width()
  drm/i915: s/gen12/tgl/ in the universal plane code

 drivers/gpu/drm/i915/display/intel_fb.c   | 96 --
 .../drm/i915/display/skl_universal_plane.c| 98 +++
 drivers/gpu/drm/i915/gt/intel_gt_regs.h   |  1 +
 drivers/gpu/drm/i915/gt/intel_workarounds.c   |  9 ++
 4 files changed, 179 insertions(+), 25 deletions(-)

-- 
2.44.2



[PATCH 7/7] drm/i915: Rename variables in ilk_intermedidate_wm()

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

ilk_compute_intermediate_wm() uses rather poor variable names
for its watermark structs. Borrow a better naming convention
from the g4x/vlv counterpart code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/i9xx_wm.c | 35 +++---
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c 
b/drivers/gpu/drm/i915/display/i9xx_wm.c
index cfc487563c25..fc928307d062 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.c
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.c
@@ -2993,8 +2993,9 @@ static int ilk_compute_intermediate_wm(struct 
intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
-   struct intel_pipe_wm *a = &new_crtc_state->wm.ilk.intermediate;
-   const struct intel_pipe_wm *b = &old_crtc_state->wm.ilk.optimal;
+   struct intel_pipe_wm *intermediate = 
&new_crtc_state->wm.ilk.intermediate;
+   const struct intel_pipe_wm *optimal = &new_crtc_state->wm.ilk.optimal;
+   const struct intel_pipe_wm *active = &old_crtc_state->wm.ilk.optimal;
int level;
 
/*
@@ -3002,25 +3003,29 @@ static int ilk_compute_intermediate_wm(struct 
intel_atomic_state *state,
 * currently active watermarks to get values that are safe both before
 * and after the vblank.
 */
-   *a = new_crtc_state->wm.ilk.optimal;
+   *intermediate = *optimal;
if (!new_crtc_state->hw.active ||
intel_crtc_needs_modeset(new_crtc_state) ||
state->skip_intermediate_wm)
return 0;
 
-   a->pipe_enabled |= b->pipe_enabled;
-   a->sprites_enabled |= b->sprites_enabled;
-   a->sprites_scaled |= b->sprites_scaled;
+   intermediate->pipe_enabled |= active->pipe_enabled;
+   intermediate->sprites_enabled |= active->sprites_enabled;
+   intermediate->sprites_scaled |= active->sprites_scaled;
 
for (level = 0; level < dev_priv->display.wm.num_levels; level++) {
-   struct intel_wm_level *a_wm = &a->wm[level];
-   const struct intel_wm_level *b_wm = &b->wm[level];
+   struct intel_wm_level *intermediate_wm = 
&intermediate->wm[level];
+   const struct intel_wm_level *active_wm = &active->wm[level];
 
-   a_wm->enable &= b_wm->enable;
-   a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val);
-   a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val);
-   a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val);
-   a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val);
+   intermediate_wm->enable &= active_wm->enable;
+   intermediate_wm->pri_val = max(intermediate_wm->pri_val,
+  active_wm->pri_val);
+   intermediate_wm->spr_val = max(intermediate_wm->spr_val,
+  active_wm->spr_val);
+   intermediate_wm->cur_val = max(intermediate_wm->cur_val,
+  active_wm->cur_val);
+   intermediate_wm->fbc_val = max(intermediate_wm->fbc_val,
+  active_wm->fbc_val);
}
 
/*
@@ -3029,14 +3034,14 @@ static int ilk_compute_intermediate_wm(struct 
intel_atomic_state *state,
 * there's no safe way to transition from the old state to
 * the new state, so we need to fail the atomic transaction.
 */
-   if (!ilk_validate_pipe_wm(dev_priv, a))
+   if (!ilk_validate_pipe_wm(dev_priv, intermediate))
return -EINVAL;
 
/*
 * If our intermediate WM are identical to the final WM, then we can
 * omit the post-vblank programming; only update if it's different.
 */
-   if (memcmp(a, &new_crtc_state->wm.ilk.optimal, sizeof(*a)) != 0)
+   if (memcmp(intermediate, optimal, sizeof(*intermediate)) != 0)
new_crtc_state->wm.need_postvbl_update = true;
 
return 0;
-- 
2.44.2



[PATCH 6/7] drm/i915: s/disable_lp_wm/disable_cxsr/

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

The ilk+ disable_lp_wm boolean has the exact same role as
disable_cxsr for gmch platforms. The documentation also
still talks about CxSR on ilk+ even theough the way you
control it has now change to involve toggling the LP watermarks.
Get rid of disable_lp_wm and just use disable_cxsr for ilk+
as well.

TODO: Unify even more to not have any gmch vs. ilk+
  details in high level modeset code...

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/i9xx_wm.c |  2 +-
 drivers/gpu/drm/i915/display/i9xx_wm.h |  4 ++--
 drivers/gpu/drm/i915/display/intel_atomic.c|  1 -
 drivers/gpu/drm/i915/display/intel_atomic_plane.c  | 10 +-
 drivers/gpu/drm/i915/display/intel_display.c   |  4 ++--
 drivers/gpu/drm/i915/display/intel_display_types.h |  3 ---
 6 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c 
b/drivers/gpu/drm/i915/display/i9xx_wm.c
index 15ed3b810947..cfc487563c25 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.c
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.c
@@ -3396,7 +3396,7 @@ static void ilk_write_wm_values(struct drm_i915_private 
*dev_priv,
dev_priv->display.wm.hw = *results;
 }
 
-bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv)
+bool ilk_disable_cxsr(struct drm_i915_private *dev_priv)
 {
return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
 }
diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.h 
b/drivers/gpu/drm/i915/display/i9xx_wm.h
index de0920730ab2..06ac37c6c94b 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.h
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.h
@@ -13,12 +13,12 @@ struct intel_crtc_state;
 struct intel_plane_state;
 
 #ifdef I915
-bool ilk_disable_lp_wm(struct drm_i915_private *i915);
+bool ilk_disable_cxsr(struct drm_i915_private *i915);
 void ilk_wm_sanitize(struct drm_i915_private *i915);
 bool intel_set_memory_cxsr(struct drm_i915_private *i915, bool enable);
 void i9xx_wm_init(struct drm_i915_private *i915);
 #else
-static inline bool ilk_disable_lp_wm(struct drm_i915_private *i915)
+static inline bool ilk_disable_cxsr(struct drm_i915_private *i915)
 {
return false;
 }
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index 12d6ed940751..6cac26af128c 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -266,7 +266,6 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->update_pipe = false;
crtc_state->update_m_n = false;
crtc_state->update_lrr = false;
-   crtc_state->disable_lp_wm = false;
crtc_state->disable_cxsr = false;
crtc_state->update_wm_pre = false;
crtc_state->update_wm_post = false;
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c 
b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index 33fec36ec0bd..ef6cffd50275 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -471,9 +471,9 @@ static bool i9xx_must_disable_cxsr(const struct 
intel_crtc_state *new_crtc_state
return old_ctl != new_ctl;
 }
 
-static bool ilk_must_disable_lp_wm(const struct intel_crtc_state 
*new_crtc_state,
-  const struct intel_plane_state 
*old_plane_state,
-  const struct intel_plane_state 
*new_plane_state)
+static bool ilk_must_disable_cxsr(const struct intel_crtc_state 
*new_crtc_state,
+ const struct intel_plane_state 
*old_plane_state,
+ const struct intel_plane_state 
*new_plane_state)
 {
struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
bool old_visible = old_plane_state->uapi.visible;
@@ -588,8 +588,8 @@ static int intel_plane_atomic_calc_changes(const struct 
intel_crtc_state *old_cr
new_crtc_state->disable_cxsr = true;
 
if ((IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv) || 
IS_IVYBRIDGE(dev_priv)) &&
-   ilk_must_disable_lp_wm(new_crtc_state, old_plane_state, 
new_plane_state))
-   new_crtc_state->disable_lp_wm = true;
+   ilk_must_disable_cxsr(new_crtc_state, old_plane_state, 
new_plane_state))
+   new_crtc_state->disable_cxsr = true;
 
if (intel_plane_do_async_flip(plane, old_crtc_state, new_crtc_state)) {
new_crtc_state->do_async_flip = true;
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 60866316fc68..a2257096bd29 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1250,8 +1250,8 @@ static void intel_pre_plane_update(struct 
intel_atomic_state *state,
 *
 * WaCxSRDisabledForSpriteScaling:ivb
 */
-   if (old_crtc_state->hw.active &&
-   new

[PATCH 5/7] drm/i915: Move the dodgy pre-g4x wm stuff into i9xx_wm

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

As with other watermark calculations, the dodgy pre-g4x
update_wm_{pre,post} flag calcultion would like to know
if a modeset is about to happen or not, and technically
later stages in the atomic_check() may still flag one.
In practice that shouldn't happen as we don't have dynamic
CDCLK implemented for these old platforms.

Regardless it'll be nice to move this old cruft out from
the supposedly platform agnostic plane code.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/i9xx_wm.c| 74 +++
 .../gpu/drm/i915/display/intel_atomic_plane.c | 36 -
 2 files changed, 74 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c 
b/drivers/gpu/drm/i915/display/i9xx_wm.c
index 3151a31a5653..15ed3b810947 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.c
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.c
@@ -705,6 +705,76 @@ static void pnv_update_wm(struct drm_i915_private 
*dev_priv)
}
 }
 
+static bool i9xx_wm_need_update(const struct intel_plane_state 
*old_plane_state,
+   const struct intel_plane_state *new_plane_state)
+{
+   /* Update watermarks on tiling or size changes. */
+   if (old_plane_state->uapi.visible != new_plane_state->uapi.visible)
+   return true;
+
+   if (!old_plane_state->hw.fb || !new_plane_state->hw.fb)
+   return false;
+
+   if (old_plane_state->hw.fb->modifier != 
new_plane_state->hw.fb->modifier ||
+   old_plane_state->hw.rotation != new_plane_state->hw.rotation ||
+   drm_rect_width(&old_plane_state->uapi.src) != 
drm_rect_width(&new_plane_state->uapi.src) ||
+   drm_rect_height(&old_plane_state->uapi.src) != 
drm_rect_height(&new_plane_state->uapi.src) ||
+   drm_rect_width(&old_plane_state->uapi.dst) != 
drm_rect_width(&new_plane_state->uapi.dst) ||
+   drm_rect_height(&old_plane_state->uapi.dst) != 
drm_rect_height(&new_plane_state->uapi.dst))
+   return true;
+
+   return false;
+}
+
+static void i9xx_wm_compute(struct intel_crtc_state *new_crtc_state,
+   const struct intel_plane_state *old_plane_state,
+   const struct intel_plane_state *new_plane_state)
+{
+   bool turn_off, turn_on, visible, was_visible, mode_changed;
+
+   mode_changed = intel_crtc_needs_modeset(new_crtc_state);
+   was_visible = old_plane_state->uapi.visible;
+   visible = new_plane_state->uapi.visible;
+
+   if (!was_visible && !visible)
+   return;
+
+   turn_off = was_visible && (!visible || mode_changed);
+   turn_on = visible && (!was_visible || mode_changed);
+
+   /* FIXME nuke when all wm code is atomic */
+   if (turn_on) {
+   new_crtc_state->update_wm_pre = true;
+   } else if (turn_off) {
+   new_crtc_state->update_wm_post = true;
+   } else if (i9xx_wm_need_update(old_plane_state, new_plane_state)) {
+   /* FIXME bollocks */
+   new_crtc_state->update_wm_pre = true;
+   new_crtc_state->update_wm_post = true;
+   }
+}
+
+static int i9xx_compute_watermarks(struct intel_atomic_state *state,
+  struct intel_crtc *crtc)
+{
+   struct intel_crtc_state *new_crtc_state =
+   intel_atomic_get_new_crtc_state(state, crtc);
+   const struct intel_plane_state *old_plane_state;
+   const struct intel_plane_state *new_plane_state;
+   struct intel_plane *plane;
+   int i;
+
+   for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
+new_plane_state, i) {
+   if (plane->pipe != crtc->pipe)
+   continue;
+
+   i9xx_wm_compute(new_crtc_state, old_plane_state, 
new_plane_state);
+   }
+
+   return 0;
+}
+
 /*
  * Documentation says:
  * "If the line size is small, the TLB fetches can get in the way of the
@@ -4056,18 +4126,22 @@ static const struct intel_wm_funcs g4x_wm_funcs = {
 };
 
 static const struct intel_wm_funcs pnv_wm_funcs = {
+   .compute_watermarks = i9xx_compute_watermarks,
.update_wm = pnv_update_wm,
 };
 
 static const struct intel_wm_funcs i965_wm_funcs = {
+   .compute_watermarks = i9xx_compute_watermarks,
.update_wm = i965_update_wm,
 };
 
 static const struct intel_wm_funcs i9xx_wm_funcs = {
+   .compute_watermarks = i9xx_compute_watermarks,
.update_wm = i9xx_update_wm,
 };
 
 static const struct intel_wm_funcs i845_wm_funcs = {
+   .compute_watermarks = i9xx_compute_watermarks,
.update_wm = i845_update_wm,
 };
 
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c 
b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index 2aeb4cd5b5a1..33fec36ec0bd 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -392,28 +39

[PATCH 4/7] drm/i915: Clean up intel_wm_need_update()

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

intel_wm_need_update() is a mess when it comes to variable
names and constness. The checks also keep alternating randomly
between 'old != cur' vs. 'cur != old'. Clean it all up.

Signed-off-by: Ville Syrjälä 
---
 .../gpu/drm/i915/display/intel_atomic_plane.c | 20 +--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c 
b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index b5bbcc773ec0..2aeb4cd5b5a1 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -393,22 +393,22 @@ void intel_plane_set_invisible(struct intel_crtc_state 
*crtc_state,
 }
 
 /* FIXME nuke when all wm code is atomic */
-static bool intel_wm_need_update(const struct intel_plane_state *cur,
-struct intel_plane_state *new)
+static bool intel_wm_need_update(const struct intel_plane_state 
*old_plane_state,
+const struct intel_plane_state 
*new_plane_state)
 {
/* Update watermarks on tiling or size changes. */
-   if (new->uapi.visible != cur->uapi.visible)
+   if (old_plane_state->uapi.visible != new_plane_state->uapi.visible)
return true;
 
-   if (!cur->hw.fb || !new->hw.fb)
+   if (!old_plane_state->hw.fb || !new_plane_state->hw.fb)
return false;
 
-   if (cur->hw.fb->modifier != new->hw.fb->modifier ||
-   cur->hw.rotation != new->hw.rotation ||
-   drm_rect_width(&new->uapi.src) != drm_rect_width(&cur->uapi.src) ||
-   drm_rect_height(&new->uapi.src) != drm_rect_height(&cur->uapi.src) 
||
-   drm_rect_width(&new->uapi.dst) != drm_rect_width(&cur->uapi.dst) ||
-   drm_rect_height(&new->uapi.dst) != drm_rect_height(&cur->uapi.dst))
+   if (old_plane_state->hw.fb->modifier != 
new_plane_state->hw.fb->modifier ||
+   old_plane_state->hw.rotation != new_plane_state->hw.rotation ||
+   drm_rect_width(&old_plane_state->uapi.src) != 
drm_rect_width(&new_plane_state->uapi.src) ||
+   drm_rect_height(&old_plane_state->uapi.src) != 
drm_rect_height(&new_plane_state->uapi.src) ||
+   drm_rect_width(&old_plane_state->uapi.dst) != 
drm_rect_width(&new_plane_state->uapi.dst) ||
+   drm_rect_height(&old_plane_state->uapi.dst) != 
drm_rect_height(&new_plane_state->uapi.dst))
return true;
 
return false;
-- 
2.44.2



[PATCH 1/7] drm/i915: Remove leftover intel_sprite_set_colorkey_ioctl() prototype

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

intel_sprite_set_colorkey_ioctl() lives in intel_sprice_uapi.{c,h}
these days. For some reason the old protoype was left behind
in intel_sprite.h and even used by i915_driver.c. Remove the
leftovers and switch to including the correct header for the
prototype.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_sprite.h | 3 ---
 drivers/gpu/drm/i915/i915_driver.c  | 2 +-
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_sprite.h 
b/drivers/gpu/drm/i915/display/intel_sprite.h
index 044a032e41b9..f22abeb82032 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.h
+++ b/drivers/gpu/drm/i915/display/intel_sprite.h
@@ -10,7 +10,6 @@
 
 struct drm_device;
 struct drm_display_mode;
-struct drm_file;
 struct drm_i915_private;
 struct intel_crtc_state;
 struct intel_plane_state;
@@ -19,8 +18,6 @@ enum pipe;
 #ifdef I915
 struct intel_plane *intel_sprite_plane_create(struct drm_i915_private 
*dev_priv,
  enum pipe pipe, int plane);
-int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
-   struct drm_file *file_priv);
 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state);
 int chv_plane_check_rotation(const struct intel_plane_state *plane_state);
 
diff --git a/drivers/gpu/drm/i915/i915_driver.c 
b/drivers/gpu/drm/i915/i915_driver.c
index 943e938040c0..b0ec54a4e033 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -59,7 +59,7 @@
 #include "display/intel_overlay.h"
 #include "display/intel_pch_refclk.h"
 #include "display/intel_pps.h"
-#include "display/intel_sprite.h"
+#include "display/intel_sprite_uapi.h"
 #include "display/skl_watermark.h"
 
 #include "gem/i915_gem_context.h"
-- 
2.44.2



[PATCH 3/7] drm/i915: Extract ilk_must_disable_lp_wm()

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

Pull the ilk/snb/ivb LP watermark disable checks into a separate
function similar to the gmch counterpart (i9xx_must_disable_cxsr()).
Reduces the clutter in intel_plane_atomic_calc_changes() significantly.

Reviewed-by: Arun R Murthy 
Signed-off-by: Ville Syrjälä 
---
 .../gpu/drm/i915/display/intel_atomic_plane.c | 95 +++
 1 file changed, 57 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c 
b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index 928d985f9985..b5bbcc773ec0 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -493,6 +493,61 @@ static bool i9xx_must_disable_cxsr(const struct 
intel_crtc_state *new_crtc_state
return old_ctl != new_ctl;
 }
 
+static bool ilk_must_disable_lp_wm(const struct intel_crtc_state 
*new_crtc_state,
+  const struct intel_plane_state 
*old_plane_state,
+  const struct intel_plane_state 
*new_plane_state)
+{
+   struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
+   bool old_visible = old_plane_state->uapi.visible;
+   bool new_visible = new_plane_state->uapi.visible;
+   bool modeset, turn_on;
+
+   if (plane->id == PLANE_CURSOR)
+   return false;
+
+   modeset = intel_crtc_needs_modeset(new_crtc_state);
+   turn_on = new_visible && (!old_visible || modeset);
+
+   /*
+* ILK/SNB DVSACNTR/Sprite Enable
+* IVB SPR_CTL/Sprite Enable
+* "When in Self Refresh Big FIFO mode, a write to enable the
+*  plane will be internally buffered and delayed while Big FIFO
+*  mode is exiting."
+*
+* Which means that enabling the sprite can take an extra frame
+* when we start in big FIFO mode (LP1+). Thus we need to drop
+* down to LP0 and wait for vblank in order to make sure the
+* sprite gets enabled on the next vblank after the register write.
+* Doing otherwise would risk enabling the sprite one frame after
+* we've already signalled flip completion. We can resume LP1+
+* once the sprite has been enabled.
+*
+* With experimental results seems this is needed also for primary
+* plane, not only sprite plane.
+*/
+   if (turn_on)
+   return true;
+
+   /*
+* WaCxSRDisabledForSpriteScaling:ivb
+* IVB SPR_SCALE/Scaling Enable
+* "Low Power watermarks must be disabled for at least one
+*  frame before enabling sprite scaling, and kept disabled
+*  until sprite scaling is disabled."
+*
+* ILK/SNB DVSASCALE/Scaling Enable
+* "When in Self Refresh Big FIFO mode, scaling enable will be
+*  masked off while Big FIFO mode is exiting."
+*
+* Despite the w/a only being listed for IVB we assume that
+* the ILK/SNB note has similar ramifications, hence we apply
+* the w/a on all three platforms.
+*/
+   return !intel_plane_is_scaled(old_plane_state) &&
+   intel_plane_is_scaled(new_plane_state);
+}
+
 static int intel_plane_atomic_calc_changes(const struct intel_crtc_state 
*old_crtc_state,
   struct intel_crtc_state 
*new_crtc_state,
   const struct intel_plane_state 
*old_plane_state,
@@ -568,44 +623,8 @@ static int intel_plane_atomic_calc_changes(const struct 
intel_crtc_state *old_cr
i9xx_must_disable_cxsr(new_crtc_state, old_plane_state, 
new_plane_state))
new_crtc_state->disable_cxsr = true;
 
-   /*
-* ILK/SNB DVSACNTR/Sprite Enable
-* IVB SPR_CTL/Sprite Enable
-* "When in Self Refresh Big FIFO mode, a write to enable the
-*  plane will be internally buffered and delayed while Big FIFO
-*  mode is exiting."
-*
-* Which means that enabling the sprite can take an extra frame
-* when we start in big FIFO mode (LP1+). Thus we need to drop
-* down to LP0 and wait for vblank in order to make sure the
-* sprite gets enabled on the next vblank after the register write.
-* Doing otherwise would risk enabling the sprite one frame after
-* we've already signalled flip completion. We can resume LP1+
-* once the sprite has been enabled.
-*
-*
-* WaCxSRDisabledForSpriteScaling:ivb
-* IVB SPR_SCALE/Scaling Enable
-* "Low Power watermarks must be disabled for at least one
-*  frame before enabling sprite scaling, and kept disabled
-*  until sprite scaling is disabled."
-*
-* ILK/SNB DVSASCALE/Scaling Enable
-* "When in Self Refresh Big FIFO mode, scaling enable will be
-*  masked off while Big FIFO mode is exiting."
-*
-* Despi

[PATCH 2/7] drm/i915: Combine .compute_{pipe, intermediate}_wm() into one

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

We always call .compute_pipe_wm() and .compute_intermediate_wm()
back to back. Just combine them to a single hook for simplicity.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/i9xx_wm.c| 57 +--
 drivers/gpu/drm/i915/display/intel_display.c  | 17 +-
 .../gpu/drm/i915/display/intel_display_core.h |  6 +-
 drivers/gpu/drm/i915/display/intel_wm.c   | 24 ++--
 drivers/gpu/drm/i915/display/intel_wm.h   |  6 +-
 5 files changed, 63 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c 
b/drivers/gpu/drm/i915/display/i9xx_wm.c
index 5b21604312fd..3151a31a5653 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.c
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.c
@@ -1288,6 +1288,22 @@ static int g4x_compute_intermediate_wm(struct 
intel_atomic_state *state,
return 0;
 }
 
+static int g4x_compute_watermarks(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+   int ret;
+
+   ret = g4x_compute_pipe_wm(state, crtc);
+   if (ret)
+   return ret;
+
+   ret = g4x_compute_intermediate_wm(state, crtc);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 static void g4x_merge_wm(struct drm_i915_private *dev_priv,
 struct g4x_wm_values *wm)
 {
@@ -1914,6 +1930,22 @@ static int vlv_compute_intermediate_wm(struct 
intel_atomic_state *state,
return 0;
 }
 
+static int vlv_compute_watermarks(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+   int ret;
+
+   ret = vlv_compute_pipe_wm(state, crtc);
+   if (ret)
+   return ret;
+
+   ret = vlv_compute_intermediate_wm(state, crtc);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 static void vlv_merge_wm(struct drm_i915_private *dev_priv,
 struct vlv_wm_values *wm)
 {
@@ -2940,6 +2972,22 @@ static int ilk_compute_intermediate_wm(struct 
intel_atomic_state *state,
return 0;
 }
 
+static int ilk_compute_watermarks(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+   int ret;
+
+   ret = ilk_compute_pipe_wm(state, crtc);
+   if (ret)
+   return ret;
+
+   ret = ilk_compute_intermediate_wm(state, crtc);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 /*
  * Merge the watermarks from all active pipes for a specific level.
  */
@@ -3986,16 +4034,14 @@ static void ilk_wm_get_hw_state(struct drm_i915_private 
*dev_priv)
 }
 
 static const struct intel_wm_funcs ilk_wm_funcs = {
-   .compute_pipe_wm = ilk_compute_pipe_wm,
-   .compute_intermediate_wm = ilk_compute_intermediate_wm,
+   .compute_watermarks = ilk_compute_watermarks,
.initial_watermarks = ilk_initial_watermarks,
.optimize_watermarks = ilk_optimize_watermarks,
.get_hw_state = ilk_wm_get_hw_state,
 };
 
 static const struct intel_wm_funcs vlv_wm_funcs = {
-   .compute_pipe_wm = vlv_compute_pipe_wm,
-   .compute_intermediate_wm = vlv_compute_intermediate_wm,
+   .compute_watermarks = vlv_compute_watermarks,
.initial_watermarks = vlv_initial_watermarks,
.optimize_watermarks = vlv_optimize_watermarks,
.atomic_update_watermarks = vlv_atomic_update_fifo,
@@ -4003,8 +4049,7 @@ static const struct intel_wm_funcs vlv_wm_funcs = {
 };
 
 static const struct intel_wm_funcs g4x_wm_funcs = {
-   .compute_pipe_wm = g4x_compute_pipe_wm,
-   .compute_intermediate_wm = g4x_compute_intermediate_wm,
+   .compute_watermarks = g4x_compute_watermarks,
.initial_watermarks = g4x_initial_watermarks,
.optimize_watermarks = g4x_optimize_watermarks,
.get_hw_state = g4x_wm_get_hw_state_and_sanitize,
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index d4a371edfcdd..60866316fc68 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4292,22 +4292,11 @@ static int intel_crtc_atomic_check(struct 
intel_atomic_state *state,
if (ret)
return ret;
 
-   ret = intel_compute_pipe_wm(state, crtc);
+   ret = intel_wm_compute(state, crtc);
if (ret) {
drm_dbg_kms(&dev_priv->drm,
-   "Target pipe watermarks are invalid\n");
-   return ret;
-   }
-
-   /*
-* Calculate 'intermediate' watermarks that satisfy both the
-* old state and the new state.  We can program these
-* immediately.
-*/
-   ret = intel_compute_intermediate_wm(state, crtc);
-   if (ret) {
-   drm_dbg_kms(&dev_priv->drm,
-   "No valid intermediate pipe watermarks are 
possible\n");
+   "[CRTC:%d:%s] watermarks are invalid\n",
+

[PATCH 0/7] drm/i915: Some wm/cxsr cleanups

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

Start sorting out the pre-skl wm/cxsr code a bit. My plan is:
- move platform specific stuff out from intel_atomic_plane.c
- make cxsr actually robust (currently it has a bunch of poorly
  handled corner cases)
- probably some other fixes and cleanups

This series doesn't achieve those goals yet, because
I decided to limit it to non-functional changes, but
it's a start.

Also included the sprite uapi header cleanup here
to save ci a bit of grief.

Ville Syrjälä (7):
  drm/i915: Remove leftover intel_sprite_set_colorkey_ioctl() prototype
  drm/i915: Combine .compute_{pipe,intermediate}_wm() into one
  drm/i915: Extract ilk_must_disable_lp_wm()
  drm/i915: Clean up intel_wm_need_update()
  drm/i915: Move the dodgy pre-g4x wm stuff into i9xx_wm
  drm/i915: s/disable_lp_wm/disable_cxsr/
  drm/i915: Rename variables in ilk_intermedidate_wm()

 drivers/gpu/drm/i915/display/i9xx_wm.c| 168 +++---
 drivers/gpu/drm/i915/display/i9xx_wm.h|   4 +-
 drivers/gpu/drm/i915/display/intel_atomic.c   |   1 -
 .../gpu/drm/i915/display/intel_atomic_plane.c | 133 ++
 drivers/gpu/drm/i915/display/intel_display.c  |  21 +--
 .../gpu/drm/i915/display/intel_display_core.h |   6 +-
 .../drm/i915/display/intel_display_types.h|   3 -
 drivers/gpu/drm/i915/display/intel_sprite.h   |   3 -
 drivers/gpu/drm/i915/display/intel_wm.c   |  24 +--
 drivers/gpu/drm/i915/display/intel_wm.h   |   6 +-
 drivers/gpu/drm/i915/i915_driver.c|   2 +-
 11 files changed, 221 insertions(+), 150 deletions(-)

-- 
2.44.2



[PATCH 2/2] drm/i915: Extract intel_post_plane_update_after_readout()

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

Clean up the main commit_tail() codepath a bit by pulling
the post plane update steps that need to performed after
readout into their own little function
(intel_post_plane_update_after_readout()).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c | 25 +---
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 591fe3b4ace8..5776f9514346 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1117,6 +1117,22 @@ static void intel_post_plane_update(struct 
intel_atomic_state *state,
intel_encoders_audio_enable(state, crtc);
 }
 
+static void intel_post_plane_update_after_readout(struct intel_atomic_state 
*state,
+ struct intel_crtc *crtc)
+{
+   const struct intel_crtc_state *new_crtc_state =
+   intel_atomic_get_new_crtc_state(state, crtc);
+
+   /* Must be done after gamma readout due to HSW split gamma vs. IPS w/a 
*/
+   hsw_ips_post_update(state, crtc);
+
+   /*
+* Activate DRRS after state readout to avoid
+* dp_m_n vs. dp_m2_n2 confusion on BDW+.
+*/
+   intel_drrs_activate(new_crtc_state);
+}
+
 static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
struct intel_crtc *crtc)
 {
@@ -7479,14 +7495,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
 
intel_modeset_verify_crtc(state, crtc);
 
-   /* Must be done after gamma readout due to HSW split gamma vs. 
IPS w/a */
-   hsw_ips_post_update(state, crtc);
-
-   /*
-* Activate DRRS after state readout to avoid
-* dp_m_n vs. dp_m2_n2 confusion on BDW+.
-*/
-   intel_drrs_activate(new_crtc_state);
+   intel_post_plane_update_after_readout(state, crtc);
 
/*
 * DSB cleanup is done in cleanup_work aligning with framebuffer
-- 
2.44.2



[PATCH 1/2] drm/i915/color: Extract intel_color_modeset()

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

We always perform the same steps to program color management
stuff during a full modeset. Extract that code to a helper
to avoid duplication.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_color.c   | 17 ++
 drivers/gpu/drm/i915/display/intel_color.h   |  1 +
 drivers/gpu/drm/i915/display/intel_display.c | 33 +++-
 3 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_color.c 
b/drivers/gpu/drm/i915/display/intel_color.c
index 5d701f48351b..50f41aeb3c28 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -1902,6 +1902,23 @@ void intel_color_post_update(const struct 
intel_crtc_state *crtc_state)
i915->display.funcs.color->color_post_update(crtc_state);
 }
 
+void intel_color_modeset(const struct intel_crtc_state *crtc_state)
+{
+   struct intel_display *display = to_intel_display(crtc_state);
+
+   intel_color_load_luts(crtc_state);
+   intel_color_commit_noarm(crtc_state);
+   intel_color_commit_arm(crtc_state);
+
+   if (DISPLAY_VER(display) < 9) {
+   struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+   struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+
+   /* update DSPCNTR to configure gamma/csc for pipe bottom color 
*/
+   plane->disable_arm(plane, crtc_state);
+   }
+}
+
 void intel_color_prepare_commit(struct intel_atomic_state *state,
struct intel_crtc *crtc)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_color.h 
b/drivers/gpu/drm/i915/display/intel_color.h
index 79f230a1709a..ab3aaec06a2a 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -28,6 +28,7 @@ void intel_color_commit_noarm(const struct intel_crtc_state 
*crtc_state);
 void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
 void intel_color_post_update(const struct intel_crtc_state *crtc_state);
 void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
+void intel_color_modeset(const struct intel_crtc_state *crtc_state);
 void intel_color_get_config(struct intel_crtc_state *crtc_state);
 bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
   const struct drm_property_blob *blob1,
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index d4a371edfcdd..591fe3b4ace8 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1503,14 +1503,6 @@ static void intel_encoders_update_pipe(struct 
intel_atomic_state *state,
}
 }
 
-static void intel_disable_primary_plane(const struct intel_crtc_state 
*crtc_state)
-{
-   struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-   struct intel_plane *plane = to_intel_plane(crtc->base.primary);
-
-   plane->disable_arm(plane, crtc_state);
-}
-
 static void ilk_configure_cpu_transcoder(const struct intel_crtc_state 
*crtc_state)
 {
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -1576,11 +1568,7 @@ static void ilk_crtc_enable(struct intel_atomic_state 
*state,
 * On ILK+ LUT must be loaded before the pipe is running but with
 * clocks enabled
 */
-   intel_color_load_luts(new_crtc_state);
-   intel_color_commit_noarm(new_crtc_state);
-   intel_color_commit_arm(new_crtc_state);
-   /* update DSPCNTR to configure gamma for pipe bottom color */
-   intel_disable_primary_plane(new_crtc_state);
+   intel_color_modeset(new_crtc_state);
 
intel_initial_watermarks(state, crtc);
intel_enable_transcoder(new_crtc_state);
@@ -1743,12 +1731,7 @@ static void hsw_crtc_enable(struct intel_atomic_state 
*state,
 * On ILK+ LUT must be loaded before the pipe is running but 
with
 * clocks enabled
 */
-   intel_color_load_luts(pipe_crtc_state);
-   intel_color_commit_noarm(pipe_crtc_state);
-   intel_color_commit_arm(pipe_crtc_state);
-   /* update DSPCNTR to configure gamma/csc for pipe bottom color 
*/
-   if (DISPLAY_VER(dev_priv) < 9)
-   intel_disable_primary_plane(pipe_crtc_state);
+   intel_color_modeset(pipe_crtc_state);
 
hsw_set_linetime_wm(pipe_crtc_state);
 
@@ -2150,11 +2133,7 @@ static void valleyview_crtc_enable(struct 
intel_atomic_state *state,
 
i9xx_pfit_enable(new_crtc_state);
 
-   intel_color_load_luts(new_crtc_state);
-   intel_color_commit_noarm(new_crtc_state);
-   intel_color_commit_arm(new_crtc_state);
-   /* update DSPCNTR to configure gamma for pipe bottom color */
-   intel_disable_primary_plane(new_crtc_state);
+   intel_color_modeset(

[PATCH 0/2] drm/i915: Some modeset refactoring

2024-09-16 Thread Ville Syrjala
From: Ville Syrjälä 

Clean up the modeset code a bit by extracting some functions.

Ville Syrjälä (2):
  drm/i915/color: Extract intel_color_modeset()
  drm/i915: Extract intel_post_plane_update_after_readout()

 drivers/gpu/drm/i915/display/intel_color.c   | 17 ++
 drivers/gpu/drm/i915/display/intel_color.h   |  1 +
 drivers/gpu/drm/i915/display/intel_display.c | 58 +++-
 3 files changed, 39 insertions(+), 37 deletions(-)

-- 
2.44.2



[PATCH] drm/i915/psr: Fix PSR sink enable sequence

2024-09-11 Thread Ville Syrjala
From: Ville Syrjälä 

According to the eDP spec, the source must first configure all
PSR related DPCD registers apart from the actual enable bit,
and only then set the enable bit. Split the current single DPCD
write to two to match the spec.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 1a4ef231a53c..2b7c0c73f335 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -745,7 +745,7 @@ static void _psr_enable_sink(struct intel_dp *intel_dp,
 const struct intel_crtc_state *crtc_state)
 {
struct intel_display *display = to_intel_display(intel_dp);
-   u8 val = DP_PSR_ENABLE;
+   u8 val = 0;
 
if (crtc_state->has_sel_update) {
val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS;
@@ -765,7 +765,9 @@ static void _psr_enable_sink(struct intel_dp *intel_dp,
 
if (intel_dp->psr.entry_setup_frames > 0)
val |= DP_PSR_FRAME_CAPTURE;
+   drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val);
 
+   val |= DP_PSR_ENABLE;
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val);
 }
 
-- 
2.44.2



[PATCH 3/5] drm/i915/bios: Extract intel_spi_read16()

2024-09-10 Thread Ville Syrjala
From: Ville Syrjälä 

The SPI VBT codepath only knows how to read 4 bytes at a time.
So to read the 2 byte vbt_size it masks out the unwanted msbs.
Hide that little implementation detail inside a new intel_spi_read16()
helper. Alse rename the existing intel_spi_read() to intel_spi_read32()
to make it clear what it does.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index cc4a4cc2bf3e..cbbda94c3dab 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -3053,13 +3053,18 @@ static struct vbt_header *firmware_get_vbt(struct 
intel_display *display,
return vbt;
 }
 
-static u32 intel_spi_read(struct intel_uncore *uncore, u32 offset)
+static u32 intel_spi_read32(struct intel_uncore *uncore, u32 offset)
 {
intel_uncore_write(uncore, PRIMARY_SPI_ADDRESS, offset);
 
return intel_uncore_read(uncore, PRIMARY_SPI_TRIGGER);
 }
 
+static u16 intel_spi_read16(struct intel_uncore *uncore, u32 offset)
+{
+   return intel_spi_read32(uncore, offset) & 0x;
+}
+
 static struct vbt_header *spi_oprom_get_vbt(struct intel_display *display,
size_t *size)
 {
@@ -3078,7 +3083,7 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
oprom_offset &= OROM_OFFSET_MASK;
 
for (count = 0; count < oprom_size; count += 4) {
-   data = intel_spi_read(&i915->uncore, oprom_offset + count);
+   data = intel_spi_read32(&i915->uncore, oprom_offset + count);
if (data == *((const u32 *)"$VBT")) {
found = oprom_offset + count;
break;
@@ -3094,9 +3099,8 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
}
 
/* Get VBT size and allocate space for the VBT */
-   vbt_size = intel_spi_read(&i915->uncore,
- found + offsetof(struct vbt_header, 
vbt_size));
-   vbt_size &= 0x;
+   vbt_size = intel_spi_read16(&i915->uncore,
+   found + offsetof(struct vbt_header, 
vbt_size));
 
if (vbt_size > oprom_size - count) {
drm_dbg(display->drm,
@@ -3109,7 +3113,7 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
goto err_not_found;
 
for (count = 0; count < vbt_size; count += 4)
-   *(vbt + store++) = intel_spi_read(&i915->uncore, found + count);
+   *(vbt + store++) = intel_spi_read32(&i915->uncore, found + 
count);
 
if (!intel_bios_is_valid_vbt(display, vbt, vbt_size))
goto err_free_vbt;
-- 
2.44.2



[PATCH 5/5] drm/i915/bios: Extract soc/intel_rom.c

2024-09-10 Thread Ville Syrjala
From: Ville Syrjälä 

Abstract away the nuts and bolts of the SPI vs. PCI ROM
stuff, and hide it all in soc/intel_rom.c so that the
VBT code doesn't have to care about this stuff.

This leaves intel_bios.c with a single codepath that
can focus on the details related to the VBT layout.

This should have no functional changes.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/Makefile |   3 +-
 drivers/gpu/drm/i915/display/intel_bios.c | 150 
 drivers/gpu/drm/i915/soc/intel_rom.c  | 160 ++
 drivers/gpu/drm/i915/soc/intel_rom.h  |  25 +++
 drivers/gpu/drm/xe/Makefile   |   3 +-
 .../xe/compat-i915-headers/soc/intel_rom.h|   6 +
 6 files changed, 224 insertions(+), 123 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/soc/intel_rom.c
 create mode 100644 drivers/gpu/drm/i915/soc/intel_rom.h
 create mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index c63fa2133ccb..d14c8870aecb 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -51,7 +51,8 @@ i915-y += \
 i915-y += \
soc/intel_dram.o \
soc/intel_gmch.o \
-   soc/intel_pch.o
+   soc/intel_pch.o \
+   soc/intel_rom.o
 
 # core library code
 i915-y += \
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index 0b92b494117f..37d4b4ddfa95 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -33,12 +33,12 @@
 #include 
 #include 
 
+#include "soc/intel_rom.h"
+
 #include "i915_drv.h"
-#include "i915_reg.h"
 #include "intel_display.h"
 #include "intel_display_types.h"
 #include "intel_gmbus.h"
-#include "intel_uncore.h"
 
 #define _INTEL_BIOS_PRIVATE
 #include "intel_vbt_defs.h"
@@ -3055,150 +3055,58 @@ static struct vbt_header *firmware_get_vbt(struct 
intel_display *display,
return vbt;
 }
 
-static u32 intel_spi_read32(struct intel_uncore *uncore, u32 offset)
+static struct vbt_header *oprom_get_vbt(struct intel_display *display,
+   struct intel_rom *rom,
+   size_t *size, const char *type)
 {
-   intel_uncore_write(uncore, PRIMARY_SPI_ADDRESS, offset);
+   struct vbt_header *vbt;
+   size_t vbt_size;
+   loff_t offset;
 
-   return intel_uncore_read(uncore, PRIMARY_SPI_TRIGGER);
-}
-
-static u16 intel_spi_read16(struct intel_uncore *uncore, u32 offset)
-{
-   return intel_spi_read32(uncore, offset) & 0x;
-}
-
-static struct vbt_header *spi_oprom_get_vbt(struct intel_display *display,
-   size_t *size)
-{
-   struct drm_i915_private *i915 = to_i915(display->drm);
-   u32 count, data, found, store = 0;
-   u32 static_region, oprom_offset;
-   u32 oprom_size = 0x20;
-   u16 vbt_size;
-   u32 *vbt;
-
-   static_region = intel_uncore_read(&i915->uncore, SPI_STATIC_REGIONS);
-   static_region &= OPTIONROM_SPI_REGIONID_MASK;
-   intel_uncore_write(&i915->uncore, PRIMARY_SPI_REGIONID, static_region);
-
-   oprom_offset = intel_uncore_read(&i915->uncore, OROM_OFFSET);
-   oprom_offset &= OROM_OFFSET_MASK;
+   if (!rom)
+   return NULL;
 
BUILD_BUG_ON(sizeof(vbt_signature) != sizeof(u32));
 
-   for (count = 0; count < oprom_size; count += 4) {
-   data = intel_spi_read32(&i915->uncore, oprom_offset + count);
-   if (data == *((const u32 *)vbt_signature)) {
-   found = oprom_offset + count;
-   break;
-   }
-   }
+   offset = intel_rom_find(rom, *(const u32 *)vbt_signature);
+   if (offset < 0)
+   goto err_free_rom;
 
-   if (count >= oprom_size)
-   goto err_not_found;
-
-   if (sizeof(struct vbt_header) > oprom_size - count) {
+   if (sizeof(struct vbt_header) > intel_rom_size(rom) - offset) {
drm_dbg(display->drm, "VBT header incomplete\n");
-   goto err_not_found;
+   goto err_free_rom;
}
 
-   /* Get VBT size and allocate space for the VBT */
-   vbt_size = intel_spi_read16(&i915->uncore,
-   found + offsetof(struct vbt_header, 
vbt_size));
+   BUILD_BUG_ON(sizeof(vbt->vbt_size) != sizeof(u16));
 
-   if (vbt_size > oprom_size - count) {
-   drm_dbg(display->drm,
-   "VBT incomplete (vbt_size overflows)\n");
-   goto err_not_found;
+   vbt_size = intel_rom_read16(rom, offset + offsetof(struct vbt_header, 
vbt_size));
+   if (vbt_size > intel_rom_size(rom) - offset) {
+   drm_dbg(display->drm, "VBT incomplete (vbt_size overflows)\n");
+   goto err_free_rom;
}
 
vbt = kzalloc(round_up(vbt_size, 4

[PATCH 4/5] drm/i915/bios: Extract vbt_signature[]

2024-09-10 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the three hand rolled "$VBT"s with a vbt_signature[]
to avoid accidents.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index cbbda94c3dab..0b92b494117f 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -2964,6 +2964,8 @@ static const struct bdb_header *get_bdb_header(const 
struct vbt_header *vbt)
return _vbt + vbt->bdb_offset;
 }
 
+static const char vbt_signature[4] = "$VBT";
+
 /**
  * intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
  * @display:   display device
@@ -2986,7 +2988,7 @@ bool intel_bios_is_valid_vbt(struct intel_display 
*display,
return false;
}
 
-   if (memcmp(vbt->signature, "$VBT", 4)) {
+   if (memcmp(vbt->signature, vbt_signature, sizeof(vbt_signature))) {
drm_dbg_kms(display->drm, "VBT invalid signature\n");
return false;
}
@@ -3082,9 +3084,11 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
oprom_offset = intel_uncore_read(&i915->uncore, OROM_OFFSET);
oprom_offset &= OROM_OFFSET_MASK;
 
+   BUILD_BUG_ON(sizeof(vbt_signature) != sizeof(u32));
+
for (count = 0; count < oprom_size; count += 4) {
data = intel_spi_read32(&i915->uncore, oprom_offset + count);
-   if (data == *((const u32 *)"$VBT")) {
+   if (data == *((const u32 *)vbt_signature)) {
found = oprom_offset + count;
break;
}
@@ -3144,9 +3148,11 @@ static struct vbt_header *oprom_get_vbt(struct 
intel_display *display,
if (!oprom)
return NULL;
 
+   BUILD_BUG_ON(sizeof(vbt_signature) != sizeof(u32));
+
/* Scour memory looking for the VBT signature. */
for (i = 0; i + 4 < size; i += 4) {
-   if (ioread32(oprom + i) != *((const u32 *)"$VBT"))
+   if (ioread32(oprom + i) != *((const u32 *)vbt_signature))
continue;
 
p = oprom + i;
-- 
2.44.2



[PATCH 2/5] drm/i915/bios: Round PCI ROM VBT allocation to multiple of 4

2024-09-10 Thread Ville Syrjala
From: Ville Syrjälä 

The SPI code rounds the VBT allocation to a multiple of four bytes
(presumably because it reads the VBT 4 bytes at a time). Do the
same for the PCI ROM side to eliminate pointless differences between
the two codepaths. This will make no functional difference.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index 86b81fd23f58..cc4a4cc2bf3e 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -3166,7 +3166,7 @@ static struct vbt_header *oprom_get_vbt(struct 
intel_display *display,
}
 
/* The rest will be validated by intel_bios_is_valid_vbt() */
-   vbt = kmalloc(vbt_size, GFP_KERNEL);
+   vbt = kmalloc(round_up(vbt_size, 4), GFP_KERNEL);
if (!vbt)
goto err_unmap_oprom;
 
-- 
2.44.2



[PATCH 1/5] drm/i915/bios: Add some size checks to SPI VBT read

2024-09-10 Thread Ville Syrjala
From: Ville Syrjälä 

Unify the SPI vs. PCI ROM VBT read codepaths a bit by
pulling some size overflow checks from the PCI side
into the SPI side.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_bios.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index cd32c9cd38a9..86b81fd23f58 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -3088,11 +3088,22 @@ static struct vbt_header *spi_oprom_get_vbt(struct 
intel_display *display,
if (count >= oprom_size)
goto err_not_found;
 
+   if (sizeof(struct vbt_header) > oprom_size - count) {
+   drm_dbg(display->drm, "VBT header incomplete\n");
+   goto err_not_found;
+   }
+
/* Get VBT size and allocate space for the VBT */
vbt_size = intel_spi_read(&i915->uncore,
  found + offsetof(struct vbt_header, 
vbt_size));
vbt_size &= 0x;
 
+   if (vbt_size > oprom_size - count) {
+   drm_dbg(display->drm,
+   "VBT incomplete (vbt_size overflows)\n");
+   goto err_not_found;
+   }
+
vbt = kzalloc(round_up(vbt_size, 4), GFP_KERNEL);
if (!vbt)
goto err_not_found;
-- 
2.44.2



[PATCH 0/5] drm/i915/bios: Refactor ROM access

2024-09-10 Thread Ville Syrjala
From: Ville Syrjälä 

Unify the behaviour of the PCI ROM vs. SPI flash VBT
read codepaths, and relocate out the low level nuts details
from intel_bios.c into a new soc/intel_rom.c file.

Ville Syrjälä (5):
  drm/i915/bios: Add some size checks to SPI VBT read
  drm/i915/bios: Round PCI ROM VBT allocation to multiple of 4
  drm/i915/bios: Extract intel_spi_read16()
  drm/i915/bios: Extract vbt_signature[]
  drm/i915/bios: Extract soc/intel_rom.c

 drivers/gpu/drm/i915/Makefile |   3 +-
 drivers/gpu/drm/i915/display/intel_bios.c | 141 ---
 drivers/gpu/drm/i915/soc/intel_rom.c  | 160 ++
 drivers/gpu/drm/i915/soc/intel_rom.h  |  25 +++
 drivers/gpu/drm/xe/Makefile   |   3 +-
 .../xe/compat-i915-headers/soc/intel_rom.h|   6 +
 6 files changed, 230 insertions(+), 108 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/soc/intel_rom.c
 create mode 100644 drivers/gpu/drm/i915/soc/intel_rom.h
 create mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h

-- 
2.44.2



[PATCH 6/6] drm/i915/dmc: Convert DMC code to intel_display

2024-09-06 Thread Ville Syrjala
From: Ville Syrjälä 

struct intel_display will replace struct drm_i915_private as
the main thing for display code. Convert the DMC code to
use it (as much as possible at this stage).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c  |   7 +-
 .../drm/i915/display/intel_display_debugfs.c  |   2 +-
 .../drm/i915/display/intel_display_driver.c   |   6 +-
 .../drm/i915/display/intel_display_power.c|  17 +-
 .../i915/display/intel_display_power_well.c   |   8 +-
 drivers/gpu/drm/i915/display/intel_dmc.c  | 391 +-
 drivers/gpu/drm/i915/display/intel_dmc.h  |  26 +-
 drivers/gpu/drm/i915/display/intel_dmc_wl.c   |   4 +-
 .../drm/i915/display/intel_modeset_setup.c|   3 +-
 drivers/gpu/drm/i915/i915_driver.c|   6 +-
 drivers/gpu/drm/i915/i915_gpu_error.c |   2 +-
 drivers/gpu/drm/xe/display/xe_display.c   |   4 +-
 12 files changed, 243 insertions(+), 233 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 0ec78b06ca80..fdf244a32b24 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1690,7 +1690,7 @@ static void hsw_crtc_enable(struct intel_atomic_state 
*state,
 
for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
 
intel_crtc_joined_pipe_mask(new_crtc_state))
-   intel_dmc_enable_pipe(dev_priv, pipe_crtc->pipe);
+   intel_dmc_enable_pipe(display, pipe_crtc->pipe);
 
intel_encoders_pre_pll_enable(state, crtc);
 
@@ -1843,9 +1843,10 @@ static void ilk_crtc_disable(struct intel_atomic_state 
*state,
 static void hsw_crtc_disable(struct intel_atomic_state *state,
 struct intel_crtc *crtc)
 {
+   struct intel_display *display = to_intel_display(state);
+   struct drm_i915_private *i915 = to_i915(display->drm);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
-   struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_crtc *pipe_crtc;
 
/*
@@ -1867,7 +1868,7 @@ static void hsw_crtc_disable(struct intel_atomic_state 
*state,
 
for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc,
 
intel_crtc_joined_pipe_mask(old_crtc_state))
-   intel_dmc_disable_pipe(i915, pipe_crtc->pipe);
+   intel_dmc_disable_pipe(display, pipe_crtc->pipe);
 }
 
 static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index c1bef34d1ffd..b75361e95e97 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -1069,7 +1069,7 @@ void intel_display_debugfs_register(struct 
drm_i915_private *i915)
 
intel_bios_debugfs_register(display);
intel_cdclk_debugfs_register(display);
-   intel_dmc_debugfs_register(i915);
+   intel_dmc_debugfs_register(display);
intel_fbc_debugfs_register(display);
intel_hpd_debugfs_register(i915);
intel_opregion_debugfs_register(display);
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c 
b/drivers/gpu/drm/i915/display/intel_display_driver.c
index f8da72af2107..c106fb2dd20b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -237,7 +237,7 @@ int intel_display_driver_probe_noirq(struct 
drm_i915_private *i915)
if (!HAS_DISPLAY(i915))
return 0;
 
-   intel_dmc_init(i915);
+   intel_dmc_init(display);
 
i915->display.wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
i915->display.wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
@@ -272,7 +272,7 @@ int intel_display_driver_probe_noirq(struct 
drm_i915_private *i915)
return 0;
 
 cleanup_vga_client_pw_domain_dmc:
-   intel_dmc_fini(i915);
+   intel_dmc_fini(display);
intel_power_domains_driver_remove(i915);
 cleanup_vga:
intel_vga_unregister(display);
@@ -621,7 +621,7 @@ void intel_display_driver_remove_nogem(struct 
drm_i915_private *i915)
 {
struct intel_display *display = &i915->display;
 
-   intel_dmc_fini(i915);
+   intel_dmc_fini(display);
 
intel_power_domains_driver_remove(i915);
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c 
b/drivers/gpu/drm/i915/display/intel_display_power.c
index 86ac494ed33b..ecabb674644b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -1445,7 +1445,7 @@ static void skl_display_core_init(struct drm_i915_private 
*dev_priv,
gen9_dbuf_enable(dev_priv);
 
if (resu

[PATCH 5/6] drm/i915/power: Convert "i830 power well" code to intel_display

2024-09-06 Thread Ville Syrjala
From: Ville Syrjälä 

struct intel_display will replace struct drm_i915_private as
the main thing for display code. Convert the "i830 power well"
code to use it (as much as possible at this stage).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c  | 79 +--
 drivers/gpu/drm/i915/display/intel_display.h  |  5 +-
 .../i915/display/intel_display_power_well.c   | 22 --
 3 files changed, 56 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index b4ec9bf12aa7..0ec78b06ca80 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2226,9 +2226,10 @@ static void i9xx_pfit_disable(const struct 
intel_crtc_state *old_crtc_state)
 static void i9xx_crtc_disable(struct intel_atomic_state *state,
  struct intel_crtc *crtc)
 {
+   struct intel_display *display = to_intel_display(state);
+   struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
-   struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
 
/*
@@ -2267,7 +2268,7 @@ static void i9xx_crtc_disable(struct intel_atomic_state 
*state,
 
/* clock the pipe down to 640x480@60 to potentially save power */
if (IS_I830(dev_priv))
-   i830_enable_pipe(dev_priv, pipe);
+   i830_enable_pipe(display, pipe);
 }
 
 void intel_encoder_destroy(struct drm_encoder *encoder)
@@ -8257,9 +8258,8 @@ int intel_initial_commit(struct drm_device *dev)
return ret;
 }
 
-void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
+void i830_enable_pipe(struct intel_display *display, enum pipe pipe)
 {
-   struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
enum transcoder cpu_transcoder = (enum transcoder)pipe;
/* 640x480@60Hz, ~25175 kHz */
@@ -8273,10 +8273,10 @@ void i830_enable_pipe(struct drm_i915_private 
*dev_priv, enum pipe pipe)
u32 dpll, fp;
int i;
 
-   drm_WARN_ON(&dev_priv->drm,
+   drm_WARN_ON(display->drm,
i9xx_calc_dpll_params(48000, &clock) != 25154);
 
-   drm_dbg_kms(&dev_priv->drm,
+   drm_dbg_kms(display->drm,
"enabling pipe %c due to force quirk (vco=%d dot=%d)\n",
pipe_name(pipe), clock.vco, clock.dot);
 
@@ -8288,35 +8288,35 @@ void i830_enable_pipe(struct drm_i915_private 
*dev_priv, enum pipe pipe)
PLL_REF_INPUT_DREFCLK |
DPLL_VCO_ENABLE;
 
-   intel_de_write(dev_priv, TRANS_HTOTAL(dev_priv, cpu_transcoder),
+   intel_de_write(display, TRANS_HTOTAL(display, cpu_transcoder),
   HACTIVE(640 - 1) | HTOTAL(800 - 1));
-   intel_de_write(dev_priv, TRANS_HBLANK(dev_priv, cpu_transcoder),
+   intel_de_write(display, TRANS_HBLANK(display, cpu_transcoder),
   HBLANK_START(640 - 1) | HBLANK_END(800 - 1));
-   intel_de_write(dev_priv, TRANS_HSYNC(dev_priv, cpu_transcoder),
+   intel_de_write(display, TRANS_HSYNC(display, cpu_transcoder),
   HSYNC_START(656 - 1) | HSYNC_END(752 - 1));
-   intel_de_write(dev_priv, TRANS_VTOTAL(dev_priv, cpu_transcoder),
+   intel_de_write(display, TRANS_VTOTAL(display, cpu_transcoder),
   VACTIVE(480 - 1) | VTOTAL(525 - 1));
-   intel_de_write(dev_priv, TRANS_VBLANK(dev_priv, cpu_transcoder),
+   intel_de_write(display, TRANS_VBLANK(display, cpu_transcoder),
   VBLANK_START(480 - 1) | VBLANK_END(525 - 1));
-   intel_de_write(dev_priv, TRANS_VSYNC(dev_priv, cpu_transcoder),
+   intel_de_write(display, TRANS_VSYNC(display, cpu_transcoder),
   VSYNC_START(490 - 1) | VSYNC_END(492 - 1));
-   intel_de_write(dev_priv, PIPESRC(dev_priv, pipe),
+   intel_de_write(display, PIPESRC(display, pipe),
   PIPESRC_WIDTH(640 - 1) | PIPESRC_HEIGHT(480 - 1));
 
-   intel_de_write(dev_priv, FP0(pipe), fp);
-   intel_de_write(dev_priv, FP1(pipe), fp);
+   intel_de_write(display, FP0(pipe), fp);
+   intel_de_write(display, FP1(pipe), fp);
 
/*
 * Apparently we need to have VGA mode enabled prior to changing
 * the P1/P2 dividers. Otherwise the DPLL will keep using the old
 * dividers, even though the register value does change.
 */
-   intel_de_write(dev_priv, DPLL(dev_priv, pipe),
+   intel_de_write(display, DPLL(display, pipe),
   dpll & ~DPLL_VGA_MODE_DIS);
-   intel_de_write(dev_priv, DPLL(dev_priv, pipe), dpll);
+   intel_de_write(display, DPLL(display, pipe), dpll);
 
/* Wait for the clocks to stabilize. *

[PATCH 4/6] drm/i915/vga: Convert VGA code to intel_display

2024-09-06 Thread Ville Syrjala
From: Ville Syrjälä 

struct intel_display will replace struct drm_i915_private as
the main thing for display code. Convert the VGA code to
use it (as much as possible at this stage).

Signed-off-by: Ville Syrjälä 
---
 .../drm/i915/display/intel_display_driver.c   | 11 ++---
 .../i915/display/intel_display_power_well.c   |  6 ++-
 drivers/gpu/drm/i915/display/intel_vga.c  | 45 ++-
 drivers/gpu/drm/i915/display/intel_vga.h  | 14 +++---
 drivers/gpu/drm/i915/i915_suspend.c   |  3 +-
 5 files changed, 43 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c 
b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 434e52f450ff..f8da72af2107 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -221,7 +221,7 @@ int intel_display_driver_probe_noirq(struct 
drm_i915_private *i915)
 
intel_bios_init(display);
 
-   ret = intel_vga_register(i915);
+   ret = intel_vga_register(display);
if (ret)
goto cleanup_bios;
 
@@ -275,7 +275,7 @@ int intel_display_driver_probe_noirq(struct 
drm_i915_private *i915)
intel_dmc_fini(i915);
intel_power_domains_driver_remove(i915);
 cleanup_vga:
-   intel_vga_unregister(i915);
+   intel_vga_unregister(display);
 cleanup_bios:
intel_bios_driver_remove(display);
 
@@ -458,7 +458,7 @@ int intel_display_driver_probe_nogem(struct 
drm_i915_private *i915)
intel_hti_init(display);
 
/* Just disable it once at startup */
-   intel_vga_disable(i915);
+   intel_vga_disable(display);
intel_setup_outputs(i915);
 
ret = intel_dp_tunnel_mgr_init(display);
@@ -625,7 +625,7 @@ void intel_display_driver_remove_nogem(struct 
drm_i915_private *i915)
 
intel_power_domains_driver_remove(i915);
 
-   intel_vga_unregister(i915);
+   intel_vga_unregister(display);
 
intel_bios_driver_remove(display);
 }
@@ -683,12 +683,13 @@ __intel_display_driver_resume(struct drm_i915_private 
*i915,
  struct drm_atomic_state *state,
  struct drm_modeset_acquire_ctx *ctx)
 {
+   struct intel_display *display = &i915->display;
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
int ret, i;
 
intel_modeset_setup_hw_state(i915, ctx);
-   intel_vga_redisable(i915);
+   intel_vga_redisable(display);
 
if (!state)
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c 
b/drivers/gpu/drm/i915/display/intel_display_power_well.c
index 1f0084ca6248..a5d9b17e03a2 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -187,8 +187,10 @@ int intel_power_well_refcount(struct i915_power_well 
*power_well)
 static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv,
   u8 irq_pipe_mask, bool has_vga)
 {
+   struct intel_display *display = &dev_priv->display;
+
if (has_vga)
-   intel_vga_reset_io_mem(dev_priv);
+   intel_vga_reset_io_mem(display);
 
if (irq_pipe_mask)
gen8_irq_power_well_post_enable(dev_priv, irq_pipe_mask);
@@ -1248,7 +1250,7 @@ static void vlv_display_power_well_init(struct 
drm_i915_private *dev_priv)
intel_crt_reset(&encoder->base);
}
 
-   intel_vga_redisable_power_on(dev_priv);
+   intel_vga_redisable_power_on(display);
 
intel_pps_unlock_regs_wa(display);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_vga.c 
b/drivers/gpu/drm/i915/display/intel_vga.c
index 0b5916c15307..2c76a0176a35 100644
--- a/drivers/gpu/drm/i915/display/intel_vga.c
+++ b/drivers/gpu/drm/i915/display/intel_vga.c
@@ -14,24 +14,26 @@
 #include "intel_de.h"
 #include "intel_vga.h"
 
-static i915_reg_t intel_vga_cntrl_reg(struct drm_i915_private *i915)
+static i915_reg_t intel_vga_cntrl_reg(struct intel_display *display)
 {
+   struct drm_i915_private *i915 = to_i915(display->drm);
+
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
return VLV_VGACNTRL;
-   else if (DISPLAY_VER(i915) >= 5)
+   else if (DISPLAY_VER(display) >= 5)
return CPU_VGACNTRL;
else
return VGACNTRL;
 }
 
 /* Disable the VGA plane that we never use */
-void intel_vga_disable(struct drm_i915_private *dev_priv)
+void intel_vga_disable(struct intel_display *display)
 {
-   struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
-   i915_reg_t vga_reg = intel_vga_cntrl_reg(dev_priv);
+   struct pci_dev *pdev = to_pci_dev(display->drm->dev);
+   i915_reg_t vga_reg = intel_vga_cntrl_reg(display);
u8 sr1;
 
-   if (intel_de_read(dev_priv, vga_reg) & VGA_DISP_DISABLE)
+   if (intel_de_read(display, vga_reg) & VGA_D

[PATCH 2/6] drm/i915/cdclk: Convert CDCLK code to intel_display

2024-09-06 Thread Ville Syrjala
From: Ville Syrjälä 

struct intel_display will replace struct drm_i915_private as
the main thing for display code. Convert the CDCLK code to
use it (as much as possible at this stage).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_cdclk.c| 1168 +
 drivers/gpu/drm/i915/display/intel_cdclk.h|   24 +-
 .../drm/i915/display/intel_display_debugfs.c  |2 +-
 .../drm/i915/display/intel_display_device.c   |2 +-
 .../drm/i915/display/intel_display_driver.c   |   17 +-
 .../drm/i915/display/intel_display_power.c|   35 +-
 .../i915/display/intel_display_power_well.c   |9 +-
 drivers/gpu/drm/i915/display/skl_watermark.c  |3 +-
 8 files changed, 657 insertions(+), 603 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 9d870d15d888..b4eda0a2a45d 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -113,81 +113,81 @@
  */
 
 struct intel_cdclk_funcs {
-   void (*get_cdclk)(struct drm_i915_private *i915,
+   void (*get_cdclk)(struct intel_display *display,
  struct intel_cdclk_config *cdclk_config);
-   void (*set_cdclk)(struct drm_i915_private *i915,
+   void (*set_cdclk)(struct intel_display *display,
  const struct intel_cdclk_config *cdclk_config,
  enum pipe pipe);
int (*modeset_calc_cdclk)(struct intel_atomic_state *state);
u8 (*calc_voltage_level)(int cdclk);
 };
 
-void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv,
+void intel_cdclk_get_cdclk(struct intel_display *display,
   struct intel_cdclk_config *cdclk_config)
 {
-   dev_priv->display.funcs.cdclk->get_cdclk(dev_priv, cdclk_config);
+   display->funcs.cdclk->get_cdclk(display, cdclk_config);
 }
 
-static void intel_cdclk_set_cdclk(struct drm_i915_private *dev_priv,
+static void intel_cdclk_set_cdclk(struct intel_display *display,
  const struct intel_cdclk_config *cdclk_config,
  enum pipe pipe)
 {
-   dev_priv->display.funcs.cdclk->set_cdclk(dev_priv, cdclk_config, pipe);
+   display->funcs.cdclk->set_cdclk(display, cdclk_config, pipe);
 }
 
 static int intel_cdclk_modeset_calc_cdclk(struct intel_atomic_state *state)
 {
-   struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+   struct intel_display *display = to_intel_display(state);
 
-   return dev_priv->display.funcs.cdclk->modeset_calc_cdclk(state);
+   return display->funcs.cdclk->modeset_calc_cdclk(state);
 }
 
-static u8 intel_cdclk_calc_voltage_level(struct drm_i915_private *dev_priv,
+static u8 intel_cdclk_calc_voltage_level(struct intel_display *display,
 int cdclk)
 {
-   return dev_priv->display.funcs.cdclk->calc_voltage_level(cdclk);
+   return display->funcs.cdclk->calc_voltage_level(cdclk);
 }
 
-static void fixed_133mhz_get_cdclk(struct drm_i915_private *dev_priv,
+static void fixed_133mhz_get_cdclk(struct intel_display *display,
   struct intel_cdclk_config *cdclk_config)
 {
cdclk_config->cdclk = 13;
 }
 
-static void fixed_200mhz_get_cdclk(struct drm_i915_private *dev_priv,
+static void fixed_200mhz_get_cdclk(struct intel_display *display,
   struct intel_cdclk_config *cdclk_config)
 {
cdclk_config->cdclk = 20;
 }
 
-static void fixed_266mhz_get_cdclk(struct drm_i915_private *dev_priv,
+static void fixed_266mhz_get_cdclk(struct intel_display *display,
   struct intel_cdclk_config *cdclk_config)
 {
cdclk_config->cdclk = 27;
 }
 
-static void fixed_333mhz_get_cdclk(struct drm_i915_private *dev_priv,
+static void fixed_333mhz_get_cdclk(struct intel_display *display,
   struct intel_cdclk_config *cdclk_config)
 {
cdclk_config->cdclk = 33;
 }
 
-static void fixed_400mhz_get_cdclk(struct drm_i915_private *dev_priv,
+static void fixed_400mhz_get_cdclk(struct intel_display *display,
   struct intel_cdclk_config *cdclk_config)
 {
cdclk_config->cdclk = 40;
 }
 
-static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv,
+static void fixed_450mhz_get_cdclk(struct intel_display *display,
   struct intel_cdclk_config *cdclk_config)
 {
cdclk_config->cdclk = 45;
 }
 
-static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
+static void i85x_get_cdclk(struct intel_display *display,
   struct intel_cdclk_config *cdclk_config)
 {
-   struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
+   struct pci_dev *pdev = to_pci_dev(display->drm->dev);
u16 hpllcc = 0;
 
/*
@@ -226,10 +226,10 @@ static void i85x_get

[PATCH 3/6] drm/i915/power: Convert low level DC state code to intel_display

2024-09-06 Thread Ville Syrjala
From: Ville Syrjälä 

struct intel_display will replace struct drm_i915_private as
the main thing for display code. Convert the lower level
DC state code to use it (as much as possible at this stage).

Signed-off-by: Ville Syrjälä 
---
 .../drm/i915/display/intel_display_power.c|  41 ++--
 .../i915/display/intel_display_power_well.c   | 199 ++
 .../i915/display/intel_display_power_well.h   |  15 +-
 3 files changed, 139 insertions(+), 116 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c 
b/drivers/gpu/drm/i915/display/intel_display_power.c
index eb3e2a56af1d..86ac494ed33b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -1421,7 +1421,7 @@ static void skl_display_core_init(struct drm_i915_private 
*dev_priv,
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
 
-   gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+   gen9_set_dc_state(display, DC_STATE_DISABLE);
 
/* enable PCH reset handshake */
intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
@@ -1457,7 +1457,7 @@ static void skl_display_core_uninit(struct 
drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
 
-   gen9_disable_dc_states(dev_priv);
+   gen9_disable_dc_states(display);
/* TODO: disable DMC program */
 
gen9_dbuf_disable(dev_priv);
@@ -1489,7 +1489,7 @@ static void bxt_display_core_init(struct drm_i915_private 
*dev_priv, bool resume
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
 
-   gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+   gen9_set_dc_state(display, DC_STATE_DISABLE);
 
/*
 * NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT
@@ -1527,7 +1527,7 @@ static void bxt_display_core_uninit(struct 
drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
 
-   gen9_disable_dc_states(dev_priv);
+   gen9_disable_dc_states(display);
/* TODO: disable DMC program */
 
gen9_dbuf_disable(dev_priv);
@@ -1632,7 +1632,7 @@ static void icl_display_core_init(struct drm_i915_private 
*dev_priv,
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
 
-   gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+   gen9_set_dc_state(display, DC_STATE_DISABLE);
 
/* Wa_14011294188:ehl,jsl,tgl,rkl,adl-s */
if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP &&
@@ -1717,7 +1717,7 @@ static void icl_display_core_uninit(struct 
drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
 
-   gen9_disable_dc_states(dev_priv);
+   gen9_disable_dc_states(display);
intel_dmc_disable_program(dev_priv);
 
/* 1. Disable all display engine functions -> aready done */
@@ -2232,9 +2232,11 @@ static void intel_power_domains_verify_state(struct 
drm_i915_private *i915)
 
 void intel_display_power_suspend_late(struct drm_i915_private *i915)
 {
+   struct intel_display *display = &i915->display;
+
if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||
IS_BROXTON(i915)) {
-   bxt_enable_dc9(i915);
+   bxt_enable_dc9(display);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
hsw_enable_pc8(i915);
}
@@ -2246,10 +2248,12 @@ void intel_display_power_suspend_late(struct 
drm_i915_private *i915)
 
 void intel_display_power_resume_early(struct drm_i915_private *i915)
 {
+   struct intel_display *display = &i915->display;
+
if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||
IS_BROXTON(i915)) {
-   gen9_sanitize_dc_state(i915);
-   bxt_disable_dc9(i915);
+   gen9_sanitize_dc_state(display);
+   bxt_disable_dc9(display);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
hsw_disable_pc8(i915);
}
@@ -2261,12 +2265,14 @@ void intel_display_power_resume_early(struct 
drm_i915_private *i915)
 
 void intel_display_power_suspend(struct drm_i915_private *i915)
 {
+   struct intel_display *display = &i915->display;
+
if (DISPLAY_VER(i915) >= 11) {
icl_display_core_uninit(i915);
-   bxt_enable_dc9(i915);
+   bxt_enable_dc9(display);
} else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
bxt_display_core_uninit(i915);
-   bxt_enable_dc9(i915);
+   bxt_enable_dc9(display);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
hsw_enable_pc8(i915);
}
@@ -2274,23 +2280,24 @@ void intel_display_power_suspend(struct 
drm_i915_private *i915)
 
 void intel_display_power_resume(struct drm_i915_private *i915)
 {
-   struct i915_power_domai

[PATCH 0/6] drm/i915: Some intel_display conversions

2024-09-06 Thread Ville Syrjala
From: Ville Syrjälä 

I somehow ended up in the power domains code and decided
to see how much of it could be converted to use struct
intel_display. The result was still too messy but at least
I managed to convert some of the dependecies in somewhat
decent way. Here they are.

Ville Syrjälä (6):
  drm/i915/cdclk: Add missing braces
  drm/i915/cdclk: Convert CDCLK code to intel_display
  drm/i915/power: Convert low level DC state code to intel_display
  drm/i915/vga: Convert VGA code to intel_display
  drm/i915/power: Convert "i830 power well" code to intel_display
  drm/i915/dmc: Convert DMC code to intel_display

 drivers/gpu/drm/i915/display/intel_cdclk.c| 1171 +
 drivers/gpu/drm/i915/display/intel_cdclk.h|   24 +-
 drivers/gpu/drm/i915/display/intel_display.c  |   86 +-
 drivers/gpu/drm/i915/display/intel_display.h  |5 +-
 .../drm/i915/display/intel_display_debugfs.c  |4 +-
 .../drm/i915/display/intel_display_device.c   |2 +-
 .../drm/i915/display/intel_display_driver.c   |   34 +-
 .../drm/i915/display/intel_display_power.c|   93 +-
 .../i915/display/intel_display_power_well.c   |  238 ++--
 .../i915/display/intel_display_power_well.h   |   15 +-
 drivers/gpu/drm/i915/display/intel_dmc.c  |  391 +++---
 drivers/gpu/drm/i915/display/intel_dmc.h  |   26 +-
 drivers/gpu/drm/i915/display/intel_dmc_wl.c   |4 +-
 .../drm/i915/display/intel_modeset_setup.c|3 +-
 drivers/gpu/drm/i915/display/intel_vga.c  |   45 +-
 drivers/gpu/drm/i915/display/intel_vga.h  |   14 +-
 drivers/gpu/drm/i915/display/skl_watermark.c  |3 +-
 drivers/gpu/drm/i915/i915_driver.c|6 +-
 drivers/gpu/drm/i915/i915_gpu_error.c |2 +-
 drivers/gpu/drm/i915/i915_suspend.c   |3 +-
 drivers/gpu/drm/xe/display/xe_display.c   |4 +-
 21 files changed, 1137 insertions(+), 1036 deletions(-)

-- 
2.44.2



[PATCH 1/6] drm/i915/cdclk: Add missing braces

2024-09-06 Thread Ville Syrjala
From: Ville Syrjälä 

CodingStyle says when one branch of an if ladder is braced
then all of them should be. Make it so.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_cdclk.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
b/drivers/gpu/drm/i915/display/intel_cdclk.c
index 66964c7d2a2c..9d870d15d888 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -2053,8 +2053,9 @@ static void _bxt_set_cdclk(struct drm_i915_private 
*dev_priv,
dg2_cdclk_squash_program(dev_priv, 0);
 
icl_cdclk_pll_update(dev_priv, vco);
-   } else
+   } else {
bxt_cdclk_pll_update(dev_priv, vco);
+   }
 
if (HAS_CDCLK_SQUASH(dev_priv)) {
u16 waveform = cdclk_squash_waveform(dev_priv, cdclk);
-- 
2.44.2



[PATCH 13/13] drm/i915/dsb: Use DSB for plane/color management updates

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Push regular plane/color management updates to the DSB,
if other constraints allow it.

The first part of the sequence will go as follows:
- CPU will kick off DSB0 immediately
- DSB0 writes double bufferd non-arming registers
- DSB0 evades the vblank
- DSB0 writes double buffered arming registers

If no color management updates is needed we follow that up with:
- DSB0 waits for the undelayed vblank
- DSB0 waits for the delayed vblank (usec wait)
- DSB0 emits an interrupt which will cause the CPU to complete the commit

If color management update is needed:
- DSB0 will start DSB1 with wait for undelayed vblank
- DSB0 will in parallel perform the force DEwake tricks
- DSB1 writes single buffered LUT registers
- DSB1 waits for the delayed vblank (usec wait)
- DSB1 emits an interrupt which will cause the CPU to complete the commit

With this sequence we don't need to increase the vblank delay
to make room for register programming during vblank, which is
a good thing for high refresh rate display. But I'll need to
still think of some way to eliminate VRR commit completion
related races under this scheme.

Stuff that isn't ready for DSB yet:
- modesets (potentially we could do
  at least the plane enabling via DSB)
- fastsets
- VRR
- PSR
- scalers
- async flips

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_atomic.c   |   5 +-
 drivers/gpu/drm/i915/display/intel_color.c|  25 +---
 drivers/gpu/drm/i915/display/intel_crtc.c |   5 +-
 drivers/gpu/drm/i915/display/intel_display.c  | 128 --
 .../drm/i915/display/intel_display_types.h|   5 +-
 5 files changed, 128 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index 12d6ed940751..52a055032c68 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -277,7 +277,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->fb_bits = 0;
crtc_state->update_planes = 0;
crtc_state->dsb_color_vblank = NULL;
-   crtc_state->dsb_color_commit = NULL;
+   crtc_state->dsb_commit = NULL;
+   crtc_state->use_dsb = false;
 
return &crtc_state->uapi;
 }
@@ -312,7 +313,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
struct intel_crtc_state *crtc_state = to_intel_crtc_state(state);
 
drm_WARN_ON(crtc->dev, crtc_state->dsb_color_vblank);
-   drm_WARN_ON(crtc->dev, crtc_state->dsb_color_commit);
+   drm_WARN_ON(crtc->dev, crtc_state->dsb_commit);
 
__drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);
intel_crtc_free_hw_state(crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_color.c 
b/drivers/gpu/drm/i915/display/intel_color.c
index 685da9f84b0a..ac4d4f5349a4 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -1913,9 +1913,6 @@ void intel_color_commit_arm(struct intel_dsb *dsb,
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
 
i915->display.funcs.color->color_commit_arm(dsb, crtc_state);
-
-   if (crtc_state->dsb_color_commit)
-   intel_dsb_commit(crtc_state->dsb_color_commit, false);
 }
 
 void intel_color_post_update(const struct intel_crtc_state *crtc_state)
@@ -1949,28 +1946,14 @@ void intel_color_prepare_commit(struct 
intel_atomic_state *state,
 
i915->display.funcs.color->load_luts(crtc_state);
 
+   intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color_vblank);
+   intel_dsb_interrupt(crtc_state->dsb_color_vblank);
+
intel_dsb_finish(crtc_state->dsb_color_vblank);
-
-   crtc_state->dsb_color_commit = intel_dsb_prepare(state, crtc, 
INTEL_DSB_0, 16);
-   if (!crtc_state->dsb_color_commit) {
-   intel_dsb_cleanup(crtc_state->dsb_color_vblank);
-   crtc_state->dsb_color_vblank = NULL;
-   return;
-   }
-
-   intel_dsb_chain(state, crtc_state->dsb_color_commit,
-   crtc_state->dsb_color_vblank, true);
-
-   intel_dsb_finish(crtc_state->dsb_color_commit);
 }
 
 void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
 {
-   if (crtc_state->dsb_color_commit) {
-   intel_dsb_cleanup(crtc_state->dsb_color_commit);
-   crtc_state->dsb_color_commit = NULL;
-   }
-
if (crtc_state->dsb_color_vblank) {
intel_dsb_cleanup(crtc_state->dsb_color_vblank);
crtc_state->dsb_color_vblank = NULL;
@@ -1979,8 +1962,6 @@ void intel_color_cleanup_commit(struct intel_crtc_state 
*crtc_state)
 
 void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
 {
-   if (crtc_state->dsb_color_commit)
-   intel_dsb_wait(crtc_state->dsb_color_commit);
if (crtc_state->dsb_color_vblank)
intel_dsb_wait(crtc_state->dsb_color_vblank);
 }
diff --git a/drivers

[PATCH 12/13] drm/i915: Plumb 'dsb' all way to the color commit hooks

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Pass the 'dsb' all the way down to the color commit hooks so that
we'll be able to update the double buffered color management registers
(eg. CSC) via the DSB.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_color.c| 176 ++
 drivers/gpu/drm/i915/display/intel_color.h|   7 +-
 drivers/gpu/drm/i915/display/intel_display.c  |  20 +-
 .../drm/i915/display/intel_modeset_setup.c|   4 +-
 4 files changed, 117 insertions(+), 90 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_color.c 
b/drivers/gpu/drm/i915/display/intel_color.c
index 5d701f48351b..685da9f84b0a 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -39,7 +39,8 @@ struct intel_color_funcs {
 * the next vblank start, alongside any other double buffered
 * registers involved with the same commit. This hook is optional.
 */
-   void (*color_commit_noarm)(const struct intel_crtc_state *crtc_state);
+   void (*color_commit_noarm)(struct intel_dsb *dsb,
+  const struct intel_crtc_state *crtc_state);
/*
 * Program arming double buffered color management registers
 * during vblank evasion. The registers (and whatever other registers
@@ -47,7 +48,8 @@ struct intel_color_funcs {
 * during the next vblank start, alongside any other double buffered
 * registers involved with the same commit.
 */
-   void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);
+   void (*color_commit_arm)(struct intel_dsb *dsb,
+const struct intel_crtc_state *crtc_state);
/*
 * Perform any extra tasks needed after all the
 * double buffered registers have been latched.
@@ -205,37 +207,44 @@ static u64 *ctm_mult_by_limited(u64 *result, const u64 
*input)
return result;
 }
 
-static void ilk_update_pipe_csc(struct intel_crtc *crtc,
+static void ilk_update_pipe_csc(struct intel_dsb *dsb,
+   struct intel_crtc *crtc,
const struct intel_csc_matrix *csc)
 {
-   struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+   struct intel_display *display = to_intel_display(crtc->base.dev);
enum pipe pipe = crtc->pipe;
 
-   intel_de_write_fw(i915, PIPE_CSC_PREOFF_HI(pipe), csc->preoff[0]);
-   intel_de_write_fw(i915, PIPE_CSC_PREOFF_ME(pipe), csc->preoff[1]);
-   intel_de_write_fw(i915, PIPE_CSC_PREOFF_LO(pipe), csc->preoff[2]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_PREOFF_HI(pipe),
+  csc->preoff[0]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_PREOFF_ME(pipe),
+  csc->preoff[1]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_PREOFF_LO(pipe),
+  csc->preoff[2]);
 
-   intel_de_write_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe),
- csc->coeff[0] << 16 | csc->coeff[1]);
-   intel_de_write_fw(i915, PIPE_CSC_COEFF_BY(pipe),
- csc->coeff[2] << 16);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_RY_GY(pipe),
+  csc->coeff[0] << 16 | csc->coeff[1]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_BY(pipe),
+  csc->coeff[2] << 16);
 
-   intel_de_write_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe),
- csc->coeff[3] << 16 | csc->coeff[4]);
-   intel_de_write_fw(i915, PIPE_CSC_COEFF_BU(pipe),
- csc->coeff[5] << 16);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_RU_GU(pipe),
+  csc->coeff[3] << 16 | csc->coeff[4]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_BU(pipe),
+  csc->coeff[5] << 16);
 
-   intel_de_write_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe),
- csc->coeff[6] << 16 | csc->coeff[7]);
-   intel_de_write_fw(i915, PIPE_CSC_COEFF_BV(pipe),
- csc->coeff[8] << 16);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_RV_GV(pipe),
+  csc->coeff[6] << 16 | csc->coeff[7]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_BV(pipe),
+  csc->coeff[8] << 16);
 
-   if (DISPLAY_VER(i915) < 7)
+   if (DISPLAY_VER(display) < 7)
return;
 
-   intel_de_write_fw(i915, PIPE_CSC_POSTOFF_HI(pipe), csc->postoff[0]);
-   intel_de_write_fw(i915, PIPE_CSC_POSTOFF_ME(pipe), csc->postoff[1]);
-   intel_de_write_fw(i915, PIPE_CSC_POSTOFF_LO(pipe), csc->postoff[2]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_POSTOFF_HI(pipe),
+  csc->postoff[0]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_POSTOFF_ME(pipe),
+  csc->postoff[1]);
+   intel_de_write_dsb(display, dsb, PIPE_CSC_POSTOFF_LO(pi

[PATCH 11/13] drm/i915: Plumb 'dsb' all way to the plane hooks

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

We need to be able to do both MMIO and DSB based pipe/plane
programming. To that end plumb the 'dsb' all way from the top
into the plane commit hooks.

The compiler appears smart enough to combine the branches from
all the back-to-back register writes into a single branch.
So the generated asm ends up looking more or less like this:
plane_hook()
{
if (dsb) {
intel_dsb_reg_write();
intel_dsb_reg_write();
...
} else {
intel_de_write_fw();
intel_de_write_fw();
...
}
}
which seems like a reasonably efficient way to do this.

An alternative I was also considering is some kind of closure
(register write function + display vs. dsb pointer passed to it).
That does result is smaller code as there are no branches anymore,
but having each register access go via function pointer sounds
less efficient.

Not that I actually measured the overhead of either approach yet.
Also the reg_rw tracepoint seems to be making a huge mess of the
generated code for the mmio path. And additionally there's some
kind of IS_GSI_REG() hack in __raw_uncore_read() which ends up
generating a pointless branch for every mmio register access.
So looks like there might be quite a bit of room for improvement
in the mmio path still.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/i9xx_plane.c |  22 +-
 .../gpu/drm/i915/display/intel_atomic_plane.c |  49 +--
 .../gpu/drm/i915/display/intel_atomic_plane.h |  19 +-
 drivers/gpu/drm/i915/display/intel_cursor.c   | 101 +++---
 drivers/gpu/drm/i915/display/intel_de.h   |  11 +
 drivers/gpu/drm/i915/display/intel_display.c  |  27 +-
 .../drm/i915/display/intel_display_types.h|  16 +-
 drivers/gpu/drm/i915/display/intel_sprite.c   |  27 +-
 .../drm/i915/display/skl_universal_plane.c| 305 ++
 drivers/gpu/drm/xe/display/xe_plane_initial.c |   2 +-
 10 files changed, 333 insertions(+), 246 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c 
b/drivers/gpu/drm/i915/display/i9xx_plane.c
index 9447f7229b60..17a1e3801a85 100644
--- a/drivers/gpu/drm/i915/display/i9xx_plane.c
+++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
@@ -416,7 +416,8 @@ static int i9xx_plane_min_cdclk(const struct 
intel_crtc_state *crtc_state,
return DIV_ROUND_UP(pixel_rate * num, den);
 }
 
-static void i9xx_plane_update_noarm(struct intel_plane *plane,
+static void i9xx_plane_update_noarm(struct intel_dsb *dsb,
+   struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
 {
@@ -444,7 +445,8 @@ static void i9xx_plane_update_noarm(struct intel_plane 
*plane,
}
 }
 
-static void i9xx_plane_update_arm(struct intel_plane *plane,
+static void i9xx_plane_update_arm(struct intel_dsb *dsb,
+ struct intel_plane *plane,
  const struct intel_crtc_state *crtc_state,
  const struct intel_plane_state *plane_state)
 {
@@ -507,7 +509,8 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
  intel_plane_ggtt_offset(plane_state) + 
dspaddr_offset);
 }
 
-static void i830_plane_update_arm(struct intel_plane *plane,
+static void i830_plane_update_arm(struct intel_dsb *dsb,
+ struct intel_plane *plane,
  const struct intel_crtc_state *crtc_state,
  const struct intel_plane_state *plane_state)
 {
@@ -517,11 +520,12 @@ static void i830_plane_update_arm(struct intel_plane 
*plane,
 * Additional breakage on i830 causes register reads to return
 * the last latched value instead of the last written value [ALM026].
 */
-   i9xx_plane_update_noarm(plane, crtc_state, plane_state);
-   i9xx_plane_update_arm(plane, crtc_state, plane_state);
+   i9xx_plane_update_noarm(dsb, plane, crtc_state, plane_state);
+   i9xx_plane_update_arm(dsb, plane, crtc_state, plane_state);
 }
 
-static void i9xx_plane_disable_arm(struct intel_plane *plane,
+static void i9xx_plane_disable_arm(struct intel_dsb *dsb,
+  struct intel_plane *plane,
   const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
@@ -549,7 +553,8 @@ static void i9xx_plane_disable_arm(struct intel_plane 
*plane,
 }
 
 static void
-g4x_primary_async_flip(struct intel_plane *plane,
+g4x_primary_async_flip(struct intel_dsb *dsb,
+  struct intel_plane *plane,
   const struct intel_crtc_state *crtc_state,
   const struct intel_plane_state *plane_state,
   bool async_flip)
@@ -56

[PATCH 10/13] drm/i915: Extract intel_crtc_prepare_vblank_event()

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Extract the code for staging the vblank event for the
flip done interrupt handler. We'll reuse this for DSB
stuff later.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_crtc.c | 21 +++--
 drivers/gpu/drm/i915/display/intel_crtc.h |  3 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c 
b/drivers/gpu/drm/i915/display/intel_crtc.c
index 77cfab1d13de..30616101b4f2 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -495,12 +495,8 @@ void intel_pipe_update_start(struct intel_atomic_state 
*state,
intel_psr_lock(new_crtc_state);
 
if (new_crtc_state->do_async_flip) {
-   spin_lock_irq(&crtc->base.dev->event_lock);
-   /* arm the event for the flip done irq handler */
-   crtc->flip_done_event = new_crtc_state->uapi.event;
-   spin_unlock_irq(&crtc->base.dev->event_lock);
-
-   new_crtc_state->uapi.event = NULL;
+   intel_crtc_prepare_vblank_event(new_crtc_state,
+   &crtc->flip_done_event);
return;
}
 
@@ -600,6 +596,19 @@ void intel_crtc_arm_vblank_event(struct intel_crtc_state 
*crtc_state)
crtc_state->uapi.event = NULL;
 }
 
+void intel_crtc_prepare_vblank_event(struct intel_crtc_state *crtc_state,
+struct drm_pending_vblank_event **event)
+{
+   struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+   unsigned long irqflags;
+
+   spin_lock_irqsave(&crtc->base.dev->event_lock, irqflags);
+   *event = crtc_state->uapi.event;
+   spin_unlock_irqrestore(&crtc->base.dev->event_lock, irqflags);
+
+   crtc_state->uapi.event = NULL;
+}
+
 /**
  * intel_pipe_update_end() - end update of a set of display registers
  * @state: the atomic state
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h 
b/drivers/gpu/drm/i915/display/intel_crtc.h
index c1dd8c42cea2..4b0bdddc1db5 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.h
+++ b/drivers/gpu/drm/i915/display/intel_crtc.h
@@ -12,6 +12,7 @@ enum i9xx_plane_id;
 enum pipe;
 struct drm_display_mode;
 struct drm_i915_private;
+struct drm_pending_vblank_event;
 struct intel_atomic_state;
 struct intel_crtc;
 struct intel_crtc_state;
@@ -31,6 +32,8 @@ int intel_usecs_to_scanlines(const struct drm_display_mode 
*adjusted_mode,
 int intel_scanlines_to_usecs(const struct drm_display_mode *adjusted_mode,
 int scanlines);
 void intel_crtc_arm_vblank_event(struct intel_crtc_state *crtc_state);
+void intel_crtc_prepare_vblank_event(struct intel_crtc_state *crtc_state,
+struct drm_pending_vblank_event **event);
 u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
 int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
 struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
-- 
2.44.2



[PATCH 09/13] drm/i915/dsb: Introduce intel_dsb_wait_vblank_delay()

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Add intel_dsb_wait_vblank_delay() which instructs the DSB
to wait for duration between the undelayed and delayed vblanks.
We'll need this as the DSB can only directly wait for the
undelayed vblank, but we'll need to wait until the delayed
vblank has elapsed as well.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 11 +++
 drivers/gpu/drm/i915/display/intel_dsb.h |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index d444bb5f6fb2..ac6aaa022c08 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -635,6 +635,17 @@ void intel_dsb_chain(struct intel_atomic_state *state,
 wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0);
 }
 
+void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state,
+struct intel_dsb *dsb)
+{
+   struct intel_crtc *crtc = dsb->crtc;
+   const struct intel_crtc_state *crtc_state = 
pre_commit_crtc_state(state, crtc);
+   int usecs = intel_scanlines_to_usecs(&crtc_state->hw.adjusted_mode,
+dsb_vblank_delay(crtc_state)) + 1;
+
+   intel_dsb_wait_usec(dsb, usecs);
+}
+
 static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
  int hw_dewake_scanline)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h 
b/drivers/gpu/drm/i915/display/intel_dsb.h
index 115f51c75a1e..33e0fc2ab380 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -42,6 +42,8 @@ void intel_dsb_nonpost_end(struct intel_dsb *dsb);
 void intel_dsb_interrupt(struct intel_dsb *dsb);
 void intel_dsb_wait_usec(struct intel_dsb *dsb, int count);
 void intel_dsb_wait_vblanks(struct intel_dsb *dsb, int count);
+void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state,
+struct intel_dsb *dsb);
 void intel_dsb_wait_scanline_in(struct intel_atomic_state *state,
struct intel_dsb *dsb,
int lower, int upper);
-- 
2.44.2



[PATCH 08/13] drm/i915: Introduce intel_scanlines_to_usecs()

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Introduce intel_scanlines_to_usecs() as a counterpart to
intel_usecs_to_scanlines().

We'll have some use for this in DSB code as we want to do
relative scanline waits to evade the delayed vblank, but
unfortunately DSB can't do relative scanline waits (only
absolute). So we'll instead convert the relative scanline
count to usec and do a relative usec wait instead (which the
DSB knows how to do).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_crtc.c | 11 +++
 drivers/gpu/drm/i915/display/intel_crtc.h |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c 
b/drivers/gpu/drm/i915/display/intel_crtc.c
index 1b578cad2813..77cfab1d13de 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -457,6 +457,17 @@ int intel_usecs_to_scanlines(const struct drm_display_mode 
*adjusted_mode,
1000 * adjusted_mode->crtc_htotal);
 }
 
+int intel_scanlines_to_usecs(const struct drm_display_mode *adjusted_mode,
+int scanlines)
+{
+   /* paranoia */
+   if (!adjusted_mode->crtc_clock)
+   return 1;
+
+   return DIV_ROUND_UP_ULL(mul_u32_u32(scanlines, 
adjusted_mode->crtc_htotal * 1000),
+   adjusted_mode->crtc_clock);
+}
+
 /**
  * intel_pipe_update_start() - start update of a set of display registers
  * @state: the atomic state
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h 
b/drivers/gpu/drm/i915/display/intel_crtc.h
index b615b7ab5ccd..c1dd8c42cea2 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.h
+++ b/drivers/gpu/drm/i915/display/intel_crtc.h
@@ -28,6 +28,8 @@ struct intel_crtc_state;
 
 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
 int usecs);
+int intel_scanlines_to_usecs(const struct drm_display_mode *adjusted_mode,
+int scanlines);
 void intel_crtc_arm_vblank_event(struct intel_crtc_state *crtc_state);
 u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
 int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
-- 
2.44.2



[PATCH 07/13] drm/i915/dsb: Introduce intel_dsb_wait_vblanks()

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Add a function to emit a DSB wait for vblank instruction. This
just waits until the specified number of vblanks.

Note that this triggers on the transcoder's undelayed vblank,
as opposed to the pipe's delayed vblank.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 6 ++
 drivers/gpu/drm/i915/display/intel_dsb.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index da5c25f3d01e..d444bb5f6fb2 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -397,6 +397,12 @@ void intel_dsb_wait_usec(struct intel_dsb *dsb, int count)
   DSB_OPCODE_WAIT_USEC << DSB_OPCODE_SHIFT);
 }
 
+void intel_dsb_wait_vblanks(struct intel_dsb *dsb, int count)
+{
+   intel_dsb_emit(dsb, count,
+  DSB_OPCODE_WAIT_VBLANKS << DSB_OPCODE_SHIFT);
+}
+
 static void intel_dsb_emit_wait_dsl(struct intel_dsb *dsb,
u32 opcode, int lower, int upper)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h 
b/drivers/gpu/drm/i915/display/intel_dsb.h
index 882088f55580..115f51c75a1e 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -41,6 +41,7 @@ void intel_dsb_nonpost_start(struct intel_dsb *dsb);
 void intel_dsb_nonpost_end(struct intel_dsb *dsb);
 void intel_dsb_interrupt(struct intel_dsb *dsb);
 void intel_dsb_wait_usec(struct intel_dsb *dsb, int count);
+void intel_dsb_wait_vblanks(struct intel_dsb *dsb, int count);
 void intel_dsb_wait_scanline_in(struct intel_atomic_state *state,
struct intel_dsb *dsb,
int lower, int upper);
-- 
2.44.2



[PATCH 06/13] drm/i915/dsb: Introduce intel_dsb_wait_usec()

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Add a function to emit the DSB "wait usecs" instruction.
This is just a usleep() for the DSB.

As a lower bound it seems pretty accurate, but the upper bound
seemed oddly relaxed (ie. sometimes I've seen waits that are
quite a bit longer than specified, not sure why).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 6 ++
 drivers/gpu/drm/i915/display/intel_dsb.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 997196ba69ca..da5c25f3d01e 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -391,6 +391,12 @@ void intel_dsb_interrupt(struct intel_dsb *dsb)
   DSB_OPCODE_INTERRUPT << DSB_OPCODE_SHIFT);
 }
 
+void intel_dsb_wait_usec(struct intel_dsb *dsb, int count)
+{
+   intel_dsb_emit(dsb, count,
+  DSB_OPCODE_WAIT_USEC << DSB_OPCODE_SHIFT);
+}
+
 static void intel_dsb_emit_wait_dsl(struct intel_dsb *dsb,
u32 opcode, int lower, int upper)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h 
b/drivers/gpu/drm/i915/display/intel_dsb.h
index cce5cb1c6071..882088f55580 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -40,6 +40,7 @@ void intel_dsb_noop(struct intel_dsb *dsb, int count);
 void intel_dsb_nonpost_start(struct intel_dsb *dsb);
 void intel_dsb_nonpost_end(struct intel_dsb *dsb);
 void intel_dsb_interrupt(struct intel_dsb *dsb);
+void intel_dsb_wait_usec(struct intel_dsb *dsb, int count);
 void intel_dsb_wait_scanline_in(struct intel_atomic_state *state,
struct intel_dsb *dsb,
int lower, int upper);
-- 
2.44.2



[PATCH 05/13] drm/i915/dsb: Introduce intel_dsb_vblank_evade()

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Add a helper for performing vblank evasion on the DSB. DSB based
plane updates will need this to guarantee all the double buffered
arming registers will get programmed atomically within the same
frame.

With VRR we more or less have two vblanks to worry about:
- vmax vblank start in case no push was sent
- vmin vblank start in case a push was already sent during
  the vertical active. Only a concern for mailbox updates,
  which I suppose could happen if the legacy cursor updates
  take the non-fastpath without setting
  state->legacy_cursor_update to false.
Since we don't know which case is relevant we'll just evade
both.

We must also make sure to evade both the delayed vblank
(for pipe/plane registers) and the undelayed vblank
(for transcoder registers and chained DSBs w/
DSB_WAIT_FOR_VBLANK).

TODO: come up with a sensible usec number for the evasion...

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 31 
 drivers/gpu/drm/i915/display/intel_dsb.h |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 6de33c0c16c3..997196ba69ca 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -126,6 +126,12 @@ pre_commit_crtc_state(struct intel_atomic_state *state,
return old_crtc_state;
 }
 
+static int dsb_vblank_delay(const struct intel_crtc_state *crtc_state)
+{
+   return intel_mode_vblank_start(&crtc_state->hw.adjusted_mode) -
+   intel_mode_vdisplay(&crtc_state->hw.adjusted_mode);
+}
+
 static int dsb_vtotal(struct intel_atomic_state *state,
  struct intel_crtc *crtc)
 {
@@ -525,6 +531,31 @@ static u32 dsb_error_int_en(struct intel_display *display)
return errors;
 }
 
+void intel_dsb_vblank_evade(struct intel_atomic_state *state,
+   struct intel_dsb *dsb)
+{
+   struct intel_crtc *crtc = dsb->crtc;
+   const struct intel_crtc_state *crtc_state = 
pre_commit_crtc_state(state, crtc);
+   /* FIXME calibrate sensibly */
+   int latency = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 
20);
+   int vblank_delay = dsb_vblank_delay(crtc_state);
+   int start, end;
+
+   if (pre_commit_is_vrr_active(state, crtc)) {
+   end = intel_vrr_vmin_vblank_start(crtc_state);
+   start = end - vblank_delay - latency;
+   intel_dsb_wait_scanline_out(state, dsb, start, end);
+
+   end = intel_vrr_vmax_vblank_start(crtc_state);
+   start = end - vblank_delay - latency;
+   intel_dsb_wait_scanline_out(state, dsb, start, end);
+   } else {
+   end = intel_mode_vblank_start(&crtc_state->hw.adjusted_mode);
+   start = end - vblank_delay - latency;
+   intel_dsb_wait_scanline_out(state, dsb, start, end);
+   }
+}
+
 static void _intel_dsb_chain(struct intel_atomic_state *state,
 struct intel_dsb *dsb,
 struct intel_dsb *chained_dsb,
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h 
b/drivers/gpu/drm/i915/display/intel_dsb.h
index ff3b89dfffc1..cce5cb1c6071 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -46,6 +46,8 @@ void intel_dsb_wait_scanline_in(struct intel_atomic_state 
*state,
 void intel_dsb_wait_scanline_out(struct intel_atomic_state *state,
 struct intel_dsb *dsb,
 int lower, int upper);
+void intel_dsb_vblank_evade(struct intel_atomic_state *state,
+   struct intel_dsb *dsb);
 void intel_dsb_chain(struct intel_atomic_state *state,
 struct intel_dsb *dsb,
 struct intel_dsb *chained_dsb,
-- 
2.44.2



[PATCH 04/13] drm/i915/dsb: Enable programmable DSB interrupt

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

The DSB can signal a programmable interrupt in response to
a specific DSB command getting executed. Hook that up.

For now we'll just use this to signal the completion of the
commit via a vblank event. If, in the future, we'll need to
do other things in response to DSB interrupts we may need to
come up with some kind of fancier DSB interrupt framework where
the caller can specify a custom handler...

Signed-off-by: Ville Syrjälä 
---
 .../drm/i915/display/intel_display_types.h|  2 ++
 drivers/gpu/drm/i915/display/intel_dsb.c  | 27 +--
 drivers/gpu/drm/i915/display/intel_dsb.h  |  1 +
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index d98bcda16edf..1af74c224f86 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1488,6 +1488,8 @@ struct intel_crtc {
 
/* armed event for async flip */
struct drm_pending_vblank_event *flip_done_event;
+   /* armed event for DSB based updates */
+   struct drm_pending_vblank_event *dsb_event;
 
/* Access to these should be protected by dev_priv->irq_lock. */
bool cpu_fifo_underrun_disabled;
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index a14b0230a4f4..6de33c0c16c3 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -379,6 +379,12 @@ void intel_dsb_nonpost_end(struct intel_dsb *dsb)
intel_dsb_noop(dsb, 4);
 }
 
+void intel_dsb_interrupt(struct intel_dsb *dsb)
+{
+   intel_dsb_emit(dsb, 0,
+  DSB_OPCODE_INTERRUPT << DSB_OPCODE_SHIFT);
+}
+
 static void intel_dsb_emit_wait_dsl(struct intel_dsb *dsb,
u32 opcode, int lower, int upper)
 {
@@ -544,7 +550,7 @@ static void _intel_dsb_chain(struct intel_atomic_state 
*state,
 
intel_dsb_reg_write(dsb, DSB_INTERRUPT(pipe, chained_dsb->id),
dsb_error_int_status(display) | DSB_PROG_INT_STATUS 
|
-   dsb_error_int_en(display));
+   dsb_error_int_en(display) | DSB_PROG_INT_EN);
 
if (ctrl & DSB_WAIT_FOR_VBLANK) {
int dewake_scanline = dsb_dewake_scanline_start(state, crtc);
@@ -612,7 +618,7 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 
ctrl,
 
intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id),
  dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
- dsb_error_int_en(display));
+ dsb_error_int_en(display) | DSB_PROG_INT_EN);
 
intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id),
  intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf));
@@ -779,6 +785,23 @@ void intel_dsb_irq_handler(struct intel_display *display,
tmp = intel_de_read_fw(display, DSB_INTERRUPT(pipe, dsb_id));
intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb_id), tmp);
 
+   if (tmp & DSB_PROG_INT_STATUS) {
+   spin_lock(&display->drm->event_lock);
+
+   if (crtc->dsb_event) {
+   /*
+* Update vblank counter/timestmap in case it
+* hasn't been done yet for this frame.
+*/
+   drm_crtc_accurate_vblank_count(&crtc->base);
+
+   drm_crtc_send_vblank_event(&crtc->base, 
crtc->dsb_event);
+   crtc->dsb_event = NULL;
+   }
+
+   spin_unlock(&display->drm->event_lock);
+   }
+
errors = tmp & dsb_error_int_status(display);
if (errors)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d error interrupt: 
0x%x\n",
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h 
b/drivers/gpu/drm/i915/display/intel_dsb.h
index c352c12aa59f..ff3b89dfffc1 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -39,6 +39,7 @@ void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
 void intel_dsb_noop(struct intel_dsb *dsb, int count);
 void intel_dsb_nonpost_start(struct intel_dsb *dsb);
 void intel_dsb_nonpost_end(struct intel_dsb *dsb);
+void intel_dsb_interrupt(struct intel_dsb *dsb);
 void intel_dsb_wait_scanline_in(struct intel_atomic_state *state,
struct intel_dsb *dsb,
int lower, int upper);
-- 
2.44.2



[PATCH 03/13] drm/i915/dsb: Generate the DSB buffer in commit_tail()

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Once we start using DSB for plane updates we'll need to defer
generating the DSB buffer until the clear color has been
read out. So we need to move at some of the DSB stuff into
commit_tail(). That is perhaps a better place for it anyway
as the ioctl thread can move on immediately without spending
time building the DSB commands.

We always have the MMIO fallback (in case the DSB buffer
allocation fails), so there's no real reason to keep any
of this in the synchronous part of the ioctl.

Because the DSB LUT programming doesn't depend on the plane
clear color we can still do that part before waiting for
fences/etc. which should help paralleize things a bit more.
The DSB plane programming will need to happen after those
however as that depends on the clear color.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c | 23 +---
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 048051d9a624..a3555885597d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6732,17 +6732,12 @@ int intel_atomic_check(struct drm_device *dev,
 
 static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
 {
-   struct intel_crtc_state __maybe_unused *crtc_state;
-   struct intel_crtc *crtc;
-   int i, ret;
+   int ret;
 
ret = drm_atomic_helper_prepare_planes(state->base.dev, &state->base);
if (ret < 0)
return ret;
 
-   for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i)
-   intel_color_prepare_commit(state, crtc);
-
return 0;
 }
 
@@ -7333,6 +7328,12 @@ static void 
intel_atomic_prepare_plane_clear_colors(struct intel_atomic_state *s
}
 }
 
+static void intel_atomic_dsb_prepare(struct intel_atomic_state *state,
+struct intel_crtc *crtc)
+{
+   intel_color_prepare_commit(state, crtc);
+}
+
 static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 {
struct drm_device *dev = state->base.dev;
@@ -7343,6 +7344,9 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
intel_wakeref_t wakeref = 0;
int i;
 
+   for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
+   intel_atomic_dsb_prepare(state, crtc);
+
intel_atomic_commit_fence_wait(state);
 
intel_td_flush(dev_priv);
@@ -7661,13 +7665,6 @@ int intel_atomic_commit(struct drm_device *dev, struct 
drm_atomic_state *_state,
ret = intel_atomic_swap_state(state);
 
if (ret) {
-   struct intel_crtc_state *new_crtc_state;
-   struct intel_crtc *crtc;
-   int i;
-
-   for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
-   intel_color_cleanup_commit(new_crtc_state);
-
drm_atomic_helper_unprepare_planes(dev, &state->base);
intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);
return ret;
-- 
2.44.2



[PATCH 02/13] drm/i915: Prepare clear color before wait_for_dependencies()

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Read out the clear color as soon as fences and the transient
data flush have finished. There is no need to wait for
all the display specific operations that might still be
going on. This could parallelize things a bit more effectively.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 78ce402a5cd0..048051d9a624 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7347,6 +7347,8 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
 
intel_td_flush(dev_priv);
 
+   intel_atomic_prepare_plane_clear_colors(state);
+
drm_atomic_helper_wait_for_dependencies(&state->base);
drm_dp_mst_atomic_wait_for_dependencies(&state->base);
intel_atomic_global_state_wait_for_dependencies(state);
@@ -7380,8 +7382,6 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
 */
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DC_OFF);
 
-   intel_atomic_prepare_plane_clear_colors(state);
-
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (intel_crtc_needs_modeset(new_crtc_state) ||
-- 
2.44.2



[PATCH 01/13] drm/i915/dsb: Avoid reads of the DSB buffer for indexed register writes

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Reading from the DSB command buffer might be somewhat expensive on
discrete GPUs because the buffer resides in GPU local memory. Avoid
such reads in the indexed register write handling by tracking the
previous instruction in intel_dsb.

TODO: actually measure this

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 54 ++--
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index da24e041d269..a14b0230a4f4 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -37,9 +37,16 @@ struct intel_dsb {
unsigned int free_pos;
 
/*
-* ins_start_offset will help to store start dword of the dsb
-* instuction and help in identifying the batch of auto-increment
-* register.
+* Previously emitted DSB instruction. Used to
+* identify/adjust the instruction for indexed
+* register writes.
+*/
+   u32 ins[2];
+
+   /*
+* Start of the previously emitted DSB instruction.
+* Used to adjust the instruction for indexed
+* register writes.
 */
unsigned int ins_start_offset;
 
@@ -215,9 +222,11 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, 
u32 udw)
dsb->free_pos = ALIGN(dsb->free_pos, 2);
 
dsb->ins_start_offset = dsb->free_pos;
+   dsb->ins[0] = ldw;
+   dsb->ins[1] = udw;
 
-   intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, ldw);
-   intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, udw);
+   intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, dsb->ins[0]);
+   intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, dsb->ins[1]);
 }
 
 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
@@ -233,10 +242,8 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb 
*dsb,
if (dsb->free_pos == 0)
return false;
 
-   prev_opcode = intel_dsb_buffer_read(&dsb->dsb_buf,
-   dsb->ins_start_offset + 1) & 
~DSB_REG_VALUE_MASK;
-   prev_reg =  intel_dsb_buffer_read(&dsb->dsb_buf,
- dsb->ins_start_offset + 1) & 
DSB_REG_VALUE_MASK;
+   prev_opcode = dsb->ins[1] & ~DSB_REG_VALUE_MASK;
+   prev_reg =  dsb->ins[1] & DSB_REG_VALUE_MASK;
 
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
 }
@@ -269,8 +276,6 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct 
intel_dsb *dsb, i915_reg_
 void intel_dsb_reg_write(struct intel_dsb *dsb,
 i915_reg_t reg, u32 val)
 {
-   u32 old_val;
-
/*
 * For example the buffer will look like below for 3 dwords for auto
 * increment register:
@@ -299,23 +304,27 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
 
/* convert to indexed write? */
if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) {
-   u32 prev_val = intel_dsb_buffer_read(&dsb->dsb_buf,
-
dsb->ins_start_offset + 0);
+   u32 prev_val = dsb->ins[0];
 
-   intel_dsb_buffer_write(&dsb->dsb_buf,
-  dsb->ins_start_offset + 0, 1); 
/* count */
+   dsb->ins[0] = 1; /* count */
+   dsb->ins[1] = (DSB_OPCODE_INDEXED_WRITE << 
DSB_OPCODE_SHIFT) |
+   i915_mmio_reg_offset(reg);
+
+   intel_dsb_buffer_write(&dsb->dsb_buf, 
dsb->ins_start_offset + 0,
+  dsb->ins[0]);
intel_dsb_buffer_write(&dsb->dsb_buf, 
dsb->ins_start_offset + 1,
-  (DSB_OPCODE_INDEXED_WRITE << 
DSB_OPCODE_SHIFT) |
-  i915_mmio_reg_offset(reg));
-   intel_dsb_buffer_write(&dsb->dsb_buf, 
dsb->ins_start_offset + 2, prev_val);
+  dsb->ins[1]);
+   intel_dsb_buffer_write(&dsb->dsb_buf, 
dsb->ins_start_offset + 2,
+  prev_val);
 
dsb->free_pos++;
}
 
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, val);
/* Update the count */
-   old_val = intel_dsb_buffer_read(&dsb->dsb_buf, 
dsb->ins_start_offset);
-   intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset, 
old_val + 1);
+   dsb->ins[0]++;
+   intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
+  dsb->ins[0]);
 
/* if number of data words is odd, then the last dword should 
be 0.*/
 

[PATCH 00/13] drm/i915: Use DSB for plane/color management commits

2024-09-02 Thread Ville Syrjala
From: Ville Syrjälä 

Use the DSB to perform simple plane/color management commits.
Anything more complicatd (modesets and fastsets) are still
punted to the mmio path.

Also DSB won't be used when any of these are in use:
- scalers (scaler code needs more work)
- VRR (need to figure out a race free commit completion scheme)
- PSR (zero thoughts given for PSR interactions so far)
- async flips (no real though given here either)

Ville Syrjälä (13):
  drm/i915/dsb: Avoid reads of the DSB buffer for indexed register
writes
  drm/i915: Prepare clear color before wait_for_dependencies()
  drm/i915/dsb: Generate the DSB buffer in commit_tail()
  drm/i915/dsb: Enable programmable DSB interrupt
  drm/i915/dsb: Introduce intel_dsb_vblank_evade()
  drm/i915/dsb: Introduce intel_dsb_wait_usec()
  drm/i915/dsb: Introduce intel_dsb_wait_vblanks()
  drm/i915: Introduce intel_scanlines_to_usecs()
  drm/i915/dsb: Introduce intel_dsb_wait_vblank_delay()
  drm/i915: Extract intel_crtc_prepare_vblank_event()
  drm/i915: Plumb 'dsb' all way to the plane hooks
  drm/i915: Plumb 'dsb' all way to the color commit hooks
  drm/i915/dsb: Use DSB for plane/color management updates

 drivers/gpu/drm/i915/display/i9xx_plane.c |  22 +-
 drivers/gpu/drm/i915/display/intel_atomic.c   |   5 +-
 .../gpu/drm/i915/display/intel_atomic_plane.c |  49 +--
 .../gpu/drm/i915/display/intel_atomic_plane.h |  19 +-
 drivers/gpu/drm/i915/display/intel_color.c| 201 ++--
 drivers/gpu/drm/i915/display/intel_color.h|   7 +-
 drivers/gpu/drm/i915/display/intel_crtc.c |  37 ++-
 drivers/gpu/drm/i915/display/intel_crtc.h |   5 +
 drivers/gpu/drm/i915/display/intel_cursor.c   | 101 +++---
 drivers/gpu/drm/i915/display/intel_de.h   |  11 +
 drivers/gpu/drm/i915/display/intel_display.c  | 198 +---
 .../drm/i915/display/intel_display_types.h|  23 +-
 drivers/gpu/drm/i915/display/intel_dsb.c  | 135 ++--
 drivers/gpu/drm/i915/display/intel_dsb.h  |   7 +
 .../drm/i915/display/intel_modeset_setup.c|   4 +-
 drivers/gpu/drm/i915/display/intel_sprite.c   |  27 +-
 .../drm/i915/display/skl_universal_plane.c| 305 ++
 drivers/gpu/drm/xe/display/xe_plane_initial.c |   2 +-
 18 files changed, 739 insertions(+), 419 deletions(-)

-- 
2.44.2



[PATCH] drm/i915: Fix readout degamma_lut mismatch on ilk/snb

2024-07-10 Thread Ville Syrjala
From: Ville Syrjälä 

On ilk/snb the pipe may be configured to place the LUT before or
after the CSC depending on various factors, but as there is only
one LUT (no split mode like on IVB+) we only advertise a gamma_lut
and no degamma_lut in the uapi to avoid confusing userspace.

This can cause a problem during readout if the VBIOS/GOP enabled
the LUT in the pre CSC configuration. The current code blindly
assigns the results of the readout to the degamma_lut, which will
cause a failure during the next atomic_check() as we aren't expecting
anything to be in degamma_lut since it's not visible to userspace.

Fix the problem by assigning whatever LUT we read out from the
hardware into gamma_lut.

Cc: sta...@vger.kernel.org
Fixes: d2559299d339 ("drm/i915: Make ilk_read_luts() capable of degamma 
readout")
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11608
Signed-off-by: Ville Syrjälä 
---
 .../drm/i915/display/intel_modeset_setup.c| 31 ---
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c 
b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
index 7602cb30ebf1..e1213f3d93cc 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
@@ -326,6 +326,8 @@ static void 
intel_modeset_update_connector_atomic_state(struct drm_i915_private
 
 static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state 
*crtc_state)
 {
+   struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
if (intel_crtc_is_joiner_secondary(crtc_state))
return;
 
@@ -337,11 +339,30 @@ static void intel_crtc_copy_hw_to_uapi_state(struct 
intel_crtc_state *crtc_state
crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
 
-   /* assume 1:1 mapping */
-   drm_property_replace_blob(&crtc_state->hw.degamma_lut,
- crtc_state->pre_csc_lut);
-   drm_property_replace_blob(&crtc_state->hw.gamma_lut,
- crtc_state->post_csc_lut);
+   if (DISPLAY_INFO(i915)->color.degamma_lut_size) {
+   /* assume 1:1 mapping */
+   drm_property_replace_blob(&crtc_state->hw.degamma_lut,
+ crtc_state->pre_csc_lut);
+   drm_property_replace_blob(&crtc_state->hw.gamma_lut,
+ crtc_state->post_csc_lut);
+   } else {
+   /*
+* ilk/snb hw may be configured for either pre_csc_lut
+* or post_csc_lut, but we don't advertise degamma_lut as
+* being available in the uapi since there is only one
+* hardware LUT. Always assign the result of the readout
+* to gamma_lut as that is the only valid source of LUTs
+* in the uapi.
+*/
+   drm_WARN_ON(&i915->drm, crtc_state->post_csc_lut &&
+   crtc_state->pre_csc_lut);
+
+   drm_property_replace_blob(&crtc_state->hw.degamma_lut,
+ NULL);
+   drm_property_replace_blob(&crtc_state->hw.gamma_lut,
+ crtc_state->post_csc_lut ?:
+ crtc_state->pre_csc_lut);
+   }
 
drm_property_replace_blob(&crtc_state->uapi.degamma_lut,
  crtc_state->hw.degamma_lut);
-- 
2.44.2



[PATCH 20/20] drm/xe/fbdev: Adjust fbdev stolen mem usage heuristic

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the "1/2 of stolen size" fbdev fb size heuristic with
something a bit more clever, that is ask the FBC code how much
stolen mem it would like to have avaialable for its CFB use.

TODO:
- This doesn't account for the fact that FBC's idea
  usable stolen size might differ from other users of stolen
- Would be nice to share the code with i915, but need to
  figure out how to abstract the stolen size and
  dgpu/lmem stuff

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/xe/display/intel_fbdev_fb.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c 
b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
index f67bc0fd803b..62e1d176b07f 100644
--- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
+++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
@@ -24,12 +24,11 @@ bool intel_fbdev_fb_prefer_stolen(struct intel_display 
*display,
if (!stolen)
return false;
 
-   /*
-* If the FB is too big, just don't use it since fbdev is not very
-* important and we should probably use that space with FBC or other
-* features.
-*/
-   return stolen->size >= size * 2;
+   if (size > stolen->size)
+   return false;
+
+   /* try to ensure FBC has enough stolen to do its job well */
+   return stolen->size - size >= 
intel_fbc_preferred_cfb_size(&xe->display);
 }
 
 struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
-- 
2.44.2



[PATCH 19/20] drm/i915/fbdev: Adjust fbdev stolen mem usage heuristic

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Replace the "1/2 of stolen size" fbdev fb size heuristic with
something a bit more clever, that is ask the FBC code how much
stolen mem it would like to have avaialable for its CFB use.

TODO:
- This doesn't account for the fact that FBC's idea
  usable stolen size might differ from other users of stolen
- Would be nice to share the code with xe, but need to
  figure out how to abstract the stolen size and
  dgpu/lmem stuff

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbdev_fb.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c 
b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
index 0a6445acb100..29f3241c9270 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
@@ -16,12 +16,11 @@ bool intel_fbdev_fb_prefer_stolen(struct intel_display 
*display,
 {
struct drm_i915_private *i915 = to_i915(display->drm);
 
-   /*
-* If the FB is too big, just don't use it since fbdev is not very
-* important and we should probably use that space with FBC or other
-* features.
-*/
-   return i915->dsm.usable_size >= size * 2;
+   if (size > i915->dsm.usable_size)
+   return false;
+
+   /* try to ensure FBC has enough stolen to do its job well */
+   return i915->dsm.usable_size - size >= 
intel_fbc_preferred_cfb_size(&i915->display);
 }
 
 struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
-- 
2.44.2



[PATCH 18/20] drm/xe/fbdev: Use the same logic for fbdev stolen takever and fresh allocation

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Currently xe only checks that the BIOS FB doesn't take up too much
stolen memory, but does no such check when allocating a fresh FB
from stolen. Use the same rule for both, just like i915 does.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/xe/display/intel_fbdev_fb.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c 
b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
index f7905b382d06..f67bc0fd803b 100644
--- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
+++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
@@ -17,6 +17,9 @@ bool intel_fbdev_fb_prefer_stolen(struct intel_display 
*display,
struct xe_device *xe = to_xe_device(display->drm);
struct ttm_resource_manager *stolen;
 
+   if (IS_DGFX(xe))
+   return false;
+
stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
if (!stolen)
return false;
@@ -55,7 +58,7 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct 
drm_fb_helper *helper,
size = PAGE_ALIGN(size);
obj = ERR_PTR(-ENODEV);
 
-   if (!IS_DGFX(xe)) {
+   if (intel_fbdev_fb_prefer_stolen(&xe->display, size)) {
obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe),
   NULL, size,
   ttm_bo_type_kernel, 
XE_BO_FLAG_SCANOUT |
-- 
2.44.2



[PATCH 16/20] drm/i915/fbdev: Extract intel_fbdev_fb_prefer_stolen()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Consolidate the "should we allocate fbdev fb in stolen?"
check into a helper function. Makes it easier to change the
heuristics without having to change so many places.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbdev_fb.c | 24 ---
 drivers/gpu/drm/i915/display/intel_fbdev_fb.h |  5 +++-
 .../drm/i915/display/intel_plane_initial.c| 10 +++-
 3 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c 
b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
index 497525ef9668..0a6445acb100 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c
@@ -11,6 +11,19 @@
 #include "intel_display_types.h"
 #include "intel_fbdev_fb.h"
 
+bool intel_fbdev_fb_prefer_stolen(struct intel_display *display,
+ unsigned int size)
+{
+   struct drm_i915_private *i915 = to_i915(display->drm);
+
+   /*
+* If the FB is too big, just don't use it since fbdev is not very
+* important and we should probably use that space with FBC or other
+* features.
+*/
+   return i915->dsm.usable_size >= size * 2;
+}
+
 struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
   struct 
drm_fb_helper_surface_size *sizes)
 {
@@ -42,14 +55,9 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct 
drm_fb_helper *helper,
  I915_BO_ALLOC_CONTIGUOUS |
  I915_BO_ALLOC_USER);
} else {
-   /*
-* If the FB is too big, just don't use it since fbdev is not 
very
-* important and we should probably use that space with FBC or 
other
-* features.
-*
-* Also skip stolen on MTL as Wa_22018444074 mitigation.
-*/
-   if (!(IS_METEORLAKE(dev_priv)) && size * 2 < 
dev_priv->dsm.usable_size)
+   /* skip stolen on MTL as Wa_22018444074 mitigation */
+   if (!IS_METEORLAKE(dev_priv) &&
+   intel_fbdev_fb_prefer_stolen(&dev_priv->display, size))
obj = i915_gem_object_create_stolen(dev_priv, size);
if (IS_ERR(obj))
obj = i915_gem_object_create_shmem(dev_priv, size);
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h 
b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h
index 4832fe688fbf..3b9033bd2160 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h
+++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h
@@ -6,16 +6,19 @@
 #ifndef __INTEL_FBDEV_FB_H__
 #define __INTEL_FBDEV_FB_H__
 
+#include 
+
 struct drm_fb_helper;
 struct drm_fb_helper_surface_size;
 struct drm_i915_gem_object;
 struct drm_i915_private;
 struct fb_info;
 struct i915_vma;
+struct intel_display;
 
 struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
   struct 
drm_fb_helper_surface_size *sizes);
 int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info 
*info,
 struct drm_i915_gem_object *obj, struct i915_vma 
*vma);
-
+bool intel_fbdev_fb_prefer_stolen(struct intel_display *display, unsigned int 
size);
 #endif
diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c 
b/drivers/gpu/drm/i915/display/intel_plane_initial.c
index ada1792df5b3..4622bb5f3426 100644
--- a/drivers/gpu/drm/i915/display/intel_plane_initial.c
+++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c
@@ -11,6 +11,7 @@
 #include "intel_display.h"
 #include "intel_display_types.h"
 #include "intel_fb.h"
+#include "intel_fbdev_fb.h"
 #include "intel_frontbuffer.h"
 #include "intel_plane_initial.h"
 
@@ -160,15 +161,10 @@ initial_plane_vma(struct drm_i915_private *i915,
mem->min_page_size);
size -= base;
 
-   /*
-* If the FB is too big, just don't use it since fbdev is not very
-* important and we should probably use that space with FBC or other
-* features.
-*/
if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
mem == i915->mm.stolen_region &&
-   size * 2 > i915->dsm.usable_size) {
-   drm_dbg_kms(&i915->drm, "Initial FB size exceeds half of 
stolen, discarding\n");
+   !intel_fbdev_fb_prefer_stolen(&i915->display, size)) {
+   drm_dbg_kms(&i915->drm, "Initial FB size uses too much stolen, 
discarding\n");
return NULL;
}
 
-- 
2.44.2



[PATCH 17/20] drm/xe/fbdev: Extract intel_fbdev_fb_prefer_stolen()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Pull the "should we keep the bios fb in stolen?" logic into
into a helper function, same as was done for i915. Gives us
a single place where to tweak the heuristics.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/xe/display/intel_fbdev_fb.c   | 18 ++
 drivers/gpu/drm/xe/display/xe_plane_initial.c |  8 ++--
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c 
b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
index 816ad13821a8..f7905b382d06 100644
--- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
+++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c
@@ -11,6 +11,24 @@
 #include "xe_gt.h"
 #include "xe_ttm_stolen_mgr.h"
 
+bool intel_fbdev_fb_prefer_stolen(struct intel_display *display,
+ unsigned int size)
+{
+   struct xe_device *xe = to_xe_device(display->drm);
+   struct ttm_resource_manager *stolen;
+
+   stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN);
+   if (!stolen)
+   return false;
+
+   /*
+* If the FB is too big, just don't use it since fbdev is not very
+* important and we should probably use that space with FBC or other
+* features.
+*/
+   return stolen->size >= size * 2;
+}
+
 struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
   struct 
drm_fb_helper_surface_size *sizes)
 {
diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c 
b/drivers/gpu/drm/xe/display/xe_plane_initial.c
index 21965cc8a9ca..4c000e95aea5 100644
--- a/drivers/gpu/drm/xe/display/xe_plane_initial.c
+++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c
@@ -15,6 +15,7 @@
 #include "intel_display_types.h"
 #include "intel_fb.h"
 #include "intel_fb_pin.h"
+#include "intel_fbdev_fb.h"
 #include "intel_frontbuffer.h"
 #include "intel_plane_initial.h"
 #include "xe_bo.h"
@@ -104,13 +105,8 @@ initial_plane_bo(struct xe_device *xe,
phys_base = base;
flags |= XE_BO_FLAG_STOLEN;
 
-   /*
-* If the FB is too big, just don't use it since fbdev is not 
very
-* important and we should probably use that space with FBC or 
other
-* features.
-*/
if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
-   plane_config->size * 2 > stolen->size)
+   !intel_fbdev_fb_prefer_stolen(&xe->display, 
plane_config->size))
return NULL;
}
 
-- 
2.44.2



[PATCH 15/20] drm/xe/fbdev: Fix BIOS FB vs.s stolen size checke

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Looks like stolen->size is in bytes, not pages. Remove the
bogus PAGE_SHIFT stuff.

Also for some rnadom reason xe rejects the FB if it takes up
exactly half of stolen, whereas i915 allows it to be used
in that case. Adjust xe to follow the i915 rule for consistency.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/xe/display/xe_plane_initial.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c 
b/drivers/gpu/drm/xe/display/xe_plane_initial.c
index 5eccd6abb3ef..21965cc8a9ca 100644
--- a/drivers/gpu/drm/xe/display/xe_plane_initial.c
+++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c
@@ -110,7 +110,7 @@ initial_plane_bo(struct xe_device *xe,
 * features.
 */
if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
-   plane_config->size * 2 >> PAGE_SHIFT >= stolen->size)
+   plane_config->size * 2 > stolen->size)
return NULL;
}
 
-- 
2.44.2



[PATCH 14/20] drm/i915/fbc: Introduce intel_fbc_preferred_cfb_size()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Allow the code to declare roughly how much stolen memory
should remain available for the CFB. Since we don't know
the actual resolutions that will eventually be used simply
assume that the maximum plane size (with no extra stride
padding) is enough, with 1:1 compression ratio limit.

This should be useful for the fbdev code to determine
whether to allocate/keep the fbdev framebuffer in stolen
or not.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 17 +
 drivers/gpu/drm/i915/display/intel_fbc.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index a0e539bc80f1..efe0a554a281 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -1911,6 +1911,23 @@ static int intel_sanitize_fbc_option(struct 
intel_display *display)
return 0;
 }
 
+unsigned int intel_fbc_preferred_cfb_size(struct intel_display *display)
+{
+   unsigned int cpp, width, height, stride;
+
+   if (!HAS_FBC(display))
+   return 0;
+
+   intel_fbc_max_plane_size(display, &width, &height);
+
+   cpp = intel_fbc_cfb_cpp();
+
+   /* assume stride matches width to keep this simple */
+   stride = _intel_fbc_cfb_stride(display, cpp, width, width * cpp);
+
+   return _intel_fbc_cfb_size(display, height, stride);
+}
+
 void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane)
 {
plane->fbc = fbc;
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h 
b/drivers/gpu/drm/i915/display/intel_fbc.h
index 834b271505b1..40d8efec6d9d 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.h
+++ b/drivers/gpu/drm/i915/display/intel_fbc.h
@@ -46,6 +46,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
 void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane);
 void intel_fbc_handle_fifo_underrun_irq(struct intel_display *display);
 void intel_fbc_reset_underrun(struct intel_display *display);
+unsigned int intel_fbc_preferred_cfb_size(struct intel_display *display);
 void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc);
 void intel_fbc_debugfs_register(struct intel_display *display);
 
-- 
2.44.2



[PATCH 13/20] drm/i915/fbc: Extract intel_fbc_cfb_cpp()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Extract a helper to determine the CFB bytes per pixel value.
Currently this is always 4, but that could change in the
future.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 293e1a3b9a9d..a0e539bc80f1 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -140,20 +140,24 @@ static unsigned int intel_fbc_plane_stride(const struct 
intel_plane_state *plane
return stride;
 }
 
+static unsigned int intel_fbc_cfb_cpp(void)
+{
+   return 4; /* FBC always 4 bytes per pixel */
+}
+
 /* plane stride based cfb stride in bytes, assuming 1:1 compression limit */
 static unsigned int intel_fbc_plane_cfb_stride(const struct intel_plane_state 
*plane_state)
 {
-   unsigned int cpp = 4; /* FBC always 4 bytes per pixel */
+   unsigned int cpp = intel_fbc_cfb_cpp();
 
return intel_fbc_plane_stride(plane_state) * cpp;
 }
 
 /* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */
 static unsigned int skl_fbc_min_cfb_stride(struct intel_display *display,
-  unsigned int width)
+  unsigned int cpp, unsigned int width)
 {
unsigned int limit = 4; /* 1:4 compression limit is the worst case */
-   unsigned int cpp = 4; /* FBC always 4 bytes per pixel */
unsigned int height = 4; /* FBC segment is 4 lines */
unsigned int stride;
 
@@ -179,7 +183,8 @@ static unsigned int skl_fbc_min_cfb_stride(struct 
intel_display *display,
 
 /* properly aligned cfb stride in bytes, assuming 1:1 compression limit */
 static unsigned int _intel_fbc_cfb_stride(struct intel_display *display,
- unsigned int width, unsigned int 
stride)
+ unsigned int cpp, unsigned int width,
+ unsigned int stride)
 {
/*
 * At least some of the platforms require each 4 line segment to
@@ -187,7 +192,7 @@ static unsigned int _intel_fbc_cfb_stride(struct 
intel_display *display,
 * that regardless of the compression limit we choose later.
 */
if (DISPLAY_VER(display) >= 9)
-   return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(display, 
width));
+   return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(display, 
cpp, width));
else
return stride;
 }
@@ -197,8 +202,9 @@ static unsigned int intel_fbc_cfb_stride(const struct 
intel_plane_state *plane_s
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
unsigned int stride = intel_fbc_plane_cfb_stride(plane_state);
unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16;
+   unsigned int cpp = intel_fbc_cfb_cpp();
 
-   return _intel_fbc_cfb_stride(display, width, stride);
+   return _intel_fbc_cfb_stride(display, cpp, width, stride);
 }
 
 /*
-- 
2.44.2



[PATCH 12/20] drm/i915/fbc: Extract _intel_fbc_cfb_size()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Pull the lower level stuff out from intel_fbc_cfb_size() into
a separate function that doesn't depend on the plane_state.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 47b715e5d533..293e1a3b9a9d 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -218,13 +218,18 @@ static unsigned int intel_fbc_max_cfb_height(struct 
intel_display *display)
return 1536;
 }
 
+static unsigned int _intel_fbc_cfb_size(struct intel_display *display,
+   unsigned int height, unsigned int 
stride)
+{
+   return min(height, intel_fbc_max_cfb_height(display)) * stride;
+}
+
 static unsigned int intel_fbc_cfb_size(const struct intel_plane_state 
*plane_state)
 {
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
unsigned int height = drm_rect_height(&plane_state->uapi.src) >> 16;
 
-   return min(height, intel_fbc_max_cfb_height(display)) *
-   intel_fbc_cfb_stride(plane_state);
+   return _intel_fbc_cfb_size(display, height, 
intel_fbc_cfb_stride(plane_state));
 }
 
 static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state 
*plane_state)
-- 
2.44.2



[PATCH 11/20] drm/i915/fbc: Extract intel_fbc_max_cfb_height()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Pull the code to determine the maximum CFB height
into a separate function. For pre-HSW the maximum CFB
height is the same as the maximum plane height (ie. the
older hardware supposedely doens't have the trick of leaving
the extra lines uncompressed).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 27 ++--
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index cf5750ed4681..47b715e5d533 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -201,17 +201,30 @@ static unsigned int intel_fbc_cfb_stride(const struct 
intel_plane_state *plane_s
return _intel_fbc_cfb_stride(display, width, stride);
 }
 
-static unsigned int intel_fbc_cfb_size(const struct intel_plane_state 
*plane_state)
+/*
+ * Maximum height the hardware will compress, on HSW+
+ * additional lines (up to the actual plane height) will
+ * remain uncompressed.
+ */
+static unsigned int intel_fbc_max_cfb_height(struct intel_display *display)
 {
-   struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
-   int height = drm_rect_height(&plane_state->uapi.src) >> 16;
+   struct drm_i915_private *i915 = to_i915(display->drm);
 
if (DISPLAY_VER(display) >= 8)
-   height = min(height, 2560);
-   else if (DISPLAY_VER(display) == 7)
-   height = min(height, 2048);
+   return 2560;
+   else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915))
+   return 2048;
+   else
+   return 1536;
+}
 
-   return height * intel_fbc_cfb_stride(plane_state);
+static unsigned int intel_fbc_cfb_size(const struct intel_plane_state 
*plane_state)
+{
+   struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
+   unsigned int height = drm_rect_height(&plane_state->uapi.src) >> 16;
+
+   return min(height, intel_fbc_max_cfb_height(display)) *
+   intel_fbc_cfb_stride(plane_state);
 }
 
 static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state 
*plane_state)
-- 
2.44.2



[PATCH 10/20] drm/i915/fbc: Reoder CFB max height platform checks

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Rearrange the max CFB max height platform into the
more common "new first, old last" order.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 4d25ebb5ae9d..cf5750ed4681 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -206,10 +206,10 @@ static unsigned int intel_fbc_cfb_size(const struct 
intel_plane_state *plane_sta
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
int height = drm_rect_height(&plane_state->uapi.src) >> 16;
 
-   if (DISPLAY_VER(display) == 7)
-   height = min(height, 2048);
-   else if (DISPLAY_VER(display) >= 8)
+   if (DISPLAY_VER(display) >= 8)
height = min(height, 2560);
+   else if (DISPLAY_VER(display) == 7)
+   height = min(height, 2048);
 
return height * intel_fbc_cfb_stride(plane_state);
 }
-- 
2.44.2



[PATCH 09/20] drm/i915/fbc: s/lines/height/

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Use the more customary name 'height' instead of 'lines'.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 4a9321f5218f..4d25ebb5ae9d 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -204,14 +204,14 @@ static unsigned int intel_fbc_cfb_stride(const struct 
intel_plane_state *plane_s
 static unsigned int intel_fbc_cfb_size(const struct intel_plane_state 
*plane_state)
 {
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
-   int lines = drm_rect_height(&plane_state->uapi.src) >> 16;
+   int height = drm_rect_height(&plane_state->uapi.src) >> 16;
 
if (DISPLAY_VER(display) == 7)
-   lines = min(lines, 2048);
+   height = min(height, 2048);
else if (DISPLAY_VER(display) >= 8)
-   lines = min(lines, 2560);
+   height = min(height, 2560);
 
-   return lines * intel_fbc_cfb_stride(plane_state);
+   return height * intel_fbc_cfb_stride(plane_state);
 }
 
 static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state 
*plane_state)
-- 
2.44.2



[PATCH 08/20] drm/i915/fbc: Extract _intel_fbc_cfb_stride()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Pull the lower level stuff out from intel_fbc_cfb_stride() into
a separate function that doesn't depend on the plane_state.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 22 ++
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 5ba3d8797243..4a9321f5218f 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -149,12 +149,11 @@ static unsigned int intel_fbc_plane_cfb_stride(const 
struct intel_plane_state *p
 }
 
 /* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */
-static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state 
*plane_state)
+static unsigned int skl_fbc_min_cfb_stride(struct intel_display *display,
+  unsigned int width)
 {
-   struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
unsigned int limit = 4; /* 1:4 compression limit is the worst case */
unsigned int cpp = 4; /* FBC always 4 bytes per pixel */
-   unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16;
unsigned int height = 4; /* FBC segment is 4 lines */
unsigned int stride;
 
@@ -179,22 +178,29 @@ static unsigned int skl_fbc_min_cfb_stride(const struct 
intel_plane_state *plane
 }
 
 /* properly aligned cfb stride in bytes, assuming 1:1 compression limit */
-static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state 
*plane_state)
+static unsigned int _intel_fbc_cfb_stride(struct intel_display *display,
+ unsigned int width, unsigned int 
stride)
 {
-   struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
-   unsigned int stride = intel_fbc_plane_cfb_stride(plane_state);
-
/*
 * At least some of the platforms require each 4 line segment to
 * be 512 byte aligned. Aligning each line to 512 bytes guarantees
 * that regardless of the compression limit we choose later.
 */
if (DISPLAY_VER(display) >= 9)
-   return max(ALIGN(stride, 512), 
skl_fbc_min_cfb_stride(plane_state));
+   return max(ALIGN(stride, 512), skl_fbc_min_cfb_stride(display, 
width));
else
return stride;
 }
 
+static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state 
*plane_state)
+{
+   struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
+   unsigned int stride = intel_fbc_plane_cfb_stride(plane_state);
+   unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16;
+
+   return _intel_fbc_cfb_stride(display, width, stride);
+}
+
 static unsigned int intel_fbc_cfb_size(const struct intel_plane_state 
*plane_state)
 {
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
-- 
2.44.2



[PATCH 07/20] drm/i915/fbc: Adjust g4x+ platform checks

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Do the "is this ilk+ or g4x" checks in the customary order instead
of the reverse order. Easier for the poor brain to parse this
when it's always done the same way.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 40a3b4937dc5..5ba3d8797243 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -1087,7 +1087,7 @@ static void intel_fbc_max_surface_size(struct 
intel_display *display,
} else if (DISPLAY_VER(display) >= 7) {
*w = 4096;
*h = 4096;
-   } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) {
+   } else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) {
*w = 4096;
*h = 2048;
} else {
@@ -1128,7 +1128,7 @@ static void intel_fbc_max_plane_size(struct intel_display 
*display,
} else if (DISPLAY_VER(display) >= 8 || IS_HASWELL(i915)) {
*w = 4096;
*h = 4096;
-   } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) {
+   } else if (DISPLAY_VER(display) >= 5 || IS_G4X(i915)) {
*w = 4096;
*h = 2048;
} else {
-- 
2.44.2



[PATCH 06/20] drm/i915/fbc: s/intel_fbc_hw_tracking_covers_screen()/intel_fbc_surface_size_ok()/

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Rename intel_fbc_hw_tracking_covers_screen() to intel_fbc_surface_size_ok()
so that the naming scheme is the same for the surface size vs. plane
size checks. "surface size" is what bspec talks about.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index c7fd774440a8..40a3b4937dc5 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -1102,7 +1102,7 @@ static void intel_fbc_max_surface_size(struct 
intel_display *display,
  * the X and Y offset registers. That's why we include the src x/y offsets
  * instead of just looking at the plane size.
  */
-static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state 
*plane_state)
+static bool intel_fbc_surface_size_ok(const struct intel_plane_state 
*plane_state)
 {
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
unsigned int effective_w, effective_h, max_w, max_h;
@@ -1354,7 +1354,7 @@ static int intel_fbc_check_plane(struct 
intel_atomic_state *state,
return 0;
}
 
-   if (!intel_fbc_hw_tracking_covers_screen(plane_state)) {
+   if (!intel_fbc_surface_size_ok(plane_state)) {
plane_state->no_fbc_reason = "surface size too big";
return 0;
}
-- 
2.44.2



[PATCH 05/20] drm/i915/fbc: Extract intel_fbc_max_surface_size()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Extract intel_fbc_max_surface_size() from
intel_fbc_hw_tracking_covers_screen(), mainly to mirror the
"max plane size" counterparts.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 41 ++--
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 08a431cfbbb3..c7fd774440a8 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -1073,6 +1073,29 @@ static bool rotation_is_valid(const struct 
intel_plane_state *plane_state)
return i8xx_fbc_rotation_is_valid(plane_state);
 }
 
+static void intel_fbc_max_surface_size(struct intel_display *display,
+  unsigned int *w, unsigned int *h)
+{
+   struct drm_i915_private *i915 = to_i915(display->drm);
+
+   if (DISPLAY_VER(display) >= 11) {
+   *w = 8192;
+   *h = 4096;
+   } else if (DISPLAY_VER(display) >= 10) {
+   *w = 5120;
+   *h = 4096;
+   } else if (DISPLAY_VER(display) >= 7) {
+   *w = 4096;
+   *h = 4096;
+   } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) {
+   *w = 4096;
+   *h = 2048;
+   } else {
+   *w = 2048;
+   *h = 1536;
+   }
+}
+
 /*
  * For some reason, the hardware tracking starts looking at whatever we
  * programmed as the display plane base address register. It does not look at
@@ -1082,25 +1105,9 @@ static bool rotation_is_valid(const struct 
intel_plane_state *plane_state)
 static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state 
*plane_state)
 {
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
-   struct drm_i915_private *i915 = to_i915(display->drm);
unsigned int effective_w, effective_h, max_w, max_h;
 
-   if (DISPLAY_VER(display) >= 11) {
-   max_w = 8192;
-   max_h = 4096;
-   } else if (DISPLAY_VER(display) >= 10) {
-   max_w = 5120;
-   max_h = 4096;
-   } else if (DISPLAY_VER(display) >= 7) {
-   max_w = 4096;
-   max_h = 4096;
-   } else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) {
-   max_w = 4096;
-   max_h = 2048;
-   } else {
-   max_w = 2048;
-   max_h = 1536;
-   }
+   intel_fbc_max_surface_size(display, &max_w, &max_h);
 
effective_w = plane_state->view.color_plane[0].x +
(drm_rect_width(&plane_state->uapi.src) >> 16);
-- 
2.44.2



[PATCH 03/20] drm/i915/fbc: s/_intel_fbc_cfb_stride()/intel_fbc_plane_cfb_stride()/

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

_intel_fbc_cfb_stride() calculates the CFB stride the hardware would
automagically generate from the plane's stride. Rename the function
to intel_fbc_plane_cfb_stride() to better reflect its purpose.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index de8caa69a0dd..8f3b8f2cbf7b 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -141,7 +141,7 @@ static unsigned int intel_fbc_plane_stride(const struct 
intel_plane_state *plane
 }
 
 /* plane stride based cfb stride in bytes, assuming 1:1 compression limit */
-static unsigned int _intel_fbc_cfb_stride(const struct intel_plane_state 
*plane_state)
+static unsigned int intel_fbc_plane_cfb_stride(const struct intel_plane_state 
*plane_state)
 {
unsigned int cpp = 4; /* FBC always 4 bytes per pixel */
 
@@ -182,7 +182,7 @@ static unsigned int skl_fbc_min_cfb_stride(const struct 
intel_plane_state *plane
 static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state 
*plane_state)
 {
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
-   unsigned int stride = _intel_fbc_cfb_stride(plane_state);
+   unsigned int stride = intel_fbc_plane_cfb_stride(plane_state);
 
/*
 * At least some of the platforms require each 4 line segment to
@@ -212,7 +212,7 @@ static u16 intel_fbc_override_cfb_stride(const struct 
intel_plane_state *plane_s
 {
struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
unsigned int stride_aligned = intel_fbc_cfb_stride(plane_state);
-   unsigned int stride = _intel_fbc_cfb_stride(plane_state);
+   unsigned int stride = intel_fbc_plane_cfb_stride(plane_state);
const struct drm_framebuffer *fb = plane_state->hw.fb;
 
/*
-- 
2.44.2



[PATCH 04/20] drm/i915/fbc: Extract intel_fbc_max_plane_size()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Extract intel_fbc_max_plane_size() from intel_fbc_plane_size_valid().
We'll have another use for this soon in determining how much stolen
memory we'd like to keep reserved for FBC.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 29 +++-
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 8f3b8f2cbf7b..08a431cfbbb3 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -1110,25 +1110,32 @@ static bool intel_fbc_hw_tracking_covers_screen(const 
struct intel_plane_state *
return effective_w <= max_w && effective_h <= max_h;
 }
 
-static bool intel_fbc_plane_size_valid(const struct intel_plane_state 
*plane_state)
+static void intel_fbc_max_plane_size(struct intel_display *display,
+unsigned int *w, unsigned int *h)
 {
-   struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
struct drm_i915_private *i915 = to_i915(display->drm);
-   unsigned int w, h, max_w, max_h;
 
if (DISPLAY_VER(display) >= 10) {
-   max_w = 5120;
-   max_h = 4096;
+   *w = 5120;
+   *h = 4096;
} else if (DISPLAY_VER(display) >= 8 || IS_HASWELL(i915)) {
-   max_w = 4096;
-   max_h = 4096;
+   *w = 4096;
+   *h = 4096;
} else if (IS_G4X(i915) || DISPLAY_VER(display) >= 5) {
-   max_w = 4096;
-   max_h = 2048;
+   *w = 4096;
+   *h = 2048;
} else {
-   max_w = 2048;
-   max_h = 1536;
+   *w = 2048;
+   *h = 1536;
}
+}
+
+static bool intel_fbc_plane_size_valid(const struct intel_plane_state 
*plane_state)
+{
+   struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
+   unsigned int w, h, max_w, max_h;
+
+   intel_fbc_max_plane_size(display, &max_w, &max_h);
 
w = drm_rect_width(&plane_state->uapi.src) >> 16;
h = drm_rect_height(&plane_state->uapi.src) >> 16;
-- 
2.44.2



[PATCH 02/20] drm/i915/fbc: Convert to intel_display, mostly

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Switch the FBC code over to intel_display from i915, as
much as possible. This is the future direction so that
the display code can be shared between i915 and xe more
cleanly.

Some of the platform checks and the stolen mem facing stiff
still need i915 around though.

Signed-off-by: Ville Syrjälä 
---
 .../drm/i915/display/intel_display_debugfs.c  |   4 +-
 .../drm/i915/display/intel_display_driver.c   |   4 +-
 drivers/gpu/drm/i915/display/intel_fbc.c  | 422 ++
 drivers/gpu/drm/i915/display/intel_fbc.h  |  13 +-
 .../drm/i915/display/intel_fifo_underrun.c|   2 +-
 .../drm/i915/display/intel_modeset_setup.c|   2 +-
 6 files changed, 239 insertions(+), 208 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c 
b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 91757fed9c6d..5cf9b4af9adf 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -1008,7 +1008,7 @@ i915_fifo_underrun_reset_write(struct file *filp,
return ret;
}
 
-   intel_fbc_reset_underrun(dev_priv);
+   intel_fbc_reset_underrun(&dev_priv->display);
 
return cnt;
 }
@@ -1063,7 +1063,7 @@ void intel_display_debugfs_register(struct 
drm_i915_private *i915)
intel_bios_debugfs_register(i915);
intel_cdclk_debugfs_register(i915);
intel_dmc_debugfs_register(i915);
-   intel_fbc_debugfs_register(i915);
+   intel_fbc_debugfs_register(&i915->display);
intel_hpd_debugfs_register(i915);
intel_opregion_debugfs_register(i915);
intel_psr_debugfs_register(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c 
b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 794b4af38055..13e206ec450f 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -265,7 +265,7 @@ int intel_display_driver_probe_noirq(struct 
drm_i915_private *i915)
 
intel_init_quirks(display);
 
-   intel_fbc_init(i915);
+   intel_fbc_init(display);
 
return 0;
 
@@ -607,7 +607,7 @@ void intel_display_driver_remove_noirq(struct 
drm_i915_private *i915)
destroy_workqueue(i915->display.wq.flip);
destroy_workqueue(i915->display.wq.modeset);
 
-   intel_fbc_cleanup(i915);
+   intel_fbc_cleanup(&i915->display);
 }
 
 /* part #3: call after gem init */
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index ba9820d4b78f..de8caa69a0dd 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -61,13 +61,13 @@
 #include "intel_fbc_regs.h"
 #include "intel_frontbuffer.h"
 
-#define for_each_fbc_id(__dev_priv, __fbc_id) \
+#define for_each_fbc_id(__display, __fbc_id) \
for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; 
(__fbc_id)++) \
-   for_each_if(DISPLAY_RUNTIME_INFO(__dev_priv)->fbc_mask & 
BIT(__fbc_id))
+   for_each_if(DISPLAY_RUNTIME_INFO(__display)->fbc_mask & 
BIT(__fbc_id))
 
-#define for_each_intel_fbc(__dev_priv, __fbc, __fbc_id) \
-   for_each_fbc_id((__dev_priv), (__fbc_id)) \
-   for_each_if((__fbc) = (__dev_priv)->display.fbc[(__fbc_id)])
+#define for_each_intel_fbc(__display, __fbc, __fbc_id) \
+   for_each_fbc_id((__display), (__fbc_id)) \
+   for_each_if((__fbc) = (__display)->fbc[(__fbc_id)])
 
 struct intel_fbc_funcs {
void (*activate)(struct intel_fbc *fbc);
@@ -90,7 +90,7 @@ struct intel_fbc_state {
 };
 
 struct intel_fbc {
-   struct drm_i915_private *i915;
+   struct intel_display *display;
const struct intel_fbc_funcs *funcs;
 
/*
@@ -151,7 +151,7 @@ static unsigned int _intel_fbc_cfb_stride(const struct 
intel_plane_state *plane_
 /* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */
 static unsigned int skl_fbc_min_cfb_stride(const struct intel_plane_state 
*plane_state)
 {
-   struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
+   struct intel_display *display = 
to_intel_display(plane_state->uapi.plane->dev);
unsigned int limit = 4; /* 1:4 compression limit is the worst case */
unsigned int cpp = 4; /* FBC always 4 bytes per pixel */
unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16;
@@ -165,7 +165,7 @@ static unsigned int skl_fbc_min_cfb_stride(const struct 
intel_plane_state *plane
 * Wa_16011863758: icl+
 * Avoid some hardware segment address miscalculation.
 */
-   if (DISPLAY_VER(i915) >= 11)
+   if (DISPLAY_VER(display) >= 11)
stride += 64;
 
/*
@@ -181,7 +181,7 @@ static unsigned int skl_fbc_min_cfb_stride(const struct 
intel_plane_state *plane
 /* properly aligned cfb stride in bytes, assuming 1:1 compression limit */
 static u

[PATCH 01/20] drm/i915/fbc: Extract intel_fbc_has_fences()

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Pull the "do we have fences?" check into a single helper in the FBC
code. Avoids having to call to outside the display code in multiple
places for this.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fbc.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
b/drivers/gpu/drm/i915/display/intel_fbc.c
index 8488f82143a4..ba9820d4b78f 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -229,6 +229,11 @@ static u16 intel_fbc_override_cfb_stride(const struct 
intel_plane_state *plane_s
return 0;
 }
 
+static bool intel_fbc_has_fences(struct drm_i915_private *i915)
+{
+   return intel_gt_support_legacy_fencing(to_gt(i915));
+}
+
 static u32 i8xx_fbc_ctl(struct intel_fbc *fbc)
 {
const struct intel_fbc_state *fbc_state = &fbc->state;
@@ -620,7 +625,7 @@ static void ivb_fbc_activate(struct intel_fbc *fbc)
else if (DISPLAY_VER(i915) == 9)
skl_fbc_program_cfb_stride(fbc);
 
-   if (intel_gt_support_legacy_fencing(to_gt(i915)))
+   if (intel_fbc_has_fences(i915))
snb_fbc_program_fence(fbc);
 
/* wa_14019417088 Alternative WA*/
@@ -1154,7 +1159,7 @@ static void intel_fbc_update_state(struct 
intel_atomic_state *state,
fbc_state->fence_y_offset = intel_plane_fence_y_offset(plane_state);
 
drm_WARN_ON(&i915->drm, plane_state->flags & PLANE_HAS_FENCE &&
-   !intel_gt_support_legacy_fencing(to_gt(i915)));
+   !intel_fbc_has_fences(i915));
 
if (plane_state->flags & PLANE_HAS_FENCE)
fbc_state->fence_id =  i915_vma_fence_id(plane_state->ggtt_vma);
-- 
2.44.2



[PATCH 00/20] drm/{i915, xe}: FBC cleanups + tweak fbdev stolen usage

2024-07-05 Thread Ville Syrjala
From: Ville Syrjälä 

Here's an idea for a slightly better heuristic to answer
the "should fbdev use stolen or not?" question.

Ended up with a pile of refactoring and cleanups in
the FBC code as a result.

Ville Syrjälä (20):
  drm/i915/fbc: Extract intel_fbc_has_fences()
  drm/i915/fbc: Convert to intel_display, mostly
  drm/i915/fbc: s/_intel_fbc_cfb_stride()/intel_fbc_plane_cfb_stride()/
  drm/i915/fbc: Extract intel_fbc_max_plane_size()
  drm/i915/fbc: Extract intel_fbc_max_surface_size()
  drm/i915/fbc:
s/intel_fbc_hw_tracking_covers_screen()/intel_fbc_surface_size_ok()/
  drm/i915/fbc: Adjust g4x+ platform checks
  drm/i915/fbc: Extract _intel_fbc_cfb_stride()
  drm/i915/fbc: s/lines/height/
  drm/i915/fbc: Reoder CFB max height platform checks
  drm/i915/fbc: Extract intel_fbc_max_cfb_height()
  drm/i915/fbc: Extract _intel_fbc_cfb_size()
  drm/i915/fbc: Extract intel_fbc_cfb_cpp()
  drm/i915/fbc: Introduce intel_fbc_preferred_cfb_size()
  drm/xe/fbdev: Fix BIOS FB vs.s stolen size checke
  drm/i915/fbdev: Extract intel_fbdev_fb_prefer_stolen()
  drm/xe/fbdev: Extract intel_fbdev_fb_prefer_stolen()
  drm/xe/fbdev: Use the same logic for fbdev stolen takever and fresh
allocation
  drm/i915/fbdev: Adjust fbdev stolen mem usage heuristic
  drm/xe/fbdev: Adjust fbdev stolen mem usage heuristic

 .../drm/i915/display/intel_display_debugfs.c  |   4 +-
 .../drm/i915/display/intel_display_driver.c   |   4 +-
 drivers/gpu/drm/i915/display/intel_fbc.c  | 564 ++
 drivers/gpu/drm/i915/display/intel_fbc.h  |  14 +-
 drivers/gpu/drm/i915/display/intel_fbdev_fb.c |  23 +-
 drivers/gpu/drm/i915/display/intel_fbdev_fb.h |   5 +-
 .../drm/i915/display/intel_fifo_underrun.c|   2 +-
 .../drm/i915/display/intel_modeset_setup.c|   2 +-
 .../drm/i915/display/intel_plane_initial.c|  10 +-
 drivers/gpu/drm/xe/display/intel_fbdev_fb.c   |  22 +-
 drivers/gpu/drm/xe/display/xe_plane_initial.c |   8 +-
 11 files changed, 389 insertions(+), 269 deletions(-)

-- 
2.44.2



[PATCH v2 03/14] drm/i915/dsb: Hook up DSB error interrupts

2024-06-25 Thread Ville Syrjala
From: Ville Syrjälä 

Enable all DSB error/fault interrupts so that we can see if
anything goes terribly wrong.

v2: Pass intel_display to DISPLAY_VER() (Jani)
Drop extra '/' from drm_err() for consistency

Cc: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 .../gpu/drm/i915/display/intel_display_irq.c  | 17 ++
 drivers/gpu/drm/i915/display/intel_dsb.c  | 56 +++
 drivers/gpu/drm/i915/display/intel_dsb.h  |  6 ++
 drivers/gpu/drm/i915/i915_reg.h   |  4 ++
 4 files changed, 83 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c 
b/drivers/gpu/drm/i915/display/intel_display_irq.c
index 5219ba295c74..7169db984651 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -14,6 +14,7 @@
 #include "intel_display_trace.h"
 #include "intel_display_types.h"
 #include "intel_dp_aux.h"
+#include "intel_dsb.h"
 #include "intel_fdi_regs.h"
 #include "intel_fifo_underrun.h"
 #include "intel_gmbus.h"
@@ -1143,6 +1144,17 @@ void gen8_de_irq_handler(struct drm_i915_private 
*dev_priv, u32 master_ctl)
 
intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), 
iir);
 
+   if (HAS_DSB(dev_priv)) {
+   if (iir & GEN12_DSB_INT(INTEL_DSB_0))
+   intel_dsb_irq_handler(&dev_priv->display, pipe, 
INTEL_DSB_0);
+
+   if (iir & GEN12_DSB_INT(INTEL_DSB_1))
+   intel_dsb_irq_handler(&dev_priv->display, pipe, 
INTEL_DSB_1);
+
+   if (iir & GEN12_DSB_INT(INTEL_DSB_2))
+   intel_dsb_irq_handler(&dev_priv->display, pipe, 
INTEL_DSB_2);
+   }
+
if (iir & GEN8_PIPE_VBLANK)
intel_handle_vblank(dev_priv, pipe);
 
@@ -1718,6 +1730,11 @@ void gen8_de_irq_postinstall(struct drm_i915_private 
*dev_priv)
de_port_masked |= DSI0_TE | DSI1_TE;
}
 
+   if (HAS_DSB(dev_priv))
+   de_pipe_masked |= GEN12_DSB_INT(INTEL_DSB_0) |
+   GEN12_DSB_INT(INTEL_DSB_1) |
+   GEN12_DSB_INT(INTEL_DSB_2);
+
de_pipe_enables = de_pipe_masked |
GEN8_PIPE_VBLANK |
gen8_de_pipe_underrun_mask(dev_priv) |
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 2ab3765f6c06..3453989728aa 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -339,6 +339,40 @@ static u32 dsb_chicken(struct intel_crtc *crtc)
return DSB_SKIP_WAITS_EN;
 }
 
+static u32 dsb_error_int_status(struct intel_display *display)
+{
+   u32 errors;
+
+   errors = DSB_GTT_FAULT_INT_STATUS |
+   DSB_RSPTIMEOUT_INT_STATUS |
+   DSB_POLL_ERR_INT_STATUS;
+
+   /*
+* All the non-existing status bits operate as
+* normal r/w bits, so any attempt to clear them
+* will just end up setting them. Never do that so
+* we won't mistake them for actual error interrupts.
+*/
+   if (DISPLAY_VER(display) >= 14)
+   errors |= DSB_ATS_FAULT_INT_STATUS;
+
+   return errors;
+}
+
+static u32 dsb_error_int_en(struct intel_display *display)
+{
+   u32 errors;
+
+   errors = DSB_GTT_FAULT_INT_EN |
+   DSB_RSPTIMEOUT_INT_EN |
+   DSB_POLL_ERR_INT_EN;
+
+   if (DISPLAY_VER(display) >= 14)
+   errors |= DSB_ATS_FAULT_INT_EN;
+
+   return errors;
+}
+
 static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
  int dewake_scanline)
 {
@@ -363,6 +397,10 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 
ctrl,
intel_de_write_fw(display, DSB_CHICKEN(pipe, dsb->id),
  dsb_chicken(crtc));
 
+   intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id),
+ dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
+ dsb_error_int_en(display));
+
intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id),
  intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf));
 
@@ -430,6 +468,9 @@ void intel_dsb_wait(struct intel_dsb *dsb)
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
intel_de_write_fw(display, DSB_CTRL(pipe, dsb->id), 0);
+
+   intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id),
+ dsb_error_int_status(display) | DSB_PROG_INT_STATUS);
 }
 
 /**
@@ -513,3 +554,18 @@ void intel_dsb_cleanup(struct intel_dsb *dsb)
intel_dsb_buffer_cleanup(&dsb->dsb_buf);
kfree(dsb);
 }
+
+void intel_dsb_irq_handler(struct intel_display *display,
+  enum pipe pipe, enum intel_dsb_id dsb_id)
+{
+   struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(display->drm), 
pipe);
+   u32 tmp, errors

[PATCH 14/14] drm/i915/dsb: Use chained DSBs for LUT programming

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

In order to better handle the necessary DSB DEwake tricks let's
switch over to using a chained DSB for the actual LUT programming.
The CPU will start 'dsb_color_commit', which in turn will start the
chained 'dsb_color_vblank'.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_atomic.c   |  2 ++
 drivers/gpu/drm/i915/display/intel_color.c| 32 +++
 drivers/gpu/drm/i915/display/intel_display.c  |  1 +
 .../drm/i915/display/intel_display_types.h|  2 +-
 4 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index 55ce71be41ec..12d6ed940751 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -277,6 +277,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->fb_bits = 0;
crtc_state->update_planes = 0;
crtc_state->dsb_color_vblank = NULL;
+   crtc_state->dsb_color_commit = NULL;
 
return &crtc_state->uapi;
 }
@@ -311,6 +312,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
struct intel_crtc_state *crtc_state = to_intel_crtc_state(state);
 
drm_WARN_ON(crtc->dev, crtc_state->dsb_color_vblank);
+   drm_WARN_ON(crtc->dev, crtc_state->dsb_color_commit);
 
__drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);
intel_crtc_free_hw_state(crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_color.c 
b/drivers/gpu/drm/i915/display/intel_color.c
index 27acbf92d60f..5d701f48351b 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -1890,8 +1890,8 @@ void intel_color_commit_arm(const struct intel_crtc_state 
*crtc_state)
 
i915->display.funcs.color->color_commit_arm(crtc_state);
 
-   if (crtc_state->dsb_color_vblank)
-   intel_dsb_commit(crtc_state->dsb_color_vblank, true);
+   if (crtc_state->dsb_color_commit)
+   intel_dsb_commit(crtc_state->dsb_color_commit, false);
 }
 
 void intel_color_post_update(const struct intel_crtc_state *crtc_state)
@@ -1919,26 +1919,44 @@ void intel_color_prepare_commit(struct 
intel_atomic_state *state,
if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut)
return;
 
-   crtc_state->dsb_color_vblank = intel_dsb_prepare(state, crtc, 
INTEL_DSB_0, 1024);
+   crtc_state->dsb_color_vblank = intel_dsb_prepare(state, crtc, 
INTEL_DSB_1, 1024);
if (!crtc_state->dsb_color_vblank)
return;
 
i915->display.funcs.color->load_luts(crtc_state);
 
intel_dsb_finish(crtc_state->dsb_color_vblank);
+
+   crtc_state->dsb_color_commit = intel_dsb_prepare(state, crtc, 
INTEL_DSB_0, 16);
+   if (!crtc_state->dsb_color_commit) {
+   intel_dsb_cleanup(crtc_state->dsb_color_vblank);
+   crtc_state->dsb_color_vblank = NULL;
+   return;
+   }
+
+   intel_dsb_chain(state, crtc_state->dsb_color_commit,
+   crtc_state->dsb_color_vblank, true);
+
+   intel_dsb_finish(crtc_state->dsb_color_commit);
 }
 
 void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
 {
-   if (!crtc_state->dsb_color_vblank)
-   return;
+   if (crtc_state->dsb_color_commit) {
+   intel_dsb_cleanup(crtc_state->dsb_color_commit);
+   crtc_state->dsb_color_commit = NULL;
+   }
 
-   intel_dsb_cleanup(crtc_state->dsb_color_vblank);
-   crtc_state->dsb_color_vblank = NULL;
+   if (crtc_state->dsb_color_vblank) {
+   intel_dsb_cleanup(crtc_state->dsb_color_vblank);
+   crtc_state->dsb_color_vblank = NULL;
+   }
 }
 
 void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
 {
+   if (crtc_state->dsb_color_commit)
+   intel_dsb_wait(crtc_state->dsb_color_commit);
if (crtc_state->dsb_color_vblank)
intel_dsb_wait(crtc_state->dsb_color_vblank);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 05a2a6942000..d5e0fa5c78b5 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7511,6 +7511,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
 * FIXME get rid of this funny new->old swapping
 */
old_crtc_state->dsb_color_vblank = 
fetch_and_zero(&new_crtc_state->dsb_color_vblank);
+   old_crtc_state->dsb_color_commit = 
fetch_and_zero(&new_crtc_state->dsb_color_commit);
}
 
/* Underruns don't always raise interrupts, so check manually */
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index bd079cd77bda..f22de0495dd7 100644
--- a/drivers/gpu/drm/i915/display/intel_

[PATCH 13/14] drm/i915/dsb: s/dsb/dsb_color_vblank/

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

We'll soon utilize several DSBs during the commit. To that end
rename the current crtc_state->dsb to crtc_state->dsb_color_vblank
to better reflect its role (color managemnent stuff programmed during
vblank).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_atomic.c   |  4 +--
 drivers/gpu/drm/i915/display/intel_color.c| 36 +--
 drivers/gpu/drm/i915/display/intel_display.c  |  2 +-
 .../drm/i915/display/intel_display_types.h|  4 +--
 4 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c 
b/drivers/gpu/drm/i915/display/intel_atomic.c
index 76aa10b6f647..55ce71be41ec 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -276,7 +276,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->do_async_flip = false;
crtc_state->fb_bits = 0;
crtc_state->update_planes = 0;
-   crtc_state->dsb = NULL;
+   crtc_state->dsb_color_vblank = NULL;
 
return &crtc_state->uapi;
 }
@@ -310,7 +310,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
 {
struct intel_crtc_state *crtc_state = to_intel_crtc_state(state);
 
-   drm_WARN_ON(crtc->dev, crtc_state->dsb);
+   drm_WARN_ON(crtc->dev, crtc_state->dsb_color_vblank);
 
__drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);
intel_crtc_free_hw_state(crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_color.c 
b/drivers/gpu/drm/i915/display/intel_color.c
index 7ac50aacec73..27acbf92d60f 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -1313,8 +1313,8 @@ static void ilk_lut_write(const struct intel_crtc_state 
*crtc_state,
 {
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
 
-   if (crtc_state->dsb)
-   intel_dsb_reg_write(crtc_state->dsb, reg, val);
+   if (crtc_state->dsb_color_vblank)
+   intel_dsb_reg_write(crtc_state->dsb_color_vblank, reg, val);
else
intel_de_write_fw(i915, reg, val);
 }
@@ -1337,15 +1337,15 @@ static void ilk_load_lut_8(const struct 
intel_crtc_state *crtc_state,
 * unless we either write each entry twice,
 * or use non-posted writes
 */
-   if (crtc_state->dsb)
-   intel_dsb_nonpost_start(crtc_state->dsb);
+   if (crtc_state->dsb_color_vblank)
+   intel_dsb_nonpost_start(crtc_state->dsb_color_vblank);
 
for (i = 0; i < 256; i++)
ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
  i9xx_lut_8(&lut[i]));
 
-   if (crtc_state->dsb)
-   intel_dsb_nonpost_end(crtc_state->dsb);
+   if (crtc_state->dsb_color_vblank)
+   intel_dsb_nonpost_end(crtc_state->dsb_color_vblank);
 }
 
 static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state,
@@ -1870,7 +1870,7 @@ void intel_color_load_luts(const struct intel_crtc_state 
*crtc_state)
 {
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
 
-   if (crtc_state->dsb)
+   if (crtc_state->dsb_color_vblank)
return;
 
i915->display.funcs.color->load_luts(crtc_state);
@@ -1890,8 +1890,8 @@ void intel_color_commit_arm(const struct intel_crtc_state 
*crtc_state)
 
i915->display.funcs.color->color_commit_arm(crtc_state);
 
-   if (crtc_state->dsb)
-   intel_dsb_commit(crtc_state->dsb, true);
+   if (crtc_state->dsb_color_vblank)
+   intel_dsb_commit(crtc_state->dsb_color_vblank, true);
 }
 
 void intel_color_post_update(const struct intel_crtc_state *crtc_state)
@@ -1919,33 +1919,33 @@ void intel_color_prepare_commit(struct 
intel_atomic_state *state,
if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut)
return;
 
-   crtc_state->dsb = intel_dsb_prepare(state, crtc, INTEL_DSB_0, 1024);
-   if (!crtc_state->dsb)
+   crtc_state->dsb_color_vblank = intel_dsb_prepare(state, crtc, 
INTEL_DSB_0, 1024);
+   if (!crtc_state->dsb_color_vblank)
return;
 
i915->display.funcs.color->load_luts(crtc_state);
 
-   intel_dsb_finish(crtc_state->dsb);
+   intel_dsb_finish(crtc_state->dsb_color_vblank);
 }
 
 void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
 {
-   if (!crtc_state->dsb)
+   if (!crtc_state->dsb_color_vblank)
return;
 
-   intel_dsb_cleanup(crtc_state->dsb);
-   crtc_state->dsb = NULL;
+   intel_dsb_cleanup(crtc_state->dsb_color_vblank);
+   crtc_state->dsb_color_vblank = NULL;
 }
 
 void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
 {
-   if (crtc_state->dsb)
-   intel_dsb_wait(crtc_state->dsb);
+   if (crtc_state->dsb_color_vblank)
+   intel_dsb_wait(crtc_state->dsb_color_vblank);
 }
 
 bool 

[PATCH 10/14] drm/i915/dsb: Introduce intel_dsb_chain()

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

In order to handle the DEwake tricks without involving
the CPU we need a mechanism by which one DSB can start
another one. Add a basic function to do so. We'll extend
it later with additional code to actually deal with
DEwake.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 42 
 drivers/gpu/drm/i915/display/intel_dsb.h |  3 ++
 2 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 092cf082ac39..4c0519c41f16 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -502,6 +502,48 @@ static u32 dsb_error_int_en(struct intel_display *display)
return errors;
 }
 
+static void _intel_dsb_chain(struct intel_atomic_state *state,
+struct intel_dsb *dsb,
+struct intel_dsb *chained_dsb,
+u32 ctrl)
+{
+   struct intel_display *display = to_intel_display(state->base.dev);
+   struct intel_crtc *crtc = dsb->crtc;
+   enum pipe pipe = crtc->pipe;
+   u32 tail;
+
+   if (drm_WARN_ON(display->drm, dsb->id == chained_dsb->id))
+   return;
+
+   tail = chained_dsb->free_pos * 4;
+   if (drm_WARN_ON(display->drm, !IS_ALIGNED(tail, CACHELINE_BYTES)))
+   return;
+
+   intel_dsb_reg_write(dsb, DSB_CTRL(pipe, chained_dsb->id),
+   ctrl | DSB_ENABLE);
+
+   intel_dsb_reg_write(dsb, DSB_CHICKEN(pipe, chained_dsb->id),
+   dsb_chicken(state, crtc));
+
+   intel_dsb_reg_write(dsb, DSB_INTERRUPT(pipe, chained_dsb->id),
+   dsb_error_int_status(display) | DSB_PROG_INT_STATUS 
|
+   dsb_error_int_en(display));
+
+   intel_dsb_reg_write(dsb, DSB_HEAD(pipe, chained_dsb->id),
+   
intel_dsb_buffer_ggtt_offset(&chained_dsb->dsb_buf));
+
+   intel_dsb_reg_write(dsb, DSB_TAIL(pipe, chained_dsb->id),
+   intel_dsb_buffer_ggtt_offset(&chained_dsb->dsb_buf) 
+ tail);
+}
+
+void intel_dsb_chain(struct intel_atomic_state *state,
+struct intel_dsb *dsb,
+struct intel_dsb *chained_dsb)
+{
+   _intel_dsb_chain(state, dsb, chained_dsb,
+0);
+}
+
 static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
  int hw_dewake_scanline)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h 
b/drivers/gpu/drm/i915/display/intel_dsb.h
index d0737cefb393..e59fd7da0fc0 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -45,6 +45,9 @@ void intel_dsb_wait_scanline_in(struct intel_atomic_state 
*state,
 void intel_dsb_wait_scanline_out(struct intel_atomic_state *state,
 struct intel_dsb *dsb,
 int lower, int upper);
+void intel_dsb_chain(struct intel_atomic_state *state,
+struct intel_dsb *dsb,
+struct intel_dsb *chained_dsb);
 
 void intel_dsb_commit(struct intel_dsb *dsb,
  bool wait_for_vblank);
-- 
2.44.2



[PATCH 12/14] drm/i915/dsb: Clear DSB_ENABLE_DEWAKE once the DSB is done

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

In order to avoid the DSB keeping the DEwake permanently
asserted we must clear DSB_PMCTRL_2.DSB_FORCE_DEWAKE once
we are done. For good measure do the same for
DSB_PMCTRL.DSB_ENABLE_DEWAKE.

Experimentally this doens't seem to be actually necessary
(unlike with DSB_FORCE_DEWAKE). That is, the DSB_ENABLE_DEWAKE
doesn't seem to do anything whenever the DSB is not active.
But I'd hate to waste a ton of power in case there I'm wrong
and there is some way DEwake could remaing asserted. One extra
register write is a small price to pay for some peace of mind.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index cf710f0bf430..fad37e7856b1 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -464,8 +464,10 @@ void intel_dsb_finish(struct intel_dsb *dsb)
/*
 * DSB_FORCE_DEWAKE remains active even after DSB is
 * disabled, so make sure to clear it (if set during
-* intel_dsb_commit()).
+* intel_dsb_commit()). And clear DSB_ENABLE_DEWAKE as
+* well for good measure.
 */
+   intel_dsb_reg_write(dsb, DSB_PMCTRL(crtc->pipe, dsb->id), 0);
intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id),
   DSB_FORCE_DEWAKE, 0);
 
-- 
2.44.2



[PATCH 11/14] drm/i915/dsb: Allow intel_dsb_chain() to use DSB_WAIT_FOR_VBLANK

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Allow intel_dsb_chain() to start the chained DSB
at start of the undelaye vblank. This is slightly
more involved than simply setting the bit as we
must use the DEwake mechanism to eliminate pkgC
latency.

And DSB_ENABLE_DEWAKE itself is problematic in that
it allows us to configure just a single scanline,
and if the current scanline is already past that
DSB_ENABLE_DEWAKE won't do anything, rendering the
whole thing moot.

The current workaround involves checking the pipe's current
scanline with the CPU, and if it looks like we're about to
miss the configured DEwake scanline we set DSB_FORCE_DEWAKE
to immediately assert DEwake. This is somewhat racy since the
hardware is making progress all the while we're checking it on
the CPU.

We can make things less racy by chaining two DSBs and handling
the DSB_FORCE_DEWAKE stuff entirely without CPU involvement:
1. CPU starts the first DSB immediately
2. First DSB configures the second DSB, including its dewake_scanline
3. First DSB starts the second w/ DSB_WAIT_FOR_VBLANK
4. First DSB asserts DSB_FORCE_DEWAKE
5. First DSB waits until we're outside the dewake_scanline-vblank_start
   window
6. First DSB deasserts DSB_FORCE_DEWAKE

That will guarantee that the we are fully awake when the second
DSB starts to actually execute.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 43 +---
 drivers/gpu/drm/i915/display/intel_dsb.h |  3 +-
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 4c0519c41f16..cf710f0bf430 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -130,8 +130,8 @@ static int dsb_vtotal(struct intel_atomic_state *state,
return intel_mode_vtotal(&crtc_state->hw.adjusted_mode);
 }
 
-static int dsb_dewake_scanline(struct intel_atomic_state *state,
-  struct intel_crtc *crtc)
+static int dsb_dewake_scanline_start(struct intel_atomic_state *state,
+struct intel_crtc *crtc)
 {
const struct intel_crtc_state *crtc_state = 
pre_commit_crtc_state(state, crtc);
struct drm_i915_private *i915 = to_i915(state->base.dev);
@@ -141,6 +141,14 @@ static int dsb_dewake_scanline(struct intel_atomic_state 
*state,
intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 
latency);
 }
 
+static int dsb_dewake_scanline_end(struct intel_atomic_state *state,
+  struct intel_crtc *crtc)
+{
+   const struct intel_crtc_state *crtc_state = 
pre_commit_crtc_state(state, crtc);
+
+   return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode);
+}
+
 static int dsb_scanline_to_hw(struct intel_atomic_state *state,
  struct intel_crtc *crtc, int scanline)
 {
@@ -529,19 +537,44 @@ static void _intel_dsb_chain(struct intel_atomic_state 
*state,
dsb_error_int_status(display) | DSB_PROG_INT_STATUS 
|
dsb_error_int_en(display));
 
+   if (ctrl & DSB_WAIT_FOR_VBLANK) {
+   int dewake_scanline = dsb_dewake_scanline_start(state, crtc);
+   int hw_dewake_scanline = dsb_scanline_to_hw(state, crtc, 
dewake_scanline);
+
+   intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id),
+   DSB_ENABLE_DEWAKE |
+   
DSB_SCANLINE_FOR_DEWAKE(hw_dewake_scanline));
+   }
+
intel_dsb_reg_write(dsb, DSB_HEAD(pipe, chained_dsb->id),

intel_dsb_buffer_ggtt_offset(&chained_dsb->dsb_buf));
 
intel_dsb_reg_write(dsb, DSB_TAIL(pipe, chained_dsb->id),
intel_dsb_buffer_ggtt_offset(&chained_dsb->dsb_buf) 
+ tail);
+
+   if (ctrl & DSB_WAIT_FOR_VBLANK) {
+   /*
+* Keep DEwake alive via the first DSB, in
+* case we're already past dewake_scanline,
+* and thus DSB_ENABLE_DEWAKE on the second
+* DSB won't do its job.
+*/
+   intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(pipe, dsb->id),
+  DSB_FORCE_DEWAKE, DSB_FORCE_DEWAKE);
+
+   intel_dsb_wait_scanline_out(state, dsb,
+   dsb_dewake_scanline_start(state, 
crtc),
+   dsb_dewake_scanline_end(state, 
crtc));
+   }
 }
 
 void intel_dsb_chain(struct intel_atomic_state *state,
 struct intel_dsb *dsb,
-struct intel_dsb *chained_dsb)
+struct intel_dsb *chained_dsb,
+bool wait_for_vblank)
 {
_intel_dsb_chain(state, dsb, chained_dsb,
-0);
+wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0);

[PATCH 09/14] drm/i915/dsb: Introduce intel_dsb_wait_scanline_{in, out}()

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Add functions to emit a DSB scanline window wait instructions.
We can either wait for the scanline to be IN the window
or OUT of the window.

The hardware doesn't handle wraparound so we must manually
deal with it by swapping the IN range to the inverse OUT
range, or vice versa.

Also add a bit of paranoia to catch the edge case of waiting
for the entire frame. That doesn't make sense since an IN
wait would be a nop, and an OUT wait would imply waiting
forever. Most of the time this also results in both scanline
ranges (original and inverted) to have lower=upper+1
which is nonsense from the hw POV.

For now we are only handling the case where the scanline wait
happens prior to latching the double buffered registers during
the commit (which might change the timings due to LRR/VRR/etc.)

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 73 
 drivers/gpu/drm/i915/display/intel_dsb.h |  6 ++
 2 files changed, 79 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 81937908c798..092cf082ac39 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -362,6 +362,79 @@ void intel_dsb_nonpost_end(struct intel_dsb *dsb)
intel_dsb_noop(dsb, 4);
 }
 
+static void intel_dsb_emit_wait_dsl(struct intel_dsb *dsb,
+   u32 opcode, int lower, int upper)
+{
+   u64 window = ((u64)upper << DSB_SCANLINE_UPPER_SHIFT) |
+   ((u64)lower << DSB_SCANLINE_LOWER_SHIFT);
+
+   intel_dsb_emit(dsb, lower_32_bits(window),
+  (opcode << DSB_OPCODE_SHIFT) |
+  upper_32_bits(window));
+}
+
+static void intel_dsb_wait_dsl(struct intel_atomic_state *state,
+  struct intel_dsb *dsb,
+  int lower_in, int upper_in,
+  int lower_out, int upper_out)
+{
+   struct intel_crtc *crtc = dsb->crtc;
+
+   lower_in = dsb_scanline_to_hw(state, crtc, lower_in);
+   upper_in = dsb_scanline_to_hw(state, crtc, upper_in);
+
+   lower_out = dsb_scanline_to_hw(state, crtc, lower_out);
+   upper_out = dsb_scanline_to_hw(state, crtc, upper_out);
+
+   if (upper_in >= lower_in)
+   intel_dsb_emit_wait_dsl(dsb, DSB_OPCODE_WAIT_DSL_IN,
+   lower_in, upper_in);
+   else if (upper_out >= lower_out)
+   intel_dsb_emit_wait_dsl(dsb, DSB_OPCODE_WAIT_DSL_OUT,
+   lower_out, upper_out);
+   else
+   drm_WARN_ON(crtc->base.dev, 1); /* assert_dsl_ok() should have 
caught it already */
+}
+
+static void assert_dsl_ok(struct intel_atomic_state *state,
+ struct intel_dsb *dsb,
+ int start, int end)
+{
+   struct intel_crtc *crtc = dsb->crtc;
+   int vtotal = dsb_vtotal(state, crtc);
+
+   /*
+* Waiting for the entire frame doesn't make sense,
+* (IN==don't wait, OUT=wait forever).
+*/
+   drm_WARN(crtc->base.dev, (end - start + vtotal) % vtotal == vtotal - 1,
+"[CRTC:%d:%s] DSB %d bad scanline window wait: %d-%d 
(vt=%d)\n",
+crtc->base.base.id, crtc->base.name, dsb->id,
+start, end, vtotal);
+}
+
+void intel_dsb_wait_scanline_in(struct intel_atomic_state *state,
+   struct intel_dsb *dsb,
+   int start, int end)
+{
+   assert_dsl_ok(state, dsb, start, end);
+
+   intel_dsb_wait_dsl(state, dsb,
+  start, end,
+  end + 1, start - 1);
+}
+
+void intel_dsb_wait_scanline_out(struct intel_atomic_state *state,
+struct intel_dsb *dsb,
+int start, int end)
+{
+   assert_dsl_ok(state, dsb, start, end);
+
+   intel_dsb_wait_dsl(state, dsb,
+  end + 1, start - 1,
+  start, end);
+}
+
 static void intel_dsb_align_tail(struct intel_dsb *dsb)
 {
u32 aligned_tail, tail;
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h 
b/drivers/gpu/drm/i915/display/intel_dsb.h
index 84fc2f8434d1..d0737cefb393 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -39,6 +39,12 @@ void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
 void intel_dsb_noop(struct intel_dsb *dsb, int count);
 void intel_dsb_nonpost_start(struct intel_dsb *dsb);
 void intel_dsb_nonpost_end(struct intel_dsb *dsb);
+void intel_dsb_wait_scanline_in(struct intel_atomic_state *state,
+   struct intel_dsb *dsb,
+   int lower, int upper);
+void intel_dsb_wait_scanline_out(struct intel_atomic_state *state,
+struct intel_dsb *dsb,
+ 

[PATCH 06/14] drm/i915/dsb: Fix dewake scanline

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Currently we calculate the DEwake scanline based on
the delayed vblank start, while in reality it should be computed
based on the undelayed vblank start (as that is where the DSB
actually starts). Currently it doesn't really matter as we
don't have any vblank delay configured, but that may change
in the future so let's be accurate in what we do.

We can also remove the max() as intel_crtc_scanline_to_hw()
can deal with negative numbers, which there really shouldn't
be anyway.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index d3e5e5263603..e871af5517b5 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -86,16 +86,10 @@ struct intel_dsb {
 static int dsb_dewake_scanline(const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
-   const struct drm_display_mode *adjusted_mode = 
&crtc_state->hw.adjusted_mode;
unsigned int latency = skl_watermark_max_latency(i915, 0);
-   int vblank_start;
 
-   if (crtc_state->vrr.enable)
-   vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
-   else
-   vblank_start = intel_mode_vblank_start(adjusted_mode);
-
-   return max(0, vblank_start - intel_usecs_to_scanlines(adjusted_mode, 
latency));
+   return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode) -
+   intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 
latency);
 }
 
 static u32 dsb_chicken(struct intel_crtc *crtc)
-- 
2.44.2



[PATCH 08/14] drm/i915/dsb: Precompute DSB_CHICKEN

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Adjust the code that determines the correct DSB_CHICKEN value
to be usable for use within DSB commands themselves. Ie.
precompute it based on our knowledge of what the hardware state
(VRR vs. not mainly) will be at the time of the commit.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index b362a3050c7f..81937908c798 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -43,6 +43,7 @@ struct intel_dsb {
 */
unsigned int ins_start_offset;
 
+   u32 chicken;
int hw_dewake_scanline;
 };
 
@@ -149,9 +150,10 @@ static int dsb_scanline_to_hw(struct intel_atomic_state 
*state,
return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % 
vtotal;
 }
 
-static u32 dsb_chicken(struct intel_crtc *crtc)
+static u32 dsb_chicken(struct intel_atomic_state *state,
+  struct intel_crtc *crtc)
 {
-   if (crtc->mode_flags & I915_MODE_FLAG_VRR)
+   if (pre_commit_is_vrr_active(state, crtc))
return DSB_SKIP_WAITS_EN |
DSB_CTRL_WAIT_SAFE_WINDOW |
DSB_CTRL_NO_WAIT_VBLANK |
@@ -449,7 +451,7 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 
ctrl,
  ctrl | DSB_ENABLE);
 
intel_de_write_fw(display, DSB_CHICKEN(pipe, dsb->id),
- dsb_chicken(crtc));
+ dsb->chicken);
 
intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id),
  dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
@@ -580,6 +582,7 @@ struct intel_dsb *intel_dsb_prepare(struct 
intel_atomic_state *state,
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
 
+   dsb->chicken = dsb_chicken(state, crtc);
dsb->hw_dewake_scanline =
dsb_scanline_to_hw(state, crtc, dsb_dewake_scanline(state, 
crtc));
 
-- 
2.44.2



[PATCH 07/14] drm/i915/dsb: Account for VRR properly in DSB scanline stuff

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

When determining various scanlines for DSB use we should take into
account whether VRR is active at the time when the DSB uses said
scanline information. For now all DSB scanline usage occurs prior
to the actual commit, so we only need to care about the state of
VRR at that time.

I've decided to move intel_crtc_scanline_to_hw() in its entirety
to the DSB code as it will also need to know the actual state
of VRR in order to do its job 100% correctly.

TODO: figure out how much of this could be moved to some
  more generic place and perhaps be shared with the CPU
  vblank evasion code/etc...

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c |  4 +-
 drivers/gpu/drm/i915/display/intel_display.h |  3 +
 drivers/gpu/drm/i915/display/intel_dsb.c | 65 ++--
 drivers/gpu/drm/i915/display/intel_vblank.c  | 10 +--
 drivers/gpu/drm/i915/display/intel_vblank.h  |  3 +-
 5 files changed, 67 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 01a5faa3fea5..592483651b3c 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1031,8 +1031,8 @@ static bool intel_crtc_vrr_enabling(struct 
intel_atomic_state *state,
  vrr_params_changed(old_crtc_state, new_crtc_state)));
 }
 
-static bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
-struct intel_crtc *crtc)
+bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
 {
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h 
b/drivers/gpu/drm/i915/display/intel_display.h
index b0cf6ca70952..b21d9578d5db 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -532,6 +532,9 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state 
*crtc_state);
 
 void intel_update_watermarks(struct drm_i915_private *i915);
 
+bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
+
 /* modesetting */
 int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
  const char *reason, u8 pipe_mask);
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index e871af5517b5..b362a3050c7f 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -83,15 +83,72 @@ struct intel_dsb {
 #define DSB_OPCODE_POLL0xA
 /* see DSB_REG_VALUE_MASK */
 
-static int dsb_dewake_scanline(const struct intel_crtc_state *crtc_state)
+static bool pre_commit_is_vrr_active(struct intel_atomic_state *state,
+struct intel_crtc *crtc)
 {
-   struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+   const struct intel_crtc_state *old_crtc_state =
+   intel_atomic_get_old_crtc_state(state, crtc);
+   const struct intel_crtc_state *new_crtc_state =
+   intel_atomic_get_new_crtc_state(state, crtc);
+
+   /* VRR will be enabled afterwards, if necessary */
+   if (intel_crtc_needs_modeset(new_crtc_state))
+   return false;
+
+   /* VRR will have been disabled during intel_pre_plane_update() */
+   return old_crtc_state->vrr.enable && !intel_crtc_vrr_disabling(state, 
crtc);
+}
+
+static const struct intel_crtc_state *
+pre_commit_crtc_state(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+   const struct intel_crtc_state *old_crtc_state =
+   intel_atomic_get_old_crtc_state(state, crtc);
+   const struct intel_crtc_state *new_crtc_state =
+   intel_atomic_get_new_crtc_state(state, crtc);
+
+   /*
+* During fastsets/etc. the transcoder is still
+* running with the old timings at this point.
+*/
+   if (intel_crtc_needs_modeset(new_crtc_state))
+   return new_crtc_state;
+   else
+   return old_crtc_state;
+}
+
+static int dsb_vtotal(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+   const struct intel_crtc_state *crtc_state = 
pre_commit_crtc_state(state, crtc);
+
+   if (pre_commit_is_vrr_active(state, crtc))
+   return crtc_state->vrr.vmax;
+   else
+   return intel_mode_vtotal(&crtc_state->hw.adjusted_mode);
+}
+
+static int dsb_dewake_scanline(struct intel_atomic_state *state,
+  struct intel_crtc *crtc)
+{
+   const struct intel_crtc_state *crtc_state = 
pre_commit_crtc_state(state, crtc);
+   struct drm_i915_private *i915 = to_i915(s

[PATCH 04/14] drm/i915/dsb: Convert dewake_scanline to a hw scanline number earlier

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Currently we switch from out software idea of a scanline
to the hw's idea of a scanline during the commit phase in
_intel_dsb_commit(). While that is slightly easier due to
fastsets fiddling with the timings, we'll also need to
generate proper hw scanline numbers already when emitting
DSB scanline wait instructions. So this approach won't
do in the future. Switch to hw scanline numbers earlier.

Also intel_dsb_dewake_scanline() itself already makes
some assumptions about VRR that don't take into account
VRR toggling during fastsets, so technically delaying
the sw->hw conversion doesn't even help us.

The other reason for delaying the conversion was that we
are using intel_get_crtc_scanline() during intel_dsb_commit()
which gives us the current sw scanline. But this is pretty
low level stuff anyway so just using raw PIPEDSL reads seems
fine here, and that of course gives us the hw scanline
directly, reducing the need to do so many conversions.

v2: Return the non-hw scanline from intel_dsb_dewake_scanline()

Reviewed-by: Jani Nikula 
Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c| 21 -
 drivers/gpu/drm/i915/display/intel_vblank.c |  9 -
 drivers/gpu/drm/i915/display/intel_vblank.h |  3 ++-
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index ded696363258..cee33c66a26b 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -6,6 +6,7 @@
 
 #include "i915_drv.h"
 #include "i915_irq.h"
+#include "i915_reg.h"
 #include "intel_crtc.h"
 #include "intel_de.h"
 #include "intel_display_types.h"
@@ -42,7 +43,7 @@ struct intel_dsb {
 */
unsigned int ins_start_offset;
 
-   int dewake_scanline;
+   int hw_dewake_scanline;
 };
 
 /**
@@ -376,7 +377,7 @@ static u32 dsb_error_int_en(struct intel_display *display)
 }
 
 static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
- int dewake_scanline)
+ int hw_dewake_scanline)
 {
struct intel_crtc *crtc = dsb->crtc;
struct intel_display *display = to_intel_display(crtc->base.dev);
@@ -406,10 +407,8 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 
ctrl,
intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id),
  intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf));
 
-   if (dewake_scanline >= 0) {
-   int diff, hw_dewake_scanline;
-
-   hw_dewake_scanline = intel_crtc_scanline_to_hw(crtc, 
dewake_scanline);
+   if (hw_dewake_scanline >= 0) {
+   int diff, position;
 
intel_de_write_fw(display, DSB_PMCTRL(pipe, dsb->id),
  DSB_ENABLE_DEWAKE |
@@ -419,7 +418,9 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 
ctrl,
 * Force DEwake immediately if we're already past
 * or close to racing past the target scanline.
 */
-   diff = dewake_scanline - intel_get_crtc_scanline(crtc);
+   position = intel_de_read_fw(display, PIPEDSL(display, pipe)) & 
PIPEDSL_LINE_MASK;
+
+   diff = hw_dewake_scanline - position;
intel_de_write_fw(display, DSB_PMCTRL_2(pipe, dsb->id),
  (diff >= 0 && diff < 5 ? DSB_FORCE_DEWAKE : 
0) |
  DSB_BLOCK_DEWAKE_EXTENSION);
@@ -441,7 +442,7 @@ void intel_dsb_commit(struct intel_dsb *dsb,
 {
_intel_dsb_commit(dsb,
  wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0,
- wait_for_vblank ? dsb->dewake_scanline : -1);
+ wait_for_vblank ? dsb->hw_dewake_scanline : -1);
 }
 
 void intel_dsb_wait(struct intel_dsb *dsb)
@@ -529,7 +530,9 @@ struct intel_dsb *intel_dsb_prepare(struct 
intel_atomic_state *state,
dsb->size = size / 4; /* in dwords */
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
-   dsb->dewake_scanline = intel_dsb_dewake_scanline(crtc_state);
+
+   dsb->hw_dewake_scanline =
+   intel_crtc_scanline_to_hw(crtc_state, 
intel_dsb_dewake_scanline(crtc_state));
 
return dsb;
 
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c 
b/drivers/gpu/drm/i915/display/intel_vblank.c
index f183e0d4b2ba..56c8033eec4c 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -284,13 +284,12 @@ static int __intel_get_crtc_scanline(struct intel_crtc 
*crtc)
return (position + vtotal + crtc->scanline_offset) % vtotal;
 }
 
-int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline)
+int intel_crtc_scanline_to_hw(const struct intel_crtc_state *crtc_state,
+ int scanline)
 {
-   const struct drm_vblank_crtc *vblank = 
drm_crtc_vblank

[PATCH 05/14] drm/i915/dsb: Shuffle code around

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Relocate intel_dsb_dewake_scanline() and dsb_chicken() upwards
in the file. I need to reuse these while emitting DSB
commands, and I'd like to keep the DSB command emission
stuff more or less grouped together in the file.

Also drop the intel_ prefix from intel_dsb_dewake_scanline() since
it's all internal stuff and thus doesn't need so much namespacing.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_dsb.c | 56 
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index cee33c66a26b..d3e5e5263603 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -83,6 +83,33 @@ struct intel_dsb {
 #define DSB_OPCODE_POLL0xA
 /* see DSB_REG_VALUE_MASK */
 
+static int dsb_dewake_scanline(const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+   const struct drm_display_mode *adjusted_mode = 
&crtc_state->hw.adjusted_mode;
+   unsigned int latency = skl_watermark_max_latency(i915, 0);
+   int vblank_start;
+
+   if (crtc_state->vrr.enable)
+   vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
+   else
+   vblank_start = intel_mode_vblank_start(adjusted_mode);
+
+   return max(0, vblank_start - intel_usecs_to_scanlines(adjusted_mode, 
latency));
+}
+
+static u32 dsb_chicken(struct intel_crtc *crtc)
+{
+   if (crtc->mode_flags & I915_MODE_FLAG_VRR)
+   return DSB_SKIP_WAITS_EN |
+   DSB_CTRL_WAIT_SAFE_WINDOW |
+   DSB_CTRL_NO_WAIT_VBLANK |
+   DSB_INST_WAIT_SAFE_WINDOW |
+   DSB_INST_NO_WAIT_VBLANK;
+   else
+   return DSB_SKIP_WAITS_EN;
+}
+
 static bool assert_dsb_has_room(struct intel_dsb *dsb)
 {
struct intel_crtc *crtc = dsb->crtc;
@@ -313,33 +340,6 @@ void intel_dsb_finish(struct intel_dsb *dsb)
intel_dsb_buffer_flush_map(&dsb->dsb_buf);
 }
 
-static int intel_dsb_dewake_scanline(const struct intel_crtc_state *crtc_state)
-{
-   struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
-   const struct drm_display_mode *adjusted_mode = 
&crtc_state->hw.adjusted_mode;
-   unsigned int latency = skl_watermark_max_latency(i915, 0);
-   int vblank_start;
-
-   if (crtc_state->vrr.enable)
-   vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
-   else
-   vblank_start = intel_mode_vblank_start(adjusted_mode);
-
-   return max(0, vblank_start - intel_usecs_to_scanlines(adjusted_mode, 
latency));
-}
-
-static u32 dsb_chicken(struct intel_crtc *crtc)
-{
-   if (crtc->mode_flags & I915_MODE_FLAG_VRR)
-   return DSB_SKIP_WAITS_EN |
-   DSB_CTRL_WAIT_SAFE_WINDOW |
-   DSB_CTRL_NO_WAIT_VBLANK |
-   DSB_INST_WAIT_SAFE_WINDOW |
-   DSB_INST_NO_WAIT_VBLANK;
-   else
-   return DSB_SKIP_WAITS_EN;
-}
-
 static u32 dsb_error_int_status(struct intel_display *display)
 {
struct drm_i915_private *i915 = to_i915(display->drm);
@@ -532,7 +532,7 @@ struct intel_dsb *intel_dsb_prepare(struct 
intel_atomic_state *state,
dsb->ins_start_offset = 0;
 
dsb->hw_dewake_scanline =
-   intel_crtc_scanline_to_hw(crtc_state, 
intel_dsb_dewake_scanline(crtc_state));
+   intel_crtc_scanline_to_hw(crtc_state, 
dsb_dewake_scanline(crtc_state));
 
return dsb;
 
-- 
2.44.2



[PATCH 03/14] drm/i915/dsb: Hook up DSB error interrupts

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Enable all DSB error/fault interrupts so that we can see if
anything goes terribly wrong.

Signed-off-by: Ville Syrjälä 
---
 .../gpu/drm/i915/display/intel_display_irq.c  | 17 ++
 drivers/gpu/drm/i915/display/intel_dsb.c  | 58 +++
 drivers/gpu/drm/i915/display/intel_dsb.h  |  6 ++
 drivers/gpu/drm/i915/i915_reg.h   |  4 ++
 4 files changed, 85 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c 
b/drivers/gpu/drm/i915/display/intel_display_irq.c
index 5219ba295c74..7169db984651 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -14,6 +14,7 @@
 #include "intel_display_trace.h"
 #include "intel_display_types.h"
 #include "intel_dp_aux.h"
+#include "intel_dsb.h"
 #include "intel_fdi_regs.h"
 #include "intel_fifo_underrun.h"
 #include "intel_gmbus.h"
@@ -1143,6 +1144,17 @@ void gen8_de_irq_handler(struct drm_i915_private 
*dev_priv, u32 master_ctl)
 
intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe), 
iir);
 
+   if (HAS_DSB(dev_priv)) {
+   if (iir & GEN12_DSB_INT(INTEL_DSB_0))
+   intel_dsb_irq_handler(&dev_priv->display, pipe, 
INTEL_DSB_0);
+
+   if (iir & GEN12_DSB_INT(INTEL_DSB_1))
+   intel_dsb_irq_handler(&dev_priv->display, pipe, 
INTEL_DSB_1);
+
+   if (iir & GEN12_DSB_INT(INTEL_DSB_2))
+   intel_dsb_irq_handler(&dev_priv->display, pipe, 
INTEL_DSB_2);
+   }
+
if (iir & GEN8_PIPE_VBLANK)
intel_handle_vblank(dev_priv, pipe);
 
@@ -1718,6 +1730,11 @@ void gen8_de_irq_postinstall(struct drm_i915_private 
*dev_priv)
de_port_masked |= DSI0_TE | DSI1_TE;
}
 
+   if (HAS_DSB(dev_priv))
+   de_pipe_masked |= GEN12_DSB_INT(INTEL_DSB_0) |
+   GEN12_DSB_INT(INTEL_DSB_1) |
+   GEN12_DSB_INT(INTEL_DSB_2);
+
de_pipe_enables = de_pipe_masked |
GEN8_PIPE_VBLANK |
gen8_de_pipe_underrun_mask(dev_priv) |
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 2ab3765f6c06..ded696363258 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -339,6 +339,42 @@ static u32 dsb_chicken(struct intel_crtc *crtc)
return DSB_SKIP_WAITS_EN;
 }
 
+static u32 dsb_error_int_status(struct intel_display *display)
+{
+   struct drm_i915_private *i915 = to_i915(display->drm);
+   u32 errors;
+
+   errors = DSB_GTT_FAULT_INT_STATUS |
+   DSB_RSPTIMEOUT_INT_STATUS |
+   DSB_POLL_ERR_INT_STATUS;
+
+   /*
+* All the non-existing status bits operate as
+* normal r/w bits, so any attempt to clear them
+* will just end up setting them. Never do that so
+* we won't mistake them for actual error interrupts.
+*/
+   if (DISPLAY_VER(i915) >= 14)
+   errors |= DSB_ATS_FAULT_INT_STATUS;
+
+   return errors;
+}
+
+static u32 dsb_error_int_en(struct intel_display *display)
+{
+   struct drm_i915_private *i915 = to_i915(display->drm);
+   u32 errors;
+
+   errors = DSB_GTT_FAULT_INT_EN |
+   DSB_RSPTIMEOUT_INT_EN |
+   DSB_POLL_ERR_INT_EN;
+
+   if (DISPLAY_VER(i915) >= 14)
+   errors |= DSB_ATS_FAULT_INT_EN;
+
+   return errors;
+}
+
 static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
  int dewake_scanline)
 {
@@ -363,6 +399,10 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 
ctrl,
intel_de_write_fw(display, DSB_CHICKEN(pipe, dsb->id),
  dsb_chicken(crtc));
 
+   intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id),
+ dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
+ dsb_error_int_en(display));
+
intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id),
  intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf));
 
@@ -430,6 +470,9 @@ void intel_dsb_wait(struct intel_dsb *dsb)
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
intel_de_write_fw(display, DSB_CTRL(pipe, dsb->id), 0);
+
+   intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id),
+ dsb_error_int_status(display) | DSB_PROG_INT_STATUS);
 }
 
 /**
@@ -513,3 +556,18 @@ void intel_dsb_cleanup(struct intel_dsb *dsb)
intel_dsb_buffer_cleanup(&dsb->dsb_buf);
kfree(dsb);
 }
+
+void intel_dsb_irq_handler(struct intel_display *display,
+  enum pipe pipe, enum intel_dsb_id dsb_id)
+{
+   struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(display->drm), 
pipe);
+   u32 tmp, e

[PATCH 02/14] drm/i915: Make vrr_{enabling, disabling}() usable outside intel_display.c

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Give vrr_enabling() and vrr_disabling() slightly fancier names, and
pass in the whole atomic state so that they'll be easier to use.
We'll need to call at least the disabling part from the DSB code
soon enough (so that we can do vblank evasions/etc. correctly on
the DSB).

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c | 26 +---
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index c2c388212e2e..01a5faa3fea5 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1014,9 +1014,14 @@ static bool cmrr_params_changed(const struct 
intel_crtc_state *old_crtc_state,
old_crtc_state->cmrr.cmrr_n != new_crtc_state->cmrr.cmrr_n;
 }
 
-static bool vrr_enabling(const struct intel_crtc_state *old_crtc_state,
-const struct intel_crtc_state *new_crtc_state)
+static bool intel_crtc_vrr_enabling(struct intel_atomic_state *state,
+   struct intel_crtc *crtc)
 {
+   const struct intel_crtc_state *old_crtc_state =
+   intel_atomic_get_old_crtc_state(state, crtc);
+   const struct intel_crtc_state *new_crtc_state =
+   intel_atomic_get_new_crtc_state(state, crtc);
+
if (!new_crtc_state->hw.active)
return false;
 
@@ -1026,9 +1031,14 @@ static bool vrr_enabling(const struct intel_crtc_state 
*old_crtc_state,
  vrr_params_changed(old_crtc_state, new_crtc_state)));
 }
 
-static bool vrr_disabling(const struct intel_crtc_state *old_crtc_state,
- const struct intel_crtc_state *new_crtc_state)
+static bool intel_crtc_vrr_disabling(struct intel_atomic_state *state,
+struct intel_crtc *crtc)
 {
+   const struct intel_crtc_state *old_crtc_state =
+   intel_atomic_get_old_crtc_state(state, crtc);
+   const struct intel_crtc_state *new_crtc_state =
+   intel_atomic_get_new_crtc_state(state, crtc);
+
if (!old_crtc_state->hw.active)
return false;
 
@@ -1181,7 +1191,7 @@ static void intel_pre_plane_update(struct 
intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
 
-   if (vrr_disabling(old_crtc_state, new_crtc_state)) {
+   if (intel_crtc_vrr_disabling(state, crtc)) {
intel_vrr_disable(old_crtc_state);
intel_crtc_update_active_timings(old_crtc_state, false);
}
@@ -6830,8 +6840,6 @@ static void commit_pipe_post_planes(struct 
intel_atomic_state *state,
struct intel_crtc *crtc)
 {
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-   const struct intel_crtc_state *old_crtc_state =
-   intel_atomic_get_old_crtc_state(state, crtc);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
 
@@ -6844,7 +6852,7 @@ static void commit_pipe_post_planes(struct 
intel_atomic_state *state,
!intel_crtc_needs_modeset(new_crtc_state))
skl_detach_scalers(new_crtc_state);
 
-   if (vrr_enabling(old_crtc_state, new_crtc_state))
+   if (intel_crtc_vrr_enabling(state, crtc))
intel_vrr_enable(new_crtc_state);
 }
 
@@ -6944,7 +6952,7 @@ static void intel_update_crtc(struct intel_atomic_state 
*state,
 *
 * FIXME Should be synchronized with the start of vblank somehow...
 */
-   if (vrr_enabling(old_crtc_state, new_crtc_state) ||
+   if (intel_crtc_vrr_enabling(state, crtc) ||
new_crtc_state->update_m_n || new_crtc_state->update_lrr)
intel_crtc_update_active_timings(new_crtc_state,
 new_crtc_state->vrr.enable);
-- 
2.44.2



[PATCH 01/14] drm/i915: Calculate vblank delay more accurately

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Calculate the vblank delay in the vblank evasion code correctly
for interlaced modes.

The current code assumes that we won't be using an interlaced mode.
That assumption is actually valid since we've defeatured interlaced
scanout in commit f71c9b7bc35f ("drm/i915/display: Prune Interlace
modes for Display >=12") for DSB capable platforms. However the
feature is still present in the hardware, and if we ever find the
need to re-enable it seems better to calculate the vblank delay
correctly.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_vblank.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c 
b/drivers/gpu/drm/i915/display/intel_vblank.c
index 5b065e1cd4e4..f183e0d4b2ba 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -652,7 +652,8 @@ void intel_vblank_evade_init(const struct intel_crtc_state 
*old_crtc_state,
 */
if (intel_color_uses_dsb(new_crtc_state) ||
new_crtc_state->update_m_n || new_crtc_state->update_lrr)
-   evade->min -= adjusted_mode->crtc_vblank_start - 
adjusted_mode->crtc_vdisplay;
+   evade->min -= intel_mode_vblank_start(adjusted_mode) -
+   intel_mode_vdisplay(adjusted_mode);
 }
 
 /* must be called with vblank interrupt already enabled! */
-- 
2.44.2



[PATCH 00/14] drm/i915/dsb: Use chained DSBs for LUT programming

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Handle the DSB's DEwake shenanigans more elegantly
by chaining two DSBs together.

Ville Syrjälä (14):
  drm/i915: Calculate vblank delay more accurately
  drm/i915: Make vrr_{enabling,disabling}() usable outside
intel_display.c
  drm/i915/dsb: Hook up DSB error interrupts
  drm/i915/dsb: Convert dewake_scanline to a hw scanline number earlier
  drm/i915/dsb: Shuffle code around
  drm/i915/dsb: Fix dewake scanline
  drm/i915/dsb: Account for VRR properly in DSB scanline stuff
  drm/i915/dsb: Precompute DSB_CHICKEN
  drm/i915/dsb: Introduce intel_dsb_wait_scanline_{in,out}()
  drm/i915/dsb: Introduce intel_dsb_chain()
  drm/i915/dsb: Allow intel_dsb_chain() to use DSB_WAIT_FOR_VBLANK
  drm/i915/dsb: Clear DSB_ENABLE_DEWAKE once the DSB is done
  drm/i915/dsb: s/dsb/dsb_color_vblank/
  drm/i915/dsb: Use chained DSBs for LUT programming

 drivers/gpu/drm/i915/display/intel_atomic.c   |   6 +-
 drivers/gpu/drm/i915/display/intel_color.c|  56 ++-
 drivers/gpu/drm/i915/display/intel_display.c  |  29 +-
 drivers/gpu/drm/i915/display/intel_display.h  |   3 +
 .../gpu/drm/i915/display/intel_display_irq.c  |  17 +
 .../drm/i915/display/intel_display_types.h|   4 +-
 drivers/gpu/drm/i915/display/intel_dsb.c  | 327 --
 drivers/gpu/drm/i915/display/intel_dsb.h  |  16 +
 drivers/gpu/drm/i915/display/intel_vblank.c   |  14 +-
 drivers/gpu/drm/i915/display/intel_vblank.h   |   2 +-
 drivers/gpu/drm/i915/i915_reg.h   |   4 +
 11 files changed, 401 insertions(+), 77 deletions(-)

-- 
2.44.2



[PATCH 5/5] drm/i915: Allow async flips with CCS on ICL

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Apparently ICL can do async flips with CCS. In fact it already
seems to work on GLK, but apparently can lead to underruns there
so we'll only enable it for ICL.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c | 21 +++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 0b0c5ef1d48e..eeba224b9f25 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6243,7 +6243,26 @@ static int intel_async_flip_check_hw(struct 
intel_atomic_state *state, struct in
return -EINVAL;
}
break;
-
+   case I915_FORMAT_MOD_Y_TILED_CCS:
+   case I915_FORMAT_MOD_Yf_TILED_CCS:
+   /*
+* Display WA #0731: skl
+* WaDisableRCWithAsyncFlip: skl
+* "When render decompression is enabled, hardware
+*  internally converts the Async flips to Sync flips."
+*
+* Display WA #1159: glk
+* "Async flip with render compression may result in
+*  intermittent underrun corruption."
+*/
+   if (DISPLAY_VER(i915) < 11) {
+   drm_dbg_kms(&i915->drm,
+   "[PLANE:%d:%s] Modifier 0x%llx does 
not support async flip on display ver %d\n",
+   plane->base.base.id, 
plane->base.name,
+   new_plane_state->hw.fb->modifier, 
DISPLAY_VER(i915));
+   return -EINVAL;
+   }
+   break;
case I915_FORMAT_MOD_X_TILED:
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Yf_TILED:
-- 
2.44.2



[PATCH 4/5] drm/i915: Allow async flips with render compression on TGL+

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Looks like CCS + async flips has been a thing for a while now.
Enable this for TGL+ render compression modifiers.

Note that we can't update AUX_DIST during async flips we must
check to make sure it remains unchanged.

We also can't do clear color. Supposedly there was some attempt
to make it work, but apparently the issues only got ironed out
in MTL. For now we'll not worry about it and refuse async flips
with clear color modifiers.

Bspec claims that media compression doesn't support async flips.
Based on a quick test it does seem to work to some degree, but
perhaps it has issues as well. Let's trust the spec here and
continue to refuse async flips + media compression.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_display.c| 14 +-
 .../gpu/drm/i915/display/skl_universal_plane.c  | 17 ++---
 .../gpu/drm/i915/display/skl_universal_plane.h  |  3 +++
 3 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index c782e65a7123..0b0c5ef1d48e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6248,6 +6248,9 @@ static int intel_async_flip_check_hw(struct 
intel_atomic_state *state, struct in
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Yf_TILED:
case I915_FORMAT_MOD_4_TILED:
+   case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
+   case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
+   case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
break;
default:
drm_dbg_kms(&i915->drm,
@@ -6257,7 +6260,8 @@ static int intel_async_flip_check_hw(struct 
intel_atomic_state *state, struct in
return -EINVAL;
}
 
-   if (new_plane_state->hw.fb->format->num_planes > 1) {
+   if 
(intel_format_info_is_yuv_semiplanar(new_plane_state->hw.fb->format,
+   
new_plane_state->hw.fb->modifier)) {
drm_dbg_kms(&i915->drm,
"[PLANE:%d:%s] Planar formats do not 
support async flips\n",
plane->base.base.id, plane->base.name);
@@ -6303,6 +6307,14 @@ static int intel_async_flip_check_hw(struct 
intel_atomic_state *state, struct in
return -EINVAL;
}
 
+   if (skl_plane_aux_dist(old_plane_state, 0) !=
+   skl_plane_aux_dist(new_plane_state, 0)) {
+   drm_dbg_kms(&i915->drm,
+   "[PLANE:%d:%s] AUX_DIST cannot be changed 
in async flip\n",
+   plane->base.base.id, plane->base.name);
+   return -EINVAL;
+   }
+
if (!drm_rect_equals(&old_plane_state->uapi.src, 
&new_plane_state->uapi.src) ||
!drm_rect_equals(&old_plane_state->uapi.dst, 
&new_plane_state->uapi.dst)) {
drm_dbg_kms(&i915->drm,
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index c80a89b71ef7..6f4b3839724d 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -528,15 +528,18 @@ static u32 tgl_plane_min_alignment(struct intel_plane 
*plane,
if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915))
return mult * 16 * 1024;
return mult * 4 * 1024;
-   case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
-   case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
-   case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
-   case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
-   case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
+   if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915))
+   return mult * 16 * 1024;
+   fallthrough;
+   case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
+   case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
+   case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
+   case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
+   case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
/*
 * Align to at least 4x1 main surface
 * tiles (16K) to match 64B of AUX.
@@ -1185,8 +1188,8 @@ static u32 skl_plane_surf(const struct intel_plane_state 
*plane_state,
return plane_surf;
 }
 
-static u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state,
- int color_plane)
+u32 skl_plane_aux_dist(const struct intel_pla

[PATCH 2/5] drm/i915: Expose CCS for 10bpc RGB formats on TGL+

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

CCS + 10bpc formats has been a thing for a while now. Expose it
it on TGL+.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fb.c   | 36 +++
 .../drm/i915/display/skl_universal_plane.c|  8 ++---
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
b/drivers/gpu/drm/i915/display/intel_fb.c
index f23547a88b1f..43d0574814a6 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -66,6 +66,18 @@ static const struct drm_format_info gen12_ccs_formats[] = {
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 2,
  .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB2101010, .depth = 32, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR2101010, .depth = 32, .num_planes = 2,
+ .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_YUYV, .num_planes = 2,
  .char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
  .hsub = 2, .vsub = 1, .is_yuv = true },
@@ -112,6 +124,18 @@ static const struct drm_format_info gen12_ccs_cc_formats[] 
= {
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 3,
  .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 3,
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 3,
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB2101010, .depth = 32, .num_planes = 3,
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR2101010, .depth = 32, .num_planes = 3,
+ .char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 
1, 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
 static const struct drm_format_info gen12_flat_ccs_cc_formats[] = {
@@ -127,6 +151,18 @@ static const struct drm_format_info 
gen12_flat_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 2,
  .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
  .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
+ .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, },
+   { .format = DRM_FORMAT_ARGB2101010, .depth = 32, .num_planes = 2,
+ .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
+   { .format = DRM_FORMAT_ABGR2101010, .depth = 32, .num_planes = 2,
+ .char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
+ .hsub = 1, .vsub = 1, .has_alpha = true },
 };
 
 struct intel_modifier_desc {
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index ba5a628b4757..92e5db82cbd9 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2314,6 +2314,10 @@ static bool gen12_plane_format_mod_supported(struct 
drm_plane *_plane,
case DRM_FORMAT_XBGR:
case DRM_FORMAT_ARGB:
case DRM_FORMAT_ABGR:
+   case DRM_FORMAT_XRGB2101010:
+   case DRM_FORMAT_XBGR2101010:
+   case DRM_FORMAT_ARGB2101010:
+   case DRM_FORMAT_ABGR2101010:
if (intel_fb_is_ccs_modifier(modifier))
return true;
fallthrough;
@@ -2330,10 +2334,6 @@ static bool gen12_plane_format_mod_supported(struct 
drm_plane *_plane,
return true

[PATCH 3/5] drm/i915: Enable 10bpc + CCS on ICL

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

ICL supports 10bpc compressed scanout. Enable it.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/display/intel_fb.c   |  8 +++
 .../drm/i915/display/skl_universal_plane.c| 65 +++
 2 files changed, 73 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_fb.c 
b/drivers/gpu/drm/i915/display/intel_fb.c
index 43d0574814a6..1376476b7d60 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -44,6 +44,14 @@ static const struct drm_format_info skl_ccs_formats[] = {
  .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
{ .format = DRM_FORMAT_ABGR, .depth = 32, .num_planes = 2,
  .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
+   { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
+ .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
+   { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
+ .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
+   { .format = DRM_FORMAT_ARGB2101010, .depth = 32, .num_planes = 2,
+ .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
+   { .format = DRM_FORMAT_ABGR2101010, .depth = 32, .num_planes = 2,
+ .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
 };
 
 /*
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 92e5db82cbd9..c80a89b71ef7 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2301,6 +2301,60 @@ static bool skl_plane_format_mod_supported(struct 
drm_plane *_plane,
}
 }
 
+static bool icl_plane_format_mod_supported(struct drm_plane *_plane,
+  u32 format, u64 modifier)
+{
+   struct intel_plane *plane = to_intel_plane(_plane);
+
+   if (!intel_fb_plane_supports_modifier(plane, modifier))
+   return false;
+
+   switch (format) {
+   case DRM_FORMAT_XRGB:
+   case DRM_FORMAT_XBGR:
+   case DRM_FORMAT_ARGB:
+   case DRM_FORMAT_ABGR:
+   case DRM_FORMAT_XRGB2101010:
+   case DRM_FORMAT_XBGR2101010:
+   case DRM_FORMAT_ARGB2101010:
+   case DRM_FORMAT_ABGR2101010:
+   if (intel_fb_is_ccs_modifier(modifier))
+   return true;
+   fallthrough;
+   case DRM_FORMAT_RGB565:
+   case DRM_FORMAT_YUYV:
+   case DRM_FORMAT_YVYU:
+   case DRM_FORMAT_UYVY:
+   case DRM_FORMAT_VYUY:
+   case DRM_FORMAT_NV12:
+   case DRM_FORMAT_XYUV:
+   case DRM_FORMAT_P010:
+   case DRM_FORMAT_P012:
+   case DRM_FORMAT_P016:
+   case DRM_FORMAT_XVYU2101010:
+   if (modifier == I915_FORMAT_MOD_Yf_TILED)
+   return true;
+   fallthrough;
+   case DRM_FORMAT_C8:
+   case DRM_FORMAT_XBGR16161616F:
+   case DRM_FORMAT_ABGR16161616F:
+   case DRM_FORMAT_XRGB16161616F:
+   case DRM_FORMAT_ARGB16161616F:
+   case DRM_FORMAT_Y210:
+   case DRM_FORMAT_Y212:
+   case DRM_FORMAT_Y216:
+   case DRM_FORMAT_XVYU12_16161616:
+   case DRM_FORMAT_XVYU16161616:
+   if (modifier == DRM_FORMAT_MOD_LINEAR ||
+   modifier == I915_FORMAT_MOD_X_TILED ||
+   modifier == I915_FORMAT_MOD_Y_TILED)
+   return true;
+   fallthrough;
+   default:
+   return false;
+   }
+}
+
 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
 u32 format, u64 modifier)
 {
@@ -2362,6 +2416,15 @@ static const struct drm_plane_funcs skl_plane_funcs = {
.format_mod_supported = skl_plane_format_mod_supported,
 };
 
+static const struct drm_plane_funcs icl_plane_funcs = {
+   .update_plane = drm_atomic_helper_update_plane,
+   .disable_plane = drm_atomic_helper_disable_plane,
+   .destroy = intel_plane_destroy,
+   .atomic_duplicate_state = intel_plane_duplicate_state,
+   .atomic_destroy_state = intel_plane_destroy_state,
+   .format_mod_supported = icl_plane_format_mod_supported,
+};
+
 static const struct drm_plane_funcs gen12_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
@@ -2538,6 +2601,8 @@ skl_universal_plane_create(struct drm_i915_private 
*dev_priv,
 
if (DISPLAY_VER(dev_priv) >= 12)
plane_funcs = &gen12_plane_funcs;
+   else if (DISPLAY_VER(dev_priv) == 11)
+   plane_funcs = &icl_plane_funcs;
else
plane_funcs = &skl_plane_funcs;
 
-- 
2.44.2



[PATCH 1/5] drm/i915: Disable compression tricks on JSL

2024-06-24 Thread Ville Syrjala
From: Ville Syrjälä 

Bspec asks us to disable some compression trick on JSL. While the
bspec description is pretty vague it looks like this is some extra
trick for 10bpc+ CCS which presumably the ICL derived display engine
doesn't support.

Note that we aren't currently exposing 10bpc CCS scanout support,
but once that gets added this presumably becomes an issue.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/gt/intel_gt_regs.h | 1 +
 drivers/gpu/drm/i915/gt/intel_workarounds.c | 9 +
 2 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h 
b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
index e42b3a5d4e63..af53c40e6c21 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
@@ -432,6 +432,7 @@
 #define XEHPG_INSTDONE_GEOM_SVGMCR_REG(0x666c)
 
 #define CACHE_MODE_0_GEN7  _MMIO(0x7000) /* IVB+ */
+#define   DISABLE_REPACKING_FOR_COMPRESSIONREG_BIT(15) /* jsl+ */
 #define   RC_OP_FLUSH_ENABLE   (1 << 0)
 #define   HIZ_RAW_STALL_OPT_DISABLE(1 << 2)
 #define CACHE_MODE_1   _MMIO(0x7004) /* IVB+ */
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 09a287c1aedd..a424b442493f 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -2286,6 +2286,15 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, 
struct i915_wa_list *wal)
 GEN8_RC_SEMA_IDLE_MSG_DISABLE);
}
 
+   if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) {
+   /*
+* "Disable Repacking for Compression (masked R/W access)
+*  before rendering compressed surfaces for display."
+*/
+   wa_masked_en(wal, CACHE_MODE_0_GEN7,
+DISABLE_REPACKING_FOR_COMPRESSION);
+   }
+
if (GRAPHICS_VER(i915) == 11) {
/* This is not an Wa. Enable for better image quality */
wa_masked_en(wal,
-- 
2.44.2



  1   2   3   4   5   6   7   8   9   10   >