Add accessor function for Snps to read requested table from VBT #57.
Parse the requested table and transform data into port's buffer.

For C20, use 6th table if encoder supports DP 2.0 or higher. Otherwise
use 5th table for DP.

For C20, tables 1-4 are not used at all and are most likely to be
zeroed. 5th table is used for any mode below DP 2.0 (exclusive). 6th
table is used for any mode above DP 2.0 (inclusive).

For C10, use 2nd table for external DP if encoder supports any mode
beyond or including HBR2. Use 1st table if external DP encoder supports
anything lower than HBR2. For eDP, use 4th table if encoder supports
HBR3. Otherwise use 3rd table for eDP.

For C10, 1st table is used for external DP with modes below HBR2
(exclusive). 1st table is also used as a fallback for non-DPs. 2nd
table is used for external DP with modes higher than HBR2 (inclusive).
3rd table is used for eDP with modes lower than HBR3 (exclusive). 4th
table is used for eDP with modes higher than HBR3 (inclusive).

Indices for other tables have not yet been observed to be used as of
now.

There are no changes to intel_ddi_dp_level() since selection of correct
row of intel_ddi_buf_trans_entry is same as when no override request has
been done.

v4->v5
- blend index computation with table parsing
- remove enums entirely
- change funcs prefix from snps_ to mtl_ (Suraj)
- add spaces around operators (Suraj)
- remove spaces after type casting (Suraj)
- remove INTEL_DISPLAY_STATE_WARN (Suraj)

v3->v4
- stick to solely changing VBT data into current structures (Jani)
- move iterator declaration to declaration block (Suraj)

v2->v3
- remove unnecessary braces from if block (Suraj)
- return -EINVAL instead of -1 (Suraj)

Signed-off-by: Michał Grzelak <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_bios.c     | 30 ++++++++++++
 drivers/gpu/drm/i915/display/intel_bios.h     |  3 ++
 .../drm/i915/display/intel_ddi_buf_trans.c    | 47 ++++++++++++++++++-
 3 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index 97026d3cf6441..130cb32254dd5 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -3896,6 +3896,36 @@ intel_bios_get_lt_vspeo(const struct 
intel_bios_encoder_data *devdata,
        return vspeo;
 }
 
+const struct intel_ddi_buf_trans *
+intel_bios_get_cx0_vspeo(const struct intel_bios_encoder_data *devdata,
+                        int idx)
+{
+       struct intel_display *display = devdata->display;
+       struct intel_ddi_buf_trans *vspeo = (void *)devdata->vspeo;
+       union intel_ddi_buf_trans_entry *entries = (void *)vspeo->entries;
+       const u32 *tables = display->vbt.vspeo.tables;
+       int num_columns = display->vbt.vspeo.num_columns;
+       int num_rows = display->vbt.vspeo.num_rows;
+       size_t offset = 0;
+       int level;
+
+       offset += idx * num_rows * num_columns;
+
+       for (level = 0; level < num_rows; level++) {
+               u32 vswing = tables[offset];
+               u32 pre_cursor = tables[offset + 1];
+               u32 post_cursor = tables[offset + 2];
+
+               entries[level].snps.vswing = vswing;
+               entries[level].snps.pre_cursor = pre_cursor;
+               entries[level].snps.post_cursor = post_cursor;
+
+               offset += num_columns;
+       }
+
+       return vspeo;
+}
+
 bool intel_bios_encoder_is_dedicated_external(const struct 
intel_bios_encoder_data *devdata)
 {
        return devdata->display->vbt.version >= 264 &&
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h 
b/drivers/gpu/drm/i915/display/intel_bios.h
index 4a2fd30314fd6..940f42efd4d7e 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -76,6 +76,9 @@ intel_bios_encoder_data_lookup(struct intel_display *display, 
enum port port);
 const struct intel_ddi_buf_trans *
 intel_bios_get_lt_vspeo(const struct intel_bios_encoder_data *devdata,
                        int idx);
+const struct intel_ddi_buf_trans *
+intel_bios_get_cx0_vspeo(const struct intel_bios_encoder_data *devdata,
+                        int idx);
 
 bool intel_bios_encoder_requests_vspeo(const struct intel_bios_encoder_data 
*devdata);
 bool intel_bios_encoder_supports_dvi(const struct intel_bios_encoder_data 
*devdata);
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c 
b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
index 6f3eb0fa16c66..bb619f94f0ec1 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
@@ -1784,6 +1784,43 @@ xe3plpd_get_lt_buf_trans(struct intel_encoder *encoder,
                return intel_get_buf_trans(&xe3plpd_lt_trans_dp14, n_entries);
 }
 
+static const struct intel_ddi_buf_trans *
+mtl_get_c10_vspeo_buf_trans(struct intel_encoder *encoder,
+                           const struct intel_crtc_state *crtc_state,
+                           int *n_entries)
+{
+       if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
+               if (crtc_state->port_clock > 540000)
+                       return intel_bios_get_cx0_vspeo(encoder->devdata, 3);
+               else
+                       return intel_bios_get_cx0_vspeo(encoder->devdata, 2);
+       }
+
+       if (intel_crtc_has_dp_encoder(crtc_state)) {
+               if (crtc_state->port_clock > 270000)
+                       return intel_bios_get_cx0_vspeo(encoder->devdata, 1);
+               else
+                       return intel_bios_get_cx0_vspeo(encoder->devdata, 0);
+       }
+
+       return encoder->get_buf_trans(encoder, crtc_state, n_entries);
+}
+
+static const struct intel_ddi_buf_trans *
+mtl_get_c20_vspeo_buf_trans(struct intel_encoder *encoder,
+                           const struct intel_crtc_state *crtc_state,
+                           int *n_entries)
+{
+       if (intel_crtc_has_dp_encoder(crtc_state)) {
+               if (intel_dp_is_uhbr(crtc_state))
+                       return intel_bios_get_cx0_vspeo(encoder->devdata, 5);
+               else
+                       return intel_bios_get_cx0_vspeo(encoder->devdata, 4);
+       }
+
+       return encoder->get_buf_trans(encoder, crtc_state, n_entries);
+}
+
 static const struct intel_ddi_buf_trans *
 xe3plpd_get_lt_vspeo_buf_trans(struct intel_encoder *encoder,
                               const struct intel_crtc_state *crtc_state,
@@ -1880,10 +1917,16 @@ const struct intel_ddi_buf_trans 
*intel_ddi_buf_trans_get(struct intel_encoder *
        if (!vspeo)
                return encoder->get_buf_trans(encoder, crtc_state, n_entries);
 
-       if (HAS_LT_PHY(display))
+       if (HAS_LT_PHY(display)) {
                buf_trans = xe3plpd_get_lt_vspeo_buf_trans(encoder, crtc_state, 
n_entries);
-       else
+       } else if (DISPLAY_VER(display) >= 14) {
+               if (intel_encoder_is_c10phy(encoder))
+                       buf_trans = mtl_get_c10_vspeo_buf_trans(encoder, 
crtc_state, n_entries);
+               else
+                       buf_trans = mtl_get_c20_vspeo_buf_trans(encoder, 
crtc_state, n_entries);
+       } else {
                buf_trans = encoder->get_buf_trans(encoder, crtc_state, 
n_entries);
+       }
 
        return intel_get_buf_trans(buf_trans, n_entries);
 }
-- 
2.45.2

Reply via email to