Loading drivers/gpu/drm/msm/dp/dp_catalog.c +52 −0 Original line number Diff line number Diff line Loading @@ -1573,6 +1573,57 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl, dp_write(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, slot_reg_2); } static void dp_catalog_ctrl_channel_dealloc(struct dp_catalog_ctrl *ctrl, u32 ch, u32 ch_start_slot, u32 tot_slot_cnt) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; u32 i, slot_reg_1, slot_reg_2, slot; u32 reg_off = 0; if (!ctrl || ch >= DP_STREAM_MAX) { pr_err("invalid input. ch %d\n", ch); return; } if (ch_start_slot > DP_MAX_TIME_SLOTS || (ch_start_slot + tot_slot_cnt > DP_MAX_TIME_SLOTS)) { pr_err("invalid slots start %d, tot %d\n", ch_start_slot, tot_slot_cnt); return; } catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; pr_debug("dealloc ch %d, start_slot %d, tot_slot %d\n", ch, ch_start_slot, tot_slot_cnt); 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); ch_start_slot = ch_start_slot - 1; for (i = 0; i < tot_slot_cnt; i++) { if (ch_start_slot < 33) { slot_reg_1 &= ~BIT(ch_start_slot); } else { slot = ch_start_slot - 33; slot_reg_2 &= ~BIT(slot); } ch_start_slot++; } pr_debug("dealloc ch:%d slot_reg_1:%d, slot_reg_2:%d\n", ch, slot_reg_1, slot_reg_2); dp_write(catalog, io_data, DP_DP0_TIMESLOT_1_32 + reg_off, slot_reg_1); dp_write(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, slot_reg_2); } static void dp_catalog_ctrl_update_rg(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int, u32 y_frac_enum) { Loading Loading @@ -2111,6 +2162,7 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) .read_act_complete_sts = dp_catalog_ctrl_read_act_complete_sts, .channel_alloc = dp_catalog_ctrl_channel_alloc, .update_rg = dp_catalog_ctrl_update_rg, .channel_dealloc = dp_catalog_ctrl_channel_dealloc, }; struct dp_catalog_audio audio = { .init = dp_catalog_audio_init, Loading drivers/gpu/drm/msm/dp/dp_catalog.h +2 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,8 @@ struct dp_catalog_ctrl { u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt); void (*update_rg)(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int, u32 y_frac_enum); void (*channel_dealloc)(struct dp_catalog_ctrl *ctrl, u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt); }; #define HEADER_BYTE_2_BIT 0 Loading drivers/gpu/drm/msm/dp/dp_ctrl.c +117 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/types.h> #include <linux/completion.h> #include <linux/delay.h> #include <drm/drm_fixed.h> #include "dp_ctrl.h" Loading Loading @@ -843,6 +844,81 @@ static void dp_ctrl_send_video(struct dp_ctrl_private *ctrl) ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO); } static void dp_ctrl_mst_calculate_rg(struct dp_ctrl_private *ctrl, struct dp_panel *panel, u32 *p_x_int, u32 *p_y_frac_enum) { u64 min_slot_cnt, max_slot_cnt; u64 raw_target_sc, target_sc_fixp; u64 ts_denom, ts_enum, ts_int; u64 pclk = panel->pinfo.pixel_clk_khz; u64 lclk = panel->link_info.rate; u64 lanes = panel->link_info.num_lanes; u64 bpp = panel->pinfo.bpp; u64 pbn = panel->pbn; u64 numerator, denominator, temp, temp1, temp2; u32 x_int = 0, y_frac_enum = 0; u64 target_strm_sym, ts_int_fixp, ts_frac_fixp, y_frac_enum_fixp; /* min_slot_cnt */ numerator = pclk * bpp * 64 * 1000; denominator = lclk * lanes * 8 * 1000; min_slot_cnt = drm_fixp_from_fraction(numerator, denominator); /* max_slot_cnt */ numerator = pbn * 54 * 1000; denominator = lclk * lanes; max_slot_cnt = drm_fixp_from_fraction(numerator, denominator); /* raw_target_sc */ numerator = max_slot_cnt + min_slot_cnt; denominator = drm_fixp_from_fraction(2, 1); raw_target_sc = drm_fixp_div(numerator, denominator); /* target_sc */ temp = drm_fixp_from_fraction(256 * lanes, 1); numerator = drm_fixp_mul(raw_target_sc, temp); denominator = drm_fixp_from_fraction(256 * lanes, 1); target_sc_fixp = drm_fixp_div(numerator, denominator); ts_enum = 256 * lanes; ts_denom = drm_fixp_from_fraction(256 * lanes, 1); ts_int = drm_fixp2int(target_sc_fixp); temp = drm_fixp2int_ceil(raw_target_sc); if (temp != ts_int) { temp = drm_fixp_from_fraction(ts_int, 1); temp1 = raw_target_sc - temp; temp2 = drm_fixp_mul(temp1, ts_denom); ts_enum = drm_fixp2int(temp2); } /* target_strm_sym */ ts_int_fixp = drm_fixp_from_fraction(ts_int, 1); ts_frac_fixp = drm_fixp_from_fraction(ts_enum, drm_fixp2int(ts_denom)); temp = ts_int_fixp + ts_frac_fixp; temp1 = drm_fixp_from_fraction(lanes, 1); target_strm_sym = drm_fixp_mul(temp, temp1); /* x_int */ x_int = drm_fixp2int(target_strm_sym); /* y_enum_frac */ temp = drm_fixp_from_fraction(x_int, 1); temp1 = target_strm_sym - temp; temp2 = drm_fixp_from_fraction(256, 1); y_frac_enum_fixp = drm_fixp_mul(temp1, temp2); temp1 = drm_fixp2int(y_frac_enum_fixp); temp2 = drm_fixp2int_ceil(y_frac_enum_fixp); y_frac_enum = (u32)((temp1 == temp2) ? temp1 : temp1 + 1); *p_x_int = x_int; *p_y_frac_enum = y_frac_enum; pr_debug("x_int: %d, y_frac_enum: %d\n", x_int, y_frac_enum); } static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, struct dp_panel *panel) { Loading @@ -862,9 +938,7 @@ static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, lanes = ctrl->link->link_params.lane_count; bw_code = ctrl->link->link_params.bw_code; x_int = (u32)(lanes * panel->channel_total_slots); y_frac_enum = (u32)(256 * ((lanes * lanes * panel->channel_total_slots) - x_int)); dp_ctrl_mst_calculate_rg(ctrl, panel, &x_int, &y_frac_enum); ctrl->catalog->update_rg(ctrl->catalog, panel->stream_id, x_int, y_frac_enum); Loading Loading @@ -932,6 +1006,45 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) return rc; } static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) { struct dp_ctrl_private *ctrl; bool act_complete; 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); ctrl->catalog->trigger_act(ctrl->catalog); msleep(20); /* needs 1 frame time */ ctrl->catalog->read_act_complete_sts(ctrl->catalog, &act_complete); if (!act_complete) pr_err("mst stream_off act trigger complete failed\n"); else DP_MST_DEBUG("mst stream_off ACT trigger complete SUCCESS\n"); } static void dp_ctrl_stream_pre_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) { if (!dp_ctrl || !panel) { pr_err("invalid input\n"); return; } dp_ctrl_push_idle(dp_ctrl, panel->stream_id); dp_ctrl_mst_stream_pre_off(dp_ctrl, panel); } static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) { struct dp_ctrl_private *ctrl; Loading Loading @@ -1107,6 +1220,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in) dp_ctrl->process_phy_test_request = dp_ctrl_process_phy_test_request; 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; return dp_ctrl; error: Loading drivers/gpu/drm/msm/dp/dp_ctrl.h +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ struct dp_ctrl { int (*link_maintenance)(struct dp_ctrl *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); }; struct dp_ctrl_in { Loading drivers/gpu/drm/msm/dp/dp_display.c +80 −22 Original line number Diff line number Diff line Loading @@ -798,12 +798,17 @@ static void dp_display_handle_maintenance_req(struct dp_display_private *dp) int idx; struct dp_panel *dp_panel; mutex_lock(&dp->session_lock); for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) { if (!dp->active_panels[idx]) continue; dp_panel = dp->active_panels[idx]; dp->ctrl->stream_pre_off(dp->ctrl, dp_panel); dp->ctrl->stream_off(dp->ctrl, dp_panel); mutex_lock(&dp_panel->audio->ops_lock); if (dp_panel->audio_supported) Loading @@ -818,11 +823,15 @@ static void dp_display_handle_maintenance_req(struct dp_display_private *dp) dp_panel = dp->active_panels[idx]; dp->ctrl->stream_on(dp->ctrl, dp_panel); if (dp_panel->audio_supported) dp_panel->audio->on(dp_panel->audio); mutex_unlock(&dp_panel->audio->ops_lock); } mutex_unlock(&dp->session_lock); } static void dp_display_mst_attention(struct dp_display_private *dp) Loading Loading @@ -1048,6 +1057,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) panel_in.catalog = &dp->catalog->panel; panel_in.link = dp->link; panel_in.connector = dp->dp_display.base_connector; panel_in.base_panel = NULL; dp->panel = dp_panel_get(&panel_in); if (IS_ERR(dp->panel)) { Loading Loading @@ -1198,14 +1208,45 @@ static int dp_display_set_mode(struct dp_display *dp_display, void *panel, return 0; } static int dp_display_prepare(struct dp_display *dp, void *panel) static int dp_display_prepare(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp_panel = panel; if (!dp_panel->connector) { pr_err("invalid connector input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); if (atomic_read(&dp->aborted)) goto end; dp->aux->init(dp->aux, dp->parser->aux_cfg); if (dp->debug->psm_enabled) { dp->link->psm_config(dp->link, &dp->panel->link_info, false); dp->debug->psm_enabled = false; } end: mutex_unlock(&dp->session_lock); return 0; } 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 ch_tot_slots, u32 pbn) { int rc = 0; struct dp_panel *dp_panel; Loading @@ -1217,7 +1258,7 @@ static int dp_display_set_stream_info(struct dp_display *dp_display, dp_panel = panel; dp_panel->set_stream_info(dp_panel, ch_id, ch_start_slot, ch_tot_slots); ch_start_slot, ch_tot_slots, pbn); return rc; } Loading Loading @@ -1266,13 +1307,6 @@ static int dp_display_enable(struct dp_display *dp_display, void *panel) goto end; } dp->aux->init(dp->aux, dp->parser->aux_cfg); if (dp->debug->psm_enabled) { dp->link->psm_config(dp->link, &dp->panel->link_info, false); dp->debug->psm_enabled = false; } rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active); if (rc) goto end; Loading Loading @@ -1355,9 +1389,8 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) static int dp_display_stream_pre_disable(struct dp_display_private *dp, struct dp_panel *dp_panel) { dp->ctrl->push_idle(dp->ctrl, dp_panel->stream_id); dp_panel->audio->deregister_ext_disp(dp_panel->audio); dp->ctrl->stream_pre_off(dp->ctrl, dp_panel); return 0; } Loading Loading @@ -1390,17 +1423,17 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) dp->hdcp.ops->off(dp->hdcp.data); } if (dp->usbpd->hpd_high && !dp_display_is_sink_count_zero(dp) && dp->usbpd->alt_mode_cfg_done) { if (dp_panel->audio_supported) dp_panel->audio->off(dp_panel->audio); rc = dp_display_stream_pre_disable(dp, dp_panel); if (dp->usbpd->hpd_high && !dp_display_is_sink_count_zero(dp) && dp->usbpd->alt_mode_cfg_done && !dp->mst.mst_active) { dp->link->psm_config(dp->link, &dp->panel->link_info, true); dp->debug->psm_enabled = true; } rc = dp_display_stream_pre_disable(dp, dp_panel); end: mutex_unlock(&dp->session_lock); return 0; Loading Loading @@ -1455,10 +1488,7 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel) dp->dp_display.is_sst_connected = false; } dp->aux->deinit(dp->aux); dp->power_on = false; dp->aux->state = DP_STATE_CTRL_POWERED_OFF; complete_all(&dp->notification_comp); end: mutex_unlock(&dp->session_lock); return 0; Loading Loading @@ -1509,8 +1539,35 @@ static struct dp_debug *dp_get_debug(struct dp_display *dp_display) return dp->debug; } static int dp_display_unprepare(struct dp_display *dp, void *panel) static int dp_display_unprepare(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); if (dp->active_stream_cnt) goto end; if (atomic_read(&dp->aborted)) goto end; if (!dp->mst.mst_active) { dp->aux->deinit(dp->aux); dp->aux->state = DP_STATE_CTRL_POWERED_OFF; } complete_all(&dp->notification_comp); end: mutex_unlock(&dp->session_lock); return 0; } Loading Loading @@ -1739,6 +1796,7 @@ static int dp_display_mst_connector_install(struct dp_display *dp_display, panel_in.catalog = &dp->catalog->panel; panel_in.link = dp->link; panel_in.connector = connector; panel_in.base_panel = dp->panel; dp_panel = dp_panel_get(&panel_in); if (IS_ERR(dp_panel)) { Loading Loading
drivers/gpu/drm/msm/dp/dp_catalog.c +52 −0 Original line number Diff line number Diff line Loading @@ -1573,6 +1573,57 @@ static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl, dp_write(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, slot_reg_2); } static void dp_catalog_ctrl_channel_dealloc(struct dp_catalog_ctrl *ctrl, u32 ch, u32 ch_start_slot, u32 tot_slot_cnt) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; u32 i, slot_reg_1, slot_reg_2, slot; u32 reg_off = 0; if (!ctrl || ch >= DP_STREAM_MAX) { pr_err("invalid input. ch %d\n", ch); return; } if (ch_start_slot > DP_MAX_TIME_SLOTS || (ch_start_slot + tot_slot_cnt > DP_MAX_TIME_SLOTS)) { pr_err("invalid slots start %d, tot %d\n", ch_start_slot, tot_slot_cnt); return; } catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; pr_debug("dealloc ch %d, start_slot %d, tot_slot %d\n", ch, ch_start_slot, tot_slot_cnt); 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); ch_start_slot = ch_start_slot - 1; for (i = 0; i < tot_slot_cnt; i++) { if (ch_start_slot < 33) { slot_reg_1 &= ~BIT(ch_start_slot); } else { slot = ch_start_slot - 33; slot_reg_2 &= ~BIT(slot); } ch_start_slot++; } pr_debug("dealloc ch:%d slot_reg_1:%d, slot_reg_2:%d\n", ch, slot_reg_1, slot_reg_2); dp_write(catalog, io_data, DP_DP0_TIMESLOT_1_32 + reg_off, slot_reg_1); dp_write(catalog, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, slot_reg_2); } static void dp_catalog_ctrl_update_rg(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int, u32 y_frac_enum) { Loading Loading @@ -2111,6 +2162,7 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) .read_act_complete_sts = dp_catalog_ctrl_read_act_complete_sts, .channel_alloc = dp_catalog_ctrl_channel_alloc, .update_rg = dp_catalog_ctrl_update_rg, .channel_dealloc = dp_catalog_ctrl_channel_dealloc, }; struct dp_catalog_audio audio = { .init = dp_catalog_audio_init, Loading
drivers/gpu/drm/msm/dp/dp_catalog.h +2 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,8 @@ struct dp_catalog_ctrl { u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt); void (*update_rg)(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int, u32 y_frac_enum); void (*channel_dealloc)(struct dp_catalog_ctrl *ctrl, u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt); }; #define HEADER_BYTE_2_BIT 0 Loading
drivers/gpu/drm/msm/dp/dp_ctrl.c +117 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <linux/types.h> #include <linux/completion.h> #include <linux/delay.h> #include <drm/drm_fixed.h> #include "dp_ctrl.h" Loading Loading @@ -843,6 +844,81 @@ static void dp_ctrl_send_video(struct dp_ctrl_private *ctrl) ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO); } static void dp_ctrl_mst_calculate_rg(struct dp_ctrl_private *ctrl, struct dp_panel *panel, u32 *p_x_int, u32 *p_y_frac_enum) { u64 min_slot_cnt, max_slot_cnt; u64 raw_target_sc, target_sc_fixp; u64 ts_denom, ts_enum, ts_int; u64 pclk = panel->pinfo.pixel_clk_khz; u64 lclk = panel->link_info.rate; u64 lanes = panel->link_info.num_lanes; u64 bpp = panel->pinfo.bpp; u64 pbn = panel->pbn; u64 numerator, denominator, temp, temp1, temp2; u32 x_int = 0, y_frac_enum = 0; u64 target_strm_sym, ts_int_fixp, ts_frac_fixp, y_frac_enum_fixp; /* min_slot_cnt */ numerator = pclk * bpp * 64 * 1000; denominator = lclk * lanes * 8 * 1000; min_slot_cnt = drm_fixp_from_fraction(numerator, denominator); /* max_slot_cnt */ numerator = pbn * 54 * 1000; denominator = lclk * lanes; max_slot_cnt = drm_fixp_from_fraction(numerator, denominator); /* raw_target_sc */ numerator = max_slot_cnt + min_slot_cnt; denominator = drm_fixp_from_fraction(2, 1); raw_target_sc = drm_fixp_div(numerator, denominator); /* target_sc */ temp = drm_fixp_from_fraction(256 * lanes, 1); numerator = drm_fixp_mul(raw_target_sc, temp); denominator = drm_fixp_from_fraction(256 * lanes, 1); target_sc_fixp = drm_fixp_div(numerator, denominator); ts_enum = 256 * lanes; ts_denom = drm_fixp_from_fraction(256 * lanes, 1); ts_int = drm_fixp2int(target_sc_fixp); temp = drm_fixp2int_ceil(raw_target_sc); if (temp != ts_int) { temp = drm_fixp_from_fraction(ts_int, 1); temp1 = raw_target_sc - temp; temp2 = drm_fixp_mul(temp1, ts_denom); ts_enum = drm_fixp2int(temp2); } /* target_strm_sym */ ts_int_fixp = drm_fixp_from_fraction(ts_int, 1); ts_frac_fixp = drm_fixp_from_fraction(ts_enum, drm_fixp2int(ts_denom)); temp = ts_int_fixp + ts_frac_fixp; temp1 = drm_fixp_from_fraction(lanes, 1); target_strm_sym = drm_fixp_mul(temp, temp1); /* x_int */ x_int = drm_fixp2int(target_strm_sym); /* y_enum_frac */ temp = drm_fixp_from_fraction(x_int, 1); temp1 = target_strm_sym - temp; temp2 = drm_fixp_from_fraction(256, 1); y_frac_enum_fixp = drm_fixp_mul(temp1, temp2); temp1 = drm_fixp2int(y_frac_enum_fixp); temp2 = drm_fixp2int_ceil(y_frac_enum_fixp); y_frac_enum = (u32)((temp1 == temp2) ? temp1 : temp1 + 1); *p_x_int = x_int; *p_y_frac_enum = y_frac_enum; pr_debug("x_int: %d, y_frac_enum: %d\n", x_int, y_frac_enum); } static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, struct dp_panel *panel) { Loading @@ -862,9 +938,7 @@ static int dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, lanes = ctrl->link->link_params.lane_count; bw_code = ctrl->link->link_params.bw_code; x_int = (u32)(lanes * panel->channel_total_slots); y_frac_enum = (u32)(256 * ((lanes * lanes * panel->channel_total_slots) - x_int)); dp_ctrl_mst_calculate_rg(ctrl, panel, &x_int, &y_frac_enum); ctrl->catalog->update_rg(ctrl->catalog, panel->stream_id, x_int, y_frac_enum); Loading Loading @@ -932,6 +1006,45 @@ static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) return rc; } static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) { struct dp_ctrl_private *ctrl; bool act_complete; 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); ctrl->catalog->trigger_act(ctrl->catalog); msleep(20); /* needs 1 frame time */ ctrl->catalog->read_act_complete_sts(ctrl->catalog, &act_complete); if (!act_complete) pr_err("mst stream_off act trigger complete failed\n"); else DP_MST_DEBUG("mst stream_off ACT trigger complete SUCCESS\n"); } static void dp_ctrl_stream_pre_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) { if (!dp_ctrl || !panel) { pr_err("invalid input\n"); return; } dp_ctrl_push_idle(dp_ctrl, panel->stream_id); dp_ctrl_mst_stream_pre_off(dp_ctrl, panel); } static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) { struct dp_ctrl_private *ctrl; Loading Loading @@ -1107,6 +1220,7 @@ struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in) dp_ctrl->process_phy_test_request = dp_ctrl_process_phy_test_request; 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; return dp_ctrl; error: Loading
drivers/gpu/drm/msm/dp/dp_ctrl.h +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ struct dp_ctrl { int (*link_maintenance)(struct dp_ctrl *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); }; struct dp_ctrl_in { Loading
drivers/gpu/drm/msm/dp/dp_display.c +80 −22 Original line number Diff line number Diff line Loading @@ -798,12 +798,17 @@ static void dp_display_handle_maintenance_req(struct dp_display_private *dp) int idx; struct dp_panel *dp_panel; mutex_lock(&dp->session_lock); for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) { if (!dp->active_panels[idx]) continue; dp_panel = dp->active_panels[idx]; dp->ctrl->stream_pre_off(dp->ctrl, dp_panel); dp->ctrl->stream_off(dp->ctrl, dp_panel); mutex_lock(&dp_panel->audio->ops_lock); if (dp_panel->audio_supported) Loading @@ -818,11 +823,15 @@ static void dp_display_handle_maintenance_req(struct dp_display_private *dp) dp_panel = dp->active_panels[idx]; dp->ctrl->stream_on(dp->ctrl, dp_panel); if (dp_panel->audio_supported) dp_panel->audio->on(dp_panel->audio); mutex_unlock(&dp_panel->audio->ops_lock); } mutex_unlock(&dp->session_lock); } static void dp_display_mst_attention(struct dp_display_private *dp) Loading Loading @@ -1048,6 +1057,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) panel_in.catalog = &dp->catalog->panel; panel_in.link = dp->link; panel_in.connector = dp->dp_display.base_connector; panel_in.base_panel = NULL; dp->panel = dp_panel_get(&panel_in); if (IS_ERR(dp->panel)) { Loading Loading @@ -1198,14 +1208,45 @@ static int dp_display_set_mode(struct dp_display *dp_display, void *panel, return 0; } static int dp_display_prepare(struct dp_display *dp, void *panel) static int dp_display_prepare(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp_panel = panel; if (!dp_panel->connector) { pr_err("invalid connector input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); if (atomic_read(&dp->aborted)) goto end; dp->aux->init(dp->aux, dp->parser->aux_cfg); if (dp->debug->psm_enabled) { dp->link->psm_config(dp->link, &dp->panel->link_info, false); dp->debug->psm_enabled = false; } end: mutex_unlock(&dp->session_lock); return 0; } 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 ch_tot_slots, u32 pbn) { int rc = 0; struct dp_panel *dp_panel; Loading @@ -1217,7 +1258,7 @@ static int dp_display_set_stream_info(struct dp_display *dp_display, dp_panel = panel; dp_panel->set_stream_info(dp_panel, ch_id, ch_start_slot, ch_tot_slots); ch_start_slot, ch_tot_slots, pbn); return rc; } Loading Loading @@ -1266,13 +1307,6 @@ static int dp_display_enable(struct dp_display *dp_display, void *panel) goto end; } dp->aux->init(dp->aux, dp->parser->aux_cfg); if (dp->debug->psm_enabled) { dp->link->psm_config(dp->link, &dp->panel->link_info, false); dp->debug->psm_enabled = false; } rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active); if (rc) goto end; Loading Loading @@ -1355,9 +1389,8 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) static int dp_display_stream_pre_disable(struct dp_display_private *dp, struct dp_panel *dp_panel) { dp->ctrl->push_idle(dp->ctrl, dp_panel->stream_id); dp_panel->audio->deregister_ext_disp(dp_panel->audio); dp->ctrl->stream_pre_off(dp->ctrl, dp_panel); return 0; } Loading Loading @@ -1390,17 +1423,17 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) dp->hdcp.ops->off(dp->hdcp.data); } if (dp->usbpd->hpd_high && !dp_display_is_sink_count_zero(dp) && dp->usbpd->alt_mode_cfg_done) { if (dp_panel->audio_supported) dp_panel->audio->off(dp_panel->audio); rc = dp_display_stream_pre_disable(dp, dp_panel); if (dp->usbpd->hpd_high && !dp_display_is_sink_count_zero(dp) && dp->usbpd->alt_mode_cfg_done && !dp->mst.mst_active) { dp->link->psm_config(dp->link, &dp->panel->link_info, true); dp->debug->psm_enabled = true; } rc = dp_display_stream_pre_disable(dp, dp_panel); end: mutex_unlock(&dp->session_lock); return 0; Loading Loading @@ -1455,10 +1488,7 @@ static int dp_display_disable(struct dp_display *dp_display, void *panel) dp->dp_display.is_sst_connected = false; } dp->aux->deinit(dp->aux); dp->power_on = false; dp->aux->state = DP_STATE_CTRL_POWERED_OFF; complete_all(&dp->notification_comp); end: mutex_unlock(&dp->session_lock); return 0; Loading Loading @@ -1509,8 +1539,35 @@ static struct dp_debug *dp_get_debug(struct dp_display *dp_display) return dp->debug; } static int dp_display_unprepare(struct dp_display *dp, void *panel) static int dp_display_unprepare(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); mutex_lock(&dp->session_lock); if (dp->active_stream_cnt) goto end; if (atomic_read(&dp->aborted)) goto end; if (!dp->mst.mst_active) { dp->aux->deinit(dp->aux); dp->aux->state = DP_STATE_CTRL_POWERED_OFF; } complete_all(&dp->notification_comp); end: mutex_unlock(&dp->session_lock); return 0; } Loading Loading @@ -1739,6 +1796,7 @@ static int dp_display_mst_connector_install(struct dp_display *dp_display, panel_in.catalog = &dp->catalog->panel; panel_in.link = dp->link; panel_in.connector = connector; panel_in.base_panel = dp->panel; dp_panel = dp_panel_get(&panel_in); if (IS_ERR(dp_panel)) { Loading