1052 lines · c
1// SPDX-License-Identifier: GPL-2.02#include "radeonfb.h"3 4#include <linux/slab.h>5 6#include "../edid.h"7 8static const struct fb_var_screeninfo radeonfb_default_var = {9 .xres = 640,10 .yres = 480,11 .xres_virtual = 640,12 .yres_virtual = 480,13 .bits_per_pixel = 8,14 .red = { .length = 8 },15 .green = { .length = 8 },16 .blue = { .length = 8 },17 .activate = FB_ACTIVATE_NOW,18 .height = -1,19 .width = -1,20 .pixclock = 39721,21 .left_margin = 40,22 .right_margin = 24,23 .upper_margin = 32,24 .lower_margin = 11,25 .hsync_len = 96,26 .vsync_len = 2,27 .vmode = FB_VMODE_NONINTERLACED28};29 30static char *radeon_get_mon_name(int type)31{32 char *pret = NULL;33 34 switch (type) {35 case MT_NONE:36 pret = "no";37 break;38 case MT_CRT:39 pret = "CRT";40 break;41 case MT_DFP:42 pret = "DFP";43 break;44 case MT_LCD:45 pret = "LCD";46 break;47 case MT_CTV:48 pret = "CTV";49 break;50 case MT_STV:51 pret = "STV";52 break;53 }54 55 return pret;56}57 58 59#if defined(CONFIG_PPC) || defined(CONFIG_SPARC)60/*61 * Try to find monitor informations & EDID data out of the Open Firmware62 * device-tree. This also contains some "hacks" to work around a few machine63 * models with broken OF probing by hard-coding known EDIDs for some Mac64 * laptops internal LVDS panel. (XXX: not done yet)65 */66static int radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID,67 int hdno)68{69 static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID",70 "EDID1", "EDID2", NULL };71 const u8 *pedid = NULL;72 const u8 *pmt = NULL;73 u8 *tmp;74 int i, mt = MT_NONE; 75 76 pr_debug("analyzing OF properties...\n");77 pmt = of_get_property(dp, "display-type", NULL);78 if (!pmt)79 return MT_NONE;80 pr_debug("display-type: %s\n", pmt);81 /* OF says "LCD" for DFP as well, we discriminate from the caller of this82 * function83 */84 if (!strcmp(pmt, "LCD") || !strcmp(pmt, "DFP"))85 mt = MT_DFP;86 else if (!strcmp(pmt, "CRT"))87 mt = MT_CRT;88 else {89 if (strcmp(pmt, "NONE") != 0)90 printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n",91 pmt);92 return MT_NONE;93 }94 95 for (i = 0; propnames[i] != NULL; ++i) {96 pedid = of_get_property(dp, propnames[i], NULL);97 if (pedid != NULL)98 break;99 }100 /* We didn't find the EDID in the leaf node, some cards will actually101 * put EDID1/EDID2 in the parent, look for these (typically M6 tipb).102 * single-head cards have hdno == -1 and skip this step103 */104 if (pedid == NULL && dp->parent && (hdno != -1))105 pedid = of_get_property(dp->parent,106 (hdno == 0) ? "EDID1" : "EDID2", NULL);107 if (pedid == NULL && dp->parent && (hdno == 0))108 pedid = of_get_property(dp->parent, "EDID", NULL);109 if (pedid == NULL)110 return mt;111 112 tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL);113 if (!tmp)114 return mt;115 *out_EDID = tmp;116 return mt;117}118 119static int radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no,120 u8 **out_EDID)121{122 struct device_node *dp;123 124 pr_debug("radeon_probe_OF_head\n");125 126 dp = rinfo->of_node;127 while (dp == NULL)128 return MT_NONE;129 130 if (rinfo->has_CRTC2) {131 const char *pname;132 int len, second = 0;133 134 dp = dp->child;135 do {136 if (!dp)137 return MT_NONE;138 pname = of_get_property(dp, "name", NULL);139 if (!pname)140 return MT_NONE;141 len = strlen(pname);142 pr_debug("head: %s (letter: %c, head_no: %d)\n",143 pname, pname[len-1], head_no);144 if (pname[len-1] == 'A' && head_no == 0) {145 int mt = radeon_parse_montype_prop(dp, out_EDID, 0);146 /* Maybe check for LVDS_GEN_CNTL here ? I need to check out147 * what OF does when booting with lid closed148 */149 if (mt == MT_DFP && rinfo->is_mobility)150 mt = MT_LCD;151 return mt;152 } else if (pname[len-1] == 'B' && head_no == 1)153 return radeon_parse_montype_prop(dp, out_EDID, 1);154 second = 1;155 dp = dp->sibling;156 } while(!second);157 } else {158 if (head_no > 0)159 return MT_NONE;160 return radeon_parse_montype_prop(dp, out_EDID, -1);161 }162 return MT_NONE;163}164#endif /* CONFIG_PPC || CONFIG_SPARC */165 166 167static int radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)168{169 unsigned long tmp, tmp0;170 char stmp[30];171 int i;172 173 if (!rinfo->bios_seg)174 return 0;175 176 if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) {177 printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n");178 rinfo->panel_info.pwr_delay = 200;179 return 0;180 }181 182 for(i=0; i<24; i++)183 stmp[i] = BIOS_IN8(tmp+i+1);184 stmp[24] = 0;185 printk("radeonfb: panel ID string: %s\n", stmp);186 rinfo->panel_info.xres = BIOS_IN16(tmp + 25);187 rinfo->panel_info.yres = BIOS_IN16(tmp + 27);188 printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n",189 rinfo->panel_info.xres, rinfo->panel_info.yres);190 191 rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44);192 pr_debug("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay);193 if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0)194 rinfo->panel_info.pwr_delay = 2000;195 196 /*197 * Some panels only work properly with some divider combinations198 */199 rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46);200 rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48);201 rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49);202 if (rinfo->panel_info.ref_divider != 0 &&203 rinfo->panel_info.fbk_divider > 3) {204 rinfo->panel_info.use_bios_dividers = 1;205 printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n");206 pr_debug("ref_divider = %x\n", rinfo->panel_info.ref_divider);207 pr_debug("post_divider = %x\n", rinfo->panel_info.post_divider);208 pr_debug("fbk_divider = %x\n", rinfo->panel_info.fbk_divider);209 }210 pr_debug("Scanning BIOS table ...\n");211 for(i=0; i<32; i++) {212 tmp0 = BIOS_IN16(tmp+64+i*2);213 if (tmp0 == 0)214 break;215 pr_debug(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2));216 if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) &&217 (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) {218 rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8;219 rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) -220 BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff;221 rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8;222 rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26);223 rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26);224 rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11;225 rinfo->panel_info.clock = BIOS_IN16(tmp0+9);226 /* Assume high active syncs for now until ATI tells me more... maybe we227 * can probe register values here ?228 */229 rinfo->panel_info.hAct_high = 1;230 rinfo->panel_info.vAct_high = 1;231 /* Mark panel infos valid */232 rinfo->panel_info.valid = 1;233 234 pr_debug("Found panel in BIOS table:\n");235 pr_debug(" hblank: %d\n", rinfo->panel_info.hblank);236 pr_debug(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus);237 pr_debug(" hSync_width: %d\n", rinfo->panel_info.hSync_width);238 pr_debug(" vblank: %d\n", rinfo->panel_info.vblank);239 pr_debug(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus);240 pr_debug(" vSync_width: %d\n", rinfo->panel_info.vSync_width);241 pr_debug(" clock: %d\n", rinfo->panel_info.clock);242 243 return 1;244 }245 }246 pr_debug("Didn't find panel in BIOS table !\n");247 248 return 0;249}250 251/* Try to extract the connector informations from the BIOS. This252 * doesn't quite work yet, but it's output is still useful for253 * debugging254 */255static void radeon_parse_connector_info(struct radeonfb_info *rinfo)256{257 int offset, chips, connectors, tmp, i, conn, type;258 259 static char* __conn_type_table[16] = {260 "NONE", "Proprietary", "CRT", "DVI-I", "DVI-D", "Unknown", "Unknown",261 "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",262 "Unknown", "Unknown", "Unknown"263 };264 265 if (!rinfo->bios_seg)266 return;267 268 offset = BIOS_IN16(rinfo->fp_bios_start + 0x50);269 if (offset == 0) {270 printk(KERN_WARNING "radeonfb: No connector info table detected\n");271 return;272 }273 274 /* Don't do much more at this point but displaying the data if275 * DEBUG is enabled276 */277 chips = BIOS_IN8(offset++) >> 4;278 pr_debug("%d chips in connector info\n", chips);279 for (i = 0; i < chips; i++) {280 tmp = BIOS_IN8(offset++);281 connectors = tmp & 0x0f;282 pr_debug(" - chip %d has %d connectors\n", tmp >> 4, connectors);283 for (conn = 0; ; conn++) {284 tmp = BIOS_IN16(offset);285 if (tmp == 0)286 break;287 offset += 2;288 type = (tmp >> 12) & 0x0f;289 pr_debug(" * connector %d of type %d (%s) : %04x\n",290 conn, type, __conn_type_table[type], tmp);291 }292 }293}294 295 296/*297 * Probe physical connection of a CRT. This code comes from XFree298 * as well and currently is only implemented for the CRT DAC, the299 * code for the TVDAC is commented out in XFree as "non working"300 */301static int radeon_crt_is_connected(struct radeonfb_info *rinfo, int is_crt_dac)302{303 int connected = 0;304 305 /* the monitor either wasn't connected or it is a non-DDC CRT.306 * try to probe it307 */308 if (is_crt_dac) {309 unsigned long ulOrigVCLK_ECP_CNTL;310 unsigned long ulOrigDAC_CNTL;311 unsigned long ulOrigDAC_EXT_CNTL;312 unsigned long ulOrigCRTC_EXT_CNTL;313 unsigned long ulData;314 unsigned long ulMask;315 316 ulOrigVCLK_ECP_CNTL = INPLL(VCLK_ECP_CNTL);317 318 ulData = ulOrigVCLK_ECP_CNTL;319 ulData &= ~(PIXCLK_ALWAYS_ONb320 | PIXCLK_DAC_ALWAYS_ONb);321 ulMask = ~(PIXCLK_ALWAYS_ONb322 | PIXCLK_DAC_ALWAYS_ONb);323 OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask);324 325 ulOrigCRTC_EXT_CNTL = INREG(CRTC_EXT_CNTL);326 ulData = ulOrigCRTC_EXT_CNTL;327 ulData |= CRTC_CRT_ON;328 OUTREG(CRTC_EXT_CNTL, ulData);329 330 ulOrigDAC_EXT_CNTL = INREG(DAC_EXT_CNTL);331 ulData = ulOrigDAC_EXT_CNTL;332 ulData &= ~DAC_FORCE_DATA_MASK;333 ulData |= (DAC_FORCE_BLANK_OFF_EN334 |DAC_FORCE_DATA_EN335 |DAC_FORCE_DATA_SEL_MASK);336 if ((rinfo->family == CHIP_FAMILY_RV250) ||337 (rinfo->family == CHIP_FAMILY_RV280))338 ulData |= (0x01b6 << DAC_FORCE_DATA_SHIFT);339 else340 ulData |= (0x01ac << DAC_FORCE_DATA_SHIFT);341 342 OUTREG(DAC_EXT_CNTL, ulData);343 344 ulOrigDAC_CNTL = INREG(DAC_CNTL);345 ulData = ulOrigDAC_CNTL;346 ulData |= DAC_CMP_EN;347 ulData &= ~(DAC_RANGE_CNTL_MASK348 | DAC_PDWN);349 ulData |= 0x2;350 OUTREG(DAC_CNTL, ulData);351 352 mdelay(1);353 354 ulData = INREG(DAC_CNTL);355 connected = (DAC_CMP_OUTPUT & ulData) ? 1 : 0;356 357 ulData = ulOrigVCLK_ECP_CNTL;358 ulMask = 0xFFFFFFFFL;359 OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask);360 361 OUTREG(DAC_CNTL, ulOrigDAC_CNTL );362 OUTREG(DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL );363 OUTREG(CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL);364 }365 366 return connected ? MT_CRT : MT_NONE;367}368 369/*370 * Parse the "monitor_layout" string if any. This code is mostly371 * copied from XFree's radeon driver372 */373static int radeon_parse_monitor_layout(struct radeonfb_info *rinfo,374 const char *monitor_layout)375{376 char s1[5], s2[5];377 int i = 0, second = 0;378 const char *s;379 380 if (!monitor_layout)381 return 0;382 383 s = monitor_layout;384 do {385 switch(*s) {386 case ',':387 s1[i] = '\0';388 i = 0;389 second = 1;390 break;391 case ' ':392 case '\0':393 break;394 default:395 if (i > 4)396 break;397 if (second)398 s2[i] = *s;399 else400 s1[i] = *s;401 i++;402 }403 404 if (i > 4)405 i = 4;406 407 } while (*s++);408 if (second)409 s2[i] = 0;410 else {411 s1[i] = 0;412 s2[0] = 0;413 }414 if (strcmp(s1, "CRT") == 0)415 rinfo->mon1_type = MT_CRT;416 else if (strcmp(s1, "TMDS") == 0)417 rinfo->mon1_type = MT_DFP;418 else if (strcmp(s1, "LVDS") == 0)419 rinfo->mon1_type = MT_LCD;420 421 if (strcmp(s2, "CRT") == 0)422 rinfo->mon2_type = MT_CRT;423 else if (strcmp(s2, "TMDS") == 0)424 rinfo->mon2_type = MT_DFP;425 else if (strcmp(s2, "LVDS") == 0)426 rinfo->mon2_type = MT_LCD;427 428 return 1;429}430 431/*432 * Probe display on both primary and secondary card's connector (if any)433 * by various available techniques (i2c, OF device tree, BIOS, ...) and434 * try to retrieve EDID. The algorithm here comes from XFree's radeon435 * driver436 */437void radeon_probe_screens(struct radeonfb_info *rinfo,438 const char *monitor_layout, int ignore_edid)439{440#ifdef CONFIG_FB_RADEON_I2C441 int ddc_crt2_used = 0; 442#endif443 int tmp, i;444 445 radeon_parse_connector_info(rinfo);446 447 if (radeon_parse_monitor_layout(rinfo, monitor_layout)) {448 449 /*450 * If user specified a monitor_layout option, use it instead451 * of auto-detecting. Maybe we should only use this argument452 * on the first radeon card probed or provide a way to specify453 * a layout for each card ?454 */455 456 pr_debug("Using specified monitor layout: %s", monitor_layout);457#ifdef CONFIG_FB_RADEON_I2C458 if (!ignore_edid) {459 if (rinfo->mon1_type != MT_NONE)460 if (!radeon_probe_i2c_connector(rinfo, ddc_dvi, &rinfo->mon1_EDID)) {461 radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon1_EDID);462 ddc_crt2_used = 1;463 }464 if (rinfo->mon2_type != MT_NONE)465 if (!radeon_probe_i2c_connector(rinfo, ddc_vga, &rinfo->mon2_EDID) &&466 !ddc_crt2_used)467 radeon_probe_i2c_connector(rinfo, ddc_crt2, &rinfo->mon2_EDID);468 }469#endif /* CONFIG_FB_RADEON_I2C */470 if (rinfo->mon1_type == MT_NONE) {471 if (rinfo->mon2_type != MT_NONE) {472 rinfo->mon1_type = rinfo->mon2_type;473 rinfo->mon1_EDID = rinfo->mon2_EDID;474 } else {475 rinfo->mon1_type = MT_CRT;476 printk(KERN_INFO "radeonfb: No valid monitor, assuming CRT on first port\n");477 }478 rinfo->mon2_type = MT_NONE;479 rinfo->mon2_EDID = NULL;480 }481 } else {482 /*483 * Auto-detecting display type (well... trying to ...)484 */485 486 pr_debug("Starting monitor auto detection...\n");487 488#if defined(DEBUG) && defined(CONFIG_FB_RADEON_I2C)489 {490 u8 *EDIDs[4] = { NULL, NULL, NULL, NULL };491 int i;492 493 for (i = 0; i < 4; i++)494 radeon_probe_i2c_connector(rinfo, i + 1, &EDIDs[i]);495 }496#endif /* DEBUG */497 /*498 * Old single head cards499 */500 if (!rinfo->has_CRTC2) {501#if defined(CONFIG_PPC) || defined(CONFIG_SPARC)502 if (rinfo->mon1_type == MT_NONE)503 rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,504 &rinfo->mon1_EDID);505#endif /* CONFIG_PPC || CONFIG_SPARC */506#ifdef CONFIG_FB_RADEON_I2C507 if (rinfo->mon1_type == MT_NONE)508 rinfo->mon1_type =509 radeon_probe_i2c_connector(rinfo, ddc_dvi,510 &rinfo->mon1_EDID);511 if (rinfo->mon1_type == MT_NONE)512 rinfo->mon1_type =513 radeon_probe_i2c_connector(rinfo, ddc_vga,514 &rinfo->mon1_EDID);515 if (rinfo->mon1_type == MT_NONE)516 rinfo->mon1_type =517 radeon_probe_i2c_connector(rinfo, ddc_crt2,518 &rinfo->mon1_EDID); 519#endif /* CONFIG_FB_RADEON_I2C */520 if (rinfo->mon1_type == MT_NONE)521 rinfo->mon1_type = MT_CRT;522 goto bail;523 }524 525 /*526 * Check for cards with reversed DACs or TMDS controllers using BIOS527 */528 if (rinfo->bios_seg &&529 (tmp = BIOS_IN16(rinfo->fp_bios_start + 0x50))) {530 for (i = 1; i < 4; i++) {531 unsigned int tmp0;532 533 if (!BIOS_IN8(tmp + i*2) && i > 1)534 break;535 tmp0 = BIOS_IN16(tmp + i*2);536 if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0x0f) == ddc_dvi)) {537 rinfo->reversed_DAC = 1;538 printk(KERN_INFO "radeonfb: Reversed DACs detected\n");539 }540 if ((((tmp0 >> 8) & 0x0f) == ddc_dvi) && ((tmp0 >> 4) & 0x01)) {541 rinfo->reversed_TMDS = 1;542 printk(KERN_INFO "radeonfb: Reversed TMDS detected\n");543 }544 }545 }546 547 /*548 * Probe primary head (DVI or laptop internal panel)549 */550#if defined(CONFIG_PPC) || defined(CONFIG_SPARC)551 if (rinfo->mon1_type == MT_NONE)552 rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,553 &rinfo->mon1_EDID);554#endif /* CONFIG_PPC || CONFIG_SPARC */555#ifdef CONFIG_FB_RADEON_I2C556 if (rinfo->mon1_type == MT_NONE)557 rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,558 &rinfo->mon1_EDID);559 if (rinfo->mon1_type == MT_NONE) {560 rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,561 &rinfo->mon1_EDID);562 if (rinfo->mon1_type != MT_NONE)563 ddc_crt2_used = 1;564 }565#endif /* CONFIG_FB_RADEON_I2C */566 if (rinfo->mon1_type == MT_NONE && rinfo->is_mobility &&567 ((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4))568 || (INREG(LVDS_GEN_CNTL) & LVDS_ON))) {569 rinfo->mon1_type = MT_LCD;570 printk("Non-DDC laptop panel detected\n");571 }572 if (rinfo->mon1_type == MT_NONE)573 rinfo->mon1_type = radeon_crt_is_connected(rinfo, rinfo->reversed_DAC);574 575 /*576 * Probe secondary head (mostly VGA, can be DVI)577 */578#if defined(CONFIG_PPC) || defined(CONFIG_SPARC)579 if (rinfo->mon2_type == MT_NONE)580 rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1,581 &rinfo->mon2_EDID);582#endif /* CONFIG_PPC || defined(CONFIG_SPARC) */583#ifdef CONFIG_FB_RADEON_I2C584 if (rinfo->mon2_type == MT_NONE)585 rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_vga,586 &rinfo->mon2_EDID);587 if (rinfo->mon2_type == MT_NONE && !ddc_crt2_used)588 rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_crt2,589 &rinfo->mon2_EDID);590#endif /* CONFIG_FB_RADEON_I2C */591 if (rinfo->mon2_type == MT_NONE)592 rinfo->mon2_type = radeon_crt_is_connected(rinfo, !rinfo->reversed_DAC);593 594 /*595 * If we only detected port 2, we swap them, if none detected,596 * assume CRT (maybe fallback to old BIOS_SCRATCH stuff ? or look597 * at FP registers ?)598 */599 if (rinfo->mon1_type == MT_NONE) {600 if (rinfo->mon2_type != MT_NONE) {601 rinfo->mon1_type = rinfo->mon2_type;602 rinfo->mon1_EDID = rinfo->mon2_EDID;603 } else604 rinfo->mon1_type = MT_CRT;605 rinfo->mon2_type = MT_NONE;606 rinfo->mon2_EDID = NULL;607 }608 609 /*610 * Deal with reversed TMDS611 */612 if (rinfo->reversed_TMDS) {613 /* Always keep internal TMDS as primary head */614 if (rinfo->mon1_type == MT_DFP || rinfo->mon2_type == MT_DFP) {615 int tmp_type = rinfo->mon1_type;616 u8 *tmp_EDID = rinfo->mon1_EDID;617 rinfo->mon1_type = rinfo->mon2_type;618 rinfo->mon1_EDID = rinfo->mon2_EDID;619 rinfo->mon2_type = tmp_type;620 rinfo->mon2_EDID = tmp_EDID;621 if (rinfo->mon1_type == MT_CRT || rinfo->mon2_type == MT_CRT)622 rinfo->reversed_DAC ^= 1;623 }624 }625 }626 if (ignore_edid) {627 kfree(rinfo->mon1_EDID);628 rinfo->mon1_EDID = NULL;629 kfree(rinfo->mon2_EDID);630 rinfo->mon2_EDID = NULL;631 }632 633 bail:634 printk(KERN_INFO "radeonfb: Monitor 1 type %s found\n",635 radeon_get_mon_name(rinfo->mon1_type));636 if (rinfo->mon1_EDID)637 printk(KERN_INFO "radeonfb: EDID probed\n");638 if (!rinfo->has_CRTC2)639 return;640 printk(KERN_INFO "radeonfb: Monitor 2 type %s found\n",641 radeon_get_mon_name(rinfo->mon2_type));642 if (rinfo->mon2_EDID)643 printk(KERN_INFO "radeonfb: EDID probed\n");644}645 646 647/*648 * This function applies any arch/model/machine specific fixups649 * to the panel info. It may eventually alter EDID block as650 * well or whatever is specific to a given model and not probed651 * properly by the default code652 */653static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)654{655#ifdef CONFIG_PPC656 /*657 * LCD Flat panels should use fixed dividers, we enfore that on658 * PPC only for now...659 */660 if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD661 && rinfo->is_mobility) {662 int ppll_div_sel;663 u32 ppll_divn;664 ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;665 radeon_pll_errata_after_index(rinfo);666 ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);667 rinfo->panel_info.ref_divider = rinfo->pll.ref_div;668 rinfo->panel_info.fbk_divider = ppll_divn & 0x7ff;669 rinfo->panel_info.post_divider = (ppll_divn >> 16) & 0x7;670 rinfo->panel_info.use_bios_dividers = 1;671 672 printk(KERN_DEBUG "radeonfb: Using Firmware dividers 0x%08x "673 "from PPLL %d\n",674 rinfo->panel_info.fbk_divider |675 (rinfo->panel_info.post_divider << 16),676 ppll_div_sel);677 }678#endif /* CONFIG_PPC */679}680 681 682/*683 * Fill up panel infos from a mode definition, either returned by the EDID684 * or from the default mode when we can't do any better685 */686static void radeon_var_to_panel_info(struct radeonfb_info *rinfo, struct fb_var_screeninfo *var)687{688 rinfo->panel_info.xres = var->xres;689 rinfo->panel_info.yres = var->yres;690 rinfo->panel_info.clock = 100000000 / var->pixclock;691 rinfo->panel_info.hOver_plus = var->right_margin;692 rinfo->panel_info.hSync_width = var->hsync_len;693 rinfo->panel_info.hblank = var->left_margin +694 (var->right_margin + var->hsync_len);695 rinfo->panel_info.vOver_plus = var->lower_margin;696 rinfo->panel_info.vSync_width = var->vsync_len;697 rinfo->panel_info.vblank = var->upper_margin +698 (var->lower_margin + var->vsync_len);699 rinfo->panel_info.hAct_high =700 (var->sync & FB_SYNC_HOR_HIGH_ACT) != 0;701 rinfo->panel_info.vAct_high =702 (var->sync & FB_SYNC_VERT_HIGH_ACT) != 0;703 rinfo->panel_info.valid = 1;704 /* We use a default of 200ms for the panel power delay, 705 * I need to have a real schedule() instead of mdelay's in the panel code.706 * we might be possible to figure out a better power delay either from707 * MacOS OF tree or from the EDID block (proprietary extensions ?)708 */709 rinfo->panel_info.pwr_delay = 200;710}711 712static void radeon_videomode_to_var(struct fb_var_screeninfo *var,713 const struct fb_videomode *mode)714{715 var->xres = mode->xres;716 var->yres = mode->yres;717 var->xres_virtual = mode->xres;718 var->yres_virtual = mode->yres;719 var->xoffset = 0;720 var->yoffset = 0;721 var->pixclock = mode->pixclock;722 var->left_margin = mode->left_margin;723 var->right_margin = mode->right_margin;724 var->upper_margin = mode->upper_margin;725 var->lower_margin = mode->lower_margin;726 var->hsync_len = mode->hsync_len;727 var->vsync_len = mode->vsync_len;728 var->sync = mode->sync;729 var->vmode = mode->vmode;730}731 732#ifdef CONFIG_PPC_PSERIES733static int is_powerblade(const char *model)734{735 struct device_node *root;736 const char* cp;737 int len, l, rc = 0;738 739 root = of_find_node_by_path("/");740 if (root && model) {741 l = strlen(model);742 cp = of_get_property(root, "model", &len);743 if (cp)744 rc = memcmp(model, cp, min(len, l)) == 0;745 of_node_put(root);746 }747 return rc;748}749#endif750 751/*752 * Build the modedb for head 1 (head 2 will come later), check panel infos753 * from either BIOS or EDID, and pick up the default mode754 */755void radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option)756{757 struct fb_info * info = rinfo->info;758 int has_default_mode = 0;759 760 /*761 * Fill default var first762 */763 info->var = radeonfb_default_var;764 INIT_LIST_HEAD(&info->modelist);765 766 /*767 * First check out what BIOS has to say768 */769 if (rinfo->mon1_type == MT_LCD)770 radeon_get_panel_info_BIOS(rinfo);771 772 /*773 * Parse EDID detailed timings and deduce panel infos if any. Right now774 * we only deal with first entry returned by parse_EDID, we may do better775 * some day...776 */777 if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type != MT_CRT778 && rinfo->mon1_EDID) {779 struct fb_var_screeninfo var;780 pr_debug("Parsing EDID data for panel info\n");781 if (fb_parse_edid(rinfo->mon1_EDID, &var) == 0) {782 if (var.xres >= rinfo->panel_info.xres &&783 var.yres >= rinfo->panel_info.yres)784 radeon_var_to_panel_info(rinfo, &var);785 }786 }787 788 /*789 * Do any additional platform/arch fixups to the panel infos790 */791 radeon_fixup_panel_info(rinfo);792 793 /*794 * If we have some valid panel infos, we setup the default mode based on795 * those796 */797 if (rinfo->mon1_type != MT_CRT && rinfo->panel_info.valid) {798 struct fb_var_screeninfo *var = &info->var;799 800 pr_debug("Setting up default mode based on panel info\n");801 var->xres = rinfo->panel_info.xres;802 var->yres = rinfo->panel_info.yres;803 var->xres_virtual = rinfo->panel_info.xres;804 var->yres_virtual = rinfo->panel_info.yres;805 var->xoffset = var->yoffset = 0;806 var->bits_per_pixel = 8;807 var->pixclock = 100000000 / rinfo->panel_info.clock;808 var->left_margin = (rinfo->panel_info.hblank - rinfo->panel_info.hOver_plus809 - rinfo->panel_info.hSync_width);810 var->right_margin = rinfo->panel_info.hOver_plus;811 var->upper_margin = (rinfo->panel_info.vblank - rinfo->panel_info.vOver_plus812 - rinfo->panel_info.vSync_width);813 var->lower_margin = rinfo->panel_info.vOver_plus;814 var->hsync_len = rinfo->panel_info.hSync_width;815 var->vsync_len = rinfo->panel_info.vSync_width;816 var->sync = 0;817 if (rinfo->panel_info.hAct_high)818 var->sync |= FB_SYNC_HOR_HIGH_ACT;819 if (rinfo->panel_info.vAct_high)820 var->sync |= FB_SYNC_VERT_HIGH_ACT;821 var->vmode = 0;822 has_default_mode = 1;823 }824 825 /*826 * Now build modedb from EDID827 */828 if (rinfo->mon1_EDID) {829 fb_edid_to_monspecs(rinfo->mon1_EDID, &info->monspecs);830 fb_videomode_to_modelist(info->monspecs.modedb,831 info->monspecs.modedb_len,832 &info->modelist);833 rinfo->mon1_modedb = info->monspecs.modedb;834 rinfo->mon1_dbsize = info->monspecs.modedb_len;835 }836 837 838 /*839 * Finally, if we don't have panel infos we need to figure some (or840 * we try to read it from card), we try to pick a default mode841 * and create some panel infos. Whatever...842 */843 if (rinfo->mon1_type != MT_CRT && !rinfo->panel_info.valid) {844 struct fb_videomode *modedb;845 int dbsize;846 char modename[32];847 848 pr_debug("Guessing panel info...\n");849 if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {850 u32 tmp = INREG(FP_HORZ_STRETCH) & HORZ_PANEL_SIZE;851 rinfo->panel_info.xres = ((tmp >> HORZ_PANEL_SHIFT) + 1) * 8;852 tmp = INREG(FP_VERT_STRETCH) & VERT_PANEL_SIZE;853 rinfo->panel_info.yres = (tmp >> VERT_PANEL_SHIFT) + 1;854 }855 if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) {856 printk(KERN_WARNING "radeonfb: Can't find panel size, going back to CRT\n");857 rinfo->mon1_type = MT_CRT;858 goto pickup_default;859 }860 printk(KERN_WARNING "radeonfb: Assuming panel size %dx%d\n",861 rinfo->panel_info.xres, rinfo->panel_info.yres);862 modedb = rinfo->mon1_modedb;863 dbsize = rinfo->mon1_dbsize;864 snprintf(modename, 31, "%dx%d", rinfo->panel_info.xres, rinfo->panel_info.yres);865 if (fb_find_mode(&info->var, info, modename,866 modedb, dbsize, NULL, 8) == 0) {867 printk(KERN_WARNING "radeonfb: Can't find mode for panel size, going back to CRT\n");868 rinfo->mon1_type = MT_CRT;869 goto pickup_default;870 }871 has_default_mode = 1;872 radeon_var_to_panel_info(rinfo, &info->var);873 }874 875 pickup_default:876 /*877 * Apply passed-in mode option if any878 */879 if (mode_option) {880 if (fb_find_mode(&info->var, info, mode_option,881 info->monspecs.modedb,882 info->monspecs.modedb_len, NULL, 8) != 0)883 has_default_mode = 1;884 }885 886#ifdef CONFIG_PPC_PSERIES887 if (!has_default_mode && (888 is_powerblade("IBM,8842") || /* JS20 */889 is_powerblade("IBM,8844") || /* JS21 */890 is_powerblade("IBM,7998") || /* JS12/JS21/JS22 */891 is_powerblade("IBM,0792") || /* QS21 */892 is_powerblade("IBM,0793") /* QS22 */893 )) {894 printk("Falling back to 800x600 on JSxx hardware\n");895 if (fb_find_mode(&info->var, info, "800x600@60",896 info->monspecs.modedb,897 info->monspecs.modedb_len, NULL, 8) != 0)898 has_default_mode = 1;899 }900#endif901 902 /*903 * Still no mode, let's pick up a default from the db904 */905 if (!has_default_mode && info->monspecs.modedb != NULL) {906 struct fb_monspecs *specs = &info->monspecs;907 struct fb_videomode *modedb = NULL;908 909 /* get preferred timing */910 if (specs->misc & FB_MISC_1ST_DETAIL) {911 int i;912 913 for (i = 0; i < specs->modedb_len; i++) {914 if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {915 modedb = &specs->modedb[i];916 break;917 }918 }919 } else {920 /* otherwise, get first mode in database */921 modedb = &specs->modedb[0];922 }923 if (modedb != NULL) {924 info->var.bits_per_pixel = 8;925 radeon_videomode_to_var(&info->var, modedb);926 has_default_mode = 1;927 }928 }929 if (1) {930 struct fb_videomode mode;931 /* Make sure that whatever mode got selected is actually in the932 * modelist or the kernel may die933 */934 fb_var_to_videomode(&mode, &info->var);935 fb_add_videomode(&mode, &info->modelist);936 }937}938 939/*940 * The code below is used to pick up a mode in check_var and941 * set_var. It should be made generic942 */943 944/*945 * This is used when looking for modes. We assign a "distance" value946 * to a mode in the modedb depending how "close" it is from what we947 * are looking for.948 * Currently, we don't compare that much, we could do better but949 * the current fbcon doesn't quite mind ;)950 */951static int radeon_compare_modes(const struct fb_var_screeninfo *var,952 const struct fb_videomode *mode)953{954 int distance = 0;955 956 distance = mode->yres - var->yres;957 distance += (mode->xres - var->xres)/2;958 return distance;959}960 961/*962 * This function is called by check_var, it gets the passed in mode parameter, and963 * outputs a valid mode matching the passed-in one as closely as possible.964 * We need something better ultimately. Things like fbcon basically pass us out965 * current mode with xres/yres hacked, while things like XFree will actually966 * produce a full timing that we should respect as much as possible.967 *968 * This is why I added the FB_ACTIVATE_FIND that is used by fbcon. Without this,969 * we do a simple spec match, that's all. With it, we actually look for a mode in970 * either our monitor modedb or the vesa one if none971 *972 */973int radeon_match_mode(struct radeonfb_info *rinfo,974 struct fb_var_screeninfo *dest,975 const struct fb_var_screeninfo *src)976{977 const struct fb_videomode *db = vesa_modes;978 int i, dbsize = 34;979 int has_rmx, native_db = 0;980 int distance = INT_MAX;981 const struct fb_videomode *candidate = NULL;982 983 /* Start with a copy of the requested mode */984 memcpy(dest, src, sizeof(struct fb_var_screeninfo));985 986 /* Check if we have a modedb built from EDID */987 if (rinfo->mon1_modedb) {988 db = rinfo->mon1_modedb;989 dbsize = rinfo->mon1_dbsize;990 native_db = 1;991 }992 993 /* Check if we have a scaler allowing any fancy mode */994 has_rmx = rinfo->mon1_type == MT_LCD || rinfo->mon1_type == MT_DFP;995 996 /* If we have a scaler and are passed FB_ACTIVATE_TEST or997 * FB_ACTIVATE_NOW, just do basic checking and return if the998 * mode match999 */1000 if ((src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST ||1001 (src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {1002 /* We don't have an RMX, validate timings. If we don't have1003 * monspecs, we should be paranoid and not let use go above1004 * 640x480-60, but I assume userland knows what it's doing here1005 * (though I may be proven wrong...)1006 */1007 if (has_rmx == 0 && rinfo->mon1_modedb)1008 if (fb_validate_mode((struct fb_var_screeninfo *)src, rinfo->info))1009 return -EINVAL;1010 return 0;1011 }1012 1013 /* Now look for a mode in the database */1014 while (db) {1015 for (i = 0; i < dbsize; i++) {1016 int d;1017 1018 if (db[i].yres < src->yres)1019 continue; 1020 if (db[i].xres < src->xres)1021 continue;1022 d = radeon_compare_modes(src, &db[i]);1023 /* If the new mode is at least as good as the previous one,1024 * then it's our new candidate1025 */1026 if (d < distance) {1027 candidate = &db[i];1028 distance = d;1029 }1030 }1031 db = NULL;1032 /* If we have a scaler, we allow any mode from the database */1033 if (native_db && has_rmx) {1034 db = vesa_modes;1035 dbsize = 34;1036 native_db = 0;1037 }1038 }1039 1040 /* If we have found a match, return it */1041 if (candidate != NULL) {1042 radeon_videomode_to_var(dest, candidate);1043 return 0;1044 }1045 1046 /* If we haven't and don't have a scaler, fail */1047 if (!has_rmx)1048 return -EINVAL;1049 1050 return 0;1051}1052