/* * Try to find monitor informations & EDID data out of the Open Firmware * device-tree. This also contains some "hacks" to work around a few machine * 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, int hdno) { static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID2", NULL }; u8 *pedid = NULL; u8 *pmt = NULL; u8 *tmp; int i, mt = MT_NONE; RTRACE("analyzing OF properties...\n"); pmt = (u8 *)get_property(dp, "display-type", NULL); if (!pmt) return MT_NONE; 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, "NONE") != 0) printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n", pmt); return MT_NONE; } for (i = 0; propnames[i] != NULL; ++i) { pedid = (u8 *)get_property(dp, propnames[i], NULL); if (pedid != NULL) break; } /* We didn't find the EDID in the leaf node, some cards will actually * put EDID1/EDID2 in the parent, look for these (typically M6 tipb). * single-head cards have hdno == -1 and skip this step */ if (pedid == NULL && dp->parent && (hdno != -1)) pedid = get_property(dp->parent, (hdno == 0) ? "EDID1" : "EDID2", NULL); if (pedid == NULL && dp->parent && (hdno == 0)) pedid = get_property(dp->parent, "EDID", NULL); if (pedid == NULL) return mt; tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL); if (!tmp) return mt; memcpy(tmp, pedid, EDID_LENGTH); *out_EDID = tmp; return mt; }
static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no, u8 **out_EDID) { struct device_node *dp; RTRACE("radeon_probe_OF_head\n"); dp = rinfo->of_node; while (dp == NULL) return MT_NONE; if (rinfo->has_CRTC2) { char *pname; int len, second = 0; dp = dp->child; do { if (!dp) return MT_NONE; pname = (char *)get_property(dp, "name", NULL); if (!pname) return MT_NONE; 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); second = 1; dp = dp->sibling; } while(!second); } else { if (head_no > 0) return MT_NONE; return radeon_parse_montype_prop(dp, out_EDID, -1); } return MT_NONE; }
SEXP attribute_hidden do_retracemem(SEXP call, SEXP op, SEXP args, SEXP rho) { #ifdef R_MEMORY_PROFILING SEXP object, previous, ans, argList; char buffer[21]; static SEXP do_retracemem_formals = NULL; if (do_retracemem_formals == NULL) do_retracemem_formals = allocFormalsList2(install("x"), R_PreviousSymbol); PROTECT(argList = matchArgs(do_retracemem_formals, args, call)); if(CAR(argList) == R_MissingArg) SETCAR(argList, R_NilValue); if(CADR(argList) == R_MissingArg) SETCAR(CDR(argList), R_NilValue); object = CAR(argList); if (TYPEOF(object) == CLOSXP || TYPEOF(object) == BUILTINSXP || TYPEOF(object) == SPECIALSXP) errorcall(call, _("argument must not be a function")); previous = CADR(argList); if(!isNull(previous) && !isString(previous)) errorcall(call, _("invalid '%s' argument"), "previous"); if (RTRACE(object)) { snprintf(buffer, 21, "<%p>", (void *) object); ans = mkString(buffer); } else { R_Visible = 0; ans = R_NilValue; } if (previous != R_NilValue){ SET_RTRACE(object, 1); if (R_current_trace_state()) { /* FIXME: previous will have <0x....> whereas other values are without the < > */ Rprintf("tracemem[%s -> %p]: ", translateChar(STRING_ELT(previous, 0)), (void *) object); memtrace_stack_dump(); } } UNPROTECT(1); return ans; #else R_Visible = 0; /* for consistency with other case */ return R_NilValue; #endif }
SEXP duplicate(SEXP s){ SEXP t; #ifdef R_PROFILING duplicate_counter++; #endif t = duplicate1(s, TRUE); #ifdef R_MEMORY_PROFILING if (RTRACE(s) && !(TYPEOF(s) == CLOSXP || TYPEOF(s) == BUILTINSXP || TYPEOF(s) == SPECIALSXP || TYPEOF(s) == PROMSXP || TYPEOF(s) == ENVSXP)){ memtrace_report(s,t); SET_RTRACE(t,1); } #endif return t; }
SEXP attribute_hidden do_untracemem(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP object; checkArity(op, args); check1arg(args, call, "x"); object=CAR(args); if (TYPEOF(object) == CLOSXP || TYPEOF(object) == BUILTINSXP || TYPEOF(object) == SPECIALSXP) errorcall(call, _("argument must not be a function")); if (RTRACE(object)) SET_RTRACE(object, 0); return R_NilValue; }
SEXP attribute_hidden do_untracemem(SEXP call, SEXP op, SEXP args, SEXP rho) { #ifdef R_MEMORY_PROFILING SEXP object; checkArity(op, args); check1arg(args, call, "x"); object=CAR(args); if (TYPEOF(object) == CLOSXP || TYPEOF(object) == BUILTINSXP || TYPEOF(object) == SPECIALSXP) errorcall(call, _("argument must not be a function")); if (RTRACE(object)) SET_RTRACE(object, 0); #else errorcall(call, _("R was not compiled with support for memory profiling")); #endif return R_NilValue; }
static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo) { unsigned long tmp, tmp0; char stmp[30]; int i; if (!rinfo->bios_seg) return 0; if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) { printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n"); rinfo->panel_info.pwr_delay = 200; return 0; } for(i=0; i<24; i++) stmp[i] = BIOS_IN8(tmp+i+1); stmp[24] = 0; printk("radeonfb: panel ID string: %s\n", stmp); 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.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 */ rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46); rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48); rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49); if (rinfo->panel_info.ref_divider != 0 && rinfo->panel_info.fbk_divider > 3) { rinfo->panel_info.use_bios_dividers = 1; printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n"); RTRACE("ref_divider = %x\n", rinfo->panel_info.ref_divider); RTRACE("post_divider = %x\n", rinfo->panel_info.post_divider); RTRACE("fbk_divider = %x\n", rinfo->panel_info.fbk_divider); } RTRACE("Scanning BIOS table ...\n"); for(i=0; i<32; i++) { tmp0 = BIOS_IN16(tmp+64+i*2); if (tmp0 == 0) break; RTRACE(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2)); if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) && (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) { rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8; rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) - BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff; rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8; rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26); rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26); rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11; rinfo->panel_info.clock = BIOS_IN16(tmp0+9); /* 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; RTRACE("Found panel in BIOS table:\n"); RTRACE(" hblank: %d\n", rinfo->panel_info.hblank); RTRACE(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus); RTRACE(" hSync_width: %d\n", rinfo->panel_info.hSync_width); RTRACE(" vblank: %d\n", rinfo->panel_info.vblank); RTRACE(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus); RTRACE(" vSync_width: %d\n", rinfo->panel_info.vSync_width); RTRACE(" clock: %d\n", rinfo->panel_info.clock); return 1; } }
int ATIRadeon::MapROM( int nFd, PCI_Info_s *dev ) { uint16 dptr; uint8 rom_type; unsigned long rom_base_phys; /* If this is a primary card, there is a shadow copy of the * ROM somewhere in the first meg (presumably at 0xc0000) */ /* Fix from ATI for problem with Radeon hardware not leaving ROM enabled */ unsigned int temp; temp = INREG(MPP_TB_CONFIG); temp &= 0x00ffffffu; temp |= 0x04 << 24; OUTREG(MPP_TB_CONFIG, temp); temp = INREG(MPP_TB_CONFIG); rom_base_phys = RADEON_I386_ROM_ADDRESS; pci_gfx_write_config( nFd, dev->nBus, dev->nDevice, dev->nFunction, PCI_ROM_BASE, 4, RADEON_I386_ROM_ENABLE ); RTRACE("Radeon :: ROM base address %x\n", (uint) rom_base_phys); RTRACE("Radeon :: ROM size %x\n", (uint) get_pci_rom_memory_size(nFd, dev)); // map the ROM m_pROMBase = NULL; m_hROMArea = create_area ("radeon_rom", (void **)&m_pROMBase, get_pci_rom_memory_size(nFd, dev), AREA_FULL_ACCESS, AREA_NO_LOCK); if( m_hROMArea < 0 ) { dbprintf ("Radeon :: failed to create ROM area\n"); return false; } if( remap_area (m_hROMArea, (void *)((rom_base_phys))) < 0 ) { printf("Radeon :: failed to map ROM area (%d)\n", m_hROMArea); return false; } rinfo.bios_seg = m_pROMBase; /* Very simple test to make sure it appeared */ if (BIOS_IN16(0) != 0xaa55) { dbprintf("Radeon :: Warning: Invalid ROM signature %x should be 0xaa55\n", BIOS_IN16(0)); goto failed; } /* Look for the PCI data to check the ROM type */ dptr = BIOS_IN16(0x18); /* Check the PCI data signature. If it's wrong, we still assume a normal x86 ROM * for now, until I've verified this works everywhere. The goal here is more * 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 * relative start of ROM, but so far, I never found a dual-image ATI card * * typedef struct { * uint32 signature; + 0x00 * uint16 vendor; + 0x04 * uint16 device; + 0x06 * uint16 reserved_1; + 0x08 * uint16 dlen; + 0x0a * uint8 drevision; + 0x0c * uint8 class_hi; + 0x0d * uint16 class_lo; + 0x0e * uint16 ilen; + 0x10 * uint16 irevision; + 0x12 * uint8 type; + 0x14 * uint8 indicator; + 0x15 * uint16 reserved_2; + 0x16 * } pci_data_t; */ if (BIOS_IN32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) { dbprintf("Radeon :: Warning: PCI DATA signature in ROM incorrect: %08x\n", BIOS_IN32(dptr)); goto anyway; } rom_type = BIOS_IN8(dptr + 0x14); switch(rom_type) { case 0: dbprintf("Radeon :: Found Intel x86 BIOS ROM Image\n"); break; case 1: dbprintf("Radeon :: Found Open Firmware ROM Image\n"); goto failed; case 2: dbprintf("Radeon :: Found HP PA-RISC ROM Image\n"); goto failed; default: dbprintf("Radeon :: Found unknown type %d ROM Image\n", rom_type); goto failed; } anyway: /* Locate the flat panel infos, do some sanity checking !!! */ rinfo.fp_bios_start = BIOS_IN16(0x48); /* Check for ATOM BIOS */ dptr = rinfo.fp_bios_start + 4; if ((BIOS_IN8(dptr) == 'A' && BIOS_IN8(dptr+1) == 'T' && BIOS_IN8(dptr+2) == 'O' && BIOS_IN8(dptr+3) == 'M') || (BIOS_IN8(dptr) == 'M' && BIOS_IN8(dptr+1) == 'O' && BIOS_IN8(dptr+2) == 'T' && BIOS_IN8(dptr+3) == 'A')) rinfo.bios_type = bios_atom; else rinfo.bios_type = bios_legacy; if (rinfo.bios_type == bios_atom) rinfo.fp_atom_bios_start = BIOS_IN16 (rinfo.fp_bios_start + 32); dbprintf( "Radeon :: %s BIOS detected\n", (rinfo.bios_type == bios_atom) ? "ATOM" : "Legacy" ); return 0; failed: rinfo.bios_seg = NULL; return -ENXIO; }