Loading drivers/gpu/drm/msm/sde/sde_crtc.c +118 −92 Original line number Diff line number Diff line Loading @@ -602,10 +602,9 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer, struct sde_hw_dim_layer *dim_layer) { struct sde_crtc_state *cstate; struct sde_hw_mixer *lm; struct sde_rect mixer_rect; struct sde_hw_dim_layer split_dim_layer; u32 mixer_width, mixer_height; int i; if (!dim_layer->rect.w || !dim_layer->rect.h) { Loading @@ -613,9 +612,7 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, return; } mixer_width = get_crtc_split_width(crtc); mixer_height = get_crtc_mixer_height(crtc); mixer_rect = (struct sde_rect) {0, 0, mixer_width, mixer_height}; cstate = to_sde_crtc_state(crtc->state); split_dim_layer.stage = dim_layer->stage; split_dim_layer.color_fill = dim_layer->color_fill; Loading @@ -626,17 +623,15 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, */ for (i = 0; i < sde_crtc->num_mixers; i++) { split_dim_layer.flags = dim_layer->flags; mixer_rect.x = i * mixer_width; sde_kms_rect_intersect(&mixer_rect, &dim_layer->rect, sde_kms_rect_intersect(&cstate->lm_bounds[i], &dim_layer->rect, &split_dim_layer.rect); if (!split_dim_layer.rect.w && !split_dim_layer.rect.h) { if (sde_kms_rect_is_null(&split_dim_layer.rect)) { /* * no extra programming required for non-intersecting * layer mixers with INCLUSIVE dim layer */ if (split_dim_layer.flags & SDE_DRM_DIM_LAYER_INCLUSIVE) if (split_dim_layer.flags & SDE_DRM_DIM_LAYER_INCLUSIVE) continue; /* Loading @@ -646,12 +641,13 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, */ split_dim_layer.flags &= ~SDE_DRM_DIM_LAYER_EXCLUSIVE; split_dim_layer.flags |= SDE_DRM_DIM_LAYER_INCLUSIVE; split_dim_layer.rect = (struct sde_rect) {0, 0, mixer_width, mixer_height}; memcpy(&split_dim_layer.rect, &cstate->lm_bounds[i], sizeof(split_dim_layer.rect)); } else { split_dim_layer.rect.x = split_dim_layer.rect.x - (i * mixer_width); split_dim_layer.rect.x = split_dim_layer.rect.x - cstate->lm_bounds[i].w; } lm = mixer[i].hw_lm; Loading @@ -660,6 +656,32 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, } } static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; struct sde_crtc_state *crtc_state; int lm_idx, lm_horiz_position; sde_crtc = to_sde_crtc(crtc); crtc_state = to_sde_crtc_state(crtc->state); lm_horiz_position = 0; for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) { const struct sde_rect *lm_roi = &crtc_state->lm_bounds[lm_idx]; struct sde_hw_mixer *hw_lm = sde_crtc->mixers[lm_idx].hw_lm; struct sde_hw_mixer_cfg cfg; if (sde_kms_rect_is_null(lm_roi)) continue; cfg.out_width = lm_roi->w; cfg.out_height = lm_roi->h; cfg.right_mixer = lm_horiz_position++; cfg.flags = 0; hw_lm->ops.setup_mixer_out(hw_lm, &cfg); } } static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer) { Loading @@ -672,13 +694,12 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct sde_hw_ctl *ctl; struct sde_hw_mixer *lm; struct sde_hw_stage_cfg *stage_cfg; struct sde_rect plane_crtc_roi; u32 flush_mask = 0, crtc_split_width; uint32_t lm_idx = LEFT_MIXER, idx; u32 flush_mask = 0; uint32_t lm_idx = LEFT_MIXER, stage_idx; bool bg_alpha_enable[CRTC_DUAL_MIXERS] = {false}; bool lm_right = false; int left_crtc_zpos_cnt[SDE_STAGE_MAX + 1] = {0}; int right_crtc_zpos_cnt[SDE_STAGE_MAX + 1] = {0}; int zpos_cnt[CRTC_DUAL_MIXERS][SDE_STAGE_MAX + 1] = { {0} }; int i; bool sbuf_mode = false; u32 prefill = 0; Loading @@ -691,13 +712,18 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, ctl = mixer->hw_ctl; lm = mixer->hw_lm; stage_cfg = &sde_crtc->stage_cfg; crtc_split_width = get_crtc_split_width(crtc); cstate = to_sde_crtc_state(crtc->state); drm_atomic_crtc_for_each_plane(plane, crtc) { state = plane->state; if (!state) continue; plane_crtc_roi.x = state->crtc_x; plane_crtc_roi.y = state->crtc_y; plane_crtc_roi.w = state->crtc_w; plane_crtc_roi.h = state->crtc_h; pstate = to_sde_plane_state(state); fb = state->fb; Loading @@ -706,25 +732,6 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, sde_plane_get_ctl_flush(plane, ctl, &flush_mask); /* always stage plane on either left or right lm */ if (state->crtc_x >= crtc_split_width) { lm_idx = RIGHT_MIXER; idx = right_crtc_zpos_cnt[pstate->stage]++; } else { lm_idx = LEFT_MIXER; idx = left_crtc_zpos_cnt[pstate->stage]++; } /* stage plane on right LM if it crosses the boundary */ lm_right = (lm_idx == LEFT_MIXER) && (state->crtc_x + state->crtc_w > crtc_split_width); stage_cfg->stage[lm_idx][pstate->stage][idx] = sde_plane_pipe(plane); stage_cfg->multirect_index [lm_idx][pstate->stage][idx] = pstate->multirect_index; mixer[lm_idx].flush_mask |= flush_mask; SDE_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n", crtc->base.id, Loading @@ -738,47 +745,46 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, SDE_EVT32(DRMID(plane), state->src_x, state->src_y, state->src_w >> 16, state->src_h >> 16, state->crtc_x, state->crtc_y, state->crtc_w, state->crtc_h); SDE_EVT32(DRMID(plane), DRMID(crtc), lm_idx, lm_right, pstate->stage, pstate->multirect_index, pstate->multirect_mode, format->base.pixel_format, fb ? fb->modifier[0] : 0); /* blend config update */ if (pstate->stage != SDE_STAGE_BASE) { _sde_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format); for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) { struct sde_rect intersect; if (bg_alpha_enable[lm_idx] && !format->alpha_enable) mixer[lm_idx].mixer_op_mode = 0; else mixer[lm_idx].mixer_op_mode |= 1 << pstate->stage; } else if (format->alpha_enable) { bg_alpha_enable[lm_idx] = true; } /* skip if the roi doesn't fall within LM's bounds */ sde_kms_rect_intersect(&plane_crtc_roi, &cstate->lm_bounds[lm_idx], &intersect); if (sde_kms_rect_is_null(&intersect)) continue; if (lm_right) { idx = right_crtc_zpos_cnt[pstate->stage]++; stage_cfg->stage[RIGHT_MIXER][pstate->stage][idx] = stage_idx = zpos_cnt[lm_idx][pstate->stage]++; stage_cfg->stage[lm_idx][pstate->stage][stage_idx] = sde_plane_pipe(plane); stage_cfg->multirect_index [RIGHT_MIXER][pstate->stage][idx] = [lm_idx][pstate->stage][stage_idx] = pstate->multirect_index; mixer[RIGHT_MIXER].flush_mask |= flush_mask; mixer[lm_idx].flush_mask |= flush_mask; SDE_EVT32(DRMID(plane), DRMID(crtc), lm_idx, stage_idx, pstate->stage, pstate->multirect_index, pstate->multirect_mode, format->base.pixel_format, fb ? fb->modifier[0] : 0); /* blend config update */ if (pstate->stage != SDE_STAGE_BASE) { _sde_crtc_setup_blend_cfg(mixer + RIGHT_MIXER, _sde_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format); if (bg_alpha_enable[RIGHT_MIXER] && if (bg_alpha_enable[lm_idx] && !format->alpha_enable) mixer[RIGHT_MIXER].mixer_op_mode = 0; mixer[lm_idx].mixer_op_mode = 0; else mixer[RIGHT_MIXER].mixer_op_mode |= mixer[lm_idx].mixer_op_mode |= 1 << pstate->stage; } else if (format->alpha_enable) { bg_alpha_enable[RIGHT_MIXER] = true; bg_alpha_enable[lm_idx] = true; } } } Loading @@ -804,6 +810,8 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, ctl->ops.setup_sbuf_cfg(ctl, &cstate->sbuf_cfg); } _sde_crtc_program_lm_output_roi(crtc); } /** Loading Loading @@ -1296,9 +1304,44 @@ static void _sde_crtc_setup_mixers(struct drm_crtc *crtc) _sde_crtc_setup_mixer_for_encoder(crtc, enc); } mutex_unlock(&sde_crtc->crtc_lock); } static void _sde_crtc_setup_lm_bounds(struct drm_crtc *crtc, struct drm_crtc_state *state) { struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; struct drm_display_mode *adj_mode; u32 crtc_split_width; int i; if (!crtc || !state) { SDE_ERROR("invalid args\n"); return; } sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(state); adj_mode = &state->adjusted_mode; crtc_split_width = sde_crtc_mixer_width(sde_crtc, adj_mode); for (i = 0; i < sde_crtc->num_mixers; i++) { struct sde_rect *lm_bound = &cstate->lm_bounds[i]; lm_bound->x = crtc_split_width * i; lm_bound->y = 0; lm_bound->w = crtc_split_width; lm_bound->h = adj_mode->vdisplay; SDE_EVT32(DRMID(crtc), i, lm_bound->x, lm_bound->y, lm_bound->w, lm_bound->h); } drm_mode_debug_printmodeline(adj_mode); } static void sde_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { Loading Loading @@ -1326,6 +1369,8 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, if (!sde_crtc->num_mixers) _sde_crtc_setup_mixers(crtc); _sde_crtc_setup_lm_bounds(crtc, crtc->state); if (sde_crtc->event) { WARN_ON(sde_crtc->event); } else { Loading Loading @@ -1776,13 +1821,10 @@ static void sde_crtc_disable(struct drm_crtc *crtc) static void sde_crtc_enable(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; struct sde_crtc_mixer *mixer; struct sde_hw_mixer *lm; struct drm_display_mode *mode; struct drm_encoder *encoder; unsigned long flags; struct sde_crtc_irq_info *node = NULL; int i, ret; int ret; if (!crtc) { SDE_ERROR("invalid crtc\n"); Loading @@ -1791,16 +1833,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc) SDE_DEBUG("crtc%d\n", crtc->base.id); SDE_EVT32(DRMID(crtc)); sde_crtc = to_sde_crtc(crtc); mixer = sde_crtc->mixers; if (WARN_ON(!crtc->state)) return; mode = &crtc->state->adjusted_mode; drm_mode_debug_printmodeline(mode); drm_for_each_encoder(encoder, crtc->dev) { if (encoder->crtc != crtc) Loading @@ -1809,15 +1842,6 @@ static void sde_crtc_enable(struct drm_crtc *crtc) sde_crtc_frame_event_cb, (void *)crtc); } for (i = 0; i < sde_crtc->num_mixers; i++) { lm = mixer[i].hw_lm; lm->cfg.out_width = sde_crtc_mixer_width(sde_crtc, mode); lm->cfg.out_height = mode->vdisplay; lm->cfg.right_mixer = (i == 0) ? false : true; lm->cfg.flags = 0; lm->ops.setup_mixer_out(lm, &lm->cfg); } spin_lock_irqsave(&sde_crtc->spin_lock, flags); list_for_each_entry(node, &sde_crtc->user_event_list, list) { ret = 0; Loading Loading @@ -1894,6 +1918,8 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, mixer_width = sde_crtc_mixer_width(sde_crtc, mode); _sde_crtc_setup_lm_bounds(crtc, state); /* get plane state for all drm planes associated with crtc state */ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { if (IS_ERR_OR_NULL(pstate)) { Loading drivers/gpu/drm/msm/sde/sde_crtc.h +5 −25 Original line number Diff line number Diff line Loading @@ -108,7 +108,7 @@ struct sde_crtc_event { * @name : ASCII description of this crtc * @num_ctls : Number of ctl paths in use * @num_mixers : Number of mixers in use * @mixer : List of active mixers * @mixers : List of active mixers * @event : Pointer to last received drm vblank event. If there is a * pending vblank event, this will be non-null. * @vsync_count : Running count of received vsync events Loading Loading @@ -248,6 +248,8 @@ struct sde_crtc_respool { * @num_connectors: Number of associated drm connectors * @intf_mode : Interface mode of the primary connector * @rsc_client : sde rsc client when mode is valid * @lm_bounds : LM boundaries based on current mode full resolution, no ROI. * Origin top left of CRTC. * @property_values: Current crtc property values * @input_fence_timeout_ns : Cached input fence timeout, in ns * @property_blobs: Reference pointers for blob properties Loading @@ -267,6 +269,8 @@ struct sde_crtc_state { struct sde_rsc_client *rsc_client; bool rsc_update; struct sde_rect lm_bounds[CRTC_DUAL_MIXERS]; uint64_t property_values[CRTC_PROP_COUNT]; uint64_t input_fence_timeout_ns; struct drm_property_blob *property_blobs[CRTC_PROP_COUNT]; Loading Loading @@ -303,30 +307,6 @@ static inline int sde_crtc_mixer_width(struct sde_crtc *sde_crtc, mode->hdisplay / CRTC_DUAL_MIXERS : mode->hdisplay; } static inline uint32_t get_crtc_split_width(struct drm_crtc *crtc) { struct drm_display_mode *mode; struct sde_crtc *sde_crtc; if (!crtc || !crtc->state) return 0; sde_crtc = to_sde_crtc(crtc); mode = &crtc->state->adjusted_mode; return sde_crtc_mixer_width(sde_crtc, mode); } static inline uint32_t get_crtc_mixer_height(struct drm_crtc *crtc) { struct drm_display_mode *mode; if (!crtc || !crtc->state) return 0; mode = &crtc->state->adjusted_mode; return mode->vdisplay; } /** * sde_crtc_vblank - enable or disable vblanks for this crtc * @crtc: Pointer to drm crtc object Loading Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +118 −92 Original line number Diff line number Diff line Loading @@ -602,10 +602,9 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer, struct sde_hw_dim_layer *dim_layer) { struct sde_crtc_state *cstate; struct sde_hw_mixer *lm; struct sde_rect mixer_rect; struct sde_hw_dim_layer split_dim_layer; u32 mixer_width, mixer_height; int i; if (!dim_layer->rect.w || !dim_layer->rect.h) { Loading @@ -613,9 +612,7 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, return; } mixer_width = get_crtc_split_width(crtc); mixer_height = get_crtc_mixer_height(crtc); mixer_rect = (struct sde_rect) {0, 0, mixer_width, mixer_height}; cstate = to_sde_crtc_state(crtc->state); split_dim_layer.stage = dim_layer->stage; split_dim_layer.color_fill = dim_layer->color_fill; Loading @@ -626,17 +623,15 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, */ for (i = 0; i < sde_crtc->num_mixers; i++) { split_dim_layer.flags = dim_layer->flags; mixer_rect.x = i * mixer_width; sde_kms_rect_intersect(&mixer_rect, &dim_layer->rect, sde_kms_rect_intersect(&cstate->lm_bounds[i], &dim_layer->rect, &split_dim_layer.rect); if (!split_dim_layer.rect.w && !split_dim_layer.rect.h) { if (sde_kms_rect_is_null(&split_dim_layer.rect)) { /* * no extra programming required for non-intersecting * layer mixers with INCLUSIVE dim layer */ if (split_dim_layer.flags & SDE_DRM_DIM_LAYER_INCLUSIVE) if (split_dim_layer.flags & SDE_DRM_DIM_LAYER_INCLUSIVE) continue; /* Loading @@ -646,12 +641,13 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, */ split_dim_layer.flags &= ~SDE_DRM_DIM_LAYER_EXCLUSIVE; split_dim_layer.flags |= SDE_DRM_DIM_LAYER_INCLUSIVE; split_dim_layer.rect = (struct sde_rect) {0, 0, mixer_width, mixer_height}; memcpy(&split_dim_layer.rect, &cstate->lm_bounds[i], sizeof(split_dim_layer.rect)); } else { split_dim_layer.rect.x = split_dim_layer.rect.x - (i * mixer_width); split_dim_layer.rect.x = split_dim_layer.rect.x - cstate->lm_bounds[i].w; } lm = mixer[i].hw_lm; Loading @@ -660,6 +656,32 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, } } static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; struct sde_crtc_state *crtc_state; int lm_idx, lm_horiz_position; sde_crtc = to_sde_crtc(crtc); crtc_state = to_sde_crtc_state(crtc->state); lm_horiz_position = 0; for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) { const struct sde_rect *lm_roi = &crtc_state->lm_bounds[lm_idx]; struct sde_hw_mixer *hw_lm = sde_crtc->mixers[lm_idx].hw_lm; struct sde_hw_mixer_cfg cfg; if (sde_kms_rect_is_null(lm_roi)) continue; cfg.out_width = lm_roi->w; cfg.out_height = lm_roi->h; cfg.right_mixer = lm_horiz_position++; cfg.flags = 0; hw_lm->ops.setup_mixer_out(hw_lm, &cfg); } } static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer) { Loading @@ -672,13 +694,12 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct sde_hw_ctl *ctl; struct sde_hw_mixer *lm; struct sde_hw_stage_cfg *stage_cfg; struct sde_rect plane_crtc_roi; u32 flush_mask = 0, crtc_split_width; uint32_t lm_idx = LEFT_MIXER, idx; u32 flush_mask = 0; uint32_t lm_idx = LEFT_MIXER, stage_idx; bool bg_alpha_enable[CRTC_DUAL_MIXERS] = {false}; bool lm_right = false; int left_crtc_zpos_cnt[SDE_STAGE_MAX + 1] = {0}; int right_crtc_zpos_cnt[SDE_STAGE_MAX + 1] = {0}; int zpos_cnt[CRTC_DUAL_MIXERS][SDE_STAGE_MAX + 1] = { {0} }; int i; bool sbuf_mode = false; u32 prefill = 0; Loading @@ -691,13 +712,18 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, ctl = mixer->hw_ctl; lm = mixer->hw_lm; stage_cfg = &sde_crtc->stage_cfg; crtc_split_width = get_crtc_split_width(crtc); cstate = to_sde_crtc_state(crtc->state); drm_atomic_crtc_for_each_plane(plane, crtc) { state = plane->state; if (!state) continue; plane_crtc_roi.x = state->crtc_x; plane_crtc_roi.y = state->crtc_y; plane_crtc_roi.w = state->crtc_w; plane_crtc_roi.h = state->crtc_h; pstate = to_sde_plane_state(state); fb = state->fb; Loading @@ -706,25 +732,6 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, sde_plane_get_ctl_flush(plane, ctl, &flush_mask); /* always stage plane on either left or right lm */ if (state->crtc_x >= crtc_split_width) { lm_idx = RIGHT_MIXER; idx = right_crtc_zpos_cnt[pstate->stage]++; } else { lm_idx = LEFT_MIXER; idx = left_crtc_zpos_cnt[pstate->stage]++; } /* stage plane on right LM if it crosses the boundary */ lm_right = (lm_idx == LEFT_MIXER) && (state->crtc_x + state->crtc_w > crtc_split_width); stage_cfg->stage[lm_idx][pstate->stage][idx] = sde_plane_pipe(plane); stage_cfg->multirect_index [lm_idx][pstate->stage][idx] = pstate->multirect_index; mixer[lm_idx].flush_mask |= flush_mask; SDE_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n", crtc->base.id, Loading @@ -738,47 +745,46 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, SDE_EVT32(DRMID(plane), state->src_x, state->src_y, state->src_w >> 16, state->src_h >> 16, state->crtc_x, state->crtc_y, state->crtc_w, state->crtc_h); SDE_EVT32(DRMID(plane), DRMID(crtc), lm_idx, lm_right, pstate->stage, pstate->multirect_index, pstate->multirect_mode, format->base.pixel_format, fb ? fb->modifier[0] : 0); /* blend config update */ if (pstate->stage != SDE_STAGE_BASE) { _sde_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format); for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) { struct sde_rect intersect; if (bg_alpha_enable[lm_idx] && !format->alpha_enable) mixer[lm_idx].mixer_op_mode = 0; else mixer[lm_idx].mixer_op_mode |= 1 << pstate->stage; } else if (format->alpha_enable) { bg_alpha_enable[lm_idx] = true; } /* skip if the roi doesn't fall within LM's bounds */ sde_kms_rect_intersect(&plane_crtc_roi, &cstate->lm_bounds[lm_idx], &intersect); if (sde_kms_rect_is_null(&intersect)) continue; if (lm_right) { idx = right_crtc_zpos_cnt[pstate->stage]++; stage_cfg->stage[RIGHT_MIXER][pstate->stage][idx] = stage_idx = zpos_cnt[lm_idx][pstate->stage]++; stage_cfg->stage[lm_idx][pstate->stage][stage_idx] = sde_plane_pipe(plane); stage_cfg->multirect_index [RIGHT_MIXER][pstate->stage][idx] = [lm_idx][pstate->stage][stage_idx] = pstate->multirect_index; mixer[RIGHT_MIXER].flush_mask |= flush_mask; mixer[lm_idx].flush_mask |= flush_mask; SDE_EVT32(DRMID(plane), DRMID(crtc), lm_idx, stage_idx, pstate->stage, pstate->multirect_index, pstate->multirect_mode, format->base.pixel_format, fb ? fb->modifier[0] : 0); /* blend config update */ if (pstate->stage != SDE_STAGE_BASE) { _sde_crtc_setup_blend_cfg(mixer + RIGHT_MIXER, _sde_crtc_setup_blend_cfg(mixer + lm_idx, pstate, format); if (bg_alpha_enable[RIGHT_MIXER] && if (bg_alpha_enable[lm_idx] && !format->alpha_enable) mixer[RIGHT_MIXER].mixer_op_mode = 0; mixer[lm_idx].mixer_op_mode = 0; else mixer[RIGHT_MIXER].mixer_op_mode |= mixer[lm_idx].mixer_op_mode |= 1 << pstate->stage; } else if (format->alpha_enable) { bg_alpha_enable[RIGHT_MIXER] = true; bg_alpha_enable[lm_idx] = true; } } } Loading @@ -804,6 +810,8 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, ctl->ops.setup_sbuf_cfg(ctl, &cstate->sbuf_cfg); } _sde_crtc_program_lm_output_roi(crtc); } /** Loading Loading @@ -1296,9 +1304,44 @@ static void _sde_crtc_setup_mixers(struct drm_crtc *crtc) _sde_crtc_setup_mixer_for_encoder(crtc, enc); } mutex_unlock(&sde_crtc->crtc_lock); } static void _sde_crtc_setup_lm_bounds(struct drm_crtc *crtc, struct drm_crtc_state *state) { struct sde_crtc *sde_crtc; struct sde_crtc_state *cstate; struct drm_display_mode *adj_mode; u32 crtc_split_width; int i; if (!crtc || !state) { SDE_ERROR("invalid args\n"); return; } sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(state); adj_mode = &state->adjusted_mode; crtc_split_width = sde_crtc_mixer_width(sde_crtc, adj_mode); for (i = 0; i < sde_crtc->num_mixers; i++) { struct sde_rect *lm_bound = &cstate->lm_bounds[i]; lm_bound->x = crtc_split_width * i; lm_bound->y = 0; lm_bound->w = crtc_split_width; lm_bound->h = adj_mode->vdisplay; SDE_EVT32(DRMID(crtc), i, lm_bound->x, lm_bound->y, lm_bound->w, lm_bound->h); } drm_mode_debug_printmodeline(adj_mode); } static void sde_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { Loading Loading @@ -1326,6 +1369,8 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, if (!sde_crtc->num_mixers) _sde_crtc_setup_mixers(crtc); _sde_crtc_setup_lm_bounds(crtc, crtc->state); if (sde_crtc->event) { WARN_ON(sde_crtc->event); } else { Loading Loading @@ -1776,13 +1821,10 @@ static void sde_crtc_disable(struct drm_crtc *crtc) static void sde_crtc_enable(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; struct sde_crtc_mixer *mixer; struct sde_hw_mixer *lm; struct drm_display_mode *mode; struct drm_encoder *encoder; unsigned long flags; struct sde_crtc_irq_info *node = NULL; int i, ret; int ret; if (!crtc) { SDE_ERROR("invalid crtc\n"); Loading @@ -1791,16 +1833,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc) SDE_DEBUG("crtc%d\n", crtc->base.id); SDE_EVT32(DRMID(crtc)); sde_crtc = to_sde_crtc(crtc); mixer = sde_crtc->mixers; if (WARN_ON(!crtc->state)) return; mode = &crtc->state->adjusted_mode; drm_mode_debug_printmodeline(mode); drm_for_each_encoder(encoder, crtc->dev) { if (encoder->crtc != crtc) Loading @@ -1809,15 +1842,6 @@ static void sde_crtc_enable(struct drm_crtc *crtc) sde_crtc_frame_event_cb, (void *)crtc); } for (i = 0; i < sde_crtc->num_mixers; i++) { lm = mixer[i].hw_lm; lm->cfg.out_width = sde_crtc_mixer_width(sde_crtc, mode); lm->cfg.out_height = mode->vdisplay; lm->cfg.right_mixer = (i == 0) ? false : true; lm->cfg.flags = 0; lm->ops.setup_mixer_out(lm, &lm->cfg); } spin_lock_irqsave(&sde_crtc->spin_lock, flags); list_for_each_entry(node, &sde_crtc->user_event_list, list) { ret = 0; Loading Loading @@ -1894,6 +1918,8 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, mixer_width = sde_crtc_mixer_width(sde_crtc, mode); _sde_crtc_setup_lm_bounds(crtc, state); /* get plane state for all drm planes associated with crtc state */ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { if (IS_ERR_OR_NULL(pstate)) { Loading
drivers/gpu/drm/msm/sde/sde_crtc.h +5 −25 Original line number Diff line number Diff line Loading @@ -108,7 +108,7 @@ struct sde_crtc_event { * @name : ASCII description of this crtc * @num_ctls : Number of ctl paths in use * @num_mixers : Number of mixers in use * @mixer : List of active mixers * @mixers : List of active mixers * @event : Pointer to last received drm vblank event. If there is a * pending vblank event, this will be non-null. * @vsync_count : Running count of received vsync events Loading Loading @@ -248,6 +248,8 @@ struct sde_crtc_respool { * @num_connectors: Number of associated drm connectors * @intf_mode : Interface mode of the primary connector * @rsc_client : sde rsc client when mode is valid * @lm_bounds : LM boundaries based on current mode full resolution, no ROI. * Origin top left of CRTC. * @property_values: Current crtc property values * @input_fence_timeout_ns : Cached input fence timeout, in ns * @property_blobs: Reference pointers for blob properties Loading @@ -267,6 +269,8 @@ struct sde_crtc_state { struct sde_rsc_client *rsc_client; bool rsc_update; struct sde_rect lm_bounds[CRTC_DUAL_MIXERS]; uint64_t property_values[CRTC_PROP_COUNT]; uint64_t input_fence_timeout_ns; struct drm_property_blob *property_blobs[CRTC_PROP_COUNT]; Loading Loading @@ -303,30 +307,6 @@ static inline int sde_crtc_mixer_width(struct sde_crtc *sde_crtc, mode->hdisplay / CRTC_DUAL_MIXERS : mode->hdisplay; } static inline uint32_t get_crtc_split_width(struct drm_crtc *crtc) { struct drm_display_mode *mode; struct sde_crtc *sde_crtc; if (!crtc || !crtc->state) return 0; sde_crtc = to_sde_crtc(crtc); mode = &crtc->state->adjusted_mode; return sde_crtc_mixer_width(sde_crtc, mode); } static inline uint32_t get_crtc_mixer_height(struct drm_crtc *crtc) { struct drm_display_mode *mode; if (!crtc || !crtc->state) return 0; mode = &crtc->state->adjusted_mode; return mode->vdisplay; } /** * sde_crtc_vblank - enable or disable vblanks for this crtc * @crtc: Pointer to drm crtc object Loading