Loading drivers/gpu/drm/msm/sde/sde_connector.c +55 −0 Original line number Diff line number Diff line Loading @@ -636,6 +636,18 @@ static int _sde_connector_update_dirty_properties( return 0; } struct sde_connector_dyn_hdr_metadata *sde_connector_get_dyn_hdr_meta( struct drm_connector *connector) { struct sde_connector_state *c_state; if (!connector) return NULL; c_state = to_sde_connector_state(connector->state); return &c_state->dyn_hdr_meta; } int sde_connector_pre_kickoff(struct drm_connector *connector) { struct sde_connector *c_conn; Loading Loading @@ -927,6 +939,12 @@ sde_connector_atomic_duplicate_state(struct drm_connector *connector) if (c_state->out_fb) drm_framebuffer_get(c_state->out_fb); /* clear dynamic HDR metadata from prev state */ if (c_state->dyn_hdr_meta.dynamic_hdr_update) { c_state->dyn_hdr_meta.dynamic_hdr_update = false; c_state->dyn_hdr_meta.dynamic_hdr_payload_size = 0; } return &c_state->base; } Loading Loading @@ -1069,6 +1087,8 @@ static int _sde_connector_set_ext_hdr_info( int rc = 0; struct drm_connector *connector; struct drm_msm_ext_hdr_metadata *hdr_meta; size_t payload_size = 0; u8 *payload = NULL; int i; if (!c_conn || !c_state) { Loading Loading @@ -1102,6 +1122,37 @@ static int _sde_connector_set_ext_hdr_info( hdr_meta = &c_state->hdr_meta; /* dynamic metadata support */ if (!hdr_meta->hdr_plus_payload_size || !hdr_meta->hdr_plus_payload) goto skip_dhdr; if (!connector->hdr_plus_app_ver) { SDE_ERROR_CONN(c_conn, "sink doesn't support dynamic HDR\n"); rc = -ENOTSUPP; goto end; } payload_size = hdr_meta->hdr_plus_payload_size; if (payload_size > sizeof(c_state->dyn_hdr_meta.dynamic_hdr_payload)) { SDE_ERROR_CONN(c_conn, "payload size exceeds limit\n"); rc = -EINVAL; goto end; } payload = c_state->dyn_hdr_meta.dynamic_hdr_payload; if (copy_from_user(payload, (void __user *)c_state->hdr_meta.hdr_plus_payload, payload_size)) { SDE_ERROR_CONN(c_conn, "failed to copy dhdr metadata\n"); rc = -EFAULT; goto end; } c_state->dyn_hdr_meta.dynamic_hdr_update = true; skip_dhdr: c_state->dyn_hdr_meta.dynamic_hdr_payload_size = payload_size; SDE_DEBUG_CONN(c_conn, "hdr_state %d\n", hdr_meta->hdr_state); SDE_DEBUG_CONN(c_conn, "hdr_supported %d\n", hdr_meta->hdr_supported); SDE_DEBUG_CONN(c_conn, "eotf %d\n", hdr_meta->eotf); Loading @@ -1119,6 +1170,9 @@ static int _sde_connector_set_ext_hdr_info( SDE_DEBUG_CONN(c_conn, "display_primaries_y [%d]\n", hdr_meta->display_primaries_y[i]); } SDE_DEBUG_CONN(c_conn, "hdr_plus payload%s updated, size %d\n", c_state->dyn_hdr_meta.dynamic_hdr_update ? "" : " NOT", c_state->dyn_hdr_meta.dynamic_hdr_payload_size); end: return rc; Loading Loading @@ -1335,6 +1389,7 @@ static void sde_connector_update_hdr_props(struct drm_connector *connector) connector->hdr_max_luminance, connector->hdr_avg_luminance, connector->hdr_min_luminance, connector->hdr_plus_app_ver, }; msm_property_set_blob(&c_conn->property_info, &c_conn->blob_ext_hdr, Loading drivers/gpu/drm/msm/sde/sde_connector.h +19 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "sde_fence.h" #define SDE_CONNECTOR_NAME_SIZE 16 #define SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE SZ_2K struct sde_connector; struct sde_connector_state; Loading Loading @@ -330,6 +331,12 @@ struct sde_connector_evt { void *usr; }; struct sde_connector_dyn_hdr_metadata { u8 dynamic_hdr_payload[SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE]; int dynamic_hdr_payload_size; bool dynamic_hdr_update; }; /** * struct sde_connector - local sde connector structure * @base: Base drm connector structure Loading Loading @@ -372,6 +379,7 @@ struct sde_connector_evt { * @qsync_updated: Qsync settings were updated * last_cmd_tx_sts: status of the last command transfer * @hdr_capable: external hdr support present * @core_clk_rate: MDP core clk rate used for dynamic HDR packet calculation */ struct sde_connector { struct drm_connector base; Loading Loading @@ -491,6 +499,7 @@ struct sde_connector { * @property_blobs: blob properties * @mode_info: local copy of msm_mode_info struct * @hdr_meta: HDR metadata info passed from userspace * @dyn_hdr_meta: Dynamic HDR metadata payload and state tracking * @old_topology_name: topology of previous atomic state. remove this in later * kernel versions which provide drm_atomic_state old_state pointers */ Loading @@ -504,6 +513,7 @@ struct sde_connector_state { struct drm_property_blob *property_blobs[CONNECTOR_PROP_BLOBCOUNT]; struct msm_mode_info mode_info; struct drm_msm_ext_hdr_metadata hdr_meta; struct sde_connector_dyn_hdr_metadata dyn_hdr_meta; enum sde_rm_topology_name old_topology_name; }; Loading Loading @@ -697,6 +707,15 @@ int sde_connector_get_dpms(struct drm_connector *connector); */ void sde_connector_set_qsync_params(struct drm_connector *connector); /** * sde_connector_get_dyn_hdr_meta - returns pointer to connector state's dynamic * HDR metadata info * @connector: pointer to drm connector */ struct sde_connector_dyn_hdr_metadata *sde_connector_get_dyn_hdr_meta( struct drm_connector *connector); /** * sde_connector_trigger_event - indicate that an event has occurred * Any callbacks that have been registered against this event will Loading drivers/gpu/drm/msm/sde/sde_crtc.c +1 −0 Original line number Diff line number Diff line Loading @@ -4988,6 +4988,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, sde_kms_info_add_keyint(info, "has_src_split", catalog->has_src_split); sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr); sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus); if (catalog->perf.max_bw_low) sde_kms_info_add_keyint(info, "max_bandwidth_low", catalog->perf.max_bw_low * 1000LL); Loading drivers/gpu/drm/msm/sde/sde_encoder.c +42 −6 Original line number Diff line number Diff line Loading @@ -214,6 +214,7 @@ enum sde_enc_rc_states { * @idle_pc_restore: flag to indicate idle_pc_restore happened * @frame_trigger_mode: frame trigger mode indication for command * mode display * @dynamic_hdr_updated: flag to indicate if mempool was programmed * @rsc_config: rsc configuration for display vtotal, fps, etc. * @cur_conn_roi: current connector roi * @prv_conn_roi: previous connector roi to optimize if unchanged Loading Loading @@ -271,6 +272,7 @@ struct sde_encoder_virt { bool vblank_enabled; bool idle_pc_restore; enum frame_trigger_mode_type frame_trigger_mode; bool dynamic_hdr_updated; struct sde_rsc_cmd_config rsc_config; struct sde_rect cur_conn_roi; Loading Loading @@ -3775,13 +3777,20 @@ static inline void _sde_encoder_trigger_flush(struct drm_encoder *drm_enc, pend_ret_fence_cnt = atomic_read(&phys->pending_retire_fence_cnt); /* perform peripheral flush on every frame update for dp dsc */ if (phys->hw_intf && phys->hw_intf->cap->type == INTF_DP && phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC && phys->comp_ratio && ctl->ops.update_bitmask_periph && c_conn->ops.update_pps) { c_conn->ops.update_pps(phys->connector, NULL, c_conn->display); ctl->ops.update_bitmask_periph(ctl, phys->hw_intf->idx, 1); ctl->ops.update_bitmask_periph) { /* perform peripheral flush on every frame update for dp dsc */ if (phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC && phys->comp_ratio && c_conn->ops.update_pps) { c_conn->ops.update_pps(phys->connector, NULL, c_conn->display); ctl->ops.update_bitmask_periph(ctl, phys->hw_intf->idx, 1); } if (sde_enc->dynamic_hdr_updated) ctl->ops.update_bitmask_periph(ctl, phys->hw_intf->idx, 1); } if ((extra_flush && extra_flush->pending_flush_mask) Loading Loading @@ -4603,6 +4612,31 @@ static void _helper_flush_dsc(struct sde_encoder_virt *sde_enc) sde_enc->dirty_dsc_ids[i] = DSC_NONE; } } static void _sde_encoder_helper_hdr_plus_mempool_update( struct sde_encoder_virt *sde_enc) { struct sde_connector_dyn_hdr_metadata *dhdr_meta = NULL; struct sde_hw_mdp *mdptop = NULL; sde_enc->dynamic_hdr_updated = false; if (sde_enc->cur_master) { mdptop = sde_enc->cur_master->hw_mdptop; dhdr_meta = sde_connector_get_dyn_hdr_meta( sde_enc->cur_master->connector); } if (!mdptop || !dhdr_meta || !dhdr_meta->dynamic_hdr_update) return; if (mdptop->ops.set_hdr_plus_metadata) { sde_enc->dynamic_hdr_updated = true; mdptop->ops.set_hdr_plus_metadata( mdptop, dhdr_meta->dynamic_hdr_payload, dhdr_meta->dynamic_hdr_payload_size, sde_enc->cur_master->intf_idx == INTF_0 ? 0 : 1); } } static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc, int ln_cnt1) Loading Loading @@ -4668,6 +4702,8 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, sde_enc->cur_master->connector->state, CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); _sde_encoder_helper_hdr_plus_mempool_update(sde_enc); /* prepare for next kickoff, may include waiting on previous kickoff */ SDE_ATRACE_BEGIN("sde_encoder_prepare_for_kickoff"); for (i = 0; i < sde_enc->num_phys_encs; i++) { Loading drivers/gpu/drm/msm/sde/sde_hw_catalog.c +4 −0 Original line number Diff line number Diff line Loading @@ -3753,6 +3753,8 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->has_wb_ubwc = true; sde_cfg->has_qsync = true; sde_cfg->has_hdr = true; sde_cfg->has_hdr_plus = true; set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features); sde_cfg->has_vig_p010 = true; sde_cfg->perf.min_prefill_lines = 24; sde_cfg->vbif_qos_nlvl = 8; Loading Loading @@ -3824,6 +3826,8 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); sde_cfg->has_hdr = true; sde_cfg->has_hdr_plus = true; set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features); sde_cfg->has_vig_p010 = true; sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_1_0_0; sde_cfg->true_inline_dwnscale_rt = Loading Loading
drivers/gpu/drm/msm/sde/sde_connector.c +55 −0 Original line number Diff line number Diff line Loading @@ -636,6 +636,18 @@ static int _sde_connector_update_dirty_properties( return 0; } struct sde_connector_dyn_hdr_metadata *sde_connector_get_dyn_hdr_meta( struct drm_connector *connector) { struct sde_connector_state *c_state; if (!connector) return NULL; c_state = to_sde_connector_state(connector->state); return &c_state->dyn_hdr_meta; } int sde_connector_pre_kickoff(struct drm_connector *connector) { struct sde_connector *c_conn; Loading Loading @@ -927,6 +939,12 @@ sde_connector_atomic_duplicate_state(struct drm_connector *connector) if (c_state->out_fb) drm_framebuffer_get(c_state->out_fb); /* clear dynamic HDR metadata from prev state */ if (c_state->dyn_hdr_meta.dynamic_hdr_update) { c_state->dyn_hdr_meta.dynamic_hdr_update = false; c_state->dyn_hdr_meta.dynamic_hdr_payload_size = 0; } return &c_state->base; } Loading Loading @@ -1069,6 +1087,8 @@ static int _sde_connector_set_ext_hdr_info( int rc = 0; struct drm_connector *connector; struct drm_msm_ext_hdr_metadata *hdr_meta; size_t payload_size = 0; u8 *payload = NULL; int i; if (!c_conn || !c_state) { Loading Loading @@ -1102,6 +1122,37 @@ static int _sde_connector_set_ext_hdr_info( hdr_meta = &c_state->hdr_meta; /* dynamic metadata support */ if (!hdr_meta->hdr_plus_payload_size || !hdr_meta->hdr_plus_payload) goto skip_dhdr; if (!connector->hdr_plus_app_ver) { SDE_ERROR_CONN(c_conn, "sink doesn't support dynamic HDR\n"); rc = -ENOTSUPP; goto end; } payload_size = hdr_meta->hdr_plus_payload_size; if (payload_size > sizeof(c_state->dyn_hdr_meta.dynamic_hdr_payload)) { SDE_ERROR_CONN(c_conn, "payload size exceeds limit\n"); rc = -EINVAL; goto end; } payload = c_state->dyn_hdr_meta.dynamic_hdr_payload; if (copy_from_user(payload, (void __user *)c_state->hdr_meta.hdr_plus_payload, payload_size)) { SDE_ERROR_CONN(c_conn, "failed to copy dhdr metadata\n"); rc = -EFAULT; goto end; } c_state->dyn_hdr_meta.dynamic_hdr_update = true; skip_dhdr: c_state->dyn_hdr_meta.dynamic_hdr_payload_size = payload_size; SDE_DEBUG_CONN(c_conn, "hdr_state %d\n", hdr_meta->hdr_state); SDE_DEBUG_CONN(c_conn, "hdr_supported %d\n", hdr_meta->hdr_supported); SDE_DEBUG_CONN(c_conn, "eotf %d\n", hdr_meta->eotf); Loading @@ -1119,6 +1170,9 @@ static int _sde_connector_set_ext_hdr_info( SDE_DEBUG_CONN(c_conn, "display_primaries_y [%d]\n", hdr_meta->display_primaries_y[i]); } SDE_DEBUG_CONN(c_conn, "hdr_plus payload%s updated, size %d\n", c_state->dyn_hdr_meta.dynamic_hdr_update ? "" : " NOT", c_state->dyn_hdr_meta.dynamic_hdr_payload_size); end: return rc; Loading Loading @@ -1335,6 +1389,7 @@ static void sde_connector_update_hdr_props(struct drm_connector *connector) connector->hdr_max_luminance, connector->hdr_avg_luminance, connector->hdr_min_luminance, connector->hdr_plus_app_ver, }; msm_property_set_blob(&c_conn->property_info, &c_conn->blob_ext_hdr, Loading
drivers/gpu/drm/msm/sde/sde_connector.h +19 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "sde_fence.h" #define SDE_CONNECTOR_NAME_SIZE 16 #define SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE SZ_2K struct sde_connector; struct sde_connector_state; Loading Loading @@ -330,6 +331,12 @@ struct sde_connector_evt { void *usr; }; struct sde_connector_dyn_hdr_metadata { u8 dynamic_hdr_payload[SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE]; int dynamic_hdr_payload_size; bool dynamic_hdr_update; }; /** * struct sde_connector - local sde connector structure * @base: Base drm connector structure Loading Loading @@ -372,6 +379,7 @@ struct sde_connector_evt { * @qsync_updated: Qsync settings were updated * last_cmd_tx_sts: status of the last command transfer * @hdr_capable: external hdr support present * @core_clk_rate: MDP core clk rate used for dynamic HDR packet calculation */ struct sde_connector { struct drm_connector base; Loading Loading @@ -491,6 +499,7 @@ struct sde_connector { * @property_blobs: blob properties * @mode_info: local copy of msm_mode_info struct * @hdr_meta: HDR metadata info passed from userspace * @dyn_hdr_meta: Dynamic HDR metadata payload and state tracking * @old_topology_name: topology of previous atomic state. remove this in later * kernel versions which provide drm_atomic_state old_state pointers */ Loading @@ -504,6 +513,7 @@ struct sde_connector_state { struct drm_property_blob *property_blobs[CONNECTOR_PROP_BLOBCOUNT]; struct msm_mode_info mode_info; struct drm_msm_ext_hdr_metadata hdr_meta; struct sde_connector_dyn_hdr_metadata dyn_hdr_meta; enum sde_rm_topology_name old_topology_name; }; Loading Loading @@ -697,6 +707,15 @@ int sde_connector_get_dpms(struct drm_connector *connector); */ void sde_connector_set_qsync_params(struct drm_connector *connector); /** * sde_connector_get_dyn_hdr_meta - returns pointer to connector state's dynamic * HDR metadata info * @connector: pointer to drm connector */ struct sde_connector_dyn_hdr_metadata *sde_connector_get_dyn_hdr_meta( struct drm_connector *connector); /** * sde_connector_trigger_event - indicate that an event has occurred * Any callbacks that have been registered against this event will Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +1 −0 Original line number Diff line number Diff line Loading @@ -4988,6 +4988,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, sde_kms_info_add_keyint(info, "has_src_split", catalog->has_src_split); sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr); sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus); if (catalog->perf.max_bw_low) sde_kms_info_add_keyint(info, "max_bandwidth_low", catalog->perf.max_bw_low * 1000LL); Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +42 −6 Original line number Diff line number Diff line Loading @@ -214,6 +214,7 @@ enum sde_enc_rc_states { * @idle_pc_restore: flag to indicate idle_pc_restore happened * @frame_trigger_mode: frame trigger mode indication for command * mode display * @dynamic_hdr_updated: flag to indicate if mempool was programmed * @rsc_config: rsc configuration for display vtotal, fps, etc. * @cur_conn_roi: current connector roi * @prv_conn_roi: previous connector roi to optimize if unchanged Loading Loading @@ -271,6 +272,7 @@ struct sde_encoder_virt { bool vblank_enabled; bool idle_pc_restore; enum frame_trigger_mode_type frame_trigger_mode; bool dynamic_hdr_updated; struct sde_rsc_cmd_config rsc_config; struct sde_rect cur_conn_roi; Loading Loading @@ -3775,13 +3777,20 @@ static inline void _sde_encoder_trigger_flush(struct drm_encoder *drm_enc, pend_ret_fence_cnt = atomic_read(&phys->pending_retire_fence_cnt); /* perform peripheral flush on every frame update for dp dsc */ if (phys->hw_intf && phys->hw_intf->cap->type == INTF_DP && phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC && phys->comp_ratio && ctl->ops.update_bitmask_periph && c_conn->ops.update_pps) { c_conn->ops.update_pps(phys->connector, NULL, c_conn->display); ctl->ops.update_bitmask_periph(ctl, phys->hw_intf->idx, 1); ctl->ops.update_bitmask_periph) { /* perform peripheral flush on every frame update for dp dsc */ if (phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC && phys->comp_ratio && c_conn->ops.update_pps) { c_conn->ops.update_pps(phys->connector, NULL, c_conn->display); ctl->ops.update_bitmask_periph(ctl, phys->hw_intf->idx, 1); } if (sde_enc->dynamic_hdr_updated) ctl->ops.update_bitmask_periph(ctl, phys->hw_intf->idx, 1); } if ((extra_flush && extra_flush->pending_flush_mask) Loading Loading @@ -4603,6 +4612,31 @@ static void _helper_flush_dsc(struct sde_encoder_virt *sde_enc) sde_enc->dirty_dsc_ids[i] = DSC_NONE; } } static void _sde_encoder_helper_hdr_plus_mempool_update( struct sde_encoder_virt *sde_enc) { struct sde_connector_dyn_hdr_metadata *dhdr_meta = NULL; struct sde_hw_mdp *mdptop = NULL; sde_enc->dynamic_hdr_updated = false; if (sde_enc->cur_master) { mdptop = sde_enc->cur_master->hw_mdptop; dhdr_meta = sde_connector_get_dyn_hdr_meta( sde_enc->cur_master->connector); } if (!mdptop || !dhdr_meta || !dhdr_meta->dynamic_hdr_update) return; if (mdptop->ops.set_hdr_plus_metadata) { sde_enc->dynamic_hdr_updated = true; mdptop->ops.set_hdr_plus_metadata( mdptop, dhdr_meta->dynamic_hdr_payload, dhdr_meta->dynamic_hdr_payload_size, sde_enc->cur_master->intf_idx == INTF_0 ? 0 : 1); } } static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc, int ln_cnt1) Loading Loading @@ -4668,6 +4702,8 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, sde_enc->cur_master->connector->state, CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); _sde_encoder_helper_hdr_plus_mempool_update(sde_enc); /* prepare for next kickoff, may include waiting on previous kickoff */ SDE_ATRACE_BEGIN("sde_encoder_prepare_for_kickoff"); for (i = 0; i < sde_enc->num_phys_encs; i++) { Loading
drivers/gpu/drm/msm/sde/sde_hw_catalog.c +4 −0 Original line number Diff line number Diff line Loading @@ -3753,6 +3753,8 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->has_wb_ubwc = true; sde_cfg->has_qsync = true; sde_cfg->has_hdr = true; sde_cfg->has_hdr_plus = true; set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features); sde_cfg->has_vig_p010 = true; sde_cfg->perf.min_prefill_lines = 24; sde_cfg->vbif_qos_nlvl = 8; Loading Loading @@ -3824,6 +3826,8 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); sde_cfg->has_hdr = true; sde_cfg->has_hdr_plus = true; set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features); sde_cfg->has_vig_p010 = true; sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_1_0_0; sde_cfg->true_inline_dwnscale_rt = Loading