Loading Documentation/devicetree/bindings/display/msm/dsi.txt +0 −2 Original line number Diff line number Diff line Loading @@ -127,7 +127,6 @@ Optional properties: turns off PHY pmic power supply, phy ldo and DSI Lane ldo during idle screen (footswitch control off) when this property is enabled. - qcom,dsi-phy-regulator-min-datarate-bps: Minimum per lane data rate (bps) to turn on PHY regulator. - qcom,panel-force-clock-lane-hs: A boolean property indicates that panel needs clock lanes in HS mode only [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/graph.txt Loading Loading @@ -238,5 +237,4 @@ Example: qcom,dsi-phy-regulator-ldo-mode; qcom,panel-allow-phy-poweroff; qcom,dsi-phy-regulator-min-datarate-bps = <1200000000>; qcom,panel-force-clock-lane-hs; }; drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +13 −23 Original line number Diff line number Diff line Loading @@ -62,7 +62,6 @@ struct dp_hdcp2p2_ctrl { u8 rx_status; char abort_mask; bool cp_irq_done; bool polling; }; Loading Loading @@ -191,6 +190,8 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) if (dp_hdcp2p2_copy_buf(ctrl, data)) goto exit; ctrl->polling = false; pr_debug("%s\n", hdcp_transport_cmd_to_str(ctrl->wakeup_cmd)); switch (ctrl->wakeup_cmd) { Loading @@ -198,6 +199,9 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) kthread_queue_work(&ctrl->worker, &ctrl->send_msg); break; case HDCP_TRANSPORT_CMD_RECV_MESSAGE: if (ctrl->rx_status) ctrl->polling = true; else kthread_queue_work(&ctrl->worker, &ctrl->recv_msg); break; case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: Loading @@ -212,9 +216,6 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_LINK_POLL: if (ctrl->cp_irq_done) kthread_queue_work(&ctrl->worker, &ctrl->recv_msg); else ctrl->polling = true; break; case HDCP_TRANSPORT_CMD_AUTHENTICATE: Loading Loading @@ -533,26 +534,12 @@ static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work) return; } if (ctrl->rx_status) { if (!ctrl->cp_irq_done) { pr_debug("waiting for CP_IRQ\n"); ctrl->polling = true; return; } if (ctrl->rx_status & ctrl->sink_rx_status) { ctrl->cp_irq_done = false; ctrl->sink_rx_status = 0; ctrl->rx_status = 0; } } dp_hdcp2p2_get_msg_from_sink(ctrl); } static void dp_hdcp2p2_link_work(struct kthread_work *work) { int rc = 0; int rc = 0, retries = 10; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, link); struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; Loading Loading @@ -587,6 +574,11 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work) goto exit; } /* wait for polling to start till spec allowed timeout */ while (!ctrl->polling && retries--) msleep(20); /* check if sink has made a message available */ if (ctrl->polling && (ctrl->sink_rx_status & ctrl->rx_status)) { ctrl->sink_rx_status = 0; ctrl->rx_status = 0; Loading @@ -594,8 +586,6 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work) dp_hdcp2p2_get_msg_from_sink(ctrl); ctrl->polling = false; } else { ctrl->cp_irq_done = true; } exit: if (rc) Loading drivers/gpu/drm/msm/dp/dp_mst_drm.c +60 −38 Original line number Diff line number Diff line /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -30,6 +30,7 @@ #include "dp_drm.h" #define DP_MST_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) #define DP_MST_INFO_LOG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) #define MAX_DP_MST_STREAMS 2 #define MAX_DP_MST_DRM_ENCODERS 2 Loading Loading @@ -102,7 +103,9 @@ struct dp_mst_bridge { struct drm_display_mode drm_mode; struct dp_display_mode dp_mode; struct drm_connector *connector; struct drm_connector *old_connector; void *dp_panel; void *old_dp_panel; int vcpi; int pbn; Loading @@ -120,6 +123,7 @@ struct dp_mst_private { struct dp_mst_sim_mode simulator; struct mutex mst_lock; enum dp_drv_state state; bool mst_session_state; }; struct dp_mst_encoder_info_cache { Loading Loading @@ -681,8 +685,6 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) struct dp_display *dp; struct dp_mst_private *mst; DP_MST_DEBUG("enter\n"); if (!drm_bridge) { pr_err("Invalid params\n"); return; Loading @@ -691,6 +693,9 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) bridge = to_dp_mst_bridge(drm_bridge); dp = bridge->display; bridge->old_connector = NULL; bridge->old_dp_panel = NULL; if (!bridge->connector) { pr_err("Invalid connector\n"); return; Loading Loading @@ -727,7 +732,14 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) _dp_mst_bridge_pre_enable_part2(bridge); } DP_MST_DEBUG("mst bridge [%d] pre enable complete\n", bridge->id); DP_MST_INFO_LOG("mode: id(%d) mode(%s), refresh(%d)\n", bridge->id, bridge->drm_mode.name, bridge->drm_mode.vrefresh); DP_MST_INFO_LOG("dsc: id(%d) dsc(%d)\n", bridge->id, bridge->dp_mode.timing.comp_info.comp_ratio); DP_MST_INFO_LOG("channel: id(%d) vcpi(%d) start(%d) tot(%d)\n", bridge->id, bridge->vcpi, bridge->start_slot, bridge->num_slots); end: mutex_unlock(&mst->mst_lock); } Loading @@ -738,8 +750,6 @@ static void dp_mst_bridge_enable(struct drm_bridge *drm_bridge) struct dp_mst_bridge *bridge; struct dp_display *dp; DP_MST_DEBUG("enter\n"); if (!drm_bridge) { pr_err("Invalid params\n"); return; Loading @@ -760,7 +770,8 @@ static void dp_mst_bridge_enable(struct drm_bridge *drm_bridge) return; } DP_MST_DEBUG("mst bridge [%d] post enable complete\n", bridge->id); DP_MST_INFO_LOG("mst bridge [%d] post enable complete\n", bridge->id); } static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) Loading @@ -770,8 +781,6 @@ static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) struct dp_display *dp; struct dp_mst_private *mst; DP_MST_DEBUG("enter\n"); if (!drm_bridge) { pr_err("Invalid params\n"); return; Loading Loading @@ -800,7 +809,7 @@ static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) _dp_mst_bridge_pre_disable_part2(bridge); DP_MST_DEBUG("mst bridge [%d] disable complete\n", bridge->id); DP_MST_INFO_LOG("mst bridge [%d] disable complete\n", bridge->id); mutex_unlock(&mst->mst_lock); } Loading @@ -812,8 +821,6 @@ static void dp_mst_bridge_post_disable(struct drm_bridge *drm_bridge) struct dp_display *dp; struct dp_mst_private *mst; DP_MST_DEBUG("enter\n"); if (!drm_bridge) { pr_err("Invalid params\n"); return; Loading Loading @@ -841,12 +848,17 @@ static void dp_mst_bridge_post_disable(struct drm_bridge *drm_bridge) /* maintain the connector to encoder link during suspend/resume */ if (mst->state != PM_SUSPEND) { /* Disconnect the connector and panel info from bridge */ mst->mst_bridge[bridge->id].old_connector = mst->mst_bridge[bridge->id].connector; mst->mst_bridge[bridge->id].old_dp_panel = mst->mst_bridge[bridge->id].dp_panel; mst->mst_bridge[bridge->id].connector = NULL; mst->mst_bridge[bridge->id].dp_panel = NULL; mst->mst_bridge[bridge->id].encoder_active_sts = false; } DP_MST_DEBUG("mst bridge [%d] post disable complete\n", bridge->id); DP_MST_INFO_LOG("mst bridge [%d] post disable complete\n", bridge->id); } static void dp_mst_bridge_mode_set(struct drm_bridge *drm_bridge, Loading @@ -865,14 +877,22 @@ static void dp_mst_bridge_mode_set(struct drm_bridge *drm_bridge, bridge = to_dp_mst_bridge(drm_bridge); if (!bridge->connector) { if (!bridge->old_connector) { pr_err("Invalid connector\n"); return; } bridge->connector = bridge->old_connector; bridge->old_connector = NULL; } if (!bridge->dp_panel) { if (!bridge->old_dp_panel) { pr_err("Invalid dp_panel\n"); return; } bridge->dp_panel = bridge->old_dp_panel; bridge->old_dp_panel = NULL; } dp = bridge->display; Loading Loading @@ -1381,7 +1401,7 @@ dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr, /* unlock connector and make it accessible */ drm_modeset_unlock_all(dev); DP_MST_DEBUG("add mst connector:%d\n", connector->base.id); DP_MST_INFO_LOG("add mst connector id:%d\n", connector->base.id); return connector; } Loading @@ -1392,7 +1412,8 @@ static void dp_mst_register_connector(struct drm_connector *connector) connector->status = connector->funcs->detect(connector, false); DP_MST_DEBUG("register mst connector:%d\n", connector->base.id); DP_MST_INFO_LOG("register mst connector id:%d\n", connector->base.id); drm_connector_register(connector); } Loading @@ -1401,7 +1422,7 @@ static void dp_mst_destroy_connector(struct drm_dp_mst_topology_mgr *mgr, { DP_MST_DEBUG("enter\n"); DP_MST_DEBUG("destroy mst connector:%d\n", connector->base.id); DP_MST_INFO_LOG("destroy mst connector id:%d\n", connector->base.id); drm_connector_unregister(connector); drm_connector_unreference(connector); Loading @@ -1420,7 +1441,7 @@ static void dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); DP_MST_DEBUG("mst hot plug event\n"); DP_MST_INFO_LOG("mst hot plug event\n"); } static void dp_mst_hpd_event_notify(struct dp_mst_private *mst, bool hpd_status) Loading @@ -1441,7 +1462,7 @@ static void dp_mst_hpd_event_notify(struct dp_mst_private *mst, bool hpd_status) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); DP_MST_DEBUG("%s finished\n", __func__); DP_MST_INFO_LOG("%s finished\n", __func__); } /* DP Driver Callback OPs */ Loading @@ -1453,7 +1474,9 @@ static void dp_mst_display_hpd(void *dp_display, bool hpd_status, struct dp_display *dp = dp_display; struct dp_mst_private *mst = dp->dp_mst_prv_info; DP_MST_DEBUG("enter:\n"); mutex_lock(&mst->mst_lock); mst->mst_session_state = hpd_status; mutex_unlock(&mst->mst_lock); if (!hpd_status) rc = mst->mst_fw_cbs->topology_mgr_set_mst(&mst->mst_mgr, Loading @@ -1475,9 +1498,7 @@ static void dp_mst_display_hpd(void *dp_display, bool hpd_status, dp_mst_hpd_event_notify(mst, hpd_status); DP_MST_DEBUG("mst display hpd:%d, rc:%d\n", hpd_status, rc); DP_MST_DEBUG("exit:\n"); DP_MST_INFO_LOG("mst display hpd:%d, rc:%d\n", hpd_status, rc); } static void dp_mst_display_hpd_irq(void *dp_display, Loading @@ -1486,26 +1507,29 @@ static void dp_mst_display_hpd_irq(void *dp_display, int rc; struct dp_display *dp = dp_display; struct dp_mst_private *mst = dp->dp_mst_prv_info; u8 esi[14], idx; u8 esi[14]; unsigned int esi_res = DP_SINK_COUNT_ESI + 1; bool handled; DP_MST_DEBUG("enter:\n"); if (info->mst_hpd_sim) { dp_mst_hotplug(&mst->mst_mgr); return; } if (!mst->mst_session_state) { pr_err("mst_hpd_irq received before mst session start\n"); return; } rc = drm_dp_dpcd_read(mst->caps.drm_aux, DP_SINK_COUNT_ESI, esi, 14); if (rc != 14) { pr_err("dpcd sync status read failed, rlen=%d\n", rc); goto end; pr_err("dpcd sink status read failed, rlen=%d\n", rc); return; } for (idx = 0; idx < 14; idx++) DP_MST_DEBUG("mst irq: esi[%d]: 0x%x\n", idx, esi[idx]); DP_MST_DEBUG("mst irq: esi1[0x%x] esi2[0x%x] esi3[%x]\n", esi[1], esi[2], esi[3]); rc = drm_dp_mst_hpd_irq(&mst->mst_mgr, esi, &handled); Loading @@ -1518,9 +1542,6 @@ static void dp_mst_display_hpd_irq(void *dp_display, } DP_MST_DEBUG("mst display hpd_irq handled:%d rc:%d\n", handled, rc); end: DP_MST_DEBUG("exit:\n"); } static void dp_mst_set_state(void *dp_display, enum dp_drv_state mst_state) Loading @@ -1534,6 +1555,7 @@ static void dp_mst_set_state(void *dp_display, enum dp_drv_state mst_state) } mst->state = mst_state; DP_MST_INFO_LOG("mst power state:%d\n", mst_state); } /* DP MST APIs */ Loading Loading @@ -1615,7 +1637,7 @@ int dp_mst_init(struct dp_display *dp_display) } memset(&dp_mst_enc_cache, 0, sizeof(dp_mst_enc_cache)); DP_MST_DEBUG("dp drm mst topology manager init completed\n"); DP_MST_INFO_LOG("dp drm mst topology manager init completed\n"); return ret; Loading Loading @@ -1646,6 +1668,6 @@ void dp_mst_deinit(struct dp_display *dp_display) mutex_destroy(&mst->mst_lock); DP_MST_DEBUG("dp drm mst topology manager deinit completed\n"); DP_MST_INFO_LOG("dp drm mst topology manager deinit completed\n"); } drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +0 −1 Original line number Diff line number Diff line Loading @@ -475,7 +475,6 @@ struct dsi_video_engine_cfg { bool hsa_lp11_en; bool eof_bllp_lp11_en; bool bllp_lp11_en; bool force_clk_lane_hs; enum dsi_video_traffic_mode traffic_mode; u32 vc_id; u32 dma_sched_line; Loading drivers/gpu/drm/msm/dsi-staging/dsi_display.c +195 −59 Original line number Diff line number Diff line Loading @@ -3504,8 +3504,15 @@ static int dsi_display_parse_dt(struct dsi_display *display) /* Parse TE data */ dsi_display_parse_te_data(display); /* Parse external bridge from port 0, reg 0 */ display->ext_bridge_of = of_graph_get_remote_node(of_node, 0, 0); /* Parse all external bridges from port 0 */ display_for_each_ctrl(i, display) { display->ext_bridge[i].node_of = of_graph_get_remote_node(of_node, 0, i); if (display->ext_bridge[i].node_of) display->ext_bridge_cnt++; else break; } pr_debug("success\n"); error: Loading Loading @@ -3543,6 +3550,14 @@ static int dsi_display_res_init(struct dsi_display *display) display->parser_node, display->display_type, display->cmdline_topology); display_for_each_ctrl(i, display) { struct msm_dsi_phy *phy = display->ctrl[i].phy; phy->cfg.force_clk_lane_hs = display->panel->host_config.force_hs_clk_lane; } if (IS_ERR_OR_NULL(display->panel)) { rc = PTR_ERR(display->panel); pr_err("failed to get panel, rc=%d\n", rc); Loading Loading @@ -5118,6 +5133,102 @@ static int dsi_display_ext_get_mode_info(struct drm_connector *connector, return 0; } static struct dsi_display_ext_bridge *dsi_display_ext_get_bridge( struct drm_bridge *bridge) { struct msm_drm_private *priv; struct sde_kms *sde_kms; struct list_head *connector_list; struct drm_connector *conn_iter; struct sde_connector *sde_conn; struct dsi_display *display; int i; if (!bridge || !bridge->encoder) { SDE_ERROR("invalid argument\n"); return NULL; } priv = bridge->dev->dev_private; sde_kms = to_sde_kms(priv->kms); connector_list = &sde_kms->dev->mode_config.connector_list; list_for_each_entry(conn_iter, connector_list, head) { sde_conn = to_sde_connector(conn_iter); if (sde_conn->encoder == bridge->encoder) { display = sde_conn->display; for (i = 0; i < display->ctrl_count; i++) { if (display->ext_bridge[i].bridge == bridge) return &display->ext_bridge[i]; } } } return NULL; } static void dsi_display_drm_ext_adjust_timing( const struct dsi_display *display, struct drm_display_mode *mode) { mode->hdisplay /= display->ctrl_count; mode->hsync_start /= display->ctrl_count; mode->hsync_end /= display->ctrl_count; mode->htotal /= display->ctrl_count; mode->hskew /= display->ctrl_count; mode->clock /= display->ctrl_count; } static enum drm_mode_status dsi_display_drm_ext_bridge_mode_valid( struct drm_bridge *bridge, const struct drm_display_mode *mode) { struct dsi_display_ext_bridge *ext_bridge; struct drm_display_mode tmp; ext_bridge = dsi_display_ext_get_bridge(bridge); if (!ext_bridge) return MODE_ERROR; tmp = *mode; dsi_display_drm_ext_adjust_timing(ext_bridge->display, &tmp); return ext_bridge->orig_funcs->mode_valid(bridge, &tmp); } static bool dsi_display_drm_ext_bridge_mode_fixup( struct drm_bridge *bridge, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct dsi_display_ext_bridge *ext_bridge; struct drm_display_mode tmp; ext_bridge = dsi_display_ext_get_bridge(bridge); if (!ext_bridge) return false; tmp = *mode; dsi_display_drm_ext_adjust_timing(ext_bridge->display, &tmp); return ext_bridge->orig_funcs->mode_fixup(bridge, &tmp, &tmp); } static void dsi_display_drm_ext_bridge_mode_set( struct drm_bridge *bridge, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct dsi_display_ext_bridge *ext_bridge; struct drm_display_mode tmp; ext_bridge = dsi_display_ext_get_bridge(bridge); if (!ext_bridge) return; tmp = *mode; dsi_display_drm_ext_adjust_timing(ext_bridge->display, &tmp); ext_bridge->orig_funcs->mode_set(bridge, &tmp, &tmp); } static int dsi_host_ext_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *dsi) { Loading Loading @@ -5210,31 +5321,50 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display, struct drm_bridge *ext_bridge; struct drm_connector *ext_conn; struct sde_connector *sde_conn = to_sde_connector(connector); int rc; struct drm_bridge *prev_bridge = bridge; int rc = 0, i; /* check if ext_bridge is already attached */ if (display->ext_bridge) return 0; for (i = 0; i < display->ext_bridge_cnt; i++) { struct dsi_display_ext_bridge *ext_bridge_info = &display->ext_bridge[i]; /* check if there is no external bridge defined */ if (!display->ext_bridge_of) /* return if ext bridge is already initialized */ if (ext_bridge_info->bridge) return 0; ext_bridge = of_drm_find_bridge(display->ext_bridge_of); ext_bridge = of_drm_find_bridge(ext_bridge_info->node_of); if (IS_ERR_OR_NULL(ext_bridge)) { rc = PTR_ERR(ext_bridge); pr_err("failed to find ext bridge\n"); goto error; } rc = drm_bridge_attach(bridge->encoder, ext_bridge, bridge); /* override functions for mode adjustment */ if (display->ext_bridge_cnt > 1) { ext_bridge_info->bridge_funcs = *ext_bridge->funcs; if (ext_bridge->funcs->mode_fixup) ext_bridge_info->bridge_funcs.mode_fixup = dsi_display_drm_ext_bridge_mode_fixup; if (ext_bridge->funcs->mode_valid) ext_bridge_info->bridge_funcs.mode_valid = dsi_display_drm_ext_bridge_mode_valid; if (ext_bridge->funcs->mode_set) ext_bridge_info->bridge_funcs.mode_set = dsi_display_drm_ext_bridge_mode_set; ext_bridge_info->orig_funcs = ext_bridge->funcs; ext_bridge->funcs = &ext_bridge_info->bridge_funcs; } rc = drm_bridge_attach(encoder, ext_bridge, prev_bridge); if (rc) { pr_err("[%s] ext brige attach failed, %d\n", display->name, rc); goto error; } display->ext_bridge = ext_bridge; ext_bridge_info->display = display; ext_bridge_info->bridge = ext_bridge; prev_bridge = ext_bridge; /* ext bridge will init its own connector during attach, * we need to extract it out of the connector list Loading @@ -5249,14 +5379,15 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display, } spin_unlock_irq(&drm->mode_config.connector_list_lock); /* if there is no valid external connector created, we'll use default * setting from panel defined in DT file. /* if there is no valid external connector created, or in split * mode, default setting is used from panel defined in DT file. */ if (!display->ext_conn || !display->ext_conn->funcs || !display->ext_conn->helper_private) { !display->ext_conn->helper_private || display->ext_bridge_cnt > 1) { display->ext_conn = NULL; return 0; continue; } /* otherwise, hook up the functions to use external connector */ Loading @@ -5264,13 +5395,16 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display, sde_conn->ops.detect = dsi_display_drm_ext_detect; if (display->ext_conn->helper_private->get_modes) sde_conn->ops.get_modes = dsi_display_drm_ext_get_modes; sde_conn->ops.get_modes = dsi_display_drm_ext_get_modes; if (display->ext_conn->helper_private->mode_valid) sde_conn->ops.mode_valid = dsi_display_drm_ext_mode_valid; sde_conn->ops.mode_valid = dsi_display_drm_ext_mode_valid; if (display->ext_conn->helper_private->atomic_check) sde_conn->ops.atomic_check = dsi_display_drm_ext_atomic_check; sde_conn->ops.atomic_check = dsi_display_drm_ext_atomic_check; sde_conn->ops.get_info = dsi_display_ext_get_info; Loading @@ -5279,6 +5413,8 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display, /* add support to attach/detach */ display->host.ops = &dsi_host_ext_ops; } return 0; error: return rc; Loading Loading
Documentation/devicetree/bindings/display/msm/dsi.txt +0 −2 Original line number Diff line number Diff line Loading @@ -127,7 +127,6 @@ Optional properties: turns off PHY pmic power supply, phy ldo and DSI Lane ldo during idle screen (footswitch control off) when this property is enabled. - qcom,dsi-phy-regulator-min-datarate-bps: Minimum per lane data rate (bps) to turn on PHY regulator. - qcom,panel-force-clock-lane-hs: A boolean property indicates that panel needs clock lanes in HS mode only [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Documentation/devicetree/bindings/graph.txt Loading Loading @@ -238,5 +237,4 @@ Example: qcom,dsi-phy-regulator-ldo-mode; qcom,panel-allow-phy-poweroff; qcom,dsi-phy-regulator-min-datarate-bps = <1200000000>; qcom,panel-force-clock-lane-hs; };
drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +13 −23 Original line number Diff line number Diff line Loading @@ -62,7 +62,6 @@ struct dp_hdcp2p2_ctrl { u8 rx_status; char abort_mask; bool cp_irq_done; bool polling; }; Loading Loading @@ -191,6 +190,8 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) if (dp_hdcp2p2_copy_buf(ctrl, data)) goto exit; ctrl->polling = false; pr_debug("%s\n", hdcp_transport_cmd_to_str(ctrl->wakeup_cmd)); switch (ctrl->wakeup_cmd) { Loading @@ -198,6 +199,9 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) kthread_queue_work(&ctrl->worker, &ctrl->send_msg); break; case HDCP_TRANSPORT_CMD_RECV_MESSAGE: if (ctrl->rx_status) ctrl->polling = true; else kthread_queue_work(&ctrl->worker, &ctrl->recv_msg); break; case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: Loading @@ -212,9 +216,6 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) dp_hdcp2p2_send_auth_status(ctrl); break; case HDCP_TRANSPORT_CMD_LINK_POLL: if (ctrl->cp_irq_done) kthread_queue_work(&ctrl->worker, &ctrl->recv_msg); else ctrl->polling = true; break; case HDCP_TRANSPORT_CMD_AUTHENTICATE: Loading Loading @@ -533,26 +534,12 @@ static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work) return; } if (ctrl->rx_status) { if (!ctrl->cp_irq_done) { pr_debug("waiting for CP_IRQ\n"); ctrl->polling = true; return; } if (ctrl->rx_status & ctrl->sink_rx_status) { ctrl->cp_irq_done = false; ctrl->sink_rx_status = 0; ctrl->rx_status = 0; } } dp_hdcp2p2_get_msg_from_sink(ctrl); } static void dp_hdcp2p2_link_work(struct kthread_work *work) { int rc = 0; int rc = 0, retries = 10; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, link); struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; Loading Loading @@ -587,6 +574,11 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work) goto exit; } /* wait for polling to start till spec allowed timeout */ while (!ctrl->polling && retries--) msleep(20); /* check if sink has made a message available */ if (ctrl->polling && (ctrl->sink_rx_status & ctrl->rx_status)) { ctrl->sink_rx_status = 0; ctrl->rx_status = 0; Loading @@ -594,8 +586,6 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work) dp_hdcp2p2_get_msg_from_sink(ctrl); ctrl->polling = false; } else { ctrl->cp_irq_done = true; } exit: if (rc) Loading
drivers/gpu/drm/msm/dp/dp_mst_drm.c +60 −38 Original line number Diff line number Diff line /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -30,6 +30,7 @@ #include "dp_drm.h" #define DP_MST_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) #define DP_MST_INFO_LOG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) #define MAX_DP_MST_STREAMS 2 #define MAX_DP_MST_DRM_ENCODERS 2 Loading Loading @@ -102,7 +103,9 @@ struct dp_mst_bridge { struct drm_display_mode drm_mode; struct dp_display_mode dp_mode; struct drm_connector *connector; struct drm_connector *old_connector; void *dp_panel; void *old_dp_panel; int vcpi; int pbn; Loading @@ -120,6 +123,7 @@ struct dp_mst_private { struct dp_mst_sim_mode simulator; struct mutex mst_lock; enum dp_drv_state state; bool mst_session_state; }; struct dp_mst_encoder_info_cache { Loading Loading @@ -681,8 +685,6 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) struct dp_display *dp; struct dp_mst_private *mst; DP_MST_DEBUG("enter\n"); if (!drm_bridge) { pr_err("Invalid params\n"); return; Loading @@ -691,6 +693,9 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) bridge = to_dp_mst_bridge(drm_bridge); dp = bridge->display; bridge->old_connector = NULL; bridge->old_dp_panel = NULL; if (!bridge->connector) { pr_err("Invalid connector\n"); return; Loading Loading @@ -727,7 +732,14 @@ static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) _dp_mst_bridge_pre_enable_part2(bridge); } DP_MST_DEBUG("mst bridge [%d] pre enable complete\n", bridge->id); DP_MST_INFO_LOG("mode: id(%d) mode(%s), refresh(%d)\n", bridge->id, bridge->drm_mode.name, bridge->drm_mode.vrefresh); DP_MST_INFO_LOG("dsc: id(%d) dsc(%d)\n", bridge->id, bridge->dp_mode.timing.comp_info.comp_ratio); DP_MST_INFO_LOG("channel: id(%d) vcpi(%d) start(%d) tot(%d)\n", bridge->id, bridge->vcpi, bridge->start_slot, bridge->num_slots); end: mutex_unlock(&mst->mst_lock); } Loading @@ -738,8 +750,6 @@ static void dp_mst_bridge_enable(struct drm_bridge *drm_bridge) struct dp_mst_bridge *bridge; struct dp_display *dp; DP_MST_DEBUG("enter\n"); if (!drm_bridge) { pr_err("Invalid params\n"); return; Loading @@ -760,7 +770,8 @@ static void dp_mst_bridge_enable(struct drm_bridge *drm_bridge) return; } DP_MST_DEBUG("mst bridge [%d] post enable complete\n", bridge->id); DP_MST_INFO_LOG("mst bridge [%d] post enable complete\n", bridge->id); } static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) Loading @@ -770,8 +781,6 @@ static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) struct dp_display *dp; struct dp_mst_private *mst; DP_MST_DEBUG("enter\n"); if (!drm_bridge) { pr_err("Invalid params\n"); return; Loading Loading @@ -800,7 +809,7 @@ static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) _dp_mst_bridge_pre_disable_part2(bridge); DP_MST_DEBUG("mst bridge [%d] disable complete\n", bridge->id); DP_MST_INFO_LOG("mst bridge [%d] disable complete\n", bridge->id); mutex_unlock(&mst->mst_lock); } Loading @@ -812,8 +821,6 @@ static void dp_mst_bridge_post_disable(struct drm_bridge *drm_bridge) struct dp_display *dp; struct dp_mst_private *mst; DP_MST_DEBUG("enter\n"); if (!drm_bridge) { pr_err("Invalid params\n"); return; Loading Loading @@ -841,12 +848,17 @@ static void dp_mst_bridge_post_disable(struct drm_bridge *drm_bridge) /* maintain the connector to encoder link during suspend/resume */ if (mst->state != PM_SUSPEND) { /* Disconnect the connector and panel info from bridge */ mst->mst_bridge[bridge->id].old_connector = mst->mst_bridge[bridge->id].connector; mst->mst_bridge[bridge->id].old_dp_panel = mst->mst_bridge[bridge->id].dp_panel; mst->mst_bridge[bridge->id].connector = NULL; mst->mst_bridge[bridge->id].dp_panel = NULL; mst->mst_bridge[bridge->id].encoder_active_sts = false; } DP_MST_DEBUG("mst bridge [%d] post disable complete\n", bridge->id); DP_MST_INFO_LOG("mst bridge [%d] post disable complete\n", bridge->id); } static void dp_mst_bridge_mode_set(struct drm_bridge *drm_bridge, Loading @@ -865,14 +877,22 @@ static void dp_mst_bridge_mode_set(struct drm_bridge *drm_bridge, bridge = to_dp_mst_bridge(drm_bridge); if (!bridge->connector) { if (!bridge->old_connector) { pr_err("Invalid connector\n"); return; } bridge->connector = bridge->old_connector; bridge->old_connector = NULL; } if (!bridge->dp_panel) { if (!bridge->old_dp_panel) { pr_err("Invalid dp_panel\n"); return; } bridge->dp_panel = bridge->old_dp_panel; bridge->old_dp_panel = NULL; } dp = bridge->display; Loading Loading @@ -1381,7 +1401,7 @@ dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr, /* unlock connector and make it accessible */ drm_modeset_unlock_all(dev); DP_MST_DEBUG("add mst connector:%d\n", connector->base.id); DP_MST_INFO_LOG("add mst connector id:%d\n", connector->base.id); return connector; } Loading @@ -1392,7 +1412,8 @@ static void dp_mst_register_connector(struct drm_connector *connector) connector->status = connector->funcs->detect(connector, false); DP_MST_DEBUG("register mst connector:%d\n", connector->base.id); DP_MST_INFO_LOG("register mst connector id:%d\n", connector->base.id); drm_connector_register(connector); } Loading @@ -1401,7 +1422,7 @@ static void dp_mst_destroy_connector(struct drm_dp_mst_topology_mgr *mgr, { DP_MST_DEBUG("enter\n"); DP_MST_DEBUG("destroy mst connector:%d\n", connector->base.id); DP_MST_INFO_LOG("destroy mst connector id:%d\n", connector->base.id); drm_connector_unregister(connector); drm_connector_unreference(connector); Loading @@ -1420,7 +1441,7 @@ static void dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); DP_MST_DEBUG("mst hot plug event\n"); DP_MST_INFO_LOG("mst hot plug event\n"); } static void dp_mst_hpd_event_notify(struct dp_mst_private *mst, bool hpd_status) Loading @@ -1441,7 +1462,7 @@ static void dp_mst_hpd_event_notify(struct dp_mst_private *mst, bool hpd_status) kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); DP_MST_DEBUG("%s finished\n", __func__); DP_MST_INFO_LOG("%s finished\n", __func__); } /* DP Driver Callback OPs */ Loading @@ -1453,7 +1474,9 @@ static void dp_mst_display_hpd(void *dp_display, bool hpd_status, struct dp_display *dp = dp_display; struct dp_mst_private *mst = dp->dp_mst_prv_info; DP_MST_DEBUG("enter:\n"); mutex_lock(&mst->mst_lock); mst->mst_session_state = hpd_status; mutex_unlock(&mst->mst_lock); if (!hpd_status) rc = mst->mst_fw_cbs->topology_mgr_set_mst(&mst->mst_mgr, Loading @@ -1475,9 +1498,7 @@ static void dp_mst_display_hpd(void *dp_display, bool hpd_status, dp_mst_hpd_event_notify(mst, hpd_status); DP_MST_DEBUG("mst display hpd:%d, rc:%d\n", hpd_status, rc); DP_MST_DEBUG("exit:\n"); DP_MST_INFO_LOG("mst display hpd:%d, rc:%d\n", hpd_status, rc); } static void dp_mst_display_hpd_irq(void *dp_display, Loading @@ -1486,26 +1507,29 @@ static void dp_mst_display_hpd_irq(void *dp_display, int rc; struct dp_display *dp = dp_display; struct dp_mst_private *mst = dp->dp_mst_prv_info; u8 esi[14], idx; u8 esi[14]; unsigned int esi_res = DP_SINK_COUNT_ESI + 1; bool handled; DP_MST_DEBUG("enter:\n"); if (info->mst_hpd_sim) { dp_mst_hotplug(&mst->mst_mgr); return; } if (!mst->mst_session_state) { pr_err("mst_hpd_irq received before mst session start\n"); return; } rc = drm_dp_dpcd_read(mst->caps.drm_aux, DP_SINK_COUNT_ESI, esi, 14); if (rc != 14) { pr_err("dpcd sync status read failed, rlen=%d\n", rc); goto end; pr_err("dpcd sink status read failed, rlen=%d\n", rc); return; } for (idx = 0; idx < 14; idx++) DP_MST_DEBUG("mst irq: esi[%d]: 0x%x\n", idx, esi[idx]); DP_MST_DEBUG("mst irq: esi1[0x%x] esi2[0x%x] esi3[%x]\n", esi[1], esi[2], esi[3]); rc = drm_dp_mst_hpd_irq(&mst->mst_mgr, esi, &handled); Loading @@ -1518,9 +1542,6 @@ static void dp_mst_display_hpd_irq(void *dp_display, } DP_MST_DEBUG("mst display hpd_irq handled:%d rc:%d\n", handled, rc); end: DP_MST_DEBUG("exit:\n"); } static void dp_mst_set_state(void *dp_display, enum dp_drv_state mst_state) Loading @@ -1534,6 +1555,7 @@ static void dp_mst_set_state(void *dp_display, enum dp_drv_state mst_state) } mst->state = mst_state; DP_MST_INFO_LOG("mst power state:%d\n", mst_state); } /* DP MST APIs */ Loading Loading @@ -1615,7 +1637,7 @@ int dp_mst_init(struct dp_display *dp_display) } memset(&dp_mst_enc_cache, 0, sizeof(dp_mst_enc_cache)); DP_MST_DEBUG("dp drm mst topology manager init completed\n"); DP_MST_INFO_LOG("dp drm mst topology manager init completed\n"); return ret; Loading Loading @@ -1646,6 +1668,6 @@ void dp_mst_deinit(struct dp_display *dp_display) mutex_destroy(&mst->mst_lock); DP_MST_DEBUG("dp drm mst topology manager deinit completed\n"); DP_MST_INFO_LOG("dp drm mst topology manager deinit completed\n"); }
drivers/gpu/drm/msm/dsi-staging/dsi_defs.h +0 −1 Original line number Diff line number Diff line Loading @@ -475,7 +475,6 @@ struct dsi_video_engine_cfg { bool hsa_lp11_en; bool eof_bllp_lp11_en; bool bllp_lp11_en; bool force_clk_lane_hs; enum dsi_video_traffic_mode traffic_mode; u32 vc_id; u32 dma_sched_line; Loading
drivers/gpu/drm/msm/dsi-staging/dsi_display.c +195 −59 Original line number Diff line number Diff line Loading @@ -3504,8 +3504,15 @@ static int dsi_display_parse_dt(struct dsi_display *display) /* Parse TE data */ dsi_display_parse_te_data(display); /* Parse external bridge from port 0, reg 0 */ display->ext_bridge_of = of_graph_get_remote_node(of_node, 0, 0); /* Parse all external bridges from port 0 */ display_for_each_ctrl(i, display) { display->ext_bridge[i].node_of = of_graph_get_remote_node(of_node, 0, i); if (display->ext_bridge[i].node_of) display->ext_bridge_cnt++; else break; } pr_debug("success\n"); error: Loading Loading @@ -3543,6 +3550,14 @@ static int dsi_display_res_init(struct dsi_display *display) display->parser_node, display->display_type, display->cmdline_topology); display_for_each_ctrl(i, display) { struct msm_dsi_phy *phy = display->ctrl[i].phy; phy->cfg.force_clk_lane_hs = display->panel->host_config.force_hs_clk_lane; } if (IS_ERR_OR_NULL(display->panel)) { rc = PTR_ERR(display->panel); pr_err("failed to get panel, rc=%d\n", rc); Loading Loading @@ -5118,6 +5133,102 @@ static int dsi_display_ext_get_mode_info(struct drm_connector *connector, return 0; } static struct dsi_display_ext_bridge *dsi_display_ext_get_bridge( struct drm_bridge *bridge) { struct msm_drm_private *priv; struct sde_kms *sde_kms; struct list_head *connector_list; struct drm_connector *conn_iter; struct sde_connector *sde_conn; struct dsi_display *display; int i; if (!bridge || !bridge->encoder) { SDE_ERROR("invalid argument\n"); return NULL; } priv = bridge->dev->dev_private; sde_kms = to_sde_kms(priv->kms); connector_list = &sde_kms->dev->mode_config.connector_list; list_for_each_entry(conn_iter, connector_list, head) { sde_conn = to_sde_connector(conn_iter); if (sde_conn->encoder == bridge->encoder) { display = sde_conn->display; for (i = 0; i < display->ctrl_count; i++) { if (display->ext_bridge[i].bridge == bridge) return &display->ext_bridge[i]; } } } return NULL; } static void dsi_display_drm_ext_adjust_timing( const struct dsi_display *display, struct drm_display_mode *mode) { mode->hdisplay /= display->ctrl_count; mode->hsync_start /= display->ctrl_count; mode->hsync_end /= display->ctrl_count; mode->htotal /= display->ctrl_count; mode->hskew /= display->ctrl_count; mode->clock /= display->ctrl_count; } static enum drm_mode_status dsi_display_drm_ext_bridge_mode_valid( struct drm_bridge *bridge, const struct drm_display_mode *mode) { struct dsi_display_ext_bridge *ext_bridge; struct drm_display_mode tmp; ext_bridge = dsi_display_ext_get_bridge(bridge); if (!ext_bridge) return MODE_ERROR; tmp = *mode; dsi_display_drm_ext_adjust_timing(ext_bridge->display, &tmp); return ext_bridge->orig_funcs->mode_valid(bridge, &tmp); } static bool dsi_display_drm_ext_bridge_mode_fixup( struct drm_bridge *bridge, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct dsi_display_ext_bridge *ext_bridge; struct drm_display_mode tmp; ext_bridge = dsi_display_ext_get_bridge(bridge); if (!ext_bridge) return false; tmp = *mode; dsi_display_drm_ext_adjust_timing(ext_bridge->display, &tmp); return ext_bridge->orig_funcs->mode_fixup(bridge, &tmp, &tmp); } static void dsi_display_drm_ext_bridge_mode_set( struct drm_bridge *bridge, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct dsi_display_ext_bridge *ext_bridge; struct drm_display_mode tmp; ext_bridge = dsi_display_ext_get_bridge(bridge); if (!ext_bridge) return; tmp = *mode; dsi_display_drm_ext_adjust_timing(ext_bridge->display, &tmp); ext_bridge->orig_funcs->mode_set(bridge, &tmp, &tmp); } static int dsi_host_ext_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *dsi) { Loading Loading @@ -5210,31 +5321,50 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display, struct drm_bridge *ext_bridge; struct drm_connector *ext_conn; struct sde_connector *sde_conn = to_sde_connector(connector); int rc; struct drm_bridge *prev_bridge = bridge; int rc = 0, i; /* check if ext_bridge is already attached */ if (display->ext_bridge) return 0; for (i = 0; i < display->ext_bridge_cnt; i++) { struct dsi_display_ext_bridge *ext_bridge_info = &display->ext_bridge[i]; /* check if there is no external bridge defined */ if (!display->ext_bridge_of) /* return if ext bridge is already initialized */ if (ext_bridge_info->bridge) return 0; ext_bridge = of_drm_find_bridge(display->ext_bridge_of); ext_bridge = of_drm_find_bridge(ext_bridge_info->node_of); if (IS_ERR_OR_NULL(ext_bridge)) { rc = PTR_ERR(ext_bridge); pr_err("failed to find ext bridge\n"); goto error; } rc = drm_bridge_attach(bridge->encoder, ext_bridge, bridge); /* override functions for mode adjustment */ if (display->ext_bridge_cnt > 1) { ext_bridge_info->bridge_funcs = *ext_bridge->funcs; if (ext_bridge->funcs->mode_fixup) ext_bridge_info->bridge_funcs.mode_fixup = dsi_display_drm_ext_bridge_mode_fixup; if (ext_bridge->funcs->mode_valid) ext_bridge_info->bridge_funcs.mode_valid = dsi_display_drm_ext_bridge_mode_valid; if (ext_bridge->funcs->mode_set) ext_bridge_info->bridge_funcs.mode_set = dsi_display_drm_ext_bridge_mode_set; ext_bridge_info->orig_funcs = ext_bridge->funcs; ext_bridge->funcs = &ext_bridge_info->bridge_funcs; } rc = drm_bridge_attach(encoder, ext_bridge, prev_bridge); if (rc) { pr_err("[%s] ext brige attach failed, %d\n", display->name, rc); goto error; } display->ext_bridge = ext_bridge; ext_bridge_info->display = display; ext_bridge_info->bridge = ext_bridge; prev_bridge = ext_bridge; /* ext bridge will init its own connector during attach, * we need to extract it out of the connector list Loading @@ -5249,14 +5379,15 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display, } spin_unlock_irq(&drm->mode_config.connector_list_lock); /* if there is no valid external connector created, we'll use default * setting from panel defined in DT file. /* if there is no valid external connector created, or in split * mode, default setting is used from panel defined in DT file. */ if (!display->ext_conn || !display->ext_conn->funcs || !display->ext_conn->helper_private) { !display->ext_conn->helper_private || display->ext_bridge_cnt > 1) { display->ext_conn = NULL; return 0; continue; } /* otherwise, hook up the functions to use external connector */ Loading @@ -5264,13 +5395,16 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display, sde_conn->ops.detect = dsi_display_drm_ext_detect; if (display->ext_conn->helper_private->get_modes) sde_conn->ops.get_modes = dsi_display_drm_ext_get_modes; sde_conn->ops.get_modes = dsi_display_drm_ext_get_modes; if (display->ext_conn->helper_private->mode_valid) sde_conn->ops.mode_valid = dsi_display_drm_ext_mode_valid; sde_conn->ops.mode_valid = dsi_display_drm_ext_mode_valid; if (display->ext_conn->helper_private->atomic_check) sde_conn->ops.atomic_check = dsi_display_drm_ext_atomic_check; sde_conn->ops.atomic_check = dsi_display_drm_ext_atomic_check; sde_conn->ops.get_info = dsi_display_ext_get_info; Loading @@ -5279,6 +5413,8 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display, /* add support to attach/detach */ display->host.ops = &dsi_host_ext_ops; } return 0; error: return rc; Loading