]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/amd/display: Move power control from link encoder to hwsequencer
authorAndrew Jiang <Andrew.Jiang@amd.com>
Mon, 25 Sep 2017 22:03:14 +0000 (18:03 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Sat, 21 Oct 2017 20:44:08 +0000 (16:44 -0400)
A recent commit moved the backlight control code along with the register
defines, but did not move the power control code. This along with
remnant fields in the dce110_link_enc_registers struct made it so that
the code still compiled, but any attempts to access the
LVTMA_PWRSEQ_STATE register led to reading from an address of 0. This
patch corrects that.

Also, rename blacklight_control to edp_backlight_control (Typo fix).

Signed-off-by: Andrew Jiang <Andrew.Jiang@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
12 files changed:
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h
drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c

index a58e61b6e9f9a6e6fdcda2e5dfd92768c970dea9..feb10be0ce4caf59c5c362cc76bfc2c345f32eca 100644 (file)
@@ -78,14 +78,15 @@ static void destruct(struct dc_link *link)
                dc_sink_release(link->remote_sinks[i]);
 }
 
-static struct gpio *get_hpd_gpio(const struct dc_link *link)
+struct gpio *get_hpd_gpio(struct dc_bios *dcb,
+               struct graphics_object_id link_id,
+               struct gpio_service *gpio_service)
 {
        enum bp_result bp_result;
-       struct dc_bios *dcb = link->ctx->dc_bios;
        struct graphics_object_hpd_info hpd_info;
        struct gpio_pin_info pin_info;
 
-       if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK)
+       if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK)
                return NULL;
 
        bp_result = dcb->funcs->get_gpio_pin_info(dcb,
@@ -97,7 +98,7 @@ static struct gpio *get_hpd_gpio(const struct dc_link *link)
        }
 
        return dal_gpio_service_create_irq(
-               link->ctx->gpio_service,
+               gpio_service,
                pin_info.offset,
                pin_info.mask);
 }
@@ -153,7 +154,7 @@ static bool program_hpd_filter(
        }
 
        /* Obtain HPD handle */
-       hpd = get_hpd_gpio(link);
+       hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
 
        if (!hpd)
                return result;
@@ -186,7 +187,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type)
        struct gpio *hpd_pin;
 
        /* todo: may need to lock gpio access */
-       hpd_pin = get_hpd_gpio(link);
+       hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
        if (hpd_pin == NULL)
                goto hpd_gpio_failure;
 
@@ -795,7 +796,7 @@ static enum hpd_source_id get_hpd_line(
        struct gpio *hpd;
        enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;
 
-       hpd = get_hpd_gpio(link);
+       hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
 
        if (hpd) {
                switch (dal_irq_get_source(hpd)) {
@@ -965,7 +966,7 @@ static bool construct(
                goto create_fail;
        }
 
-       hpd_gpio = get_hpd_gpio(link);
+       hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
 
        if (hpd_gpio != NULL)
                link->irq_source_hpd = dal_irq_get_source(hpd_gpio);
index fa2250554be504e79c3a263430aea99bad19c56e..34b6d1cb151eefd474fc593a1fc6e6b8fb718af9 100644 (file)
@@ -89,12 +89,12 @@ void dp_enable_link_phy(
 
        if (dc_is_dp_sst_signal(signal)) {
                if (signal == SIGNAL_TYPE_EDP) {
-                       link_enc->funcs->power_control(link_enc, true);
+                       link->dc->hwss.edp_power_control(link->link_enc, true);
                        link_enc->funcs->enable_dp_output(
                                                link_enc,
                                                link_settings,
                                                clock_source);
-                       link->dc->hwss.backlight_control(link, true);
+                       link->dc->hwss.edp_backlight_control(link, true);
                } else
                        link_enc->funcs->enable_dp_output(
                                                link_enc,
@@ -138,10 +138,10 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
                dp_receiver_power_ctrl(link, false);
 
        if (signal == SIGNAL_TYPE_EDP) {
-               link->dc->hwss.backlight_control(link, false);
+               link->dc->hwss.edp_backlight_control(link, false);
                edp_receiver_ready_T9(link);
                link->link_enc->funcs->disable_output(link->link_enc, signal, link);
-               link->link_enc->funcs->power_control(link->link_enc, false);
+               link->dc->hwss.edp_power_control(link->link_enc, false);
        } else
                link->link_enc->funcs->disable_output(link->link_enc, signal, link);
 
index 227c9b655b65533db905f5a6ec1330a0e0032418..0a058e0c3fec846068026d20545d0019623cb0b5 100644 (file)
@@ -391,23 +391,27 @@ struct dce_hwseq_registers {
        HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\
        HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\
        HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
+       HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
        HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
 
 #define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\
        HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\
        HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\
        HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_), \
-       HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh)
+       HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
+       HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
 
 #define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\
        HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
        SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\
        HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
+       HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
        HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
 
 #define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\
        HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
        HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
+       HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
        HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_)
 
 #define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\
@@ -416,7 +420,8 @@ struct dce_hwseq_registers {
        SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\
        SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\
        SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh), \
-       HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh)
+       HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
+       HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
 
 #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\
        HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\
@@ -424,7 +429,8 @@ struct dce_hwseq_registers {
        HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\
        HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\
        HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh), \
-       HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh)
+       HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
+       HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
 
 #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\
        HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\
@@ -489,7 +495,8 @@ struct dce_hwseq_registers {
        HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \
        HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \
        HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
-       HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh)
+       HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
+       HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
 
 #define HWSEQ_REG_FIELD_LIST(type) \
        type DCFE_CLOCK_ENABLE; \
@@ -520,7 +527,8 @@ struct dce_hwseq_registers {
        type LOGICAL_ADDR; \
        type ENABLE_L1_TLB;\
        type SYSTEM_ACCESS_MODE;\
-       type LVTMA_BLON;
+       type LVTMA_BLON;\
+       type LVTMA_PWRSEQ_TARGET_STATE_R;
 
 #define HWSEQ_DCN_REG_FIELD_LIST(type) \
        type VUPDATE_NO_LOCK_EVENT_CLEAR; \
index 1cb727bdaa562e534bb126dadd9bf016b9e02f8d..0cf0fff74d44f04d89339a82e379d5f2e4d697dd 100644 (file)
 #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
 #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40
 
-/* all values are in milliseconds */
-/* For eDP, after power-up/power/down,
- * 300/500 msec max. delay from LCDVCC to black video generation */
-#define PANEL_POWER_UP_TIMEOUT 300
-#define PANEL_POWER_DOWN_TIMEOUT 500
-#define HPD_CHECK_INTERVAL 10
-
 /* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */
 #define TMDS_MIN_PIXEL_CLOCK 25000
 /* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */
@@ -122,7 +115,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
        .psr_program_dp_dphy_fast_training =
                        dce110_psr_program_dp_dphy_fast_training,
        .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
-       .power_control = dce110_link_encoder_edp_power_control,
        .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
        .enable_hpd = dce110_link_encoder_enable_hpd,
        .disable_hpd = dce110_link_encoder_disable_hpd,
@@ -492,165 +484,6 @@ static void configure_encoder(
        REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);
 }
 
-static bool is_panel_powered_on(struct dce110_link_encoder *enc110)
-{
-       bool ret;
-       uint32_t value;
-
-       REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value);
-       ret = value;
-
-       return ret == 1;
-}
-
-
-/* TODO duplicate of dc_link.c version */
-static struct gpio *get_hpd_gpio(const struct link_encoder *enc)
-{
-       enum bp_result bp_result;
-       struct dc_bios *dcb = enc->ctx->dc_bios;
-       struct graphics_object_hpd_info hpd_info;
-       struct gpio_pin_info pin_info;
-
-       if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK)
-               return NULL;
-
-       bp_result = dcb->funcs->get_gpio_pin_info(dcb,
-               hpd_info.hpd_int_gpio_uid, &pin_info);
-
-       if (bp_result != BP_RESULT_OK) {
-               ASSERT(bp_result == BP_RESULT_NORECORD);
-               return NULL;
-       }
-
-       return dal_gpio_service_create_irq(
-               enc->ctx->gpio_service,
-               pin_info.offset,
-               pin_info.mask);
-}
-
-/*
- * @brief
- * eDP only.
- */
-static void link_encoder_edp_wait_for_hpd_ready(
-       struct dce110_link_encoder *enc110,
-       bool power_up)
-{
-       struct dc_context *ctx = enc110->base.ctx;
-       struct graphics_object_id connector = enc110->base.connector;
-       struct gpio *hpd;
-       bool edp_hpd_high = false;
-       uint32_t time_elapsed = 0;
-       uint32_t timeout = power_up ?
-               PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
-
-       if (dal_graphics_object_id_get_connector_id(connector) !=
-               CONNECTOR_ID_EDP) {
-               BREAK_TO_DEBUGGER();
-               return;
-       }
-
-       if (!power_up)
-               /* from KV, we will not HPD low after turning off VCC -
-                * instead, we will check the SW timer in power_up(). */
-               return;
-
-       /* when we power on/off the eDP panel,
-        * we need to wait until SENSE bit is high/low */
-
-       /* obtain HPD */
-       /* TODO what to do with this? */
-       hpd = get_hpd_gpio(&enc110->base);
-
-       if (!hpd) {
-               BREAK_TO_DEBUGGER();
-               return;
-       }
-
-       dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
-
-       /* wait until timeout or panel detected */
-
-       do {
-               uint32_t detected = 0;
-
-               dal_gpio_get_value(hpd, &detected);
-
-               if (!(detected ^ power_up)) {
-                       edp_hpd_high = true;
-                       break;
-               }
-
-               msleep(HPD_CHECK_INTERVAL);
-
-               time_elapsed += HPD_CHECK_INTERVAL;
-       } while (time_elapsed < timeout);
-
-       dal_gpio_close(hpd);
-
-       dal_gpio_destroy_irq(&hpd);
-
-       if (false == edp_hpd_high) {
-               dm_logger_write(ctx->logger, LOG_ERROR,
-                               "%s: wait timed out!\n", __func__);
-       }
-}
-
-/*
- * @brief
- * eDP only. Control the power of the eDP panel.
- */
-void dce110_link_encoder_edp_power_control(
-       struct link_encoder *enc,
-       bool power_up)
-{
-       struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-       struct dc_context *ctx = enc110->base.ctx;
-       struct bp_transmitter_control cntl = { 0 };
-       enum bp_result bp_result;
-
-       if (dal_graphics_object_id_get_connector_id(enc110->base.connector) !=
-               CONNECTOR_ID_EDP) {
-               BREAK_TO_DEBUGGER();
-               return;
-       }
-
-       if ((power_up && !is_panel_powered_on(enc110)) ||
-               (!power_up && is_panel_powered_on(enc110))) {
-
-               /* Send VBIOS command to prompt eDP panel power */
-
-               dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
-                               "%s: Panel Power action: %s\n",
-                               __func__, (power_up ? "On":"Off"));
-
-               cntl.action = power_up ?
-                       TRANSMITTER_CONTROL_POWER_ON :
-                       TRANSMITTER_CONTROL_POWER_OFF;
-               cntl.transmitter = enc110->base.transmitter;
-               cntl.connector_obj_id = enc110->base.connector;
-               cntl.coherent = false;
-               cntl.lanes_number = LANE_COUNT_FOUR;
-               cntl.hpd_sel = enc110->base.hpd_source;
-
-               bp_result = link_transmitter_control(enc110, &cntl);
-
-               if (BP_RESULT_OK != bp_result) {
-
-                       dm_logger_write(ctx->logger, LOG_ERROR,
-                                       "%s: Panel Power bp_result: %d\n",
-                                       __func__, bp_result);
-               }
-       } else {
-               dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
-                               "%s: Skipping Panel Power action: %s\n",
-                               __func__, (power_up ? "On":"Off"));
-       }
-
-       link_encoder_edp_wait_for_hpd_ready(enc110, true);
-}
-
 static void aux_initialize(
        struct dce110_link_encoder *enc110)
 {
@@ -1018,7 +851,7 @@ void dce110_link_encoder_hw_init(
                ASSERT(result == BP_RESULT_OK);
 
        } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) {
-               enc->funcs->power_control(&enc110->base, true);
+               ctx->dc->hwss.edp_power_control(enc, true);
        }
        aux_initialize(enc110);
 
@@ -1218,7 +1051,7 @@ void dce110_link_encoder_disable_output(
                return;
        }
        if (enc110->base.connector.id == CONNECTOR_ID_EDP)
-               ctx->dc->hwss.backlight_control(link, false);
+               ctx->dc->hwss.edp_backlight_control(link, false);
        /* Power-down RX and disable GPU PHY should be paired.
         * Disabling PHY without powering down RX may cause
         * symbol lock loss, on which we will get DP Sink interrupt. */
index c65def5f6a441457b560c7d9db146759e9c1238b..494067dedd03a13388fdfa25d99bd63741757fac 100644 (file)
@@ -114,10 +114,6 @@ struct dce110_link_enc_hpd_registers {
 };
 
 struct dce110_link_enc_registers {
-       /* Backlight registers */
-       uint32_t LVTMA_PWRSEQ_CNTL;
-       uint32_t LVTMA_PWRSEQ_STATE;
-
        /* DMCU registers */
        uint32_t MASTER_COMM_DATA_REG1;
        uint32_t MASTER_COMM_DATA_REG2;
@@ -250,10 +246,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table(
        struct link_encoder *enc,
        const struct link_mst_stream_allocation_table *table);
 
-void dce110_link_encoder_edp_power_control(
-       struct link_encoder *enc,
-       bool power_up);
-
 void dce110_link_encoder_connect_dig_be_to_fe(
        struct link_encoder *enc,
        enum engine_id engine,
index f28fce6e6ba4e8a9d0ba3351ac9083970af2956d..a891e387ed7b534b0df5d52a548c37e94ae6c427 100644 (file)
@@ -32,6 +32,7 @@
 #include "dce110_hw_sequencer.h"
 #include "dce110_timing_generator.h"
 #include "dce/dce_hwseq.h"
+#include "gpio_service_interface.h"
 
 #ifdef ENABLE_FBC
 #include "dce110_compressor.h"
 #include "transform.h"
 #include "stream_encoder.h"
 #include "link_encoder.h"
+#include "link_hwss.h"
 #include "clock_source.h"
 #include "abm.h"
 #include "audio.h"
-#include "dce/dce_hwseq.h"
 #include "reg_helper.h"
 
 /* include DCE11 register header files */
 #include "dce/dce_11_0_sh_mask.h"
 #include "custom_float.h"
 
+/*
+ * All values are in milliseconds;
+ * For eDP, after power-up/power/down,
+ * 300/500 msec max. delay from LCDVCC to black video generation
+ */
+#define PANEL_POWER_UP_TIMEOUT 300
+#define PANEL_POWER_DOWN_TIMEOUT 500
+#define HPD_CHECK_INTERVAL 10
+
 #define CTX \
        hws->ctx
 #define REG(reg)\
@@ -780,25 +790,150 @@ static bool is_panel_backlight_on(struct dce_hwseq *hws)
        return value;
 }
 
+static bool is_panel_powered_on(struct dce_hwseq *hws)
+{
+       uint32_t value;
+
+       REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value);
+       return value == 1;
+}
+
 static enum bp_result link_transmitter_control(
-               struct dc_link *link,
+               struct dc_bios *bios,
        struct bp_transmitter_control *cntl)
 {
        enum bp_result result;
-       struct dc_bios *bp = link->dc->ctx->dc_bios;
 
-       result = bp->funcs->transmitter_control(bp, cntl);
+       result = bios->funcs->transmitter_control(bios, cntl);
 
        return result;
 }
 
+/*
+ * @brief
+ * eDP only.
+ */
+void hwss_edp_wait_for_hpd_ready(
+       struct link_encoder *enc,
+       bool power_up)
+{
+       struct dc_context *ctx = enc->ctx;
+       struct graphics_object_id connector = enc->connector;
+       struct gpio *hpd;
+       bool edp_hpd_high = false;
+       uint32_t time_elapsed = 0;
+       uint32_t timeout = power_up ?
+               PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
+
+       if (dal_graphics_object_id_get_connector_id(connector)
+                       != CONNECTOR_ID_EDP) {
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       if (!power_up)
+               /*
+                * From KV, we will not HPD low after turning off VCC -
+                * instead, we will check the SW timer in power_up().
+                */
+               return;
+
+       /*
+        * When we power on/off the eDP panel,
+        * we need to wait until SENSE bit is high/low.
+        */
+
+       /* obtain HPD */
+       /* TODO what to do with this? */
+       hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
+
+       if (!hpd) {
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
+
+       /* wait until timeout or panel detected */
+
+       do {
+               uint32_t detected = 0;
+
+               dal_gpio_get_value(hpd, &detected);
+
+               if (!(detected ^ power_up)) {
+                       edp_hpd_high = true;
+                       break;
+               }
+
+               msleep(HPD_CHECK_INTERVAL);
+
+               time_elapsed += HPD_CHECK_INTERVAL;
+       } while (time_elapsed < timeout);
+
+       dal_gpio_close(hpd);
+
+       dal_gpio_destroy_irq(&hpd);
+
+       if (false == edp_hpd_high) {
+               dm_logger_write(ctx->logger, LOG_ERROR,
+                               "%s: wait timed out!\n", __func__);
+       }
+}
+
+void hwss_edp_power_control(
+       struct link_encoder *enc,
+       bool power_up)
+{
+       struct dc_context *ctx = enc->ctx;
+       struct dce_hwseq *hwseq = ctx->dc->hwseq;
+       struct bp_transmitter_control cntl = { 0 };
+       enum bp_result bp_result;
+
+
+       if (dal_graphics_object_id_get_connector_id(enc->connector)
+                       != CONNECTOR_ID_EDP) {
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       if (power_up != is_panel_powered_on(hwseq)) {
+               /* Send VBIOS command to prompt eDP panel power */
+
+               dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
+                               "%s: Panel Power action: %s\n",
+                               __func__, (power_up ? "On":"Off"));
+
+               cntl.action = power_up ?
+                       TRANSMITTER_CONTROL_POWER_ON :
+                       TRANSMITTER_CONTROL_POWER_OFF;
+               cntl.transmitter = enc->transmitter;
+               cntl.connector_obj_id = enc->connector;
+               cntl.coherent = false;
+               cntl.lanes_number = LANE_COUNT_FOUR;
+               cntl.hpd_sel = enc->hpd_source;
+
+               bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
+
+               if (bp_result != BP_RESULT_OK)
+                       dm_logger_write(ctx->logger, LOG_ERROR,
+                                       "%s: Panel Power bp_result: %d\n",
+                                       __func__, bp_result);
+       } else {
+               dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
+                               "%s: Skipping Panel Power action: %s\n",
+                               __func__, (power_up ? "On":"Off"));
+       }
+
+       hwss_edp_wait_for_hpd_ready(enc, true);
+}
 
 /*todo: cloned in stream enc, fix*/
 /*
  * @brief
  * eDP only. Control the backlight of the eDP panel
  */
-void hwss_blacklight_control(
+void hwss_edp_backlight_control(
        struct dc_link *link,
        bool enable)
 {
@@ -828,6 +963,7 @@ void hwss_blacklight_control(
        cntl.action = enable ?
                TRANSMITTER_CONTROL_BACKLIGHT_ON :
                TRANSMITTER_CONTROL_BACKLIGHT_OFF;
+
        /*cntl.engine_id = ctx->engine;*/
        cntl.transmitter = link->link_enc->transmitter;
        cntl.connector_obj_id = link->link_enc->connector;
@@ -846,7 +982,7 @@ void hwss_blacklight_control(
         * Enable it in the future if necessary.
         */
        /* dc_service_sleep_in_milliseconds(50); */
-       link_transmitter_control(link, &cntl);
+       link_transmitter_control(link->dc->ctx->dc_bios, &cntl);
 }
 
 void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
@@ -886,7 +1022,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
        /* blank at encoder level */
        if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
                if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP)
-                       hwss_blacklight_control(link, false);
+                       hwss_edp_backlight_control(link, false);
                pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
        }
        link->link_enc->funcs->connect_dig_be_to_fe(
@@ -908,7 +1044,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
        params.link_settings.link_rate = link_settings->link_rate;
        pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, &params);
        if (link->connector_signal == SIGNAL_TYPE_EDP)
-               hwss_blacklight_control(link, true);
+               hwss_edp_backlight_control(link, true);
 }
 
 
@@ -2821,7 +2957,8 @@ static const struct hw_sequencer_funcs dce110_funcs = {
        .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
        .ready_shared_resources = ready_shared_resources,
        .optimize_shared_resources = optimize_shared_resources,
-       .backlight_control = hwss_blacklight_control
+       .edp_backlight_control = hwss_edp_backlight_control,
+       .edp_power_control = hwss_edp_power_control,
 };
 
 void dce110_hw_sequencer_construct(struct dc *dc)
index 3e95f7f92c737a6325b1e5d1f97efecd6b6786fb..a1e964af60ac135d6849de9718d485f8600ee4c3 100644 (file)
@@ -69,7 +69,11 @@ uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context);
 
 void dp_receiver_power_ctrl(struct dc_link *link, bool on);
 
-void hwss_blacklight_control(
+void hwss_edp_power_control(
+       struct link_encoder *enc,
+       bool power_up);
+
+void hwss_edp_backlight_control(
        struct dc_link *link,
        bool enable);
 
index 014911ebdbd6f145d524404ed3c378aed6194557..efa3f6f97bafb3f2abe805e3ea651d12a177de39 100644 (file)
@@ -2903,7 +2903,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
        .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
        .ready_shared_resources = ready_shared_resources,
        .optimize_shared_resources = optimize_shared_resources,
-       .backlight_control = hwss_blacklight_control
+       .edp_backlight_control = hwss_edp_backlight_control,
+       .edp_power_control = hwss_edp_power_control
 };
 
 
index 6cd6bc7d15fbeaddce6ad038cc7a01b202cc2055..3d33bcda7059432d4b0343311bf7d3b998accda9 100644 (file)
@@ -123,8 +123,6 @@ struct link_encoder_funcs {
                        bool exit_link_training_required);
        void (*psr_program_secondary_packet)(struct link_encoder *enc,
                                unsigned int sdp_transmit_line_num_deadline);
-       void (*power_control) (struct link_encoder *enc,
-               bool power_up);
        void (*connect_dig_be_to_fe)(struct link_encoder *enc,
                enum engine_id engine,
                bool connect);
index 210874f37722a5f493e5e8629ae33af93d837177..bf3ab5d7398e34c57c82d41fb3e5424d43cd46a3 100644 (file)
@@ -28,6 +28,7 @@
 #include "dc_types.h"
 #include "clock_source.h"
 #include "inc/hw/timing_generator.h"
+#include "inc/hw/link_encoder.h"
 #include "core_status.h"
 
 enum pipe_gating_control {
@@ -176,8 +177,10 @@ struct hw_sequencer_funcs {
 
        void (*ready_shared_resources)(struct dc *dc, struct dc_state *context);
        void (*optimize_shared_resources)(struct dc *dc);
-
-       void (*backlight_control)(
+       void (*edp_power_control)(
+                       struct link_encoder *enc,
+                       bool enable);
+       void (*edp_backlight_control)(
                        struct dc_link *link,
                        bool enable);
 };
index f7994cfc850d637ed148fafad146241a6cf7fefb..f2b8c9a376d5a7f8e70c7b8ddd7afbc7c0dee197 100644 (file)
@@ -40,6 +40,10 @@ enum dc_status core_link_write_dpcd(
        const uint8_t *data,
        uint32_t size);
 
+struct gpio *get_hpd_gpio(struct dc_bios *dcb,
+               struct graphics_object_id link_id,
+               struct gpio_service *gpio_service);
+
 void dp_enable_link_phy(
        struct dc_link *link,
        enum signal_type signal,
index 4f405348130f23b543c499120a305db31c255de3..88c2bde3f0392353170603de3530d377afbff972 100644 (file)
@@ -73,10 +73,6 @@ static void virtual_link_encoder_update_mst_stream_allocation_table(
        struct link_encoder *enc,
        const struct link_mst_stream_allocation_table *table) {}
 
-static void virtual_link_encoder_edp_power_control(
-       struct link_encoder *enc,
-       bool power_up) {}
-
 static void virtual_link_encoder_connect_dig_be_to_fe(
        struct link_encoder *enc,
        enum engine_id engine,
@@ -102,7 +98,6 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = {
        .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern,
        .update_mst_stream_allocation_table =
                virtual_link_encoder_update_mst_stream_allocation_table,
-       .power_control = virtual_link_encoder_edp_power_control,
        .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe,
        .destroy = virtual_link_encoder_destroy
 };