#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) }
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;
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;
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);
{ 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
+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,
.fb_fillrect = radeonfb_fillrect,
.fb_copyarea = radeonfb_copyarea,
.fb_imageblit = radeonfb_imageblit,
+ .fb_read = radeonfb_read,
+ .fb_write = radeonfb_write,
.fb_cursor = soft_cursor,
};
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);
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;
}
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;
/*
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;
/* 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
/* 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;
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)) {
/*
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
*/