Loading drivers/gpu/drm/msm/dp/dp_aux.c +24 −8 Original line number Diff line number Diff line Loading @@ -492,30 +492,42 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux, goto end; } if ((msg->address + msg->size) > SZ_16K) { if ((msg->address + msg->size) > SZ_4K) { pr_err("invalid dpcd access: addr=0x%x, size=0x%x\n", msg->address + msg->size); goto address_error; } if (aux->native) { if (aux->read) { aux->dp_aux.reg = msg->address; aux->dp_aux.read = aux->read; aux->dp_aux.size = msg->size; reinit_completion(&aux->comp); if (aux->read) { timeout = wait_for_completion_timeout(&aux->comp, HZ); if (!timeout) if (!timeout) { pr_err("aux timeout for 0x%x\n", msg->address); aux->dp_aux.reg = 0xFFFF; ret = -ETIMEDOUT; goto end; } memcpy(msg->buffer, aux->dpcd + msg->address, msg->size); aux->aux_error_num = DP_AUX_ERR_NONE; } else { memcpy(aux->dpcd + msg->address, msg->buffer, msg->size); timeout = wait_for_completion_timeout(&aux->comp, HZ); if (!timeout) { pr_err("aux timeout for 0x%x\n", msg->address); ret = -ETIMEDOUT; goto end; } } aux->aux_error_num = DP_AUX_ERR_NONE; } else { if (aux->read && msg->address == 0x50) { memcpy(msg->buffer, Loading Loading @@ -545,6 +557,10 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux, memset(msg->buffer, 0, msg->size); ret = msg->size; end: aux->dp_aux.reg = 0xFFFF; aux->dp_aux.read = true; aux->dp_aux.size = 0; mutex_unlock(&aux->mutex); return ret; } Loading drivers/gpu/drm/msm/dp/dp_aux.h +3 −0 Original line number Diff line number Diff line Loading @@ -43,8 +43,11 @@ enum dp_aux_error { struct dp_aux { u32 reg; u32 size; u32 state; bool read; struct drm_dp_aux *drm_aux; int (*drm_aux_register)(struct dp_aux *aux); void (*drm_aux_deregister)(struct dp_aux *aux); Loading drivers/gpu/drm/msm/dp/dp_debug.c +28 −8 Original line number Diff line number Diff line Loading @@ -74,13 +74,13 @@ static int dp_debug_get_dpcd_buf(struct dp_debug_private *debug) int rc = 0; if (!debug->dpcd) { debug->dpcd = devm_kzalloc(debug->dev, SZ_16K, GFP_KERNEL); debug->dpcd = devm_kzalloc(debug->dev, SZ_4K, GFP_KERNEL); if (!debug->dpcd) { rc = -ENOMEM; goto end; } debug->dpcd_size = SZ_16K; debug->dpcd_size = SZ_4K; } end: return rc; Loading Loading @@ -254,21 +254,41 @@ static ssize_t dp_debug_read_dpcd(struct file *file, char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; char buf[SZ_8]; char *buf; int const buf_size = SZ_4K; u32 offset = 0; u32 len = 0; if (!debug) if (!debug || !debug->aux || !debug->dpcd) return -ENODEV; if (*ppos) return 0; len += snprintf(buf, SZ_8, "0x%x\n", debug->aux->reg); buf = kzalloc(buf_size, GFP_KERNEL); if (!buf) return -ENOMEM; len += snprintf(buf, buf_size, "0x%x", debug->aux->reg); if (copy_to_user(user_buff, buf, len)) return -EFAULT; if (!debug->aux->read) { while (1) { if (debug->aux->reg + offset >= buf_size || offset >= debug->aux->size) break; len += snprintf(buf + len, buf_size - len, "0x%x", debug->dpcd[debug->aux->reg + offset++]); } if (debug->dp_debug.sim_mode && debug->aux->dpcd_updated) debug->aux->dpcd_updated(debug->aux); } if (!copy_to_user(user_buff, buf, len)) *ppos += len; kfree(buf); return len; } Loading drivers/gpu/drm/msm/dp/dp_display.c +21 −23 Original line number Diff line number Diff line Loading @@ -603,10 +603,11 @@ static void dp_display_host_init(struct dp_display_private *dp) bool flip = false; bool reset; if (dp->core_initialized) { pr_debug("DP core already initialized\n"); if (dp->core_initialized) return; } if (!dp->debug->sim_mode && !dp->parser->no_aux_switch) dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation); if (dp->hpd->orientation == ORIENTATION_CC2) flip = true; Loading @@ -618,38 +619,39 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->aux->init(dp->aux, dp->parser->aux_cfg); enable_irq(dp->irq); dp->core_initialized = true; /* log this as it results from user action of cable connection */ pr_info("[OK]\n"); } static void dp_display_host_deinit(struct dp_display_private *dp) { if (!dp->core_initialized) { pr_debug("DP core already off\n"); if (!dp->core_initialized) return; } if (dp->active_stream_cnt) { pr_debug("active stream present\n"); return; } if (!dp->debug->sim_mode && !dp->parser->no_aux_switch) dp->aux->aux_switch(dp->aux, false, ORIENTATION_NONE); dp->aux->deinit(dp->aux); dp->ctrl->deinit(dp->ctrl); dp->power->deinit(dp->power); disable_irq(dp->irq); dp->core_initialized = false; dp->aux->state = 0; /* log this as it results from user action of cable dis-connection */ pr_info("[OK]\n"); } static int dp_display_process_hpd_high(struct dp_display_private *dp) { int rc = 0; if (!dp->debug->sim_mode && !dp->parser->no_aux_switch) { rc = dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation); if (rc) goto end; } dp->is_connected = true; dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; Loading Loading @@ -727,10 +729,8 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp) dp_panel = dp->active_panels[idx]; if (dp_panel->audio_supported) { if (dp_panel->audio_supported) dp_panel->audio->off(dp_panel->audio); dp_panel->audio_supported = false; } } mutex_unlock(&dp->session_lock); Loading Loading @@ -767,6 +767,8 @@ static int dp_display_usbpd_configure_cb(struct device *dev) goto end; } dp_display_host_init(dp); /* check for hpd high and framework ready */ if (dp->hpd->hpd_high && dp_display_framework_ready(dp)) queue_delayed_work(dp->wq, &dp->connect_work, 0); Loading Loading @@ -860,9 +862,6 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) cancel_work(&dp->attention_work); flush_workqueue(dp->wq); if (!dp->debug->sim_mode && !dp->parser->no_aux_switch) dp->aux->aux_switch(dp->aux, false, ORIENTATION_NONE); dp_display_handle_disconnect(dp); /* Reset abort value to allow future connections */ Loading Loading @@ -981,7 +980,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev) return -ENODEV; } DP_MST_DEBUG("mst: hpd_irq:%d, hpd_high:%d, power_on:%d\n", pr_debug("hpd_irq:%d, hpd_high:%d, power_on:%d\n", dp->hpd->hpd_irq, dp->hpd->hpd_high, dp->power_on); Loading Loading @@ -1428,7 +1427,6 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct dp_panel *dp_panel; struct edid *edid; if (!dp_display || !panel) { pr_err("invalid input\n"); Loading @@ -1455,9 +1453,6 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) dp_display_stream_post_enable(dp, dp_panel); edid = dp_panel->edid_ctrl->edid; dp_panel->audio_supported = drm_detect_monitor_audio(edid); if (dp_panel->audio_supported) { dp_panel->audio->bw_code = dp->link->link_params.bw_code; dp_panel->audio->lane_count = dp->link->link_params.lane_count; Loading Loading @@ -1568,6 +1563,9 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel) } dp->power_on = false; /* log this as it results from user action of cable dis-connection */ pr_info("[OK]\n"); end: dp_panel->deinit(dp_panel); mutex_unlock(&dp->session_lock); Loading drivers/gpu/drm/msm/dp/dp_mst_drm.c +24 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #define MAX_DP_MST_DRM_ENCODERS 2 #define MAX_DP_MST_DRM_BRIDGES 2 #define DP_MST_SIM_MAX_PORTS 2 #define HPD_STRING_SIZE 30 struct dp_drm_mst_fw_helper_ops { int (*calc_pbn_mode)(int clock, int bpp); Loading Loading @@ -1330,6 +1331,27 @@ static void dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) DP_MST_DEBUG("mst hot plug event\n"); } static void dp_mst_hpd_event_notify(struct dp_mst_private *mst, bool hpd_status) { struct drm_device *dev = mst->dp_display->drm_dev; char event_string[] = "MST_HOTPLUG=1"; char status[HPD_STRING_SIZE]; char *envp[3]; if (hpd_status) snprintf(status, HPD_STRING_SIZE, "status=connected"); else snprintf(status, HPD_STRING_SIZE, "status=disconnected"); envp[0] = event_string; envp[1] = status; envp[2] = NULL; kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); DP_MST_DEBUG("%s finished\n", __func__); } /* DP Driver Callback OPs */ static void dp_mst_display_hpd(void *dp_display, bool hpd_status, Loading Loading @@ -1357,6 +1379,8 @@ static void dp_mst_display_hpd(void *dp_display, bool hpd_status, rc = mst->mst_fw_cbs->topology_mgr_set_mst(&mst->mst_mgr, 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"); Loading Loading
drivers/gpu/drm/msm/dp/dp_aux.c +24 −8 Original line number Diff line number Diff line Loading @@ -492,30 +492,42 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux, goto end; } if ((msg->address + msg->size) > SZ_16K) { if ((msg->address + msg->size) > SZ_4K) { pr_err("invalid dpcd access: addr=0x%x, size=0x%x\n", msg->address + msg->size); goto address_error; } if (aux->native) { if (aux->read) { aux->dp_aux.reg = msg->address; aux->dp_aux.read = aux->read; aux->dp_aux.size = msg->size; reinit_completion(&aux->comp); if (aux->read) { timeout = wait_for_completion_timeout(&aux->comp, HZ); if (!timeout) if (!timeout) { pr_err("aux timeout for 0x%x\n", msg->address); aux->dp_aux.reg = 0xFFFF; ret = -ETIMEDOUT; goto end; } memcpy(msg->buffer, aux->dpcd + msg->address, msg->size); aux->aux_error_num = DP_AUX_ERR_NONE; } else { memcpy(aux->dpcd + msg->address, msg->buffer, msg->size); timeout = wait_for_completion_timeout(&aux->comp, HZ); if (!timeout) { pr_err("aux timeout for 0x%x\n", msg->address); ret = -ETIMEDOUT; goto end; } } aux->aux_error_num = DP_AUX_ERR_NONE; } else { if (aux->read && msg->address == 0x50) { memcpy(msg->buffer, Loading Loading @@ -545,6 +557,10 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux, memset(msg->buffer, 0, msg->size); ret = msg->size; end: aux->dp_aux.reg = 0xFFFF; aux->dp_aux.read = true; aux->dp_aux.size = 0; mutex_unlock(&aux->mutex); return ret; } Loading
drivers/gpu/drm/msm/dp/dp_aux.h +3 −0 Original line number Diff line number Diff line Loading @@ -43,8 +43,11 @@ enum dp_aux_error { struct dp_aux { u32 reg; u32 size; u32 state; bool read; struct drm_dp_aux *drm_aux; int (*drm_aux_register)(struct dp_aux *aux); void (*drm_aux_deregister)(struct dp_aux *aux); Loading
drivers/gpu/drm/msm/dp/dp_debug.c +28 −8 Original line number Diff line number Diff line Loading @@ -74,13 +74,13 @@ static int dp_debug_get_dpcd_buf(struct dp_debug_private *debug) int rc = 0; if (!debug->dpcd) { debug->dpcd = devm_kzalloc(debug->dev, SZ_16K, GFP_KERNEL); debug->dpcd = devm_kzalloc(debug->dev, SZ_4K, GFP_KERNEL); if (!debug->dpcd) { rc = -ENOMEM; goto end; } debug->dpcd_size = SZ_16K; debug->dpcd_size = SZ_4K; } end: return rc; Loading Loading @@ -254,21 +254,41 @@ static ssize_t dp_debug_read_dpcd(struct file *file, char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; char buf[SZ_8]; char *buf; int const buf_size = SZ_4K; u32 offset = 0; u32 len = 0; if (!debug) if (!debug || !debug->aux || !debug->dpcd) return -ENODEV; if (*ppos) return 0; len += snprintf(buf, SZ_8, "0x%x\n", debug->aux->reg); buf = kzalloc(buf_size, GFP_KERNEL); if (!buf) return -ENOMEM; len += snprintf(buf, buf_size, "0x%x", debug->aux->reg); if (copy_to_user(user_buff, buf, len)) return -EFAULT; if (!debug->aux->read) { while (1) { if (debug->aux->reg + offset >= buf_size || offset >= debug->aux->size) break; len += snprintf(buf + len, buf_size - len, "0x%x", debug->dpcd[debug->aux->reg + offset++]); } if (debug->dp_debug.sim_mode && debug->aux->dpcd_updated) debug->aux->dpcd_updated(debug->aux); } if (!copy_to_user(user_buff, buf, len)) *ppos += len; kfree(buf); return len; } Loading
drivers/gpu/drm/msm/dp/dp_display.c +21 −23 Original line number Diff line number Diff line Loading @@ -603,10 +603,11 @@ static void dp_display_host_init(struct dp_display_private *dp) bool flip = false; bool reset; if (dp->core_initialized) { pr_debug("DP core already initialized\n"); if (dp->core_initialized) return; } if (!dp->debug->sim_mode && !dp->parser->no_aux_switch) dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation); if (dp->hpd->orientation == ORIENTATION_CC2) flip = true; Loading @@ -618,38 +619,39 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->aux->init(dp->aux, dp->parser->aux_cfg); enable_irq(dp->irq); dp->core_initialized = true; /* log this as it results from user action of cable connection */ pr_info("[OK]\n"); } static void dp_display_host_deinit(struct dp_display_private *dp) { if (!dp->core_initialized) { pr_debug("DP core already off\n"); if (!dp->core_initialized) return; } if (dp->active_stream_cnt) { pr_debug("active stream present\n"); return; } if (!dp->debug->sim_mode && !dp->parser->no_aux_switch) dp->aux->aux_switch(dp->aux, false, ORIENTATION_NONE); dp->aux->deinit(dp->aux); dp->ctrl->deinit(dp->ctrl); dp->power->deinit(dp->power); disable_irq(dp->irq); dp->core_initialized = false; dp->aux->state = 0; /* log this as it results from user action of cable dis-connection */ pr_info("[OK]\n"); } static int dp_display_process_hpd_high(struct dp_display_private *dp) { int rc = 0; if (!dp->debug->sim_mode && !dp->parser->no_aux_switch) { rc = dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation); if (rc) goto end; } dp->is_connected = true; dp->dp_display.max_pclk_khz = dp->parser->max_pclk_khz; Loading Loading @@ -727,10 +729,8 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp) dp_panel = dp->active_panels[idx]; if (dp_panel->audio_supported) { if (dp_panel->audio_supported) dp_panel->audio->off(dp_panel->audio); dp_panel->audio_supported = false; } } mutex_unlock(&dp->session_lock); Loading Loading @@ -767,6 +767,8 @@ static int dp_display_usbpd_configure_cb(struct device *dev) goto end; } dp_display_host_init(dp); /* check for hpd high and framework ready */ if (dp->hpd->hpd_high && dp_display_framework_ready(dp)) queue_delayed_work(dp->wq, &dp->connect_work, 0); Loading Loading @@ -860,9 +862,6 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) cancel_work(&dp->attention_work); flush_workqueue(dp->wq); if (!dp->debug->sim_mode && !dp->parser->no_aux_switch) dp->aux->aux_switch(dp->aux, false, ORIENTATION_NONE); dp_display_handle_disconnect(dp); /* Reset abort value to allow future connections */ Loading Loading @@ -981,7 +980,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev) return -ENODEV; } DP_MST_DEBUG("mst: hpd_irq:%d, hpd_high:%d, power_on:%d\n", pr_debug("hpd_irq:%d, hpd_high:%d, power_on:%d\n", dp->hpd->hpd_irq, dp->hpd->hpd_high, dp->power_on); Loading Loading @@ -1428,7 +1427,6 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct dp_panel *dp_panel; struct edid *edid; if (!dp_display || !panel) { pr_err("invalid input\n"); Loading @@ -1455,9 +1453,6 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) dp_display_stream_post_enable(dp, dp_panel); edid = dp_panel->edid_ctrl->edid; dp_panel->audio_supported = drm_detect_monitor_audio(edid); if (dp_panel->audio_supported) { dp_panel->audio->bw_code = dp->link->link_params.bw_code; dp_panel->audio->lane_count = dp->link->link_params.lane_count; Loading Loading @@ -1568,6 +1563,9 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel) } dp->power_on = false; /* log this as it results from user action of cable dis-connection */ pr_info("[OK]\n"); end: dp_panel->deinit(dp_panel); mutex_unlock(&dp->session_lock); Loading
drivers/gpu/drm/msm/dp/dp_mst_drm.c +24 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #define MAX_DP_MST_DRM_ENCODERS 2 #define MAX_DP_MST_DRM_BRIDGES 2 #define DP_MST_SIM_MAX_PORTS 2 #define HPD_STRING_SIZE 30 struct dp_drm_mst_fw_helper_ops { int (*calc_pbn_mode)(int clock, int bpp); Loading Loading @@ -1330,6 +1331,27 @@ static void dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) DP_MST_DEBUG("mst hot plug event\n"); } static void dp_mst_hpd_event_notify(struct dp_mst_private *mst, bool hpd_status) { struct drm_device *dev = mst->dp_display->drm_dev; char event_string[] = "MST_HOTPLUG=1"; char status[HPD_STRING_SIZE]; char *envp[3]; if (hpd_status) snprintf(status, HPD_STRING_SIZE, "status=connected"); else snprintf(status, HPD_STRING_SIZE, "status=disconnected"); envp[0] = event_string; envp[1] = status; envp[2] = NULL; kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); DP_MST_DEBUG("%s finished\n", __func__); } /* DP Driver Callback OPs */ static void dp_mst_display_hpd(void *dp_display, bool hpd_status, Loading Loading @@ -1357,6 +1379,8 @@ static void dp_mst_display_hpd(void *dp_display, bool hpd_status, rc = mst->mst_fw_cbs->topology_mgr_set_mst(&mst->mst_mgr, 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"); Loading