Loading msm/sde/sde_crtc.c +2 −2 Original line number Diff line number Diff line Loading @@ -5498,7 +5498,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, } static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, const struct drm_crtc_state *state, uint64_t *val) struct drm_crtc_state *state, uint64_t *val) { struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; Loading @@ -5511,7 +5511,7 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) { if (sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE)) MSM_DISPLAY_VIDEO_MODE) && !sde_crtc_state_in_clone_mode(encoder, state)) is_vid = true; if (is_vid) break; Loading msm/sde/sde_encoder.c +9 −0 Original line number Diff line number Diff line Loading @@ -809,6 +809,8 @@ void sde_encoder_set_clone_mode(struct drm_encoder *drm_enc, SDE_DEBUG("enc:%d phys state:%d\n", DRMID(drm_enc), phys->enable_state); } } sde_crtc_state->cwb_enc_mask = 0; } static int _sde_encoder_atomic_check_phys_enc(struct sde_encoder_virt *sde_enc, Loading Loading @@ -917,6 +919,12 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc, return ret; } /* Skip RM allocation for Primary during CWB usecase */ if (!crtc_state->mode_changed && !crtc_state->active_changed && crtc_state->connectors_changed && (conn_state->crtc == conn_state->connector->state->crtc)) goto skip_reserve; /* Reserve dynamic resources, indicating atomic_check phase */ ret = sde_rm_reserve(&sde_kms->rm, drm_enc, crtc_state, conn_state, true); Loading @@ -927,6 +935,7 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc, return ret; } skip_reserve: /** * Update connector state with the topology selected for the * resource set validated. Reset the topology if we are Loading msm/sde/sde_encoder_phys.h +3 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef __SDE_ENCODER_PHYS_H__ Loading Loading @@ -394,6 +394,7 @@ struct sde_encoder_phys_cmd_te_timestamp { * @wr_ptr_wait_success: log wr_ptr_wait success for release fence trigger * @te_timestamp_list: List head for the TE timestamp list * @te_timestamp: Array of size MAX_TE_PROFILE_COUNT te_timestamp_list elements * @frame_trigger_count: atomic counter tracking number of frame triggers per TE interval */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; Loading @@ -406,6 +407,7 @@ struct sde_encoder_phys_cmd { struct list_head te_timestamp_list; struct sde_encoder_phys_cmd_te_timestamp te_timestamp[MAX_TE_PROFILE_COUNT]; atomic_t frame_trigger_count; }; /** Loading msm/sde/sde_encoder_phys_cmd.c +34 −0 Original line number Diff line number Diff line Loading @@ -241,6 +241,7 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}}; struct sde_encoder_phys_cmd_te_timestamp *te_timestamp; unsigned long lock_flags; struct drm_display_mode *mode; if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf) return; Loading Loading @@ -270,6 +271,11 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) info[1].wr_ptr_line_count, info[1].intf_frame_count, scheduler_status); mode = &phys_enc->cached_mode; if (!mode || info[0].wr_ptr_line_count == mode->vdisplay || !info[0].wr_ptr_line_count) atomic_add_unless(&cmd_enc->frame_trigger_count, -1, 0); if (phys_enc->parent_ops.handle_vblank_virt) phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent, phys_enc); Loading @@ -285,12 +291,16 @@ static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx) struct sde_hw_ctl *ctl; u32 event = 0; struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}}; struct sde_encoder_phys_cmd *cmd_enc; if (!phys_enc || !phys_enc->hw_ctl) return; SDE_ATRACE_BEGIN("wr_ptr_irq"); ctl = phys_enc->hw_ctl; cmd_enc = to_sde_encoder_phys_cmd(phys_enc); atomic_inc(&cmd_enc->frame_trigger_count); if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) { event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; Loading Loading @@ -1923,10 +1933,34 @@ static void sde_encoder_phys_cmd_trigger_start( struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); u32 frame_cnt; struct drm_connector *conn; int threshold_lines, curr_rd_ptr_line_count; struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}}; struct drm_display_mode *mode; if (!phys_enc) return; conn = phys_enc->connector; mode = &phys_enc->cached_mode; if (mode && sde_connector_get_qsync_mode(conn)) { threshold_lines = _get_tearcheck_threshold(phys_enc); sde_encoder_helper_get_pp_line_count(phys_enc->parent, info); curr_rd_ptr_line_count = info[0].rd_ptr_line_count; /* * Vsync wait is required only if both the below conditions satisfy * - current rd_ptr linecount is within the start threshold window * - frame trigger already happened in this TE interval */ if ((curr_rd_ptr_line_count < mode->vdisplay + threshold_lines) && atomic_read(&cmd_enc->frame_trigger_count)) { SDE_EVT32(curr_rd_ptr_line_count, mode->vdisplay + threshold_lines, atomic_read(&cmd_enc->frame_trigger_count), 0xebad); sde_encoder_phys_cmd_wait_for_vblank(phys_enc); } } /* we don't issue CTL_START when using autorefresh */ frame_cnt = _sde_encoder_phys_cmd_get_autorefresh_property(phys_enc); if (frame_cnt) { Loading msm/sde/sde_kms.h +1 −1 Original line number Diff line number Diff line Loading @@ -478,7 +478,7 @@ void *sde_debugfs_get_root(struct sde_kms *sde_kms); * These functions/definitions allow for building up a 'sde_info' structure * containing one or more "key=value\n" entries. */ #define SDE_KMS_INFO_MAX_SIZE 4096 #define SDE_KMS_INFO_MAX_SIZE 8192 /** * struct sde_kms_info - connector information structure container Loading Loading
msm/sde/sde_crtc.c +2 −2 Original line number Diff line number Diff line Loading @@ -5498,7 +5498,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, } static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, const struct drm_crtc_state *state, uint64_t *val) struct drm_crtc_state *state, uint64_t *val) { struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; Loading @@ -5511,7 +5511,7 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) { if (sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE)) MSM_DISPLAY_VIDEO_MODE) && !sde_crtc_state_in_clone_mode(encoder, state)) is_vid = true; if (is_vid) break; Loading
msm/sde/sde_encoder.c +9 −0 Original line number Diff line number Diff line Loading @@ -809,6 +809,8 @@ void sde_encoder_set_clone_mode(struct drm_encoder *drm_enc, SDE_DEBUG("enc:%d phys state:%d\n", DRMID(drm_enc), phys->enable_state); } } sde_crtc_state->cwb_enc_mask = 0; } static int _sde_encoder_atomic_check_phys_enc(struct sde_encoder_virt *sde_enc, Loading Loading @@ -917,6 +919,12 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc, return ret; } /* Skip RM allocation for Primary during CWB usecase */ if (!crtc_state->mode_changed && !crtc_state->active_changed && crtc_state->connectors_changed && (conn_state->crtc == conn_state->connector->state->crtc)) goto skip_reserve; /* Reserve dynamic resources, indicating atomic_check phase */ ret = sde_rm_reserve(&sde_kms->rm, drm_enc, crtc_state, conn_state, true); Loading @@ -927,6 +935,7 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc, return ret; } skip_reserve: /** * Update connector state with the topology selected for the * resource set validated. Reset the topology if we are Loading
msm/sde/sde_encoder_phys.h +3 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef __SDE_ENCODER_PHYS_H__ Loading Loading @@ -394,6 +394,7 @@ struct sde_encoder_phys_cmd_te_timestamp { * @wr_ptr_wait_success: log wr_ptr_wait success for release fence trigger * @te_timestamp_list: List head for the TE timestamp list * @te_timestamp: Array of size MAX_TE_PROFILE_COUNT te_timestamp_list elements * @frame_trigger_count: atomic counter tracking number of frame triggers per TE interval */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; Loading @@ -406,6 +407,7 @@ struct sde_encoder_phys_cmd { struct list_head te_timestamp_list; struct sde_encoder_phys_cmd_te_timestamp te_timestamp[MAX_TE_PROFILE_COUNT]; atomic_t frame_trigger_count; }; /** Loading
msm/sde/sde_encoder_phys_cmd.c +34 −0 Original line number Diff line number Diff line Loading @@ -241,6 +241,7 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}}; struct sde_encoder_phys_cmd_te_timestamp *te_timestamp; unsigned long lock_flags; struct drm_display_mode *mode; if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf) return; Loading Loading @@ -270,6 +271,11 @@ static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx) info[1].wr_ptr_line_count, info[1].intf_frame_count, scheduler_status); mode = &phys_enc->cached_mode; if (!mode || info[0].wr_ptr_line_count == mode->vdisplay || !info[0].wr_ptr_line_count) atomic_add_unless(&cmd_enc->frame_trigger_count, -1, 0); if (phys_enc->parent_ops.handle_vblank_virt) phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent, phys_enc); Loading @@ -285,12 +291,16 @@ static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx) struct sde_hw_ctl *ctl; u32 event = 0; struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}}; struct sde_encoder_phys_cmd *cmd_enc; if (!phys_enc || !phys_enc->hw_ctl) return; SDE_ATRACE_BEGIN("wr_ptr_irq"); ctl = phys_enc->hw_ctl; cmd_enc = to_sde_encoder_phys_cmd(phys_enc); atomic_inc(&cmd_enc->frame_trigger_count); if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0)) { event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE; Loading Loading @@ -1923,10 +1933,34 @@ static void sde_encoder_phys_cmd_trigger_start( struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); u32 frame_cnt; struct drm_connector *conn; int threshold_lines, curr_rd_ptr_line_count; struct sde_hw_pp_vsync_info info[MAX_CHANNELS_PER_ENC] = {{0}}; struct drm_display_mode *mode; if (!phys_enc) return; conn = phys_enc->connector; mode = &phys_enc->cached_mode; if (mode && sde_connector_get_qsync_mode(conn)) { threshold_lines = _get_tearcheck_threshold(phys_enc); sde_encoder_helper_get_pp_line_count(phys_enc->parent, info); curr_rd_ptr_line_count = info[0].rd_ptr_line_count; /* * Vsync wait is required only if both the below conditions satisfy * - current rd_ptr linecount is within the start threshold window * - frame trigger already happened in this TE interval */ if ((curr_rd_ptr_line_count < mode->vdisplay + threshold_lines) && atomic_read(&cmd_enc->frame_trigger_count)) { SDE_EVT32(curr_rd_ptr_line_count, mode->vdisplay + threshold_lines, atomic_read(&cmd_enc->frame_trigger_count), 0xebad); sde_encoder_phys_cmd_wait_for_vblank(phys_enc); } } /* we don't issue CTL_START when using autorefresh */ frame_cnt = _sde_encoder_phys_cmd_get_autorefresh_property(phys_enc); if (frame_cnt) { Loading
msm/sde/sde_kms.h +1 −1 Original line number Diff line number Diff line Loading @@ -478,7 +478,7 @@ void *sde_debugfs_get_root(struct sde_kms *sde_kms); * These functions/definitions allow for building up a 'sde_info' structure * containing one or more "key=value\n" entries. */ #define SDE_KMS_INFO_MAX_SIZE 4096 #define SDE_KMS_INFO_MAX_SIZE 8192 /** * struct sde_kms_info - connector information structure container Loading