aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc
diff options
context:
space:
mode:
authorYongqiang Sun <yongqiang.sun@amd.com>2019-12-16 17:21:10 -0500
committerAlex Deucher <alexander.deucher@amd.com>2020-01-16 14:13:38 -0500
commit8c0192533c39660ae229d7b80adeeb3bc63a3eba (patch)
tree6360699620c47a88052a52aa6fa7ca5bff365e20 /drivers/gpu/drm/amd/display/dc
parentdrm/amd/display: Double buffer dcn2 Gamut Remap (diff)
downloadlinux-dev-8c0192533c39660ae229d7b80adeeb3bc63a3eba.tar.xz
linux-dev-8c0192533c39660ae229d7b80adeeb3bc63a3eba.zip
drm/amd/display: programing surface flip by dmcub.
Programming surface flip addresses via dmcub uC for optimizing the data flush. Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Harry Wentland <harry.wentland@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c116
2 files changed, 117 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index dfc66954a24b..ecd2257de80b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -420,6 +420,7 @@ struct dc_debug_options {
bool nv12_iflip_vm_wa;
bool disable_dram_clock_change_vactive_support;
bool validate_dml_output;
+ bool enable_dmcub_surface_flip;
};
struct dc_debug_data {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
index 4d2564f79395..1f4e2cd08d4c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
@@ -29,6 +29,8 @@
#include "dm_services.h"
#include "reg_helper.h"
+#include "dc_dmub_srv.h"
+
#define DC_LOGGER_INIT(logger)
#define REG(reg)\
@@ -688,6 +690,113 @@ 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,
+ 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 };
+
+ 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;
+
+ switch (address->type) {
+ case PLN_ADDR_TYPE_GRAPHICS:
+ if (address->grph.addr.quad_part == 0)
+ return;
+
+ if (address->grph.meta_addr.quad_part != 0) {
+ surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS =
+ address->grph.meta_addr.low_part;
+ surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH =
+ address->grph.meta_addr.high_part;
+ }
+
+ surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS =
+ address->grph.addr.low_part;
+ surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH =
+ address->grph.addr.high_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)
+ return;
+
+ if (address->video_progressive.luma_meta_addr.quad_part != 0) {
+ surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS =
+ address->video_progressive.luma_meta_addr.low_part;
+ surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH =
+ address->video_progressive.luma_meta_addr.high_part;
+
+ surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS_C =
+ address->video_progressive.chroma_meta_addr.low_part;
+ surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C =
+ address->video_progressive.chroma_meta_addr.high_part;
+ }
+
+ surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS =
+ address->video_progressive.luma_addr.low_part;
+ surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH =
+ address->video_progressive.luma_addr.high_part;
+
+ 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;
+ if (address->grph_stereo.right_addr.quad_part == 0)
+ return;
+
+ surface_flip.flip.grph_stereo = true;
+
+ if (address->grph_stereo.right_meta_addr.quad_part != 0) {
+ surface_flip.flip.DCSURF_SECONDARY_META_SURFACE_ADDRESS =
+ address->grph_stereo.right_meta_addr.low_part;
+ surface_flip.flip.DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH =
+ address->grph_stereo.right_meta_addr.high_part;
+ }
+
+ if (address->grph_stereo.left_meta_addr.quad_part != 0) {
+ surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS =
+ address->grph_stereo.left_meta_addr.low_part;
+ surface_flip.flip.DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH =
+ address->grph_stereo.left_meta_addr.high_part;
+ }
+
+ surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS =
+ address->grph_stereo.left_addr.low_part;
+ surface_flip.flip.DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH =
+ address->grph_stereo.left_addr.high_part;
+
+ surface_flip.flip.DCSURF_SECONDARY_SURFACE_ADDRESS =
+ address->grph_stereo.right_addr.low_part;
+ surface_flip.flip.DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH =
+ 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,
@@ -696,6 +805,13 @@ bool hubp21_program_surface_flip_and_addr(
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);