diff options
author | Jordan Crouse <jordan.crouse@amd.com> | 2006-12-20 17:30:44 -0700 |
---|---|---|
committer | Jordan Crouse <jordan.crouse@amd.com> | 2006-12-20 17:32:28 -0700 |
commit | fb92319afde24b91c64314e4f2d8725fa2cd61fe (patch) | |
tree | d1a381aeaa7616dd5ac966c459a70ccbe5926ce6 /src/durango.c | |
parent | e34f70fc46b36a0ea26636045ce9f9bf24ec89cd (diff) |
Replace the VSA MSR interface with something more sane
Diffstat (limited to 'src/durango.c')
-rw-r--r-- | src/durango.c | 398 |
1 files changed, 164 insertions, 234 deletions
diff --git a/src/durango.c b/src/durango.c index 9fcfa6f..9f8efb7 100644 --- a/src/durango.c +++ b/src/durango.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2003-2005 Advanced Micro Devices, Inc. +/* Copyright (c) 2003-2006 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 @@ -23,159 +23,75 @@ * software without specific prior written permission. * */ -/* - * This is the main file used to add Durango graphics support to a software - * project. The main reason to have a single file include the other files - * is that it centralizes the location of the compiler options. This file - * should be tuned for a specific implementation, and then modified as needed - * for new Durango releases. The releases.txt file indicates any updates to - * this main file, such as a new definition for a new hardware platform. - * - * In other words, this file should be copied from the Durango source files - * once when a software project starts, and then maintained as necessary. - * It should not be recopied with new versions of Durango unless the - * developer is willing to tune the file again for the specific project. - * */ +/* The previous version of this file was way more complex then it should have + been - remove the unnessesary #defines and routines, and concentrate on + Linux for now. +*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif -/* COMPILER OPTIONS - * These compiler options specify how the Durango routines are compiled - * for the different hardware platforms. For best performance, a driver - * would build for a specific platform. The "dynamic" switches are set - * by diagnostic applications such as Darwin that will run on a variety - * of platforms and use the appropriate code at runtime. Each component - * may be separately dynamic, so that a driver has the option of being - * tuned for a specific 2D accelerator, but will still run with a variety - * of chipsets. - */ - -#define GFX_DISPLAY_DYNAMIC 0 /* runtime selection */ -#define GFX_DISPLAY_GU1 0 /* 1st generation display controller */ -#define GFX_DISPLAY_GU2 1 /* 2nd generation display controller */ -#define GFX_DISPLAY_GU3 0 /* 3nd generation display controller */ - -#define GFX_INIT_DYNAMIC 0 /* runtime selection */ -#define GFX_INIT_GU1 0 /* Geode family */ -#define GFX_INIT_GU2 1 /* Redcloud */ -#define GFX_INIT_GU3 0 /* Castle */ - -#define GFX_MSR_DYNAMIC 1 /* runtime selection */ -#define GFX_MSR_REDCLOUD 1 /* Redcloud */ - -#define GFX_2DACCEL_DYNAMIC 0 /* runtime selection */ -#define GFX_2DACCEL_GU1 0 /* 1st generation 2D accelerator */ -#define GFX_2DACCEL_GU2 1 /* 2nd generation 2D accelerator */ - -#define GFX_VIDEO_DYNAMIC 0 /* runtime selection */ -#define GFX_VIDEO_CS5530 0 /* support for CS5530 */ -#define GFX_VIDEO_SC1200 0 /* support for SC1200 */ -#define GFX_VIDEO_REDCLOUD 1 /* support for Redcloud */ -#define GFX_VIDEO_CASTLE 0 /* support for Castle */ - -#define GFX_VIP_DYNAMIC 0 /* runtime selection */ -#define GFX_VIP_SC1200 0 /* support for SC1200 */ - -#define GFX_DECODER_DYNAMIC 0 /* runtime selection */ -#define GFX_DECODER_SAA7114 0 /* Philips SAA7114 decoder */ - -#define GFX_TV_DYNAMIC 0 /* runtime selection */ -#define GFX_TV_FS451 0 /* Focus Enhancements FS450 */ -#define GFX_TV_SC1200 0 /* SC1200 integrated TV encoder */ - -#define GFX_I2C_DYNAMIC 0 /* runtime selection */ -#define GFX_I2C_ACCESS 0 /* support for ACCESS.BUS */ -#define GFX_I2C_GPIO 0 /* support for CS5530 GPIOs */ - -#define GFX_VGA_DYNAMIC 0 /* runtime selection */ -#define GFX_VGA_GU1 0 /* 1st generation graphics unit */ - -#define FB4MB 1 /* Set to use 4Mb video ram for - * Pyramid */ - -#define GFX_NO_IO_IN_WAIT_MACROS 1 /* Set to remove I/O accesses in GP - * bit testing */ - -/* ROUTINES TO READ VALUES - * These are routines used by Darwin or other diagnostics to read the - * current state of the hardware. Display drivers or embedded applications - * can reduce the size of the Durango code by not including these routines. - */ -#define GFX_READ_ROUTINES 1 /* add routines to read values */ - -/* HEADER FILE FOR DURANGO ROUTINE DEFINITIONS - * Needed since some of the Durango routines call other Durango routines. - * Also defines the size of chipset array (GFX_CSPTR_SIZE). - */ -#include "gfx_rtns.h" /* routine definitions */ -#include "gfx_priv.h" +#define _LARGEFILE64_SOURCE -/* VARIABLES USED FOR RUNTIME SELECTION - * If part of the graphics subsystem is declared as dynamic, then the - * following variables are used to specify which platform has been detected. - * The variables are set in the "gfx_detect_cpu" routine. The values should - * be bit flags to allow masks to be used to check for multiple platforms. - */ +#include <unistd.h> +#include <errno.h> +#include <xf86_ansic.h> +#include <compiler.h> -#if GFX_DISPLAY_DYNAMIC -int gfx_display_type = 0; -#endif +/* Compiler options */ -#if GFX_INIT_DYNAMIC -int gfx_init_type = 0; -#endif -#if GFX_MSR_DYNAMIC -int gfx_msr_type = 0; -#endif +#define GFX_DISPLAY_GU1 0 /* 1st generation display controller */ +#define GFX_DISPLAY_GU2 1 /* 2nd generation display controller */ -#if GFX_2DACCEL_DYNAMIC -int gfx_2daccel_type = 0; -#endif +#define GFX_INIT_DYNAMIC 0 /* runtime selection */ +#define GFX_INIT_GU1 0 /* SC1200/GX1 */ +#define GFX_INIT_GU2 1 /* GX */ -#if GFX_VIDEO_DYNAMIC -int gfx_video_type = 0; -#endif +#define GFX_MSR_DYNAMIC 1 /* runtime selection */ +#define GFX_MSR_REDCLOUD 1 /* GX */ -#if GFX_VIP_DYNAMIC -int gfx_vip_type = 0; -#endif +#define GFX_2DACCEL_DYNAMIC 0 /* runtime selection */ +#define GFX_2DACCEL_GU1 0 /* 1st generation 2D accelerator */ +#define GFX_2DACCEL_GU2 1 /* 2nd generation 2D accelerator */ -#if GFX_DECODER_DYNAMIC -int gfx_decoder_type = 0; -#endif +#define GFX_VIDEO_DYNAMIC 0 /* runtime selection */ +#define GFX_VIDEO_CS5530 0 /* support for CS5530 */ +#define GFX_VIDEO_SC1200 0 /* support for SC1200 */ +#define GFX_VIDEO_REDCLOUD 1 /* support for GX */ -#if GFX_TV_DYNAMIC -int gfx_tv_type = 0; -#endif +#define GFX_VIP_DYNAMIC 0 /* runtime selection */ +#define GFX_VIP_SC1200 0 /* support for SC1200 */ -#if GFX_I2C_DYNAMIC -int gfx_i2c_type = 0; -#endif +#define GFX_DECODER_DYNAMIC 0 /* runtime selection */ +#define GFX_DECODER_SAA7114 0 /* Philips SAA7114 decoder */ -#if GFX_VGA_DYNAMIC -int gfx_vga_type = 0; -#endif +#define GFX_TV_DYNAMIC 0 /* runtime selection */ +#define GFX_TV_FS451 0 /* Focus Enhancements FS450 */ +#define GFX_TV_SC1200 0 /* SC1200 integrated TV encoder */ + +#define GFX_I2C_DYNAMIC 0 /* runtime selection */ +#define GFX_I2C_ACCESS 0 /* support for ACCESS.BUS */ +#define GFX_I2C_GPIO 0 /* support for CS5530 GPIOs */ + +#define GFX_VGA_DYNAMIC 0 /* runtime selection */ +#define GFX_VGA_GU1 0 /* 1st generation graphics unit */ -/* DEFINE POINTERS TO MEMORY MAPPED REGIONS - * These pointers are used by the Durango routines to access the hardware. - * The variables must be set by the project's initialization code after - * mapping the regions in the appropriate manner. - */ - -/* DEFINE VIRTUAL ADDRESSES */ -/* Note: These addresses define the starting base expected by all */ -/* Durango offsets. Under an OS that requires these pointers */ -/* to be mapped to linear addresses (i.e Windows), it may not */ -/* be possible to keep these base offsets. In these cases, */ -/* the addresses are modified to point to the beginning of the */ -/* relevant memory region and the access macros are adjusted */ -/* to subtract the offset from the default base. For example, */ -/* the register pointer could be moved to be 0x40008000, while */ -/* the WRITE_REG* macros are modified to subtract 0x8000 from */ -/* the offset. */ +#define FB4MB 1 /* Set to use 4Mb vid ram for Pyramid */ + +#define GFX_NO_IO_IN_WAIT_MACROS 1 /* Set to remove I/O accesses in GP + bit testing */ +#define GFX_READ_ROUTINES 1 + +#include "gfx_rtns.h" +#include "gfx_priv.h" +#include "gfx_regs.h" +#include "gfx_defs.h" + +#if GFX_MSR_DYNAMIC +int gfx_msr_type = 0; +#endif unsigned char *gfx_virt_regptr = (unsigned char *)0x40000000; unsigned char *gfx_virt_fbptr = (unsigned char *)0x40800000; @@ -184,31 +100,11 @@ unsigned char *gfx_virt_vipptr = (unsigned char *)0x40015000; unsigned char *gfx_virt_spptr = (unsigned char *)0x40000000; unsigned char *gfx_virt_gpptr = (unsigned char *)0x40000000; -/* DEFINE PHYSICAL ADDRESSES */ - unsigned char *gfx_phys_regptr = (unsigned char *)0x40000000; unsigned char *gfx_phys_fbptr = (unsigned char *)0x40800000; unsigned char *gfx_phys_vidptr = (unsigned char *)0x40010000; unsigned char *gfx_phys_vipptr = (unsigned char *)0x40015000; -/* HEADER FILE FOR GRAPHICS REGISTER DEFINITIONS - * This contains only constant definitions, so it should be able to be - * included in any software project as is. - */ -#include "gfx_regs.h" /* graphics register definitions */ - -/* HEADER FILE FOR REGISTER ACCESS MACROS - * This file contains the definitions of the WRITE_REG32 and similar macros - * used by the Durango routines to access the hardware. The file assumes - * that the environment can handle 32-bit pointer access. If this is not - * the case, or if there are special requirements, then this header file - * should not be included and the project must define the macros itself. - * (A project may define WRITE_REG32 to call a routine, for example). - */ -#include "gfx_defs.h" /* register access macros */ -#include <xf86_ansic.h> -#include <compiler.h> - #define INB(port) inb(port) #define INW(port) inw(port) #define IND(port) inl(port) @@ -216,55 +112,45 @@ unsigned char *gfx_phys_vipptr = (unsigned char *)0x40015000; #define OUTW(port,data) outw(port, data) #define OUTD(port,data) outl(port, data) -unsigned char gfx_inb(unsigned short port); -unsigned short gfx_inw(unsigned short port); -unsigned long gfx_ind(unsigned short port); -void gfx_outb(unsigned short port, unsigned char data); -void gfx_outw(unsigned short port, unsigned short data); -void gfx_outd(unsigned short port, unsigned long data); - -unsigned char +inline unsigned char gfx_inb(unsigned short port) { return inb(port); } -unsigned short +inline unsigned short gfx_inw(unsigned short port) { return inw(port); } -unsigned long +inline unsigned long gfx_ind(unsigned short port) { return inl(port); } -void +inline void gfx_outb(unsigned short port, unsigned char data) { outb(port, data); } -void +inline void gfx_outw(unsigned short port, unsigned short data) { outw(port, data); } -void +inline void gfx_outd(unsigned short port, unsigned long data) { outl(port, data); } -/*----------------------------------------------------------------- - * gfx_msr_asm_read - * Read the contents of a 64 bit MSR into address pointers - *-----------------------------------------------------------------*/ +/* These routines use VSA to read the MSRs - these are a second resort to the Linux MSR method */ -#define gfx_msr_asm_read(msr,adr,high,low) \ +#define vsa_msr_read(msr,adr,high,low) \ __asm__ __volatile__( \ " mov $0x0AC1C, %%edx\n" \ " mov $0xFC530007, %%eax\n" \ @@ -274,12 +160,8 @@ gfx_outd(unsigned short port, unsigned long data) : "=a" (*(low)), "=d" (*(high)) \ : "c" (msr | adr)) -/*----------------------------------------------------------------- - * gfx_msr_asm_write - * Write the contents of address pointers to a MSR. - *-----------------------------------------------------------------*/ -#define gfx_msr_asm_write(msr,adr,high,low) \ +#define vsa_msr_write(msr,adr,high,low) \ { int d0, d1, d2, d3, d4; \ __asm__ __volatile__( \ " push %%ebx\n" \ @@ -299,61 +181,109 @@ gfx_outd(unsigned short port, unsigned long data) : "1"(msr | adr),"2"(*(high)),"3"(*(low))); \ } -/* INITIALIZATION ROUTINES - * These routines are used during the initialization of the driver to - * perform such tasks as detecting the type of CPU and video hardware. - * The routines require the use of IO, so the above IO routines need - * to be implemented before the initialization routines will work - * properly. - */ +static int lnx_msr_open(void) +{ + static int msrfd = 0; -#include "gfx_init.c" + if (msrfd == 0) { + msrfd = open("/dev/cpu/0/msr", O_RDWR); + if (msrfd == -1) + ErrorF("Unable to open /dev/cpu/0/msr: %d\n", errno); + } -/* INCLUDE MSR ACCESS ROUTINES */ + return msrfd; +} -#include "gfx_msr.c" +/* These are the preferred method (in Linux) to read the MSRs */ -/* INCLUDE GRAPHICS ENGINE ROUTINES - * These routines are used to program the 2D graphics accelerator. If - * the project does not use graphics acceleration (direct frame buffer - * access only), then this file does not need to be included. - */ -#include "gfx_rndr.c" /* graphics engine routines */ - -/* INCLUDE DISPLAY CONTROLLER ROUTINES - * These routines are used if the display mode is set directly. If the - * project uses VGA registers to set a display mode, then these files - * do not need to be included. - */ -#include "gfx_mode.h" /* display mode tables */ -#include "gfx_disp.c" /* display controller routines */ - -/* INCLUDE VIDEO OVERLAY ROUTINES - * These routines control the video overlay hardware. - */ -#include "gfx_vid.c" /* video overlay routines */ - -/* VIDEO PORT AND VIDEO DECODER ROUTINES - * These routines rely on the I2C routines. - */ -#include "gfx_vip.c" /* video port routines */ -#include "gfx_dcdr.c" /* video decoder routines */ - -/* I2C BUS ACCESS ROUTINES - * These routines are used by the video decoder and possibly an - * external TV encoer. - */ -#include "gfx_i2c.c" /* I2C bus access routines */ - -/* TV ENCODER ROUTINES - * This file does not need to be included if the system does not - * support TV output. - */ -#include "gfx_tv.c" /* TV encoder routines */ - -/* VGA ROUTINES - * This file is used if setting display modes using VGA registers. - */ -#include "gfx_vga.c" /* VGA routines */ - -/* END OF FILE */ +int lnx_msr_read(unsigned long addr, unsigned long *hi, unsigned long *lo) +{ + unsigned int data[2]; + int fd = lnx_msr_open(); + int ret; + + if (fd == -1) + return - 1; + + ret = lseek64(fd, (off64_t) addr, SEEK_SET); + + if (ret == -1) { + return -1; + } + + ret = read(fd, (void *) data, sizeof(data)); + + if (ret != 8) { + return -1; + } + + *hi = data[1]; + *lo = data[0]; + + return 0; +} + +int lnx_msr_write(unsigned long addr, unsigned long *hi, unsigned long *lo) +{ + unsigned int data[2]; + int fd = lnx_msr_open(); + + if (fd == -1) + return - 1; + + if (lseek64(fd, (off64_t) addr, SEEK_SET) == -1) + return -1; + + data[0] = *lo; + data[1] = *hi; + + if (write(fd, (void *) data, 8) != 8) + return -1; + + return 0; +} + +void gfx_msr_asm_write(unsigned short reg, unsigned long addr, +unsigned long *hi, unsigned long *lo) +{ + static int msr_method = 0; + + if (msr_method == 0) { + if (!(lnx_msr_write(addr | reg, hi, lo))) + return; + + msr_method = 1; + } + + /* This is the fallback VSA method - not preferred */ + vsa_msr_write(reg, addr, hi, lo); +} + +void gfx_msr_asm_read(unsigned short reg, unsigned long addr, +unsigned long *hi, unsigned long *lo) +{ + static int msr_method = 0; + + if (msr_method == 0) { + if (!(lnx_msr_read(addr | reg, hi, lo))) + return; + + ErrorF("Unable to read the MSR - reverting to the VSA method.\n"); + msr_method = 1; + } + + /* This is the fallback VSA method - not preferred */ + vsa_msr_read(reg, addr, hi, lo); +} + +#include "gfx_init.c" +#include "gfx_msr.c" +#include "gfx_rndr.c" +#include "gfx_mode.h" +#include "gfx_disp.c" +#include "gfx_vid.c" +#include "gfx_vip.c" +#include "gfx_dcdr.c" +#include "gfx_i2c.c" +#include "gfx_tv.c" +#include "gfx_vga.c" |