diff options
Diffstat (limited to 'drivers/gpu/drm/msm/dp')
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_audio.c | 131 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_audio.h | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_ctrl.c | 146 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_display.c | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_display.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_drm.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_link.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_link.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dp/dp_panel.c | 12 |
9 files changed, 169 insertions, 247 deletions
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 70fdc9fe228a..f8bfb908f9b4 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -13,13 +13,13 @@ #include "dp_catalog.h" #include "dp_audio.h" +#include "dp_drm.h" #include "dp_panel.h" #include "dp_reg.h" #include "dp_display.h" #include "dp_utils.h" struct msm_dp_audio_private { - struct platform_device *audio_pdev; struct platform_device *pdev; struct drm_device *drm_dev; struct msm_dp_catalog *catalog; @@ -160,24 +160,11 @@ static void msm_dp_audio_enable(struct msm_dp_audio_private *audio, bool enable) msm_dp_catalog_audio_enable(catalog, enable); } -static struct msm_dp_audio_private *msm_dp_audio_get_data(struct platform_device *pdev) +static struct msm_dp_audio_private *msm_dp_audio_get_data(struct msm_dp *msm_dp_display) { struct msm_dp_audio *msm_dp_audio; - struct msm_dp *msm_dp_display; - - if (!pdev) { - DRM_ERROR("invalid input\n"); - return ERR_PTR(-ENODEV); - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - DRM_ERROR("invalid input\n"); - return ERR_PTR(-ENODEV); - } msm_dp_audio = msm_dp_display->msm_dp_audio; - if (!msm_dp_audio) { DRM_ERROR("invalid msm_dp_audio data\n"); return ERR_PTR(-EINVAL); @@ -186,68 +173,16 @@ static struct msm_dp_audio_private *msm_dp_audio_get_data(struct platform_device return container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio); } -static int msm_dp_audio_hook_plugged_cb(struct device *dev, void *data, - hdmi_codec_plugged_cb fn, - struct device *codec_dev) -{ - - struct platform_device *pdev; - struct msm_dp *msm_dp_display; - - pdev = to_platform_device(dev); - if (!pdev) { - pr_err("invalid input\n"); - return -ENODEV; - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - pr_err("invalid input\n"); - return -ENODEV; - } - - return msm_dp_display_set_plugged_cb(msm_dp_display, fn, codec_dev); -} - -static int msm_dp_audio_get_eld(struct device *dev, - void *data, uint8_t *buf, size_t len) -{ - struct platform_device *pdev; - struct msm_dp *msm_dp_display; - - pdev = to_platform_device(dev); - - if (!pdev) { - DRM_ERROR("invalid input\n"); - return -ENODEV; - } - - msm_dp_display = platform_get_drvdata(pdev); - if (!msm_dp_display) { - DRM_ERROR("invalid input\n"); - return -ENODEV; - } - - mutex_lock(&msm_dp_display->connector->eld_mutex); - memcpy(buf, msm_dp_display->connector->eld, - min(sizeof(msm_dp_display->connector->eld), len)); - mutex_unlock(&msm_dp_display->connector->eld_mutex); - - return 0; -} - -int msm_dp_audio_hw_params(struct device *dev, - void *data, - struct hdmi_codec_daifmt *daifmt, - struct hdmi_codec_params *params) +int msm_dp_audio_prepare(struct drm_connector *connector, + struct drm_bridge *bridge, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) { int rc = 0; struct msm_dp_audio_private *audio; - struct platform_device *pdev; struct msm_dp *msm_dp_display; - pdev = to_platform_device(dev); - msm_dp_display = platform_get_drvdata(pdev); + msm_dp_display = to_dp_bridge(bridge)->msm_dp_display; /* * there could be cases where sound card can be opened even @@ -262,7 +197,7 @@ int msm_dp_audio_hw_params(struct device *dev, goto end; } - audio = msm_dp_audio_get_data(pdev); + audio = msm_dp_audio_get_data(msm_dp_display); if (IS_ERR(audio)) { rc = PTR_ERR(audio); goto end; @@ -281,15 +216,14 @@ end: return rc; } -static void msm_dp_audio_shutdown(struct device *dev, void *data) +void msm_dp_audio_shutdown(struct drm_connector *connector, + struct drm_bridge *bridge) { struct msm_dp_audio_private *audio; - struct platform_device *pdev; struct msm_dp *msm_dp_display; - pdev = to_platform_device(dev); - msm_dp_display = platform_get_drvdata(pdev); - audio = msm_dp_audio_get_data(pdev); + msm_dp_display = to_dp_bridge(bridge)->msm_dp_display; + audio = msm_dp_audio_get_data(msm_dp_display); if (IS_ERR(audio)) { DRM_ERROR("failed to get audio data\n"); return; @@ -311,47 +245,6 @@ static void msm_dp_audio_shutdown(struct device *dev, void *data) msm_dp_display_signal_audio_complete(msm_dp_display); } -static const struct hdmi_codec_ops msm_dp_audio_codec_ops = { - .hw_params = msm_dp_audio_hw_params, - .audio_shutdown = msm_dp_audio_shutdown, - .get_eld = msm_dp_audio_get_eld, - .hook_plugged_cb = msm_dp_audio_hook_plugged_cb, -}; - -static struct hdmi_codec_pdata codec_data = { - .ops = &msm_dp_audio_codec_ops, - .max_i2s_channels = 8, - .i2s = 1, -}; - -void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio) -{ - struct msm_dp_audio_private *audio_priv; - - audio_priv = container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio); - - if (audio_priv->audio_pdev) { - platform_device_unregister(audio_priv->audio_pdev); - audio_priv->audio_pdev = NULL; - } -} - -int msm_dp_register_audio_driver(struct device *dev, - struct msm_dp_audio *msm_dp_audio) -{ - struct msm_dp_audio_private *audio_priv; - - audio_priv = container_of(msm_dp_audio, - struct msm_dp_audio_private, msm_dp_audio); - - audio_priv->audio_pdev = platform_device_register_data(dev, - HDMI_CODEC_DRV_NAME, - PLATFORM_DEVID_AUTO, - &codec_data, - sizeof(codec_data)); - return PTR_ERR_OR_ZERO(audio_priv->audio_pdev); -} - struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, struct msm_dp_catalog *catalog) { diff --git a/drivers/gpu/drm/msm/dp/dp_audio.h b/drivers/gpu/drm/msm/dp/dp_audio.h index beea34cbab77..58fc14693e48 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.h +++ b/drivers/gpu/drm/msm/dp/dp_audio.h @@ -36,23 +36,6 @@ struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev, struct msm_dp_catalog *catalog); /** - * msm_dp_register_audio_driver() - * - * Registers DP device with hdmi_codec interface. - * - * @dev: DP device instance. - * @msm_dp_audio: an instance of msm_dp_audio module. - * - * - * Returns the error code in case of failure, otherwise - * zero on success. - */ -int msm_dp_register_audio_driver(struct device *dev, - struct msm_dp_audio *msm_dp_audio); - -void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio); - -/** * msm_dp_audio_put() * * Cleans the msm_dp_audio instance. @@ -61,10 +44,12 @@ void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm */ void msm_dp_audio_put(struct msm_dp_audio *msm_dp_audio); -int msm_dp_audio_hw_params(struct device *dev, - void *data, - struct hdmi_codec_daifmt *daifmt, - struct hdmi_codec_params *params); +int msm_dp_audio_prepare(struct drm_connector *connector, + struct drm_bridge *bridge, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params); +void msm_dp_audio_shutdown(struct drm_connector *connector, + struct drm_bridge *bridge); #endif /* _DP_AUDIO_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index d8633a596f8d..a50bfafbb4ea 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1034,10 +1034,12 @@ static int msm_dp_ctrl_set_vx_px(struct msm_dp_ctrl_private *ctrl, return 0; } -static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) +static int msm_dp_ctrl_update_phy_vx_px(struct msm_dp_ctrl_private *ctrl, + enum drm_dp_phy dp_phy) { struct msm_dp_link *link = ctrl->link; - int ret = 0, lane, lane_cnt; + int lane, lane_cnt, reg; + int ret = 0; u8 buf[4]; u32 max_level_reached = 0; u32 voltage_swing_level = link->phy_params.v_level; @@ -1075,8 +1077,13 @@ static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) drm_dbg_dp(ctrl->drm_dev, "sink: p|v=0x%x\n", voltage_swing_level | pre_emphasis_level); - ret = drm_dp_dpcd_write(ctrl->aux, DP_TRAINING_LANE0_SET, - buf, lane_cnt); + + if (dp_phy == DP_PHY_DPRX) + reg = DP_TRAINING_LANE0_SET; + else + reg = DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy); + + ret = drm_dp_dpcd_write(ctrl->aux, reg, buf, lane_cnt); if (ret == lane_cnt) ret = 0; @@ -1084,9 +1091,10 @@ static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl) } static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl, - u8 pattern) + u8 pattern, enum drm_dp_phy dp_phy) { u8 buf; + int reg; int ret = 0; drm_dbg_dp(ctrl->drm_dev, "sink: pattern=%x\n", pattern); @@ -1096,31 +1104,26 @@ static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl, if (pattern && pattern != DP_TRAINING_PATTERN_4) buf |= DP_LINK_SCRAMBLING_DISABLE; - ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf); - return ret == 1; -} - -static int msm_dp_ctrl_read_link_status(struct msm_dp_ctrl_private *ctrl, - u8 *link_status) -{ - int ret = 0, len; - - len = drm_dp_dpcd_read_link_status(ctrl->aux, link_status); - if (len != DP_LINK_STATUS_SIZE) { - DRM_ERROR("DP link status read failed, err: %d\n", len); - ret = -EINVAL; - } + if (dp_phy == DP_PHY_DPRX) + reg = DP_TRAINING_PATTERN_SET; + else + reg = DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy); - return ret; + ret = drm_dp_dpcd_writeb(ctrl->aux, reg, buf); + return ret == 1; } static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, enum drm_dp_phy dp_phy) { + int delay_us; int tries, old_v_level, ret = 0; u8 link_status[DP_LINK_STATUS_SIZE]; int const maximum_retries = 4; + delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); *training_step = DP_TRAINING_1; @@ -1129,18 +1132,19 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, if (ret) return ret; msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); + DP_LINK_SCRAMBLING_DISABLE, dp_phy); - ret = msm_dp_ctrl_update_vx_px(ctrl); + msm_dp_link_reset_phy_params_vx_px(ctrl->link); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; tries = 0; old_v_level = ctrl->link->phy_params.v_level; for (tries = 0; tries < maximum_retries; tries++) { - drm_dp_link_train_clock_recovery_delay(ctrl->aux, ctrl->panel->dpcd); + fsleep(delay_us); - ret = msm_dp_ctrl_read_link_status(ctrl, link_status); + ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status); if (ret) return ret; @@ -1161,7 +1165,7 @@ static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl, } msm_dp_link_adjust_levels(ctrl->link, link_status); - ret = msm_dp_ctrl_update_vx_px(ctrl); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; } @@ -1213,21 +1217,31 @@ static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl) return 0; } -static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl) +static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl, + enum drm_dp_phy dp_phy) { - msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE); - drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); + int delay_us; + + msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy); + + delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + fsleep(delay_us); } static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, enum drm_dp_phy dp_phy) { + int delay_us; int tries = 0, ret = 0; u8 pattern; u32 state_ctrl_bit; int const maximum_retries = 5; u8 link_status[DP_LINK_STATUS_SIZE]; + delay_us = drm_dp_read_channel_eq_delay(ctrl->aux, + ctrl->panel->dpcd, dp_phy, false); + msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); *training_step = DP_TRAINING_2; @@ -1247,12 +1261,12 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, if (ret) return ret; - msm_dp_ctrl_train_pattern_set(ctrl, pattern); + msm_dp_ctrl_train_pattern_set(ctrl, pattern, dp_phy); for (tries = 0; tries <= maximum_retries; tries++) { - drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd); + fsleep(delay_us); - ret = msm_dp_ctrl_read_link_status(ctrl, link_status); + ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status); if (ret) return ret; @@ -1262,7 +1276,7 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, } msm_dp_link_adjust_levels(ctrl->link, link_status); - ret = msm_dp_ctrl_update_vx_px(ctrl); + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy); if (ret) return ret; @@ -1271,9 +1285,32 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, return -ETIMEDOUT; } +static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl, + int *training_step, enum drm_dp_phy dp_phy) +{ + int ret; + + ret = msm_dp_ctrl_link_train_1(ctrl, training_step, dp_phy); + if (ret) { + DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret); + return ret; + } + drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy); + + ret = msm_dp_ctrl_link_train_2(ctrl, training_step, dp_phy); + if (ret) { + DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret); + return ret; + } + drm_dbg_dp(ctrl->drm_dev, "link training #2 on phy %d successful\n", dp_phy); + + return 0; +} + static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, int *training_step) { + int i; int ret = 0; const u8 *dpcd = ctrl->panel->dpcd; u8 encoding[] = { 0, DP_SET_ANSI_8B10B }; @@ -1286,8 +1323,6 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, link_info.rate = ctrl->link->link_params.rate; link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING; - msm_dp_link_reset_phy_params_vx_px(ctrl->link); - msm_dp_aux_link_configure(ctrl->aux, &link_info); if (drm_dp_max_downspread(dpcd)) @@ -1302,24 +1337,27 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, &assr, 1); } - ret = msm_dp_ctrl_link_train_1(ctrl, training_step); + for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) { + enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i); + + ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, dp_phy); + msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy); + + if (ret) + break; + } + if (ret) { - DRM_ERROR("link training #1 failed. ret=%d\n", ret); + DRM_ERROR("link training of LTTPR(s) failed. ret=%d\n", ret); goto end; } - /* print success info as this is a result of user initiated action */ - drm_dbg_dp(ctrl->drm_dev, "link training #1 successful\n"); - - ret = msm_dp_ctrl_link_train_2(ctrl, training_step); + ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, DP_PHY_DPRX); if (ret) { - DRM_ERROR("link training #2 failed. ret=%d\n", ret); + DRM_ERROR("link training on sink failed. ret=%d\n", ret); goto end; } - /* print success info as this is a result of user initiated action */ - drm_dbg_dp(ctrl->drm_dev, "link training #2 successful\n"); - end: msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); @@ -1636,7 +1674,7 @@ static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl) if (ret) goto end; - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); @@ -1660,7 +1698,7 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl) return false; } msm_dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested); - msm_dp_ctrl_update_vx_px(ctrl); + msm_dp_ctrl_update_phy_vx_px(ctrl, DP_PHY_DPRX); msm_dp_link_send_test_response(ctrl->link); pattern_sent = msm_dp_catalog_ctrl_read_phy_pattern(ctrl->catalog); @@ -1805,7 +1843,7 @@ static bool msm_dp_ctrl_channel_eq_ok(struct msm_dp_ctrl_private *ctrl) u8 link_status[DP_LINK_STATUS_SIZE]; int num_lanes = ctrl->link->link_params.num_lanes; - msm_dp_ctrl_read_link_status(ctrl, link_status); + drm_dp_dpcd_read_link_status(ctrl->aux, link_status); return drm_dp_channel_eq_ok(link_status, num_lanes); } @@ -1863,7 +1901,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) if (!msm_dp_catalog_link_is_connected(ctrl->catalog)) break; - msm_dp_ctrl_read_link_status(ctrl, link_status); + drm_dp_dpcd_read_link_status(ctrl->aux, link_status); rc = msm_dp_ctrl_link_rate_down_shift(ctrl); if (rc < 0) { /* already in RBR = 1.6G */ @@ -1888,7 +1926,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) if (!msm_dp_catalog_link_is_connected(ctrl->catalog)) break; - msm_dp_ctrl_read_link_status(ctrl, link_status); + drm_dp_dpcd_read_link_status(ctrl->aux, link_status); if (!drm_dp_clock_recovery_ok(link_status, ctrl->link->link_params.num_lanes)) @@ -1902,7 +1940,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) } /* stop link training before start re training */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); } rc = msm_dp_ctrl_reinitialize_mainlink(ctrl); @@ -1926,7 +1964,7 @@ int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl) * link training failed * end txing train pattern here */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); msm_dp_ctrl_deinitialize_mainlink(ctrl); rc = -ECONNRESET; @@ -1997,7 +2035,7 @@ int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train msm_dp_ctrl_link_retrain(ctrl); /* stop txing train pattern to end link training */ - msm_dp_ctrl_clear_training_pattern(ctrl); + msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX); /* * Set up transfer unit values and set controller state to send diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index bbc47d86ae9e..386c4669c831 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -13,6 +13,7 @@ #include <linux/delay.h> #include <linux/string_choices.h> #include <drm/display/drm_dp_aux_bus.h> +#include <drm/display/drm_hdmi_audio_helper.h> #include <drm/drm_edid.h> #include "msm_drv.h" @@ -288,13 +289,6 @@ static int msm_dp_display_bind(struct device *dev, struct device *master, goto end; } - - rc = msm_dp_register_audio_driver(dev, dp->audio); - if (rc) { - DRM_ERROR("Audio registration Dp failed\n"); - goto end; - } - rc = msm_dp_hpd_event_thread_start(dp); if (rc) { DRM_ERROR("Event thread create failed\n"); @@ -316,7 +310,6 @@ static void msm_dp_display_unbind(struct device *dev, struct device *master, of_dp_aux_depopulate_bus(dp->aux); - msm_dp_unregister_audio_driver(dev, dp->audio); msm_dp_aux_unregister(dp->aux); dp->drm_dev = NULL; dp->aux->drm_dev = NULL; @@ -367,17 +360,21 @@ 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) +static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd) { - u8 lttpr_caps[DP_LTTPR_COMMON_CAP_SIZE]; - int rc; + int rc, lttpr_count; - if (drm_dp_read_lttpr_common_caps(dp->aux, dp->panel->dpcd, lttpr_caps)) - return; + if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->link->lttpr_common_caps)) + return 0; - rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(lttpr_caps)); - if (rc) + lttpr_count = drm_dp_lttpr_count(dp->link->lttpr_common_caps); + rc = drm_dp_lttpr_init(dp->aux, lttpr_count); + if (rc) { DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc); + return 0; + } + + return lttpr_count; } static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) @@ -385,12 +382,17 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) struct drm_connector *connector = dp->msm_dp_display.connector; const struct drm_display_info *info = &connector->display_info; int rc = 0; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; - rc = msm_dp_panel_read_sink_caps(dp->panel, connector); + rc = drm_dp_read_dpcd_caps(dp->aux, dpcd); if (rc) goto end; - msm_dp_display_lttpr_init(dp); + dp->link->lttpr_count = msm_dp_display_lttpr_init(dp, dpcd); + + rc = msm_dp_panel_read_sink_caps(dp->panel, connector); + if (rc) + goto end; msm_dp_link_process_request(dp->link); @@ -626,9 +628,9 @@ static void msm_dp_display_handle_plugged_change(struct msm_dp *msm_dp_display, struct msm_dp_display_private, msm_dp_display); /* notify audio subsystem only if sink supports audio */ - if (msm_dp_display->plugged_cb && msm_dp_display->codec_dev && - dp->audio_supported) - msm_dp_display->plugged_cb(msm_dp_display->codec_dev, plugged); + if (dp->audio_supported) + drm_connector_hdmi_audio_plugged_notify(msm_dp_display->connector, + plugged); } static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp, u32 data) @@ -907,19 +909,6 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp) return 0; } -int msm_dp_display_set_plugged_cb(struct msm_dp *msm_dp_display, - hdmi_codec_plugged_cb fn, struct device *codec_dev) -{ - bool plugged; - - msm_dp_display->plugged_cb = fn; - msm_dp_display->codec_dev = codec_dev; - plugged = msm_dp_display->link_ready; - msm_dp_display_handle_plugged_change(msm_dp_display, plugged); - - return 0; -} - /** * msm_dp_bridge_mode_valid - callback to determine if specified mode is valid * @bridge: Pointer to drm bridge structure diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index ecbc2d92f546..cc6e2cab36e9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -7,7 +7,6 @@ #define _DP_DISPLAY_H_ #include "dp_panel.h" -#include <sound/hdmi-codec.h> #include "disp/msm_disp_snapshot.h" #define DP_MAX_PIXEL_CLK_KHZ 675000 @@ -15,7 +14,6 @@ struct msm_dp { struct drm_device *drm_dev; struct platform_device *pdev; - struct device *codec_dev; struct drm_connector *connector; struct drm_bridge *next_bridge; bool link_ready; @@ -25,14 +23,10 @@ struct msm_dp { bool is_edp; bool internal_hpd; - hdmi_codec_plugged_cb plugged_cb; - struct msm_dp_audio *msm_dp_audio; bool psr_supported; }; -int msm_dp_display_set_plugged_cb(struct msm_dp *msm_dp_display, - hdmi_codec_plugged_cb fn, struct device *codec_dev); int msm_dp_display_get_modes(struct msm_dp *msm_dp_display); bool msm_dp_display_check_video_test(struct msm_dp *msm_dp_display); int msm_dp_display_get_test_bpp(struct msm_dp *msm_dp_display); diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index cca57e56c906..f222d7ccaa88 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -12,6 +12,7 @@ #include "msm_drv.h" #include "msm_kms.h" +#include "dp_audio.h" #include "dp_drm.h" /** @@ -114,6 +115,9 @@ static const struct drm_bridge_funcs msm_dp_bridge_ops = { .hpd_disable = msm_dp_bridge_hpd_disable, .hpd_notify = msm_dp_bridge_hpd_notify, .debugfs_init = msm_dp_bridge_debugfs_init, + + .dp_audio_prepare = msm_dp_audio_prepare, + .dp_audio_shutdown = msm_dp_audio_shutdown, }; static int msm_edp_bridge_atomic_check(struct drm_bridge *drm_bridge, @@ -296,14 +300,15 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, struct msm_dp_bridge *msm_dp_bridge; struct drm_bridge *bridge; - msm_dp_bridge = devm_kzalloc(dev->dev, sizeof(*msm_dp_bridge), GFP_KERNEL); - if (!msm_dp_bridge) - return -ENOMEM; + msm_dp_bridge = devm_drm_bridge_alloc(dev->dev, struct msm_dp_bridge, bridge, + msm_dp_display->is_edp ? &msm_edp_bridge_ops : + &msm_dp_bridge_ops); + if (IS_ERR(msm_dp_bridge)) + return PTR_ERR(msm_dp_bridge); msm_dp_bridge->msm_dp_display = msm_dp_display; bridge = &msm_dp_bridge->bridge; - bridge->funcs = msm_dp_display->is_edp ? &msm_edp_bridge_ops : &msm_dp_bridge_ops; bridge->type = msm_dp_display->connector_type; bridge->ycbcr_420_allowed = yuv_supported; @@ -320,9 +325,13 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, */ if (!msm_dp_display->is_edp) { bridge->ops = + DRM_BRIDGE_OP_DP_AUDIO | DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES; + bridge->hdmi_audio_dev = &msm_dp_display->pdev->dev; + bridge->hdmi_audio_max_i2s_playback_channels = 8; + bridge->hdmi_audio_dai_port = -1; } rc = devm_drm_bridge_add(dev->dev, bridge); diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 1a1fbb2d7d4f..92a9077959b3 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -714,21 +714,21 @@ end: static int msm_dp_link_parse_sink_status_field(struct msm_dp_link_private *link) { - int len; + int ret; link->prev_sink_count = link->msm_dp_link.sink_count; - len = drm_dp_read_sink_count(link->aux); - if (len < 0) { + ret = drm_dp_read_sink_count(link->aux); + if (ret < 0) { DRM_ERROR("DP parse sink count failed\n"); - return len; + return ret; } - link->msm_dp_link.sink_count = len; + link->msm_dp_link.sink_count = ret; - len = drm_dp_dpcd_read_link_status(link->aux, - link->link_status); - if (len < DP_LINK_STATUS_SIZE) { + ret = drm_dp_dpcd_read_link_status(link->aux, + link->link_status); + if (ret < 0) { DRM_ERROR("DP link status read failed\n"); - return len; + return ret; } return msm_dp_link_parse_request(link); diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 8db5d5698a97..ba47c6d19fbf 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -7,6 +7,7 @@ #define _DP_LINK_H_ #include "dp_aux.h" +#include <drm/display/drm_dp_helper.h> #define DS_PORT_STATUS_CHANGED 0x200 #define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF @@ -60,6 +61,9 @@ struct msm_dp_link_phy_params { }; struct msm_dp_link { + u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE]; + int lttpr_count; + u32 sink_request; u32 test_response; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 92415bf8aa16..4e8ab75c771b 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -47,7 +47,7 @@ static void msm_dp_panel_read_psr_cap(struct msm_dp_panel_private *panel) static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) { - int rc; + int rc, max_lttpr_lanes, max_lttpr_rate; struct msm_dp_panel_private *panel; struct msm_dp_link_info *link_info; u8 *dpcd, major, minor; @@ -75,6 +75,16 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel) if (link_info->rate > msm_dp_panel->max_dp_link_rate) link_info->rate = msm_dp_panel->max_dp_link_rate; + /* Limit data lanes from LTTPR capabilities, if any */ + max_lttpr_lanes = drm_dp_lttpr_max_lane_count(panel->link->lttpr_common_caps); + if (max_lttpr_lanes && max_lttpr_lanes < link_info->num_lanes) + link_info->num_lanes = max_lttpr_lanes; + + /* Limit link rate from LTTPR capabilities, if any */ + max_lttpr_rate = drm_dp_lttpr_max_link_rate(panel->link->lttpr_common_caps); + if (max_lttpr_rate && max_lttpr_rate < link_info->rate) + link_info->rate = max_lttpr_rate; + drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor); drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate); drm_dbg_dp(panel->drm_dev, "lane_count=%d\n", link_info->num_lanes); |