Loading msm/sde/sde_connector.c +3 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ Loading Loading @@ -2571,6 +2571,8 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn, continue; } sde_kms_info_add_keyint(info, "has_cwb_crop", sde_kms->catalog->has_cwb_crop); sde_kms_info_add_keyint(info, "mdp_transfer_time_us", mode_info.mdp_transfer_time_us); Loading msm/sde/sde_encoder_phys_wb.c +59 −19 Original line number Diff line number Diff line Loading @@ -314,6 +314,8 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, struct sde_hw_wb_cfg *wb_cfg; struct sde_hw_wb_cdp_cfg *cdp_cfg; const struct msm_format *format; struct sde_crtc_state *cstate; struct sde_rect pu_roi = {0,}; int ret; struct msm_gem_address_space *aspace; u32 fb_mode; Loading @@ -324,6 +326,8 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, return; } cstate = to_sde_crtc_state(wb_enc->crtc->state); hw_wb = wb_enc->hw_wb; wb_cfg = &wb_enc->wb_cfg; cdp_cfg = &wb_enc->cdp_cfg; Loading Loading @@ -373,7 +377,6 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, } wb_cfg->roi = *wb_roi; if (hw_wb->caps->features & BIT(SDE_WB_XY_ROI_OFFSET)) { ret = sde_format_populate_layout(aspace, fb, &wb_cfg->dest); if (ret) { SDE_DEBUG("failed to populate layout %d\n", ret); Loading @@ -382,13 +385,25 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, wb_cfg->dest.width = fb->width; wb_cfg->dest.height = fb->height; wb_cfg->dest.num_planes = wb_cfg->dest.format->num_planes; if (hw_wb->ops.setup_crop && phys_enc->in_clone_mode) { wb_cfg->crop.x = wb_cfg->roi.x; wb_cfg->crop.y = wb_cfg->roi.y; if (cstate->user_roi_list.num_rects) { sde_kms_rect_merge_rectangles(&cstate->user_roi_list, &pu_roi); if ((wb_cfg->roi.w != pu_roi.w) || (wb_cfg->roi.h != pu_roi.h)) { /* offset cropping region to PU region */ wb_cfg->crop.x = wb_cfg->crop.x - pu_roi.x; wb_cfg->crop.y = wb_cfg->crop.y - pu_roi.y; hw_wb->ops.setup_crop(hw_wb, wb_cfg, true); } } else if ((wb_cfg->roi.w != wb_cfg->dest.width) || (wb_cfg->roi.h != wb_cfg->dest.height)) { hw_wb->ops.setup_crop(hw_wb, wb_cfg, true); } else { ret = sde_format_populate_layout_with_roi(aspace, fb, wb_roi, &wb_cfg->dest); if (ret) { /* this error should be detected during atomic_check */ SDE_DEBUG("failed to populate layout %d\n", ret); return; hw_wb->ops.setup_crop(hw_wb, wb_cfg, false); } } Loading Loading @@ -613,6 +628,7 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, struct sde_rect pu_roi = {0,}; int out_width = 0, out_height = 0; int ds_srcw = 0, ds_srch = 0, ds_outw = 0, ds_outh = 0; const struct sde_format *fmt; int data_pt; int ds_in_use = false; int i = 0; Loading @@ -624,6 +640,12 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, return 0; } fmt = sde_get_sde_format_ext(fb->format->format, fb->modifier); if (!fmt) { SDE_ERROR("unsupported output pixel format:%x\n", fb->format->format); return -EINVAL; } ret = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi); if (ret) { SDE_ERROR("failed to get roi %d\n", ret); Loading Loading @@ -664,6 +686,10 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, * 2.2) DSPP Tap point: same as No DS case * a) wb-roi should be inside FB * b) mode resolution & wb-roi should be same * 3) Partial Update case: additional stride check * a) cwb roi should be inside PU region or FB * b) cropping is only allowed for fully sampled data * c) add check for stride and QOS setting by 256B */ if (ds_in_use && data_pt == CAPTURE_DSPP_OUT) { out_width = ds_outw; Loading @@ -676,9 +702,23 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, out_height = mode->vdisplay; } if ((wb_roi.w != out_width) || (wb_roi.h != out_height)) { if (SDE_FORMAT_IS_YUV(fmt) && ((wb_roi.w != out_width) || (wb_roi.h != out_height))) { SDE_ERROR("invalid wb roi[%dx%d] with ds_use:%d out[%dx%d] fmt:%x\n", wb_roi.w, wb_roi.h, ds_in_use, out_width, out_height, fmt->base.pixel_format); return -EINVAL; } if ((wb_roi.w > out_width) || (wb_roi.h > out_height)) { SDE_ERROR("invalid wb roi[%dx%d] with ds_use:%d out[%dx%d]\n", wb_roi.w, wb_roi.h, out_width, out_height); wb_roi.w, wb_roi.h, ds_in_use, out_width, out_height); return -EINVAL; } if (((wb_roi.w < out_width) || (wb_roi.h < out_height)) && (wb_roi.w * wb_roi.h * fmt->bpp) % 256) { SDE_ERROR("invalid stride w = %d h = %d bpp =%d out_width = %d, out_height = %d\n", wb_roi.w, wb_roi.h, fmt->bpp, out_width, out_height); return -EINVAL; } Loading @@ -693,7 +733,7 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, /* validate wb roi against pu rect */ if (cstate->user_roi_list.num_rects) { sde_kms_rect_merge_rectangles(&cstate->user_roi_list, &pu_roi); if (wb_roi.w != pu_roi.w || wb_roi.h != pu_roi.h) { if (wb_roi.w > pu_roi.w || wb_roi.h > pu_roi.h) { SDE_ERROR("invalid wb roi with pu [%dx%d vs %dx%d]\n", wb_roi.w, wb_roi.h, pu_roi.w, pu_roi.h); return -EINVAL; Loading msm/sde/sde_formats.c +1 −64 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. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ Loading Loading @@ -1112,69 +1112,6 @@ int sde_format_populate_layout( return ret; } static void _sde_format_calc_offset_linear(struct sde_hw_fmt_layout *source, u32 x, u32 y) { if ((x == 0) && (y == 0)) return; source->plane_addr[0] += y * source->plane_pitch[0]; if (source->num_planes == 1) { source->plane_addr[0] += x * source->format->bpp; } else { uint32_t xoff, yoff; uint32_t v_subsample = 1; uint32_t h_subsample = 1; _sde_get_v_h_subsample_rate(source->format->chroma_sample, &v_subsample, &h_subsample); xoff = x / h_subsample; yoff = y / v_subsample; source->plane_addr[0] += x; source->plane_addr[1] += xoff + (yoff * source->plane_pitch[1]); if (source->num_planes == 2) /* pseudo planar */ source->plane_addr[1] += xoff; else /* planar */ source->plane_addr[2] += xoff + (yoff * source->plane_pitch[2]); } } int sde_format_populate_layout_with_roi( struct msm_gem_address_space *aspace, struct drm_framebuffer *fb, struct sde_rect *roi, struct sde_hw_fmt_layout *layout) { int ret; ret = sde_format_populate_layout(aspace, fb, layout); if (ret || !roi) return ret; if (!roi->w || !roi->h || (roi->x + roi->w > fb->width) || (roi->y + roi->h > fb->height)) { DRM_ERROR("invalid roi=[%d,%d,%d,%d], fb=[%u,%u]\n", roi->x, roi->y, roi->w, roi->h, fb->width, fb->height); ret = -EINVAL; } else if (SDE_FORMAT_IS_LINEAR(layout->format)) { _sde_format_calc_offset_linear(layout, roi->x, roi->y); layout->width = roi->w; layout->height = roi->h; } else if (roi->x || roi->y || (roi->w != fb->width) || (roi->h != fb->height)) { DRM_ERROR("non-linear layout with roi not supported\n"); ret = -EINVAL; } return ret; } int sde_format_check_modified_format( const struct msm_kms *kms, const struct msm_format *msm_fmt, Loading msm/sde/sde_formats.h +1 −17 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_FORMATS_H Loading Loading @@ -108,22 +108,6 @@ int sde_format_populate_layout( struct drm_framebuffer *fb, struct sde_hw_fmt_layout *fmtl); /** * sde_format_populate_layout_with_roi - populate the given format layout * based on mmu, fb, roi, and format found in the fb * @aspace: address space pointer * @fb: framebuffer pointer * @roi: region of interest (optional) * @fmtl: format layout structure to populate * * Return: error code on failure, 0 on success */ int sde_format_populate_layout_with_roi( struct msm_gem_address_space *aspace, struct drm_framebuffer *fb, struct sde_rect *roi, struct sde_hw_fmt_layout *fmtl); /** * sde_format_get_framebuffer_size - get framebuffer memory size * @format: DRM pixel format Loading msm/sde/sde_hw_catalog.c +4 −0 Original line number Diff line number Diff line Loading @@ -2344,6 +2344,9 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) if (sde_cfg->has_wb_ubwc) set_bit(SDE_WB_UBWC, &wb->features); if (sde_cfg->has_cwb_crop) set_bit(SDE_WB_CROP, &wb->features); set_bit(SDE_WB_XY_ROI_OFFSET, &wb->features); if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) Loading Loading @@ -4809,6 +4812,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->syscache_supported = true; } else if (IS_YUPIK_TARGET(hw_rev)) { sde_cfg->has_cwb_support = true; sde_cfg->has_cwb_crop = true; sde_cfg->has_qsync = true; sde_cfg->perf.min_prefill_lines = 40; sde_cfg->vbif_qos_nlvl = 8; Loading Loading
msm/sde/sde_connector.c +3 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ Loading Loading @@ -2571,6 +2571,8 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn, continue; } sde_kms_info_add_keyint(info, "has_cwb_crop", sde_kms->catalog->has_cwb_crop); sde_kms_info_add_keyint(info, "mdp_transfer_time_us", mode_info.mdp_transfer_time_us); Loading
msm/sde/sde_encoder_phys_wb.c +59 −19 Original line number Diff line number Diff line Loading @@ -314,6 +314,8 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, struct sde_hw_wb_cfg *wb_cfg; struct sde_hw_wb_cdp_cfg *cdp_cfg; const struct msm_format *format; struct sde_crtc_state *cstate; struct sde_rect pu_roi = {0,}; int ret; struct msm_gem_address_space *aspace; u32 fb_mode; Loading @@ -324,6 +326,8 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, return; } cstate = to_sde_crtc_state(wb_enc->crtc->state); hw_wb = wb_enc->hw_wb; wb_cfg = &wb_enc->wb_cfg; cdp_cfg = &wb_enc->cdp_cfg; Loading Loading @@ -373,7 +377,6 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, } wb_cfg->roi = *wb_roi; if (hw_wb->caps->features & BIT(SDE_WB_XY_ROI_OFFSET)) { ret = sde_format_populate_layout(aspace, fb, &wb_cfg->dest); if (ret) { SDE_DEBUG("failed to populate layout %d\n", ret); Loading @@ -382,13 +385,25 @@ static void sde_encoder_phys_wb_setup_fb(struct sde_encoder_phys *phys_enc, wb_cfg->dest.width = fb->width; wb_cfg->dest.height = fb->height; wb_cfg->dest.num_planes = wb_cfg->dest.format->num_planes; if (hw_wb->ops.setup_crop && phys_enc->in_clone_mode) { wb_cfg->crop.x = wb_cfg->roi.x; wb_cfg->crop.y = wb_cfg->roi.y; if (cstate->user_roi_list.num_rects) { sde_kms_rect_merge_rectangles(&cstate->user_roi_list, &pu_roi); if ((wb_cfg->roi.w != pu_roi.w) || (wb_cfg->roi.h != pu_roi.h)) { /* offset cropping region to PU region */ wb_cfg->crop.x = wb_cfg->crop.x - pu_roi.x; wb_cfg->crop.y = wb_cfg->crop.y - pu_roi.y; hw_wb->ops.setup_crop(hw_wb, wb_cfg, true); } } else if ((wb_cfg->roi.w != wb_cfg->dest.width) || (wb_cfg->roi.h != wb_cfg->dest.height)) { hw_wb->ops.setup_crop(hw_wb, wb_cfg, true); } else { ret = sde_format_populate_layout_with_roi(aspace, fb, wb_roi, &wb_cfg->dest); if (ret) { /* this error should be detected during atomic_check */ SDE_DEBUG("failed to populate layout %d\n", ret); return; hw_wb->ops.setup_crop(hw_wb, wb_cfg, false); } } Loading Loading @@ -613,6 +628,7 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, struct sde_rect pu_roi = {0,}; int out_width = 0, out_height = 0; int ds_srcw = 0, ds_srch = 0, ds_outw = 0, ds_outh = 0; const struct sde_format *fmt; int data_pt; int ds_in_use = false; int i = 0; Loading @@ -624,6 +640,12 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, return 0; } fmt = sde_get_sde_format_ext(fb->format->format, fb->modifier); if (!fmt) { SDE_ERROR("unsupported output pixel format:%x\n", fb->format->format); return -EINVAL; } ret = sde_wb_connector_state_get_output_roi(conn_state, &wb_roi); if (ret) { SDE_ERROR("failed to get roi %d\n", ret); Loading Loading @@ -664,6 +686,10 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, * 2.2) DSPP Tap point: same as No DS case * a) wb-roi should be inside FB * b) mode resolution & wb-roi should be same * 3) Partial Update case: additional stride check * a) cwb roi should be inside PU region or FB * b) cropping is only allowed for fully sampled data * c) add check for stride and QOS setting by 256B */ if (ds_in_use && data_pt == CAPTURE_DSPP_OUT) { out_width = ds_outw; Loading @@ -676,9 +702,23 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, out_height = mode->vdisplay; } if ((wb_roi.w != out_width) || (wb_roi.h != out_height)) { if (SDE_FORMAT_IS_YUV(fmt) && ((wb_roi.w != out_width) || (wb_roi.h != out_height))) { SDE_ERROR("invalid wb roi[%dx%d] with ds_use:%d out[%dx%d] fmt:%x\n", wb_roi.w, wb_roi.h, ds_in_use, out_width, out_height, fmt->base.pixel_format); return -EINVAL; } if ((wb_roi.w > out_width) || (wb_roi.h > out_height)) { SDE_ERROR("invalid wb roi[%dx%d] with ds_use:%d out[%dx%d]\n", wb_roi.w, wb_roi.h, out_width, out_height); wb_roi.w, wb_roi.h, ds_in_use, out_width, out_height); return -EINVAL; } if (((wb_roi.w < out_width) || (wb_roi.h < out_height)) && (wb_roi.w * wb_roi.h * fmt->bpp) % 256) { SDE_ERROR("invalid stride w = %d h = %d bpp =%d out_width = %d, out_height = %d\n", wb_roi.w, wb_roi.h, fmt->bpp, out_width, out_height); return -EINVAL; } Loading @@ -693,7 +733,7 @@ static int _sde_enc_phys_wb_validate_cwb(struct sde_encoder_phys *phys_enc, /* validate wb roi against pu rect */ if (cstate->user_roi_list.num_rects) { sde_kms_rect_merge_rectangles(&cstate->user_roi_list, &pu_roi); if (wb_roi.w != pu_roi.w || wb_roi.h != pu_roi.h) { if (wb_roi.w > pu_roi.w || wb_roi.h > pu_roi.h) { SDE_ERROR("invalid wb roi with pu [%dx%d vs %dx%d]\n", wb_roi.w, wb_roi.h, pu_roi.w, pu_roi.h); return -EINVAL; Loading
msm/sde/sde_formats.c +1 −64 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. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ Loading Loading @@ -1112,69 +1112,6 @@ int sde_format_populate_layout( return ret; } static void _sde_format_calc_offset_linear(struct sde_hw_fmt_layout *source, u32 x, u32 y) { if ((x == 0) && (y == 0)) return; source->plane_addr[0] += y * source->plane_pitch[0]; if (source->num_planes == 1) { source->plane_addr[0] += x * source->format->bpp; } else { uint32_t xoff, yoff; uint32_t v_subsample = 1; uint32_t h_subsample = 1; _sde_get_v_h_subsample_rate(source->format->chroma_sample, &v_subsample, &h_subsample); xoff = x / h_subsample; yoff = y / v_subsample; source->plane_addr[0] += x; source->plane_addr[1] += xoff + (yoff * source->plane_pitch[1]); if (source->num_planes == 2) /* pseudo planar */ source->plane_addr[1] += xoff; else /* planar */ source->plane_addr[2] += xoff + (yoff * source->plane_pitch[2]); } } int sde_format_populate_layout_with_roi( struct msm_gem_address_space *aspace, struct drm_framebuffer *fb, struct sde_rect *roi, struct sde_hw_fmt_layout *layout) { int ret; ret = sde_format_populate_layout(aspace, fb, layout); if (ret || !roi) return ret; if (!roi->w || !roi->h || (roi->x + roi->w > fb->width) || (roi->y + roi->h > fb->height)) { DRM_ERROR("invalid roi=[%d,%d,%d,%d], fb=[%u,%u]\n", roi->x, roi->y, roi->w, roi->h, fb->width, fb->height); ret = -EINVAL; } else if (SDE_FORMAT_IS_LINEAR(layout->format)) { _sde_format_calc_offset_linear(layout, roi->x, roi->y); layout->width = roi->w; layout->height = roi->h; } else if (roi->x || roi->y || (roi->w != fb->width) || (roi->h != fb->height)) { DRM_ERROR("non-linear layout with roi not supported\n"); ret = -EINVAL; } return ret; } int sde_format_check_modified_format( const struct msm_kms *kms, const struct msm_format *msm_fmt, Loading
msm/sde/sde_formats.h +1 −17 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_FORMATS_H Loading Loading @@ -108,22 +108,6 @@ int sde_format_populate_layout( struct drm_framebuffer *fb, struct sde_hw_fmt_layout *fmtl); /** * sde_format_populate_layout_with_roi - populate the given format layout * based on mmu, fb, roi, and format found in the fb * @aspace: address space pointer * @fb: framebuffer pointer * @roi: region of interest (optional) * @fmtl: format layout structure to populate * * Return: error code on failure, 0 on success */ int sde_format_populate_layout_with_roi( struct msm_gem_address_space *aspace, struct drm_framebuffer *fb, struct sde_rect *roi, struct sde_hw_fmt_layout *fmtl); /** * sde_format_get_framebuffer_size - get framebuffer memory size * @format: DRM pixel format Loading
msm/sde/sde_hw_catalog.c +4 −0 Original line number Diff line number Diff line Loading @@ -2344,6 +2344,9 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) if (sde_cfg->has_wb_ubwc) set_bit(SDE_WB_UBWC, &wb->features); if (sde_cfg->has_cwb_crop) set_bit(SDE_WB_CROP, &wb->features); set_bit(SDE_WB_XY_ROI_OFFSET, &wb->features); if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) Loading Loading @@ -4809,6 +4812,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->syscache_supported = true; } else if (IS_YUPIK_TARGET(hw_rev)) { sde_cfg->has_cwb_support = true; sde_cfg->has_cwb_crop = true; sde_cfg->has_qsync = true; sde_cfg->perf.min_prefill_lines = 40; sde_cfg->vbif_qos_nlvl = 8; Loading