Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 107350 Details for
Bug 162628
gentoo-sources - include radeonfb patch for new radeon mobility cards (ie. x700) into genpatches
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
The patch itself
radeonfb-atom-2.6.18-v6a.diff (text/plain), 84.82 KB, created by
Anssi
on 2007-01-18 09:21:55 UTC
(
hide
)
Description:
The patch itself
Filename:
MIME Type:
Creator:
Anssi
Created:
2007-01-18 09:21:55 UTC
Size:
84.82 KB
patch
obsolete
>diff -Naur aty-2.6.18/ati_ids.h aty-2.6.18-patched/ati_ids.h >--- aty-2.6.18/ati_ids.h 2006-09-05 16:42:31.000000000 -0400 >+++ aty-2.6.18-patched/ati_ids.h 2006-09-05 16:58:55.000000000 -0400 >@@ -31,6 +31,7 @@ > #define PCI_CHIP_RV360_AR 0x4152 > #define PCI_CHIP_RV350_AS 0x4153 > #define PCI_CHIP_RV350_AT 0x4154 >+#define PCI_CHIP_RV350_AU 0x4155 > #define PCI_CHIP_RV350_AV 0x4156 > #define PCI_CHIP_MACH32 0x4158 > #define PCI_CHIP_RS250_4237 0x4237 >@@ -71,7 +72,13 @@ > #define PCI_CHIP_R420_JL 0x4A4C > #define PCI_CHIP_R420_JM 0x4A4D > #define PCI_CHIP_R420_JN 0x4A4E >+#define PCI_CHIP_R420_JO 0x4A4F > #define PCI_CHIP_R420_JP 0x4A50 >+#define PCI_CHIP_R420_JT 0x4A54 >+#define PCI_CHIP_R480_KI 0x4B49 >+#define PCI_CHIP_R480_KJ 0x4B4A >+#define PCI_CHIP_R480_KK 0x4B4B >+#define PCI_CHIP_R480_KL 0x4B4C > #define PCI_CHIP_MACH64LB 0x4C42 > #define PCI_CHIP_MACH64LD 0x4C44 > #define PCI_CHIP_RAGE128LE 0x4C45 >@@ -182,9 +189,19 @@ > #define PCI_CHIP_R423_UI 0x5549 > #define PCI_CHIP_R423_UJ 0x554A > #define PCI_CHIP_R423_UK 0x554B >+#define PCI_CHIP_R423_UL 0x554C >+#define PCI_CHIP_R423_UM 0x554D >+#define PCI_CHIP_R423_UN 0x554E >+#define PCI_CHIP_R423_UO 0x554F >+#define PCI_CHIP_R423_UP 0x5550 > #define PCI_CHIP_R423_UQ 0x5551 > #define PCI_CHIP_R423_UR 0x5552 > #define PCI_CHIP_R423_UT 0x5554 >+#define PCI_CHIP_RV410_VJ 0x564A >+#define PCI_CHIP_RV410_VK 0x564B >+#define PCI_CHIP_RV410_VO 0x564F >+#define PCI_CHIP_RV410_VR 0x5652 >+#define PCI_CHIP_RV410_VS 0x5653 > #define PCI_CHIP_MACH64VT 0x5654 > #define PCI_CHIP_MACH64VU 0x5655 > #define PCI_CHIP_MACH64VV 0x5656 >@@ -206,7 +223,22 @@ > #define PCI_CHIP_RV280_5964 0x5964 > #define PCI_CHIP_RV280_5C61 0x5C61 > #define PCI_CHIP_RV280_5C63 0x5C63 >+#define PCI_CHIP_R423_5D48 0x5D48 >+#define PCI_CHIP_R423_5D49 0x5D49 >+#define PCI_CHIP_R423_5D4A 0x5D4A >+#define PCI_CHIP_R480_5D4C 0x5D4C >+#define PCI_CHIP_R480_5D4D 0x5D4D >+#define PCI_CHIP_R480_5D4E 0x5D4E >+#define PCI_CHIP_R480_5D4F 0x5D4F >+#define PCI_CHIP_R480_5D50 0x5D50 >+#define PCI_CHIP_R480_5D52 0x5D52 > #define PCI_CHIP_R423_5D57 0x5D57 >+#define PCI_CHIP_RV410_5E48 0x5E48 >+#define PCI_CHIP_RV410_5E4A 0x5E4A >+#define PCI_CHIP_RV410_5E4B 0x5E4B >+#define PCI_CHIP_RV410_5E4C 0x5E4C >+#define PCI_CHIP_RV410_5E4D 0x5E4D >+#define PCI_CHIP_RV410_5E4F 0x5E4F > #define PCI_CHIP_RS350_7834 0x7834 > #define PCI_CHIP_RS350_7835 0x7835 > >diff -Naur aty-2.6.18/radeon_accel.c aty-2.6.18-patched/radeon_accel.c >--- aty-2.6.18/radeon_accel.c 2006-09-05 16:42:31.000000000 -0400 >+++ aty-2.6.18-patched/radeon_accel.c 2006-09-06 10:04:39.000000000 -0400 >@@ -203,9 +203,7 @@ > host_path_cntl = INREG(HOST_PATH_CNTL); > rbbm_soft_reset = INREG(RBBM_SOFT_RESET); > >- if (rinfo->family == CHIP_FAMILY_R300 || >- rinfo->family == CHIP_FAMILY_R350 || >- rinfo->family == CHIP_FAMILY_RV350) { >+ if (IS_R300_VARIANT(rinfo)) { > u32 tmp; > > OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | >@@ -241,9 +239,7 @@ > INREG(HOST_PATH_CNTL); > OUTREG(HOST_PATH_CNTL, host_path_cntl); > >- if (rinfo->family != CHIP_FAMILY_R300 || >- rinfo->family != CHIP_FAMILY_R350 || >- rinfo->family != CHIP_FAMILY_RV350) >+ if (IS_R300_VARIANT(rinfo)) > OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); > > OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); >@@ -254,16 +250,15 @@ > { > unsigned long temp; > >- /* disable 3D engine */ >- OUTREG(RB3D_CNTL, 0); >- > radeonfb_engine_reset(rinfo); > > radeon_fifo_wait (1); >- if ((rinfo->family != CHIP_FAMILY_R300) && >- (rinfo->family != CHIP_FAMILY_R350) && >- (rinfo->family != CHIP_FAMILY_RV350)) >+ if (IS_R300_VARIANT(rinfo)) { >+ temp = INREG(RB2D_DSTCACHE_MODE); >+ OUTREG(RB2D_DSTCACHE_MODE, temp | (1<<17)); /* FIXME */ >+ } else { > OUTREG(RB2D_DSTCACHE_MODE, 0); >+ } > > radeon_fifo_wait (3); > /* We re-read MC_FB_LOCATION from card as it can have been >diff -Naur aty-2.6.18/radeon_backlight.c aty-2.6.18-patched/radeon_backlight.c >--- aty-2.6.18/radeon_backlight.c 2006-09-05 16:42:31.000000000 -0400 >+++ aty-2.6.18-patched/radeon_backlight.c 2006-09-05 16:47:03.000000000 -0400 >@@ -58,7 +58,7 @@ > u32 lvds_gen_cntl, tmpPixclksCntl; > int level; > >- if (rinfo->mon1_type != MT_LCD) >+ if (PRIMARY_MONITOR(rinfo) != MT_LCD) > return 0; > > /* We turn off the LCD completely instead of just dimming the >@@ -146,7 +146,7 @@ > struct radeon_bl_privdata *pdata; > char name[12]; > >- if (rinfo->mon1_type != MT_LCD) >+ if (PRIMARY_MONITOR(rinfo) == MT_LCD) { > return; > > #ifdef CONFIG_PMAC_BACKLIGHT >diff -Naur aty-2.6.18/radeon_base.c aty-2.6.18-patched/radeon_base.c >--- aty-2.6.18/radeon_base.c 2006-09-05 16:42:31.000000000 -0400 >+++ aty-2.6.18-patched/radeon_base.c 2006-09-15 12:41:57.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/module.h> > #include <linux/moduleparam.h> >@@ -180,6 +181,7 @@ > CHIP_DEF(PCI_CHIP_RV360_AR, RV350, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_RV350_AS, RV350, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_RV350_AT, RV350, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_RV350_AU, RV350, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_RV350_AV, RV350, CHIP_HAS_CRTC2), > /* 9800/Pro/FileGL X2 */ > CHIP_DEF(PCI_CHIP_R350_AH, R350, CHIP_HAS_CRTC2), >@@ -190,7 +192,7 @@ > CHIP_DEF(PCI_CHIP_R350_NI, R350, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R360_NJ, R350, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R350_NK, R350, CHIP_HAS_CRTC2), >- /* Newer stuff */ >+ /* X300/X600 */ > CHIP_DEF(PCI_CHIP_RV380_3E50, RV380, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_RV380_3E54, RV380, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_RV380_3150, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >@@ -201,6 +203,19 @@ > CHIP_DEF(PCI_CHIP_RV370_5B65, RV380, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_RV370_5460, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), > CHIP_DEF(PCI_CHIP_RV370_5464, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ /* X700 */ >+ CHIP_DEF(PCI_CHIP_RV410_VJ, RV410, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ CHIP_DEF(PCI_CHIP_RV410_VK, RV410, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ CHIP_DEF(PCI_CHIP_RV410_VO, RV410, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ CHIP_DEF(PCI_CHIP_RV410_VR, RV410, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ CHIP_DEF(PCI_CHIP_RV410_VS, RV410, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ CHIP_DEF(PCI_CHIP_RV410_5E48, RV410, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_RV410_5E4A, RV410, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_RV410_5E4B, RV410, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_RV410_5E4C, RV410, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_RV410_5E4D, RV410, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_RV410_5E4F, RV410, CHIP_HAS_CRTC2), >+ /* X800/X850 */ > CHIP_DEF(PCI_CHIP_R420_JH, R420, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R420_JI, R420, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R420_JJ, R420, CHIP_HAS_CRTC2), >@@ -208,7 +223,9 @@ > 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_R420_JO, R420, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R420_JP, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R420_JT, R420, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R423_UH, R420, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R423_UI, R420, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R423_UJ, R420, CHIP_HAS_CRTC2), >@@ -217,6 +234,24 @@ > CHIP_DEF(PCI_CHIP_R423_UR, R420, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R423_UT, R420, CHIP_HAS_CRTC2), > CHIP_DEF(PCI_CHIP_R423_5D57, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R423_UP, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R423_5D49, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ CHIP_DEF(PCI_CHIP_R423_5D4A, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ CHIP_DEF(PCI_CHIP_R423_5D48, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), >+ CHIP_DEF(PCI_CHIP_R423_UO, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R423_UM, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R423_UN, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R423_UL, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_5D4C, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_5D50, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_5D4E, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_5D4F, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_5D52, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_5D4D, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_KJ, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_KK, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_KI, R420, CHIP_HAS_CRTC2), >+ CHIP_DEF(PCI_CHIP_R480_KL, R420, CHIP_HAS_CRTC2), > /* Original Radeon/7200 */ > CHIP_DEF(PCI_CHIP_RADEON_QD, RADEON, 0), > CHIP_DEF(PCI_CHIP_RADEON_QE, RADEON, 0), >@@ -259,6 +294,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; >@@ -269,6 +305,12 @@ > static int force_sleep; > static int ignore_devlist; > >+#ifdef CONFIG_FB_RADEON_DEBUG >+int radeonfb_debug = 1; >+#else >+int radeonfb_debug = 0; >+#endif >+ > /* > * prototypes > */ >@@ -324,7 +366,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 { >@@ -410,7 +452,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; >@@ -433,6 +475,7 @@ > if (val && *val) > rinfo->pll.mclk = (*val) / 10; > >+ RTRACE("Retrieved PLL infos from Open Firmware\n"); > return 0; > } > #endif /* CONFIG_PPC_OF */ >@@ -575,10 +618,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); >+ >+ RTRACE("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); >+ >+ RTRACE("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 >@@ -630,46 +751,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 we have a way to retrieve the PLL information, do so. > */ >- 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 (!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) { >@@ -683,6 +788,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 >@@ -698,7 +819,7 @@ > rinfo->pll.ref_div, > rinfo->pll.mclk / 100, rinfo->pll.mclk % 100, > rinfo->pll.sclk / 100, rinfo->pll.sclk % 100); >- printk("radeonfb: PLL min %d max %d\n", rinfo->pll.ppll_min, rinfo->pll.ppll_max); >+ RTRACE("PLL min %d max %d\n", rinfo->pll.ppll_min, rinfo->pll.ppll_max); > } > > static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info) >@@ -839,7 +960,7 @@ > if (rinfo->asleep) > return 0; > >- radeon_fifo_wait(2); >+ radeon_engine_idle(); > OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) > * var->bits_per_pixel / 8) & ~7); > return 0; >@@ -923,6 +1044,7 @@ > u32 val; > u32 tmp_pix_clks; > int unblank = 0; >+ int i; > > if (rinfo->lock_blank) > return 0; >@@ -952,78 +1074,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 */ >@@ -1274,10 +1398,7 @@ > radeon_pll_errata_after_data(rinfo); > > /* Set PPLL ref. div */ >- if (rinfo->family == CHIP_FAMILY_R300 || >- rinfo->family == CHIP_FAMILY_RS300 || >- rinfo->family == CHIP_FAMILY_R350 || >- rinfo->family == CHIP_FAMILY_RV350) { >+ if (IS_R300_VARIANT(rinfo) || (rinfo->family == CHIP_FAMILY_RS300)) { > if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { > /* When restoring console mode, use saved PPLL_REF_DIV > * setting. >@@ -1374,6 +1495,7 @@ > OUTREG(CRTC_OFFSET_CNTL, 0); > OUTREG(CRTC_PITCH, mode->crtc_pitch); > OUTREG(SURFACE_CNTL, mode->surface_cntl); >+ OUTREG(DISP_MERGE_CNTL, 0xffff0000); > > radeon_write_pll_regs(rinfo, mode); > >@@ -1884,7 +2006,7 @@ > info->fix.ywrapstep = 0; > info->fix.type_aux = 0; > info->fix.mmio_start = rinfo->mmio_base_phys; >- info->fix.mmio_len = RADEON_REGSIZE; >+ info->fix.mmio_len = pci_resource_len(rinfo->pdev, 2); > info->fix.accel = FB_ACCEL_ATI_RADEON; > > fb_alloc_cmap(&info->cmap, 256, 0); >@@ -1988,9 +2110,7 @@ > u32 tmp; > > /* framebuffer size */ >- if ((rinfo->family == CHIP_FAMILY_RS100) || >- (rinfo->family == CHIP_FAMILY_RS200) || >- (rinfo->family == CHIP_FAMILY_RS300)) { >+ if (rinfo->is_IGP) { > u32 tom = INREG(NB_TOM); > tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); > >@@ -2018,6 +2138,10 @@ > /* mem size is bits [28:0], mask off the rest */ > rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; > >+ /* Limit memory to 128 megs for now */ >+ if (rinfo->video_ram > MAX_VRAM) >+ rinfo->video_ram = MAX_VRAM; >+ > /* > * Hack to get around some busted production M6's > * reporting no ram >@@ -2102,7 +2226,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); > } > > >@@ -2113,7 +2237,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 = { >@@ -2136,6 +2280,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) >@@ -2143,6 +2306,7 @@ > struct fb_info *info; > struct radeonfb_info *rinfo; > int ret; >+ int i; > > RTRACE("radeonfb_pci_register BEGIN\n"); > >@@ -2199,7 +2363,8 @@ > } > > /* map the regions */ >- rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE); >+ rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, >+ pci_resource_len(rinfo->pdev, 2)); > if (!rinfo->mmio_base) { > printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n", > pci_name(rinfo->pdev)); >@@ -2284,6 +2449,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); >@@ -2295,14 +2461,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); > >@@ -2313,10 +2488,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 >@@ -2361,10 +2541,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); >@@ -2389,18 +2571,24 @@ > { > struct fb_info *info = pci_get_drvdata(pdev); > struct radeonfb_info *rinfo = info->par; >- >+ >+ int i; >+ > if (!rinfo) > return; > > radeonfb_bl_exit(rinfo); > 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 > * >@@ -2426,10 +2614,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 >@@ -2479,12 +2668,18 @@ > 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 if (!strncmp( this_opt, "default_dynclk:", 15)) { >+ default_dynclk = simple_strtoul((this_opt+15), NULL, 10); > #if defined(CONFIG_PM) && defined(CONFIG_X86) > } else if (!strncmp(this_opt, "force_sleep", 11)) { > force_sleep = 1; > } else if (!strncmp(this_opt, "ignore_devlist", 14)) { > ignore_devlist = 1; > #endif >+ } else if (!strncmp(this_opt, "debug", 5)) { >+ radeonfb_debug = 1; > } else > mode_option = this_opt; > } >@@ -2528,6 +2723,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); >@@ -2546,3 +2743,5 @@ > module_param(ignore_devlist, bool, 0); > MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops"); > #endif >+module_param(radeonfb_debug, int, 0); >+MODULE_PARM_DESC(radeonfb_debug, "Enable full debugging text"); >diff -Naur aty-2.6.18/radeon_i2c.c aty-2.6.18-patched/radeon_i2c.c >--- aty-2.6.18/radeon_i2c.c 2006-09-05 16:42:31.000000000 -0400 >+++ aty-2.6.18-patched/radeon_i2c.c 2006-09-19 19:57:51.000000000 -0400 >@@ -169,13 +169,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|LVDS_EN))) { >+ 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)); > >@@ -211,7 +225,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)); >@@ -235,30 +249,43 @@ > 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; >+ // what about the special case where we are a DFP/LVDS, but have a DDC connection.. >+ // but no EDID? We should fall back to MT_LCD...? XXXX >+ 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[EDID_STRUCT_DISPLAY] & 0x80) && (conn->ddc_type == ddc_dvi)) { >+ RTRACE("radeonfb: I2C (port %d) ... found TMDS panel\n", conn->ddc_type); >+ mon_type = MT_DFP; >+ goto done; >+ } >+ >+ if (rinfo->is_mobility && >+ (conn->conn_type == conn_lvds) && >+ (edid[EDID_STRUCT_DISPLAY] & 0x80) && // ie EDID valid and marks us as a DFP... >+ (INREG(LVDS_GEN_CNTL) & (LVDS_ON|LVDS_EN))) { >+ RTRACE("radeonfb: I2C (port %d) ... found LVDS panel\n", conn->ddc_type); >+ mon_type = MT_LCD; >+ 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.18/radeon_monitor.c aty-2.6.18-patched/radeon_monitor.c >--- aty-2.6.18/radeon_monitor.c 2006-09-05 16:42:31.000000000 -0400 >+++ aty-2.6.18-patched/radeon_monitor.c 2006-09-19 19:56:49.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) { >+ RTRACE("No LVDS panel info in ATOM 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"); >+ RTRACE("No LVDS panel info in Legacy 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); >+ RTRACE("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)); >+ RTRACE("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,104 @@ > > 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); >+ /* 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 (rinfo->mon1_type == MT_NONE) >- rinfo->mon1_type = MT_CRT; >+ if (PRIMARY_MONITOR(rinfo) <= MT_NONE) { >+ radeon_find_connector_for_mon(rinfo, 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 heads */ >+#ifdef CONFIG_FB_RADEON_I2C >+ /* 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 */ > >- /* >- * 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 */ >-#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; >+ /* Mobility chips usually have LCDs... */ >+ if ((PRIMARY_MONITOR(rinfo) <= MT_NONE) && >+ rinfo->is_mobility && >+ ((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4)) || >+ (INREG(LVDS_GEN_CNTL) & (LVDS_EN|LVDS_ON)))) { >+ printk(KERN_INFO "radeonfb: Non-DDC laptop panel detected\n"); >+ radeon_find_connector_for_mon(rinfo, MT_LCD); >+ if (rinfo->radeon_get_lvds_info) { >+ rinfo->radeon_get_lvds_info(rinfo); >+ } > } >-#endif /* CONFIG_FB_RADEON_I2C */ >- if (rinfo->mon1_type == 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"); >+ >+ /* 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 (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); >+ /* 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); >+ } > >- /* >- * 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; >+ /* 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; > } >+ } >+bail: > >- /* >- * 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; >- } >+ /* 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); > } >- if (ignore_edid) { >- kfree(rinfo->mon1_EDID); >- rinfo->mon1_EDID = NULL; >- kfree(rinfo->mon2_EDID); >- rinfo->mon2_EDID = NULL; >- } >- >- 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"); > } > > >-/* >- * 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 +1228,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 >@@ -742,22 +1304,35 @@ > info->var = radeonfb_default_var; > INIT_LIST_HEAD(&info->modelist); > >- /* >- * First check out what BIOS has to say >- */ >- if (rinfo->mon1_type == MT_LCD) >- radeon_get_panel_info_BIOS(rinfo); >+ /* If we're an LCD and don't have a valid setup... */ >+ if ((PRIMARY_MONITOR(rinfo) == MT_LCD) && >+ !rinfo->panel_info.valid && >+ rinfo->radeon_get_lvds_info) { >+ rinfo->radeon_get_lvds_info(rinfo); >+ } >+ >+#if 0 >+ /* If we're a mobility and still haven't detected a screen..? */ >+ if ((PRIMARY_MONITOR(rinfo) <= MT_NONE) && >+ rinfo->is_mobility && >+ rinfo->radeon_get_lvds_info) { >+ if (! rinfo->radeon_get_lvds_info(rinfo)) { >+ radeon_find_connector_for_mon(rinfo, MT_LCD); >+ } >+ } >+#endif > > /* > * 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 +1340,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 +1374,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 +1389,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,21 +1403,22 @@ > } > 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; >+ radeon_find_connector_for_mon(rinfo, MT_LCD); > radeon_var_to_panel_info(rinfo, &info->var); > } > >@@ -947,14 +1518,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 +1538,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.18/radeonfb.h aty-2.6.18-patched/radeonfb.h >--- aty-2.6.18/radeonfb.h 2006-09-05 16:42:31.000000000 -0400 >+++ aty-2.6.18-patched/radeonfb.h 2006-09-15 12:36:11.000000000 -0400 >@@ -26,6 +26,8 @@ > * Most of the definitions here are adapted right from XFree86 * > ***************************************************************/ > >+/* Sorry, we have to limit video ram to 128M */ >+#define MAX_VRAM (128*1024*1024) > > /* > * Chip families. Must fit in the low 16 bits of a long word >@@ -47,7 +49,8 @@ > CHIP_FAMILY_R350, > CHIP_FAMILY_RV350, > CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */ >- CHIP_FAMILY_R420, /* R420/R423/M18 */ >+ CHIP_FAMILY_RV410, /* RV410/M26 */ >+ CHIP_FAMILY_R420, /* R420/R423/R480/M18 */ > CHIP_FAMILY_LAST, > }; > >@@ -64,6 +67,7 @@ > ((rinfo)->family == CHIP_FAMILY_RV350) || \ > ((rinfo)->family == CHIP_FAMILY_R350) || \ > ((rinfo)->family == CHIP_FAMILY_RV380) || \ >+ ((rinfo)->family == CHIP_FAMILY_RV410) || \ > ((rinfo)->family == CHIP_FAMILY_R420)) > > /* >@@ -86,11 +90,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 */ >@@ -100,27 +143,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 >@@ -128,11 +189,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 >@@ -299,6 +368,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]; >@@ -317,15 +400,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; > >@@ -357,24 +433,19 @@ > }; > > >-#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 > */ >-#ifdef CONFIG_FB_RADEON_DEBUG >-#define DEBUG 1 >-#else >-#define DEBUG 0 >-#endif >- >-#if DEBUG >-#define RTRACE printk >-#else >-#define RTRACE if(0) printk >-#endif >- >+extern int radeonfb_debug; >+#define RTRACE if(radeonfb_debug) printk > > /* > * IO macros >@@ -597,7 +668,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); >@@ -635,4 +706,18 @@ > static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {} > #endif > >+/* 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__ */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 162628
: 107350