Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2004-02-15 17:59:34 -0800
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2004-02-15 17:59:34 -0800
commitf2d07c2587b9ebf7f20e544159b9736683264e58 (patch)
tree818ccd185cc96e233bbd8a87c86d83f38ccb4232
parente93aa38371fff48b5fd95492c0903ca6bf1224fd (diff)
[PATCH] radeonfb: limit ioremap size & debug output
This adds a limit on how much of the framebuffer is ioremap'ed by radeonfb, thus enabling it to work with 128Mb VRAM or more on an x86 with 900Mb of lowmem in the linear mapping. It also adds a significant amount of debug messages and adds a CONFIG option to enable the debugging output, that should help with diagnosing new problems. Among others, it dumps the connector info as I understand them (so far, they give "strange" informations on laptops, I need more data on more various laptops to see if there's a pattern I can really use to figure out on which connector the LVDS is) Regarding the "lid closed at boot", ultimately, we may want to default to the VGA output in those cases, though I'm not sure what logic to use here. Maybe we could standardize some way for the platform to provide this "environment" information to the driver, but i wouldn't rely on it. More reliably, if we can find out that there is an LVDS output, and LVDS is disabled, just ignore the flat panel... We could assume any mobility chip has LVDS, which is true, but that would still cause a problem for laptops with an additional DVI output (only Macs so far afaik).
-rw-r--r--drivers/video/Kconfig9
-rw-r--r--drivers/video/aty/radeon_base.c92
-rw-r--r--drivers/video/aty/radeon_i2c.c3
-rw-r--r--drivers/video/aty/radeon_monitor.c82
-rw-r--r--drivers/video/aty/radeonfb.h5
5 files changed, 182 insertions, 9 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 214c7a9475d9..308ec9f35b5b 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -650,6 +650,15 @@ config FB_RADEON_I2C
help
Say Y here if you want DDC/I2C support for your Radeon board.
+config FB_RADEON_DEBUG
+ bool "Lots of debug output from Radeon driver"
+ depends on FB_RADEON
+ default n
+ help
+ Say Y here if you want the Radeon driver to output all sorts
+ of debugging informations to provide to the maintainer when
+ something goes wrong.
+
config FB_ATY128
tristate "ATI Rage128 display support"
depends on FB && PCI
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 9347bffb4038..d629e66f55d0 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -99,6 +99,8 @@
#include "ati_ids.h"
#include "radeonfb.h"
+#define MAX_MAPPED_VRAM (2048*2048*4)
+#define MIN_MAPPED_VRAM (1024*768*1)
#define CHIP_DEF(id, family, flags) \
{ PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
@@ -826,6 +828,9 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in
v.xres_virtual = (pitch << 6) / ((v.bits_per_pixel + 1) / 8);
}
+ if (((v.xres_virtual * v.yres_virtual * nom) / den) > rinfo->mapped_vram)
+ return -EINVAL;
+
if (v.xres_virtual < v.xres)
v.xres = v.xres_virtual;
@@ -942,7 +947,7 @@ static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int
static int radeon_screen_blank (struct radeonfb_info *rinfo, int blank)
{
u32 val = INREG(CRTC_EXT_CNTL);
- u32 val2;
+ u32 val2 = 0;
if (rinfo->mon1_type == MT_LCD)
val2 = INREG(LVDS_GEN_CNTL) & ~LVDS_DISPLAY_DIS;
@@ -1023,7 +1028,7 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
pindex = regno;
if (!rinfo->asleep) {
- u32 dac_cntl2, vclk_cntl;
+ u32 dac_cntl2, vclk_cntl = 0;
if (rinfo->is_mobility) {
vclk_cntl = INPLL(VCLK_ECP_CNTL);
@@ -1317,7 +1322,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
{ 12, 7 },
{ 0, 0 },
};
- int fb_div, pll_output_freq;
+ int fb_div, pll_output_freq = 0;
int uses_dvo = 0;
/* Check if the DVO port is enabled and sourced from the primary CRTC. I'm
@@ -1686,6 +1691,67 @@ int radeonfb_set_par(struct fb_info *info)
+static ssize_t radeonfb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = iminor(inode);
+ struct fb_info *info = registered_fb[fbidx];
+ struct radeonfb_info *rinfo = info->par;
+
+ if (p >= rinfo->mapped_vram)
+ return 0;
+ if (count >= rinfo->mapped_vram)
+ count = rinfo->mapped_vram;
+ if (count + p > rinfo->mapped_vram)
+ count = rinfo->mapped_vram - p;
+ radeonfb_sync(info);
+ if (count) {
+ char *base_addr;
+
+ base_addr = info->screen_base;
+ count -= copy_to_user(buf, base_addr+p, count);
+ if (!count)
+ return -EFAULT;
+ *ppos += count;
+ }
+ return count;
+}
+
+static ssize_t radeonfb_write(struct file *file, const char *buf, size_t count,
+ loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = iminor(inode);
+ struct fb_info *info = registered_fb[fbidx];
+ struct radeonfb_info *rinfo = info->par;
+ int err;
+
+ if (p > rinfo->mapped_vram)
+ return -ENOSPC;
+ if (count >= rinfo->mapped_vram)
+ count = rinfo->mapped_vram;
+ err = 0;
+ if (count + p > rinfo->mapped_vram) {
+ count = rinfo->mapped_vram - p;
+ err = -ENOSPC;
+ }
+ radeonfb_sync(info);
+ if (count) {
+ char *base_addr;
+
+ base_addr = info->screen_base;
+ count -= copy_from_user(base_addr+p, buf, count);
+ *ppos += count;
+ err = -EFAULT;
+ }
+ if (count)
+ return count;
+ return err;
+}
+
+
static struct fb_ops radeonfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = radeonfb_check_var,
@@ -1698,6 +1764,8 @@ static struct fb_ops radeonfb_ops = {
.fb_fillrect = radeonfb_fillrect,
.fb_copyarea = radeonfb_copyarea,
.fb_imageblit = radeonfb_imageblit,
+ .fb_read = radeonfb_read,
+ .fb_write = radeonfb_write,
.fb_cursor = soft_cursor,
};
@@ -2122,11 +2190,27 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
RTRACE("radeonfb: probed %s %ldk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
- rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys, rinfo->video_ram);
+ rinfo->mapped_vram = MAX_MAPPED_VRAM;
+ if (rinfo->video_ram < rinfo->mapped_vram)
+ rinfo->mapped_vram = rinfo->video_ram;
+ for (;;) {
+ rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys,
+ rinfo->mapped_vram);
+ if (rinfo->fb_base == 0 && rinfo->mapped_vram > MIN_MAPPED_VRAM) {
+ rinfo->mapped_vram /= 2;
+ continue;
+ }
+ break;
+ }
+
if (!rinfo->fb_base) {
printk (KERN_ERR "radeonfb: cannot map FB\n");
goto unmap_rom;
}
+
+ RTRACE("radeonfb: mapped %ldk videoram\n", rinfo->mapped_vram/1024);
+
+
/* Argh. Scary arch !!! */
#ifdef CONFIG_PPC64
rinfo->fb_base = IO_TOKEN_TO_ADDR(rinfo->fb_base);
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index def3f11fd1f6..af351c02360b 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -243,7 +243,8 @@ int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_e
return MT_NONE;
}
if (edid[0x14] & 0x80) {
- if (rinfo->is_mobility && conn == ddc_dvi &&
+ /* Fix detection using BIOS tables */
+ if (rinfo->is_mobility /*&& conn == ddc_dvi*/ &&
(INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
RTRACE("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
return MT_LCD;
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index 0efcb2ed65d2..0dea5fb25836 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -156,6 +156,7 @@ static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) {
printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n");
+ rinfo->panel_info.pwr_delay = 200;
return 0;
}
@@ -169,7 +170,8 @@ static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
rinfo->panel_info.xres, rinfo->panel_info.yres);
rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44);
- if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay < 0)
+ RTRACE("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay);
+ if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0)
rinfo->panel_info.pwr_delay = 2000;
/*
@@ -182,11 +184,16 @@ static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
rinfo->panel_info.fbk_divider > 3) {
rinfo->panel_info.use_bios_dividers = 1;
printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n");
+ RTRACE("ref_divider = %x\n", rinfo->panel_info.ref_divider);
+ RTRACE("post_divider = %x\n", rinfo->panel_info.post_divider);
+ RTRACE("fbk_divider = %x\n", rinfo->panel_info.fbk_divider);
}
+ RTRACE("Scanning BIOS table ...\n");
for(i=0; i<32; i++) {
tmp0 = BIOS_IN16(tmp+64+i*2);
if (tmp0 == 0)
break;
+ RTRACE(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2));
if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) &&
(BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) {
rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8;
@@ -205,13 +212,68 @@ static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
/* Mark panel infos valid */
rinfo->panel_info.valid = 1;
+ RTRACE("Found panel in BIOS table:\n");
+ RTRACE(" hblank: %d\n", rinfo->panel_info.hblank);
+ RTRACE(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus);
+ RTRACE(" hSync_width: %d\n", rinfo->panel_info.hSync_width);
+ RTRACE(" vblank: %d\n", rinfo->panel_info.vblank);
+ RTRACE(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus);
+ RTRACE(" vSync_width: %d\n", rinfo->panel_info.vSync_width);
+ RTRACE(" clock: %d\n", rinfo->panel_info.clock);
+
return 1;
}
}
+ RTRACE("Didn't find panel in BIOS table !\n");
return 0;
}
+/* Try to extract the connector informations from the BIOS. This
+ * doesn't quite work yet, but it's output is still useful for
+ * debugging
+ */
+static void __devinit radeon_parse_connector_info(struct radeonfb_info *rinfo)
+{
+ int offset, chips, connectors, tmp, i, conn, type;
+
+ static char* __conn_type_table[16] = {
+ "NONE", "Proprietary", "CRT", "DVI-I", "DVI-D", "Unknown", "Unknown",
+ "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",
+ "Unknown", "Unknown", "Unknown"
+ };
+
+ if (!rinfo->bios_seg)
+ return;
+
+ offset = BIOS_IN16(rinfo->fp_bios_start + 0x50);
+ if (offset == 0) {
+ printk(KERN_WARNING "radeonfb: No connector info table detected\n");
+ return;
+ }
+
+ /* Don't do much more at this point but displaying the data if
+ * DEBUG is enabled
+ */
+ chips = BIOS_IN8(offset++) >> 4;
+ RTRACE("%d chips in connector info\n", chips);
+ for (i = 0; i < chips; i++) {
+ tmp = BIOS_IN8(offset++);
+ connectors = tmp & 0x0f;
+ RTRACE(" - chip %d has %d connectors\n", tmp >> 4, connectors);
+ for (conn = 0; ; conn++) {
+ tmp = BIOS_IN16(offset);
+ if (tmp == 0)
+ break;
+ offset += 2;
+ type = (tmp >> 12) & 0x0f;
+ RTRACE(" * connector %d of type %d (%s) : %04x\n",
+ conn, type, __conn_type_table[type], tmp);
+ }
+ }
+}
+
+
/*
* Probe physical connection of a CRT. This code comes from XFree
* as well and currently is only implemented for the CRT DAC, the
@@ -224,7 +286,7 @@ static int __devinit radeon_crt_is_connected(struct radeonfb_info *rinfo, int is
/* the monitor either wasn't connected or it is a non-DDC CRT.
* try to probe it
*/
- if(is_crt_dac) {
+ if (is_crt_dac) {
unsigned long ulOrigVCLK_ECP_CNTL;
unsigned long ulOrigDAC_CNTL;
unsigned long ulOrigDAC_EXT_CNTL;
@@ -353,10 +415,12 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
const char *monitor_layout, int ignore_edid)
{
#ifdef CONFIG_FB_RADEON_I2C
- int ddc_crt2_used = 0;
+ int ddc_crt2_used = 0;
#endif
int tmp, i;
+ radeon_parse_connector_info(rinfo);
+
if (radeon_parse_monitor_layout(rinfo, monitor_layout)) {
/*
@@ -392,13 +456,23 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
rinfo->mon2_EDID = NULL;
}
} else {
-
/*
* Auto-detecting display type (well... trying to ...)
*/
RTRACE("Starting monitor auto detection...\n");
+#if DEBUG
+ {
+ u8 *EDIDs[4] = { NULL, NULL, NULL, NULL };
+ int mon_types[4] = {MT_NONE, MT_NONE, MT_NONE, MT_NONE};
+ int i;
+
+ for (i = 0; i < 4; i++)
+ mon_types[i] = radeon_probe_i2c_connector(rinfo,
+ i+1, &EDIDs[i]);
+ }
+#endif /* DEBUG */
/*
* Old single head cards
*/
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 4d55ab468ddb..a316e826f3b1 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -282,6 +282,7 @@ struct radeonfb_info {
u8 family;
u8 rev;
unsigned long video_ram;
+ unsigned long mapped_vram;
int pitch, bpp, depth;
@@ -332,7 +333,11 @@ struct radeonfb_info {
/*
* Debugging stuffs
*/
+#ifdef CONFIG_FB_RADEON_DEBUG
+#define DEBUG 1
+#else
#define DEBUG 0
+#endif
#if DEBUG
#define RTRACE printk