Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 93e14373 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: sde: add support for CWB ROI cropping feature"

parents 025b38d4 dfae4043
Loading
Loading
Loading
Loading
+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__
@@ -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);

+59 −19
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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);
@@ -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);
		}
	}

@@ -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;
@@ -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);
@@ -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;
@@ -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;
	}

@@ -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;
+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__
@@ -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,
+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
@@ -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
+4 −0
Original line number Diff line number Diff line
@@ -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))
@@ -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