| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | #include "radeonfb.h" | |||
| 2 | #include "../edid.h" | |||
| 3 | ||||
| 4 | static struct fb_var_screeninfo radeonfb_default_var = { | |||
| 5 | .xres = 640, | |||
| 6 | .yres = 480, | |||
| 7 | .xres_virtual = 640, | |||
| 8 | .yres_virtual = 480, | |||
| 9 | .bits_per_pixel = 8, | |||
| 10 | .red = { .length = 8 }, | |||
| 11 | .green = { .length = 8 }, | |||
| 12 | .blue = { .length = 8 }, | |||
| 13 | .activate = FB_ACTIVATE_NOW, | |||
| 14 | .height = -1, | |||
| 15 | .width = -1, | |||
| 16 | .pixclock = 39721, | |||
| 17 | .left_margin = 40, | |||
| 18 | .right_margin = 24, | |||
| 19 | .upper_margin = 32, | |||
| 20 | .lower_margin = 11, | |||
| 21 | .hsync_len = 96, | |||
| 22 | .vsync_len = 2, | |||
| 23 | .vmode = FB_VMODE_NONINTERLACED | |||
| 24 | }; | |||
| 25 | ||||
| 12 | 0 | 26 | static char *radeon_get_mon_name(int type) | |
| 27 | { | |||
| 28 | char *pret = NULL; | |||
| 29 | ||||
| 30 | switch (type) { | |||
| 6 | 31 | case MT_NONE: | ||
| 32 | pret = "no"; | |||
| 6 | 33 | break; | ||
| 0 | - | 34 | case MT_CRT: | |
| 35 | pret = "CRT"; | |||
| 0 | - | 36 | break; | |
| 0 | - | 37 | case MT_DFP: | |
| 38 | pret = "DFP"; | |||
| 0 | - | 39 | break; | |
| 6 | 40 | case MT_LCD: | ||
| 41 | pret = "LCD"; | |||
| 6 | 42 | break; | ||
| 0 | - | 43 | case MT_CTV: | |
| 44 | pret = "CTV"; | |||
| 0 | - | 45 | break; | |
| 0 | - | 46 | case MT_STV: | |
| 47 | pret = "STV"; | |||
| 0 | - | 48 | break; | |
| 49 | } | |||
| 50 | ||||
| 12 | 51 | return pret; | ||
| 52 | } | |||
| 53 | ||||
| 54 | ||||
| 55 | #ifdef CONFIG_PPC_OF | |||
| 56 | /* | |||
| 57 | * Try to find monitor informations & EDID data out of the Open Firmware | |||
| 58 | * device-tree. This also contains some "hacks" to work around a few machine | |||
| 59 | * models with broken OF probing by hard-coding known EDIDs for some Mac | |||
| 60 | * laptops internal LVDS panel. (XXX: not done yet) | |||
| 61 | */ | |||
| 62 | static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID, | |||
| 63 | int hdno) | |||
| 64 | { | |||
| 65 | static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", | |||
| 66 | "EDID1", "EDID2", NULL }; | |||
| 67 | u8 *pedid = NULL; | |||
| 68 | u8 *pmt = NULL; | |||
| 69 | u8 *tmp; | |||
| 70 | int i, mt = MT_NONE; | |||
| 71 | ||||
| 72 | RTRACE("analyzing OF properties...\n"); | |||
| 73 | pmt = (u8 *)get_property(dp, "display-type", NULL); | |||
| 74 | if (!pmt) | |||
| 75 | return MT_NONE; | |||
| 76 | RTRACE("display-type: %s\n", pmt); | |||
| 77 | /* OF says "LCD" for DFP as well, we discriminate from the caller of this | |||
| 78 | * function | |||
| 79 | */ | |||
| 80 | if (!strcmp(pmt, "LCD") || !strcmp(pmt, "DFP")) | |||
| 81 | mt = MT_DFP; | |||
| 82 | else if (!strcmp(pmt, "CRT")) | |||
| 83 | mt = MT_CRT; | |||
| 84 | else { | |||
| 85 | if (strcmp(pmt, "NONE") != 0) | |||
| 86 | printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n", | |||
| 87 | pmt); | |||
| 88 | return MT_NONE; | |||
| 89 | } | |||
| 90 | ||||
| 91 | for (i = 0; propnames[i] != NULL; ++i) { | |||
| 92 | pedid = (u8 *)get_property(dp, propnames[i], NULL); | |||
| 93 | if (pedid != NULL) | |||
| 94 | break; | |||
| 95 | } | |||
| 96 | /* We didn't find the EDID in the leaf node, some cards will actually | |||
| 97 | * put EDID1/EDID2 in the parent, look for these (typically M6 tipb). | |||
| 98 | * single-head cards have hdno == -1 and skip this step | |||
| 99 | */ | |||
| 100 | if (pedid == NULL && dp->parent && (hdno != -1)) | |||
| 101 | pedid = get_property(dp->parent, (hdno == 0) ? "EDID1" : "EDID2", NULL); | |||
| 102 | if (pedid == NULL && dp->parent && (hdno == 0)) | |||
| 103 | pedid = get_property(dp->parent, "EDID", NULL); | |||
| 104 | if (pedid == NULL) | |||
| 105 | return mt; | |||
| 106 | ||||
| 107 | tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL); | |||
| 108 | if (!tmp) | |||
| 109 | return mt; | |||
| 110 | memcpy(tmp, pedid, EDID_LENGTH); | |||
| 111 | *out_EDID = tmp; | |||
| 112 | return mt; | |||
| 113 | } | |||
| 114 | ||||
| 115 | static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no, | |||
| 116 | u8 **out_EDID) | |||
| 117 | { | |||
| 118 | struct device_node *dp; | |||
| 119 | ||||
| 120 | RTRACE("radeon_probe_OF_head\n"); | |||
| 121 | ||||
| 122 | dp = rinfo->of_node; | |||
| 123 | while (dp == NULL) | |||
| 124 | return MT_NONE; | |||
| 125 | ||||
| 126 | if (rinfo->has_CRTC2) { | |||
| 127 | char *pname; | |||
| 128 | int len, second = 0; | |||
| 129 | ||||
| 130 | dp = dp->child; | |||
| 131 | do { | |||
| 132 | if (!dp) | |||
| 133 | return MT_NONE; | |||
| 134 | pname = (char *)get_property(dp, "name", NULL); | |||
| 135 | if (!pname) | |||
| 136 | return MT_NONE; | |||
| 137 | len = strlen(pname); | |||
| 138 | RTRACE("head: %s (letter: %c, head_no: %d)\n", | |||
| 139 | pname, pname[len-1], head_no); | |||
| 140 | if (pname[len-1] == 'A' && head_no == 0) { | |||
| 141 | int mt = radeon_parse_montype_prop(dp, out_EDID, 0); | |||
| 142 | /* Maybe check for LVDS_GEN_CNTL here ? I need to check out | |||
| 143 | * what OF does when booting with lid closed | |||
| 144 | */ | |||
| 145 | if (mt == MT_DFP && rinfo->is_mobility) | |||
| 146 | mt = MT_LCD; | |||
| 147 | return mt; | |||
| 148 | } else if (pname[len-1] == 'B' && head_no == 1) | |||
| 149 | return radeon_parse_montype_prop(dp, out_EDID, 1); | |||
| 150 | second = 1; | |||
| 151 | dp = dp->sibling; | |||
| 152 | } while(!second); | |||
| 153 | } else { | |||
| 154 | if (head_no > 0) | |||
| 155 | return MT_NONE; | |||
| 156 | return radeon_parse_montype_prop(dp, out_EDID, -1); | |||
| 157 | } | |||
| 158 | return MT_NONE; | |||
| 159 | } | |||
| 160 | #endif /* CONFIG_PPC_OF */ | |||
| 161 | ||||
| 162 | ||||
| 6 | 0 | 163 | static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo) | |
| 164 | { | |||
| 165 | unsigned long tmp, tmp0; | |||
| 166 | char stmp[30]; | |||
| 167 | int i; | |||
| 168 | ||||
| 0 | 6 | - | 169 | if (!rinfo->bios_seg) |
| 0 | - | 170 | return 0; | |
| 171 | ||||
| 0 | 6 | - | 172 | if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) { |
| 173 | printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n"); | |||
| 174 | rinfo->panel_info.pwr_delay = 200; | |||
| 0 | - | 175 | return 0; | |
| 176 | } | |||
| 177 | ||||
| 144 | 6 | 178 | for(i=0; i<24; i++) | |
| 179 | stmp[i] = BIOS_IN8(tmp+i+1); | |||
| 180 | stmp[24] = 0; | |||
| 181 | printk("radeonfb: panel ID string: %s\n", stmp); | |||
| 182 | rinfo->panel_info.xres = BIOS_IN16(tmp + 25); | |||
| 183 | rinfo->panel_info.yres = BIOS_IN16(tmp + 27); | |||
| 184 | printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n", | |||
| 185 | rinfo->panel_info.xres, rinfo->panel_info.yres); | |||
| 186 | ||||
| 187 | rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44); | |||
| 0 | 6 | - | 188 | RTRACE("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay); |
| 0 | 6 | - | 189 | if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0) |
| 0 | - | 189 | T || _ | |
| 0 | - | 189 | F || T | |
| 6 | 189 | F || F | ||
| 190 | rinfo->panel_info.pwr_delay = 2000; | |||
| 191 | ||||
| 192 | /* | |||
| 193 | * Some panels only work properly with some divider combinations | |||
| 194 | */ | |||
| 195 | rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46); | |||
| 196 | rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48); | |||
| 197 | rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49); | |||
| 198 | if (rinfo->panel_info.ref_divider != 0 && | |||
| 6 | 0 | - | 199 | rinfo->panel_info.fbk_divider > 3) { |
| 6 | 199 | T && T | ||
| 0 | - | 199 | T && F | |
| 0 | - | 199 | F && _ | |
| 200 | rinfo->panel_info.use_bios_dividers = 1; | |||
| 201 | printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n"); | |||
| 0 | 6 | - | 202 | RTRACE("ref_divider = %x\n", rinfo->panel_info.ref_divider); |
| 0 | 6 | - | 203 | RTRACE("post_divider = %x\n", rinfo->panel_info.post_divider); |
| 0 | 6 | - | 204 | RTRACE("fbk_divider = %x\n", rinfo->panel_info.fbk_divider); |
| 205 | } | |||
| 0 | 6 | - | 206 | RTRACE("Scanning BIOS table ...\n"); |
| 102 | 0 | - | 207 | for(i=0; i<32; i++) { |
| 208 | tmp0 = BIOS_IN16(tmp+64+i*2); | |||
| 0 | 102 | - | 209 | if (tmp0 == 0) |
| 0 | - | 210 | break; | |
| 0 | 102 | - | 211 | RTRACE(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2)); |
| 212 | if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) && | |||
| 6 | 96 | 213 | (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) { | |
| 6 | 213 | (T) && (T) | ||
| 0 | - | 213 | (T) && (F) | |
| 96 | 213 | (F) && (_) | ||
| 214 | rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8; | |||
| 215 | rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) - | |||
| 216 | BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff; | |||
| 217 | rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8; | |||
| 218 | rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26); | |||
| 219 | rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26); | |||
| 220 | rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11; | |||
| 221 | rinfo->panel_info.clock = BIOS_IN16(tmp0+9); | |||
| 222 | /* Assume high active syncs for now until ATI tells me more... maybe we | |||
| 223 | * can probe register values here ? | |||
| 224 | */ | |||
| 225 | rinfo->panel_info.hAct_high = 1; | |||
| 226 | rinfo->panel_info.vAct_high = 1; | |||
| 227 | /* Mark panel infos valid */ | |||
| 228 | rinfo->panel_info.valid = 1; | |||
| 229 | ||||
| 0 | 6 | - | 230 | RTRACE("Found panel in BIOS table:\n"); |
| 0 | 6 | - | 231 | RTRACE(" hblank: %d\n", rinfo->panel_info.hblank); |
| 0 | 6 | - | 232 | RTRACE(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus); |
| 0 | 6 | - | 233 | RTRACE(" hSync_width: %d\n", rinfo->panel_info.hSync_width); |
| 0 | 6 | - | 234 | RTRACE(" vblank: %d\n", rinfo->panel_info.vblank); |
| 0 | 6 | - | 235 | RTRACE(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus); |
| 0 | 6 | - | 236 | RTRACE(" vSync_width: %d\n", rinfo->panel_info.vSync_width); |
| 0 | 6 | - | 237 | RTRACE(" clock: %d\n", rinfo->panel_info.clock); |
| 238 | ||||
| 6 | 239 | return 1; | ||
| 240 | } | |||
| 241 | } | |||
| 0 | 0 | - | 242 | RTRACE("Didn't find panel in BIOS table !\n"); |
| 243 | ||||
| 0 | - | 244 | return 0; | |
| 245 | } | |||
| 246 | ||||
| 247 | /* Try to extract the connector informations from the BIOS. This | |||
| 248 | * doesn't quite work yet, but it's output is still useful for | |||
| 249 | * debugging | |||
| 250 | */ | |||
| 6 | 6 | 251 | static void __devinit radeon_parse_connector_info(struct radeonfb_info *rinfo) | |
| 252 | { | |||
| 253 | int offset, chips, connectors, tmp, i, conn, type; | |||
| 254 | ||||
| 255 | static char* __conn_type_table[16] = { | |||
| 256 | "NONE", "Proprietary", "CRT", "DVI-I", "DVI-D", "Unknown", "Unknown", | |||
| 257 | "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", | |||
| 258 | "Unknown", "Unknown", "Unknown" | |||
| 259 | }; | |||
| 260 | ||||
| 0 | 6 | - | 261 | if (!rinfo->bios_seg) |
| 0 | - | 262 | return; | |
| 263 | ||||
| 264 | offset = BIOS_IN16(rinfo->fp_bios_start + 0x50); | |||
| 0 | 6 | - | 265 | if (offset == 0) { |
| 266 | printk(KERN_WARNING "radeonfb: No connector info table detected\n"); | |||
| 0 | - | 267 | return; | |
| 268 | } | |||
| 269 | ||||
| 270 | /* Don't do much more at this point but displaying the data if | |||
| 271 | * DEBUG is enabled | |||
| 272 | */ | |||
| 273 | chips = BIOS_IN8(offset++) >> 4; | |||
| 0 | 6 | - | 274 | RTRACE("%d chips in connector info\n", chips); |
| 6 | 6 | 275 | for (i = 0; i < chips; i++) { | |
| 276 | tmp = BIOS_IN8(offset++); | |||
| 277 | connectors = tmp & 0x0f; | |||
| 0 | 6 | - | 278 | RTRACE(" - chip %d has %d connectors\n", tmp >> 4, connectors); |
| 12 | 0 | - | 279 | for (conn = 0; ; conn++) { |
| 280 | tmp = BIOS_IN16(offset); | |||
| 6 | 6 | 281 | if (tmp == 0) | |
| 6 | 282 | break; | ||
| 283 | offset += 2; | |||
| 284 | type = (tmp >> 12) & 0x0f; | |||
| 0 | 6 | - | 285 | RTRACE(" * connector %d of type %d (%s) : %04x\n", |
| 286 | conn, type, __conn_type_table[type], tmp); | |||
| 287 | } | |||
| 288 | } | |||
| 289 | } | |||
| 290 | ||||
| 291 | ||||
| 292 | /* | |||
| 293 | * Probe physical connection of a CRT. This code comes from XFree | |||
| 294 | * as well and currently is only implemented for the CRT DAC, the | |||
| 295 | * code for the TVDAC is commented out in XFree as "non working" | |||
| 296 | */ | |||
| 6 | 0 | 297 | static int __devinit radeon_crt_is_connected(struct radeonfb_info *rinfo, int is_crt_dac) | |
| 298 | { | |||
| 299 | int connected = 0; | |||
| 300 | ||||
| 301 | /* the monitor either wasn't connected or it is a non-DDC CRT. | |||
| 302 | * try to probe it | |||
| 303 | */ | |||
| 6 | 0 | - | 304 | if (is_crt_dac) { |
| 305 | unsigned long ulOrigVCLK_ECP_CNTL; | |||
| 306 | unsigned long ulOrigDAC_CNTL; | |||
| 307 | unsigned long ulOrigDAC_EXT_CNTL; | |||
| 308 | unsigned long ulOrigCRTC_EXT_CNTL; | |||
| 309 | unsigned long ulData; | |||
| 310 | unsigned long ulMask; | |||
| 311 | ||||
| 312 | ulOrigVCLK_ECP_CNTL = INPLL(VCLK_ECP_CNTL); | |||
| 313 | ||||
| 314 | ulData = ulOrigVCLK_ECP_CNTL; | |||
| 315 | ulData &= ~(PIXCLK_ALWAYS_ONb | |||
| 316 | | PIXCLK_DAC_ALWAYS_ONb); | |||
| 317 | ulMask = ~(PIXCLK_ALWAYS_ONb | |||
| 318 | | PIXCLK_DAC_ALWAYS_ONb); | |||
| 319 | OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask); | |||
| 320 | ||||
| 321 | ulOrigCRTC_EXT_CNTL = INREG(CRTC_EXT_CNTL); | |||
| 322 | ulData = ulOrigCRTC_EXT_CNTL; | |||
| 323 | ulData |= CRTC_CRT_ON; | |||
| 324 | OUTREG(CRTC_EXT_CNTL, ulData); | |||
| 325 | ||||
| 326 | ulOrigDAC_EXT_CNTL = INREG(DAC_EXT_CNTL); | |||
| 327 | ulData = ulOrigDAC_EXT_CNTL; | |||
| 328 | ulData &= ~DAC_FORCE_DATA_MASK; | |||
| 329 | ulData |= (DAC_FORCE_BLANK_OFF_EN | |||
| 330 | |DAC_FORCE_DATA_EN | |||
| 331 | |DAC_FORCE_DATA_SEL_MASK); | |||
| 332 | if ((rinfo->family == CHIP_FAMILY_RV250) || | |||
| 0 | 6 | - | 333 | (rinfo->family == CHIP_FAMILY_RV280)) |
| 0 | - | 333 | (T) || (_) | |
| 0 | - | 333 | (F) || (T) | |
| 6 | 333 | (F) || (F) | ||
| 334 | ulData |= (0x01b6 << DAC_FORCE_DATA_SHIFT); | |||
| 335 | else | |||
| 336 | ulData |= (0x01ac << DAC_FORCE_DATA_SHIFT); | |||
| 337 | ||||
| 338 | OUTREG(DAC_EXT_CNTL, ulData); | |||
| 339 | ||||
| 340 | ulOrigDAC_CNTL = INREG(DAC_CNTL); | |||
| 341 | ulData = ulOrigDAC_CNTL; | |||
| 342 | ulData |= DAC_CMP_EN; | |||
| 343 | ulData &= ~(DAC_RANGE_CNTL_MASK | |||
| 344 | | DAC_PDWN); | |||
| 345 | ulData |= 0x2; | |||
| 346 | OUTREG(DAC_CNTL, ulData); | |||
| 347 | ||||
| 348 | mdelay(1); | |||
| 6 | 0 | - | 348 | ternary-?: ( __builtin_constant_p ( 1 ) && (.. |
| 6 | 0 | - | 348 | ternary-?: __builtin_constant_p ( ( 1 ) * 10.. |
| 0 | 6 | - | 348 | ternary-?: ( ( 1 ) * 1000 ) > 20000 |
| 349 | ||||
| 350 | ulData = INREG(DAC_CNTL); | |||
| 351 | connected = (DAC_CMP_OUTPUT & ulData) ? 1 : 0; | |||
| 0 | 6 | - | 351 | ternary-?: ( ( 1 << 7 ) & ulData ) |
| 352 | ||||
| 353 | ulData = ulOrigVCLK_ECP_CNTL; | |||
| 354 | ulMask = 0xFFFFFFFFL; | |||
| 355 | OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask); | |||
| 356 | ||||
| 357 | OUTREG(DAC_CNTL, ulOrigDAC_CNTL ); | |||
| 358 | OUTREG(DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); | |||
| 359 | OUTREG(CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); | |||
| 360 | } | |||
| 361 | ||||
| 362 | return connected ? MT_CRT : MT_NONE; | |||
| 0 | 6 | - | 362 | ternary-?: connected |
| 6 | 362 | return connected ? MT_CRT : MT_NONE | ||
| 363 | } | |||
| 364 | ||||
| 365 | /* | |||
| 366 | * Parse the "monitor_layout" string if any. This code is mostly | |||
| 367 | * copied from XFree's radeon driver | |||
| 368 | */ | |||
| 6 | 0 | 369 | static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo, | |
| 370 | const char *monitor_layout) | |||
| 371 | { | |||
| 372 | char s1[5], s2[5]; | |||
| 373 | int i = 0, second = 0; | |||
| 374 | const char *s; | |||
| 375 | ||||
| 6 | 0 | - | 376 | if (!monitor_layout) |
| 6 | 377 | return 0; | ||
| 378 | ||||
| 379 | s = monitor_layout; | |||
| 380 | do { | |||
| 381 | switch(*s) { | |||
| 0 | - | 382 | case ',': | |
| 383 | s1[i] = '\0'; | |||
| 384 | i = 0; | |||
| 385 | second = 1; | |||
| 0 | - | 386 | break; | |
| 0 | - | 387 | case ' ': | |
| 0 | - | 388 | case '\0': | |
| 0 | - | 389 | break; | |
| 0 | - | 390 | default: | |
| 0 | 0 | - | 391 | if (i > 4) |
| 0 | - | 392 | break; | |
| 0 | 0 | - | 393 | if (second) |
| 394 | s2[i] = *s; | |||
| 395 | else | |||
| 396 | s1[i] = *s; | |||
| 397 | i++; | |||
| 398 | } | |||
| 399 | ||||
| 0 | 0 | - | 400 | if (i > 4) |
| 401 | i = 4; | |||
| 402 | ||||
| 0 | 0 | - | 403 | } while (*s++); |
| 0 | 0 | - | 404 | if (second) |
| 405 | s2[i] = 0; | |||
| 406 | else { | |||
| 407 | s1[i] = 0; | |||
| 408 | s2[0] = 0; | |||
| 409 | } | |||
| 0 | 0 | - | 410 | if (strcmp(s1, "CRT") == 0) |
| 411 | rinfo->mon1_type = MT_CRT; | |||
| 0 | 0 | - | 412 | else if (strcmp(s1, "TMDS") == 0) |
| 413 | rinfo->mon1_type = MT_DFP; | |||
| 0 | 0 | - | 414 | else if (strcmp(s1, "LVDS") == 0) |
| 415 | rinfo->mon1_type = MT_LCD; | |||
| 416 | ||||
| 0 | 0 | - | 417 | if (strcmp(s2, "CRT") == 0) |
| 418 | rinfo->mon2_type = MT_CRT; | |||
| 0 | 0 | - | 419 | else if (strcmp(s2, "TMDS") == 0) |
| 420 | rinfo->mon2_type = MT_DFP; | |||
| 0 | 0 | - | 421 | else if (strcmp(s2, "LVDS") == 0) |
| 422 | rinfo->mon2_type = MT_LCD; | |||
| 423 | ||||
| 0 | - | 424 | return 1; | |
| 425 | } | |||
| 426 | ||||
| 427 | /* | |||
| 428 | * Probe display on both primary and secondary card's connector (if any) | |||
| 429 | * by various available techniques (i2c, OF device tree, BIOS, ...) and | |||
| 430 | * try to retrieve EDID. The algorithm here comes from XFree's radeon | |||
| 431 | * driver | |||
| 432 | */ | |||
| 6 | 6 | 433 | void __devinit radeon_probe_screens(struct radeonfb_info *rinfo, | |
| 434 | const char *monitor_layout, int ignore_edid) | |||
| 435 | { | |||
| 436 | #ifdef CONFIG_FB_RADEON_I2C | |||
| 437 | int ddc_crt2_used = 0; | |||
| 438 | #endif | |||
| 439 | int tmp, i; | |||
| 440 | ||||
| 441 | radeon_parse_connector_info(rinfo); | |||
| 442 | ||||
| 0 | 6 | - | 443 | if (radeon_parse_monitor_layout(rinfo, monitor_layout)) { |
| 444 | ||||
| 445 | /* | |||
| 446 | * If user specified a monitor_layout option, use it instead | |||
| 447 | * of auto-detecting. Maybe we should only use this argument | |||
| 448 | * on the first radeon card probed or provide a way to specify | |||
| 449 | * a layout for each card ? | |||
| 450 | */ | |||
| 451 | ||||
| 0 | 0 | - | 452 | RTRACE("Using specified monitor layout: %s", monitor_layout); |
| 453 | #ifdef CONFIG_FB_RADEON_I2C | |||
| 0 | 0 | - | 454 | if (!ignore_edid) { |
| 0 | 0 | - | 455 | if (rinfo->mon1_type != MT_NONE) |
| 0 | 0 | - | 456 | if (!radeon_probe_i2c_connector(rinfo, ddc_dvi, &rinfo->mon1_EDID)) { |
| 457 | radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon1_EDID); | |||
| 458 | ddc_crt2_used = 1; | |||
| 459 | } | |||
| 0 | 0 | - | 460 | if (rinfo->mon2_type != MT_NONE) |
| 461 | if (!radeon_probe_i2c_connector(rinfo, ddc_vga, &rinfo->mon2_EDID) && | |||
| 0 | 0 | - | 462 | !ddc_crt2_used) |
| 0 | - | 462 | T && T | |
| 0 | - | 462 | T && F | |
| 0 | - | 462 | F && _ | |
| 463 | radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon2_EDID); | |||
| 464 | } | |||
| 465 | #endif /* CONFIG_FB_RADEON_I2C */ | |||
| 0 | 0 | - | 466 | if (rinfo->mon1_type == MT_NONE) { |
| 0 | 0 | - | 467 | if (rinfo->mon2_type != MT_NONE) { |
| 468 | rinfo->mon1_type = rinfo->mon2_type; | |||
| 469 | rinfo->mon1_EDID = rinfo->mon2_EDID; | |||
| 470 | } else { | |||
| 471 | rinfo->mon1_type = MT_CRT; | |||
| 472 | printk(KERN_INFO "radeonfb: No valid monitor, assuming CRT on first port\n"); | |||
| 473 | } | |||
| 474 | rinfo->mon2_type = MT_NONE; | |||
| 475 | rinfo->mon2_EDID = NULL; | |||
| 476 | } | |||
| 477 | } else { | |||
| 478 | /* | |||
| 479 | * Auto-detecting display type (well... trying to ...) | |||
| 480 | */ | |||
| 481 | ||||
| 0 | 6 | - | 482 | RTRACE("Starting monitor auto detection...\n"); |
| 483 | ||||
| 484 | #if DEBUG && defined(CONFIG_FB_RADEON_I2C) | |||
| 485 | { | |||
| 486 | u8 *EDIDs[4] = { NULL, NULL, NULL, NULL }; | |||
| 487 | int mon_types[4] = {MT_NONE, MT_NONE, MT_NONE, MT_NONE}; | |||
| 488 | int i; | |||
| 489 | ||||
| 490 | for (i = 0; i < 4; i++) | |||
| 491 | mon_types[i] = radeon_probe_i2c_connector(rinfo, | |||
| 492 | i+1, &EDIDs[i]); | |||
| 493 | } | |||