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.c69
1 files changed, 39 insertions, 30 deletions
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index aff51bb973eb..bbc47d86ae9e 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -11,6 +11,7 @@
#include <linux/of_irq.h>
#include <linux/phy/phy.h>
#include <linux/delay.h>
+#include <linux/string_choices.h>
#include <drm/display/drm_dp_aux_bus.h>
#include <drm/drm_edid.h>
@@ -343,8 +344,7 @@ static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *d
{
if ((hpd && dp->msm_dp_display.link_ready) ||
(!hpd && !dp->msm_dp_display.link_ready)) {
- drm_dbg_dp(dp->drm_dev, "HPD already %s\n",
- (hpd ? "on" : "off"));
+ drm_dbg_dp(dp->drm_dev, "HPD already %s\n", str_on_off(hpd));
return 0;
}
@@ -367,6 +367,19 @@ static int msm_dp_display_send_hpd_notification(struct msm_dp_display_private *d
return 0;
}
+static void msm_dp_display_lttpr_init(struct msm_dp_display_private *dp)
+{
+ u8 lttpr_caps[DP_LTTPR_COMMON_CAP_SIZE];
+ int rc;
+
+ if (drm_dp_read_lttpr_common_caps(dp->aux, dp->panel->dpcd, lttpr_caps))
+ return;
+
+ rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(lttpr_caps));
+ if (rc)
+ DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc);
+}
+
static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp)
{
struct drm_connector *connector = dp->msm_dp_display.connector;
@@ -377,6 +390,8 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp)
if (rc)
goto end;
+ msm_dp_display_lttpr_init(dp);
+
msm_dp_link_process_request(dp->link);
if (!dp->msm_dp_display.is_edp)
@@ -722,9 +737,6 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp)
{
int rc = 0;
struct device *dev = &dp->msm_dp_display.pdev->dev;
- struct msm_dp_panel_in panel_in = {
- .dev = dev,
- };
struct phy *phy;
phy = devm_phy_get(dev, "dp");
@@ -765,11 +777,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp)
goto error_link;
}
- panel_in.aux = dp->aux;
- panel_in.catalog = dp->catalog;
- panel_in.link = dp->link;
-
- dp->panel = msm_dp_panel_get(&panel_in);
+ dp->panel = msm_dp_panel_get(dev, dp->aux, dp->link, dp->catalog);
if (IS_ERR(dp->panel)) {
rc = PTR_ERR(dp->panel);
DRM_ERROR("failed to initialize panel, rc = %d\n", rc);
@@ -787,7 +795,7 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp)
goto error_ctrl;
}
- dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->panel, dp->catalog);
+ dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->catalog);
if (IS_ERR(dp->audio)) {
rc = PTR_ERR(dp->audio);
pr_err("failed to initialize audio, rc = %d\n", rc);
@@ -937,16 +945,17 @@ enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge,
return -EINVAL;
}
- if (mode->clock > DP_MAX_PIXEL_CLK_KHZ)
- return MODE_CLOCK_HIGH;
-
msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
link_info = &msm_dp_display->panel->link_info;
- if (drm_mode_is_420_only(&dp->connector->display_info, mode) &&
- msm_dp_display->panel->vsc_sdp_supported)
+ if ((drm_mode_is_420_only(&dp->connector->display_info, mode) &&
+ msm_dp_display->panel->vsc_sdp_supported) ||
+ msm_dp_wide_bus_available(dp))
mode_pclk_khz /= 2;
+ if (mode_pclk_khz > DP_MAX_PIXEL_CLK_KHZ)
+ return MODE_CLOCK_HIGH;
+
mode_bpp = dp->connector->display_info.bpc * num_components;
if (!mode_bpp)
mode_bpp = default_bpp;
@@ -1498,13 +1507,13 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
}
void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
- struct drm_bridge_state *old_bridge_state)
+ struct drm_atomic_state *state)
{
struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
int rc = 0;
struct msm_dp_display_private *msm_dp_display;
- u32 state;
+ u32 hpd_state;
bool force_link_train = false;
msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
@@ -1523,8 +1532,8 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
return;
}
- state = msm_dp_display->hpd_state;
- if (state != ST_DISPLAY_OFF && state != ST_MAINLINK_READY) {
+ hpd_state = msm_dp_display->hpd_state;
+ if (hpd_state != ST_DISPLAY_OFF && hpd_state != ST_MAINLINK_READY) {
mutex_unlock(&msm_dp_display->event_mutex);
return;
}
@@ -1536,9 +1545,9 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
return;
}
- state = msm_dp_display->hpd_state;
+ hpd_state = msm_dp_display->hpd_state;
- if (state == ST_DISPLAY_OFF) {
+ if (hpd_state == ST_DISPLAY_OFF) {
msm_dp_display_host_phy_init(msm_dp_display);
force_link_train = true;
}
@@ -1559,7 +1568,7 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
}
void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
- struct drm_bridge_state *old_bridge_state)
+ struct drm_atomic_state *state)
{
struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
@@ -1571,11 +1580,11 @@ void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
}
void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
- struct drm_bridge_state *old_bridge_state)
+ struct drm_atomic_state *state)
{
struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
- u32 state;
+ u32 hpd_state;
struct msm_dp_display_private *msm_dp_display;
msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
@@ -1585,15 +1594,15 @@ void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
mutex_lock(&msm_dp_display->event_mutex);
- state = msm_dp_display->hpd_state;
- if (state != ST_DISCONNECT_PENDING && state != ST_CONNECTED)
+ hpd_state = msm_dp_display->hpd_state;
+ if (hpd_state != ST_DISCONNECT_PENDING && hpd_state != ST_CONNECTED)
drm_dbg_dp(dp->drm_dev, "type=%d wrong hpd_state=%d\n",
- dp->connector_type, state);
+ dp->connector_type, hpd_state);
msm_dp_display_disable(msm_dp_display);
- state = msm_dp_display->hpd_state;
- if (state == ST_DISCONNECT_PENDING) {
+ hpd_state = msm_dp_display->hpd_state;
+ if (hpd_state == ST_DISCONNECT_PENDING) {
/* completed disconnection */
msm_dp_display->hpd_state = ST_DISCONNECTED;
} else {