Loading drivers/gpu/drm/msm/dp/dp_ctrl.c +17 −4 Original line number Diff line number Diff line /* * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2018, 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 @@ -71,6 +71,8 @@ struct dp_ctrl_private { struct completion video_comp; bool orientation; bool power_on; atomic_t aborted; u32 pixel_rate; Loading Loading @@ -128,6 +130,11 @@ static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); if (!ctrl->power_on || atomic_read(&ctrl->aborted)) { pr_err("CTRL off, return\n"); return; } reinit_completion(&ctrl->idle_comp); dp_ctrl_state_ctrl(ctrl, ST_PUSH_IDLE); Loading Loading @@ -833,7 +840,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) tries = 0; old_v_level = ctrl->link->phy_params.v_level; while (1) { while (!atomic_read(&ctrl->aborted)) { drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd); ret = dp_ctrl_read_link_status(ctrl, link_status); Loading Loading @@ -960,7 +967,7 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) ret = -EINVAL; break; } } while (1); } while (!atomic_read(&ctrl->aborted)); return ret; } Loading Loading @@ -1180,6 +1187,11 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); if (!ctrl->power_on || atomic_read(&ctrl->aborted)) { pr_err("CTRL off, return\n"); return -EINVAL; } ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl); ctrl->dp_ctrl.reset(&ctrl->dp_ctrl); Loading Loading @@ -1341,7 +1353,6 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl) atomic_set(&ctrl->aborted, 0); rate = ctrl->panel->link_info.rate; ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true); ctrl->catalog->hpd_config(ctrl->catalog, true); if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { Loading Loading @@ -1396,6 +1407,7 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl) if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) dp_ctrl_send_phy_test_pattern(ctrl); ctrl->power_on = true; pr_debug("End-\n"); end: Loading @@ -1419,6 +1431,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl) dp_ctrl_disable_mainlink_clocks(ctrl); ctrl->power_on = false; pr_debug("DP off done\n"); } Loading drivers/gpu/drm/msm/dp/dp_debug.c +3 −1 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, 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 @@ -665,6 +665,8 @@ static ssize_t dp_debug_write_hdr(struct file *file, pr_err("invalid input\n"); len = -EINVAL; } debug->panel->setup_hdr(debug->panel, &c_state->hdr_meta); end: return len; } Loading drivers/gpu/drm/msm/dp/dp_display.c +66 −43 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, 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 @@ -22,6 +22,8 @@ #include <linux/of_irq.h> #include <linux/hdcp_qseecom.h> #include "sde_connector.h" #include "msm_drv.h" #include "dp_usbpd.h" #include "dp_parser.h" Loading Loading @@ -87,11 +89,12 @@ struct dp_display_private { struct workqueue_struct *wq; struct delayed_work hdcp_cb_work; struct work_struct connect_work; struct delayed_work connect_work; struct work_struct attention_work; struct mutex hdcp_mutex; struct mutex session_lock; int hdcp_status; unsigned long audio_status; }; static const struct of_device_id dp_dt_match[] = { Loading @@ -99,6 +102,11 @@ static const struct of_device_id dp_dt_match[] = { {} }; static bool dp_display_framework_ready(struct dp_display_private *dp) { return dp->dp_display.post_open ? false : true; } static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp) { return dp->hdcp.feature_enabled && Loading Loading @@ -448,31 +456,30 @@ static void dp_display_post_open(struct dp_display *dp_display) } /* if cable is already connected, send notification */ if (dp_display->is_connected) dp_display_send_hpd_event(dp); if (dp->usbpd->hpd_high) queue_delayed_work(dp->wq, &dp->connect_work, HZ * 10); else dp_display->post_open = NULL; } static int dp_display_send_hpd_notification(struct dp_display_private *dp, bool hpd) { u32 timeout_sec; dp->dp_display.is_connected = hpd; /* in case, framework is not yet up, don't notify hpd */ if (dp->dp_display.post_open) return 0; if (dp_display_framework_ready(dp)) timeout_sec = 5; else timeout_sec = 10; reinit_completion(&dp->notification_comp); dp_display_send_hpd_event(dp); if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 5)) { if (!wait_for_completion_timeout(&dp->notification_comp, HZ * timeout_sec)) { pr_warn("%s timeout\n", hpd ? "connect" : "disconnect"); /* cancel any pending request */ dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); return -EINVAL; } Loading @@ -497,26 +504,21 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector, dp->usbpd->multi_func); if (rc) { if (rc == -ETIMEDOUT) { pr_err("Sink cap read failed, skip notification\n"); /* * ETIMEDOUT --> cable may have been removed * ENOTCONN --> no downstream device connected */ if (rc == -ETIMEDOUT || rc == -ENOTCONN) goto end; } else { else goto notify; } } dp->link->process_request(dp->link); if (dp_display_is_sink_count_zero(dp)) { pr_debug("no downstream devices connected\n"); rc = -EINVAL; goto end; } edid = dp->panel->edid_ctrl->edid; dp->audio_supported = drm_detect_monitor_audio(edid); dp->link->process_request(dp->link); dp->panel->handle_sink_request(dp->panel); dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; Loading Loading @@ -573,9 +575,9 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp) if (dp->audio_supported) dp->audio->off(dp->audio); rc = dp_display_send_hpd_notification(dp, false); dp->audio_status = -ENODEV; dp->aux->deinit(dp->aux); rc = dp_display_send_hpd_notification(dp, false); dp->panel->video_test = false; Loading @@ -602,8 +604,9 @@ static int dp_display_usbpd_configure_cb(struct device *dev) dp_display_host_init(dp); if (dp->usbpd->hpd_high) queue_work(dp->wq, &dp->connect_work); /* check for hpd high and framework ready */ if (dp->usbpd->hpd_high && dp_display_framework_ready(dp)) queue_delayed_work(dp->wq, &dp->connect_work, 0); end: return rc; } Loading @@ -620,6 +623,8 @@ static void dp_display_clean(struct dp_display_private *dp) dp->ctrl->push_idle(dp->ctrl); dp->ctrl->off(dp->ctrl); dp->panel->deinit(dp->panel); dp->aux->deinit(dp->aux); dp->power_on = false; } Loading Loading @@ -667,6 +672,7 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); Loading @@ -678,13 +684,13 @@ static void dp_display_handle_maintenance_req(struct dp_display_private *dp) { mutex_lock(&dp->audio->ops_lock); if (dp->audio_supported) if (dp->audio_supported && !IS_ERR_VALUE(dp->audio_status)) dp->audio->off(dp->audio); dp->ctrl->link_maintenance(dp->ctrl); if (dp->audio_supported) dp->audio->on(dp->audio); if (dp->audio_supported && !IS_ERR_VALUE(dp->audio_status)) dp->audio_status = dp->audio->on(dp->audio); mutex_unlock(&dp->audio->ops_lock); } Loading @@ -707,7 +713,7 @@ static void dp_display_attention_work(struct work_struct *work) return; } queue_work(dp->wq, &dp->connect_work); queue_delayed_work(dp->wq, &dp->connect_work, 0); return; } Loading Loading @@ -753,17 +759,19 @@ static int dp_display_usbpd_attention_cb(struct device *dev) return -ENODEV; } if (dp->usbpd->hpd_irq && dp->usbpd->hpd_high) { if (dp->usbpd->hpd_irq && dp->usbpd->hpd_high && dp->power_on) { dp->link->process_request(dp->link); queue_work(dp->wq, &dp->attention_work); } else if (dp->usbpd->hpd_high) { queue_work(dp->wq, &dp->connect_work); queue_delayed_work(dp->wq, &dp->connect_work, 0); } else { /* cancel any pending request */ dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); Loading @@ -774,7 +782,8 @@ static int dp_display_usbpd_attention_cb(struct device *dev) static void dp_display_connect_work(struct work_struct *work) { struct dp_display_private *dp = container_of(work, struct delayed_work *dw = to_delayed_work(work); struct dp_display_private *dp = container_of(dw, struct dp_display_private, connect_work); if (dp->dp_display.is_connected) { Loading Loading @@ -1070,7 +1079,7 @@ static int dp_display_post_enable(struct dp_display *dp_display) if (dp->audio_supported) { dp->audio->bw_code = dp->link->link_params.bw_code; dp->audio->lane_count = dp->link->link_params.lane_count; dp->audio->on(dp->audio); dp->audio_status = dp->audio->on(dp->audio); } dp_display_update_hdcp_info(dp); Loading @@ -1081,6 +1090,8 @@ static int dp_display_post_enable(struct dp_display *dp_display) dp->hdcp_status = HDCP_STATE_AUTHENTICATING; queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2); } dp->panel->setup_hdr(dp->panel, NULL); end: /* clear framework event notifier */ dp_display->post_open = NULL; Loading Loading @@ -1125,6 +1136,8 @@ static int dp_display_pre_disable(struct dp_display *dp_display) static int dp_display_disable(struct dp_display *dp_display) { struct dp_display_private *dp; struct drm_connector *connector; struct sde_connector_state *c_state; if (!dp_display) { pr_err("invalid input\n"); Loading @@ -1132,6 +1145,8 @@ static int dp_display_disable(struct dp_display *dp_display) } dp = container_of(dp_display, struct dp_display_private, dp_display); connector = dp->dp_display.connector; c_state = to_sde_connector_state(connector->state); mutex_lock(&dp->session_lock); Loading @@ -1142,6 +1157,15 @@ static int dp_display_disable(struct dp_display *dp_display) dp->ctrl->off(dp->ctrl); dp->panel->deinit(dp->panel); dp->aux->deinit(dp->aux); connector->hdr_eotf = 0; connector->hdr_metadata_type_one = 0; connector->hdr_max_luminance = 0; connector->hdr_avg_luminance = 0; connector->hdr_min_luminance = 0; memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta)); dp->power_on = false; Loading Loading @@ -1252,8 +1276,7 @@ static int dp_display_get_modes(struct dp_display *dp, return ret; } static int dp_display_pre_kickoff(struct dp_display *dp_display, static int dp_display_config_hdr(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr) { int rc = 0; Loading @@ -1266,7 +1289,6 @@ static int dp_display_pre_kickoff(struct dp_display *dp_display, dp = container_of(dp_display, struct dp_display_private, dp_display); if (hdr->hdr_supported && dp->panel->hdr_supported(dp->panel)) rc = dp->panel->setup_hdr(dp->panel, hdr); return rc; Loading @@ -1281,7 +1303,7 @@ static int dp_display_create_workqueue(struct dp_display_private *dp) } INIT_DELAYED_WORK(&dp->hdcp_cb_work, dp_display_hdcp_cb_work); INIT_WORK(&dp->connect_work, dp_display_connect_work); INIT_DELAYED_WORK(&dp->connect_work, dp_display_connect_work); INIT_WORK(&dp->attention_work, dp_display_attention_work); return 0; Loading @@ -1308,6 +1330,7 @@ static int dp_display_probe(struct platform_device *pdev) dp->pdev = pdev; dp->name = "drm_dp"; dp->audio_status = -ENODEV; rc = dp_display_create_workqueue(dp); if (rc) { Loading @@ -1332,7 +1355,7 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display->get_debug = dp_get_debug; g_dp_display->post_open = dp_display_post_open; g_dp_display->post_init = dp_display_post_init; g_dp_display->pre_kickoff = dp_display_pre_kickoff; g_dp_display->config_hdr = dp_display_config_hdr; rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { Loading drivers/gpu/drm/msm/dp/dp_display.h +2 −2 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, 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 @@ -43,7 +43,7 @@ struct dp_display { int (*request_irq)(struct dp_display *dp_display); struct dp_debug *(*get_debug)(struct dp_display *dp_display); void (*post_open)(struct dp_display *dp_display); int (*pre_kickoff)(struct dp_display *dp_display, int (*config_hdr)(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr_meta); void (*post_init)(struct dp_display *dp_display); }; Loading drivers/gpu/drm/msm/dp/dp_drm.c +5 −6 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, 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 @@ -276,18 +276,17 @@ static const struct drm_bridge_funcs dp_bridge_ops = { .mode_set = dp_bridge_mode_set, }; int dp_connector_pre_kickoff(struct drm_connector *connector, void *display, struct msm_display_kickoff_params *params) int dp_connector_config_hdr(void *display, struct sde_connector_state *c_state) { struct dp_display *dp = display; if (!connector || !display || !params) { if (!display || !c_state) { pr_err("invalid params\n"); return -EINVAL; } return dp->pre_kickoff(dp, params->hdr_meta); return dp->config_hdr(dp, &c_state->hdr_meta); } int dp_connector_post_init(struct drm_connector *connector, void *display) Loading Loading
drivers/gpu/drm/msm/dp/dp_ctrl.c +17 −4 Original line number Diff line number Diff line /* * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2018, 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 @@ -71,6 +71,8 @@ struct dp_ctrl_private { struct completion video_comp; bool orientation; bool power_on; atomic_t aborted; u32 pixel_rate; Loading Loading @@ -128,6 +130,11 @@ static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); if (!ctrl->power_on || atomic_read(&ctrl->aborted)) { pr_err("CTRL off, return\n"); return; } reinit_completion(&ctrl->idle_comp); dp_ctrl_state_ctrl(ctrl, ST_PUSH_IDLE); Loading Loading @@ -833,7 +840,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) tries = 0; old_v_level = ctrl->link->phy_params.v_level; while (1) { while (!atomic_read(&ctrl->aborted)) { drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd); ret = dp_ctrl_read_link_status(ctrl, link_status); Loading Loading @@ -960,7 +967,7 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) ret = -EINVAL; break; } } while (1); } while (!atomic_read(&ctrl->aborted)); return ret; } Loading Loading @@ -1180,6 +1187,11 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); if (!ctrl->power_on || atomic_read(&ctrl->aborted)) { pr_err("CTRL off, return\n"); return -EINVAL; } ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl); ctrl->dp_ctrl.reset(&ctrl->dp_ctrl); Loading Loading @@ -1341,7 +1353,6 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl) atomic_set(&ctrl->aborted, 0); rate = ctrl->panel->link_info.rate; ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true); ctrl->catalog->hpd_config(ctrl->catalog, true); if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { Loading Loading @@ -1396,6 +1407,7 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl) if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) dp_ctrl_send_phy_test_pattern(ctrl); ctrl->power_on = true; pr_debug("End-\n"); end: Loading @@ -1419,6 +1431,7 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl) dp_ctrl_disable_mainlink_clocks(ctrl); ctrl->power_on = false; pr_debug("DP off done\n"); } Loading
drivers/gpu/drm/msm/dp/dp_debug.c +3 −1 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, 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 @@ -665,6 +665,8 @@ static ssize_t dp_debug_write_hdr(struct file *file, pr_err("invalid input\n"); len = -EINVAL; } debug->panel->setup_hdr(debug->panel, &c_state->hdr_meta); end: return len; } Loading
drivers/gpu/drm/msm/dp/dp_display.c +66 −43 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, 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 @@ -22,6 +22,8 @@ #include <linux/of_irq.h> #include <linux/hdcp_qseecom.h> #include "sde_connector.h" #include "msm_drv.h" #include "dp_usbpd.h" #include "dp_parser.h" Loading Loading @@ -87,11 +89,12 @@ struct dp_display_private { struct workqueue_struct *wq; struct delayed_work hdcp_cb_work; struct work_struct connect_work; struct delayed_work connect_work; struct work_struct attention_work; struct mutex hdcp_mutex; struct mutex session_lock; int hdcp_status; unsigned long audio_status; }; static const struct of_device_id dp_dt_match[] = { Loading @@ -99,6 +102,11 @@ static const struct of_device_id dp_dt_match[] = { {} }; static bool dp_display_framework_ready(struct dp_display_private *dp) { return dp->dp_display.post_open ? false : true; } static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp) { return dp->hdcp.feature_enabled && Loading Loading @@ -448,31 +456,30 @@ static void dp_display_post_open(struct dp_display *dp_display) } /* if cable is already connected, send notification */ if (dp_display->is_connected) dp_display_send_hpd_event(dp); if (dp->usbpd->hpd_high) queue_delayed_work(dp->wq, &dp->connect_work, HZ * 10); else dp_display->post_open = NULL; } static int dp_display_send_hpd_notification(struct dp_display_private *dp, bool hpd) { u32 timeout_sec; dp->dp_display.is_connected = hpd; /* in case, framework is not yet up, don't notify hpd */ if (dp->dp_display.post_open) return 0; if (dp_display_framework_ready(dp)) timeout_sec = 5; else timeout_sec = 10; reinit_completion(&dp->notification_comp); dp_display_send_hpd_event(dp); if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 5)) { if (!wait_for_completion_timeout(&dp->notification_comp, HZ * timeout_sec)) { pr_warn("%s timeout\n", hpd ? "connect" : "disconnect"); /* cancel any pending request */ dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); return -EINVAL; } Loading @@ -497,26 +504,21 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector, dp->usbpd->multi_func); if (rc) { if (rc == -ETIMEDOUT) { pr_err("Sink cap read failed, skip notification\n"); /* * ETIMEDOUT --> cable may have been removed * ENOTCONN --> no downstream device connected */ if (rc == -ETIMEDOUT || rc == -ENOTCONN) goto end; } else { else goto notify; } } dp->link->process_request(dp->link); if (dp_display_is_sink_count_zero(dp)) { pr_debug("no downstream devices connected\n"); rc = -EINVAL; goto end; } edid = dp->panel->edid_ctrl->edid; dp->audio_supported = drm_detect_monitor_audio(edid); dp->link->process_request(dp->link); dp->panel->handle_sink_request(dp->panel); dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; Loading Loading @@ -573,9 +575,9 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp) if (dp->audio_supported) dp->audio->off(dp->audio); rc = dp_display_send_hpd_notification(dp, false); dp->audio_status = -ENODEV; dp->aux->deinit(dp->aux); rc = dp_display_send_hpd_notification(dp, false); dp->panel->video_test = false; Loading @@ -602,8 +604,9 @@ static int dp_display_usbpd_configure_cb(struct device *dev) dp_display_host_init(dp); if (dp->usbpd->hpd_high) queue_work(dp->wq, &dp->connect_work); /* check for hpd high and framework ready */ if (dp->usbpd->hpd_high && dp_display_framework_ready(dp)) queue_delayed_work(dp->wq, &dp->connect_work, 0); end: return rc; } Loading @@ -620,6 +623,8 @@ static void dp_display_clean(struct dp_display_private *dp) dp->ctrl->push_idle(dp->ctrl); dp->ctrl->off(dp->ctrl); dp->panel->deinit(dp->panel); dp->aux->deinit(dp->aux); dp->power_on = false; } Loading Loading @@ -667,6 +672,7 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); Loading @@ -678,13 +684,13 @@ static void dp_display_handle_maintenance_req(struct dp_display_private *dp) { mutex_lock(&dp->audio->ops_lock); if (dp->audio_supported) if (dp->audio_supported && !IS_ERR_VALUE(dp->audio_status)) dp->audio->off(dp->audio); dp->ctrl->link_maintenance(dp->ctrl); if (dp->audio_supported) dp->audio->on(dp->audio); if (dp->audio_supported && !IS_ERR_VALUE(dp->audio_status)) dp->audio_status = dp->audio->on(dp->audio); mutex_unlock(&dp->audio->ops_lock); } Loading @@ -707,7 +713,7 @@ static void dp_display_attention_work(struct work_struct *work) return; } queue_work(dp->wq, &dp->connect_work); queue_delayed_work(dp->wq, &dp->connect_work, 0); return; } Loading Loading @@ -753,17 +759,19 @@ static int dp_display_usbpd_attention_cb(struct device *dev) return -ENODEV; } if (dp->usbpd->hpd_irq && dp->usbpd->hpd_high) { if (dp->usbpd->hpd_irq && dp->usbpd->hpd_high && dp->power_on) { dp->link->process_request(dp->link); queue_work(dp->wq, &dp->attention_work); } else if (dp->usbpd->hpd_high) { queue_work(dp->wq, &dp->connect_work); queue_delayed_work(dp->wq, &dp->connect_work, 0); } else { /* cancel any pending request */ dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); Loading @@ -774,7 +782,8 @@ static int dp_display_usbpd_attention_cb(struct device *dev) static void dp_display_connect_work(struct work_struct *work) { struct dp_display_private *dp = container_of(work, struct delayed_work *dw = to_delayed_work(work); struct dp_display_private *dp = container_of(dw, struct dp_display_private, connect_work); if (dp->dp_display.is_connected) { Loading Loading @@ -1070,7 +1079,7 @@ static int dp_display_post_enable(struct dp_display *dp_display) if (dp->audio_supported) { dp->audio->bw_code = dp->link->link_params.bw_code; dp->audio->lane_count = dp->link->link_params.lane_count; dp->audio->on(dp->audio); dp->audio_status = dp->audio->on(dp->audio); } dp_display_update_hdcp_info(dp); Loading @@ -1081,6 +1090,8 @@ static int dp_display_post_enable(struct dp_display *dp_display) dp->hdcp_status = HDCP_STATE_AUTHENTICATING; queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2); } dp->panel->setup_hdr(dp->panel, NULL); end: /* clear framework event notifier */ dp_display->post_open = NULL; Loading Loading @@ -1125,6 +1136,8 @@ static int dp_display_pre_disable(struct dp_display *dp_display) static int dp_display_disable(struct dp_display *dp_display) { struct dp_display_private *dp; struct drm_connector *connector; struct sde_connector_state *c_state; if (!dp_display) { pr_err("invalid input\n"); Loading @@ -1132,6 +1145,8 @@ static int dp_display_disable(struct dp_display *dp_display) } dp = container_of(dp_display, struct dp_display_private, dp_display); connector = dp->dp_display.connector; c_state = to_sde_connector_state(connector->state); mutex_lock(&dp->session_lock); Loading @@ -1142,6 +1157,15 @@ static int dp_display_disable(struct dp_display *dp_display) dp->ctrl->off(dp->ctrl); dp->panel->deinit(dp->panel); dp->aux->deinit(dp->aux); connector->hdr_eotf = 0; connector->hdr_metadata_type_one = 0; connector->hdr_max_luminance = 0; connector->hdr_avg_luminance = 0; connector->hdr_min_luminance = 0; memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta)); dp->power_on = false; Loading Loading @@ -1252,8 +1276,7 @@ static int dp_display_get_modes(struct dp_display *dp, return ret; } static int dp_display_pre_kickoff(struct dp_display *dp_display, static int dp_display_config_hdr(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr) { int rc = 0; Loading @@ -1266,7 +1289,6 @@ static int dp_display_pre_kickoff(struct dp_display *dp_display, dp = container_of(dp_display, struct dp_display_private, dp_display); if (hdr->hdr_supported && dp->panel->hdr_supported(dp->panel)) rc = dp->panel->setup_hdr(dp->panel, hdr); return rc; Loading @@ -1281,7 +1303,7 @@ static int dp_display_create_workqueue(struct dp_display_private *dp) } INIT_DELAYED_WORK(&dp->hdcp_cb_work, dp_display_hdcp_cb_work); INIT_WORK(&dp->connect_work, dp_display_connect_work); INIT_DELAYED_WORK(&dp->connect_work, dp_display_connect_work); INIT_WORK(&dp->attention_work, dp_display_attention_work); return 0; Loading @@ -1308,6 +1330,7 @@ static int dp_display_probe(struct platform_device *pdev) dp->pdev = pdev; dp->name = "drm_dp"; dp->audio_status = -ENODEV; rc = dp_display_create_workqueue(dp); if (rc) { Loading @@ -1332,7 +1355,7 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display->get_debug = dp_get_debug; g_dp_display->post_open = dp_display_post_open; g_dp_display->post_init = dp_display_post_init; g_dp_display->pre_kickoff = dp_display_pre_kickoff; g_dp_display->config_hdr = dp_display_config_hdr; rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { Loading
drivers/gpu/drm/msm/dp/dp_display.h +2 −2 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, 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 @@ -43,7 +43,7 @@ struct dp_display { int (*request_irq)(struct dp_display *dp_display); struct dp_debug *(*get_debug)(struct dp_display *dp_display); void (*post_open)(struct dp_display *dp_display); int (*pre_kickoff)(struct dp_display *dp_display, int (*config_hdr)(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr_meta); void (*post_init)(struct dp_display *dp_display); }; Loading
drivers/gpu/drm/msm/dp/dp_drm.c +5 −6 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, 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 @@ -276,18 +276,17 @@ static const struct drm_bridge_funcs dp_bridge_ops = { .mode_set = dp_bridge_mode_set, }; int dp_connector_pre_kickoff(struct drm_connector *connector, void *display, struct msm_display_kickoff_params *params) int dp_connector_config_hdr(void *display, struct sde_connector_state *c_state) { struct dp_display *dp = display; if (!connector || !display || !params) { if (!display || !c_state) { pr_err("invalid params\n"); return -EINVAL; } return dp->pre_kickoff(dp, params->hdr_meta); return dp->config_hdr(dp, &c_state->hdr_meta); } int dp_connector_post_init(struct drm_connector *connector, void *display) Loading