* radeonfb: Add ATOM BIOS parsing (rebased patch)
@ 2006-09-05 15:37 Stuffed Crust
2006-09-06 22:00 ` radeonfb: Add ATOM BIOS parsing v5b/v6 " Stuffed Crust
2006-11-02 5:33 ` radeonfb: Add ATOM BIOS parsing (rebased patch) Andrew Morton
0 siblings, 2 replies; 8+ messages in thread
From: Stuffed Crust @ 2006-09-05 15:37 UTC (permalink / raw)
To: linux-fbdev-devel
[-- Attachment #1.1.1: Type: text/plain, Size: 2065 bytes --]
Signed-Off-By: Solomon Peachy <pizza@shaftnet.org>
This is my old radeon-atom-5 patch rediffed against 2.6.17.x
Changes vs 2.6.17.x:
* ATOM BIOS support for newer Radeon cards
* Clean method of detecting and handling disparate BIOS types
* Radeon RV410/M26/M26GL (aka Mobility X700/FireGL5000) card IDs
* Default PLL clocks for R420 and variants
* Handle bogus PLL divider with sane default.
* All new connector/head detection code that uses bios/firmware
defaults whenever possible.
...
A while back I posted a patch that added full ATOM BIOS parsing for
newer radeon boards. It also re-jiggered multi head detection to be
considerably more sane (== actually work), and generally modularized
most of the "get data X from BIOS/firmware/etc" code.
I was working under BenH's direction, but he apparently got swamped a
while back and this fell through the cracks. I'm re-posting this in an
attempt to get the ball rolling again, as several people have contacted
me directly to ask about this code getting merged.
I don't have the means (hardware &| bug reports/feedback) to develop it
further. IIRC the memmap fixes for r300/r400 haven't been integrated
into the mainline either, so you may get some random lockups -- but that
is beyond the scope of this patch.
Aanyone who has a radeon card and is feeling brave, please give this a
whirl. If you are specifying a monitor layout, try it without the
layout string and things should JustWork(tm).
This patch also adds PCI IDs for the X700/M26 series. It tests fine on
the M26 (ATOM) in my laptop and the 7500AGP (Legacy) card in my workstation.
See also kernel bugzilla # 6215:
http://bugzilla.kernel.org/show_bug.cgi?id=6215
I'll rebase it against 2.6.18-rcX (if necessary) after I migrate to
2.6.18-rcX on my development boxen.
- Solomon
--
Solomon Peachy pizza at shaftnet dot org
Melbourne, FL ^^ (mail/jabber/gtalk) ^^
Quidquid latine dictum sit, altum viditur. ICQ: 1318344
[-- Attachment #1.1.2: radeonfb-atom-2.6.17-v5.diff --]
[-- Type: text/plain, Size: 76805 bytes --]
diff -Naur aty-2.6.17/ati_ids.h aty-2.6.17-patched/ati_ids.h
--- aty-2.6.17/ati_ids.h 2006-09-05 10:15:55.000000000 -0400
+++ aty-2.6.17-patched/ati_ids.h 2006-09-05 10:34:51.000000000 -0400
@@ -185,6 +185,10 @@
#define PCI_CHIP_R423_UQ 0x5551
#define PCI_CHIP_R423_UR 0x5552
#define PCI_CHIP_R423_UT 0x5554
+#define PCI_CHIP_RV410_564B 0x564A
+#define PCI_CHIP_RV410_564A 0x564B
+#define PCI_CHIP_RV410_5652 0x5652
+#define PCI_CHIP_RV410_VS 0x5653
#define PCI_CHIP_MACH64VT 0x5654
#define PCI_CHIP_MACH64VU 0x5655
#define PCI_CHIP_MACH64VV 0x5656
diff -Naur aty-2.6.17/radeon_base.c aty-2.6.17-patched/radeon_base.c
--- aty-2.6.17/radeon_base.c 2006-09-05 10:15:55.000000000 -0400
+++ aty-2.6.17-patched/radeon_base.c 2006-09-05 10:34:51.000000000 -0400
@@ -3,6 +3,7 @@
*
* framebuffer driver for ATI Radeon chipset video boards
*
+ * Copyright 2006 Solomon Peachy <pizza@shaftnet.org>
* Copyright 2003 Ben. Herrenschmidt <benh@kernel.crashing.org>
* Copyright 2000 Ani Joshi <ajoshi@kernel.crashing.org>
*
@@ -50,7 +51,7 @@
*/
-#define RADEON_VERSION "0.2.0"
+#define RADEON_VERSION "0.3.0"
#include <linux/config.h>
#include <linux/module.h>
@@ -214,6 +215,10 @@
CHIP_DEF(PCI_CHIP_R420_JL, R420, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_R420_JM, R420, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_R420_JN, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV410_564A, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV410_564B, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV410_5652, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV410_VS, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
CHIP_DEF(PCI_CHIP_R420_JP, R420, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_R423_UH, R420, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_R423_UI, R420, CHIP_HAS_CRTC2),
@@ -265,6 +270,7 @@
static int default_dynclk = -2;
static int nomodeset = 0;
static int ignore_edid = 0;
+static int ignore_conntable = 0;
static int mirror = 0;
static int panel_yres = 0;
static int force_dfp = 0;
@@ -342,7 +348,7 @@
* to phase out Open Firmware images.
*
* Currently, we only look at the first PCI data, we could iteratre and deal with
- * them all, and we should use fb_bios_start relative to start of image and not
+ * them all, and we should use fp_bios_start relative to start of image and not
* relative start of ROM, but so far, I never found a dual-image ATI card
*
* typedef struct {
@@ -428,7 +434,7 @@
* Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
* tree. Hopefully, ATI OF driver is kind enough to fill these
*/
-static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
+static int __devinit radeon_get_pll_info_openfirmware (struct radeonfb_info *rinfo)
{
struct device_node *dp = rinfo->of_node;
u32 *val;
@@ -451,6 +457,7 @@
if (val && *val)
rinfo->pll.mclk = (*val) / 10;
+ printk(KERN_INFO "radeonfb: Retrieved PLL infos from Open Firmware\n");
return 0;
}
#endif /* CONFIG_PPC_OF */
@@ -593,10 +600,88 @@
return 0;
}
+static int __devinit radeon_get_pll_info_legacy(struct radeonfb_info *rinfo)
+{
+ u16 pll_info_block;
+
+ if (!rinfo->bios_seg)
+ return -EINVAL;
+
+ pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
+
+ rinfo->pll.sclk = BIOS_IN16(pll_info_block + 0x08);
+ rinfo->pll.mclk = BIOS_IN16(pll_info_block + 0x0a);
+ rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 0x0e);
+ rinfo->pll.ref_div = BIOS_IN16(pll_info_block + 0x10);
+ rinfo->pll.ppll_min = BIOS_IN32(pll_info_block + 0x12);
+ rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 0x16);
+
+ printk(KERN_INFO "radeonfb: Retrieved PLL infos from Legacy BIOS\n");
+ return 0;
+}
+
+
+static int __devinit radeon_get_pll_info_atom(struct radeonfb_info *rinfo)
+{
+ u16 pll_info_block;
+
+ if (!rinfo->bios_seg)
+ return -EINVAL;
+
+ pll_info_block = BIOS_IN16(rinfo->atom_data_start + 12);
+
+ rinfo->pll.sclk = BIOS_IN32(pll_info_block + 8);
+ rinfo->pll.mclk = BIOS_IN32(pll_info_block + 12);
+ rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 82);
+ rinfo->pll.ref_div = 0; /* Have to get it elsewhere */
+ rinfo->pll.ppll_min = BIOS_IN16(pll_info_block + 78);
+ rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 32);
+
+ printk(KERN_INFO "radeonfb: Retrieved PLL infos from ATOM BIOS\n");
+ return 0;
+}
+
+static void radeon_detect_bios_type(struct radeonfb_info *rinfo)
+{
+#ifdef CONFIG_PPC_OF
+ rinfo->is_atom_bios = 0;
+ rinfo->get_pll_info = radeon_get_pll_info_openfirmware;
+ rinfo->get_lvds_info = radeon_get_lvds_info_openfirmware;
+ rinfo->radeon_get_tmds_info = NULL;
+ rinfo->get_conn_info = radeon_get_conn_info_openfirmware;
+#else
+ int tmp = rinfo->fp_bios_start + 4;
+
+ if ((BIOS_IN8(tmp) == 'A' &&
+ BIOS_IN8(tmp+1) == 'T' &&
+ BIOS_IN8(tmp+2) == 'O' &&
+ BIOS_IN8(tmp+3) == 'M') ||
+ (BIOS_IN8(tmp) == 'M' &&
+ BIOS_IN8(tmp+1) == 'O' &&
+ BIOS_IN8(tmp+2) == 'T' &&
+ BIOS_IN8(tmp+3) == 'A')) {
+ rinfo->is_atom_bios = 1;
+
+ rinfo->atom_data_start = BIOS_IN16(rinfo->fp_bios_start + 32);
+ rinfo->radeon_get_pll_info = radeon_get_pll_info_atom;
+ rinfo->radeon_get_lvds_info = radeon_get_lvds_info_atom;
+ rinfo->radeon_get_conn_info = radeon_get_conn_info_atom;
+ rinfo->radeon_get_tmds_info = radeon_get_tmds_info_atom;
+ } else {
+ rinfo->is_atom_bios = 0;
+ rinfo->radeon_get_pll_info = radeon_get_pll_info_legacy;
+ rinfo->radeon_get_lvds_info = radeon_get_lvds_info_legacy;
+ rinfo->radeon_get_conn_info = radeon_get_conn_info_legacy;
+ rinfo->radeon_get_tmds_info = radeon_get_tmds_info_legacy;
+ }
+#endif /* CONFIG_PPC_OF */
+
+}
+
/*
* Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...)
*/
-static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
+static void __devinit radeon_get_pll_info(struct radeonfb_info *rinfo)
{
/*
* In the case nothing works, these are defaults; they are mostly
@@ -648,46 +733,30 @@
case PCI_DEVICE_ID_ATI_RADEON_QF:
case PCI_DEVICE_ID_ATI_RADEON_QG:
default:
- rinfo->pll.ppll_max = 35000;
- rinfo->pll.ppll_min = 12000;
+ if (rinfo->family == CHIP_FAMILY_R420) {
+ rinfo->pll.ppll_max = 50000;
+ rinfo->pll.ppll_min = 20000;
+ } else {
+ rinfo->pll.ppll_max = 35000;
+ rinfo->pll.ppll_min = 12000;
+ }
rinfo->pll.mclk = 16600;
rinfo->pll.sclk = 16600;
rinfo->pll.ref_clk = 2700;
break;
}
- rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
-
-
-#ifdef CONFIG_PPC_OF
- /*
- * Retrieve PLL infos from Open Firmware first
- */
- if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
- printk(KERN_INFO "radeonfb: Retrieved PLL infos from Open Firmware\n");
- goto found;
- }
-#endif /* CONFIG_PPC_OF */
/*
- * Check out if we have an X86 which gave us some PLL informations
- * and if yes, retrieve them
+ * If we have a way to retrieve the PLL information, do so.
*/
- if (!force_measure_pll && rinfo->bios_seg) {
- u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
-
- rinfo->pll.sclk = BIOS_IN16(pll_info_block + 0x08);
- rinfo->pll.mclk = BIOS_IN16(pll_info_block + 0x0a);
- rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 0x0e);
- rinfo->pll.ref_div = BIOS_IN16(pll_info_block + 0x10);
- rinfo->pll.ppll_min = BIOS_IN32(pll_info_block + 0x12);
- rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 0x16);
-
- printk(KERN_INFO "radeonfb: Retrieved PLL infos from BIOS\n");
- goto found;
+ if (!force_measure_pll && rinfo->radeon_get_pll_info) {
+ if (!rinfo->radeon_get_pll_info(rinfo)) {
+ goto found;
+ }
}
/*
- * We didn't get PLL parameters from either OF or BIOS, we try to
+ * If we don't get the PLL parameters handed to us, we try to
* probe them
*/
if (radeon_probe_pll_params(rinfo) == 0) {
@@ -701,6 +770,22 @@
printk(KERN_INFO "radeonfb: Used default PLL infos\n");
found:
+
+ /* Check and fix-up the PLL divisor if necessary */
+ if (rinfo->pll.ref_div < 2) {
+ int tmp = INPLL(PPLL_REF_DIV);
+ if (rinfo->family == CHIP_FAMILY_RS300) {
+ rinfo->pll.ref_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT;
+ } else {
+ rinfo->pll.ref_div = tmp & PPLL_REF_DIV_MASK;
+ }
+
+ /* Sane default */
+ if (rinfo->pll.ref_div < 2) {
+ rinfo->pll.ref_div = 12;
+ }
+ }
+
/*
* Some methods fail to retrieve SCLK and MCLK values, we apply default
* settings in this case (200Mhz). If that really happne often, we could
@@ -941,6 +1026,7 @@
u32 val;
u32 tmp_pix_clks;
int unblank = 0;
+ int i;
if (rinfo->lock_blank)
return 0;
@@ -970,78 +1056,80 @@
}
OUTREG(CRTC_EXT_CNTL, val);
+ for (i = 0 ; i < RADEON_MAX_CONNECTORS ; i++) {
+ if (i == -1) continue;
- switch (rinfo->mon1_type) {
- case MT_DFP:
- if (unblank)
- OUTREGP(FP_GEN_CNTL, (FP_FPON | FP_TMDS_EN),
- ~(FP_FPON | FP_TMDS_EN));
- else {
- if (mode_switch || blank == FB_BLANK_NORMAL)
- break;
- OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN));
- }
+ switch (rinfo->connectors[rinfo->heads[i]].mon_type) {
+ case MT_DFP:
+ if (unblank)
+ OUTREGP(FP_GEN_CNTL, (FP_FPON | FP_TMDS_EN),
+ ~(FP_FPON | FP_TMDS_EN));
+ else {
+ if (mode_switch || blank == FB_BLANK_NORMAL)
+ break;
+ OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN));
+ }
break;
- case MT_LCD:
- del_timer_sync(&rinfo->lvds_timer);
- val = INREG(LVDS_GEN_CNTL);
- if (unblank) {
- u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON
- | LVDS_EN | (rinfo->init_state.lvds_gen_cntl
- & (LVDS_DIGON | LVDS_BL_MOD_EN));
- if ((val ^ target_val) == LVDS_DISPLAY_DIS)
- OUTREG(LVDS_GEN_CNTL, target_val);
- else if ((val ^ target_val) != 0) {
- OUTREG(LVDS_GEN_CNTL, target_val
- & ~(LVDS_ON | LVDS_BL_MOD_EN));
- rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
- rinfo->init_state.lvds_gen_cntl |=
- target_val & LVDS_STATE_MASK;
- if (mode_switch) {
- radeon_msleep(rinfo->panel_info.pwr_delay);
+ case MT_LCD:
+ del_timer_sync(&rinfo->lvds_timer);
+ val = INREG(LVDS_GEN_CNTL);
+ if (unblank) {
+ u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON
+ | LVDS_EN | (rinfo->init_state.lvds_gen_cntl
+ & (LVDS_DIGON | LVDS_BL_MOD_EN));
+ if ((val ^ target_val) == LVDS_DISPLAY_DIS)
OUTREG(LVDS_GEN_CNTL, target_val);
+ else if ((val ^ target_val) != 0) {
+ OUTREG(LVDS_GEN_CNTL, target_val
+ & ~(LVDS_ON | LVDS_BL_MOD_EN));
+ rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+ rinfo->init_state.lvds_gen_cntl |=
+ target_val & LVDS_STATE_MASK;
+ if (mode_switch) {
+ radeon_msleep(rinfo->panel_info.pwr_delay);
+ OUTREG(LVDS_GEN_CNTL, target_val);
+ } else {
+ rinfo->pending_lvds_gen_cntl = target_val;
+ mod_timer(&rinfo->lvds_timer,
+ jiffies +
+ msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+ }
}
- else {
- rinfo->pending_lvds_gen_cntl = target_val;
- mod_timer(&rinfo->lvds_timer,
- jiffies +
- msecs_to_jiffies(rinfo->panel_info.pwr_delay));
- }
+ } else {
+ val |= LVDS_DISPLAY_DIS;
+ OUTREG(LVDS_GEN_CNTL, val);
+
+ /* We don't do a full switch-off on a simple mode switch */
+ if (mode_switch || blank == FB_BLANK_NORMAL)
+ break;
+
+ /* Asic bug, when turning off LVDS_ON, we have to make sure
+ * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
+ */
+ tmp_pix_clks = INPLL(PIXCLKS_CNTL);
+ if (rinfo->is_mobility || rinfo->is_IGP)
+ OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+ val &= ~(LVDS_BL_MOD_EN);
+ OUTREG(LVDS_GEN_CNTL, val);
+ udelay(100);
+ val &= ~(LVDS_ON | LVDS_EN);
+ OUTREG(LVDS_GEN_CNTL, val);
+ val &= ~LVDS_DIGON;
+ rinfo->pending_lvds_gen_cntl = val;
+ mod_timer(&rinfo->lvds_timer,
+ jiffies +
+ msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+ rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+ rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;
+ if (rinfo->is_mobility || rinfo->is_IGP)
+ OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
}
- } else {
- val |= LVDS_DISPLAY_DIS;
- OUTREG(LVDS_GEN_CNTL, val);
-
- /* We don't do a full switch-off on a simple mode switch */
- if (mode_switch || blank == FB_BLANK_NORMAL)
- break;
-
- /* Asic bug, when turning off LVDS_ON, we have to make sure
- * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
- */
- tmp_pix_clks = INPLL(PIXCLKS_CNTL);
- if (rinfo->is_mobility || rinfo->is_IGP)
- OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
- val &= ~(LVDS_BL_MOD_EN);
- OUTREG(LVDS_GEN_CNTL, val);
- udelay(100);
- val &= ~(LVDS_ON | LVDS_EN);
- OUTREG(LVDS_GEN_CNTL, val);
- val &= ~LVDS_DIGON;
- rinfo->pending_lvds_gen_cntl = val;
- mod_timer(&rinfo->lvds_timer,
- jiffies +
- msecs_to_jiffies(rinfo->panel_info.pwr_delay));
- rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
- rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;
- if (rinfo->is_mobility || rinfo->is_IGP)
- OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
+ break;
+ case MT_CRT:
+ // todo: powerdown DAC
+ default:
+ break;
}
- break;
- case MT_CRT:
- // todo: powerdown DAC
- default:
- break;
}
/* let fbcon do a soft blank for us */
@@ -1942,7 +2030,7 @@
u32 lvds_gen_cntl, tmpPixclksCntl;
int* conv_table;
- if (rinfo->mon1_type != MT_LCD)
+ if (PRIMARY_MONITOR(rinfo) != MT_LCD)
return 0;
/* Pardon me for that hack... maybe some day we can figure
@@ -2230,7 +2318,7 @@
struct fb_info *info = pci_get_drvdata(pdev);
struct radeonfb_info *rinfo = info->par;
- return radeon_show_one_edid(buf, off, count, rinfo->mon1_EDID);
+ return radeon_show_one_edid(buf, off, count, rinfo->connectors[rinfo->heads[0]].edid);
}
@@ -2241,7 +2329,27 @@
struct fb_info *info = pci_get_drvdata(pdev);
struct radeonfb_info *rinfo = info->par;
- return radeon_show_one_edid(buf, off, count, rinfo->mon2_EDID);
+ return radeon_show_one_edid(buf, off, count, rinfo->connectors[rinfo->heads[1]].edid);
+}
+
+static ssize_t radeon_show_edid3(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct radeonfb_info *rinfo = info->par;
+
+ return radeon_show_one_edid(buf, off, count, rinfo->connectors[rinfo->heads[2]].edid);
+}
+
+static ssize_t radeon_show_edid4(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct radeonfb_info *rinfo = info->par;
+
+ return radeon_show_one_edid(buf, off, count, rinfo->connectors[rinfo->heads[3]].edid);
}
static struct bin_attribute edid1_attr = {
@@ -2264,6 +2372,25 @@
.read = radeon_show_edid2,
};
+static struct bin_attribute edid3_attr = {
+ .attr = {
+ .name = "edid3",
+ .owner = THIS_MODULE,
+ .mode = 0444,
+ },
+ .size = EDID_LENGTH,
+ .read = radeon_show_edid3,
+};
+
+static struct bin_attribute edid4_attr = {
+ .attr = {
+ .name = "edid4",
+ .owner = THIS_MODULE,
+ .mode = 0444,
+ },
+ .size = EDID_LENGTH,
+ .read = radeon_show_edid4,
+};
static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -2271,6 +2398,7 @@
struct fb_info *info;
struct radeonfb_info *rinfo;
int ret;
+ int i;
RTRACE("radeonfb_pci_register BEGIN\n");
@@ -2412,6 +2540,7 @@
* We probably need to make sure this is the primary display,
* but that is difficult without some arch support.
*/
+
#ifdef CONFIG_X86
if (rinfo->bios_seg == NULL)
radeon_find_mem_vbios(rinfo);
@@ -2423,14 +2552,23 @@
if (rinfo->bios_seg == NULL && rinfo->is_mobility)
radeon_map_ROM(rinfo, pdev);
+ /* Check BIOS Type */
+ radeon_detect_bios_type(rinfo);
+
/* Get informations about the board's PLL */
- radeon_get_pllinfo(rinfo);
+ radeon_get_pll_info(rinfo);
+
+ /* Get informations about internal TMDS controller if any */
+ radeon_get_tmds_info(rinfo);
#ifdef CONFIG_FB_RADEON_I2C
/* Register I2C bus */
radeon_create_i2c_busses(rinfo);
#endif
+ /* Get infos about connectors -- need I2C here! */
+ radeon_get_conn_info(rinfo, ignore_conntable);
+
/* set all the vital stuff */
radeon_set_fbinfo (rinfo);
@@ -2441,10 +2579,15 @@
radeon_check_modes(rinfo, mode_option);
/* Register some sysfs stuff (should be done better) */
- if (rinfo->mon1_EDID)
+
+ if ((rinfo->heads[0] != -1) && rinfo->connectors[rinfo->heads[0]].edid)
sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
- if (rinfo->mon2_EDID)
+ if ((rinfo->heads[1] != -1) && rinfo->connectors[rinfo->heads[1]].edid)
sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+ if ((rinfo->heads[2] != -1) && rinfo->connectors[rinfo->heads[2]].edid)
+ sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid3_attr);
+ if ((rinfo->heads[3] != -1) && rinfo->connectors[rinfo->heads[3]].edid)
+ sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid4_attr);
/* save current mode regs before we switch into the new one
* so we can restore this upon __exit
@@ -2478,7 +2621,7 @@
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
- if (rinfo->mon1_type == MT_LCD) {
+ if (PRIMARY_MONITOR(rinfo) == MT_LCD) {
register_backlight_controller(&radeon_backlight_controller,
rinfo, "ati");
register_backlight_controller(&radeon_backlight_controller,
@@ -2496,10 +2639,12 @@
err_unmap_fb:
iounmap(rinfo->fb_base);
err_unmap_rom:
- kfree(rinfo->mon1_EDID);
- kfree(rinfo->mon2_EDID);
- if (rinfo->mon1_modedb)
- fb_destroy_modedb(rinfo->mon1_modedb);
+ for (i = 0 ; i < RADEON_MAX_CONNECTORS ; i++) {
+ kfree(rinfo->connectors[i].edid);
+ if (rinfo->connectors[i].modedb)
+ fb_destroy_modedb(rinfo->connectors[i].modedb);
+ }
+
fb_dealloc_cmap(&info->cmap);
#ifdef CONFIG_FB_RADEON_I2C
radeon_delete_i2c_busses(rinfo);
@@ -2525,16 +2670,21 @@
{
struct fb_info *info = pci_get_drvdata(pdev);
struct radeonfb_info *rinfo = info->par;
-
+ int i;
+
if (!rinfo)
return;
radeonfb_pm_exit(rinfo);
- if (rinfo->mon1_EDID)
+ if ((rinfo->heads[0] != -1) && rinfo->connectors[rinfo->heads[0]].edid)
sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
- if (rinfo->mon2_EDID)
+ if ((rinfo->heads[1] != -1) && rinfo->connectors[rinfo->heads[1]].edid)
sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+ if ((rinfo->heads[2] != -1) && rinfo->connectors[rinfo->heads[2]].edid)
+ sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid3_attr);
+ if ((rinfo->heads[3] != -1) && rinfo->connectors[rinfo->heads[3]].edid)
+ sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid4_attr);
#if 0
/* restore original state
@@ -2561,10 +2711,11 @@
pci_release_region(pdev, 2);
pci_release_region(pdev, 0);
- kfree(rinfo->mon1_EDID);
- kfree(rinfo->mon2_EDID);
- if (rinfo->mon1_modedb)
- fb_destroy_modedb(rinfo->mon1_modedb);
+ for (i = 0 ; i < RADEON_MAX_CONNECTORS ; i++) {
+ kfree(rinfo->connectors[i].edid);
+ if (rinfo->connectors[i].modedb)
+ fb_destroy_modedb(rinfo->connectors[i].modedb);
+ }
#ifdef CONFIG_FB_RADEON_I2C
radeon_delete_i2c_busses(rinfo);
#endif
@@ -2615,6 +2766,8 @@
force_measure_pll = 1;
} else if (!strncmp(this_opt, "ignore_edid", 11)) {
ignore_edid = 1;
+ } else if (!strncmp(this_opt, "ignore_conntable", 16)) {
+ ignore_conntable = 1;
} else
mode_option = this_opt;
}
@@ -2658,6 +2811,8 @@
MODULE_PARM_DESC(force_dfp, "bool: force display to dfp");
module_param(ignore_edid, bool, 0);
MODULE_PARM_DESC(ignore_edid, "bool: Ignore EDID data when doing DDC probe");
+module_param(ignore_conntable, bool, 0);
+MODULE_PARM_DESC(ignore_conntable, "bool: Ignore BIOS Connector table");
module_param(monitor_layout, charp, 0);
MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)");
module_param(force_measure_pll, bool, 0);
diff -Naur aty-2.6.17/radeon_i2c.c aty-2.6.17-patched/radeon_i2c.c
--- aty-2.6.17/radeon_i2c.c 2006-09-05 10:15:55.000000000 -0400
+++ aty-2.6.17-patched/radeon_i2c.c 2006-09-05 10:34:51.000000000 -0400
@@ -170,13 +170,27 @@
return NULL;
}
-
-int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid)
+/* Returns 1 if probe unsuccessful. */
+int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, struct radeon_connector *conn)
{
- u32 reg = rinfo->i2c[conn-1].ddc_reg;
+ u32 reg;
u8 *edid = NULL;
+ int mon_type = MT_NONE;
+
int i, j;
+ if (!conn)
+ return 1;
+
+ if (rinfo->is_mobility && (conn->ddc_type == ddc_none) &&
+ (INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
+ RTRACE("radeonfb: I2C (port %d) ... found LVDS panel\n", conn->ddc_type);
+ mon_type = MT_LCD;
+ goto done;
+ }
+
+ reg = rinfo->i2c[conn->ddc_type].ddc_reg;
+
OUTREG(reg, INREG(reg) &
~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT));
@@ -212,7 +226,7 @@
msleep(15);
/* Do the real work */
- edid = radeon_do_probe_i2c_edid(&rinfo->i2c[conn-1]);
+ edid = radeon_do_probe_i2c_edid(&rinfo->i2c[conn->ddc_type]);
OUTREG(reg, INREG(reg) |
(VGA_DDC_DATA_OUT_EN | VGA_DDC_CLK_OUT_EN));
@@ -236,30 +250,32 @@
if (edid)
break;
}
+
/* Release the DDC lines when done or the Apple Cinema HD display
* will switch off
*/
OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN | VGA_DDC_DATA_OUT_EN));
(void)INREG(reg);
- if (out_edid)
- *out_edid = edid;
if (!edid) {
- RTRACE("radeonfb: I2C (port %d) ... not found\n", conn);
- return MT_NONE;
+ RTRACE("radeonfb: I2C (port %d) ... not found\n", conn->ddc_type);
+ mon_type = MT_NONE;
+ goto done;
}
- if (edid[0x14] & 0x80) {
- /* 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;
- } else {
- RTRACE("radeonfb: I2C (port %d) ... found TMDS panel\n", conn);
- return MT_DFP;
- }
+
+ if ((edid[0x14] & 0x80) && (conn->ddc_type == ddc_dvi)) {
+ RTRACE("radeonfb: I2C (port %d) ... found TMDS panel\n", conn->ddc_type);
+ mon_type = MT_DFP;
+ goto done;
}
- RTRACE("radeonfb: I2C (port %d) ... found CRT display\n", conn);
- return MT_CRT;
+
+ RTRACE("radeonfb: I2C (port %d) ... found CRT display\n", conn->ddc_type);
+ mon_type = MT_CRT;
+
+ done:
+ conn->edid = edid;
+ conn->mon_type = mon_type;
+
+ return (mon_type == MT_NONE);
}
diff -Naur aty-2.6.17/radeon_monitor.c aty-2.6.17-patched/radeon_monitor.c
--- aty-2.6.17/radeon_monitor.c 2006-09-05 10:15:55.000000000 -0400
+++ aty-2.6.17-patched/radeon_monitor.c 2006-09-05 10:34:51.000000000 -0400
@@ -1,6 +1,29 @@
#include "radeonfb.h"
#include "../edid.h"
+/*
+ * TMDS PLL configuration table, taken from X.org
+ */
+static const struct radeon_tmds_pll_info default_tmds_pll[CHIP_FAMILY_LAST][4] =
+{
+ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/
+ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/
+ {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/
+ {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/
+ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/
+ {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/
+ {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/
+ {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/
+ {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/
+ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/
+ {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x400f7/*0x40111*/}, {0, 0}}, /*CHIP_FAMILY_RV280*/
+ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/
+ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/
+ {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/
+ {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/
+ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/
+};
+
static struct fb_var_screeninfo radeonfb_default_var = {
.xres = 640,
.yres = 480,
@@ -23,35 +46,6 @@
.vmode = FB_VMODE_NONINTERLACED
};
-static char *radeon_get_mon_name(int type)
-{
- char *pret = NULL;
-
- switch (type) {
- case MT_NONE:
- pret = "no";
- break;
- case MT_CRT:
- pret = "CRT";
- break;
- case MT_DFP:
- pret = "DFP";
- break;
- case MT_LCD:
- pret = "LCD";
- break;
- case MT_CTV:
- pret = "CTV";
- break;
- case MT_STV:
- pret = "STV";
- break;
- }
-
- return pret;
-}
-
-
#ifdef CONFIG_PPC_OF
/*
* Try to find monitor informations & EDID data out of the Open Firmware
@@ -59,7 +53,8 @@
* models with broken OF probing by hard-coding known EDIDs for some Mac
* laptops internal LVDS panel. (XXX: not done yet)
*/
-static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID,
+static int __devinit radeon_parse_montype_prop(struct device_node *dp,
+ struct radeon_connector *conn,
int hdno)
{
static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID",
@@ -67,25 +62,30 @@
u8 *pedid = NULL;
u8 *pmt = NULL;
u8 *tmp;
- int i, mt = MT_NONE;
+ int i;
RTRACE("analyzing OF properties...\n");
pmt = (u8 *)get_property(dp, "display-type", NULL);
if (!pmt)
- return MT_NONE;
+ return 1;
RTRACE("display-type: %s\n", pmt);
- /* OF says "LCD" for DFP as well, we discriminate from the caller of this
- * function
- */
- if (!strcmp(pmt, "LCD") || !strcmp(pmt, "DFP"))
- mt = MT_DFP;
- else if (!strcmp(pmt, "CRT"))
- mt = MT_CRT;
- else {
+ if (!strcmp(pmt, "LCD") || !strcmp(pmt, "DFP")) {
+ /* OF says "LCD" for DFP as well.*/
+ if (rinfo->is_mobility) {
+ conn->mon_type = MT_LCD;
+ /* Maybe check for LVDS_GEN_CNTL here ? I need to check out
+ * what OF does when booting with lid closed
+ */
+ } else{
+ conn->mon_type = MT_DFP;
+ }
+ } else if (!strcmp(pmt, "CRT")) {
+ conn->mon_type = MT_CRT;
+ } else {
if (strcmp(pmt, "NONE") != 0)
printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n",
pmt);
- return MT_NONE;
+ return 1;
}
for (i = 0; propnames[i] != NULL; ++i) {
@@ -102,26 +102,41 @@
if (pedid == NULL && dp->parent && (hdno == 0))
pedid = get_property(dp->parent, "EDID", NULL);
if (pedid == NULL)
- return mt;
+ return 1;
tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (!tmp)
- return mt;
- memcpy(tmp, pedid, EDID_LENGTH);
- *out_EDID = tmp;
- return mt;
+ if (tmp) {
+ memcpy(tmp, pedid, EDID_LENGTH);
+ }
+
+ conn->edid = tmp;
+
+ {
+ int found_tmds = 0;
+ int found_crt = 0;
+ int ddc_type = ddc_none;
+ // XXX what about reversed DAC/TMDS??
+ radeon_fill_conn(conn, conn->mon_type, ddc_type, &found_crt, &found_tmds);
+ }
+
+ return 0;
}
-static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no,
- u8 **out_EDID)
+/* return a 1 on error */
+static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no)
+
{
+ struct radeon_connector *conn;
struct device_node *dp;
+ u8 *out_EDID;
RTRACE("radeon_probe_OF_head\n");
+ conn = rinfo->connectors[head_no];
+
dp = rinfo->of_node;
- while (dp == NULL)
- return MT_NONE;
+ if (dp == NULL)
+ return 1;
if (rinfo->has_CRTC2) {
char *pname;
@@ -129,52 +144,94 @@
dp = dp->child;
do {
- if (!dp)
- return MT_NONE;
+ if (!dp)
+ return 1;
+
pname = (char *)get_property(dp, "name", NULL);
- if (!pname)
- return MT_NONE;
+ if (!pname)
+ return 1;
+
len = strlen(pname);
RTRACE("head: %s (letter: %c, head_no: %d)\n",
pname, pname[len-1], head_no);
if (pname[len-1] == 'A' && head_no == 0) {
- int mt = radeon_parse_montype_prop(dp, out_EDID, 0);
- /* Maybe check for LVDS_GEN_CNTL here ? I need to check out
- * what OF does when booting with lid closed
- */
- if (mt == MT_DFP && rinfo->is_mobility)
- mt = MT_LCD;
- return mt;
- } else if (pname[len-1] == 'B' && head_no == 1)
- return radeon_parse_montype_prop(dp, out_EDID, 1);
+ return radeon_parse_montype_prop(dp, conn, 0);
+ } else if (pname[len-1] == 'B' && head_no == 1) {
+ return radeon_parse_montype_prop(dp, conn, 1);
+ }
second = 1;
dp = dp->sibling;
} while(!second);
} else {
- if (head_no > 0)
- return MT_NONE;
- return radeon_parse_montype_prop(dp, out_EDID, -1);
+ if (head_no > 0) {
+ return 1;
+ }
+ return radeon_parse_montype_prop(dp, conn, -1);
}
- return MT_NONE;
+ return 1;
}
#endif /* CONFIG_PPC_OF */
-static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
+int __devinit radeon_get_lvds_info_atom(struct radeonfb_info *rinfo)
+{
+ unsigned long tmp;
+
+ if (!rinfo->bios_seg)
+ return -ENODEV;
+
+ tmp = BIOS_IN16(rinfo->atom_data_start + 16);
+ if (!tmp) {
+ printk(KERN_ERR "radeonfb: No LVDS panel info in BIOS\n");
+ rinfo->panel_info.pwr_delay = 200;
+ return -ENODEV;
+ }
+
+ rinfo->panel_info.xres = BIOS_IN16(tmp+6);
+ rinfo->panel_info.yres = BIOS_IN16(tmp+10);
+ printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n",
+ rinfo->panel_info.xres, rinfo->panel_info.yres);
+ rinfo->panel_info.pwr_delay = BIOS_IN16(tmp+40);
+ 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;
+
+ /* No special divider combinations? */
+
+ rinfo->panel_info.hblank = BIOS_IN16(tmp+8);
+ rinfo->panel_info.hOver_plus = BIOS_IN16(tmp+14);
+ rinfo->panel_info.hSync_width = BIOS_IN16(tmp+16);
+ rinfo->panel_info.vblank = BIOS_IN16(tmp+12);
+ rinfo->panel_info.vOver_plus = BIOS_IN16(tmp+18);
+ rinfo->panel_info.vSync_width = BIOS_IN16(tmp+20);
+ rinfo->panel_info.clock = BIOS_IN16(tmp+4);
+
+ /* Assume high active syncs for now until ATI tells me more... maybe we
+ * can probe register values here ?
+ */
+ rinfo->panel_info.hAct_high = 1;
+ rinfo->panel_info.vAct_high = 1;
+ /* Mark panel infos valid */
+ rinfo->panel_info.valid = 1;
+
+ return 0;
+}
+
+int __devinit radeon_get_lvds_info_legacy(struct radeonfb_info *rinfo)
{
unsigned long tmp, tmp0;
char stmp[30];
int i;
if (!rinfo->bios_seg)
- return 0;
+ return -ENODEV;
if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) {
- printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n");
+ printk(KERN_ERR "radeonfb: No LVDS panel info in BIOS\n");
rinfo->panel_info.pwr_delay = 200;
- return 0;
+ return -ENODEV;
}
-
+
for(i=0; i<24; i++)
stmp[i] = BIOS_IN8(tmp+i+1);
stmp[24] = 0;
@@ -182,13 +239,13 @@
rinfo->panel_info.xres = BIOS_IN16(tmp + 25);
rinfo->panel_info.yres = BIOS_IN16(tmp + 27);
printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n",
- rinfo->panel_info.xres, rinfo->panel_info.yres);
-
+ rinfo->panel_info.xres, rinfo->panel_info.yres);
+
rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44);
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;
-
+
/*
* Some panels only work properly with some divider combinations
*/
@@ -203,6 +260,7 @@
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);
@@ -226,7 +284,7 @@
rinfo->panel_info.vAct_high = 1;
/* 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);
@@ -235,12 +293,427 @@
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;
+
+ return 0;
}
}
+
RTRACE("Didn't find panel in BIOS table !\n");
+ return -ENODEV;
+}
+
+/*
+ * Get informations about TMDS controllers and their setup at
+ * different operating frequencies
+ */
+void __devinit radeon_get_tmds_info(struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* Get default TMDS infos for this chip */
+ for (i=0; i<4; i++) {
+ rinfo->tmds_pll[i].value =
+ default_tmds_pll[rinfo->family][i].value;
+ rinfo->tmds_pll[i].freq =
+ default_tmds_pll[rinfo->family][i].freq;
+ }
+
+ /* Get whatever the firmware provides */
+ if (rinfo->radeon_get_tmds_info) {
+ rinfo->radeon_get_tmds_info(rinfo);
+ // XXX Do we care about the return value?
+ }
+}
+
+int __devinit radeon_get_tmds_info_legacy(struct radeonfb_info *rinfo)
+{
+ int offset, i, n, rev;
+
+ offset = BIOS_IN16(rinfo->fp_bios_start + 0x34);
+ if (offset == 0)
+ return -ENODEV;
+
+ rev = BIOS_IN8(offset);
+ printk(KERN_INFO "DFP table revision: %d\n", rev);
+
+ switch(rev) {
+ case 3:
+ n = BIOS_IN8(offset + 5) + 1;
+ if (n > 4)
+ n = 4;
+ for (i = 0; i < n; i++) {
+ /* Looks bogus ... but that's what is in X.org */
+ rinfo->tmds_pll[i].value =
+ BIOS_IN32(offset+i*10+0x08);
+ rinfo->tmds_pll[i].freq =
+ BIOS_IN16(offset+i*10+0x10);
+ }
+ return 0;
+
+ /* revision 4 has some problem as it appears in RV280,
+ * comment it off for now, use default instead
+ */
+#if 0
+ case 4:
+ stride = 0;
+ n = BIOS_IN8(offset 5) + 1;
+ if (n > 4)
+ n = 4;
+ for (i = 0; i < n; i++) {
+ rinfo->tmds_pll[i].value =
+ BIOS_IN32(tmp+stride+0x08);
+ rinfo->tmds_pll[i].freq =
+ BIOS_IN16(tmp+stride+0x10);
+ if (i == 0)
+ stride += 10;
+ else
+ stride += 6;
+ }
+ return 0;
+#endif
+ }
+ return -ENODEV;
+}
+
+int __devinit radeon_get_tmds_info_atom(struct radeonfb_info *rinfo)
+{
+ int offset, i, maxfreq;
+
+ offset = BIOS_IN16(rinfo->atom_data_start + 18);
+ if (offset == 0)
+ return -ENODEV;
+
+ maxfreq = BIOS_IN16(offset + 4);
+
+ for (i = 0; i < 4; i++) {
+ rinfo->tmds_pll[i].freq = BIOS_IN16(offset+i*6+6);
+ /* This assumes each field in TMDS_PLL has 6 bit as
+ * in R300/R420
+ */
+ rinfo->tmds_pll[i].value =
+ ((BIOS_IN8(offset+i*6+8) & 0x3f) |
+ ((BIOS_IN8(offset+i*6+10) & 0x3f)<<6) |
+ ((BIOS_IN8(offset+i*6+9) & 0xf)<<12) |
+ ((BIOS_IN8(offset+i*6+11) & 0xf)<<16));
+ printk(KERN_INFO "TMDS PLL from BIOS: %ld %x\n",
+ rinfo->tmds_pll[i].freq, rinfo->tmds_pll[i].value);
+
+ if (maxfreq == rinfo->tmds_pll[i].freq) {
+ rinfo->tmds_pll[i].freq = 0xffffffff;
+ break;
+ }
+ }
+ return 0;
+}
+
+
+static const char *conn_type_name[] = {
+ "NONE", "VGA", "DVI-I", "DVI-D", "DVI-A", "S-Video",
+ "Composite Video", "Internal Panel", "Digital",
+ "Unsupported", "Proprietary"
+};
+
+static const char *mon_type_name[] = {
+ "None", "CRT", "LVDS Flat panel",
+ "DVI Flat panel", "Composite TV", "S-Video TV"
+};
+
+static void __devinit radeon_fill_conn(struct radeon_connector *conn, int mon_type, int ddc_type, int *found_tmds, int *found_crt)
+{
+ conn->mon_type = mon_type;
+ conn->ddc_type = ddc_type;
+
+ // XXX what about reversed DAC/TMDS??
+
+ switch(mon_type) {
+ case MT_CRT:
+ conn->conn_type = conn_vga;
+ conn->tmds_type = tmds_unknown;
+ conn->dac_type = (*found_crt) ? dac_tvdac: dac_primary;
+ if (ddc_type == ddc_none) conn->ddc_type = (*found_crt) ? ddc_crt2 : ddc_vga;
+ *found_crt = 1;
+ break;
+ case MT_DFP:
+ conn->conn_type = conn_dvi_i;
+ conn->tmds_type = (*found_tmds) ? tmds_external: tmds_internal;
+ conn->dac_type = dac_unknown;
+ if (ddc_type == ddc_none) conn->ddc_type = ddc_dvi;
+ *found_tmds = 1;
+ break;
+ case MT_LCD:
+ conn->conn_type = conn_lvds;
+ conn->tmds_type = tmds_unknown;
+ conn->dac_type = dac_unknown;
+ if (ddc_type == ddc_none) conn->ddc_type = ddc_none; //heh
+ break;
+ case MT_CTV:
+ conn->conn_type = conn_ctv;
+ conn->tmds_type = tmds_unknown;
+ conn->dac_type = dac_tvdac;
+ if (ddc_type == ddc_none) conn->ddc_type = ddc_vga; // XXX ddc_crt2?
+ break;
+ case MT_STV:
+ conn->conn_type = conn_stv;
+ conn->tmds_type = tmds_unknown;
+ conn->dac_type = dac_tvdac;
+ if (ddc_type == ddc_none) conn->ddc_type = ddc_vga; // XXX ddc_crt2?
+ break;
+ case MT_UNKNOWN:
+ case MT_NONE:
+ conn->conn_type = conn_none;
+ conn->tmds_type = tmds_unknown;
+ conn->mon_type = MT_NONE;
+ conn->ddc_type = ddc_none;
+ conn->dac_type = dac_unknown;
+ break;
+ default:
+ break;
+ }
+ // leaves conn_digital, conn_unsupported, conn_propritetary
+}
+
+/*
+ * Get informations about the various connectors on this card. This is
+ * the most prone to fail function as various firmwares tend to say
+ * crap or not give any info at all. The Open Firmware version is just
+ * a table of known cards for now for example. We'll probably need some
+ * additional module params to force different settings in case of
+ * misdetection here.
+ *
+ * This doesn _not_ try actual probing of whatever is plugged on those
+ * various connectors. This will be done later. We do store whatever
+ * probing info the firmware gives us though
+ */
+void __devinit radeon_get_conn_info(struct radeonfb_info *rinfo, int ignore_conntable)
+{
+ int i;
+
+ /* Clear table */
+ for (i = 0; i < RADEON_MAX_CONNECTORS; i++) {
+ rinfo->connectors[i].conn_type = conn_none;
+ rinfo->connectors[i].ddc_type = ddc_none;
+ rinfo->connectors[i].dac_type = dac_unknown;
+ rinfo->connectors[i].tmds_type = tmds_unknown;
+ rinfo->connectors[i].mon_type = MT_UNKNOWN;
+ rinfo->connectors[i].head = -1;
+ rinfo->heads[i] = -1;
+ }
+ rinfo->num_heads = 0;
+
+ if (ignore_conntable) {
+#if defined(CONFIG_FB_RADEON_I2C)
+ struct radeon_connector conn;
+ int idx = 0;
+ int found_tmds = 0;
+ int found_crt = 0;
+
+ // XXX what about reversed DAC/TMDS??
+
+ for (i = 0; i < 4; i++) {
+ conn.ddc_type = i;
+ if (!radeon_probe_i2c_connector(rinfo, &conn)) {
+
+ radeon_fill_conn(&rinfo->connectors[idx++], conn.mon_type, conn.ddc_type, &found_tmds, &found_crt);
+ }
+ }
+
+ /* If we failed to probe something.. */
+ if (idx)
+ goto found;
+#endif /* CONFIG_FB_RADEON_I2C */
+ } else {
+ /* Try to obtain infos from firmware */
+ if (rinfo->radeon_get_conn_info) {
+ if (!rinfo->radeon_get_conn_info(rinfo)) {
+ goto found;
+ }
+ }
+ }
+
+ printk(KERN_INFO "radeonfb: No connector infos, using defaults...\n");
+
+ /* Here, we use defaults that are common enough ... we hope
+ * For a mobility chip, we assume LVDS is on primary
+ */
+ if (rinfo->is_mobility) {
+ rinfo->connectors[0].conn_type = conn_lvds;
+ rinfo->connectors[0].ddc_type = ddc_dvi;
+ rinfo->connectors[0].dac_type = dac_primary;
+ rinfo->connectors[0].tmds_type = tmds_unknown;
+ rinfo->connectors[0].mon_type = MT_UNKNOWN;
+
+ rinfo->connectors[1].conn_type = conn_dvi_d;
+ rinfo->connectors[1].ddc_type = ddc_vga;
+ rinfo->connectors[1].dac_type = dac_primary;
+ rinfo->connectors[1].tmds_type = tmds_internal;
+ rinfo->connectors[1].mon_type = MT_UNKNOWN;
+
+ rinfo->connectors[2].conn_type = conn_stv;
+ rinfo->connectors[2].ddc_type = ddc_none;
+ rinfo->connectors[2].dac_type = dac_tvdac;
+ rinfo->connectors[2].tmds_type = tmds_unknown;
+ rinfo->connectors[2].mon_type = MT_UNKNOWN;
+ } else {
+ rinfo->connectors[0].conn_type = conn_dvi_d;
+ rinfo->connectors[0].ddc_type = ddc_dvi;
+ rinfo->connectors[0].dac_type = dac_tvdac;
+ rinfo->connectors[0].tmds_type = tmds_internal;
+ rinfo->connectors[0].mon_type = MT_UNKNOWN;
+
+ rinfo->connectors[1].conn_type = conn_vga;
+ rinfo->connectors[1].ddc_type = ddc_vga;
+ rinfo->connectors[1].dac_type = dac_primary;
+ rinfo->connectors[1].tmds_type = tmds_unknown;
+ rinfo->connectors[1].mon_type = MT_UNKNOWN;
+
+ if (rinfo->has_CRTC2) {
+ rinfo->connectors[1].conn_type = conn_vga;
+ rinfo->connectors[1].ddc_type = ddc_crt2;
+ rinfo->connectors[1].dac_type = dac_tvdac;
+ rinfo->connectors[1].tmds_type = tmds_unknown;
+ rinfo->connectors[1].mon_type = MT_UNKNOWN;
+ }
+ }
+
+ found:
+ /* Now, we do additional fixups */
+
+ /* RS300 has only one DAC, force TV-DAC on VGA port */
+ if (rinfo->family == CHIP_FAMILY_RS300) {
+ for (i = 0; i < RADEON_MAX_CONNECTORS; i++) {
+ if (rinfo->connectors[i].conn_type == conn_vga)
+ rinfo->connectors[i].dac_type = dac_tvdac;
+ else if (rinfo->connectors[i].dac_type != dac_unknown)
+ rinfo->connectors[i].dac_type = dac_primary;
+ }
+ }
+
+ /* Single head chips all use primary DAC */
+ if (!rinfo->has_CRTC2)
+ rinfo->connectors[0].dac_type = dac_primary;
+
+ return;
+ }
+
+#ifdef CONFIG_PPC_OF
+int __devinit radeon_get_conn_info_openfirmware(struct radeonfb_info *rinfo)
+{
+ int i;
+ int not_found = 1;
+
+ for(i = 0 ; < 2 ; i++) { /* Only two heads for OF! */
+ if (!radeon_probe_OF_head(rinfo, i)) found = 0;
+ }
+ return found;
+}
+#endif /* CONFIG_PPC_OF */
+
+int __devinit radeon_get_conn_info_atom(struct radeonfb_info *rinfo)
+{
+ int i, j, offset, valids;
+ int ids[RADEON_MAX_CONNECTORS];
+ u16 portinfo, tmp0;
+ int conn_index = 0;
+ int conn_add = 2;
+ int idx = 0;
+ int ddc_type, dac_type, conn_type, tmds_type, port_id;
+ int connector_found = 0;
+
+ offset = BIOS_IN16(rinfo->atom_data_start + 22);
+ if (offset == 0)
+ return -ENODEV;
+
+ /* Again, I slightly modified X.org algorithm. I assign "primary" outputs
+ * to entries 0 and 1, and anything else goes after 2.
+ *
+ * Also, I keep an array of all port IDs matching connectors[] array,
+ * unlike X which limits itself to "crtc"'s
+ */
+ for (i = 0; i < RADEON_MAX_CONNECTORS; i++)
+ ids[i] = -1;
+
+ valids = BIOS_IN16(offset + 4);
+ for (i = 0; i < 8; i++) {
+ if (!(valids & (1 << i)))
+ continue;
+ portinfo = BIOS_IN16(offset + 6 + i*2);
+
+ conn_type = (portinfo >> 4) & 0xf;
+ dac_type = (portinfo & 0xf) - 1;
+ port_id = (portinfo >> 8) & 0xf;
+ ddc_type = ddc_none;
+
+ if ((tmp0 = BIOS_IN16(rinfo->atom_data_start + 24))) {
+ switch(BIOS_IN16(tmp0 + 4 + (27 * port_id)) * 4) {
+ case GPIO_MONID:
+ ddc_type = ddc_monid;
+ break;
+ case GPIO_DVI_DDC:
+ ddc_type = ddc_dvi;
+ break;
+ case GPIO_VGA_DDC:
+ ddc_type = ddc_vga;
+ break;
+ case GPIO_CRT2_DDC:
+ ddc_type = ddc_crt2;
+ break;
+ default:
+ ddc_type = ddc_none;
+ break;
+ }
+ }
+
+ if (i == 3)
+ tmds_type = tmds_internal;
+ else if (i == 7)
+ tmds_type = tmds_external;
+ else
+ tmds_type = tmds_unknown;
+
+ RTRACE("index %d port %d conn %d dac %d ddc %d tmds %d\n", i, port_id, conn_type, dac_type, ddc_type, tmds_type);
+
+ /* Ok, now we have the port ID, look for an existing port
+ * already using this ID
+ */
+ for (j = 0; j < RADEON_MAX_CONNECTORS; j++) {
+ if (port_id != ids[j])
+ continue;
+ /* Gotcha, just "update" values */
+ if (tmds_type != tmds_unknown)
+ rinfo->connectors[j].tmds_type = tmds_type;
+ if (rinfo->connectors[j].dac_type == dac_unknown)
+ rinfo->connectors[j].dac_type = dac_type;
+ if (rinfo->connectors[j].ddc_type == dac_unknown)
+ rinfo->connectors[j].ddc_type = dac_type;
+ continue;
+ }
+
+ conn_index = (ddc_type == ddc_dvi || conn_index == 1) ? 0 : 1;
+
+ /* if the port is a TV port, or both connectors are already
+ * assigned, assign it after further in the table
+ */
+ if (conn_type == conn_ctv || conn_type == conn_stv ||
+ (rinfo->connectors[0].conn_type != conn_none &&
+ rinfo->connectors[1].conn_type))
+ idx = conn_add++;
+ else
+ idx = conn_index;
+
+ rinfo->connectors[idx].tmds_type = tmds_type;
+ rinfo->connectors[idx].dac_type = dac_type;
+ rinfo->connectors[idx].ddc_type = ddc_type;
+ rinfo->connectors[idx].conn_type = conn_type;
+
+ /* increment connector_found for primary connectors only */
+ if (idx < 2)
+ connector_found += (idx + 1);
+ }
+
+ if (connector_found == 0)
+ return -ENODEV;
+
return 0;
}
@@ -248,44 +721,167 @@
* 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 __devinit radeon_get_conn_info_legacy(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"
+ int offset, i, entry, tmp;
+ int ddc_type, dac_type, conn_type, tmds_type;
+ int conn_index = 0;
+ int conn_add = 2;
+ int idx = 0;
+
+ /* Convert legacy to real connector types */
+ const enum radeon_conn_type legacy_conn_to_type[] = {
+ conn_none,
+ conn_proprietary,
+ conn_vga,
+ conn_dvi_i,
+ conn_dvi_d,
+ conn_ctv,
+ conn_stv,
+ conn_unsupported,
};
- if (!rinfo->bios_seg)
- return;
+ /* Some laptops only have one connector (VGA) listed in the connector
+ * table, we need to add LVDS in as a non-DDC display.
+ * Note, we can't assume the listed VGA will be filled in PortInfo[0],
+ * when walking through connector table. connector_found has following
+ * meaning:
+ * 0 -- nothing found,
+ * 1 -- only connectors[0] filled,
+ * 2 -- only connectors[1] filled,
+ * 3 -- both are filled.
+ *
+ * Note: I modified X.org algorithm to add additional entries if any
+ * after the second table slot. Those entries do not affect the value
+ * of connector_found. --BenH.
+ */
+ int connector_found = 0;
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);
+ if (offset == 0)
+ return -ENODEV;
+
+ for (i = 1; i < 4; i++) {
+ entry = offset + i*2;
+
+ /* End of table */
+ if (!BIOS_IN8(entry) && i > 1)
+ break;
+
+ /* Read table entry, check connector type */
+ tmp = BIOS_IN16(entry);
+ conn_type = (tmp >> 12) & 0xf;
+ if (conn_type == legacy_conn_none)
+ continue;
+ ddc_type = (tmp >> 8) & 0xf;
+ dac_type = (tmp & 0x01) ? dac_tvdac : dac_primary;
+ tmds_type = (tmp & 0x10) ? tmds_external : tmds_internal;
+
+ /* same connector */
+ if (connector_found > 0) {
+ if (rinfo->connectors[conn_index].ddc_type == ddc_type)
+ continue;
+ }
+
+ /* sanity checks */
+ if (ddc_type > ddc_crt2)
+ ddc_type = ddc_none;
+ if (conn_type > legacy_conn_unsupported)
+ conn_type = legacy_conn_unsupported;
+ if (conn_type != legacy_conn_dvi_d &&
+ conn_type != legacy_conn_dvi_i &&
+ tmds_type == tmds_internal)
+ tmds_type= tmds_unknown;
+
+ /* convert connector type */
+ conn_type = legacy_conn_to_type[conn_type];
+
+ /* internal DDC_DVI port will get assigned to connector[0], or
+ * if there is no DDC_DVI (like in some IGPs).
+ */
+ conn_index = (ddc_type == ddc_dvi || conn_index == 1) ? 0 : 1;
+
+ /* if the port is a TV port, or both connectors are already
+ * assigned, assign it after further in the table
+ */
+ if (conn_type == conn_ctv || conn_type == conn_stv ||
+ (rinfo->connectors[0].conn_type != conn_none &&
+ rinfo->connectors[1].conn_type))
+ idx = conn_add++;
+ else
+ idx = conn_index;
+
+ /* if table full, exit */
+ if (idx >= RADEON_MAX_CONNECTORS) {
+ printk(KERN_WARNING "radeonfb: Connector table full !\n");
+ break;
}
+ rinfo->connectors[idx].conn_type = conn_type;
+ rinfo->connectors[idx].ddc_type = ddc_type;
+ rinfo->connectors[idx].dac_type = dac_type;
+ rinfo->connectors[idx].tmds_type = tmds_type;
+
+ /* increment connector_found for primary connectors only */
+ if (idx < 2)
+ connector_found += (idx + 1);
+ }
+
+ if (rinfo->is_mobility) {
+ /* For the cases where only one VGA connector is found,
+ * we assume LVDS is not listed in the connector table,
+ * add it in here as the first port.
+ *
+ * TODO: Check what's up with laptops that have a DVI output
+ * and no LVDS entry in the table. I suspect some thinkpads
+ * may play trick with us here... We may want to check the
+ * presence of a panel via LVDS_GEN_CNTL to be sure...
+ */
+ if ((connector_found < 3) &&
+ (rinfo->connectors[idx].conn_type == conn_vga)) {
+ if (connector_found == 1) {
+ memcpy(&rinfo->connectors[1],
+ &rinfo->connectors[0],
+ sizeof(struct radeon_connector));
+ }
+ /* Fixme: TV DAC is probably elsewhere ... */
+ rinfo->connectors[0].dac_type = dac_tvdac;
+ rinfo->connectors[0].tmds_type = tmds_unknown;
+ rinfo->connectors[0].ddc_type = ddc_none;
+ rinfo->connectors[0].conn_type = conn_proprietary;
+
+ printk(KERN_WARNING "radeonfb: LVDS port is not in connector table, added in.\n");
+ if (connector_found == 0)
+ connector_found = 1;
+ else
+ connector_found = 3;
+ }
+
+ /* Check for LCD DDC info table */
+ if ((offset = BIOS_IN16(rinfo->fp_bios_start + 0x42))) {
+ if ((tmp = BIOS_IN16(offset + 0x15))) {
+ if ((ddc_type = BIOS_IN8(tmp+2) & 0x07)) {
+ rinfo->connectors[0].ddc_type = ddc_type;
+ printk(KERN_WARNING "radeonfb: LCD DDC Info Table found, "
+ "forcing primary port to %d\n",
+ ddc_type);
+ }
+ }
+ }
+ } else if (connector_found == 2) {
+ memcpy(&rinfo->connectors[0], &rinfo->connectors[1],
+ sizeof (struct radeon_connector));
+ rinfo->connectors[1].dac_type = dac_unknown;
+ rinfo->connectors[1].tmds_type = tmds_unknown;
+ rinfo->connectors[1].ddc_type = ddc_none;
+ rinfo->connectors[1].conn_type = conn_none;
+ connector_found = 1;
}
+
+ if (connector_found == 0)
+ return -ENODEV;
+
+ /* External TMDS Table, not used now */
+ return 0;
}
@@ -362,6 +958,50 @@
return connected ? MT_CRT : MT_NONE;
}
+/* Find if the desired connector and monitor are compatible */
+static int __devinit radeon_conn_monitor_compatible(int mon_type, int conn_type)
+{
+ switch(mon_type) {
+ case MT_CRT:
+ return ((conn_type == conn_vga) || (conn_type == conn_dvi_a));
+ case MT_DFP:
+ return ((conn_type == conn_dvi_i) || (conn_type == conn_dvi_d));
+ case MT_LCD:
+ return (conn_type == conn_lvds);
+ case MT_CTV:
+ return (conn_type == conn_ctv);
+ case MT_STV:
+ return (conn_type == conn_stv);
+ case MT_UNKNOWN:
+ case MT_NONE:
+ default:
+ return 0;
+ }
+ // leaves conn_digital, conn_unsupported, conn_propritetary
+}
+
+/* Find a suitable connector for this display type */
+static int __devinit radeon_find_connector_for_mon(struct radeonfb_info *rinfo, int mon_type)
+{
+ int i;
+
+ if (mon_type <= MT_NONE) return 0;
+
+ for (i = 0; i < RADEON_MAX_CONNECTORS ; i++) {
+ if (radeon_conn_monitor_compatible(mon_type, rinfo->connectors[i].conn_type) &&
+ (rinfo->connectors[i].mon_type <= MT_NONE)) {
+ rinfo->connectors[i].mon_type = mon_type;
+ rinfo->connectors[i].head = rinfo->num_heads;
+ rinfo->heads[rinfo->num_heads] = i;
+ rinfo->num_heads++;
+ return 0;
+ }
+ }
+
+ printk(KERN_INFO "radeonfb: couldn't find a connector for monitor %d\n", mon_type);
+ return -1;
+}
+
/*
* Parse the "monitor_layout" string if any. This code is mostly
* copied from XFree's radeon driver
@@ -407,19 +1047,20 @@
s1[i] = 0;
s2[0] = 0;
}
+
if (strcmp(s1, "CRT") == 0)
- rinfo->mon1_type = MT_CRT;
+ radeon_find_connector_for_mon(rinfo, MT_CRT);
else if (strcmp(s1, "TMDS") == 0)
- rinfo->mon1_type = MT_DFP;
+ radeon_find_connector_for_mon(rinfo, MT_DFP);
else if (strcmp(s1, "LVDS") == 0)
- rinfo->mon1_type = MT_LCD;
+ radeon_find_connector_for_mon(rinfo, MT_LCD);
if (strcmp(s2, "CRT") == 0)
- rinfo->mon2_type = MT_CRT;
+ radeon_find_connector_for_mon(rinfo, MT_CRT);
else if (strcmp(s2, "TMDS") == 0)
- rinfo->mon2_type = MT_DFP;
+ radeon_find_connector_for_mon(rinfo, MT_DFP);
else if (strcmp(s2, "LVDS") == 0)
- rinfo->mon2_type = MT_LCD;
+ radeon_find_connector_for_mon(rinfo, MT_LCD);
return 1;
}
@@ -433,12 +1074,7 @@
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;
-#endif
- int tmp, i;
-
- radeon_parse_connector_info(rinfo);
+ int i;
if (radeon_parse_monitor_layout(rinfo, monitor_layout)) {
@@ -449,30 +1085,33 @@
* a layout for each card ?
*/
- RTRACE("Using specified monitor layout: %s", monitor_layout);
+ RTRACE("Using specified monitor layout: %s\n", monitor_layout);
#ifdef CONFIG_FB_RADEON_I2C
if (!ignore_edid) {
- if (rinfo->mon1_type != MT_NONE)
- if (!radeon_probe_i2c_connector(rinfo, ddc_dvi, &rinfo->mon1_EDID)) {
- radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon1_EDID);
- ddc_crt2_used = 1;
+ int mon_type;
+
+ /* If the DDC detection fails,
+ we still want to use the user's specified layout! */
+ mon_type = PRIMARY_MONITOR(rinfo);
+
+ if (PRIMARY_MONITOR(rinfo) > MT_NONE)
+ if (radeon_probe_i2c_connector(rinfo, &PRIMARY_HEAD(rinfo)))
+ PRIMARY_MONITOR(rinfo) = mon_type;
+ if (SECONDARY_HEAD_PRESENT(rinfo)) {
+ mon_type = SECONDARY_MONITOR(rinfo);
+ if (SECONDARY_MONITOR(rinfo) > MT_NONE) {
+ if (radeon_probe_i2c_connector(rinfo, &SECONDARY_HEAD(rinfo))) {
+ rinfo->connectors[rinfo->heads[1]].mon_type = mon_type;
+ }
}
- if (rinfo->mon2_type != MT_NONE)
- if (!radeon_probe_i2c_connector(rinfo, ddc_vga, &rinfo->mon2_EDID) &&
- !ddc_crt2_used)
- radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon2_EDID);
+ }
}
#endif /* CONFIG_FB_RADEON_I2C */
- if (rinfo->mon1_type == MT_NONE) {
- if (rinfo->mon2_type != MT_NONE) {
- rinfo->mon1_type = rinfo->mon2_type;
- rinfo->mon1_EDID = rinfo->mon2_EDID;
- } else {
- rinfo->mon1_type = MT_CRT;
- printk(KERN_INFO "radeonfb: No valid monitor, assuming CRT on first port\n");
- }
- rinfo->mon2_type = MT_NONE;
- rinfo->mon2_EDID = NULL;
+
+ /* If the user specified a bogus monitor layout... */
+ if (PRIMARY_MONITOR(rinfo) <= MT_NONE) {
+ radeon_find_connector_for_mon(rinfo, MT_CRT);
+ printk(KERN_INFO "radeonfb: No valid monitor, assuming CRT on first port\n");
}
} else {
/*
@@ -481,182 +1120,100 @@
RTRACE("Starting monitor auto detection...\n");
-#if DEBUG && defined(CONFIG_FB_RADEON_I2C)
- {
- 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
*/
if (!rinfo->has_CRTC2) {
-#ifdef CONFIG_PPC_OF
- if (rinfo->mon1_type == MT_NONE)
- rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
- &rinfo->mon1_EDID);
-#endif /* CONFIG_PPC_OF */
#ifdef CONFIG_FB_RADEON_I2C
- if (rinfo->mon1_type == MT_NONE)
- rinfo->mon1_type =
- radeon_probe_i2c_connector(rinfo, ddc_dvi,
- &rinfo->mon1_EDID);
- if (rinfo->mon1_type == MT_NONE)
- rinfo->mon1_type =
- radeon_probe_i2c_connector(rinfo, ddc_vga,
- &rinfo->mon1_EDID);
- if (rinfo->mon1_type == MT_NONE)
- rinfo->mon1_type =
- radeon_probe_i2c_connector(rinfo, ddc_crt2,
- &rinfo->mon1_EDID);
-#endif /* CONFIG_FB_RADEON_I2C */
- if (rinfo->mon1_type == MT_NONE)
- rinfo->mon1_type = MT_CRT;
- goto bail;
- }
-
- /*
- * Check for cards with reversed DACs or TMDS controllers using BIOS
- */
- if (rinfo->bios_seg &&
- (tmp = BIOS_IN16(rinfo->fp_bios_start + 0x50))) {
- for (i = 1; i < 4; i++) {
- unsigned int tmp0;
-
- if (!BIOS_IN8(tmp + i*2) && i > 1)
- break;
- tmp0 = BIOS_IN16(tmp + i*2);
- if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0x0f) == ddc_dvi)) {
- rinfo->reversed_DAC = 1;
- printk(KERN_INFO "radeonfb: Reversed DACs detected\n");
- }
- if ((((tmp0 >> 8) & 0x0f) == ddc_dvi) && ((tmp0 >> 4) & 0x01)) {
- rinfo->reversed_TMDS = 1;
- printk(KERN_INFO "radeonfb: Reversed TMDS detected\n");
+ /* Probe each connector */
+ for(i = 0 ; i < RADEON_MAX_CONNECTORS ; i++) {
+ if (PRIMARY_MONITOR(rinfo) > MT_NONE) break; /* only one head */
+ if (!radeon_probe_i2c_connector(rinfo, &rinfo->connectors[i])) {
+ rinfo->heads[rinfo->num_heads] = i;
+ rinfo->connectors[i].head = rinfo->num_heads++;
}
}
+#endif /* CONFIG_FB_RADEON_I2C */
+ if (PRIMARY_MONITOR(rinfo) <= MT_NONE) {
+ radeon_find_connector_for_mon(rinfo, MT_CRT);
+ }
+ goto bail;
}
- /*
- * Probe primary head (DVI or laptop internal panel)
- */
-#ifdef CONFIG_PPC_OF
- if (rinfo->mon1_type == MT_NONE)
- rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
- &rinfo->mon1_EDID);
-#endif /* CONFIG_PPC_OF */
+ /* Probe heads */
#ifdef CONFIG_FB_RADEON_I2C
- if (rinfo->mon1_type == MT_NONE)
- rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,
- &rinfo->mon1_EDID);
- if (rinfo->mon1_type == MT_NONE) {
- rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,
- &rinfo->mon1_EDID);
- if (rinfo->mon1_type != MT_NONE)
- ddc_crt2_used = 1;
+ /* Probe each connector in turn. */
+ for(i = 0 ; i < RADEON_MAX_CONNECTORS ; i++) {
+ if (rinfo->connectors[i].mon_type > MT_NONE) continue; /* Don't probe "detected" stuff again */
+ if (!radeon_probe_i2c_connector(rinfo, &rinfo->connectors[i])) {
+ rinfo->heads[rinfo->num_heads] = i;
+ rinfo->connectors[i].head = rinfo->num_heads++;
+ }
}
+
#endif /* CONFIG_FB_RADEON_I2C */
- if (rinfo->mon1_type == MT_NONE && rinfo->is_mobility &&
+
+ /* mobility chips are usually LCDs */
+ if ((PRIMARY_MONITOR(rinfo) <= MT_NONE) && rinfo->is_mobility &&
((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4))
|| (INREG(LVDS_GEN_CNTL) & LVDS_ON))) {
- rinfo->mon1_type = MT_LCD;
- printk("Non-DDC laptop panel detected\n");
+ radeon_find_connector_for_mon(rinfo, MT_LCD);
+ printk(KERN_INFO "Non-DDC laptop panel detected\n");
}
- if (rinfo->mon1_type == MT_NONE)
- rinfo->mon1_type = radeon_crt_is_connected(rinfo, rinfo->reversed_DAC);
- /*
- * Probe secondary head (mostly VGA, can be DVI)
- */
-#ifdef CONFIG_PPC_OF
- if (rinfo->mon2_type == MT_NONE)
- rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1,
- &rinfo->mon2_EDID);
-#endif /* CONFIG_PPC_OF */
-#ifdef CONFIG_FB_RADEON_I2C
- if (rinfo->mon2_type == MT_NONE)
- rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_vga,
- &rinfo->mon2_EDID);
- if (rinfo->mon2_type == MT_NONE && !ddc_crt2_used)
- rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,
- &rinfo->mon2_EDID);
-#endif /* CONFIG_FB_RADEON_I2C */
- if (rinfo->mon2_type == MT_NONE)
- rinfo->mon2_type = radeon_crt_is_connected(rinfo, !rinfo->reversed_DAC);
+ /* Probe for monitors on the primary and secondary crtc heads */
+ if (PRIMARY_MONITOR(rinfo) <= MT_NONE) {
+ radeon_find_connector_for_mon(rinfo, radeon_crt_is_connected(rinfo, 1));
+ }
- /*
- * If we only detected port 2, we swap them, if none detected,
- * assume CRT (maybe fallback to old BIOS_SCRATCH stuff ? or look
- * at FP registers ?)
- */
- if (rinfo->mon1_type == MT_NONE) {
- if (rinfo->mon2_type != MT_NONE) {
- rinfo->mon1_type = rinfo->mon2_type;
- rinfo->mon1_EDID = rinfo->mon2_EDID;
- } else
- rinfo->mon1_type = MT_CRT;
- rinfo->mon2_type = MT_NONE;
- rinfo->mon2_EDID = NULL;
+ /* If we still haven't found anything, just force it to be on the CRT.. */
+ if (PRIMARY_MONITOR(rinfo) <= MT_NONE) {
+ radeon_find_connector_for_mon(rinfo, MT_CRT);
}
- /*
- * Deal with reversed TMDS
- */
- if (rinfo->reversed_TMDS) {
- /* Always keep internal TMDS as primary head */
- if (rinfo->mon1_type == MT_DFP || rinfo->mon2_type == MT_DFP) {
- int tmp_type = rinfo->mon1_type;
- u8 *tmp_EDID = rinfo->mon1_EDID;
- rinfo->mon1_type = rinfo->mon2_type;
- rinfo->mon1_EDID = rinfo->mon2_EDID;
- rinfo->mon2_type = tmp_type;
- rinfo->mon2_EDID = tmp_EDID;
- if (rinfo->mon1_type == MT_CRT || rinfo->mon2_type == MT_CRT)
- rinfo->reversed_DAC ^= 1;
- }
+ /* Always keep internal TMDS as primary head */
+ if (SECONDARY_HEAD_PRESENT(rinfo) && (SECONDARY_HEAD(rinfo).tmds_type == tmds_internal) && (SECONDARY_MONITOR(rinfo) == MT_DFP)) {
+ int head = rinfo->heads[0];
+ rinfo->heads[0] = rinfo->heads[1];
+ rinfo->heads[1] = head;
}
}
- if (ignore_edid) {
- kfree(rinfo->mon1_EDID);
- rinfo->mon1_EDID = NULL;
- kfree(rinfo->mon2_EDID);
- rinfo->mon2_EDID = NULL;
- }
+bail:
- bail:
- printk(KERN_INFO "radeonfb: Monitor 1 type %s found\n",
- radeon_get_mon_name(rinfo->mon1_type));
- if (rinfo->mon1_EDID)
- printk(KERN_INFO "radeonfb: EDID probed\n");
- if (!rinfo->has_CRTC2)
- return;
- printk(KERN_INFO "radeonfb: Monitor 2 type %s found\n",
- radeon_get_mon_name(rinfo->mon2_type));
- if (rinfo->mon2_EDID)
- printk(KERN_INFO "radeonfb: EDID probed\n");
+ /* Dump out the heads we've found so far */
+ for (i = 0; i < RADEON_MAX_CONNECTORS; i++) {
+
+ if (rinfo->connectors[i].conn_type == conn_none)
+ continue;
+ printk(KERN_INFO " * Connector %d is %s. Head %d, Monitor: %s ", i+1,
+ conn_type_name[rinfo->connectors[i].conn_type],
+ rinfo->connectors[i].head,
+ rinfo->connectors[i].mon_type == MT_UNKNOWN ?
+ "Not Probed Yet" :
+ mon_type_name[rinfo->connectors[i].mon_type]);
+ if (rinfo->connectors[i].edid) {
+ printk("EDID probed\n");
+ } else {
+ printk("\n");
+ }
+ printk(KERN_INFO " ddc port: %d, dac: %d, tmds: %d\n",
+ rinfo->connectors[i].ddc_type,
+ rinfo->connectors[i].dac_type,
+ rinfo->connectors[i].tmds_type);
+ }
}
-/*
- * This functions applyes any arch/model/machine specific fixups
- * to the panel info. It may eventually alter EDID block as
- * well or whatever is specific to a given model and not probed
- * properly by the default code
- */
-static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
-{
#ifdef CONFIG_PPC_OF
+int __devinit radeon_get_lvds_info_openfirmware(struct radeonfb_info *rinfo)
+{
+
/*
* LCD Flat panels should use fixed dividers, we enfore that on
* PPC only for now...
*/
- if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD
- && rinfo->is_mobility) {
+ If (!rinfo->panel_info.use_bios_dividers && (PRIMARY_MONITOR(rinfo) == MT_LCD) &&
+ rinfo->is_mobility) {
int ppll_div_sel;
u32 ppll_divn;
ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
@@ -667,15 +1224,16 @@
rinfo->panel_info.post_divider = (ppll_divn >> 16) & 0x7;
rinfo->panel_info.use_bios_dividers = 1;
- printk(KERN_DEBUG "radeonfb: Using Firmware dividers 0x%08x "
+ printk(KERN_INFO "Using Firmware dividers 0x%08x "
"from PPLL %d\n",
rinfo->panel_info.fbk_divider |
(rinfo->panel_info.post_divider << 16),
ppll_div_sel);
+ return 0;
}
-#endif /* CONFIG_PPC_OF */
+ return 1;
}
-
+#endif /* CONFIG_PPC_OF */
/*
* Fill up panel infos from a mode definition, either returned by the EDID
@@ -745,19 +1303,24 @@
/*
* First check out what BIOS has to say
*/
- if (rinfo->mon1_type == MT_LCD)
- radeon_get_panel_info_BIOS(rinfo);
+ if (PRIMARY_MONITOR(rinfo) == MT_LCD) {
+ if (rinfo->radeon_get_lvds_info) {
+ rinfo->radeon_get_lvds_info(rinfo);
+ // XXX Do we care about the return value?
+ }
+ }
/*
* Parse EDID detailed timings and deduce panel infos if any. Right now
* we only deal with first entry returned by parse_EDID, we may do better
* some day...
*/
- if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type != MT_CRT
- && rinfo->mon1_EDID) {
+ if (!rinfo->panel_info.use_bios_dividers &&
+ (PRIMARY_MONITOR(rinfo) != MT_CRT) &&
+ PRIMARY_HEAD(rinfo).edid) {
struct fb_var_screeninfo var;
RTRACE("Parsing EDID data for panel info\n");
- if (fb_parse_edid(rinfo->mon1_EDID, &var) == 0) {
+ if (fb_parse_edid(PRIMARY_HEAD(rinfo).edid, &var) == 0) {
if (var.xres >= rinfo->panel_info.xres &&
var.yres >= rinfo->panel_info.yres)
radeon_var_to_panel_info(rinfo, &var);
@@ -765,15 +1328,10 @@
}
/*
- * Do any additional platform/arch fixups to the panel infos
- */
- radeon_fixup_panel_info(rinfo);
-
- /*
* If we have some valid panel infos, we setup the default mode based on
* those
*/
- if (rinfo->mon1_type != MT_CRT && rinfo->panel_info.valid) {
+ if ((PRIMARY_MONITOR(rinfo) != MT_CRT) && rinfo->panel_info.valid) {
struct fb_var_screeninfo *var = &info->var;
RTRACE("Setting up default mode based on panel info\n");
@@ -804,13 +1362,13 @@
/*
* Now build modedb from EDID
*/
- if (rinfo->mon1_EDID) {
- fb_edid_to_monspecs(rinfo->mon1_EDID, &info->monspecs);
+ if (PRIMARY_HEAD(rinfo).edid) {
+ fb_edid_to_monspecs(PRIMARY_HEAD(rinfo).edid, &info->monspecs);
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len,
&info->modelist);
- rinfo->mon1_modedb = info->monspecs.modedb;
- rinfo->mon1_dbsize = info->monspecs.modedb_len;
+ PRIMARY_HEAD(rinfo).modedb = info->monspecs.modedb;
+ PRIMARY_HEAD(rinfo).modedb_size = info->monspecs.modedb_len;
}
@@ -819,7 +1377,7 @@
* we try to read it from card), we try to pick a default mode
* and create some panel infos. Whatever...
*/
- if (rinfo->mon1_type != MT_CRT && !rinfo->panel_info.valid) {
+ if ((PRIMARY_MONITOR(rinfo) != MT_CRT) && !rinfo->panel_info.valid) {
struct fb_videomode *modedb;
int dbsize;
char modename[32];
@@ -833,18 +1391,18 @@
}
if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {
printk(KERN_WARNING "radeonfb: Can't find panel size, going back to CRT\n");
- rinfo->mon1_type = MT_CRT;
+ radeon_find_connector_for_mon(rinfo, MT_CRT);
goto pickup_default;
}
printk(KERN_WARNING "radeonfb: Assuming panel size %dx%d\n",
rinfo->panel_info.xres, rinfo->panel_info.yres);
- modedb = rinfo->mon1_modedb;
- dbsize = rinfo->mon1_dbsize;
+ modedb = PRIMARY_HEAD(rinfo).modedb;
+ dbsize = PRIMARY_HEAD(rinfo).modedb_size;
snprintf(modename, 31, "%dx%d", rinfo->panel_info.xres, rinfo->panel_info.yres);
if (fb_find_mode(&info->var, info, modename,
modedb, dbsize, NULL, 8) == 0) {
printk(KERN_WARNING "radeonfb: Can't find mode for panel size, going back to CRT\n");
- rinfo->mon1_type = MT_CRT;
+ radeon_find_connector_for_mon(rinfo, MT_CRT);
goto pickup_default;
}
has_default_mode = 1;
@@ -947,14 +1505,14 @@
memcpy(dest, src, sizeof(struct fb_var_screeninfo));
/* Check if we have a modedb built from EDID */
- if (rinfo->mon1_modedb) {
- db = rinfo->mon1_modedb;
- dbsize = rinfo->mon1_dbsize;
+ if (PRIMARY_HEAD(rinfo).modedb) {
+ db = PRIMARY_HEAD(rinfo).modedb;
+ dbsize = PRIMARY_HEAD(rinfo).modedb_size;
native_db = 1;
}
/* Check if we have a scaler allowing any fancy mode */
- has_rmx = rinfo->mon1_type == MT_LCD || rinfo->mon1_type == MT_DFP;
+ has_rmx = (PRIMARY_MONITOR(rinfo) == MT_LCD) || (PRIMARY_MONITOR(rinfo) == MT_DFP);
/* If we have a scaler and are passed FB_ACTIVATE_TEST or
* FB_ACTIVATE_NOW, just do basic checking and return if the
@@ -967,7 +1525,7 @@
* 640x480-60, but I assume userland knows what it's doing here
* (though I may be proven wrong...)
*/
- if (has_rmx == 0 && rinfo->mon1_modedb)
+ if (has_rmx == 0 && PRIMARY_HEAD(rinfo).modedb)
if (fb_validate_mode((struct fb_var_screeninfo *)src, rinfo->info))
return -EINVAL;
return 0;
diff -Naur aty-2.6.17/radeonfb.h aty-2.6.17-patched/radeonfb.h
--- aty-2.6.17/radeonfb.h 2006-09-05 10:15:55.000000000 -0400
+++ aty-2.6.17-patched/radeonfb.h 2006-09-05 10:34:51.000000000 -0400
@@ -87,11 +87,50 @@
CHIP_ERRATA_PLL_DELAY = 0x00000004,
};
+/*
+ * DDC i2c ports
+ */
+enum radeon_ddc_type {
+ ddc_none = -1,
+ ddc_monid = 0,
+ ddc_dvi,
+ ddc_vga,
+ ddc_crt2,
+};
+
+/*
+ * Connector types
+ */
+enum radeon_legacy_conn_type {
+ legacy_conn_none = 0,
+ legacy_conn_proprietary,
+ legacy_conn_crt,
+ legacy_conn_dvi_i,
+ legacy_conn_dvi_d,
+ legacy_conn_ctv,
+ legacy_conn_stv,
+ legacy_conn_unsupported,
+};
+
+enum radeon_conn_type {
+ conn_none = 0,
+ conn_vga,
+ conn_dvi_i,
+ conn_dvi_d,
+ conn_dvi_a,
+ conn_stv,
+ conn_ctv,
+ conn_lvds,
+ conn_digital,
+ conn_unsupported,
+ conn_proprietary,
+};
/*
* Monitor types
*/
-enum radeon_montype {
+enum radeon_mon_type {
+ MT_UNKNOWN = -1,
MT_NONE = 0,
MT_CRT, /* CRT */
MT_LCD, /* LCD */
@@ -101,27 +140,45 @@
};
/*
- * DDC i2c ports
+ * DAC types
*/
-enum ddc_type {
- ddc_none,
- ddc_monid,
- ddc_dvi,
- ddc_vga,
- ddc_crt2,
+enum radeon_dac_type {
+ dac_unknown = -1,
+ dac_primary = 0,
+ dac_tvdac = 1,
};
/*
- * Connector types
+ * TMDS types
*/
-enum conn_type {
- conn_none,
- conn_proprietary,
- conn_crt,
- conn_DVI_I,
- conn_DVI_D,
+enum radeon_tmds_type {
+ tmds_unknown = -1,
+ tmds_internal = 0,
+ tmds_external = 1,
};
+/*
+ * Each connector gets this structure associated with it,
+ * containing infos about the connector wiring and about
+ * whatever has been detected on it
+ */
+struct radeon_connector {
+ enum radeon_conn_type conn_type;
+ enum radeon_ddc_type ddc_type;
+ enum radeon_dac_type dac_type;
+ enum radeon_tmds_type tmds_type;
+ enum radeon_mon_type mon_type;
+ u8 *edid;
+ struct fb_videomode *modedb;
+ unsigned int modedb_size;
+
+ int head;
+};
+
+/*
+ * Currently, the driver deals with at most 4 connectors
+ */
+#define RADEON_MAX_CONNECTORS 4
/*
* PLL infos
@@ -129,11 +186,19 @@
struct pll_info {
int ppll_max;
int ppll_min;
- int sclk, mclk;
+ int sclk;
+ int mclk;
int ref_div;
int ref_clk;
};
+/*
+ * TMDS PLL infos
+ */
+struct radeon_tmds_pll_info {
+ long freq;
+ u32 value;
+};
/*
* This structure contains the various registers manipulated by this
@@ -298,6 +363,20 @@
void __iomem *bios_seg;
int fp_bios_start;
+ int is_atom_bios;
+ int atom_data_start;
+
+ /* BIOS Functions */
+ int (*radeon_get_pll_info)(struct radeonfb_info *rinfo);
+ int (*radeon_get_lvds_info)(struct radeonfb_info *rinfo);
+ int (*radeon_get_conn_info)(struct radeonfb_info *rinfo);
+ int (*radeon_get_tmds_info)(struct radeonfb_info *rinfo);
+
+ /* Connector infos */
+ struct radeon_connector connectors[RADEON_MAX_CONNECTORS];
+ int heads[RADEON_MAX_CONNECTORS]; // index into connectors.
+ int num_heads; // number of heads.
+
u32 pseudo_palette[17];
struct { u8 red, green, blue, pad; }
palette[256];
@@ -316,15 +395,8 @@
int has_CRTC2;
int is_mobility;
int is_IGP;
- int reversed_DAC;
- int reversed_TMDS;
struct panel_info panel_info;
- int mon1_type;
- u8 *mon1_EDID;
- struct fb_videomode *mon1_modedb;
- int mon1_dbsize;
- int mon2_type;
- u8 *mon2_EDID;
+ struct radeon_tmds_pll_info tmds_pll[4];
u32 dp_gui_master_cntl;
@@ -356,8 +428,13 @@
};
-#define PRIMARY_MONITOR(rinfo) (rinfo->mon1_type)
+#define PRIMARY_HEAD(rinfo) (rinfo->connectors[rinfo->heads[0]])
+#define SECONDARY_HEAD(rinfo) (rinfo->connectors[rinfo->heads[1]])
+
+#define SECONDARY_HEAD_PRESENT(rinfo) (rinfo->heads[1] != -1)
+#define PRIMARY_MONITOR(rinfo) (rinfo->connectors[rinfo->heads[0]].mon_type)
+#define SECONDARY_MONITOR(rinfo) ((SECONDARY_HEAD_PRESENT(rinfo) ? (rinfo->connectors[rinfo->heads[1]].mon_type) : MT_NONE))
/*
* Debugging stuffs
@@ -596,7 +673,7 @@
/* I2C Functions */
extern void radeon_create_i2c_busses(struct radeonfb_info *rinfo);
extern void radeon_delete_i2c_busses(struct radeonfb_info *rinfo);
-extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
+extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, struct radeon_connector *conn);
/* PM Functions */
extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
@@ -625,4 +702,18 @@
extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
int reg_only);
+/* Bios functions. Fix this. */
+extern void __devinit radeon_get_conn_info(struct radeonfb_info *rinfo, int ignore_conntable);
+extern void __devinit radeon_get_tmds_info(struct radeonfb_info *rinfo);
+
+extern int __devinit radeon_get_lvds_info_atom(struct radeonfb_info *rinfo);
+extern int __devinit radeon_get_lvds_info_legacy(struct radeonfb_info *rinfo);
+extern int __devinit radeon_get_conn_info_atom(struct radeonfb_info *rinfo);
+extern int __devinit radeon_get_conn_info_legacy(struct radeonfb_info *rinfo);
+extern int __devinit radeon_get_tmds_info_legacy(struct radeonfb_info *rinfo);
+extern int __devinit radeon_get_tmds_info_atom(struct radeonfb_info *rinfo);
+#ifdef CONFIG_PPC_OF
+extern int __devinit radeon_get_lvds_info_openfirmware(struct radeonfb_info *rinfo);
+extern int __devinit radeon_get_conn_info_openfirmware(struct radeonfb_info *rinfo);
+#endif
#endif /* __RADEONFB_H__ */
[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]
[-- Attachment #2: Type: text/plain, Size: 373 bytes --]
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
[-- Attachment #3: Type: text/plain, Size: 182 bytes --]
_______________________________________________
Linux-fbdev-devel mailing list
Linux-fbdev-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* radeonfb: Add ATOM BIOS parsing v5b/v6 (rebased patch)
2006-09-05 15:37 radeonfb: Add ATOM BIOS parsing (rebased patch) Stuffed Crust
@ 2006-09-06 22:00 ` Stuffed Crust
2006-09-07 8:26 ` Michel Dänzer
2006-11-09 5:25 ` radeonfb: Add ATOM BIOS parsing v6a (rebased) Stuffed Crust
2006-11-02 5:33 ` radeonfb: Add ATOM BIOS parsing (rebased patch) Andrew Morton
1 sibling, 2 replies; 8+ messages in thread
From: Stuffed Crust @ 2006-09-06 22:00 UTC (permalink / raw)
To: linux-fbdev-devel
[-- Attachment #1.1: Type: text/plain, Size: 2109 bytes --]
Signed-Off-By: Solomon Peachy <pizza@shaftnet.org>
Below is v5b of the ATOM BIOS patch. Changes from v5:
* LVDS/DFP with attached DDC port can be queried
* LVDS/DFP won't be misdetected as CRT if a DDC port is connected.
http://www.shaftnet.org/users/pizza/radeonfb-atom-2.6.17-v5b.diff
http://www.shaftnet.org/users/pizza/radeonfb-atom-2.6.18-v5b.diff
Meanwhile, I've rolled in some other work to create v6 of the patch,
this time against 2.6.18-rc6 only:
http://www.shaftnet.org/users/pizza/radeonfb-atom-2.6.18-v6.diff
Changes from v5b:
(Note -- many of these changes were taken in part from an older patch by
Claudio Ciccan; I kept what was relevant and tossed the rest)
* Added many new radeon PCI IDs (X300/X600/X700/X800/X850)
* R4x0 series gets R300 tweaks (from Xorg)
* Cap VRAM to 128M (Not really sure why.. related to mmap bugs?)
* Add default_dynclk to builtin argument parsing.
* Expanded the register mmio size to max (64k vs former 16k)
(was there a reason why it wasn't already maxed?)
* Initialization tweaks for R300 and RS300 (from Xorg)
I'd really like to see the v6 patch (or its successors) go in to 2.6.19,
as the existing radeonfb driver simply won't work with newer radeon
cards -- to say nothing about its multihead detection quirks.
So, I encourage everyone with a radeon card to give this new driver a
whirl, especially if you have an X-series radeon board or if you were
having head detection problems with the existing driver.
Please run this with CONFIG_FB_RADEON_DEBUG on, so if something goes
wrong I can get it fixed up.
There at least one known corner case where things could go wrong
(LVDS/DFP port has an associated DDC port, but no EDID information is
available) but I'm already working on that.
See also:
http://bugzilla.kernel.org/show_bug.cgi?id=6215
Ciao,
- Solomon
--
Solomon Peachy pizza at shaftnet dot org
Melbourne, FL ^^ (mail/jabber/gtalk) ^^
Quidquid latine dictum sit, altum viditur. ICQ: 1318344
[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]
[-- Attachment #2: Type: text/plain, Size: 373 bytes --]
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
[-- Attachment #3: Type: text/plain, Size: 182 bytes --]
_______________________________________________
Linux-fbdev-devel mailing list
Linux-fbdev-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: radeonfb: Add ATOM BIOS parsing v5b/v6 (rebased patch)
2006-09-06 22:00 ` radeonfb: Add ATOM BIOS parsing v5b/v6 " Stuffed Crust
@ 2006-09-07 8:26 ` Michel Dänzer
2006-11-09 5:25 ` radeonfb: Add ATOM BIOS parsing v6a (rebased) Stuffed Crust
1 sibling, 0 replies; 8+ messages in thread
From: Michel Dänzer @ 2006-09-07 8:26 UTC (permalink / raw)
To: linux-fbdev-devel
On Wed, 2006-09-06 at 18:00 -0400, Stuffed Crust wrote:
>
> * Cap VRAM to 128M (Not really sure why.. related to mmap bugs?)
Traditionally, the CPU couldn't access more than 128M on Radeons. See
the current xf86-video-ati code for how to detect how much can really be
mapped.
--
Earthling Michel Dänzer | http://tungstengraphics.com
Libre software enthusiast | Debian, X and DRI developer
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Linux-fbdev-devel mailing list
Linux-fbdev-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: radeonfb: Add ATOM BIOS parsing (rebased patch)
2006-09-05 15:37 radeonfb: Add ATOM BIOS parsing (rebased patch) Stuffed Crust
2006-09-06 22:00 ` radeonfb: Add ATOM BIOS parsing v5b/v6 " Stuffed Crust
@ 2006-11-02 5:33 ` Andrew Morton
2006-11-06 14:17 ` Stuffed Crust
1 sibling, 1 reply; 8+ messages in thread
From: Andrew Morton @ 2006-11-02 5:33 UTC (permalink / raw)
To: linux-fbdev-devel; +Cc: Stuffed Crust
On Tue, 5 Sep 2006 11:37:13 -0400
Stuffed Crust <pizza@shaftnet.org> wrote:
> From: Stuffed Crust <pizza@shaftnet.org>
> ...
> Signed-Off-By: Solomon Peachy <pizza@shaftnet.org>
>
Problem. We've decided to not take contributions from
anonymous/pseudonymous contributors, as it weakens the intent of the
Developer's Certificate of Origin. I don't think either of those are your
real name ;) Sorry.
If you can sort that out then please ensure that future patches are
prepared in `patch -p1' form, as per
http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt. That means the
diff headers should look like:
--- a/drivers/video/aty/ati_ids.h
+++ a/drivers/video/aty/ati_ids.h
etc. Thanks.
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: radeonfb: Add ATOM BIOS parsing (rebased patch)
2006-11-02 5:33 ` radeonfb: Add ATOM BIOS parsing (rebased patch) Andrew Morton
@ 2006-11-06 14:17 ` Stuffed Crust
2006-11-06 19:04 ` Andrew Morton
0 siblings, 1 reply; 8+ messages in thread
From: Stuffed Crust @ 2006-11-06 14:17 UTC (permalink / raw)
To: linux-fbdev-devel; +Cc: Andrew Morton
[-- Attachment #1.1: Type: text/plain, Size: 3107 bytes --]
On Wed, Nov 01, 2006 at 09:33:46PM -0800, Andrew Morton wrote:
> > From: Stuffed Crust <pizza@shaftnet.org>
> > ...
> > Signed-Off-By: Solomon Peachy <pizza@shaftnet.org>
>
> Problem. We've decided to not take contributions from
> anonymous/pseudonymous contributors, as it weakens the intent of the
> Developer's Certificate of Origin. I don't think either of those are your
> real name ;) Sorry.
The former is what I've used as a handle for um, eight years or so now,
but the latter is what it says on my passport. Really.
The first hundred links (of over 30K) that googling my name link back to
me; I stopped counting after that. These links go back as far as '98
and include contributions I've made to half a dozen FOSS projects, my
Advodato user page (with its trust metrics), DaveM telling me off a
couple of times on lkml, my employer (AbsoluteValue Systems of
linux-wlan[-ng] "fame"), and my alma matter (Georgia Tech).
If you finger me I even have full contact information published,
complete with the phone number of my employer (although Google will
provide that too).
I realize that none of this technically establishes *my* identity, but I
think the only mutual aquaintance I've met in person is Jean Torrilhes,
and he didn't check my ID either. :)
So. Probably the most expedient manner of establishing I am who google
and I say I am is by calling my employer at +1(321)259-0737, ask my boss
(Mark Mathews) about my credentials, then you can then put me on the
line to establish I know about this conversation. Or I/we can call you.
I could fax you a copy of my ID or something, but that would only tell
you that I may have l33t photoshop skillz... :) I'm also not in the
local phone book (I ditched the land line two years ago) so you can't go
that route.
(Gee, remote identity verification is a difficult problem, isn't it? :)
> If you can sort that out then please ensure that future patches are
> prepared in `patch -p1' form, as per
I did it the way I did to avoid diffing two complete kernel trees (the
editor was running on a much slower machine than the test boxes.. the
extensive reboot-required nature of fbdev development is not condusive
to editor state)
The current version of the patch (v6a) is linked to kernel bugzilla
#6215, but it doesn't have the "correct" format either, but that's a
trivial thing to fix.
Is there anything else you'd like me to do to this patch before you
take it into -mm? I can break it down a little bit, but unfortunately
the bulk of it is fairly atomic (no pun intended) and nearly all of the
changes would need to be applied at once, broken down or not.
I also don't know if this patch will apply to (or work on) 2.6.19-rc,
but that should be a straightforward merge. I'm assuming you'd like me
to sort that out too.
Cheers,
- Solomon (really)
--
Solomon Peachy pizza at shaftnet dot org
Melbourne, FL ^^ (mail/jabber/gtalk) ^^
Quidquid latine dictum sit, altum viditur. ICQ: 1318344
[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]
[-- Attachment #2: Type: text/plain, Size: 373 bytes --]
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
[-- Attachment #3: Type: text/plain, Size: 182 bytes --]
_______________________________________________
Linux-fbdev-devel mailing list
Linux-fbdev-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: radeonfb: Add ATOM BIOS parsing (rebased patch)
2006-11-06 14:17 ` Stuffed Crust
@ 2006-11-06 19:04 ` Andrew Morton
0 siblings, 0 replies; 8+ messages in thread
From: Andrew Morton @ 2006-11-06 19:04 UTC (permalink / raw)
To: Stuffed Crust; +Cc: linux-fbdev-devel
On Mon, 6 Nov 2006 09:17:19 -0500
Stuffed Crust <pizza@shaftnet.org> wrote:
> On Wed, Nov 01, 2006 at 09:33:46PM -0800, Andrew Morton wrote:
> > > From: Stuffed Crust <pizza@shaftnet.org>
> > > ...
> > > Signed-Off-By: Solomon Peachy <pizza@shaftnet.org>
> >
> > Problem. We've decided to not take contributions from
> > anonymous/pseudonymous contributors, as it weakens the intent of the
> > Developer's Certificate of Origin. I don't think either of those are your
> > real name ;) Sorry.
>
> The former is what I've used as a handle for um, eight years or so now,
> but the latter is what it says on my passport. Really.
Oh, OK. Sorry, I thought it was a pseudonym ;)
> The current version of the patch (v6a) is linked to kernel bugzilla
> #6215, but it doesn't have the "correct" format either, but that's a
> trivial thing to fix.
>
yup, please prepare a new patch, send it over.
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
^ permalink raw reply [flat|nested] 8+ messages in thread
* radeonfb: Add ATOM BIOS parsing v6a (rebased)
2006-09-06 22:00 ` radeonfb: Add ATOM BIOS parsing v5b/v6 " Stuffed Crust
2006-09-07 8:26 ` Michel Dänzer
@ 2006-11-09 5:25 ` Stuffed Crust
2006-11-26 16:46 ` Luca Tettamanti
1 sibling, 1 reply; 8+ messages in thread
From: Stuffed Crust @ 2006-11-09 5:25 UTC (permalink / raw)
To: linux-fbdev-devel
[-- Attachment #1.1: Type: text/plain, Size: 805 bytes --]
For those of you who are still tracking this, I've rebased my ATOM BIOS
patch against 2.6.19-rc5:
http://www.shaftnet.org/users/pizza/radeonfb-atom-2.6.18-v6a.diff
http://www.shaftnet.org/users/pizza/radeonfb-atom-2.6.19-v6a.diff
There are no (intentional) functional changes between the two, although
2.6.19 re-did the edid probing to use generic calls, so it may behave
differently.
Feedback welcome, especially if you were having problems with radeonfb
mis-detecting your monitor(s).
See also:
http://bugzilla.kernel.org/show_bug.cgi?id=6215
Ciao,
- Solomon
--
Solomon Peachy pizza at shaftnet dot org
Melbourne, FL ^^ (mail/jabber/gtalk) ^^
Quidquid latine dictum sit, altum viditur. ICQ: 1318344
[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]
[-- Attachment #2: Type: text/plain, Size: 373 bytes --]
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
[-- Attachment #3: Type: text/plain, Size: 182 bytes --]
_______________________________________________
Linux-fbdev-devel mailing list
Linux-fbdev-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: radeonfb: Add ATOM BIOS parsing v6a (rebased)
2006-11-09 5:25 ` radeonfb: Add ATOM BIOS parsing v6a (rebased) Stuffed Crust
@ 2006-11-26 16:46 ` Luca Tettamanti
0 siblings, 0 replies; 8+ messages in thread
From: Luca Tettamanti @ 2006-11-26 16:46 UTC (permalink / raw)
To: linux-fbdev-devel; +Cc: pizza
Il Thu, Nov 09, 2006 at 12:25:24AM -0500, Stuffed Crust ha scritto:
> For those of you who are still tracking this, I've rebased my ATOM BIOS
> patch against 2.6.19-rc5:
>
> http://www.shaftnet.org/users/pizza/radeonfb-atom-2.6.18-v6a.diff
> http://www.shaftnet.org/users/pizza/radeonfb-atom-2.6.19-v6a.diff
>
> There are no (intentional) functional changes between the two, although
> 2.6.19 re-did the edid probing to use generic calls, so it may behave
> differently.
Hello,
I was testing your patch radeonfb-atom-2.6.19-v6a.diff on my new radeon X850.
I get a NULL pointer dereference in fb_ddc_read (during connector probe):
radeonfb_pci_register BEGIN
ACPI: PCI Interrupt 0000:01:00.0[A] -> GSI 16 (level, low) -> IRQ 16
radeonfb (0000:01:00.0): Found 131072k of DDR 256 bits wide videoram
radeonfb (0000:01:00.0): mapped 16384k videoram
radeonfb: Found Intel x86 BIOS ROM Image
Retrieved PLL infos from ATOM BIOS
radeonfb: Reference=27.00 MHz (RefDiv=12) Memory=540.00 Mhz, System=520.00 MHz
PLL min 20000 max 50000
TMDS PLL from BIOS: 16500 b011c
index 3 port 2 conn 2 dac -1 ddc 0 tmds 0
index 4 port 2 conn 2 dac 1 ddc 0 tmds -1
index 7 port 1 conn 2 dac -1 ddc 1 tmds 1
Starting monitor auto detection...
radeonfb: I2C (port 0) ... found CRT display
radeonfb: I2C (port 0) ... found CRT display
i2c_adapter i2c-2: unable to read EDID block.
i2c_adapter i2c-2: unable to read EDID block.
i2c_adapter i2c-2: unable to read EDID block.
radeonfb: I2C (port 1) ... not found
BUG: unable to handle kernel NULL pointer dereference at virtual address 00000000
printing eip:
f0d44013
*pde = 00000000
Oops: 0000 [#1]
PREEMPT SMP
Modules linked in: radeonfb(F) fb_ddc cfbcopyarea cfbimgblt cfbfillrect binfmt_misc nfs button ac battery cls_u32 cls_route sch_sfq sch_cbq nfsd exportfs lockd sunrpc vfat fat ntfs nls_base hwmon_vid hwmon i2c_isa ipv6 snd_hda_intel snd_hda_codec snd_pcm_oss snd_mixer_oss snd_pcm snd_timer ohci1394 snd parport_pc parport ieee1394 e100 mii uhci_hcd ehci_hcd intel_agp agpgart usbcore i2c_i801 rtc soundcore snd_page_alloc thermal processor fan pata_ali reiserfs xfs
CPU: 1
EIP: 0060:[<f0d44013>] Tainted: GF VLI
EFLAGS: 00010282 (2.6.19-rc6-g1abbfb41 #2)
EIP is at fb_ddc_read+0x13/0x1d8 [fb_ddc]
eax: e9ba6938 ebx: 00000000 ecx: 00000001 edx: 00000001
esi: e9ba6240 edi: 00000000 ebp: e9ba6938 esp: e2ab6e40
ds: 007b es: 007b ss: 0068
Process modprobe (pid: 15297, ti=e2ab6000 task=ef2a8070 task.ti=e2ab6000)
Stack: f0d4420d b0326128 e9ba7370 00000003 00000050 00000001 e2ab6e6b e9ba6610
e9ba6240 00000000 00000002 e9ba6634 e9ba6240 0000006c 00000003 f0db693d
f0db7f92 00000001 e9ba6240 e9ba6634 0000006c f0db4f90 f0db7c5e 00000008
Call Trace:
[<f0db693d>] radeon_probe_i2c_connector+0x63/0x152 [radeonfb]
[<f0db4f90>] radeon_probe_screens+0x2ca/0x7b4 [radeonfb]
[<f0da859a>] radeonfb_pci_register+0x886/0xe09 [radeonfb]
[<b01d1d51>] pci_device_probe+0x36/0x57
[<b02350d3>] really_probe+0x39/0xda
[<b02352fb>] __driver_attach+0x69/0xa1
[<b02347ec>] bus_for_each_dev+0x36/0x58
[<b0234ff3>] driver_attach+0x16/0x18
[<b0234ac0>] bus_add_driver+0x61/0x165
[<b01d1eb6>] __pci_register_driver+0x6e/0x88
[<b013e0a9>] sys_init_module+0x98/0x1db
[<b0102f73>] syscall_call+0x7/0xb
DWARF2 unwinder stuck at syscall_call+0x7/0xb
Leftover inexact backtrace:
=======================
Code: <8b> 03 ff 53 08 31 d2 8b 03 ff 53 08 c7 44 24 0c 00 00 00 00 31 d2 8b 03 31 f6 ff 53 04 b8 0d 00
EIP: [<f0d44013>] fb_ddc_read+0x13/0x1d8 [fb_ddc] SS:ESP 0068:e2ab6e40
I've added some debug printk and it it turned out that algo_data is NULL:
radeonfb_pci_register BEGIN
ACPI: PCI Interrupt 0000:01:00.0[A] -> GSI 16 (level, low) -> IRQ 16
radeonfb (0000:01:00.0): Found 131072k of DDR 256 bits wide videoram
radeonfb (0000:01:00.0): mapped 16384k videoram
radeonfb: Found Intel x86 BIOS ROM Image
Retrieved PLL infos from ATOM BIOS
radeonfb: Reference=27.00 MHz (RefDiv=12) Memory=540.00 Mhz, System=520.00 MHz
PLL min 20000 max 50000
TMDS PLL from BIOS: 16500 b011c
index 3 port 2 conn 2 dac -1 ddc 0 tmds 0
index 4 port 2 conn 2 dac 1 ddc 0 tmds -1
index 7 port 1 conn 2 dac -1 ddc 1 tmds 1
Starting monitor auto detection...
radeonfb: I2C (port 0) ... found CRT display
radeonfb: I2C (port 0) ... found CRT display
i2c_adapter i2c-2: unable to read EDID block.
i2c_adapter i2c-2: unable to read EDID block.
i2c_adapter i2c-2: unable to read EDID block.
radeonfb: I2C (port 1) ... not found
algo_data is NULL
radeonfb: I2C (port -1) ... not found
* Connector 1 is DVI-I. Head 0, Monitor: CRT (EDID probed)
ddc port: 0, dac: 1, tmds: -1
* Connector 2 is DVI-I. Head 1, Monitor: CRT (EDID probed)
ddc port: 0, dac: -1, tmds: 0
* Connector 3 is DVI-I. Head -1, Monitor: None
ddc port: 1, dac: -1, tmds: 1
hStart = 1048, hEnd = 1184, hTotal = 1344
vStart = 771, vEnd = 777, vTotal = 806
h_total_disp = 0x7f00a7 hsync_strt_wid = 0x910422
v_total_disp = 0x2ff0325 vsync_strt_wid = 0x860302
pixclock = 15384
freq = 6500
freq = 6500, PLL min = 20000, PLL max = 50000
ref_div = 12, ref_clk = 2700, output_freq = 26000
ref_div = 12, ref_clk = 2700, output_freq = 26000
post div = 0x2
fb_div = 0x74
ppll_div_3 = 0x20074
Console: switching to colour frame buffer device 128x48
radeonfb (0000:01:00.0): ATI Radeon ]R
radeonfb_pci_register END
For reference, I've added this code to fb_ddc_read:
if (!algo_data) {
printk(KERN_WARNING "algo_data is NULL\n");
return NULL;
}
radeonfb then works fine. The only strange thing is that it thinks that I have
two CRTs. I also have two edid files (with identical content of course).
The card has 2 DVI connectors and I'm using a VGA LCD (using DVI->VGA adapter).
The card is CrossFire capable but there's only one card in the system.
Xorg says:
(II) RADEON(0): I2C bus "DDC" initialized.
(II) RADEON(0): ATOM BIOS detected
(II) RADEON(0): Port0: DDCType-1, DACType-1, TMDSType-0, ConnectorType-2
(II) RADEON(0): Port1: DDCType-2, DACType--1, TMDSType-1, ConnectorType-2
(II) RADEON(0): I2C device "DDC:ddc2" registered at address 0xA0.
(II) RADEON(0): I2C device "DDC:ddc2" removed.
(II) RADEON(0): DDC Type: 1, Detected Type: 1
(II) RADEON(0): I2C device "DDC:ddc2" registered at address 0xA0.
(II) RADEON(0): I2C device "DDC:ddc2" removed.
(II) RADEON(0): I2C device "DDC:ddc2" registered at address 0xA0.
(II) RADEON(0): I2C device "DDC:ddc2" removed.
(II) RADEON(0): I2C device "DDC:ddc2" registered at address 0xA0.
(II) RADEON(0): I2C device "DDC:ddc2" removed.
(II) RADEON(0): DDC Type: 2, Detected Type: 0
[skip]
(II) RADEON(0): Primary:
Monitor -- CRT
Connector -- DVI-I
DAC Type -- TVDAC/ExtDAC
TMDS Type -- Internal
DDC Type -- MONID
(II) RADEON(0): Secondary:
Monitor -- NONE
Connector -- DVI-I
DAC Type -- Unknown
TMDS Type -- External
DDC Type -- DVI_DDC
Luca
--
Io mi ricordo sempre il compleanno della mia ragazza:
cade il giorno dopo di quando lei me lo ricorda
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-11-26 15:46 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-05 15:37 radeonfb: Add ATOM BIOS parsing (rebased patch) Stuffed Crust
2006-09-06 22:00 ` radeonfb: Add ATOM BIOS parsing v5b/v6 " Stuffed Crust
2006-09-07 8:26 ` Michel Dänzer
2006-11-09 5:25 ` radeonfb: Add ATOM BIOS parsing v6a (rebased) Stuffed Crust
2006-11-26 16:46 ` Luca Tettamanti
2006-11-02 5:33 ` radeonfb: Add ATOM BIOS parsing (rebased patch) Andrew Morton
2006-11-06 14:17 ` Stuffed Crust
2006-11-06 19:04 ` Andrew Morton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).