summaryrefslogtreecommitdiff
path: root/driver/xf86-video-radeonhd/utils
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2008-04-19 13:41:47 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2008-04-19 13:41:47 +0000
commit6955fa2ff594e9f967f66d061747d7cccf012c62 (patch)
tree6dfea27eeb65762163afcdba33b4c25f783eee63 /driver/xf86-video-radeonhd/utils
parentedf5e5abd24979eb74e8a9b7ae0c2198743114aa (diff)
Update to xf86-video-radeonhd 1.2.0. Tested by jdixon@ and jasper@
Diffstat (limited to 'driver/xf86-video-radeonhd/utils')
-rw-r--r--driver/xf86-video-radeonhd/utils/conntest/Makefile.am12
-rw-r--r--driver/xf86-video-radeonhd/utils/conntest/Makefile.in28
-rw-r--r--driver/xf86-video-radeonhd/utils/conntest/README8
-rw-r--r--driver/xf86-video-radeonhd/utils/conntest/git_version.h4
-rw-r--r--driver/xf86-video-radeonhd/utils/conntest/rhd_conntest.c1180
-rw-r--r--driver/xf86-video-radeonhd/utils/conntest/rhd_dump.c457
6 files changed, 1561 insertions, 128 deletions
diff --git a/driver/xf86-video-radeonhd/utils/conntest/Makefile.am b/driver/xf86-video-radeonhd/utils/conntest/Makefile.am
index 4a858aa52..b7cc322ba 100644
--- a/driver/xf86-video-radeonhd/utils/conntest/Makefile.am
+++ b/driver/xf86-video-radeonhd/utils/conntest/Makefile.am
@@ -4,10 +4,10 @@ include $(top_srcdir)/RadeonHD.am
EXTRA_DIST = README Imakefile
-EXTRA_PROGRAMS = rhd_conntest
+EXTRA_PROGRAMS = rhd_conntest rhd_dump
if HAVE_PCI_PCI_H
if HAVE_ZLIB
-noinst_PROGRAMS = rhd_conntest
+noinst_PROGRAMS = rhd_conntest rhd_dump
endif
endif
@@ -19,9 +19,13 @@ all-local:
fi
# Including config.h requires xorg-config.h, so we need the XORG_CFLAGS here
-AM_CFLAGS = @XORG_CFLAGS@ @WARN_CFLAGS@
+AM_CFLAGS = @XORG_CFLAGS@ @WARN_CFLAGS@ @PCIUTILS_CFLAGS@
AM_CPPFLAGS = -I$(top_srcdir)/src/AtomBios/includes
rhd_conntest_SOURCES = rhd_conntest.c
nodist_rhd_conntest_SOURCES = git_version.h
-rhd_conntest_LDADD = -lz -lpci
+rhd_conntest_LDADD = @PCIUTILS_LIBS@
+
+rhd_dump_SOURCES = rhd_dump.c
+nodist_rhd_dump_SOURCES = git_version.h
+rhd_dump_LDADD = @PCIUTILS_LIBS@ \ No newline at end of file
diff --git a/driver/xf86-video-radeonhd/utils/conntest/Makefile.in b/driver/xf86-video-radeonhd/utils/conntest/Makefile.in
index dd058c272..fa0e3a985 100644
--- a/driver/xf86-video-radeonhd/utils/conntest/Makefile.in
+++ b/driver/xf86-video-radeonhd/utils/conntest/Makefile.in
@@ -14,6 +14,11 @@
@SET_MAKE@
+# Copyright (c) 2007 Hans Ulrich Niedermann <hun@n-dimensional.de>
+#
+# This Makefile fragment is free software; the author(s) give(s)
+# unlimited permission to copy, distribute and modify it.
+
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
@@ -38,9 +43,10 @@ build_triplet = @build@
host_triplet = @host@
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(top_srcdir)/RadeonHD.am
-EXTRA_PROGRAMS = rhd_conntest$(EXEEXT)
+EXTRA_PROGRAMS = rhd_conntest$(EXEEXT) rhd_dump$(EXEEXT)
@HAVE_PCI_PCI_H_TRUE@@HAVE_ZLIB_TRUE@noinst_PROGRAMS = \
-@HAVE_PCI_PCI_H_TRUE@@HAVE_ZLIB_TRUE@ rhd_conntest$(EXEEXT)
+@HAVE_PCI_PCI_H_TRUE@@HAVE_ZLIB_TRUE@ rhd_conntest$(EXEEXT) \
+@HAVE_PCI_PCI_H_TRUE@@HAVE_ZLIB_TRUE@ rhd_dump$(EXEEXT)
subdir = utils/conntest
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
@@ -55,6 +61,10 @@ nodist_rhd_conntest_OBJECTS =
rhd_conntest_OBJECTS = $(am_rhd_conntest_OBJECTS) \
$(nodist_rhd_conntest_OBJECTS)
rhd_conntest_DEPENDENCIES =
+am_rhd_dump_OBJECTS = rhd_dump.$(OBJEXT)
+nodist_rhd_dump_OBJECTS =
+rhd_dump_OBJECTS = $(am_rhd_dump_OBJECTS) $(nodist_rhd_dump_OBJECTS)
+rhd_dump_DEPENDENCIES =
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -66,8 +76,9 @@ LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(rhd_conntest_SOURCES) $(nodist_rhd_conntest_SOURCES)
-DIST_SOURCES = $(rhd_conntest_SOURCES)
+SOURCES = $(rhd_conntest_SOURCES) $(nodist_rhd_conntest_SOURCES) \
+ $(rhd_dump_SOURCES) $(nodist_rhd_dump_SOURCES)
+DIST_SOURCES = $(rhd_conntest_SOURCES) $(rhd_dump_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -155,6 +166,8 @@ RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+USE_EXA_FALSE = @USE_EXA_FALSE@
+USE_EXA_TRUE = @USE_EXA_TRUE@
VERSION = @VERSION@
WARN_CFLAGS = @WARN_CFLAGS@
XORG_CFLAGS = @XORG_CFLAGS@
@@ -221,6 +234,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/AtomBios/includes
rhd_conntest_SOURCES = rhd_conntest.c
nodist_rhd_conntest_SOURCES = git_version.h
rhd_conntest_LDADD = @PCIUTILS_LIBS@
+rhd_dump_SOURCES = rhd_dump.c
+nodist_rhd_dump_SOURCES = git_version.h
+rhd_dump_LDADD = @PCIUTILS_LIBS@
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -265,6 +281,9 @@ clean-noinstPROGRAMS:
rhd_conntest$(EXEEXT): $(rhd_conntest_OBJECTS) $(rhd_conntest_DEPENDENCIES)
@rm -f rhd_conntest$(EXEEXT)
$(LINK) $(rhd_conntest_LDFLAGS) $(rhd_conntest_OBJECTS) $(rhd_conntest_LDADD) $(LIBS)
+rhd_dump$(EXEEXT): $(rhd_dump_OBJECTS) $(rhd_dump_DEPENDENCIES)
+ @rm -f rhd_dump$(EXEEXT)
+ $(LINK) $(rhd_dump_LDFLAGS) $(rhd_dump_OBJECTS) $(rhd_dump_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -273,6 +292,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rhd_conntest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rhd_dump.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
diff --git a/driver/xf86-video-radeonhd/utils/conntest/README b/driver/xf86-video-radeonhd/utils/conntest/README
index 6b73bb09f..3b42a8fd5 100644
--- a/driver/xf86-video-radeonhd/utils/conntest/README
+++ b/driver/xf86-video-radeonhd/utils/conntest/README
@@ -16,13 +16,17 @@ Usage:
------
As root run:
-./rhd_conntest <pci tag> [-s]
+./rhd_conntest <pci tag> [-d] [-s] [-x num]
<pci tag> is in the form <bus>:<device>.<function>, the most common position
is 1:0.0. lspci happily provides you with this information.
+
The optional option -s will scan the known I2C for additional slaves (besides
the DDC slave on 0xA0). Depending on your hardware this may take long.
+The optional argument -x <num> will dump <num> bytes of data from the
+available DDC slaves. <num> must not be higher than 256.
+
To dump the content of the VBIOS run:
./rhd_conntest <pci tag> -d
This will dump the VBIOS to the file:
@@ -79,7 +83,7 @@ support for your card.
Create a small text file. Each step, mention which cable was connected where.
-Go over each connector seperately, and connect the analogue (VGA) cable once
+Go over each connector separately, and connect the analogue (VGA) cable once
and connect the DVI cable once (when possible). Each time running rhd_conntest
and saving the data rhd_conntest spews out.
diff --git a/driver/xf86-video-radeonhd/utils/conntest/git_version.h b/driver/xf86-video-radeonhd/utils/conntest/git_version.h
index 6a2ff20c3..2fee1ed8c 100644
--- a/driver/xf86-video-radeonhd/utils/conntest/git_version.h
+++ b/driver/xf86-video-radeonhd/utils/conntest/git_version.h
@@ -7,7 +7,7 @@
#define GIT_VERSION_H 1
/* whether this is a dist tarball or not */
-#undef GIT_IS_DIST
+#define GIT_IS_DIST 1
/* No errors occured while running git */
#undef GIT_ERRORS
@@ -20,7 +20,7 @@
#define GIT_REPO 1
/* Git SHA ID of last commit */
-#define GIT_SHAID "9fe776ed"
+#define GIT_SHAID "9d131f90"
/* Branch this tree is on */
#define GIT_BRANCH "master"
diff --git a/driver/xf86-video-radeonhd/utils/conntest/rhd_conntest.c b/driver/xf86-video-radeonhd/utils/conntest/rhd_conntest.c
index 455cab3cc..ca297671e 100644
--- a/driver/xf86-video-radeonhd/utils/conntest/rhd_conntest.c
+++ b/driver/xf86-video-radeonhd/utils/conntest/rhd_conntest.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2007 Luc Verhaegen <lverhaegen@novell.com>
- * Copyright 2007 Matthias Hopf <mhopf@novell.com>
- * Copyright 2007 Egbert Eich <eich@novell.com>
- * Copyright 2007 Advanced Micro Devices, Inc.
+ * Copyright 2007, 2008 Luc Verhaegen <lverhaegen@novell.com>
+ * Copyright 2007, 2008 Matthias Hopf <mhopf@novell.com>
+ * Copyright 2007, 2008 Egbert Eich <eich@novell.com>
+ * Copyright 2007, 2008 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -27,7 +27,7 @@
* This tool is here to help create a connector mapping table.
*
*/
-
+/* #define DEBUG */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -37,6 +37,7 @@
#include <sys/mman.h>
#include <pci/pci.h>
#include <unistd.h>
+#include <stdlib.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -64,6 +65,13 @@ typedef int Bool;
typedef unsigned char CARD8;
typedef unsigned short CARD16;
typedef unsigned int CARD32;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define SHORT(x) (x)
+#else
+#define SHORT(x) (((x & 0xff) << 8) | ((x & 0xff) >> 8))
+#endif
+
#define VBIOS_BASE 0xC0000
#define VBIOS_MAXSIZE 0x10000
#define DEV_MEM "/dev/mem"
@@ -83,6 +91,20 @@ enum {
DACA_COMPARATOR_ENABLE = 0x785C,
DACA_COMPARATOR_OUTPUT = 0x7860,
+ RV620_DACA_ENABLE = 0x7000,
+ RV620_DACA_SOURCE_SELECT = 0x7004,
+ RV620_DACA_AUTODETECT_CONTROL = 0x7028,
+ RV620_DACA_AUTODETECT_STATUS = 0x7034,
+ RV620_DACA_AUTODETECT_INT_CONTROL = 0x7038,
+ RV620_DACA_FORCE_OUTPUT_CNTL = 0x703C,
+ RV620_DACA_FORCE_DATA = 0x7040,
+ RV620_DACA_POWERDOWN = 0x7050,
+ /* RV620_DACB_CONTROL1 moved */
+ RV620_DACA_CONTROL2 = 0x7058,
+ RV620_DACA_COMPARATOR_ENABLE = 0x705C,
+
+ RV620_DACA_CONTROL1 = 0x7ef4,
+
/* DAC B */
DACB_ENABLE = 0x7A00,
DACB_SOURCE_SELECT = 0x7A04,
@@ -95,6 +117,23 @@ enum {
DACB_COMPARATOR_ENABLE = 0x7A5C,
DACB_COMPARATOR_OUTPUT = 0x7A60,
+ RV620_DACB_ENABLE = 0x7100,
+ RV620_DACB_SOURCE_SELECT = 0x7104,
+ RV620_DACB_AUTODETECT_CONTROL = 0x7128,
+ RV620_DACB_AUTODETECT_STATUS = 0x7034,
+ RV620_DACB_FORCE_OUTPUT_CNTL = 0x713C,
+ RV620_DACB_FORCE_DATA = 0x7140,
+ RV620_DACB_POWERDOWN = 0x7150,
+ /* RV620_DACB_CONTROL1 moved */
+ RV620_DACB_CONTROL2 = 0x7158,
+ RV620_DACB_COMPARATOR_ENABLE = 0x715C,
+
+ RV620_DACB_CONTROL1 = 0x7ff4,
+
+ /* DAC common */
+ RV620_DAC_COMPARATOR_MISC = 0x7da4,
+ RV620_DAC_COMPARATOR_OUTPUT = 0x7da8,
+
/* TMDSA */
TMDSA_CNTL = 0x7880,
TMDSA_SOURCE_SELECT = 0x7884,
@@ -182,6 +221,20 @@ enum {
RS69_DC_I2C_TRANSACTION0 = 0x7D48, /* (RW) */
RS69_DC_I2C_TRANSACTION1 = 0x7D4C, /* (RW) */
+ /* RV62x I2C */
+ RV62_GENERIC_I2C_CONTROL = 0x7d80, /* (RW) */
+ RV62_GENERIC_I2C_INTERRUPT_CONTROL = 0x7d84, /* (RW) */
+ RV62_GENERIC_I2C_STATUS = 0x7d88, /* (RW) */
+ RV62_GENERIC_I2C_SPEED = 0x7d8c, /* (RW) */
+ RV62_GENERIC_I2C_SETUP = 0x7d90, /* (RW) */
+ RV62_GENERIC_I2C_TRANSACTION = 0x7d94, /* (RW) */
+ RV62_GENERIC_I2C_DATA = 0x7d98, /* (RW) */
+ RV62_GENERIC_I2C_PIN_SELECTION = 0x7d9c, /* (RW) */
+ RV62_DC_GPIO_DDC4_MASK = 0x7e20, /* (RW) */
+ RV62_DC_GPIO_DDC1_MASK = 0x7e40, /* (RW) */
+ RV62_DC_GPIO_DDC2_MASK = 0x7e50, /* (RW) */
+ RV62_DC_GPIO_DDC3_MASK = 0x7e60, /* (RW) */
+
/* HPD */
DC_GPIO_HPD_Y = 0x7E9C
};
@@ -189,10 +242,19 @@ enum {
typedef enum _chipType {
RHD_R500 = 1,
RHD_RS690,
- RHD_R600
+ RHD_R600,
+ RHD_RV620
} chipType;
-/* for RHD_R500/R600 */
+typedef enum dacOutput {
+ DAC_NONE,
+ DAC_VGA,
+ DAC_SVIDEO,
+ DAC_COMPOSITE,
+ DAC_COMPONENT
+} dacOutput;
+
+/* for RHD_R500/R600/RS690/RV620 */
chipType ChipType;
typedef struct _tableVersion
@@ -216,6 +278,9 @@ typedef struct _atomDataTables
} atomDataTables, *atomDataTablesPtr;
atomDataTables AtomData;
+unsigned char **command_table = NULL;
+int num_command_table_entries = 0;
+unsigned char * AtomBiosGetDataFromCodeTable(unsigned char **tablelist, int n, short *size);
/*
@@ -325,6 +390,9 @@ struct RHDDevice {
{ 0x1002, 0x7297, 2, RHD_R500},
{ 0x1002, 0x791E, 2, RHD_RS690},
{ 0x1002, 0x791F, 2, RHD_RS690},
+ { 0x1002, 0x793F, 2, RHD_RS690},
+ { 0x1002, 0x7941, 2, RHD_RS690},
+ { 0x1002, 0x7942, 2, RHD_RS690},
{ 0x1002, 0x796C, 2, RHD_R500},
{ 0x1002, 0x796D, 2, RHD_R500},
{ 0x1002, 0x796E, 2, RHD_R500},
@@ -333,15 +401,27 @@ struct RHDDevice {
{ 0x1002, 0x9401, 2, RHD_R600},
{ 0x1002, 0x9402, 2, RHD_R600},
{ 0x1002, 0x9403, 2, RHD_R600},
+ { 0x1002, 0x9405, 2, RHD_R600},
+ { 0x1002, 0x940A, 2, RHD_R600},
+ { 0x1002, 0x940B, 2, RHD_R600},
+ { 0x1002, 0x940F, 2, RHD_R600},
{ 0x1002, 0x94C0, 2, RHD_R600},
{ 0x1002, 0x94C1, 2, RHD_R600},
{ 0x1002, 0x94C3, 2, RHD_R600},
{ 0x1002, 0x94C4, 2, RHD_R600},
+ { 0x1002, 0x94C5, 2, RHD_R600},
{ 0x1002, 0x94C6, 2, RHD_R600},
{ 0x1002, 0x94C7, 2, RHD_R600},
{ 0x1002, 0x94C8, 2, RHD_R600},
{ 0x1002, 0x94C9, 2, RHD_R600},
{ 0x1002, 0x94CB, 2, RHD_R600},
+ { 0x1002, 0x94CC, 2, RHD_R600},
+ { 0x1002, 0x9500, 2, RHD_R600},
+ { 0x1002, 0x9501, 2, RHD_R600},
+ { 0x1002, 0x9505, 2, RHD_R600},
+ { 0x1002, 0x9507, 2, RHD_R600},
+ { 0x1002, 0x950F, 2, RHD_R600},
+ { 0x1002, 0x9511, 2, RHD_R600},
{ 0x1002, 0x9580, 2, RHD_R600},
{ 0x1002, 0x9581, 2, RHD_R600},
{ 0x1002, 0x9583, 2, RHD_R600},
@@ -351,12 +431,52 @@ struct RHDDevice {
{ 0x1002, 0x9589, 2, RHD_R600},
{ 0x1002, 0x958A, 2, RHD_R600},
{ 0x1002, 0x958B, 2, RHD_R600},
+ { 0x1002, 0x958C, 2, RHD_R600},
+ { 0x1002, 0x958D, 2, RHD_R600},
+ { 0x1002, 0x958E, 2, RHD_R600},
+ { 0x1002, 0x9598, 2, RHD_RV620},
+ { 0x1002, 0x95C5, 2, RHD_RV620},
+ { 0x1002, 0x9612, 2, RHD_RV620},
{ 0, 0, 0, 0 }
};
/*
*
*/
+#define LEN 16
+void
+dprint(unsigned char *start, unsigned long size)
+{
+ unsigned int i;
+ unsigned int count = LEN;
+ char *c = (char *)start;
+
+ while (size) {
+ char *d = c;
+ printf(" ");
+
+ if (size < LEN)
+ count = size;
+ size -= count;
+
+ for (i = 0; i<count; i++)
+ printf("%2.2x ",(unsigned char) (*(c++)));
+ c = d;
+ for (i = 0; i<count; i++) {
+ printf("%c",((((CARD8)(*c)) > 32)
+ && (((CARD8)(*c)) < 128)) ?
+ (unsigned char) (*(c)): '.');
+ c++;
+ }
+ printf("\n");
+ }
+
+ printf("\n");
+}
+
+/*
+ *
+ */
static struct pci_dev *
DeviceLocate(struct pci_dev *devices, int bus, int dev, int func)
{
@@ -410,7 +530,11 @@ MapBar(struct pci_dev *device, int ioBar, int devMem)
CARD32
RegRead(void *map, int offset)
{
- return *(volatile CARD32 *)((CARD8 *) map + offset);
+ CARD32 ret = *(volatile CARD32 *)((CARD8 *) map + offset);
+#ifdef DEBUG
+ fprintf(stderr, "0x%x = RegRead(0x%x)\n",ret,offset);
+#endif
+ return ret;
}
/*
@@ -419,6 +543,9 @@ RegRead(void *map, int offset)
void
RegWrite(void *map, int offset, CARD32 value)
{
+#ifdef DEBUG
+ fprintf(stderr, "RegWrite(0x%x, 0x%x)\n",offset,value);
+#endif
*(volatile CARD32 *)((CARD8 *) map + offset) = value;
}
@@ -463,116 +590,173 @@ HPDReport(void *map)
/*
*
*/
-static Bool
-DACALoadDetect(void *map)
+static dacOutput
+DACLoadDetect(void *map, Bool tv, int dac)
{
CARD32 CompEnable, Control1, Control2, DetectControl, Enable;
CARD8 ret;
+ unsigned int offset = 0;
+
+ if (dac) offset = 0x200;
- CompEnable = RegRead(map, DACA_COMPARATOR_ENABLE);
- Control1 = RegRead(map, DACA_CONTROL1);
- Control2 = RegRead(map, DACA_CONTROL2);
- DetectControl = RegRead(map, DACA_AUTODETECT_CONTROL);
- Enable = RegRead(map, DACA_ENABLE);
+ CompEnable = RegRead(map, offset + DACA_COMPARATOR_ENABLE);
+ Control1 = RegRead(map, offset + DACA_CONTROL1);
+ Control2 = RegRead(map, offset + DACA_CONTROL2);
+ DetectControl = RegRead(map, offset + DACA_AUTODETECT_CONTROL);
+ Enable = RegRead(map, offset + DACA_ENABLE);
- RegWrite(map, DACA_ENABLE, 1);
- RegMask(map, DACA_AUTODETECT_CONTROL, 0, 0x3);
- RegMask(map, DACA_CONTROL2, 0, 0x1);
+ RegWrite(map, offset + DACA_ENABLE, 1);
+ RegMask(map, offset + DACA_AUTODETECT_CONTROL, 0, 0x3);
+ RegMask(map, offset + DACA_CONTROL2, 0, 0xff0000);
+ RegMask(map, offset + DACA_CONTROL2, 0, 0x1);
- RegMask(map, DACA_CONTROL2, 0, 0x100);
+ RegMask(map, offset + DACA_CONTROL2, tv ? 0x100 : 0, 0x100);
- RegWrite(map, DACA_FORCE_DATA, 0);
- RegMask(map, DACA_CONTROL2, 0x1, 0x1);
+ RegWrite(map, offset + DACA_FORCE_DATA, 0);
+ RegMask(map, offset + DACA_CONTROL2, 0x1, 0x1);
- RegMask(map, DACA_COMPARATOR_ENABLE, 0x00070000, 0x00070000);
- RegWrite(map, DACA_CONTROL1, 0x00050802);
- RegMask(map, DACA_POWERDOWN, 0, 0x1); /* Shut down Bandgap Voltage Reference Power */
+ RegMask(map, offset + DACA_COMPARATOR_ENABLE, 0x00070000, 0x00070000);
+ RegWrite(map, offset + DACA_CONTROL1, 0x00050802);
+ RegMask(map, offset + DACA_POWERDOWN, 0, 0x1); /* Shut down Bandgap Voltage Reference Power */
usleep(5);
- RegMask(map, DACA_POWERDOWN, 0, 0x01010100); /* Shut down RGB */
+ RegMask(map, offset + DACA_POWERDOWN, 0, 0x01010100); /* Shut down RGB */
- RegWrite(map, DACA_FORCE_DATA, 0x1e6); /* 486 out of 1024 */
+ RegWrite(map, offset + DACA_FORCE_DATA, 0x1e6); /* 486 out of 1024 */
usleep(200);
- RegMask(map, DACA_POWERDOWN, 0x01010100, 0x01010100); /* Enable RGB */
+ RegMask(map, offset + DACA_POWERDOWN, 0x01010100, 0x01010100); /* Enable RGB */
usleep(88);
- RegMask(map, DACA_POWERDOWN, 0, 0x01010100); /* Shut down RGB */
+ RegMask(map, offset + DACA_POWERDOWN, 0, 0x01010100); /* Shut down RGB */
- RegMask(map, DACA_COMPARATOR_ENABLE, 0x100, 0x100);
+ RegMask(map, offset + DACA_COMPARATOR_ENABLE, 0x100, 0x100);
usleep(100);
/* Get RGB detect values
* If only G is detected, we could have a monochrome monitor,
* but we don't bother with this at the moment.
*/
- ret = (RegRead(map, DACA_COMPARATOR_OUTPUT) & 0x0E) >> 1;
-
- RegMask(map, DACA_COMPARATOR_ENABLE, CompEnable, 0x00FFFFFF);
- RegWrite(map, DACA_CONTROL1, Control1);
- RegMask(map, DACA_CONTROL2, Control2, 0x1FF);
- RegMask(map, DACA_AUTODETECT_CONTROL, DetectControl, 0xFF);
- RegMask(map, DACA_ENABLE, Enable, 0xFF);
-
- return (ret & 0x07);
+ ret = (RegRead(map, offset + DACA_COMPARATOR_OUTPUT) & 0x0E) >> 1;
+#ifdef DEBUG
+ fprintf(stderr, "DAC%s: %x %s\n", dac ? "B" : "A", ret, tv ? "TV" : "");
+#endif
+ RegMask(map, offset + DACA_COMPARATOR_ENABLE, CompEnable, 0x00FFFFFF);
+ RegWrite(map, offset + DACA_CONTROL1, Control1);
+ RegMask(map, offset + DACA_CONTROL2, Control2, 0x1FF);
+ RegMask(map, offset + DACA_AUTODETECT_CONTROL, DetectControl, 0xFF);
+ RegMask(map, offset + DACA_ENABLE, Enable, 0xFF);
+
+ switch (ret & 0x7) {
+ case 0x7:
+ if (tv)
+ return DAC_COMPONENT;
+ else
+ return DAC_VGA;
+ case 0x1:
+ if (tv)
+ return DAC_COMPOSITE;
+ else
+ return DAC_NONE;
+ case 0x6:
+ if (tv)
+ return DAC_SVIDEO;
+ else
+ return DAC_NONE;
+ default:
+ return DAC_NONE;
+ }
}
/*
*
*/
-static Bool
-DACBLoadDetect(void *map)
+static dacOutput
+RV620DACLoadDetect(void *map, Bool tv, int dac)
{
- CARD32 CompEnable, Control1, Control2, DetectControl, Enable;
- CARD8 ret;
-
- CompEnable = RegRead(map, DACB_COMPARATOR_ENABLE);
- Control1 = RegRead(map, DACB_CONTROL1);
- Control2 = RegRead(map, DACB_CONTROL2);
- DetectControl = RegRead(map, DACB_AUTODETECT_CONTROL);
- Enable = RegRead(map, DACB_ENABLE);
-
- RegWrite(map, DACB_ENABLE, 1);
- RegMask(map, DACB_AUTODETECT_CONTROL, 0, 0x3);
- RegMask(map, DACB_CONTROL2, 0, 0x1);
-
- RegMask(map, DACB_CONTROL2, 0, 0x100);
-
- RegWrite(map, DACB_FORCE_DATA, 0);
- RegMask(map, DACB_CONTROL2, 0x1, 0x1);
-
- RegMask(map, DACB_COMPARATOR_ENABLE, 0x00070000, 0x00070000);
- RegWrite(map, DACB_CONTROL1, 0x50802);
- RegMask(map, DACB_POWERDOWN, 0, 0x1); /* Shut down Bandgap Voltage Reference Power */
- usleep(5);
-
- RegMask(map, DACB_POWERDOWN, 0, 0x01010100); /* Shut down RGB */
-
- RegWrite(map, DACB_FORCE_DATA, 0x1e6); /* 486 out of 1024 */
- usleep(200);
-
- RegMask(map, DACB_POWERDOWN, 0x01010100, 0x01010100); /* Enable RGB */
- usleep(88);
-
- RegMask(map, DACB_POWERDOWN, 0, 0x01010100); /* Shut down RGB */
-
- RegMask(map, DACB_COMPARATOR_ENABLE, 0x100, 0x100);
+ CARD32 offset = 0;
+ CARD32 ret;
+ CARD32 DetectControl, AutodetectIntCtl, ForceData, Control1, Control2, CompEnable;
+ if (dac == 1)
+ offset = 0x100;
+ Control1 = RegRead(map, offset + RV620_DACA_CONTROL1); /* 7ef4 */
+ Control2 = RegRead(map, offset + RV620_DACA_CONTROL2); /* 7058 */
+ ForceData = RegRead(map, offset + RV620_DACA_FORCE_DATA);
+ AutodetectIntCtl = RegRead(map, offset + RV620_DACA_AUTODETECT_INT_CONTROL);
+ DetectControl = RegRead(map, offset + RV620_DACA_AUTODETECT_CONTROL);
+ CompEnable = RegRead(map, offset + RV620_DACA_COMPARATOR_ENABLE);
+#if 0
+ if (RegRead(map, offset + 0x7000) & 0x01) {
+ CARD32 my_offset = 0;
+ switch (RegRead(map, offset + 0x7004) & 0x3) {
+ case 0:
+ break;
+ case 1:
+ my_offset = 0x200;
+ break;
+ case 2:
+ switch (RegRead(map, offset + 0x60fc) & 0x1) {
+ case 0:
+ break;
+ case 1:
+ my_offset = 0x200;
+ break;
+ }
+ break;
+ }
+ if (RegRead(map, my_offset + 0x6080) & 0x1) {
+ while (!(RegRead(map, my_offset + 0x609c) & 0x02)) {};
+ while (!(RegRead(map, my_offset + 0x609c) & 0x01)) {};
+ }
+ }
+#endif
+ if (tv)
+ RegMask(map, offset + RV620_DACA_CONTROL2, 0x100, 0xff00); /* TV on */
+ else
+ RegMask(map, offset + RV620_DACA_CONTROL2, 0x00, 0xff00); /* TV off */
+ RegMask(map, offset + RV620_DACA_FORCE_DATA, 0x18, 0xffff);
+ /* ack autodetect */
+ RegMask(map, offset + RV620_DACA_AUTODETECT_INT_CONTROL, 0x01, 0x01);
+ /* autodetect off */
+ RegMask(map, offset + RV620_DACA_AUTODETECT_CONTROL, 0x00, 0xff);
+ /* bandgap */
+ RegMask(map, offset + RV620_DACA_CONTROL1, dac ? 0x2502 : 0x2002, 0xffff);
+ /* DAC RGB async enable */
+ RegMask(map, offset + RV620_DACA_CONTROL2, 0x1, 0x1);
+ /* enable r/g/b comparators, disable D/SDET ref */
+ RegMask(map, offset + RV620_DACA_COMPARATOR_ENABLE, 0x70000, 0x070101);
usleep(100);
+ /* check for connection */
+ RegMask(map, offset + RV620_DACA_AUTODETECT_CONTROL, 0x01, 0xff);
+ usleep(32);
- /*
- * Get RGB detect values
- * If only G is detected, we could have a monochrome monitor,
- * but we don't bother with this at the moment.
- */
- ret = (RegRead(map, DACB_COMPARATOR_OUTPUT) & 0x0E) >> 1;
+ ret = RegRead(map, offset + RV620_DACA_AUTODETECT_STATUS);
- RegMask(map, DACB_COMPARATOR_ENABLE, CompEnable, 0xFFFFFF);
- RegWrite(map, DACB_CONTROL1, Control1);
- RegMask(map, DACB_CONTROL2, Control2, 0x1FF);
- RegMask(map, DACB_AUTODETECT_CONTROL, DetectControl, 0xFF);
- RegMask(map, DACB_ENABLE, Enable, 0xFF);
+ RegWrite(map, offset + RV620_DACA_AUTODETECT_CONTROL, DetectControl);
+ RegWrite(map, offset + RV620_DACA_CONTROL1, Control1);
+ RegWrite(map, offset + RV620_DACA_CONTROL2, Control2);
+ RegWrite(map, offset + RV620_DACA_FORCE_DATA, ForceData);
+ RegWrite(map, offset + RV620_DACA_AUTODETECT_INT_CONTROL,
+ AutodetectIntCtl);
- return (ret & 0x07);
+#ifdef DEBUG
+ fprintf(stderr, "DAC%i: ret = 0x%x %s\n",dac,ret,tv ? "TV" : "");
+#endif
+
+ if (!tv)
+ return ((ret & 0x111) ? DAC_VGA : DAC_NONE);
+
+ switch (ret & 0x1010100) {
+ case 0x1010100:
+ if (tv)
+ return DAC_COMPONENT;
+ case 0x1000000:
+ return DAC_COMPOSITE;
+ case 0x10100:
+ return DAC_SVIDEO;
+ default:
+ return DAC_NONE;
+ }
}
/*
@@ -613,22 +797,66 @@ TMDSALoadDetect(void *map)
static void
LoadReport(void *map)
{
- Bool DACA, DACB, TMDSA;
+ dacOutput DACA = DAC_NONE, DACB = DAC_NONE, TVA = DAC_NONE, TVB = DAC_NONE;
+ Bool TMDSA;
- DACA = DACALoadDetect(map);
- DACB = DACBLoadDetect(map);
+ switch (ChipType) {
+ case RHD_R500:
+ case RHD_RS690:
+ case RHD_R600:
+ DACA = DACLoadDetect(map, FALSE, 0);
+ DACB = DACLoadDetect(map, FALSE, 1);
+ TVA = DACLoadDetect(map, TRUE, 0);
+ TVB = DACLoadDetect(map, TRUE, 1);
+ break;
+ case RHD_RV620:
+ DACA = RV620DACLoadDetect(map, FALSE, 0);
+ DACB = RV620DACLoadDetect(map, FALSE, 1);
+ TVA = RV620DACLoadDetect(map, TRUE, 0);
+ TVB = RV620DACLoadDetect(map, TRUE, 1);
+ break;
+ }
TMDSA =TMDSALoadDetect(map);
-
printf(" Load Detection:");
- if (!DACA && !DACB && !TMDSA)
+ if (!DACA && !DACB && !TMDSA && !TVA && !TVB)
printf(" RHD_OUTPUT_NONE ");
else {
- if (DACA)
+ if (DACA == DAC_VGA)
printf(" RHD_OUTPUT_DACA");
- if (DACB)
+ if (DACB == DAC_VGA)
printf(" RHD_OUTPUT_DACB");
+ switch (TVA) {
+ case DAC_SVIDEO:
+ printf(" RHD_OUTPUT_DACA_TV_SVIDEO");
+ break;
+ case DAC_COMPOSITE:
+ printf(" RHD_OUTPUT_DACA_TV_COMPOSITE");
+ break;
+ case DAC_COMPONENT:
+ if (!DACA)
+ printf(" RHD_OUTPUT_DACA_TV_COMPONENT");
+ break;
+ default:
+ break;
+ }
+
+ switch (TVB) {
+ case DAC_SVIDEO:
+ printf(" RHD_OUTPUT_DACB_TV_SVIDEO");
+ break;
+ case DAC_COMPOSITE:
+ printf(" RHD_OUTPUT_DACB_TV_COMPOSITE");
+ break;
+ case DAC_COMPONENT:
+ if (!DACB)
+ printf(" RHD_OUTPUT_DACB_TV_COMPONENT");
+ break;
+ default:
+ break;
+ }
+
if (TMDSA)
printf(" RHD_OUTPUT_TMDSA");
}
@@ -641,26 +869,32 @@ LoadReport(void *map)
CARD32
getDDCSpeed(void)
{
- CARD32 clock, ret;
+ CARD32 clock, ref_clk, ret;
switch (AtomData.FirmwareInfoVersion.crev) {
case 1:
clock = AtomData.FirmwareInfo.FirmwareInfo->ulDefaultEngineClock;
+ ref_clk = AtomData.FirmwareInfo.FirmwareInfo->usReferenceClock;
break;
case 2:
clock = AtomData.FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultEngineClock;
+ ref_clk = AtomData.FirmwareInfo.FirmwareInfo_V_1_2->usReferenceClock;
break;
case 3:
clock = AtomData.FirmwareInfo.FirmwareInfo_V_1_3->ulDefaultEngineClock;
+ ref_clk = AtomData.FirmwareInfo.FirmwareInfo_V_1_3->usReferenceClock;
break;
case 4:
clock = AtomData.FirmwareInfo.FirmwareInfo_V_1_4->ulDefaultEngineClock;
+ ref_clk = AtomData.FirmwareInfo.FirmwareInfo_V_1_4->usReferenceClock;
break;
default:
/* no AtomBIOS info; use save default */
clock = 70000;
+ ref_clk = 270;
}
clock *= 10;
+ ref_clk *= 10;
switch (ChipType) {
case RHD_R500:
@@ -671,6 +905,9 @@ getDDCSpeed(void)
case RHD_R600:
ret = (clock) / TARGET_HW_I2C_CLOCK;
break;
+ case RHD_RV620:
+ ret = (ref_clk) / (4 * TARGET_HW_I2C_CLOCK);
+ break;
default:
ret = 0;
}
@@ -805,7 +1042,7 @@ static Bool
R6xxI2CStatus(void *map)
{
int count = 800;
- CARD32 val;
+ CARD32 val = 0;
while (--count) {
@@ -831,6 +1068,91 @@ R6xxI2CStatus(void *map)
*
*/
static Bool
+R6xxI2CWriteRead(void *map, CARD8 line, CARD8 slave,
+ unsigned char *WriteBuffer, int nWrite, unsigned char *ReadBuffer, int nRead)
+{
+ Bool ret = FALSE;
+ CARD32 data = 0;
+ int idx = 1;
+
+ enum {
+ TRANS_WRITE_READ,
+ TRANS_WRITE,
+ TRANS_READ
+ } trans;
+
+ if (nWrite > 0 && nRead > 0) {
+ trans = TRANS_WRITE_READ;
+ } else if (nWrite > 0) {
+ trans = TRANS_WRITE;
+ } else if (nRead > 0) {
+ trans = TRANS_READ;
+ } else {
+ /* for bus probing */
+ trans = TRANS_WRITE;
+ }
+
+ if (!R6xxI2CSetupStatus(map, line))
+ return FALSE;
+
+ RegMask(map, R6_DC_I2C_CONTROL, (trans == TRANS_WRITE_READ)
+ ? (1 << 20) : 0, R6_DC_I2C_TRANSACTION_COUNT); /* 2 or 1 Transaction */
+ RegMask(map, R6_DC_I2C_TRANSACTION0,
+ R6_DC_I2C_STOP_ON_NACK0
+ | (trans == TRANS_READ ? R6_DC_I2C_RW0 : 0)
+ | R6_DC_I2C_START0
+ | (trans == TRANS_WRITE_READ ? 0 : R6_DC_I2C_STOP0 )
+ | ((trans == TRANS_READ ? nRead : nWrite) << 16),
+ 0xffffff);
+ if (trans == TRANS_WRITE_READ)
+ RegMask(map, R6_DC_I2C_TRANSACTION1,
+ nRead << 16
+ | R6_DC_I2C_RW1
+ | R6_DC_I2C_START1
+ | R6_DC_I2C_STOP1,
+ 0xffffff); /* <bytes> read */
+
+ data = R6_DC_I2C_INDEX_WRITE
+ | (((slave & 0xfe) | (trans == TRANS_READ ? 1 : 0)) << 8 )
+ | (0 << 16);
+ RegWrite(map, R6_DC_I2C_DATA, data);
+ if (trans != TRANS_READ) { /* we have bytes to write */
+ while (nWrite--) {
+ data = R6_DC_I2C_INDEX_WRITE | ( *(WriteBuffer++) << 8 )
+ | (idx++ << 16);
+ RegWrite(map, R6_DC_I2C_DATA, data);
+ }
+ }
+ if (trans == TRANS_WRITE_READ) { /* we have bytes to read after write */
+ data = R6_DC_I2C_INDEX_WRITE | ((slave | 0x1) << 8) | (idx++ << 16);
+ RegWrite(map, R6_DC_I2C_DATA, data);
+ }
+ /* Go! */
+ RegMask(map, R6_DC_I2C_CONTROL, R6_DC_I2C_GO, R6_DC_I2C_GO);
+ if (R6xxI2CStatus(map)) {
+ /* Hopefully this doesn't write data to index */
+ RegWrite(map, R6_DC_I2C_DATA, R6_DC_I2C_INDEX_WRITE
+ | R6_DC_I2C_DATA_RW | /* idx++ */3 << 16);
+ while (nRead--) {
+ data = RegRead(map, R6_DC_I2C_DATA);
+ *(ReadBuffer++) = (data >> 8) & 0xff;
+ }
+ ret = TRUE;
+ } else
+ return FALSE;
+
+ RegMask(map, R6_DC_I2C_CONTROL, 0x2, 0xff);
+ usleep(10);
+ RegWrite(map, R6_DC_I2C_CONTROL, 0);
+
+ return ret;
+}
+
+
+/*
+ *
+ */
+static Bool
R6xxDDCProbe(void *map, int Channel, unsigned char slave)
{
Bool ret = FALSE;
@@ -859,6 +1181,7 @@ R6xxDDCProbe(void *map, int Channel, unsigned char slave)
return ret;
}
+
enum _rhdRS69I2CBits {
/* RS69_DC_I2C_TRANSACTION0 */
RS69_DC_I2C_RW0 = (0x1 << 0),
@@ -927,6 +1250,11 @@ RS69I2CSetupStatus(void *map, int line)
RegMask(map, 0x28, 0x200, 0x200);
RegMask(map, RS69_DC_I2C_UNKNOWN_1, prescale << 16 | 0x2, 0xffff00ff);
/* add SDVO handling later */
+#ifdef DEBUG
+ fprintf(stderr,"GPIO line DDC%i: 0x%x\n",line,
+ AtomData
+ .GPIO_I2C_Info->asGPIO_Info[line & 0xf].usClkMaskRegisterIndex);
+#endif
switch (AtomData.GPIO_I2C_Info->asGPIO_Info[line & 0xf]
.usClkMaskRegisterIndex) {
case 0x1f90:
@@ -956,6 +1284,90 @@ RS69I2CSetupStatus(void *map, int line)
/*
*
*/
+static int
+RS69xI2CWriteRead(void *map, CARD8 line, CARD8 slave,
+ unsigned char *WriteBuffer, int nWrite, unsigned char *ReadBuffer, int nRead)
+{
+ Bool ret = FALSE;
+ CARD32 data = 0;
+
+ int idx = 1;
+
+ enum {
+ TRANS_WRITE_READ,
+ TRANS_WRITE,
+ TRANS_READ
+ } trans;
+
+ if (nWrite > 0 && nRead > 0) {
+ trans = TRANS_WRITE_READ;
+ } else if (nWrite > 0) {
+ trans = TRANS_WRITE;
+ } else if (nRead > 0) {
+ trans = TRANS_READ;
+ } else {
+ /* for bus probing */
+ trans = TRANS_WRITE;
+ }
+
+ if (!RS69I2CSetupStatus(map, line))
+ return FALSE;
+
+ RegMask(map, RS69_DC_I2C_CONTROL, (trans == TRANS_WRITE_READ)
+ ? (1 << 20) : 0, RS69_DC_I2C_TRANSACTION_COUNT); /* 2 or 1 Transaction */
+ RegMask(map, RS69_DC_I2C_TRANSACTION0,
+ RS69_DC_I2C_STOP_ON_NACK0
+ | (trans == TRANS_READ ? RS69_DC_I2C_RW0 : 0)
+ | RS69_DC_I2C_START0
+ | (trans == TRANS_WRITE_READ ? 0 : RS69_DC_I2C_STOP0 )
+ | ((trans == TRANS_READ ? nRead : nWrite) << 16),
+ 0xffffff);
+ if (trans == TRANS_WRITE_READ)
+ RegMask(map, RS69_DC_I2C_TRANSACTION1,
+ nRead << 16
+ | RS69_DC_I2C_RW1
+ | RS69_DC_I2C_START1
+ | RS69_DC_I2C_STOP1,
+ 0xffffff); /* <bytes> read */
+
+ data = RS69_DC_I2C_INDEX_WRITE
+ | (((slave & 0xfe) | (trans == TRANS_READ ? 1 : 0)) << 8 )
+ | (0 << 16);
+ RegWrite(map, RS69_DC_I2C_DATA, data);
+ if (trans != TRANS_READ) { /* we have bytes to write */
+ while (nWrite--) {
+ data = RS69_DC_I2C_INDEX_WRITE | ( *(WriteBuffer++) << 8 )
+ | (idx++ << 16);
+ RegWrite(map, RS69_DC_I2C_DATA, data);
+ }
+ }
+ if (trans == TRANS_WRITE_READ) { /* we have bytes to read after write */
+ data = RS69_DC_I2C_INDEX_WRITE | ((slave | 0x1) << 8) | (idx++ << 16);
+ RegWrite(map, RS69_DC_I2C_DATA, data);
+ }
+ /* Go! */
+ RegMask(map, RS69_DC_I2C_CONTROL, RS69_DC_I2C_GO, RS69_DC_I2C_GO);
+ if (RS69I2CStatus(map)) {
+ /* Hopefully this doesn't write data to index */
+ RegWrite(map, RS69_DC_I2C_DATA, RS69_DC_I2C_INDEX_WRITE
+ | RS69_DC_I2C_DATA_RW | /* idx++ */3 << 16);
+ while (nRead--) {
+ data = RegRead(map, RS69_DC_I2C_DATA);
+ *(ReadBuffer++) = (data >> 8) & 0xff;
+ }
+ ret = TRUE;
+ }
+
+ RegMask(map, RS69_DC_I2C_CONTROL, 0x2, 0xff);
+ usleep(10);
+ RegWrite(map, RS69_DC_I2C_CONTROL, 0);
+
+ return ret;
+}
+
+/*
+ *
+ */
static Bool
RS69DDCProbe(void *map, int Channel, unsigned char slave)
{
@@ -1031,6 +1443,34 @@ enum _rhdR5xxI2CBits {
*
*/
static Bool
+R5xxI2CSetupStatus(void *map, int channel)
+{
+ switch (channel) {
+ case 0:
+ RegMask(map, DC_GPIO_DDC1_MASK, 0x0, 0xffff);
+ RegMask(map, DC_GPIO_DDC1_A, 0x0, 0xffff);
+ RegMask(map, DC_GPIO_DDC1_EN, 0x0, 0xffff);
+ break;
+ case 1:
+ RegMask(map, DC_GPIO_DDC2_MASK, 0x0, 0xffff);
+ RegMask(map, DC_GPIO_DDC2_A, 0x0, 0xffff);
+ RegMask(map, DC_GPIO_DDC2_EN, 0x0, 0xffff);
+ break;
+ case 2:
+ RegMask(map, DC_GPIO_DDC3_MASK, 0x0, 0xffff);
+ RegMask(map, DC_GPIO_DDC3_A, 0x0, 0xffff);
+ RegMask(map, DC_GPIO_DDC3_EN, 0x0, 0xffff);
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ *
+ */
+static Bool
R5xxI2CStatus(void *map)
{
int count = 800;
@@ -1059,7 +1499,7 @@ R5xxI2CStatus(void *map)
/*
*
*/
-static Bool
+static int
R5xxDDCProbe(void *map, int Channel, unsigned char slave)
{
Bool ret = FALSE;
@@ -1070,6 +1510,9 @@ R5xxDDCProbe(void *map, int Channel, unsigned char slave)
if (!prescale)
return FALSE;
+ if (!R5xxI2CSetupStatus(map, Channel))
+ return FALSE;
+
RegMask(map, 0x28, 0x200, 0x200);
SaveControl1 = RegRead(map, R5_DC_I2C_CONTROL1);
@@ -1121,16 +1564,403 @@ R5xxDDCProbe(void *map, int Channel, unsigned char slave)
/*
*
*/
+Bool
+R5xxI2CWriteReadChunk(void *map, CARD8 line, CARD8 slave,
+ unsigned char *WriteBuffer, int nWrite, unsigned char *ReadBuffer, int nRead)
+{
+ int prescale = getDDCSpeed();
+ CARD32 save_I2C_CONTROL1, save_494;
+ CARD32 tmp32;
+ Bool ret = TRUE;
+
+ RegMask(map, 0x28, 0x200, 0x200);
+ save_I2C_CONTROL1 = RegRead(map, R5_DC_I2C_CONTROL1);
+ save_494 = RegRead(map, 0x494);
+ RegMask(map, 0x494, 1, 1);
+ RegMask(map, R5_DC_I2C_ARBITRATION,
+ R5_DC_I2C_SW_WANTS_TO_USE_I2C,
+ R5_DC_I2C_SW_WANTS_TO_USE_I2C);
+
+ RegMask(map, R5_DC_I2C_STATUS1, R5_DC_I2C_DONE
+ | R5_DC_I2C_NACK
+ | R5_DC_I2C_HALT, 0xff);
+ RegMask(map, R5_DC_I2C_RESET, R5_DC_I2C_SOFT_RESET, 0xffff);
+ RegWrite(map, R5_DC_I2C_RESET, 0);
+
+ RegMask(map, R5_DC_I2C_CONTROL1,
+ (line & 0x0f) << 16 | R5_DC_I2C_EN,
+ R5_DC_I2C_PIN_SELECT | R5_DC_I2C_EN);
+
+ if (nWrite || !nRead) { /* special case for bus probing */
+ /*
+ * chip can't just write the slave address without data.
+ * Add a dummy byte.
+ */
+ RegWrite(map, R5_DC_I2C_CONTROL2,
+ prescale << 16 |
+ (nWrite ? nWrite : 1) << 8 | 0x01); /* addr_cnt: 1 */
+ RegMask(map, R5_DC_I2C_CONTROL3,
+ 0x30 << 24, 0xff << 24); /* time limit 30 */
+
+ RegWrite(map, R5_DC_I2C_DATA, slave);
+
+ /* Add dummy byte */
+ if (!nWrite)
+ RegWrite(map, R5_DC_I2C_DATA, 0);
+ else
+ while (nWrite--)
+ RegWrite(map, R5_DC_I2C_DATA, *WriteBuffer++);
+
+ RegMask(map, R5_DC_I2C_CONTROL1,
+ R5_DC_I2C_START | R5_DC_I2C_STOP, 0xff);
+ RegMask(map, R5_DC_I2C_STATUS1, R5_DC_I2C_GO, 0xff);
+
+ if ((ret = R5xxI2CStatus(map)))
+ RegMask(map, R5_DC_I2C_STATUS1,R5_DC_I2C_DONE, 0xff);
+ else
+ ret = FALSE;
+ }
+
+ if (ret && nRead) {
+
+ RegWrite(map, R5_DC_I2C_DATA, slave | 1); /*slave*/
+ RegWrite(map, R5_DC_I2C_CONTROL2,
+ prescale << 16 | nRead << 8 | 0x01); /* addr_cnt: 1 */
+
+ RegMask(map, R5_DC_I2C_CONTROL1,
+ R5_DC_I2C_START | R5_DC_I2C_STOP | R5_DC_I2C_RECEIVE, 0xff);
+ RegMask(map, R5_DC_I2C_STATUS1, R5_DC_I2C_GO, 0xff);
+ if ((ret = R5xxI2CStatus(map))) {
+ RegMask(map, R5_DC_I2C_STATUS1, R5_DC_I2C_DONE, 0xff);
+ while (nRead--) {
+ *(ReadBuffer++) = (CARD8)RegRead(map, R5_DC_I2C_DATA);
+ }
+ } else
+ ret = FALSE;
+ }
+
+ RegMask(map, R5_DC_I2C_STATUS1,
+ R5_DC_I2C_DONE | R5_DC_I2C_NACK | R5_DC_I2C_HALT, 0xff);
+ RegMask(map, R5_DC_I2C_RESET, R5_DC_I2C_SOFT_RESET, 0xff);
+ RegWrite(map,R5_DC_I2C_RESET, 0);
+
+ RegMask(map,R5_DC_I2C_ARBITRATION,
+ R5_DC_I2C_SW_DONE_USING_I2C, 0xff00);
+
+ RegWrite(map,R5_DC_I2C_CONTROL1, save_I2C_CONTROL1);
+ RegWrite(map,0x494, save_494);
+ tmp32 = RegRead(map,0x28);
+ RegWrite(map,0x28, tmp32 & 0xfffffdff);
+
+ return ret;
+}
+
+/*
+ *
+ */
+static Bool
+R5xxI2CWriteRead(void *map, CARD8 line, CARD8 slave,
+ unsigned char *WriteBuffer, int nWrite, unsigned char *ReadBuffer, int nRead)
+{
+ /*
+ * Since the transaction buffer can only hold
+ * 15 bytes (+ the slave address) we bail out
+ * on every transaction that is bigger unless
+ * it's a read transaction following a write
+ * transaction sending just one byte.
+ * In this case we assume, that this byte is
+ * an offset address. Thus we will restart
+ * the transaction after 15 bytes sending
+ * a new offset.
+ */
+
+ if (nWrite > 15 || (nRead > 15 && nWrite != 1)) {
+ fprintf(stderr,
+ "%s: Currently only I2C transfers with "
+ "maximally 15bytes are supported\n",
+ __func__);
+ return FALSE;
+ }
+ if (nRead > 15) {
+ unsigned char offset = *WriteBuffer;
+ while (nRead) {
+ int n = nRead > 15 ? 15 : nRead;
+ if (!R5xxI2CWriteReadChunk(map, line, slave, &offset, 1, ReadBuffer, n))
+ return FALSE;
+ ReadBuffer += n;
+ nRead -= n;
+ offset += n;
+ }
+ return TRUE;
+ } else
+ return R5xxI2CWriteReadChunk(map, line, slave, WriteBuffer, nWrite,
+ ReadBuffer, nRead);
+}
+
+/* RV620 */
+enum rv620I2CBits {
+ /* GENERIC_I2C_CONTROL */
+ RV62_DC_I2C_GO = (0x1 << 0),
+ RV62_GENERIC_I2C_GO = (0x1 << 0),
+ RV62_GENERIC_I2C_SOFT_RESET = (0x1 << 1),
+ RV62_GENERIC_I2C_SEND_RESET = (0x1 << 2),
+ /* GENERIC_I2C_INTERRUPT_CONTROL */
+ RV62_GENERIC_I2C_DONE_INT = (0x1 << 0),
+ RV62_GENERIC_I2C_DONE_ACK = (0x1 << 1),
+ RV62_GENERIC_I2C_DONE_MASK = (0x1 << 2),
+ /* GENERIC_I2C_STATUS */
+ RV62_GENERIC_I2C_STATUS_BIT = (0xf << 0),
+ RV62_GENERIC_I2C_DONE = (0x1 << 4),
+ RV62_GENERIC_I2C_ABORTED = (0x1 << 5),
+ RV62_GENERIC_I2C_TIMEOUT = (0x1 << 6),
+ RV62_GENERIC_I2C_STOPPED_ON_NACK = (0x1 << 9),
+ RV62_GENERIC_I2C_NACK = (0x1 << 10),
+ /* GENERIC_I2C_SPEED */
+ RV62_GENERIC_I2C_THRESHOLD = (0x3 << 0),
+ RV62_GENERIC_I2C_DISABLE_FILTER_DURING_STALL = (0x1 << 4),
+ RV62_GENERIC_I2C_PRESCALE = (0xffff << 16),
+ /* GENERIC_I2C_SETUP */
+ RV62_GENERIC_I2C_DATA_DRIVE_EN = (0x1 << 0),
+ RV62_GENERIC_I2C_DATA_DRIVE_SEL = (0x1 << 1),
+ RV62_GENERIC_I2C_CLK_DRIVE_EN = (0x1 << 7),
+ RV62_GENERIC_I2C_INTRA_BYTE_DELAY = (0xff << 8),
+ RV62_GENERIC_I2C_TIME_LIMIT = (0xff << 24),
+ /* GENERIC_I2C_TRANSACTION */
+ RV62_GENERIC_I2C_RW = (0x1 << 0),
+ RV62_GENERIC_I2C_STOP_ON_NACK = (0x1 << 8),
+ RV62_GENERIC_I2C_ACK_ON_READ = (0x1 << 9),
+ RV62_GENERIC_I2C_START = (0x1 << 12),
+ RV62_GENERIC_I2C_STOP = (0x1 << 13),
+ RV62_GENERIC_I2C_COUNT = (0xf << 16),
+ /* GENERIC_I2C_DATA */
+ RV62_GENERIC_I2C_DATA_RW = (0x1 << 0),
+ RV62_GENERIC_I2C_DATA_BIT = (0xff << 8),
+ RV62_GENERIC_I2C_INDEX = (0xf << 16),
+ RV62_GENERIC_I2C_INDEX_WRITE = (0x1 << 31),
+ /* GENERIC_I2C_PIN_SELECTION */
+ RV62_GENERIC_I2C_SCL_PIN_SEL = (0x7f << 0),
+ RV62_GENERIC_I2C_SDA_PIN_SEL = (0x7f << 8),
+};
+
+/*
+ *
+ */
+static Bool
+RV620I2CStatus(void *map)
+{
+ int count = 50;
+ volatile CARD32 val;
+
+ while (--count) {
+
+ usleep(10);
+ val = RegRead(map, RV62_GENERIC_I2C_STATUS);
+#ifdef DEBUG
+ fprintf(stderr,"SW_STATUS: 0x%x %i\n",(unsigned int)val,count);
+#endif
+ if (val & RV62_GENERIC_I2C_DONE)
+ break;
+ }
+ RegMask(map, RV62_GENERIC_I2C_INTERRUPT_CONTROL, 0x2, 0xff);
+
+ if (!count
+ || (val & (RV62_GENERIC_I2C_STOPPED_ON_NACK | RV62_GENERIC_I2C_NACK
+ | RV62_GENERIC_I2C_TIMEOUT | RV62_GENERIC_I2C_ABORTED)))
+ return FALSE; /* 2 */
+
+ return TRUE; /* 1 */
+}
+
+/*
+ *
+ */
+static Bool
+RV620I2CSetupStatus(void *map, int line, int prescale)
+{
+/* CARD32 reg_7d9c[] = { 0x1, 0x0203, 0x0405, 0x0607 }; */
+ CARD32 reg_7d9c;
+ unsigned char *table;
+ short size = 0;
+ int i = 0;
+
+ if (line > 3)
+ return FALSE;
+
+ table = AtomBiosGetDataFromCodeTable(command_table, 0x36, &size);
+ while (i < size) {
+ if (table[i] == line) {
+ reg_7d9c = table[i + 3] << 8 | table[i + 2];
+#ifdef DEBUG
+ fprintf(stderr, "Line[%i] = 0x%4.4x\n",line, reg_7d9c);
+#endif
+ break;
+ }
+ i += 4;
+ }
+ if (i >= size)
+ return FALSE;
+
+ RegWrite(map, 0x7e40, 0);
+ RegWrite(map, 0x7e50, 0);
+ RegWrite(map, 0x7e60, 0);
+ RegWrite(map, 0x7e20, 0);
+
+ RegWrite(map, RV62_GENERIC_I2C_PIN_SELECTION, reg_7d9c);
+ RegMask(map, RV62_GENERIC_I2C_SPEED,
+ (prescale & 0xffff) << 16 | 0x02, 0xffff00ff);
+ RegWrite(map, RV62_GENERIC_I2C_SETUP, 0x30000000);
+ RegMask(map, RV62_GENERIC_I2C_INTERRUPT_CONTROL,
+ RV62_GENERIC_I2C_DONE_ACK, RV62_GENERIC_I2C_DONE_ACK);
+
+ return TRUE;
+}
+
+/*
+ *
+ */
+static Bool
+RV620I2CTransaction(void *map, CARD8 slave, Bool Write,
+ unsigned char *Buffer, int count)
+{
+ Bool Start = TRUE;
+
+#define MAX 8
+
+ while (count > 0) {
+ int num;
+ int idx = 0;
+ CARD32 data = 0;
+
+ if (count > MAX) {
+ num = MAX;
+ RegMask(map, RV62_GENERIC_I2C_TRANSACTION,
+ (MAX - (((Start) ? 0 : 1))) << 16
+ | RV62_GENERIC_I2C_STOP_ON_NACK
+ | RV62_GENERIC_I2C_ACK_ON_READ
+ | (Start ? RV62_GENERIC_I2C_START : 0)
+ | (!Write ? RV62_GENERIC_I2C_RW : 0 ),
+ 0xFFFFFF);
+ } else {
+ num = count;
+ data = ( count - (((Start) ? 0 : 1)) ) << 16
+ | RV62_GENERIC_I2C_STOP_ON_NACK
+ | RV62_GENERIC_I2C_STOP
+ | (Start ? RV62_GENERIC_I2C_START : 0)
+ | (!Write ? RV62_GENERIC_I2C_RW : 0);
+ RegMask(map, RV62_GENERIC_I2C_TRANSACTION,
+ data,
+ 0xFFFFFF);
+ }
+
+ if (Start) {
+ data = RV62_GENERIC_I2C_INDEX_WRITE
+ | (((slave & 0xfe) | ( Write ? 0 : 1)) << 8)
+ | (idx++ << 16);
+ RegWrite(map, RV62_GENERIC_I2C_DATA, data);
+ }
+
+ if (Write) {
+ while (num--) {
+ data = RV62_GENERIC_I2C_INDEX_WRITE
+ | (idx++ << 16)
+ | *(Buffer++) << 8;
+ RegWrite(map, RV62_GENERIC_I2C_DATA, data);
+ }
+
+ RegMask(map, RV62_GENERIC_I2C_CONTROL,
+ RV62_GENERIC_I2C_GO, RV62_GENERIC_I2C_GO);
+ if (!RV620I2CStatus(map))
+ return FALSE;
+ } else {
+
+ RegMask(map, RV62_GENERIC_I2C_CONTROL,
+ RV62_GENERIC_I2C_GO, RV62_GENERIC_I2C_GO);
+ if (!RV620I2CStatus(map))
+ return FALSE;
+
+ RegWrite(map, RV62_GENERIC_I2C_DATA,
+ RV62_GENERIC_I2C_INDEX_WRITE
+ | (idx++ << 16)
+ | RV62_GENERIC_I2C_RW);
+
+ while (num--) {
+ data = RegRead(map, RV62_GENERIC_I2C_DATA);
+ *(Buffer++) = (CARD8)((data >> 8) & 0xff);
+ }
+ }
+ Start = FALSE;
+ count -= MAX;
+ }
+ return TRUE;
+}
+
+/*
+ *
+ */
+static Bool
+RV620I2CWriteRead(void *map, CARD8 line, CARD8 slave,
+ unsigned char *WriteBuffer, int nWrite, unsigned char *ReadBuffer, int nRead)
+{
+ int prescale = getDDCSpeed();
+
+ if (!prescale)
+ return FALSE;
+
+ RV620I2CSetupStatus(map, line, prescale);
+
+ if (!nWrite && !nRead)
+ return RV620I2CTransaction(map, slave, TRUE, (unsigned char *)"", 1);
+
+ if (nWrite)
+ if (!RV620I2CTransaction(map, slave, TRUE, WriteBuffer, nWrite))
+ return FALSE;
+
+ if (nRead)
+ if (!RV620I2CTransaction(map, slave, FALSE, ReadBuffer, nRead))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ *
+ */
+static Bool
+RV620DDCProbe(void *map, int Channel, unsigned char slave)
+{
+ return RV620I2CWriteRead(map, Channel, slave, NULL, 0, NULL, 0);
+}
+
+/*
+ *
+ */
static Bool
-DDCProbe(void *map, int Channel, unsigned char slave)
+DDCProbe(void *map, int Channel, unsigned char slave, unsigned char *data, int count)
{
+ Bool ret;
+ unsigned char offset = 0;
+
switch (ChipType) {
case RHD_R500:
- return R5xxDDCProbe(map, Channel, slave);
+ if (( ret = R5xxDDCProbe(map, Channel, slave)) && count > 0) {
+ ret = R5xxI2CWriteRead(map, Channel, slave, &offset, 1, data, count);
+ };
+ return ret;
case RHD_RS690:
- return RS69DDCProbe(map, Channel, slave);
+ if ((ret = RS69DDCProbe(map, Channel, slave)) && count > 0) {
+ ret = RS69xI2CWriteRead(map, Channel, slave, &offset, 1, data, count);
+ };
+ return ret;
case RHD_R600:
- return R6xxDDCProbe(map, Channel, slave);
+ if ((ret = R6xxDDCProbe(map, Channel, slave)) && count > 0) {
+ ret = R6xxI2CWriteRead(map, Channel, slave, &offset, 1, data, count);
+ };
+ return ret;
+ case RHD_RV620:
+ if ((ret = RV620DDCProbe(map, Channel, slave)) && count > 0) {
+ ret = RV620I2CWriteRead(map, Channel, slave, &offset, 1, data, count);
+ };
+ return ret;
default:
return FALSE;
}
@@ -1146,11 +1976,11 @@ DDCReport(void *map)
{
Bool Chan0, Chan1, Chan2, Chan3;
- Chan0 = DDCProbe(map, 0, EDID_SLAVE);
- Chan1 = DDCProbe(map, 1, EDID_SLAVE);
- Chan2 = DDCProbe(map, 2, EDID_SLAVE);
+ Chan0 = DDCProbe(map, 0, EDID_SLAVE, NULL, 0);
+ Chan1 = DDCProbe(map, 1, EDID_SLAVE, NULL, 0);
+ Chan2 = DDCProbe(map, 2, EDID_SLAVE, NULL, 0);
if (ChipType >= RHD_R600)
- Chan3 = DDCProbe(map, 3, EDID_SLAVE);
+ Chan3 = DDCProbe(map, 3, EDID_SLAVE, NULL, 0);
else
Chan3 = FALSE;
@@ -1177,23 +2007,32 @@ DDCReport(void *map)
*
*/
static void
-DDCScanBus(void *map)
+DDCScanBus(void *map, int count)
{
int channel;
unsigned char slave;
int max_chan = ((ChipType >= RHD_R600) ? 3 : 2);
+ unsigned char *data = NULL;
+
+ if (count)
+ data = alloca(count);
for (channel = 0; channel < max_chan; channel ++) {
int state = 0;
for (slave = 0x8; slave < 0x78; slave++ ) {
- if (DDCProbe(map, channel, slave << 1)) {
+ if (DDCProbe(map, channel, slave << 1, data, count)) {
if (state == 0) {
printf(" DDC Line[%i]: Slaves: ", channel);
- state = 1;
+ if (!data)
+ state = 1;
}
printf("%x ", slave << 1);
+ if (data) {
+ printf("\n");
+ dprint(data, count);
+ }
}
}
if (state == 1)
@@ -1222,7 +2061,7 @@ LVDSReport(void *map)
DualLink = RegRead(map, LVTMA_CNTL) & 0x01000000;
Bits24 = RegRead(map, LVTMA_LVDS_DATA_CNTL) & 0x1;
- Fpdi = RegRead(map, LVTMA_LVDS_DATA_CNTL) & 0x1;
+ Fpdi = RegRead(map, LVTMA_LVDS_DATA_CNTL) & 0x10;
printf("\t%dbits, %s link, %s Panel found.\n",
Bits24 ? 24 : 18,
@@ -1348,13 +2187,14 @@ AnalyzeCommonHdr(ATOM_COMMON_TABLE_HEADER *hdr)
static int
AnalyzeRomHdr(unsigned char *rombase,
ATOM_ROM_HEADER *hdr,
- int *data_offset)
+ int *data_offset, int *code_offset)
{
if (AnalyzeCommonHdr(&hdr->sHeader) == -1) {
return FALSE;
}
*data_offset = hdr->usMasterDataTableOffset;
+ *code_offset = hdr->usMasterCommandTableOffset;
return TRUE;
}
@@ -1433,6 +2273,7 @@ print_help(const char* progname, const char* message, const char* msgarg)
fprintf(stderr, "Usage: %s [options] PCI-tag\n"
" Options: -d: dumpBios\n"
" -s: scanDDCBus\n"
+ " -x num: dump num bytes from available i2c channels\n"
" PCI-tag: bus:dev.func\n\n",
progname);
}
@@ -1440,10 +2281,101 @@ print_help(const char* progname, const char* message, const char* msgarg)
/*
*
*/
+struct atomCodeDataTableHeader
+{
+ unsigned char signature;
+ unsigned short size;
+};
+
+#define CODE_DATA_TABLE_SIGNATURE 0x7a
+#define ATOM_EOT_COMMAND 0x5b
+
+unsigned char *
+AtomBiosGetDataFromCodeTable(unsigned char **tablelist, int n, short *size)
+{
+ ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *header = (ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)
+ tablelist[n];
+ unsigned char *code;
+ int i;
+
+ if (!header)
+ return NULL;
+ if (!AnalyzeCommonHdr(&header->CommonHeader))
+ return NULL;
+ if (!GetAtomBiosTableRevisionAndSize(&header->CommonHeader,NULL,NULL,size))
+ return NULL;
+
+ code = (unsigned char *)header;
+#ifdef DEBUG
+ fprintf(stderr, "table[%2.2i].size = 0x%3.3x bytes\n",n,*size);
+#endif
+for (i = sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER); i < *size - 1; i++) {
+
+ if (code[i] == ATOM_EOT_COMMAND
+ && code[i+1] == CODE_DATA_TABLE_SIGNATURE) {
+
+ struct atomCodeDataTableHeader *dt
+ = (struct atomCodeDataTableHeader *)&code[i];
+ int diff;
+ diff = *size - (i + 1) + sizeof(struct atomCodeDataTableHeader)
+ + SHORT(dt->size);
+
+ if (diff < 0) {
+ fprintf(stderr,
+ "Data table in command table %i extends %i bytes "
+ "beyond command table size\n",
+ n, -diff);
+ return NULL;
+ } else {
+#ifdef DEBUG
+ fprintf(stderr, "code data table size: 0x%4.4x\n",SHORT(dt->size));
+ dprint(&code[i + sizeof(struct atomCodeDataTableHeader)], SHORT(dt->size));
+#endif
+ return &code[i + sizeof(struct atomCodeDataTableHeader)];
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *
+ */
+unsigned char **
+AtomBiosAnalyzeCommandTable(ATOM_MASTER_COMMAND_TABLE *table, unsigned char *base, int *num)
+{
+ short size;
+ int i;
+ unsigned char **tablelist = NULL;
+ unsigned short offset;
+
+ *num = sizeof(ATOM_MASTER_LIST_OF_COMMAND_TABLES)/sizeof(USHORT);
+
+ if (!AnalyzeCommonHdr(&table->sHeader))
+ return NULL;
+ if (!GetAtomBiosTableRevisionAndSize(&table->sHeader,NULL,NULL,&size))
+ return NULL;
+ if ((tablelist = (unsigned char **)calloc(*num, sizeof (char *)))) {
+ for (i = 0; i < *num; i++)
+ if ((offset = ((USHORT *)&(table->ListOfCommandTables))[i])) {
+#ifdef DEBUG
+ fprintf(stderr, "CommandTableEntry[%2.2i] = 0x%4.4x\n",i,offset);
+#endif
+ tablelist[i] = base + offset;
+ } else
+ tablelist[i] = NULL;
+ }
+
+ return tablelist;
+}
+
+/*
+ *
+ */
static Bool
InterpretATOMBIOS(unsigned char *base)
{
- int data_offset;
+ int data_offset, code_offset;
unsigned short atom_romhdr_off = *(unsigned short*)
(base + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
@@ -1453,7 +2385,7 @@ InterpretATOMBIOS(unsigned char *base)
fprintf(stderr,"No AtomBios signature found\n");
return FALSE;
}
- if (!AnalyzeRomHdr(base, atom_rom_hdr, &data_offset)) {
+ if (!AnalyzeRomHdr(base, atom_rom_hdr, &data_offset, &code_offset)) {
fprintf(stderr, "RomHeader invalid\n");
return FALSE;
}
@@ -1462,6 +2394,10 @@ InterpretATOMBIOS(unsigned char *base)
fprintf(stderr, "ROM Master Table invalid\n");
return FALSE;
}
+ command_table =
+ AtomBiosAnalyzeCommandTable((ATOM_MASTER_COMMAND_TABLE *)(base + code_offset),
+ base, &num_command_table_entries);
+
return TRUE;
}
@@ -1471,15 +2407,17 @@ InterpretATOMBIOS(unsigned char *base)
int
main(int argc, char *argv[])
{
- struct pci_dev *device;
+ struct pci_dev *device = NULL;
struct pci_access *pciAccess;
- struct RHDDevice *rhdDevice;
+ struct RHDDevice *rhdDevice = NULL;
int devMem;
void *io;
int bus, dev, func;
int ret;
int saved_errno;
- Bool dumpBios, deviceSet, scanDDCBus;
+ Bool deviceSet = FALSE;
+ Bool dumpBios = FALSE, scanDDCBus = FALSE;
+ unsigned long DumpI2CData = 0;
int i;
unsigned char *rombase;
int size;
@@ -1503,6 +2441,16 @@ main(int argc, char *argv[])
dumpBios = TRUE;
} else if (!strncmp("-s",argv[i],3)) {
scanDDCBus = TRUE;
+ } else if (!strncmp("-x",argv[i],3)) {
+ if (++i == argc || !strncmp("-", argv[i], 1)) {
+ print_help(argv[0], "Option -x requires an argument","");
+ return 1;
+ }
+ DumpI2CData = strtol(argv[i], NULL, 0);
+ if (DumpI2CData > 256) {
+ fprintf(stderr, "can only dump up to 256 bytes");
+ return -1;
+ }
} else if (!strncmp("-",argv[i],1)) {
print_help(argv[0], "Unknown option", argv[i]);
return 1;
@@ -1602,8 +2550,8 @@ main(int argc, char *argv[])
DDCReport(io);
LVDSReport(io);
- if (scanDDCBus)
- DDCScanBus(io);
+ if (scanDDCBus || DumpI2CData)
+ DDCScanBus(io, DumpI2CData);
FreeVBIOS(rombase, size);
diff --git a/driver/xf86-video-radeonhd/utils/conntest/rhd_dump.c b/driver/xf86-video-radeonhd/utils/conntest/rhd_dump.c
new file mode 100644
index 000000000..8974d104b
--- /dev/null
+++ b/driver/xf86-video-radeonhd/utils/conntest/rhd_dump.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2007, 2008 Luc Verhaegen <lverhaegen@novell.com>
+ * Copyright 2007, 2008 Matthias Hopf <mhopf@novell.com>
+ * Copyright 2007, 2008 Egbert Eich <eich@novell.com>
+ * Copyright 2007, 2008 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+/* #define DEBUG */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <pci/pci.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define DEFAULT_START 0x7200
+#define DEFAULT_END 0x7300
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include "git_version.h"
+
+#ifndef ULONG
+typedef unsigned int ULONG;
+# define ULONG ULONG
+#endif
+#ifndef UCHAR
+typedef unsigned char UCHAR;
+# define UCHAR UCHAR
+#endif
+#ifndef USHORT
+typedef unsigned short USHORT;
+# define USHORT USHORT
+#endif
+
+#include "atombios.h"
+
+typedef int Bool;
+#define FALSE 0
+#define TRUE 1
+typedef unsigned char CARD8;
+typedef unsigned short CARD16;
+typedef unsigned int CARD32;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define SHORT(x) (x)
+#else
+#define SHORT(x) (((x & 0xff) << 8) | ((x & 0xff) >> 8))
+#endif
+
+#define DEV_MEM "/dev/mem"
+
+typedef enum _chipType {
+ RHD_R500 = 1,
+ RHD_RS690,
+ RHD_R600,
+ RHD_RV620
+} chipType;
+
+/* for RHD_R500/R600 */
+chipType ChipType;
+
+/*
+ * Match pci ids against data and some callbacks
+ */
+struct RHDDevice {
+ CARD16 vendor;
+ CARD16 device;
+ int bar;
+ chipType type;
+} rhdDevices[] = {
+
+ { 0x1002, 0x7100, 2, RHD_R500},
+ { 0x1002, 0x7101, 2, RHD_R500},
+ { 0x1002, 0x7102, 2, RHD_R500},
+ { 0x1002, 0x7103, 2, RHD_R500},
+ { 0x1002, 0x7104, 2, RHD_R500},
+ { 0x1002, 0x7105, 2, RHD_R500},
+ { 0x1002, 0x7106, 2, RHD_R500},
+ { 0x1002, 0x7108, 2, RHD_R500},
+ { 0x1002, 0x7109, 2, RHD_R500},
+ { 0x1002, 0x710A, 2, RHD_R500},
+ { 0x1002, 0x710B, 2, RHD_R500},
+ { 0x1002, 0x710C, 2, RHD_R500},
+ { 0x1002, 0x710E, 2, RHD_R500},
+ { 0x1002, 0x710F, 2, RHD_R500},
+ { 0x1002, 0x7140, 2, RHD_R500},
+ { 0x1002, 0x7141, 2, RHD_R500},
+ { 0x1002, 0x7142, 2, RHD_R500},
+ { 0x1002, 0x7143, 2, RHD_R500},
+ { 0x1002, 0x7144, 2, RHD_R500},
+ { 0x1002, 0x7145, 2, RHD_R500},
+ { 0x1002, 0x7146, 2, RHD_R500},
+ { 0x1002, 0x7147, 2, RHD_R500},
+ { 0x1002, 0x7149, 2, RHD_R500},
+ { 0x1002, 0x714A, 2, RHD_R500},
+ { 0x1002, 0x714B, 2, RHD_R500},
+ { 0x1002, 0x714C, 2, RHD_R500},
+ { 0x1002, 0x714D, 2, RHD_R500},
+ { 0x1002, 0x714E, 2, RHD_R500},
+ { 0x1002, 0x714F, 2, RHD_R500},
+ { 0x1002, 0x7151, 2, RHD_R500},
+ { 0x1002, 0x7152, 2, RHD_R500},
+ { 0x1002, 0x7153, 2, RHD_R500},
+ { 0x1002, 0x715E, 2, RHD_R500},
+ { 0x1002, 0x715F, 2, RHD_R500},
+ { 0x1002, 0x7180, 2, RHD_R500},
+ { 0x1002, 0x7181, 2, RHD_R500},
+ { 0x1002, 0x7183, 2, RHD_R500},
+ { 0x1002, 0x7186, 2, RHD_R500},
+ { 0x1002, 0x7187, 2, RHD_R500},
+ { 0x1002, 0x7188, 2, RHD_R500},
+ { 0x1002, 0x718A, 2, RHD_R500},
+ { 0x1002, 0x718B, 2, RHD_R500},
+ { 0x1002, 0x718C, 2, RHD_R500},
+ { 0x1002, 0x718D, 2, RHD_R500},
+ { 0x1002, 0x718F, 2, RHD_R500},
+ { 0x1002, 0x7193, 2, RHD_R500},
+ { 0x1002, 0x7196, 2, RHD_R500},
+ { 0x1002, 0x719B, 2, RHD_R500},
+ { 0x1002, 0x719F, 2, RHD_R500},
+ { 0x1002, 0x71C0, 2, RHD_R500},
+ { 0x1002, 0x71C1, 2, RHD_R500},
+ { 0x1002, 0x71C2, 2, RHD_R500},
+ { 0x1002, 0x71C3, 2, RHD_R500},
+ { 0x1002, 0x71C4, 2, RHD_R500},
+ { 0x1002, 0x71C5, 2, RHD_R500},
+ { 0x1002, 0x71C6, 2, RHD_R500},
+ { 0x1002, 0x71C7, 2, RHD_R500},
+ { 0x1002, 0x71CD, 2, RHD_R500},
+ { 0x1002, 0x71CE, 2, RHD_R500},
+ { 0x1002, 0x71D2, 2, RHD_R500},
+ { 0x1002, 0x71D4, 2, RHD_R500},
+ { 0x1002, 0x71D5, 2, RHD_R500},
+ { 0x1002, 0x71D6, 2, RHD_R500},
+ { 0x1002, 0x71DA, 2, RHD_R500},
+ { 0x1002, 0x71DE, 2, RHD_R500},
+ { 0x1002, 0x7200, 2, RHD_R500},
+ { 0x1002, 0x7210, 2, RHD_R500},
+ { 0x1002, 0x7211, 2, RHD_R500},
+ { 0x1002, 0x7240, 2, RHD_R500},
+ { 0x1002, 0x7243, 2, RHD_R500},
+ { 0x1002, 0x7244, 2, RHD_R500},
+ { 0x1002, 0x7245, 2, RHD_R500},
+ { 0x1002, 0x7246, 2, RHD_R500},
+ { 0x1002, 0x7247, 2, RHD_R500},
+ { 0x1002, 0x7248, 2, RHD_R500},
+ { 0x1002, 0x7249, 2, RHD_R500},
+ { 0x1002, 0x724A, 2, RHD_R500},
+ { 0x1002, 0x724B, 2, RHD_R500},
+ { 0x1002, 0x724C, 2, RHD_R500},
+ { 0x1002, 0x724D, 2, RHD_R500},
+ { 0x1002, 0x724E, 2, RHD_R500},
+ { 0x1002, 0x724F, 2, RHD_R500},
+ { 0x1002, 0x7280, 2, RHD_R500},
+ { 0x1002, 0x7281, 2, RHD_R500},
+ { 0x1002, 0x7283, 2, RHD_R500},
+ { 0x1002, 0x7284, 2, RHD_R500},
+ { 0x1002, 0x7287, 2, RHD_R500},
+ { 0x1002, 0x7288, 2, RHD_R500},
+ { 0x1002, 0x7289, 2, RHD_R500},
+ { 0x1002, 0x728B, 2, RHD_R500},
+ { 0x1002, 0x728C, 2, RHD_R500},
+ { 0x1002, 0x7290, 2, RHD_R500},
+ { 0x1002, 0x7291, 2, RHD_R500},
+ { 0x1002, 0x7293, 2, RHD_R500},
+ { 0x1002, 0x7297, 2, RHD_R500},
+ { 0x1002, 0x791E, 2, RHD_RS690},
+ { 0x1002, 0x791F, 2, RHD_RS690},
+ { 0x1002, 0x793F, 2, RHD_RS690},
+ { 0x1002, 0x7941, 2, RHD_RS690},
+ { 0x1002, 0x7942, 2, RHD_RS690},
+ { 0x1002, 0x796C, 2, RHD_R500},
+ { 0x1002, 0x796D, 2, RHD_R500},
+ { 0x1002, 0x796E, 2, RHD_R500},
+ { 0x1002, 0x796F, 2, RHD_R500},
+ { 0x1002, 0x9400, 2, RHD_R600},
+ { 0x1002, 0x9401, 2, RHD_R600},
+ { 0x1002, 0x9402, 2, RHD_R600},
+ { 0x1002, 0x9403, 2, RHD_R600},
+ { 0x1002, 0x9405, 2, RHD_R600},
+ { 0x1002, 0x940A, 2, RHD_R600},
+ { 0x1002, 0x940B, 2, RHD_R600},
+ { 0x1002, 0x940F, 2, RHD_R600},
+ { 0x1002, 0x94C0, 2, RHD_R600},
+ { 0x1002, 0x94C1, 2, RHD_R600},
+ { 0x1002, 0x94C3, 2, RHD_R600},
+ { 0x1002, 0x94C4, 2, RHD_R600},
+ { 0x1002, 0x94C5, 2, RHD_R600},
+ { 0x1002, 0x94C6, 2, RHD_R600},
+ { 0x1002, 0x94C7, 2, RHD_R600},
+ { 0x1002, 0x94C8, 2, RHD_R600},
+ { 0x1002, 0x94C9, 2, RHD_R600},
+ { 0x1002, 0x94CB, 2, RHD_R600},
+ { 0x1002, 0x94CC, 2, RHD_R600},
+ { 0x1002, 0x9500, 2, RHD_R600},
+ { 0x1002, 0x9501, 2, RHD_R600},
+ { 0x1002, 0x9505, 2, RHD_R600},
+ { 0x1002, 0x9507, 2, RHD_R600},
+ { 0x1002, 0x950F, 2, RHD_R600},
+ { 0x1002, 0x9511, 2, RHD_R600},
+ { 0x1002, 0x9580, 2, RHD_R600},
+ { 0x1002, 0x9581, 2, RHD_R600},
+ { 0x1002, 0x9583, 2, RHD_R600},
+ { 0x1002, 0x9586, 2, RHD_R600},
+ { 0x1002, 0x9587, 2, RHD_R600},
+ { 0x1002, 0x9588, 2, RHD_R600},
+ { 0x1002, 0x9589, 2, RHD_R600},
+ { 0x1002, 0x958A, 2, RHD_R600},
+ { 0x1002, 0x958B, 2, RHD_R600},
+ { 0x1002, 0x958C, 2, RHD_R600},
+ { 0x1002, 0x958D, 2, RHD_R600},
+ { 0x1002, 0x958E, 2, RHD_R600},
+ { 0x1002, 0x9598, 2, RHD_RV620},
+ { 0x1002, 0x95C5, 2, RHD_RV620},
+ { 0x1002, 0x9612, 2, RHD_RV620},
+ { 0, 0, 0, 0 }
+};
+
+/*
+ *
+ */
+static struct pci_dev *
+DeviceLocate(struct pci_dev *devices, int bus, int dev, int func)
+{
+ struct pci_dev *device;
+
+ for (device = devices; device; device = device->next)
+ if ((device->bus == bus) && (device->dev == dev) &&
+ (device->func == func))
+ return device;
+ return NULL;
+}
+
+/*
+ *
+ */
+static struct RHDDevice *
+DeviceMatch(struct pci_dev *device)
+{
+ int i;
+
+ for (i = 0; rhdDevices[i].vendor; i++)
+ if ((rhdDevices[i].vendor == device->vendor_id) &&
+ (rhdDevices[i].device == device->device_id))
+ return (rhdDevices + i);
+
+ return NULL;
+}
+
+/*
+ *
+ */
+static void *
+MapBar(struct pci_dev *device, int ioBar, int devMem)
+{
+ void *map;
+
+ if (!device->base_addr[ioBar] || !device->size[ioBar])
+ return NULL;
+
+ map = mmap(0, device->size[ioBar], PROT_WRITE | PROT_READ, MAP_SHARED,
+ devMem, device->base_addr[ioBar]);
+ /* printf("Mapped IO at 0x%08llX (BAR %1d: 0x%08llX)\n",
+ device->base_addr[io_bar], io_bar, device->size[io_bar]); */
+
+ return map;
+}
+
+/*
+ *
+ */
+CARD32
+RegRead(void *map, int offset)
+{
+ CARD32 ret = *(volatile CARD32 *)((CARD8 *) map + offset);
+#ifdef DEBUG
+ fprintf(stderr, "0x%x = RegRead(0x%x)\n",ret,offset);
+#endif
+ return ret;
+}
+
+/*
+ *
+ */
+void
+RegWrite(void *map, int offset, CARD32 value)
+{
+#ifdef DEBUG
+ fprintf(stderr, "RegWrite(0x%x, 0x%x)\n",offset,value);
+#endif
+ *(volatile CARD32 *)((CARD8 *) map + offset) = value;
+}
+
+/*
+ *
+ */
+void
+RegMask(void *map, int offset, CARD32 value, CARD32 mask)
+{
+ CARD32 tmp;
+
+ tmp = RegRead(map, offset);
+ tmp &= ~mask;
+ tmp |= (value & mask);
+ RegWrite(map, offset, tmp);
+}
+
+void
+print_help(const char* progname, const char* message, const char* msgarg)
+{
+ if (message != NULL)
+ fprintf(stderr, "%s %s\n", message, msgarg);
+ fprintf(stderr, "Usage: %s [start,end] PCI-tag\n"
+ " PCI-tag: bus:dev.func\n\n",
+ progname);
+}
+
+
+/*
+ *
+ */
+int
+main(int argc, char *argv[])
+{
+ struct pci_dev *device = NULL;
+ struct pci_access *pciAccess;
+ struct RHDDevice *rhdDevice = NULL;
+ int devMem;
+ void *io;
+ int bus, dev, func;
+ int ret;
+ int saved_errno;
+ Bool deviceSet = FALSE;
+ CARD32 start = DEFAULT_START, end = DEFAULT_END;
+ int i;
+ unsigned int j;
+
+
+ printf("%s: v%s, %s\n",
+ "rhd_conntest", PACKAGE_VERSION, GIT_MESSAGE);
+
+ /* init libpci */
+ pciAccess = pci_alloc();
+ pci_init(pciAccess);
+ pci_scan_bus(pciAccess);
+
+ if (argc < 2) {
+ print_help(argv[0], "Missing argument: please provide a PCI tag\n",
+ "");
+ return 1;
+ }
+
+ for (i = 1; i < argc; i++) {
+ if (!strncmp("-r",argv[i],3)) {
+ if (++i < argc)
+ ret = sscanf(argv[i], "%x,%x", &start, &end);
+ else {
+ i--;
+ ret = 0;
+ }
+ if (ret != 2) {
+ print_help(argv[0], "Unable to read range: ", argv[i]);
+ return 1;
+ }
+ if (start & 0x3) {
+ fprintf(stderr, "%s: range start 0x%4.4X not four byte aligned\n",argv[0], start);
+ return 1;
+ }
+ }
+ else if (!strncmp("-",argv[i],1)) {
+ print_help(argv[0], "Unknown option", argv[i]);
+ return 1;
+ } else {
+ ret = sscanf(argv[i], "%x:%x.%x", &bus, &dev, &func);
+ if (ret != 3) {
+ ret = sscanf(argv[i], "%x:%x:%x", &bus, &dev, &func);
+ if (ret != 3) {
+ ret = sscanf(argv[i], "%d:%d.%d", &bus, &dev, &func);
+ if (ret != 3)
+ ret = sscanf(argv[i], "%d:%d:%d", &bus, &dev, &func);
+ }
+ }
+ if (ret != 3) {
+ print_help(argv[0], "Unable to parse the PCI tag argument: ",
+ argv[i]);
+ return 1;
+ }
+ deviceSet = TRUE;
+ }
+ }
+
+ if (deviceSet) {
+ /* find our toy */
+ device = DeviceLocate(pciAccess->devices, bus, dev, func);
+ if (!device) {
+ fprintf(stderr, "Unable to find PCI device at %02X:%02X.%02X.\n",
+ bus, dev, func);
+ return 1;
+ }
+
+ rhdDevice = DeviceMatch(device);
+ if (!rhdDevice) {
+ fprintf(stderr,
+ "Unknown device: 0x%04X:0x%04X (%02X:%02X.%02X).\n",
+ device->vendor_id, device->device_id, bus, dev, func);
+ return 1;
+ }
+ }
+
+ /* make sure we can actually read DEV_MEM before we do anything else */
+ devMem = open(DEV_MEM, O_RDWR);
+ if (devMem < 0) {
+ fprintf(stderr, "Unable to open "DEV_MEM": %s.\n", strerror(errno));
+ return errno;
+ }
+
+ io = MapBar(device, rhdDevice->bar, devMem);
+ saved_errno = errno;
+ close (devMem);
+ if (!io) {
+ fprintf(stderr, "Unable to map IO memory: %s.\n",
+ strerror(saved_errno));
+ return 1;
+ }
+
+ ChipType = rhdDevice->type;
+
+ for (j = start; j <= end; j+=4) {
+ CARD32 val = RegRead(io, j);
+ printf("0x%4.4X: 0x%8.8X\n",j, val);
+ }
+
+ return 0;
+}