Loading drivers/gpu/drm/msm/dp/dp_audio.c +1 −3 Original line number Diff line number Diff line Loading @@ -679,10 +679,8 @@ static int dp_audio_notify(struct dp_audio_private *audio, u32 state) reinit_completion(&audio->hpd_comp); rc = ext->intf_ops.audio_notify(audio->ext_pdev, &ext->codec, state); if (rc) { pr_err("failed to notify audio. state=%d err=%d\n", state, rc); if (rc) goto end; } if (atomic_read(&audio->acked)) goto end; Loading drivers/gpu/drm/msm/dp/dp_debug.c +70 −31 Original line number Diff line number Diff line Loading @@ -163,6 +163,13 @@ static ssize_t dp_debug_write_edid(struct file *file, kfree(buf); debug->panel->set_edid(debug->panel, edid); /* * print edid status as this code is executed * only while running in debug mode which is manually * triggered by a tester or a script. */ pr_info("[%s]\n", edid ? "SET" : "CLEAR"); return rc; } Loading Loading @@ -250,10 +257,18 @@ static ssize_t dp_debug_write_dpcd(struct file *file, * Reset panel's dpcd in case of any failure. Also, set the * panel's dpcd only if a full dpcd is provided with offset as 0. */ if (!dpcd || (!offset && (data_len == dp_receiver_cap_size))) if (!dpcd || (!offset && (data_len == dp_receiver_cap_size))) { debug->panel->set_dpcd(debug->panel, dpcd); else /* * print dpcd status as this code is executed * only while running in debug mode which is manually * triggered by a tester or a script. */ pr_info("[%s]\n", dpcd ? "SET" : "CLEAR"); } else { debug->aux->dpcd_updated(debug->aux); } return rc; } Loading Loading @@ -1392,36 +1407,16 @@ static ssize_t dp_debug_read_hdr(struct file *file, return rc; } static ssize_t dp_debug_write_sim(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim) { struct dp_debug_private *debug = file->private_data; char buf[SZ_8]; size_t len = 0; int sim; if (!debug) return -ENODEV; if (*ppos) return 0; /* Leave room for termination char */ len = min_t(size_t, count, SZ_8 - 1); if (copy_from_user(buf, user_buff, len)) goto end; buf[len] = '\0'; if (kstrtoint(buf, 10, &sim) != 0) goto end; if (sim) { if (dp_debug_get_edid_buf(debug)) goto end; return; if (dp_debug_get_dpcd_buf(debug)) goto error; if (dp_debug_get_dpcd_buf(debug)) { devm_kfree(debug->dev, debug->edid); return; } debug->dp_debug.sim_mode = true; debug->aux->set_sim_mode(debug->aux, true, Loading @@ -1442,11 +1437,42 @@ static ssize_t dp_debug_write_sim(struct file *file, debug->dpcd = NULL; } } /* * print simulation status as this code is executed * only while running in debug mode which is manually * triggered by a tester or a script. */ pr_info("%s\n", sim ? "[ON]" : "[OFF]"); } static ssize_t dp_debug_write_sim(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; char buf[SZ_8]; size_t len = 0; int sim; if (!debug) return -ENODEV; if (*ppos) return 0; /* Leave room for termination char */ len = min_t(size_t, count, SZ_8 - 1); if (copy_from_user(buf, user_buff, len)) goto end; buf[len] = '\0'; if (kstrtoint(buf, 10, &sim) != 0) goto end; dp_debug_set_sim_mode(debug, sim); end: return len; error: devm_kfree(debug->dev, debug->edid); return len; } static ssize_t dp_debug_write_attention(struct file *file, Loading Loading @@ -1898,6 +1924,18 @@ u8 *dp_debug_get_edid(struct dp_debug *dp_debug) return debug->edid; } static void dp_debug_abort(struct dp_debug *dp_debug) { struct dp_debug_private *debug; if (!dp_debug) return; debug = container_of(dp_debug, struct dp_debug_private, dp_debug); dp_debug_set_sim_mode(debug, false); } struct dp_debug *dp_debug_get(struct dp_debug_in *in) { int rc = 0; Loading Loading @@ -1938,6 +1976,7 @@ struct dp_debug *dp_debug_get(struct dp_debug_in *in) } dp_debug->get_edid = dp_debug_get_edid; dp_debug->abort = dp_debug_abort; INIT_LIST_HEAD(&dp_debug->dp_mst_connector_list.list); Loading drivers/gpu/drm/msm/dp/dp_debug.h +1 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ struct dp_debug { struct dp_mst_connector dp_mst_connector_list; u8 *(*get_edid)(struct dp_debug *dp_debug); void (*abort)(struct dp_debug *dp_debug); }; /** Loading drivers/gpu/drm/msm/dp/dp_display.c +68 −36 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/debugfs.h> #include <linux/component.h> #include <linux/of_irq.h> #include <linux/extcon.h> #include <linux/soc/qcom/fsa4480-i2c.h> #include "sde_connector.h" Loading Loading @@ -107,6 +108,8 @@ struct dp_display_private { u32 active_stream_cnt; struct dp_mst mst; struct notifier_block usb_nb; }; static const struct of_device_id dp_dt_match[] = { Loading Loading @@ -556,6 +559,9 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp) if (hpd && dp->mst.mst_active) goto skip_wait; if (!dp->mst.mst_active && (dp->power_on == hpd)) goto skip_wait; if (!wait_for_completion_timeout(&dp->notification_comp, HZ * timeout_sec)) { pr_warn("%s timeout\n", hpd ? "connect" : "disconnect"); Loading Loading @@ -846,6 +852,24 @@ static int dp_display_handle_disconnect(struct dp_display_private *dp) return rc; } static void dp_display_disconnect_sync(struct dp_display_private *dp) { /* cancel any pending request */ atomic_set(&dp->aborted, 1); dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); cancel_work(&dp->attention_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); /* Reset abort value to allow future connections */ atomic_set(&dp->aborted, 0); } static int dp_display_usbpd_disconnect_cb(struct device *dev) { int rc = 0; Loading Loading @@ -874,21 +898,7 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) if (dp->debug->psm_enabled) dp->link->psm_config(dp->link, &dp->panel->link_info, true); /* cancel any pending request */ atomic_set(&dp->aborted, 1); dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); cancel_work(&dp->attention_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); /* Reset abort value to allow future connections */ atomic_set(&dp->aborted, 0); dp_display_disconnect_sync(dp); dp->dp_display.post_open = NULL; end: return rc; Loading Loading @@ -990,29 +1000,14 @@ static int dp_display_usbpd_attention_cb(struct device *dev) dp->hpd->hpd_irq, dp->hpd->hpd_high, dp->power_on); if (!dp->hpd->hpd_high) { if (!dp->is_connected) { pr_debug("already disconnected\n"); return 0; } /* cancel any pending request */ atomic_set(&dp->aborted, 1); dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); cancel_work(&dp->attention_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); atomic_set(&dp->aborted, 0); } else if (dp->hpd->hpd_irq && dp->core_initialized) { if (!dp->hpd->hpd_high) dp_display_disconnect_sync(dp); else if (dp->hpd->hpd_irq && dp->core_initialized) queue_work(dp->wq, &dp->attention_work); } else { else if (!dp->power_on) queue_delayed_work(dp->wq, &dp->connect_work, 0); } else pr_debug("ignored\n"); return 0; } Loading Loading @@ -1040,6 +1035,41 @@ static void dp_display_connect_work(struct work_struct *work) dp->link->send_test_response(dp->link); } static int dp_display_usb_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { struct extcon_dev *edev = ptr; struct dp_display_private *dp = container_of(nb, struct dp_display_private, usb_nb); if (!edev) goto end; if (!event && dp->debug->sim_mode) { dp_display_disconnect_sync(dp); dp->debug->abort(dp->debug); } end: return NOTIFY_DONE; } static int dp_display_get_usb_extcon(struct dp_display_private *dp) { struct extcon_dev *edev; int rc; edev = extcon_get_edev_by_phandle(&dp->pdev->dev, 0); if (IS_ERR(edev)) return PTR_ERR(edev); dp->usb_nb.notifier_call = dp_display_usb_notifier; dp->usb_nb.priority = 2; rc = extcon_register_notifier(edev, EXTCON_USB, &dp->usb_nb); if (rc) pr_err("failed to register for usb event: %d\n", rc); return rc; } static void dp_display_deinit_sub_modules(struct dp_display_private *dp) { dp_audio_put(dp->panel->audio); Loading Loading @@ -1209,6 +1239,8 @@ static int dp_init_sub_modules(struct dp_display_private *dp) dp->debug->hdcp_disabled = hdcp_disabled; dp_display_update_hdcp_status(dp, true); dp_display_get_usb_extcon(dp); return rc; error_debug: dp_hpd_put(dp->hpd); Loading drivers/gpu/drm/msm/dp/dp_panel.c +1 −0 Original line number Diff line number Diff line Loading @@ -1004,6 +1004,7 @@ static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid) panel->custom_edid = true; } else { panel->custom_edid = false; dp_panel->edid_ctrl->edid = NULL; } pr_debug("%d\n", panel->custom_edid); Loading Loading
drivers/gpu/drm/msm/dp/dp_audio.c +1 −3 Original line number Diff line number Diff line Loading @@ -679,10 +679,8 @@ static int dp_audio_notify(struct dp_audio_private *audio, u32 state) reinit_completion(&audio->hpd_comp); rc = ext->intf_ops.audio_notify(audio->ext_pdev, &ext->codec, state); if (rc) { pr_err("failed to notify audio. state=%d err=%d\n", state, rc); if (rc) goto end; } if (atomic_read(&audio->acked)) goto end; Loading
drivers/gpu/drm/msm/dp/dp_debug.c +70 −31 Original line number Diff line number Diff line Loading @@ -163,6 +163,13 @@ static ssize_t dp_debug_write_edid(struct file *file, kfree(buf); debug->panel->set_edid(debug->panel, edid); /* * print edid status as this code is executed * only while running in debug mode which is manually * triggered by a tester or a script. */ pr_info("[%s]\n", edid ? "SET" : "CLEAR"); return rc; } Loading Loading @@ -250,10 +257,18 @@ static ssize_t dp_debug_write_dpcd(struct file *file, * Reset panel's dpcd in case of any failure. Also, set the * panel's dpcd only if a full dpcd is provided with offset as 0. */ if (!dpcd || (!offset && (data_len == dp_receiver_cap_size))) if (!dpcd || (!offset && (data_len == dp_receiver_cap_size))) { debug->panel->set_dpcd(debug->panel, dpcd); else /* * print dpcd status as this code is executed * only while running in debug mode which is manually * triggered by a tester or a script. */ pr_info("[%s]\n", dpcd ? "SET" : "CLEAR"); } else { debug->aux->dpcd_updated(debug->aux); } return rc; } Loading Loading @@ -1392,36 +1407,16 @@ static ssize_t dp_debug_read_hdr(struct file *file, return rc; } static ssize_t dp_debug_write_sim(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim) { struct dp_debug_private *debug = file->private_data; char buf[SZ_8]; size_t len = 0; int sim; if (!debug) return -ENODEV; if (*ppos) return 0; /* Leave room for termination char */ len = min_t(size_t, count, SZ_8 - 1); if (copy_from_user(buf, user_buff, len)) goto end; buf[len] = '\0'; if (kstrtoint(buf, 10, &sim) != 0) goto end; if (sim) { if (dp_debug_get_edid_buf(debug)) goto end; return; if (dp_debug_get_dpcd_buf(debug)) goto error; if (dp_debug_get_dpcd_buf(debug)) { devm_kfree(debug->dev, debug->edid); return; } debug->dp_debug.sim_mode = true; debug->aux->set_sim_mode(debug->aux, true, Loading @@ -1442,11 +1437,42 @@ static ssize_t dp_debug_write_sim(struct file *file, debug->dpcd = NULL; } } /* * print simulation status as this code is executed * only while running in debug mode which is manually * triggered by a tester or a script. */ pr_info("%s\n", sim ? "[ON]" : "[OFF]"); } static ssize_t dp_debug_write_sim(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; char buf[SZ_8]; size_t len = 0; int sim; if (!debug) return -ENODEV; if (*ppos) return 0; /* Leave room for termination char */ len = min_t(size_t, count, SZ_8 - 1); if (copy_from_user(buf, user_buff, len)) goto end; buf[len] = '\0'; if (kstrtoint(buf, 10, &sim) != 0) goto end; dp_debug_set_sim_mode(debug, sim); end: return len; error: devm_kfree(debug->dev, debug->edid); return len; } static ssize_t dp_debug_write_attention(struct file *file, Loading Loading @@ -1898,6 +1924,18 @@ u8 *dp_debug_get_edid(struct dp_debug *dp_debug) return debug->edid; } static void dp_debug_abort(struct dp_debug *dp_debug) { struct dp_debug_private *debug; if (!dp_debug) return; debug = container_of(dp_debug, struct dp_debug_private, dp_debug); dp_debug_set_sim_mode(debug, false); } struct dp_debug *dp_debug_get(struct dp_debug_in *in) { int rc = 0; Loading Loading @@ -1938,6 +1976,7 @@ struct dp_debug *dp_debug_get(struct dp_debug_in *in) } dp_debug->get_edid = dp_debug_get_edid; dp_debug->abort = dp_debug_abort; INIT_LIST_HEAD(&dp_debug->dp_mst_connector_list.list); Loading
drivers/gpu/drm/msm/dp/dp_debug.h +1 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ struct dp_debug { struct dp_mst_connector dp_mst_connector_list; u8 *(*get_edid)(struct dp_debug *dp_debug); void (*abort)(struct dp_debug *dp_debug); }; /** Loading
drivers/gpu/drm/msm/dp/dp_display.c +68 −36 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/debugfs.h> #include <linux/component.h> #include <linux/of_irq.h> #include <linux/extcon.h> #include <linux/soc/qcom/fsa4480-i2c.h> #include "sde_connector.h" Loading Loading @@ -107,6 +108,8 @@ struct dp_display_private { u32 active_stream_cnt; struct dp_mst mst; struct notifier_block usb_nb; }; static const struct of_device_id dp_dt_match[] = { Loading Loading @@ -556,6 +559,9 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp) if (hpd && dp->mst.mst_active) goto skip_wait; if (!dp->mst.mst_active && (dp->power_on == hpd)) goto skip_wait; if (!wait_for_completion_timeout(&dp->notification_comp, HZ * timeout_sec)) { pr_warn("%s timeout\n", hpd ? "connect" : "disconnect"); Loading Loading @@ -846,6 +852,24 @@ static int dp_display_handle_disconnect(struct dp_display_private *dp) return rc; } static void dp_display_disconnect_sync(struct dp_display_private *dp) { /* cancel any pending request */ atomic_set(&dp->aborted, 1); dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); cancel_work(&dp->attention_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); /* Reset abort value to allow future connections */ atomic_set(&dp->aborted, 0); } static int dp_display_usbpd_disconnect_cb(struct device *dev) { int rc = 0; Loading Loading @@ -874,21 +898,7 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) if (dp->debug->psm_enabled) dp->link->psm_config(dp->link, &dp->panel->link_info, true); /* cancel any pending request */ atomic_set(&dp->aborted, 1); dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); cancel_work(&dp->attention_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); /* Reset abort value to allow future connections */ atomic_set(&dp->aborted, 0); dp_display_disconnect_sync(dp); dp->dp_display.post_open = NULL; end: return rc; Loading Loading @@ -990,29 +1000,14 @@ static int dp_display_usbpd_attention_cb(struct device *dev) dp->hpd->hpd_irq, dp->hpd->hpd_high, dp->power_on); if (!dp->hpd->hpd_high) { if (!dp->is_connected) { pr_debug("already disconnected\n"); return 0; } /* cancel any pending request */ atomic_set(&dp->aborted, 1); dp->ctrl->abort(dp->ctrl); dp->aux->abort(dp->aux); /* wait for idle state */ cancel_delayed_work(&dp->connect_work); cancel_work(&dp->attention_work); flush_workqueue(dp->wq); dp_display_handle_disconnect(dp); atomic_set(&dp->aborted, 0); } else if (dp->hpd->hpd_irq && dp->core_initialized) { if (!dp->hpd->hpd_high) dp_display_disconnect_sync(dp); else if (dp->hpd->hpd_irq && dp->core_initialized) queue_work(dp->wq, &dp->attention_work); } else { else if (!dp->power_on) queue_delayed_work(dp->wq, &dp->connect_work, 0); } else pr_debug("ignored\n"); return 0; } Loading Loading @@ -1040,6 +1035,41 @@ static void dp_display_connect_work(struct work_struct *work) dp->link->send_test_response(dp->link); } static int dp_display_usb_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { struct extcon_dev *edev = ptr; struct dp_display_private *dp = container_of(nb, struct dp_display_private, usb_nb); if (!edev) goto end; if (!event && dp->debug->sim_mode) { dp_display_disconnect_sync(dp); dp->debug->abort(dp->debug); } end: return NOTIFY_DONE; } static int dp_display_get_usb_extcon(struct dp_display_private *dp) { struct extcon_dev *edev; int rc; edev = extcon_get_edev_by_phandle(&dp->pdev->dev, 0); if (IS_ERR(edev)) return PTR_ERR(edev); dp->usb_nb.notifier_call = dp_display_usb_notifier; dp->usb_nb.priority = 2; rc = extcon_register_notifier(edev, EXTCON_USB, &dp->usb_nb); if (rc) pr_err("failed to register for usb event: %d\n", rc); return rc; } static void dp_display_deinit_sub_modules(struct dp_display_private *dp) { dp_audio_put(dp->panel->audio); Loading Loading @@ -1209,6 +1239,8 @@ static int dp_init_sub_modules(struct dp_display_private *dp) dp->debug->hdcp_disabled = hdcp_disabled; dp_display_update_hdcp_status(dp, true); dp_display_get_usb_extcon(dp); return rc; error_debug: dp_hpd_put(dp->hpd); Loading
drivers/gpu/drm/msm/dp/dp_panel.c +1 −0 Original line number Diff line number Diff line Loading @@ -1004,6 +1004,7 @@ static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid) panel->custom_edid = true; } else { panel->custom_edid = false; dp_panel->edid_ctrl->edid = NULL; } pr_debug("%d\n", panel->custom_edid); Loading