Loading drivers/gpu/drm/msm/dp/dp_catalog.c +14 −11 Original line number Diff line number Diff line Loading @@ -1563,6 +1563,7 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl, struct dp_io_data *io_data = NULL; u32 i, slot_reg_1, slot_reg_2, slot; u32 reg_off = 0; int const num_slots_per_reg = 32; if (!ctrl || ch >= DP_STREAM_MAX) { pr_err("invalid input. ch %d\n", ch); Loading @@ -1586,19 +1587,21 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl, if (ch == DP_STREAM_1) reg_off = DP_DP1_TIMESLOT_1_32 - DP_DP0_TIMESLOT_1_32; slot_reg_1 = dp_read(catalog, io_data, DP_DP0_TIMESLOT_1_32 + reg_off); slot_reg_2 = dp_read(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off); slot_reg_1 = 0; slot_reg_2 = 0; ch_start_slot = ch_start_slot - 1; if (ch_start_slot && tot_slot_cnt) { ch_start_slot--; for (i = 0; i < tot_slot_cnt; i++) { if (ch_start_slot < 32) { if (ch_start_slot < num_slots_per_reg) { slot_reg_1 |= BIT(ch_start_slot); } else { slot = ch_start_slot - 32; slot = ch_start_slot - num_slots_per_reg; slot_reg_2 |= BIT(slot); } ch_start_slot++; } } pr_debug("ch:%d slot_reg_1:%d, slot_reg_2:%d\n", ch, slot_reg_1, slot_reg_2); Loading drivers/gpu/drm/msm/dp/dp_ctrl.c +46 −15 Original line number Diff line number Diff line Loading @@ -50,6 +50,15 @@ #define MR_LINK_CUSTOM80 0x200 #define MR_LINK_TRAINING4 0x40 struct dp_mst_ch_slot_info { u32 start_slot; u32 tot_slots; }; struct dp_mst_channel_info { struct dp_mst_ch_slot_info slot_info[DP_STREAM_MAX]; }; struct dp_ctrl_private { struct dp_ctrl dp_ctrl; Loading @@ -71,6 +80,7 @@ struct dp_ctrl_private { atomic_t aborted; u32 vic; struct dp_mst_channel_info mst_ch_info; }; enum notification_status { Loading Loading @@ -929,20 +939,23 @@ static int dp_ctrl_mst_send_act(struct dp_ctrl_private *ctrl) return 0; } static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, static void dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, struct dp_panel *panel) { u32 x_int, y_frac_enum, lanes, bw_code; int i; if (!ctrl->mst_mode) return 0; return; DP_MST_DEBUG("mst stream channel allocation\n"); for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { ctrl->catalog->channel_alloc(ctrl->catalog, panel->stream_id, panel->channel_start_slot, panel->channel_total_slots); i, ctrl->mst_ch_info.slot_info[i].start_slot, ctrl->mst_ch_info.slot_info[i].tot_slots); } lanes = ctrl->link->link_params.lane_count; bw_code = ctrl->link->link_params.bw_code; Loading @@ -958,8 +971,6 @@ static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, DP_MST_DEBUG("mst lane_cnt:%d, bw:%d, x_int:%d, y_frac:%d\n", lanes, bw_code, x_int, y_frac_enum); return 0; } static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) Loading Loading @@ -989,9 +1000,7 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) if (rc) return rc; rc = dp_ctrl_mst_stream_setup(ctrl, panel); if (rc) goto error; dp_ctrl_mst_stream_setup(ctrl, panel); dp_ctrl_send_video(ctrl); Loading @@ -1016,16 +1025,19 @@ static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl, { struct dp_ctrl_private *ctrl; bool act_complete; int i; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); if (!ctrl->mst_mode) return; ctrl->catalog->channel_dealloc(ctrl->catalog, panel->stream_id, panel->channel_start_slot, panel->channel_total_slots); for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { ctrl->catalog->channel_alloc(ctrl->catalog, i, ctrl->mst_ch_info.slot_info[i].start_slot, ctrl->mst_ch_info.slot_info[i].tot_slots); } ctrl->catalog->trigger_act(ctrl->catalog); msleep(20); /* needs 1 frame time */ Loading Loading @@ -1153,9 +1165,27 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl) ctrl->mst_mode = false; ctrl->power_on = false; memset(&ctrl->mst_ch_info, 0, sizeof(ctrl->mst_ch_info)); pr_debug("DP off done\n"); } static void dp_ctrl_set_mst_channel_info(struct dp_ctrl *dp_ctrl, enum dp_stream_id strm, u32 start_slot, u32 tot_slots) { struct dp_ctrl_private *ctrl; if (!dp_ctrl || strm >= DP_STREAM_MAX) { pr_err("invalid input\n"); return; } ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); ctrl->mst_ch_info.slot_info[strm].start_slot = start_slot; ctrl->mst_ch_info.slot_info[strm].tot_slots = tot_slots; } static void dp_ctrl_isr(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; Loading Loading @@ -1228,6 +1258,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in) dp_ctrl->stream_on = dp_ctrl_stream_on; dp_ctrl->stream_off = dp_ctrl_stream_off; dp_ctrl->stream_pre_off = dp_ctrl_stream_pre_off; dp_ctrl->set_mst_channel_info = dp_ctrl_set_mst_channel_info; return dp_ctrl; error: Loading drivers/gpu/drm/msm/dp/dp_ctrl.h +3 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,9 @@ struct dp_ctrl { int (*stream_on)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*stream_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*stream_pre_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*set_mst_channel_info)(struct dp_ctrl *dp_ctrl, enum dp_stream_id strm, u32 ch_start_slot, u32 ch_tot_slots); }; struct dp_ctrl_in { Loading drivers/gpu/drm/msm/dp/dp_display.c +63 −7 Original line number Diff line number Diff line Loading @@ -857,14 +857,20 @@ static void dp_display_attention_work(struct work_struct *work) { struct dp_display_private *dp = container_of(work, struct dp_display_private, attention_work); bool is_sink_cnt_zero; if (!dp->power_on) goto mst_attention; if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) { is_sink_cnt_zero = dp_display_is_sink_count_zero(dp); if (dp->mst.mst_active && !is_sink_cnt_zero) goto mst_attention; dp_display_handle_disconnect(dp); if (dp_display_is_sink_count_zero(dp)) { if (is_sink_cnt_zero) { pr_debug("sink count is zero, nothing to do\n"); goto mst_attention; } Loading Loading @@ -1285,20 +1291,44 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel) } static int dp_display_set_stream_info(struct dp_display *dp_display, void *panel, u32 ch_id, u32 ch_start_slot, u32 ch_tot_slots, u32 pbn) void *panel, u32 strm_id, u32 start_slot, u32 num_slots, u32 pbn) { int rc = 0; struct dp_panel *dp_panel; struct dp_display_private *dp; const int max_slots = 64; if (!dp_display || !panel) { if (!dp_display) { pr_err("invalid input\n"); return -EINVAL; } if (strm_id >= DP_STREAM_MAX) { pr_err("invalid stream id:%d\n", strm_id); return -EINVAL; } if (start_slot + num_slots > max_slots) { pr_err("invalid channel info received. start:%d, slots:%d\n", start_slot, num_slots); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); dp->ctrl->set_mst_channel_info(dp->ctrl, strm_id, start_slot, num_slots); if (panel) { dp_panel = panel; dp_panel->set_stream_info(dp_panel, ch_id, ch_start_slot, ch_tot_slots, pbn); dp_panel->set_stream_info(dp_panel, strm_id, start_slot, num_slots, pbn); } mutex_unlock(&dp->session_lock); return rc; } Loading Loading @@ -1688,6 +1718,31 @@ static int dp_display_get_modes(struct dp_display *dp, void *panel, return ret; } static void dp_display_convert_to_dp_mode(struct dp_display *dp_display, void *panel, const struct drm_display_mode *drm_mode, struct dp_display_mode *dp_mode) { struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display || !drm_mode || !dp_mode || !panel) { pr_err("invalid input\n"); return; } dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; mutex_lock(&dp->session_lock); memset(dp_mode, 0, sizeof(*dp_mode)); dp_panel->convert_to_dp_mode(dp_panel, drm_mode, dp_mode); mutex_unlock(&dp->session_lock); } static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr) { Loading Loading @@ -2026,6 +2081,7 @@ static int dp_display_probe(struct platform_device *pdev) dp_display_mst_connector_update_edid; g_dp_display->get_mst_caps = dp_display_get_mst_caps; g_dp_display->set_stream_info = dp_display_set_stream_info; g_dp_display->convert_to_dp_mode = dp_display_convert_to_dp_mode; rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { Loading drivers/gpu/drm/msm/dp/dp_display.h +5 −3 Original line number Diff line number Diff line Loading @@ -85,9 +85,11 @@ struct dp_display { struct edid *edid); int (*get_mst_caps)(struct dp_display *dp_display, struct dp_mst_caps *mst_caps); int (*set_stream_info)(struct dp_display *dp_display, void *panel, u32 ch_id, u32 ch_start_slot, u32 ch_tot_slots, u32 pbn); int (*set_stream_info)(struct dp_display *dp_display, void *panel, u32 strm_id, u32 start_slot, u32 num_slots, u32 pbn); void (*convert_to_dp_mode)(struct dp_display *dp_display, void *panel, const struct drm_display_mode *drm_mode, struct dp_display_mode *dp_mode); }; int dp_display_get_num_of_displays(void); Loading Loading
drivers/gpu/drm/msm/dp/dp_catalog.c +14 −11 Original line number Diff line number Diff line Loading @@ -1563,6 +1563,7 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl, struct dp_io_data *io_data = NULL; u32 i, slot_reg_1, slot_reg_2, slot; u32 reg_off = 0; int const num_slots_per_reg = 32; if (!ctrl || ch >= DP_STREAM_MAX) { pr_err("invalid input. ch %d\n", ch); Loading @@ -1586,19 +1587,21 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl, if (ch == DP_STREAM_1) reg_off = DP_DP1_TIMESLOT_1_32 - DP_DP0_TIMESLOT_1_32; slot_reg_1 = dp_read(catalog, io_data, DP_DP0_TIMESLOT_1_32 + reg_off); slot_reg_2 = dp_read(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off); slot_reg_1 = 0; slot_reg_2 = 0; ch_start_slot = ch_start_slot - 1; if (ch_start_slot && tot_slot_cnt) { ch_start_slot--; for (i = 0; i < tot_slot_cnt; i++) { if (ch_start_slot < 32) { if (ch_start_slot < num_slots_per_reg) { slot_reg_1 |= BIT(ch_start_slot); } else { slot = ch_start_slot - 32; slot = ch_start_slot - num_slots_per_reg; slot_reg_2 |= BIT(slot); } ch_start_slot++; } } pr_debug("ch:%d slot_reg_1:%d, slot_reg_2:%d\n", ch, slot_reg_1, slot_reg_2); Loading
drivers/gpu/drm/msm/dp/dp_ctrl.c +46 −15 Original line number Diff line number Diff line Loading @@ -50,6 +50,15 @@ #define MR_LINK_CUSTOM80 0x200 #define MR_LINK_TRAINING4 0x40 struct dp_mst_ch_slot_info { u32 start_slot; u32 tot_slots; }; struct dp_mst_channel_info { struct dp_mst_ch_slot_info slot_info[DP_STREAM_MAX]; }; struct dp_ctrl_private { struct dp_ctrl dp_ctrl; Loading @@ -71,6 +80,7 @@ struct dp_ctrl_private { atomic_t aborted; u32 vic; struct dp_mst_channel_info mst_ch_info; }; enum notification_status { Loading Loading @@ -929,20 +939,23 @@ static int dp_ctrl_mst_send_act(struct dp_ctrl_private *ctrl) return 0; } static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, static void dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, struct dp_panel *panel) { u32 x_int, y_frac_enum, lanes, bw_code; int i; if (!ctrl->mst_mode) return 0; return; DP_MST_DEBUG("mst stream channel allocation\n"); for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { ctrl->catalog->channel_alloc(ctrl->catalog, panel->stream_id, panel->channel_start_slot, panel->channel_total_slots); i, ctrl->mst_ch_info.slot_info[i].start_slot, ctrl->mst_ch_info.slot_info[i].tot_slots); } lanes = ctrl->link->link_params.lane_count; bw_code = ctrl->link->link_params.bw_code; Loading @@ -958,8 +971,6 @@ static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, DP_MST_DEBUG("mst lane_cnt:%d, bw:%d, x_int:%d, y_frac:%d\n", lanes, bw_code, x_int, y_frac_enum); return 0; } static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) Loading Loading @@ -989,9 +1000,7 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) if (rc) return rc; rc = dp_ctrl_mst_stream_setup(ctrl, panel); if (rc) goto error; dp_ctrl_mst_stream_setup(ctrl, panel); dp_ctrl_send_video(ctrl); Loading @@ -1016,16 +1025,19 @@ static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl, { struct dp_ctrl_private *ctrl; bool act_complete; int i; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); if (!ctrl->mst_mode) return; ctrl->catalog->channel_dealloc(ctrl->catalog, panel->stream_id, panel->channel_start_slot, panel->channel_total_slots); for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { ctrl->catalog->channel_alloc(ctrl->catalog, i, ctrl->mst_ch_info.slot_info[i].start_slot, ctrl->mst_ch_info.slot_info[i].tot_slots); } ctrl->catalog->trigger_act(ctrl->catalog); msleep(20); /* needs 1 frame time */ Loading Loading @@ -1153,9 +1165,27 @@ static void dp_ctrl_off(struct dp_ctrl *dp_ctrl) ctrl->mst_mode = false; ctrl->power_on = false; memset(&ctrl->mst_ch_info, 0, sizeof(ctrl->mst_ch_info)); pr_debug("DP off done\n"); } static void dp_ctrl_set_mst_channel_info(struct dp_ctrl *dp_ctrl, enum dp_stream_id strm, u32 start_slot, u32 tot_slots) { struct dp_ctrl_private *ctrl; if (!dp_ctrl || strm >= DP_STREAM_MAX) { pr_err("invalid input\n"); return; } ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); ctrl->mst_ch_info.slot_info[strm].start_slot = start_slot; ctrl->mst_ch_info.slot_info[strm].tot_slots = tot_slots; } static void dp_ctrl_isr(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; Loading Loading @@ -1228,6 +1258,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in) dp_ctrl->stream_on = dp_ctrl_stream_on; dp_ctrl->stream_off = dp_ctrl_stream_off; dp_ctrl->stream_pre_off = dp_ctrl_stream_pre_off; dp_ctrl->set_mst_channel_info = dp_ctrl_set_mst_channel_info; return dp_ctrl; error: Loading
drivers/gpu/drm/msm/dp/dp_ctrl.h +3 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,9 @@ struct dp_ctrl { int (*stream_on)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*stream_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*stream_pre_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); void (*set_mst_channel_info)(struct dp_ctrl *dp_ctrl, enum dp_stream_id strm, u32 ch_start_slot, u32 ch_tot_slots); }; struct dp_ctrl_in { Loading
drivers/gpu/drm/msm/dp/dp_display.c +63 −7 Original line number Diff line number Diff line Loading @@ -857,14 +857,20 @@ static void dp_display_attention_work(struct work_struct *work) { struct dp_display_private *dp = container_of(work, struct dp_display_private, attention_work); bool is_sink_cnt_zero; if (!dp->power_on) goto mst_attention; if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) { is_sink_cnt_zero = dp_display_is_sink_count_zero(dp); if (dp->mst.mst_active && !is_sink_cnt_zero) goto mst_attention; dp_display_handle_disconnect(dp); if (dp_display_is_sink_count_zero(dp)) { if (is_sink_cnt_zero) { pr_debug("sink count is zero, nothing to do\n"); goto mst_attention; } Loading Loading @@ -1285,20 +1291,44 @@ static int dp_display_prepare(struct dp_display *dp_display, void *panel) } static int dp_display_set_stream_info(struct dp_display *dp_display, void *panel, u32 ch_id, u32 ch_start_slot, u32 ch_tot_slots, u32 pbn) void *panel, u32 strm_id, u32 start_slot, u32 num_slots, u32 pbn) { int rc = 0; struct dp_panel *dp_panel; struct dp_display_private *dp; const int max_slots = 64; if (!dp_display || !panel) { if (!dp_display) { pr_err("invalid input\n"); return -EINVAL; } if (strm_id >= DP_STREAM_MAX) { pr_err("invalid stream id:%d\n", strm_id); return -EINVAL; } if (start_slot + num_slots > max_slots) { pr_err("invalid channel info received. start:%d, slots:%d\n", start_slot, num_slots); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); dp->ctrl->set_mst_channel_info(dp->ctrl, strm_id, start_slot, num_slots); if (panel) { dp_panel = panel; dp_panel->set_stream_info(dp_panel, ch_id, ch_start_slot, ch_tot_slots, pbn); dp_panel->set_stream_info(dp_panel, strm_id, start_slot, num_slots, pbn); } mutex_unlock(&dp->session_lock); return rc; } Loading Loading @@ -1688,6 +1718,31 @@ static int dp_display_get_modes(struct dp_display *dp, void *panel, return ret; } static void dp_display_convert_to_dp_mode(struct dp_display *dp_display, void *panel, const struct drm_display_mode *drm_mode, struct dp_display_mode *dp_mode) { struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display || !drm_mode || !dp_mode || !panel) { pr_err("invalid input\n"); return; } dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; mutex_lock(&dp->session_lock); memset(dp_mode, 0, sizeof(*dp_mode)); dp_panel->convert_to_dp_mode(dp_panel, drm_mode, dp_mode); mutex_unlock(&dp->session_lock); } static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr) { Loading Loading @@ -2026,6 +2081,7 @@ static int dp_display_probe(struct platform_device *pdev) dp_display_mst_connector_update_edid; g_dp_display->get_mst_caps = dp_display_get_mst_caps; g_dp_display->set_stream_info = dp_display_set_stream_info; g_dp_display->convert_to_dp_mode = dp_display_convert_to_dp_mode; rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { Loading
drivers/gpu/drm/msm/dp/dp_display.h +5 −3 Original line number Diff line number Diff line Loading @@ -85,9 +85,11 @@ struct dp_display { struct edid *edid); int (*get_mst_caps)(struct dp_display *dp_display, struct dp_mst_caps *mst_caps); int (*set_stream_info)(struct dp_display *dp_display, void *panel, u32 ch_id, u32 ch_start_slot, u32 ch_tot_slots, u32 pbn); int (*set_stream_info)(struct dp_display *dp_display, void *panel, u32 strm_id, u32 start_slot, u32 num_slots, u32 pbn); void (*convert_to_dp_mode)(struct dp_display *dp_display, void *panel, const struct drm_display_mode *drm_mode, struct dp_display_mode *dp_mode); }; int dp_display_get_num_of_displays(void); Loading