diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2008-04-19 13:41:47 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2008-04-19 13:41:47 +0000 |
commit | 6955fa2ff594e9f967f66d061747d7cccf012c62 (patch) | |
tree | 6dfea27eeb65762163afcdba33b4c25f783eee63 /driver/xf86-video-radeonhd/utils | |
parent | edf5e5abd24979eb74e8a9b7ae0c2198743114aa (diff) |
Update to xf86-video-radeonhd 1.2.0. Tested by jdixon@ and jasper@
Diffstat (limited to 'driver/xf86-video-radeonhd/utils')
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; +} |