Loading drivers/gpu/drm/msm/dp/dp_catalog.c +154 −0 Original line number Diff line number Diff line Loading @@ -1414,6 +1414,155 @@ static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog, return ret; } static void dp_catalog_ctrl_mst_config(struct dp_catalog_ctrl *ctrl, bool enable) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; u32 reg; if (!ctrl) { pr_err("invalid input\n"); return; } catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; reg = dp_read(catalog, io_data, DP_MAINLINK_CTRL); if (enable) reg |= (0x04000100); else reg &= ~(0x04000100); dp_write(catalog, io_data, DP_MAINLINK_CTRL, reg); /* make sure mainlink MST configuration is updated */ wmb(); } static void dp_catalog_ctrl_trigger_act(struct dp_catalog_ctrl *ctrl) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; if (!ctrl) { pr_err("invalid input\n"); return; } catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; dp_write(catalog, io_data, DP_MST_ACT, 0x1); /* make sure ACT signal is performed */ wmb(); } static void dp_catalog_ctrl_read_act_complete_sts(struct dp_catalog_ctrl *ctrl, bool *sts) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; u32 reg; if (!ctrl || !sts) { pr_err("invalid input\n"); return; } *sts = false; catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; reg = dp_read(catalog, io_data, DP_MST_ACT); if (!reg) *sts = true; } static void dp_catalog_ctrl_channel_alloc(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("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("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) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; u32 rg, reg_off = 0; if (!ctrl || ch >= DP_STREAM_MAX) { pr_err("invalid input. ch %d\n", ch); return; } catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; rg = y_frac_enum; rg |= (x_int << 16); pr_debug("ch: %d x_int:%d y_frac_enum:%d rg:%d\n", ch, x_int, y_frac_enum, rg); if (ch == DP_STREAM_1) reg_off = DP_DP1_RG - DP_DP0_RG; dp_write(catalog, io_data, DP_DP0_RG + reg_off, rg); } /* panel related catalog functions */ static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel) { Loading Loading @@ -1902,6 +2051,11 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) .read_hdcp_status = dp_catalog_ctrl_read_hdcp_status, .send_phy_pattern = dp_catalog_ctrl_send_phy_pattern, .read_phy_pattern = dp_catalog_ctrl_read_phy_pattern, .mst_config = dp_catalog_ctrl_mst_config, .trigger_act = dp_catalog_ctrl_trigger_act, .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, }; struct dp_catalog_audio audio = { .init = dp_catalog_audio_init, Loading drivers/gpu/drm/msm/dp/dp_catalog.h +9 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ #define DP_INTR_FRAME_END BIT(6) #define DP_INTR_CRC_UPDATED BIT(9) #define DP_MAX_TIME_SLOTS 64 /* stream id */ enum dp_stream_id { DP_STREAM_0, Loading Loading @@ -112,6 +114,13 @@ struct dp_catalog_ctrl { void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern); u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl); void (*mst_config)(struct dp_catalog_ctrl *ctrl, bool enable); void (*trigger_act)(struct dp_catalog_ctrl *ctrl); void (*read_act_complete_sts)(struct dp_catalog_ctrl *ctrl, bool *sts); void (*channel_alloc)(struct dp_catalog_ctrl *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); }; #define HEADER_BYTE_2_BIT 0 Loading drivers/gpu/drm/msm/dp/dp_catalog_v420.c +19 −5 Original line number Diff line number Diff line Loading @@ -132,7 +132,7 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, bool fixed_nvid) { u32 pixel_m, pixel_n; u32 mvid, nvid; u32 mvid, nvid, reg_off = 0; u64 mvid_calc; u32 const nvid_fixed = 0x8000; u32 const link_rate_hbr2 = 540000; Loading @@ -145,6 +145,11 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, return; } if (panel->stream_id >= DP_STREAM_MAX) { pr_err("invalid stream id:%d\n", panel->stream_id); return; } catalog = dp_catalog_get_priv_v420(panel); if (fixed_nvid) { pr_debug("use fixed NVID=0x%x\n", nvid_fixed); Loading @@ -168,8 +173,13 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, } else { io_data = catalog->io->dp_mmss_cc; pixel_m = dp_read(catalog, io_data, MMSS_DP_PIXEL_M_V420); pixel_n = dp_read(catalog, io_data, MMSS_DP_PIXEL_N_V420); if (panel->stream_id == DP_STREAM_1) reg_off = MMSS_DP_PIXEL1_M_V420 - MMSS_DP_PIXEL_M_V420; pixel_m = dp_read(catalog, io_data, MMSS_DP_PIXEL_M_V420 + reg_off); pixel_n = dp_read(catalog, io_data, MMSS_DP_PIXEL_N_V420 + reg_off); pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n); mvid = (pixel_m & 0xFFFF) * 5; Loading @@ -185,9 +195,13 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, } io_data = catalog->io->dp_link; if (panel->stream_id == DP_STREAM_1) reg_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID; pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); dp_write(catalog, io_data, DP_SOFTWARE_MVID, mvid); dp_write(catalog, io_data, DP_SOFTWARE_NVID, nvid); dp_write(catalog, io_data, DP_SOFTWARE_MVID + reg_off, mvid); dp_write(catalog, io_data, DP_SOFTWARE_NVID + reg_off, nvid); } static void dp_catalog_ctrl_phy_lane_cfg_v420(struct dp_catalog_ctrl *ctrl, Loading drivers/gpu/drm/msm/dp/dp_display.c +74 −40 Original line number Diff line number Diff line Loading @@ -408,7 +408,7 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp) bpp[HPD_STRING_SIZE], pattern[HPD_STRING_SIZE]; char *envp[5]; connector = dp->dp_display.connector; connector = dp->dp_display.base_connector; if (!connector) { pr_err("connector not set\n"); Loading @@ -417,7 +417,7 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp) connector->status = connector->funcs->detect(connector, false); dev = dp->dp_display.connector->dev; dev = connector->dev; snprintf(name, HPD_STRING_SIZE, "name=%s", connector->name); snprintf(status, HPD_STRING_SIZE, "status=%s", Loading Loading @@ -454,10 +454,10 @@ static void dp_display_post_open(struct dp_display *dp_display) return; } connector = dp->dp_display.connector; connector = dp->dp_display.base_connector; if (!connector) { pr_err("connector not set\n"); pr_err("base connector not set\n"); return; } Loading Loading @@ -509,10 +509,11 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->debug->psm_enabled = false; } if (!dp->dp_display.connector) if (!dp->dp_display.base_connector) return 0; rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector); rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.base_connector); if (rc) { /* * ETIMEDOUT --> cable may have been removed Loading Loading @@ -925,6 +926,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) panel_in.aux = dp->aux; panel_in.catalog = &dp->catalog->panel; panel_in.link = dp->link; panel_in.connector = dp->dp_display.base_connector; dp->panel = dp_panel_get(&panel_in); if (IS_ERR(dp->panel)) { Loading Loading @@ -970,8 +972,10 @@ static int dp_init_sub_modules(struct dp_display_private *dp) } dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd, dp->link, dp->aux, &dp->dp_display.connector, dp->link, dp->aux, &dp->dp_display.base_connector, dp->catalog); if (IS_ERR(dp->debug)) { rc = PTR_ERR(dp->debug); pr_err("failed to initialize debug, rc = %d\n", rc); Loading Loading @@ -1032,50 +1036,60 @@ static void dp_display_post_init(struct dp_display *dp_display) pr_debug("%s\n", rc ? "failed" : "success"); } static int dp_display_set_mode(struct dp_display *dp_display, static int dp_display_set_mode(struct dp_display *dp_display, void *panel, struct dp_display_mode *mode) { const u32 num_components = 3, default_bpp = 24; struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display) { 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); mode->timing.bpp = dp_display->connector->display_info.bpc * num_components; dp_panel->connector->display_info.bpc * num_components; if (!mode->timing.bpp) mode->timing.bpp = default_bpp; mode->timing.bpp = dp->panel->get_mode_bpp(dp->panel, mode->timing.bpp, mode->timing.pixel_clk_khz); dp->panel->pinfo = mode->timing; dp->panel->init(dp->panel); dp_panel->pinfo = mode->timing; dp_panel->init(dp_panel); mutex_unlock(&dp->session_lock); return 0; } static int dp_display_prepare(struct dp_display *dp) static int dp_display_prepare(struct dp_display *dp, void *panel) { return 0; } static int dp_display_enable(struct dp_display *dp_display) static int dp_display_enable(struct dp_display *dp_display, void *panel) { int rc = 0; struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; mutex_lock(&dp->session_lock); Loading @@ -1091,30 +1105,32 @@ static int dp_display_enable(struct dp_display *dp_display) dp->aux->init(dp->aux, dp->parser->aux_cfg); dp->panel->set_stream_id(dp->panel, DP_STREAM_0); dp_panel->set_stream_id(dp->panel, DP_STREAM_0); rc = dp->ctrl->on(dp->ctrl); if (!rc) dp->power_on = true; if (dp->debug->tpg_state) dp->panel->tpg_config(dp->panel, true); dp_panel->tpg_config(dp_panel, true); end: mutex_unlock(&dp->session_lock); return rc; } static int dp_display_post_enable(struct dp_display *dp_display) static int dp_display_post_enable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; mutex_lock(&dp->session_lock); Loading @@ -1128,7 +1144,7 @@ static int dp_display_post_enable(struct dp_display *dp_display) goto end; } dp->panel->spd_config(dp->panel); dp_panel->spd_config(dp_panel); if (dp->audio_supported) { dp->audio->bw_code = dp->link->link_params.bw_code; Loading @@ -1145,7 +1161,7 @@ static int dp_display_post_enable(struct dp_display *dp_display) queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2); } dp->panel->setup_hdr(dp->panel, NULL); dp_panel->setup_hdr(dp_panel, NULL); end: /* clear framework event notifier */ dp_display->post_open = NULL; Loading @@ -1156,11 +1172,11 @@ static int dp_display_post_enable(struct dp_display *dp_display) return 0; } static int dp_display_pre_disable(struct dp_display *dp_display) static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } Loading Loading @@ -1196,19 +1212,21 @@ static int dp_display_pre_disable(struct dp_display *dp_display) return 0; } static int dp_display_disable(struct dp_display *dp_display) static int dp_display_disable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct drm_connector *connector; struct sde_connector_state *c_state; struct dp_panel *dp_panel; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); connector = dp->dp_display.connector; dp_panel = panel; connector = dp_panel->connector; c_state = to_sde_connector_state(connector->state); mutex_lock(&dp->session_lock); Loading @@ -1219,7 +1237,8 @@ static int dp_display_disable(struct dp_display *dp_display) } dp->ctrl->off(dp->ctrl); dp->panel->deinit(dp->panel); dp_panel->set_stream_id(dp_panel, DP_STREAM_MAX); dp_panel->deinit(dp_panel); dp->aux->deinit(dp->aux); connector->hdr_eotf = 0; Loading Loading @@ -1292,32 +1311,39 @@ static struct dp_debug *dp_get_debug(struct dp_display *dp_display) return dp->debug; } static int dp_display_unprepare(struct dp_display *dp) static int dp_display_unprepare(struct dp_display *dp, void *panel) { return 0; } static int dp_display_validate_mode(struct dp_display *dp, u32 mode_pclk_khz) static int dp_display_validate_mode(struct dp_display *dp, void *panel, u32 mode_pclk_khz) { const u32 num_components = 3, default_bpp = 24; struct dp_display_private *dp_display; struct drm_dp_link *link_info; u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; struct dp_panel *dp_panel; if (!dp || !mode_pclk_khz || !dp->connector) { if (!dp || !mode_pclk_khz || !panel) { pr_err("invalid params\n"); return -EINVAL; } dp_panel = panel; if (!dp_panel->connector) { pr_err("invalid connector\n"); return -EINVAL; } dp_display = container_of(dp, struct dp_display_private, dp_display); link_info = &dp_display->panel->link_info; mode_bpp = dp->connector->display_info.bpc * num_components; mode_bpp = dp_panel->connector->display_info.bpc * num_components; if (!mode_bpp) mode_bpp = default_bpp; mode_bpp = dp_display->panel->get_mode_bpp(dp_display->panel, mode_bpp, mode_pclk_khz); mode_bpp = dp_panel->get_mode_bpp(dp_panel, mode_bpp, mode_pclk_khz); mode_rate_khz = mode_pclk_khz * mode_bpp; supported_rate_khz = link_info->num_lanes * link_info->rate * 8; Loading @@ -1328,40 +1354,48 @@ static int dp_display_validate_mode(struct dp_display *dp, u32 mode_pclk_khz) return MODE_OK; } static int dp_display_get_modes(struct dp_display *dp, static int dp_display_get_modes(struct dp_display *dp, void *panel, struct dp_display_mode *dp_mode) { struct dp_display_private *dp_display; struct dp_panel *dp_panel; int ret = 0; if (!dp || !dp->connector) { if (!dp || !panel) { pr_err("invalid params\n"); return 0; } dp_panel = panel; if (!dp_panel->connector) { pr_err("invalid connector\n"); return 0; } dp_display = container_of(dp, struct dp_display_private, dp_display); ret = dp_display->panel->get_modes(dp_display->panel, dp->connector, dp_mode); ret = dp_panel->get_modes(dp_panel, dp_panel->connector, dp_mode); if (dp_mode->timing.pixel_clk_khz) dp->max_pclk_khz = dp_mode->timing.pixel_clk_khz; return ret; } static int dp_display_config_hdr(struct dp_display *dp_display, static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr) { int rc = 0; struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; rc = dp->panel->setup_hdr(dp->panel, hdr); rc = dp_panel->setup_hdr(dp_panel, hdr); return rc; } Loading drivers/gpu/drm/msm/dp/dp_display.h +13 −11 Original line number Diff line number Diff line Loading @@ -23,27 +23,29 @@ struct dp_display { struct drm_device *drm_dev; struct dp_bridge *bridge; struct drm_connector *connector; struct drm_connector *base_connector; void *base_dp_panel; bool is_connected; u32 max_pclk_khz; int (*enable)(struct dp_display *dp_display); int (*post_enable)(struct dp_display *dp_display); int (*enable)(struct dp_display *dp_display, void *panel); int (*post_enable)(struct dp_display *dp_display, void *panel); int (*pre_disable)(struct dp_display *dp_display); int (*disable)(struct dp_display *dp_display); int (*pre_disable)(struct dp_display *dp_display, void *panel); int (*disable)(struct dp_display *dp_display, void *panel); int (*set_mode)(struct dp_display *dp_display, int (*set_mode)(struct dp_display *dp_display, void *panel, struct dp_display_mode *mode); int (*validate_mode)(struct dp_display *dp_display, u32 mode_pclk_khz); int (*get_modes)(struct dp_display *dp_display, int (*validate_mode)(struct dp_display *dp_display, void *panel, u32 mode_pclk_khz); int (*get_modes)(struct dp_display *dp_display, void *panel, struct dp_display_mode *dp_mode); int (*prepare)(struct dp_display *dp_display); int (*unprepare)(struct dp_display *dp_display); int (*prepare)(struct dp_display *dp_display, void *panel); int (*unprepare)(struct dp_display *dp_display, void *panel); 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 (*config_hdr)(struct dp_display *dp_display, int (*config_hdr)(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr_meta); void (*post_init)(struct dp_display *dp_display); }; Loading Loading
drivers/gpu/drm/msm/dp/dp_catalog.c +154 −0 Original line number Diff line number Diff line Loading @@ -1414,6 +1414,155 @@ static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog, return ret; } static void dp_catalog_ctrl_mst_config(struct dp_catalog_ctrl *ctrl, bool enable) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; u32 reg; if (!ctrl) { pr_err("invalid input\n"); return; } catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; reg = dp_read(catalog, io_data, DP_MAINLINK_CTRL); if (enable) reg |= (0x04000100); else reg &= ~(0x04000100); dp_write(catalog, io_data, DP_MAINLINK_CTRL, reg); /* make sure mainlink MST configuration is updated */ wmb(); } static void dp_catalog_ctrl_trigger_act(struct dp_catalog_ctrl *ctrl) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; if (!ctrl) { pr_err("invalid input\n"); return; } catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; dp_write(catalog, io_data, DP_MST_ACT, 0x1); /* make sure ACT signal is performed */ wmb(); } static void dp_catalog_ctrl_read_act_complete_sts(struct dp_catalog_ctrl *ctrl, bool *sts) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; u32 reg; if (!ctrl || !sts) { pr_err("invalid input\n"); return; } *sts = false; catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; reg = dp_read(catalog, io_data, DP_MST_ACT); if (!reg) *sts = true; } static void dp_catalog_ctrl_channel_alloc(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("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("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) { struct dp_catalog_private *catalog; struct dp_io_data *io_data = NULL; u32 rg, reg_off = 0; if (!ctrl || ch >= DP_STREAM_MAX) { pr_err("invalid input. ch %d\n", ch); return; } catalog = dp_catalog_get_priv(ctrl); io_data = catalog->io.dp_link; rg = y_frac_enum; rg |= (x_int << 16); pr_debug("ch: %d x_int:%d y_frac_enum:%d rg:%d\n", ch, x_int, y_frac_enum, rg); if (ch == DP_STREAM_1) reg_off = DP_DP1_RG - DP_DP0_RG; dp_write(catalog, io_data, DP_DP0_RG + reg_off, rg); } /* panel related catalog functions */ static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel) { Loading Loading @@ -1902,6 +2051,11 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) .read_hdcp_status = dp_catalog_ctrl_read_hdcp_status, .send_phy_pattern = dp_catalog_ctrl_send_phy_pattern, .read_phy_pattern = dp_catalog_ctrl_read_phy_pattern, .mst_config = dp_catalog_ctrl_mst_config, .trigger_act = dp_catalog_ctrl_trigger_act, .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, }; struct dp_catalog_audio audio = { .init = dp_catalog_audio_init, Loading
drivers/gpu/drm/msm/dp/dp_catalog.h +9 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ #define DP_INTR_FRAME_END BIT(6) #define DP_INTR_CRC_UPDATED BIT(9) #define DP_MAX_TIME_SLOTS 64 /* stream id */ enum dp_stream_id { DP_STREAM_0, Loading Loading @@ -112,6 +114,13 @@ struct dp_catalog_ctrl { void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern); u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl); void (*mst_config)(struct dp_catalog_ctrl *ctrl, bool enable); void (*trigger_act)(struct dp_catalog_ctrl *ctrl); void (*read_act_complete_sts)(struct dp_catalog_ctrl *ctrl, bool *sts); void (*channel_alloc)(struct dp_catalog_ctrl *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); }; #define HEADER_BYTE_2_BIT 0 Loading
drivers/gpu/drm/msm/dp/dp_catalog_v420.c +19 −5 Original line number Diff line number Diff line Loading @@ -132,7 +132,7 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, bool fixed_nvid) { u32 pixel_m, pixel_n; u32 mvid, nvid; u32 mvid, nvid, reg_off = 0; u64 mvid_calc; u32 const nvid_fixed = 0x8000; u32 const link_rate_hbr2 = 540000; Loading @@ -145,6 +145,11 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, return; } if (panel->stream_id >= DP_STREAM_MAX) { pr_err("invalid stream id:%d\n", panel->stream_id); return; } catalog = dp_catalog_get_priv_v420(panel); if (fixed_nvid) { pr_debug("use fixed NVID=0x%x\n", nvid_fixed); Loading @@ -168,8 +173,13 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, } else { io_data = catalog->io->dp_mmss_cc; pixel_m = dp_read(catalog, io_data, MMSS_DP_PIXEL_M_V420); pixel_n = dp_read(catalog, io_data, MMSS_DP_PIXEL_N_V420); if (panel->stream_id == DP_STREAM_1) reg_off = MMSS_DP_PIXEL1_M_V420 - MMSS_DP_PIXEL_M_V420; pixel_m = dp_read(catalog, io_data, MMSS_DP_PIXEL_M_V420 + reg_off); pixel_n = dp_read(catalog, io_data, MMSS_DP_PIXEL_N_V420 + reg_off); pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n); mvid = (pixel_m & 0xFFFF) * 5; Loading @@ -185,9 +195,13 @@ static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, } io_data = catalog->io->dp_link; if (panel->stream_id == DP_STREAM_1) reg_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID; pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); dp_write(catalog, io_data, DP_SOFTWARE_MVID, mvid); dp_write(catalog, io_data, DP_SOFTWARE_NVID, nvid); dp_write(catalog, io_data, DP_SOFTWARE_MVID + reg_off, mvid); dp_write(catalog, io_data, DP_SOFTWARE_NVID + reg_off, nvid); } static void dp_catalog_ctrl_phy_lane_cfg_v420(struct dp_catalog_ctrl *ctrl, Loading
drivers/gpu/drm/msm/dp/dp_display.c +74 −40 Original line number Diff line number Diff line Loading @@ -408,7 +408,7 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp) bpp[HPD_STRING_SIZE], pattern[HPD_STRING_SIZE]; char *envp[5]; connector = dp->dp_display.connector; connector = dp->dp_display.base_connector; if (!connector) { pr_err("connector not set\n"); Loading @@ -417,7 +417,7 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp) connector->status = connector->funcs->detect(connector, false); dev = dp->dp_display.connector->dev; dev = connector->dev; snprintf(name, HPD_STRING_SIZE, "name=%s", connector->name); snprintf(status, HPD_STRING_SIZE, "status=%s", Loading Loading @@ -454,10 +454,10 @@ static void dp_display_post_open(struct dp_display *dp_display) return; } connector = dp->dp_display.connector; connector = dp->dp_display.base_connector; if (!connector) { pr_err("connector not set\n"); pr_err("base connector not set\n"); return; } Loading Loading @@ -509,10 +509,11 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->debug->psm_enabled = false; } if (!dp->dp_display.connector) if (!dp->dp_display.base_connector) return 0; rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector); rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.base_connector); if (rc) { /* * ETIMEDOUT --> cable may have been removed Loading Loading @@ -925,6 +926,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) panel_in.aux = dp->aux; panel_in.catalog = &dp->catalog->panel; panel_in.link = dp->link; panel_in.connector = dp->dp_display.base_connector; dp->panel = dp_panel_get(&panel_in); if (IS_ERR(dp->panel)) { Loading Loading @@ -970,8 +972,10 @@ static int dp_init_sub_modules(struct dp_display_private *dp) } dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd, dp->link, dp->aux, &dp->dp_display.connector, dp->link, dp->aux, &dp->dp_display.base_connector, dp->catalog); if (IS_ERR(dp->debug)) { rc = PTR_ERR(dp->debug); pr_err("failed to initialize debug, rc = %d\n", rc); Loading Loading @@ -1032,50 +1036,60 @@ static void dp_display_post_init(struct dp_display *dp_display) pr_debug("%s\n", rc ? "failed" : "success"); } static int dp_display_set_mode(struct dp_display *dp_display, static int dp_display_set_mode(struct dp_display *dp_display, void *panel, struct dp_display_mode *mode) { const u32 num_components = 3, default_bpp = 24; struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display) { 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); mode->timing.bpp = dp_display->connector->display_info.bpc * num_components; dp_panel->connector->display_info.bpc * num_components; if (!mode->timing.bpp) mode->timing.bpp = default_bpp; mode->timing.bpp = dp->panel->get_mode_bpp(dp->panel, mode->timing.bpp, mode->timing.pixel_clk_khz); dp->panel->pinfo = mode->timing; dp->panel->init(dp->panel); dp_panel->pinfo = mode->timing; dp_panel->init(dp_panel); mutex_unlock(&dp->session_lock); return 0; } static int dp_display_prepare(struct dp_display *dp) static int dp_display_prepare(struct dp_display *dp, void *panel) { return 0; } static int dp_display_enable(struct dp_display *dp_display) static int dp_display_enable(struct dp_display *dp_display, void *panel) { int rc = 0; struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; mutex_lock(&dp->session_lock); Loading @@ -1091,30 +1105,32 @@ static int dp_display_enable(struct dp_display *dp_display) dp->aux->init(dp->aux, dp->parser->aux_cfg); dp->panel->set_stream_id(dp->panel, DP_STREAM_0); dp_panel->set_stream_id(dp->panel, DP_STREAM_0); rc = dp->ctrl->on(dp->ctrl); if (!rc) dp->power_on = true; if (dp->debug->tpg_state) dp->panel->tpg_config(dp->panel, true); dp_panel->tpg_config(dp_panel, true); end: mutex_unlock(&dp->session_lock); return rc; } static int dp_display_post_enable(struct dp_display *dp_display) static int dp_display_post_enable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; mutex_lock(&dp->session_lock); Loading @@ -1128,7 +1144,7 @@ static int dp_display_post_enable(struct dp_display *dp_display) goto end; } dp->panel->spd_config(dp->panel); dp_panel->spd_config(dp_panel); if (dp->audio_supported) { dp->audio->bw_code = dp->link->link_params.bw_code; Loading @@ -1145,7 +1161,7 @@ static int dp_display_post_enable(struct dp_display *dp_display) queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2); } dp->panel->setup_hdr(dp->panel, NULL); dp_panel->setup_hdr(dp_panel, NULL); end: /* clear framework event notifier */ dp_display->post_open = NULL; Loading @@ -1156,11 +1172,11 @@ static int dp_display_post_enable(struct dp_display *dp_display) return 0; } static int dp_display_pre_disable(struct dp_display *dp_display) static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } Loading Loading @@ -1196,19 +1212,21 @@ static int dp_display_pre_disable(struct dp_display *dp_display) return 0; } static int dp_display_disable(struct dp_display *dp_display) static int dp_display_disable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct drm_connector *connector; struct sde_connector_state *c_state; struct dp_panel *dp_panel; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); connector = dp->dp_display.connector; dp_panel = panel; connector = dp_panel->connector; c_state = to_sde_connector_state(connector->state); mutex_lock(&dp->session_lock); Loading @@ -1219,7 +1237,8 @@ static int dp_display_disable(struct dp_display *dp_display) } dp->ctrl->off(dp->ctrl); dp->panel->deinit(dp->panel); dp_panel->set_stream_id(dp_panel, DP_STREAM_MAX); dp_panel->deinit(dp_panel); dp->aux->deinit(dp->aux); connector->hdr_eotf = 0; Loading Loading @@ -1292,32 +1311,39 @@ static struct dp_debug *dp_get_debug(struct dp_display *dp_display) return dp->debug; } static int dp_display_unprepare(struct dp_display *dp) static int dp_display_unprepare(struct dp_display *dp, void *panel) { return 0; } static int dp_display_validate_mode(struct dp_display *dp, u32 mode_pclk_khz) static int dp_display_validate_mode(struct dp_display *dp, void *panel, u32 mode_pclk_khz) { const u32 num_components = 3, default_bpp = 24; struct dp_display_private *dp_display; struct drm_dp_link *link_info; u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; struct dp_panel *dp_panel; if (!dp || !mode_pclk_khz || !dp->connector) { if (!dp || !mode_pclk_khz || !panel) { pr_err("invalid params\n"); return -EINVAL; } dp_panel = panel; if (!dp_panel->connector) { pr_err("invalid connector\n"); return -EINVAL; } dp_display = container_of(dp, struct dp_display_private, dp_display); link_info = &dp_display->panel->link_info; mode_bpp = dp->connector->display_info.bpc * num_components; mode_bpp = dp_panel->connector->display_info.bpc * num_components; if (!mode_bpp) mode_bpp = default_bpp; mode_bpp = dp_display->panel->get_mode_bpp(dp_display->panel, mode_bpp, mode_pclk_khz); mode_bpp = dp_panel->get_mode_bpp(dp_panel, mode_bpp, mode_pclk_khz); mode_rate_khz = mode_pclk_khz * mode_bpp; supported_rate_khz = link_info->num_lanes * link_info->rate * 8; Loading @@ -1328,40 +1354,48 @@ static int dp_display_validate_mode(struct dp_display *dp, u32 mode_pclk_khz) return MODE_OK; } static int dp_display_get_modes(struct dp_display *dp, static int dp_display_get_modes(struct dp_display *dp, void *panel, struct dp_display_mode *dp_mode) { struct dp_display_private *dp_display; struct dp_panel *dp_panel; int ret = 0; if (!dp || !dp->connector) { if (!dp || !panel) { pr_err("invalid params\n"); return 0; } dp_panel = panel; if (!dp_panel->connector) { pr_err("invalid connector\n"); return 0; } dp_display = container_of(dp, struct dp_display_private, dp_display); ret = dp_display->panel->get_modes(dp_display->panel, dp->connector, dp_mode); ret = dp_panel->get_modes(dp_panel, dp_panel->connector, dp_mode); if (dp_mode->timing.pixel_clk_khz) dp->max_pclk_khz = dp_mode->timing.pixel_clk_khz; return ret; } static int dp_display_config_hdr(struct dp_display *dp_display, static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr) { int rc = 0; struct dp_display_private *dp; struct dp_panel *dp_panel; if (!dp_display) { if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp = container_of(dp_display, struct dp_display_private, dp_display); dp_panel = panel; rc = dp->panel->setup_hdr(dp->panel, hdr); rc = dp_panel->setup_hdr(dp_panel, hdr); return rc; } Loading
drivers/gpu/drm/msm/dp/dp_display.h +13 −11 Original line number Diff line number Diff line Loading @@ -23,27 +23,29 @@ struct dp_display { struct drm_device *drm_dev; struct dp_bridge *bridge; struct drm_connector *connector; struct drm_connector *base_connector; void *base_dp_panel; bool is_connected; u32 max_pclk_khz; int (*enable)(struct dp_display *dp_display); int (*post_enable)(struct dp_display *dp_display); int (*enable)(struct dp_display *dp_display, void *panel); int (*post_enable)(struct dp_display *dp_display, void *panel); int (*pre_disable)(struct dp_display *dp_display); int (*disable)(struct dp_display *dp_display); int (*pre_disable)(struct dp_display *dp_display, void *panel); int (*disable)(struct dp_display *dp_display, void *panel); int (*set_mode)(struct dp_display *dp_display, int (*set_mode)(struct dp_display *dp_display, void *panel, struct dp_display_mode *mode); int (*validate_mode)(struct dp_display *dp_display, u32 mode_pclk_khz); int (*get_modes)(struct dp_display *dp_display, int (*validate_mode)(struct dp_display *dp_display, void *panel, u32 mode_pclk_khz); int (*get_modes)(struct dp_display *dp_display, void *panel, struct dp_display_mode *dp_mode); int (*prepare)(struct dp_display *dp_display); int (*unprepare)(struct dp_display *dp_display); int (*prepare)(struct dp_display *dp_display, void *panel); int (*unprepare)(struct dp_display *dp_display, void *panel); 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 (*config_hdr)(struct dp_display *dp_display, int (*config_hdr)(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr_meta); void (*post_init)(struct dp_display *dp_display); }; Loading