Commit 22aa5614 authored by Yongqiang Sun's avatar Yongqiang Sun Committed by Alex Deucher
Browse files

drm/amd/display: Refactor surface flip programming



Rework surface programming for RN to separate preparing parameters and
register programming.

Signed-off-by: default avatarYongqiang Sun <yongqiang.sun@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c1e34175
Loading
Loading
Loading
Loading
+118 −206
Original line number Diff line number Diff line
@@ -690,28 +690,114 @@ void hubp21_validate_dml_output(struct hubp *hubp,
				dml_dlg_attr->refcyc_per_meta_chunk_flip_l, dlg_attr.refcyc_per_meta_chunk_flip_l);
}

static void program_video_progressive_dmcub(
		struct dc_dmub_srv *dmcub,
static void program_surface_flip_and_addr(struct hubp *hubp, struct dmub_rb_cmd_flip *surface_flip)
{
	struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp);

	REG_UPDATE_3(DCSURF_FLIP_CONTROL,
					SURFACE_FLIP_TYPE, surface_flip->flip.flip_params.immediate,
					SURFACE_FLIP_MODE_FOR_STEREOSYNC, surface_flip->flip.flip_params.grph_stereo,
					SURFACE_FLIP_IN_STEREOSYNC, surface_flip->flip.flip_params.grph_stereo);

	REG_UPDATE(VMID_SETTINGS_0,
				VMID, surface_flip->flip.flip_params.vmid);

	REG_UPDATE_8(DCSURF_SURFACE_CONTROL,
			PRIMARY_SURFACE_TMZ, surface_flip->flip.flip_params.tmz_surface,
			PRIMARY_SURFACE_TMZ_C, surface_flip->flip.flip_params.tmz_surface,
			PRIMARY_META_SURFACE_TMZ, surface_flip->flip.flip_params.tmz_surface,
			PRIMARY_META_SURFACE_TMZ_C, surface_flip->flip.flip_params.tmz_surface,
			SECONDARY_SURFACE_TMZ, surface_flip->flip.flip_params.tmz_surface,
			SECONDARY_SURFACE_TMZ_C, surface_flip->flip.flip_params.tmz_surface,
			SECONDARY_META_SURFACE_TMZ, surface_flip->flip.flip_params.tmz_surface,
			SECONDARY_META_SURFACE_TMZ_C, surface_flip->flip.flip_params.tmz_surface);

	REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0,
			PRIMARY_META_SURFACE_ADDRESS_HIGH_C,
			 surface_flip->flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C);

	REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0,
			PRIMARY_META_SURFACE_ADDRESS_C,
			surface_flip->flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS_C);

	REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
			PRIMARY_META_SURFACE_ADDRESS_HIGH,
			surface_flip->flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH);

	REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
			PRIMARY_META_SURFACE_ADDRESS,
			surface_flip->flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS);

	REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0,
			SECONDARY_META_SURFACE_ADDRESS_HIGH,
			surface_flip->flip.DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH);

	REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0,
			SECONDARY_META_SURFACE_ADDRESS,
			surface_flip->flip.DCSURF_SECONDARY_META_SURFACE_ADDRESS);


	REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
			SECONDARY_SURFACE_ADDRESS_HIGH,
			surface_flip->flip.DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH);

	REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0,
			SECONDARY_SURFACE_ADDRESS,
			surface_flip->flip.DCSURF_SECONDARY_SURFACE_ADDRESS);


	REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0,
			PRIMARY_SURFACE_ADDRESS_HIGH_C,
			surface_flip->flip.DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C);

	REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
			PRIMARY_SURFACE_ADDRESS_C,
			surface_flip->flip.DCSURF_PRIMARY_SURFACE_ADDRESS_C);

	REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
			PRIMARY_SURFACE_ADDRESS_HIGH,
			surface_flip->flip.DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH);

	REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
			PRIMARY_SURFACE_ADDRESS,
			surface_flip->flip.DCSURF_PRIMARY_SURFACE_ADDRESS);
}

void program_surface_flip_and_addr_dmcub(struct hubp *hubp, struct dmub_rb_cmd_flip *surface_flip)
{
	struct dc_dmub_srv *dmcub = hubp->ctx->dmub_srv;
	struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp);

	PERF_TRACE();  // TODO: remove after performance is stable.
	dc_dmub_srv_cmd_queue(dmcub, &surface_flip->header);
	PERF_TRACE();  // TODO: remove after performance is stable.
	dc_dmub_srv_cmd_execute(dmcub);
	PERF_TRACE();  // TODO: remove after performance is stable.
	dc_dmub_srv_wait_idle(dmcub);
	PERF_TRACE();  // TODO: remove after performance is stable.
}

bool hubp21_program_surface_flip_and_addr(
		struct hubp *hubp,
		const struct dc_plane_address *address,
		bool flip_immediate)
{
	struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp);
	struct dmub_rb_cmd_flip surface_flip = { 0 };
	bool grph_stereo = false;
	struct dc_debug_options *debug = &hubp->ctx->dc->debug;
	struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp);

	surface_flip.header.type = DMUB_CMD__SURFACE_FLIP;

	surface_flip.flip.addr_type = address->type;
	surface_flip.flip.immediate = flip_immediate;
	surface_flip.flip.vmid = address->vmid;

	surface_flip.flip.hubp_inst = hubp->inst;
	surface_flip.flip.tmz_surface = address->tmz_surface;
	surface_flip.flip.flip_params.vmid = address->vmid;
	surface_flip.flip.flip_params.hubp_inst = hubp->inst;

	switch (address->type) {
	case PLN_ADDR_TYPE_GRAPHICS:
		if (address->grph.addr.quad_part == 0)
			return;
		if (address->grph.addr.quad_part == 0) {
			BREAK_TO_DEBUGGER();
			break;
		}

		if (address->grph.meta_addr.quad_part != 0) {
			surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS =
@@ -728,7 +814,7 @@ static void program_video_progressive_dmcub(
	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
		if (address->video_progressive.luma_addr.quad_part == 0
				|| address->video_progressive.chroma_addr.quad_part == 0)
			return;
			break;

		if (address->video_progressive.luma_meta_addr.quad_part != 0) {
			surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS =
@@ -747,19 +833,24 @@ static void program_video_progressive_dmcub(
		surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH =
				address->video_progressive.luma_addr.high_part;

		if (debug->nv12_iflip_vm_wa) {
			surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS_C =
					address->video_progressive.chroma_addr.low_part + hubp21->PLAT_54186_wa_chroma_addr_offset;
		} else
			surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS_C =
					address->video_progressive.chroma_addr.low_part;

		surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C =
				address->video_progressive.chroma_addr.high_part;

		break;
	case PLN_ADDR_TYPE_GRPH_STEREO:
		if (address->grph_stereo.left_addr.quad_part == 0)
			return;
			break;
		if (address->grph_stereo.right_addr.quad_part == 0)
			return;
			break;

		surface_flip.flip.grph_stereo = true;
		grph_stereo = true;

		if (address->grph_stereo.right_meta_addr.quad_part != 0) {
			surface_flip.flip.DCSURF_SECONDARY_META_SURFACE_ADDRESS =
@@ -786,200 +877,21 @@ static void program_video_progressive_dmcub(
				address->grph_stereo.right_addr.high_part;

		break;

	}

	PERF_TRACE();  // TODO: remove after performance is stable.
	dc_dmub_srv_cmd_queue(dmcub, &surface_flip.header);
	PERF_TRACE();  // TODO: remove after performance is stable.
	dc_dmub_srv_cmd_execute(dmcub);
	PERF_TRACE();  // TODO: remove after performance is stable.
	dc_dmub_srv_wait_idle(dmcub);
}

bool hubp21_program_surface_flip_and_addr(
	struct hubp *hubp,
	const struct dc_plane_address *address,
	bool flip_immediate)
{
	struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp);
	struct dc_debug_options *debug = &hubp->ctx->dc->debug;


	if (hubp->ctx->dc->debug.enable_dmcub_surface_flip) {
		program_video_progressive_dmcub(hubp->ctx->dmub_srv, hubp, address, flip_immediate);
		hubp->request_address = *address;
		return true;
	}

	//program flip type
	REG_UPDATE(DCSURF_FLIP_CONTROL,
			SURFACE_FLIP_TYPE, flip_immediate);

	// Program VMID reg
	REG_UPDATE(VMID_SETTINGS_0,
			VMID, address->vmid);

	if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) {
		REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x1);
		REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1);

	} else {
		// turn off stereo if not in stereo
		REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x0);
		REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x0);
	}



	/* HW automatically latch rest of address register on write to
	 * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used
	 *
	 * program high first and then the low addr, order matters!
	 */
	switch (address->type) {
	case PLN_ADDR_TYPE_GRAPHICS:
		/* DCN1.0 does not support const color
		 * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1
		 * base on address->grph.dcc_const_color
		 * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma
		 * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma
		 */

		if (address->grph.addr.quad_part == 0)
			break;

		REG_UPDATE_2(DCSURF_SURFACE_CONTROL,
				PRIMARY_SURFACE_TMZ, address->tmz_surface,
				PRIMARY_META_SURFACE_TMZ, address->tmz_surface);

		if (address->grph.meta_addr.quad_part != 0) {
			REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
					PRIMARY_META_SURFACE_ADDRESS_HIGH,
					address->grph.meta_addr.high_part);

			REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
					PRIMARY_META_SURFACE_ADDRESS,
					address->grph.meta_addr.low_part);
		}

		REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
				PRIMARY_SURFACE_ADDRESS_HIGH,
				address->grph.addr.high_part);

		REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
				PRIMARY_SURFACE_ADDRESS,
				address->grph.addr.low_part);
		break;
	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
		if (address->video_progressive.luma_addr.quad_part == 0
				|| address->video_progressive.chroma_addr.quad_part == 0)
			break;

		REG_UPDATE_4(DCSURF_SURFACE_CONTROL,
				PRIMARY_SURFACE_TMZ, address->tmz_surface,
				PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
				PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
				PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface);

		if (address->video_progressive.luma_meta_addr.quad_part != 0) {
			REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0,
					PRIMARY_META_SURFACE_ADDRESS_HIGH_C,
					address->video_progressive.chroma_meta_addr.high_part);

			REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0,
					PRIMARY_META_SURFACE_ADDRESS_C,
					address->video_progressive.chroma_meta_addr.low_part);

			REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
					PRIMARY_META_SURFACE_ADDRESS_HIGH,
					address->video_progressive.luma_meta_addr.high_part);

			REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
					PRIMARY_META_SURFACE_ADDRESS,
					address->video_progressive.luma_meta_addr.low_part);
		}

		REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0,
				PRIMARY_SURFACE_ADDRESS_HIGH_C,
				address->video_progressive.chroma_addr.high_part);

		if (debug->nv12_iflip_vm_wa) {
			REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
					PRIMARY_SURFACE_ADDRESS_C,
					address->video_progressive.chroma_addr.low_part + hubp21->PLAT_54186_wa_chroma_addr_offset);
		} else {
			REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
					PRIMARY_SURFACE_ADDRESS_C,
					address->video_progressive.chroma_addr.low_part);
		}

		REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
				PRIMARY_SURFACE_ADDRESS_HIGH,
				address->video_progressive.luma_addr.high_part);

		REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
				PRIMARY_SURFACE_ADDRESS,
				address->video_progressive.luma_addr.low_part);
		break;
	case PLN_ADDR_TYPE_GRPH_STEREO:
		if (address->grph_stereo.left_addr.quad_part == 0)
			break;
		if (address->grph_stereo.right_addr.quad_part == 0)
			break;

		REG_UPDATE_8(DCSURF_SURFACE_CONTROL,
				PRIMARY_SURFACE_TMZ, address->tmz_surface,
				PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
				PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
				PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface,
				SECONDARY_SURFACE_TMZ, address->tmz_surface,
				SECONDARY_SURFACE_TMZ_C, address->tmz_surface,
				SECONDARY_META_SURFACE_TMZ, address->tmz_surface,
				SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface);

		if (address->grph_stereo.right_meta_addr.quad_part != 0) {

			REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0,
					SECONDARY_META_SURFACE_ADDRESS_HIGH,
					address->grph_stereo.right_meta_addr.high_part);

			REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0,
					SECONDARY_META_SURFACE_ADDRESS,
					address->grph_stereo.right_meta_addr.low_part);
		}
		if (address->grph_stereo.left_meta_addr.quad_part != 0) {

			REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
					PRIMARY_META_SURFACE_ADDRESS_HIGH,
					address->grph_stereo.left_meta_addr.high_part);

			REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
					PRIMARY_META_SURFACE_ADDRESS,
					address->grph_stereo.left_meta_addr.low_part);
		}

		REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
				SECONDARY_SURFACE_ADDRESS_HIGH,
				address->grph_stereo.right_addr.high_part);

		REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0,
				SECONDARY_SURFACE_ADDRESS,
				address->grph_stereo.right_addr.low_part);

		REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
				PRIMARY_SURFACE_ADDRESS_HIGH,
				address->grph_stereo.left_addr.high_part);

		REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
				PRIMARY_SURFACE_ADDRESS,
				address->grph_stereo.left_addr.low_part);
		break;
	default:
		BREAK_TO_DEBUGGER();
		break;
	}

	surface_flip.flip.flip_params.vmid = address->vmid;
	surface_flip.flip.flip_params.grph_stereo = grph_stereo;
	surface_flip.flip.flip_params.tmz_surface = address->tmz_surface;
	surface_flip.flip.flip_params.immediate = flip_immediate;

	if (hubp->ctx->dc->debug.enable_dmcub_surface_flip)
		program_surface_flip_and_addr_dmcub(hubp, &surface_flip);
	else
		program_surface_flip_and_addr(hubp, &surface_flip);

	hubp->request_address = *address;

	return true;
+9 −7
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@
#include "dmub_cmd_dal.h"
#include "dmub_cmd_vbios.h"
#include "atomfirmware.h"
#include "dc_hw_types.h"

#define DMUB_RB_CMD_SIZE 64
#define DMUB_RB_MAX_ENTRY 128
#define DMUB_RB_SIZE (DMUB_RB_CMD_SIZE * DMUB_RB_MAX_ENTRY)
@@ -165,12 +165,14 @@ struct dmub_cmd_surface_flip {
	uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS;
	uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH;
	uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS;
	enum dc_plane_addr_type addr_type;
	uint8_t hubp_inst;
	bool tmz_surface;
	bool immediate;
	uint8_t vmid;
	bool grph_stereo;
	struct {
		uint8_t hubp_inst : 4;
		uint8_t tmz_surface : 1;
		uint8_t immediate :1;
		uint8_t vmid : 4;
		uint8_t grph_stereo : 1;
		uint32_t reserved : 21;
	} flip_params;
};

struct dmub_rb_cmd_flip {