From: Dave Airlie <airl...@redhat.com> The DAC Load detection table is meant to take a parameter selecting the DAC to do load detection on. However on certain BIOS revisions it accept no parameters and load detects both DACs, with the result that load detecting on the second DAC causes flicker on the first, which isn't really acceptable.
We should code up a workaround function for these chips to workaround this case. Signed-off-by: Dave Airlie <airl...@redhat.com> --- drivers/gpu/drm/radeon/atom.c | 15 +++++++++++++-- drivers/gpu/drm/radeon/atom.h | 2 ++ drivers/gpu/drm/radeon/radeon_encoders.c | 11 +++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index bcec2d7..6477ac5 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -1320,12 +1320,13 @@ bool atom_parse_data_header(struct atom_context *ctx, int index, return true; } -bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev, - uint8_t * crev) +bool atom_parse_cmd_header_stack(struct atom_context *ctx, int index, uint8_t *frev, + uint8_t *crev, uint8_t *ps_size, uint8_t *ws_size) { int offset = index * 2 + 4; int idx = CU16(ctx->cmd_table + offset); u16 *mct = (u16 *)(ctx->bios + ctx->cmd_table + 4); + u16 table_attrib = CU16(idx + 4); if (!mct[index]) return false; @@ -1334,9 +1335,19 @@ bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev, *frev = CU8(idx + 2); if (crev) *crev = CU8(idx + 3); + if (ps_size) + *ps_size = (table_attrib & 0xe00) >> 8; + if (ws_size) + *ws_size = (table_attrib & 0xff); return true; } +bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *rev, + uint8_t *crev) +{ + return atom_parse_cmd_header_stack(ctx, index, rev, crev, NULL, NULL); +} + int atom_allocate_fb_scratch(struct atom_context *ctx) { int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware); diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index cd1b64a..ca21357 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h @@ -147,6 +147,8 @@ bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start); bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev); +bool atom_parse_cmd_header_stack(struct atom_context *ctx, int index, uint8_t *rev, + uint8_t *crev, uint8_t *ps_size, uint8_t *ws_size); int atom_allocate_fb_scratch(struct atom_context *ctx); #include "atom-types.h" #include "atombios.h" diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index c52fc30..36bcabd 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1398,12 +1398,19 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn ATOM_DEVICE_CRT_SUPPORT)) { DAC_LOAD_DETECTION_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); - uint8_t frev, crev; + uint8_t frev, crev, ps_size; memset(&args, 0, sizeof(args)); - if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + if (!atom_parse_cmd_header_stack(rdev->mode_info.atom_context, index, &frev, &crev, &ps_size, NULL)) return false; + + /* r4xx and some early rv5xx probe all DACs, this can cause distrubances in the force, + also on other DACs. - we can detect these tables as they have a 0 sized param stack */ + if (ps_size == 0) { + DRM_DEBUG("not executing dac load detection table due to buggy atom table\n"); + return false; + } args.sDacload.ucMisc = 0; -- 1.7.0.1 ------------------------------------------------------------------------------ -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel