summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/dp/dp_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/dp/dp_display.c')
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c196
1 files changed, 126 insertions, 70 deletions
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 7cc4d21f2091..178b774a5fbd 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -83,6 +83,7 @@ struct dp_display_private {
/* state variables */
bool core_initialized;
+ bool phy_initialized;
bool hpd_irq_on;
bool audio_supported;
@@ -143,10 +144,29 @@ static const struct msm_dp_config sc7280_dp_cfg = {
.num_descs = 2,
};
+static const struct msm_dp_config sc8180x_dp_cfg = {
+ .descs = (const struct msm_dp_desc[]) {
+ [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+ [MSM_DP_CONTROLLER_1] = { .io_start = 0x0ae98000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+ [MSM_DP_CONTROLLER_2] = { .io_start = 0x0ae9a000, .connector_type = DRM_MODE_CONNECTOR_eDP },
+ },
+ .num_descs = 3,
+};
+
+static const struct msm_dp_config sm8350_dp_cfg = {
+ .descs = (const struct msm_dp_desc[]) {
+ [MSM_DP_CONTROLLER_0] = { .io_start = 0x0ae90000, .connector_type = DRM_MODE_CONNECTOR_DisplayPort },
+ },
+ .num_descs = 1,
+};
+
static const struct of_device_id dp_dt_match[] = {
{ .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_cfg },
{ .compatible = "qcom,sc7280-dp", .data = &sc7280_dp_cfg },
{ .compatible = "qcom,sc7280-edp", .data = &sc7280_dp_cfg },
+ { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_cfg },
+ { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_cfg },
+ { .compatible = "qcom,sm8350-dp", .data = &sm8350_dp_cfg },
{}
};
@@ -246,7 +266,7 @@ static int dp_display_bind(struct device *dev, struct device *master,
goto end;
}
- dp->dp_display.panel_bridge = dp->parser->panel_bridge;
+ dp->dp_display.next_bridge = dp->parser->next_bridge;
dp->aux->drm_dev = drm;
rc = dp_aux_register(dp->aux);
@@ -372,36 +392,51 @@ end:
return rc;
}
-static void dp_display_host_init(struct dp_display_private *dp, int reset)
+static void dp_display_host_phy_init(struct dp_display_private *dp)
{
- bool flip = false;
+ DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized);
- DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized);
- if (dp->core_initialized) {
- DRM_DEBUG_DP("DP core already initialized\n");
- return;
+ if (!dp->phy_initialized) {
+ dp_ctrl_phy_init(dp->ctrl);
+ dp->phy_initialized = true;
+ }
+}
+
+static void dp_display_host_phy_exit(struct dp_display_private *dp)
+{
+ DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized);
+
+ if (dp->phy_initialized) {
+ dp_ctrl_phy_exit(dp->ctrl);
+ dp->phy_initialized = false;
}
+}
- if (dp->usbpd->orientation == ORIENTATION_CC2)
- flip = true;
+static void dp_display_host_init(struct dp_display_private *dp)
+{
+ DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized);
- dp_power_init(dp->power, flip);
- dp_ctrl_host_init(dp->ctrl, flip, reset);
+ dp_power_init(dp->power, false);
+ dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
dp_aux_init(dp->aux);
dp->core_initialized = true;
}
static void dp_display_host_deinit(struct dp_display_private *dp)
{
- if (!dp->core_initialized) {
- DRM_DEBUG_DP("DP core not initialized\n");
- return;
- }
+ DRM_DEBUG_DP("type=%d core_init=%d phy_init=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized);
- dp_ctrl_host_deinit(dp->ctrl);
+ dp_ctrl_reset_irq_ctrl(dp->ctrl, false);
dp_aux_deinit(dp->aux);
dp_power_deinit(dp->power);
-
dp->core_initialized = false;
}
@@ -409,7 +444,7 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
{
struct dp_display_private *dp = dev_get_dp_display_private(dev);
- dp_display_host_init(dp, false);
+ dp_display_host_phy_init(dp);
return dp_display_process_hpd_high(dp);
}
@@ -507,7 +542,9 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
- DRM_DEBUG_DP("hpd_state=%d\n", state);
+ DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
+
if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) {
mutex_unlock(&dp->event_mutex);
return 0;
@@ -530,11 +567,6 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
ret = dp_display_usbpd_configure_cb(&dp->pdev->dev);
if (ret) { /* link train failed */
dp->hpd_state = ST_DISCONNECTED;
-
- if (ret == -ECONNRESET) { /* cable unplugged */
- dp->core_initialized = false;
- }
-
} else {
/* start sentinel checking in case of missing uevent */
dp_add_event(dp, EV_CONNECT_PENDING_TIMEOUT, 0, tout);
@@ -544,6 +576,8 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
dp_catalog_hpd_config_intr(dp->catalog,
DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true);
+ DRM_DEBUG_DP("After, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
mutex_unlock(&dp->event_mutex);
/* uevent will complete connection part */
@@ -560,8 +594,10 @@ static int dp_connect_pending_timeout(struct dp_display_private *dp, u32 data)
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
- if (state == ST_CONNECT_PENDING)
+ if (state == ST_CONNECT_PENDING) {
dp->hpd_state = ST_CONNECTED;
+ DRM_DEBUG_DP("type=%d\n", dp->dp_display.connector_type);
+ }
mutex_unlock(&dp->event_mutex);
@@ -594,6 +630,9 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
state = dp->hpd_state;
+ DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
+
/* disable irq_hpd/replug interrupts */
dp_catalog_hpd_config_intr(dp->catalog,
DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, false);
@@ -604,8 +643,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
if (state == ST_DISCONNECTED) {
/* triggered by irq_hdp with sink_count = 0 */
if (dp->link->sink_count == 0) {
- dp_ctrl_off_phy(dp->ctrl);
- dp->core_initialized = false;
+ dp_display_host_phy_exit(dp);
}
mutex_unlock(&dp->event_mutex);
return 0;
@@ -637,13 +675,15 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
/* start sentinel checking in case of missing uevent */
dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
- DRM_DEBUG_DP("hpd_state=%d\n", state);
/* signal the disconnect event early to ensure proper teardown */
dp_display_handle_plugged_change(&dp->dp_display, false);
/* enable HDP plug interrupt to prepare for next plugin */
dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, true);
+ DRM_DEBUG_DP("After, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
+
/* uevent will complete disconnection part */
mutex_unlock(&dp->event_mutex);
return 0;
@@ -656,8 +696,10 @@ static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data
mutex_lock(&dp->event_mutex);
state = dp->hpd_state;
- if (state == ST_DISCONNECT_PENDING)
+ if (state == ST_DISCONNECT_PENDING) {
dp->hpd_state = ST_DISCONNECTED;
+ DRM_DEBUG_DP("type=%d\n", dp->dp_display.connector_type);
+ }
mutex_unlock(&dp->event_mutex);
@@ -667,12 +709,14 @@ static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data
static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
{
u32 state;
- int ret;
mutex_lock(&dp->event_mutex);
/* irq_hpd can happen at either connected or disconnected state */
state = dp->hpd_state;
+ DRM_DEBUG_DP("Before, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
+
if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) {
mutex_unlock(&dp->event_mutex);
return 0;
@@ -692,17 +736,10 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data)
return 0;
}
- /*
- * dp core (ahb/aux clks) must be initialized before
- * irq_hpd be handled
- */
- if (dp->core_initialized) {
- ret = dp_display_usbpd_attention_cb(&dp->pdev->dev);
- if (ret == -ECONNRESET) { /* cable unplugged */
- dp->core_initialized = false;
- }
- }
- DRM_DEBUG_DP("hpd_state=%d\n", state);
+ dp_display_usbpd_attention_cb(&dp->pdev->dev);
+
+ DRM_DEBUG_DP("After, type=%d hpd_state=%d\n",
+ dp->dp_display.connector_type, state);
mutex_unlock(&dp->event_mutex);
@@ -892,12 +929,19 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data)
dp_display->audio_enabled = false;
- /* triggered by irq_hpd with sink_count = 0 */
if (dp->link->sink_count == 0) {
+ /*
+ * irq_hpd with sink_count = 0
+ * hdmi unplugged out of dongle
+ */
dp_ctrl_off_link_stream(dp->ctrl);
} else {
+ /*
+ * unplugged interrupt
+ * dongle unplugged out of DUT
+ */
dp_ctrl_off(dp->ctrl);
- dp->core_initialized = false;
+ dp_display_host_phy_exit(dp);
}
dp_display->power_on = false;
@@ -1027,7 +1071,7 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp)
static void dp_display_config_hpd(struct dp_display_private *dp)
{
- dp_display_host_init(dp, true);
+ dp_display_host_init(dp);
dp_catalog_ctrl_hpd_config(dp->catalog);
/* Enable interrupt first time
@@ -1145,8 +1189,9 @@ static irqreturn_t dp_display_irq_handler(int irq, void *dev_id)
hpd_isr_status = dp_catalog_hpd_get_intr_status(dp->catalog);
- DRM_DEBUG_DP("hpd isr status=%#x\n", hpd_isr_status);
if (hpd_isr_status & 0x0F) {
+ DRM_DEBUG_DP("type=%d isr=0x%x\n",
+ dp->dp_display.connector_type, hpd_isr_status);
/* hpd related interrupts */
if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK)
dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0);
@@ -1299,27 +1344,31 @@ static int dp_pm_resume(struct device *dev)
mutex_lock(&dp->event_mutex);
- DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n",
- dp->core_initialized, dp_display->power_on);
+ DRM_DEBUG_DP("Before, type=%d core_inited=%d phy_inited=%d power_on=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized, dp_display->power_on);
/* start from disconnected state */
dp->hpd_state = ST_DISCONNECTED;
/* turn on dp ctrl/phy */
- dp_display_host_init(dp, true);
+ dp_display_host_init(dp);
dp_catalog_ctrl_hpd_config(dp->catalog);
- /*
- * set sink to normal operation mode -- D0
- * before dpcd read
- */
- dp_link_psm_config(dp->link, &dp->panel->link_info, false);
if (dp_catalog_link_is_connected(dp->catalog)) {
+ /*
+ * set sink to normal operation mode -- D0
+ * before dpcd read
+ */
+ dp_display_host_phy_init(dp);
+ dp_link_psm_config(dp->link, &dp->panel->link_info, false);
sink_count = drm_dp_read_sink_count(dp->aux);
if (sink_count < 0)
sink_count = 0;
+
+ dp_display_host_phy_exit(dp);
}
dp->link->sink_count = sink_count;
@@ -1336,9 +1385,11 @@ static int dp_pm_resume(struct device *dev)
dp_display_handle_plugged_change(dp_display, false);
}
- DRM_DEBUG_DP("After, sink_count=%d is_connected=%d core_inited=%d power_on=%d\n",
- dp->link->sink_count, dp->dp_display.is_connected,
- dp->core_initialized, dp_display->power_on);
+ DRM_DEBUG_DP("After, type=%d sink_count=%d is_connected=%d \
+ core_inited=%d phy_inited=%d power_on=%d\n",
+ dp->dp_display.connector_type, dp->link->sink_count,
+ dp->dp_display.is_connected, dp->core_initialized,
+ dp->phy_initialized, dp_display->power_on);
mutex_unlock(&dp->event_mutex);
@@ -1355,24 +1406,24 @@ static int dp_pm_suspend(struct device *dev)
mutex_lock(&dp->event_mutex);
- DRM_DEBUG_DP("Before, core_inited=%d power_on=%d\n",
- dp->core_initialized, dp_display->power_on);
-
- if (dp->core_initialized == true) {
- /* mainlink enabled */
- if (dp_power_clk_status(dp->power, DP_CTRL_PM))
- dp_ctrl_off_link_stream(dp->ctrl);
+ DRM_DEBUG_DP("Before, type=%d core_inited=%d phy_inited=%d power_on=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized, dp_display->power_on);
- dp_display_host_deinit(dp);
- }
+ /* mainlink enabled */
+ if (dp_power_clk_status(dp->power, DP_CTRL_PM))
+ dp_ctrl_off_link_stream(dp->ctrl);
- dp->hpd_state = ST_SUSPENDED;
+ dp_display_host_phy_exit(dp);
/* host_init will be called at pm_resume */
- dp->core_initialized = false;
+ dp_display_host_deinit(dp);
+
+ dp->hpd_state = ST_SUSPENDED;
- DRM_DEBUG_DP("After, core_inited=%d power_on=%d\n",
- dp->core_initialized, dp_display->power_on);
+ DRM_DEBUG_DP("After, type=%d core_inited=%d phy_inited=%d power_on=%d\n",
+ dp->dp_display.connector_type, dp->core_initialized,
+ dp->phy_initialized, dp_display->power_on);
mutex_unlock(&dp->event_mutex);
@@ -1460,6 +1511,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
struct drm_encoder *encoder)
{
struct msm_drm_private *priv;
+ struct dp_display_private *dp_priv;
int ret;
if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev))
@@ -1468,6 +1520,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
priv = dev->dev_private;
dp_display->drm_dev = dev;
+ dp_priv = container_of(dp_display, struct dp_display_private, dp_display);
+
ret = dp_display_request_irq(dp_display);
if (ret) {
DRM_ERROR("request_irq failed, ret=%d\n", ret);
@@ -1485,6 +1539,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
return ret;
}
+ dp_priv->panel->connector = dp_display->connector;
+
priv->connectors[priv->num_connectors++] = dp_display->connector;
dp_display->bridge = msm_dp_bridge_init(dp_display, dev, encoder);
@@ -1535,7 +1591,7 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder)
state = dp_display->hpd_state;
if (state == ST_DISPLAY_OFF)
- dp_display_host_init(dp_display, true);
+ dp_display_host_phy_init(dp_display);
dp_display_enable(dp_display, 0);