]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/dp: Track source OUI validity explicitly
authorImre Deak <imre.deak@intel.com>
Fri, 25 Oct 2024 16:02:55 +0000 (19:02 +0300)
committerImre Deak <imre.deak@intel.com>
Thu, 31 Oct 2024 16:10:11 +0000 (18:10 +0200)
While updating the source OUI on the sink the driver should avoid
writing the OUI if it's already up-to-date to prevent the sink from
resetting itself in response to the update. On eDP - the only output
type where the OUI was updated so far - the driver ensured this by
comparing the current source OUI DPCD register values with the expected
Intel OUI value, skipping the update in case of a match. On some non-eDP
sinks - at least on Synaptics branch devices - this method doesn't work,
since the source OUI DPCD registers read back as all 0, even after
updating the registers.

Handle the above kind of sinks by tracking when the OUI was updated and
so should be valid, regardless of what the DPCD registers contain.

eDP sinks reset the written source OUI value when the panel power is
disabled, invalidate the OUI state accordingly.

This is required by a follow-up patch updating the source OUI for
non-eDP sink types as well.

v2: Fix setting intel_dp::oui_valid=true, if the DPCD register contains
    already the expected value.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241025160259.3088727-5-imre.deak@intel.com
drivers/gpu/drm/i915/display/g4x_dp.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dp.h
drivers/gpu/drm/i915/display/intel_pps.c

index 7f19e4dac6217423b683a782d6a4d2b48dc6b448..4fbec065d53ebae73d8559ae65aadbb176273a24 100644 (file)
@@ -1249,6 +1249,7 @@ static void intel_dp_encoder_reset(struct drm_encoder *encoder)
        intel_dp->DP = intel_de_read(display, intel_dp->output_reg);
 
        intel_dp->reset_link_params = true;
+       intel_dp_invalidate_source_oui(intel_dp);
 
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                vlv_pps_pipe_reset(intel_dp);
index 2bd14e2134be93ab10a3aaa880069fc2ec84106a..eca12f0cbeca4a49ab4ade0244d042bda7264c15 100644 (file)
@@ -4392,6 +4392,7 @@ static void intel_ddi_encoder_reset(struct drm_encoder *encoder)
        struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
 
        intel_dp->reset_link_params = true;
+       intel_dp_invalidate_source_oui(intel_dp);
 
        intel_pps_encoder_reset(intel_dp);
 
index e63a1d23316cd74735d6ee1be94940ee85c49c36..d2b68505f0881684ba5edcac88e2feb315bc018e 100644 (file)
@@ -1765,6 +1765,7 @@ struct intel_dp {
 
        /* When we last wrote the OUI for eDP */
        unsigned long last_oui_write;
+       bool oui_valid;
 
        bool colorimetry_support;
 
index 735890334de3eecfa0f8575e38496a6cad251704..c2682b7ae86784ea6c2700657147007f89668b8c 100644 (file)
@@ -3404,33 +3404,46 @@ void intel_dp_sink_disable_decompression(struct intel_atomic_state *state,
 }
 
 static void
-intel_edp_init_source_oui(struct intel_dp *intel_dp, bool careful)
+intel_dp_init_source_oui(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
        u8 oui[] = { 0x00, 0xaa, 0x01 };
        u8 buf[3] = {};
 
+       if (!intel_dp_is_edp(intel_dp))
+               return;
+
+       if (READ_ONCE(intel_dp->oui_valid))
+               return;
+
+       WRITE_ONCE(intel_dp->oui_valid, true);
+
        /*
         * During driver init, we want to be careful and avoid changing the source OUI if it's
         * already set to what we want, so as to avoid clearing any state by accident
         */
-       if (careful) {
-               if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)) < 0)
-                       drm_err(&i915->drm, "Failed to read source OUI\n");
+       if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)) < 0)
+               drm_err(&i915->drm, "Failed to read source OUI\n");
 
-               if (memcmp(oui, buf, sizeof(oui)) == 0) {
-                       /* Assume the OUI was written now. */
-                       intel_dp->last_oui_write = jiffies;
-                       return;
-               }
+       if (memcmp(oui, buf, sizeof(oui)) == 0) {
+               /* Assume the OUI was written now. */
+               intel_dp->last_oui_write = jiffies;
+               return;
        }
 
-       if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0)
+       if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) {
                drm_info(&i915->drm, "Failed to write source OUI\n");
+               WRITE_ONCE(intel_dp->oui_valid, false);
+       }
 
        intel_dp->last_oui_write = jiffies;
 }
 
+void intel_dp_invalidate_source_oui(struct intel_dp *intel_dp)
+{
+       WRITE_ONCE(intel_dp->oui_valid, false);
+}
+
 void intel_dp_wait_source_oui(struct intel_dp *intel_dp)
 {
        struct intel_connector *connector = intel_dp->attached_connector;
@@ -3466,8 +3479,7 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode)
                lspcon_resume(dp_to_dig_port(intel_dp));
 
                /* Write the source OUI as early as possible */
-               if (intel_dp_is_edp(intel_dp))
-                       intel_edp_init_source_oui(intel_dp, false);
+               intel_dp_init_source_oui(intel_dp);
 
                /*
                 * When turning on, we need to retry for 1ms to give the sink
@@ -4188,7 +4200,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector
         * If needed, program our source OUI so we can make various Intel-specific AUX services
         * available (such as HDR backlight controls)
         */
-       intel_edp_init_source_oui(intel_dp, true);
+       intel_dp_init_source_oui(intel_dp);
 
        return true;
 }
index 4efb9605a50e0077343134a6235c70d65dc35f90..48f10876be656684a0c07ea643bb02c65a6d8b2e 100644 (file)
@@ -189,6 +189,7 @@ void intel_dp_check_frl_training(struct intel_dp *intel_dp);
 void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
                                 const struct intel_crtc_state *crtc_state);
 
+void intel_dp_invalidate_source_oui(struct intel_dp *intel_dp);
 void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
 int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
 
index a1b2c400d6a54881fc01957b63031b5061685205..093fe37a39833c164695f4b43da5b0674a981568 100644 (file)
@@ -857,8 +857,10 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
                    intel_de_read(display, pp_stat_reg),
                    intel_de_read(display, pp_ctrl_reg));
 
-       if ((pp & PANEL_POWER_ON) == 0)
+       if ((pp & PANEL_POWER_ON) == 0) {
                intel_dp->pps.panel_power_off_time = ktime_get_boottime();
+               intel_dp_invalidate_source_oui(intel_dp);
+       }
 
        intel_display_power_put(dev_priv,
                                intel_aux_power_domain(dig_port),
@@ -1068,6 +1070,8 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
        wait_panel_off(intel_dp);
        intel_dp->pps.panel_power_off_time = ktime_get_boottime();
 
+       intel_dp_invalidate_source_oui(intel_dp);
+
        /* We got a reference when we enabled the VDD. */
        intel_display_power_put(dev_priv,
                                intel_aux_power_domain(dig_port),