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

Reply via email to