fbmon.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  1. /*
  2. * linux/drivers/video/fbmon.c
  3. *
  4. * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
  5. *
  6. * Credits:
  7. *
  8. * The EDID Parser is a conglomeration from the following sources:
  9. *
  10. * 1. SciTech SNAP Graphics Architecture
  11. * Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
  12. *
  13. * 2. XFree86 4.3.0, interpret_edid.c
  14. * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
  15. *
  16. * 3. John Fremlin <vii@users.sourceforge.net> and
  17. * Ani Joshi <ajoshi@unixbox.com>
  18. *
  19. * Generalized Timing Formula is derived from:
  20. *
  21. * GTF Spreadsheet by Andy Morrish (1/5/97)
  22. * available at http://www.vesa.org
  23. *
  24. * This file is subject to the terms and conditions of the GNU General Public
  25. * License. See the file COPYING in the main directory of this archive
  26. * for more details.
  27. *
  28. */
  29. #include <linux/tty.h>
  30. #include <linux/fb.h>
  31. #include <linux/module.h>
  32. #include <video/edid.h>
  33. #ifdef CONFIG_PPC_OF
  34. #include <linux/pci.h>
  35. #include <asm/prom.h>
  36. #include <asm/pci-bridge.h>
  37. #endif
  38. #include "edid.h"
  39. /*
  40. * EDID parser
  41. */
  42. #undef DEBUG /* define this for verbose EDID parsing output */
  43. #ifdef DEBUG
  44. #define DPRINTK(fmt, args...) printk(fmt,## args)
  45. #else
  46. #define DPRINTK(fmt, args...)
  47. #endif
  48. #define FBMON_FIX_HEADER 1
  49. #define FBMON_FIX_INPUT 2
  50. #ifdef CONFIG_FB_MODE_HELPERS
  51. struct broken_edid {
  52. u8 manufacturer[4];
  53. u32 model;
  54. u32 fix;
  55. };
  56. static struct broken_edid brokendb[] = {
  57. /* DEC FR-PCXAV-YZ */
  58. {
  59. .manufacturer = "DEC",
  60. .model = 0x073a,
  61. .fix = FBMON_FIX_HEADER,
  62. },
  63. /* ViewSonic PF775a */
  64. {
  65. .manufacturer = "VSC",
  66. .model = 0x5a44,
  67. .fix = FBMON_FIX_INPUT,
  68. },
  69. };
  70. static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
  71. 0xff, 0xff, 0xff, 0x00
  72. };
  73. static void copy_string(unsigned char *c, unsigned char *s)
  74. {
  75. int i;
  76. c = c + 5;
  77. for (i = 0; (i < 13 && *c != 0x0A); i++)
  78. *(s++) = *(c++);
  79. *s = 0;
  80. while (i-- && (*--s == 0x20)) *s = 0;
  81. }
  82. static int check_edid(unsigned char *edid)
  83. {
  84. unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
  85. unsigned char *b;
  86. u32 model;
  87. int i, fix = 0, ret = 0;
  88. manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
  89. manufacturer[1] = ((block[0] & 0x03) << 3) +
  90. ((block[1] & 0xe0) >> 5) + '@';
  91. manufacturer[2] = (block[1] & 0x1f) + '@';
  92. manufacturer[3] = 0;
  93. model = block[2] + (block[3] << 8);
  94. for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
  95. if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
  96. brokendb[i].model == model) {
  97. printk("fbmon: The EDID Block of "
  98. "Manufacturer: %s Model: 0x%x is known to "
  99. "be broken,\n", manufacturer, model);
  100. fix = brokendb[i].fix;
  101. break;
  102. }
  103. }
  104. switch (fix) {
  105. case FBMON_FIX_HEADER:
  106. for (i = 0; i < 8; i++) {
  107. if (edid[i] != edid_v1_header[i])
  108. ret = fix;
  109. }
  110. break;
  111. case FBMON_FIX_INPUT:
  112. b = edid + EDID_STRUCT_DISPLAY;
  113. /* Only if display is GTF capable will
  114. the input type be reset to analog */
  115. if (b[4] & 0x01 && b[0] & 0x80)
  116. ret = fix;
  117. break;
  118. }
  119. return ret;
  120. }
  121. static void fix_edid(unsigned char *edid, int fix)
  122. {
  123. unsigned char *b;
  124. switch (fix) {
  125. case FBMON_FIX_HEADER:
  126. printk("fbmon: trying a header reconstruct\n");
  127. memcpy(edid, edid_v1_header, 8);
  128. break;
  129. case FBMON_FIX_INPUT:
  130. printk("fbmon: trying to fix input type\n");
  131. b = edid + EDID_STRUCT_DISPLAY;
  132. b[0] &= ~0x80;
  133. edid[127] += 0x80;
  134. }
  135. }
  136. static int edid_checksum(unsigned char *edid)
  137. {
  138. unsigned char i, csum = 0, all_null = 0;
  139. int err = 0, fix = check_edid(edid);
  140. if (fix)
  141. fix_edid(edid, fix);
  142. for (i = 0; i < EDID_LENGTH; i++) {
  143. csum += edid[i];
  144. all_null |= edid[i];
  145. }
  146. if (csum == 0x00 && all_null) {
  147. /* checksum passed, everything's good */
  148. err = 1;
  149. }
  150. return err;
  151. }
  152. static int edid_check_header(unsigned char *edid)
  153. {
  154. int i, err = 1, fix = check_edid(edid);
  155. if (fix)
  156. fix_edid(edid, fix);
  157. for (i = 0; i < 8; i++) {
  158. if (edid[i] != edid_v1_header[i])
  159. err = 0;
  160. }
  161. return err;
  162. }
  163. static void parse_vendor_block(unsigned char *block, struct fb_monspecs *specs)
  164. {
  165. specs->manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
  166. specs->manufacturer[1] = ((block[0] & 0x03) << 3) +
  167. ((block[1] & 0xe0) >> 5) + '@';
  168. specs->manufacturer[2] = (block[1] & 0x1f) + '@';
  169. specs->manufacturer[3] = 0;
  170. specs->model = block[2] + (block[3] << 8);
  171. specs->serial = block[4] + (block[5] << 8) +
  172. (block[6] << 16) + (block[7] << 24);
  173. specs->year = block[9] + 1990;
  174. specs->week = block[8];
  175. DPRINTK(" Manufacturer: %s\n", specs->manufacturer);
  176. DPRINTK(" Model: %x\n", specs->model);
  177. DPRINTK(" Serial#: %u\n", specs->serial);
  178. DPRINTK(" Year: %u Week %u\n", specs->year, specs->week);
  179. }
  180. static void get_dpms_capabilities(unsigned char flags,
  181. struct fb_monspecs *specs)
  182. {
  183. specs->dpms = 0;
  184. if (flags & DPMS_ACTIVE_OFF)
  185. specs->dpms |= FB_DPMS_ACTIVE_OFF;
  186. if (flags & DPMS_SUSPEND)
  187. specs->dpms |= FB_DPMS_SUSPEND;
  188. if (flags & DPMS_STANDBY)
  189. specs->dpms |= FB_DPMS_STANDBY;
  190. DPRINTK(" DPMS: Active %s, Suspend %s, Standby %s\n",
  191. (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
  192. (flags & DPMS_SUSPEND) ? "yes" : "no",
  193. (flags & DPMS_STANDBY) ? "yes" : "no");
  194. }
  195. static void get_chroma(unsigned char *block, struct fb_monspecs *specs)
  196. {
  197. int tmp;
  198. DPRINTK(" Chroma\n");
  199. /* Chromaticity data */
  200. tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2);
  201. tmp *= 1000;
  202. tmp += 512;
  203. specs->chroma.redx = tmp/1024;
  204. DPRINTK(" RedX: 0.%03d ", specs->chroma.redx);
  205. tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2);
  206. tmp *= 1000;
  207. tmp += 512;
  208. specs->chroma.redy = tmp/1024;
  209. DPRINTK("RedY: 0.%03d\n", specs->chroma.redy);
  210. tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2);
  211. tmp *= 1000;
  212. tmp += 512;
  213. specs->chroma.greenx = tmp/1024;
  214. DPRINTK(" GreenX: 0.%03d ", specs->chroma.greenx);
  215. tmp = (block[5] & 3) | (block[0xa] << 2);
  216. tmp *= 1000;
  217. tmp += 512;
  218. specs->chroma.greeny = tmp/1024;
  219. DPRINTK("GreenY: 0.%03d\n", specs->chroma.greeny);
  220. tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2);
  221. tmp *= 1000;
  222. tmp += 512;
  223. specs->chroma.bluex = tmp/1024;
  224. DPRINTK(" BlueX: 0.%03d ", specs->chroma.bluex);
  225. tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2);
  226. tmp *= 1000;
  227. tmp += 512;
  228. specs->chroma.bluey = tmp/1024;
  229. DPRINTK("BlueY: 0.%03d\n", specs->chroma.bluey);
  230. tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
  231. tmp *= 1000;
  232. tmp += 512;
  233. specs->chroma.whitex = tmp/1024;
  234. DPRINTK(" WhiteX: 0.%03d ", specs->chroma.whitex);
  235. tmp = (block[6] & 3) | (block[0xe] << 2);
  236. tmp *= 1000;
  237. tmp += 512;
  238. specs->chroma.whitey = tmp/1024;
  239. DPRINTK("WhiteY: 0.%03d\n", specs->chroma.whitey);
  240. }
  241. static int edid_is_serial_block(unsigned char *block)
  242. {
  243. if ((block[0] == 0x00) && (block[1] == 0x00) &&
  244. (block[2] == 0x00) && (block[3] == 0xff) &&
  245. (block[4] == 0x00))
  246. return 1;
  247. else
  248. return 0;
  249. }
  250. static int edid_is_ascii_block(unsigned char *block)
  251. {
  252. if ((block[0] == 0x00) && (block[1] == 0x00) &&
  253. (block[2] == 0x00) && (block[3] == 0xfe) &&
  254. (block[4] == 0x00))
  255. return 1;
  256. else
  257. return 0;
  258. }
  259. static int edid_is_limits_block(unsigned char *block)
  260. {
  261. if ((block[0] == 0x00) && (block[1] == 0x00) &&
  262. (block[2] == 0x00) && (block[3] == 0xfd) &&
  263. (block[4] == 0x00))
  264. return 1;
  265. else
  266. return 0;
  267. }
  268. static int edid_is_monitor_block(unsigned char *block)
  269. {
  270. if ((block[0] == 0x00) && (block[1] == 0x00) &&
  271. (block[2] == 0x00) && (block[3] == 0xfc) &&
  272. (block[4] == 0x00))
  273. return 1;
  274. else
  275. return 0;
  276. }
  277. static void calc_mode_timings(int xres, int yres, int refresh,
  278. struct fb_videomode *mode)
  279. {
  280. struct fb_var_screeninfo var;
  281. struct fb_info info;
  282. memset(&var, 0, sizeof(struct fb_var_screeninfo));
  283. var.xres = xres;
  284. var.yres = yres;
  285. fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
  286. refresh, &var, &info);
  287. mode->xres = xres;
  288. mode->yres = yres;
  289. mode->pixclock = var.pixclock;
  290. mode->refresh = refresh;
  291. mode->left_margin = var.left_margin;
  292. mode->right_margin = var.right_margin;
  293. mode->upper_margin = var.upper_margin;
  294. mode->lower_margin = var.lower_margin;
  295. mode->hsync_len = var.hsync_len;
  296. mode->vsync_len = var.vsync_len;
  297. mode->vmode = 0;
  298. mode->sync = 0;
  299. }
  300. static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
  301. {
  302. int num = 0;
  303. unsigned char c;
  304. c = block[0];
  305. if (c&0x80) {
  306. calc_mode_timings(720, 400, 70, &mode[num]);
  307. mode[num++].flag = FB_MODE_IS_CALCULATED;
  308. DPRINTK(" 720x400@70Hz\n");
  309. }
  310. if (c&0x40) {
  311. calc_mode_timings(720, 400, 88, &mode[num]);
  312. mode[num++].flag = FB_MODE_IS_CALCULATED;
  313. DPRINTK(" 720x400@88Hz\n");
  314. }
  315. if (c&0x20) {
  316. mode[num++] = vesa_modes[3];
  317. DPRINTK(" 640x480@60Hz\n");
  318. }
  319. if (c&0x10) {
  320. calc_mode_timings(640, 480, 67, &mode[num]);
  321. mode[num++].flag = FB_MODE_IS_CALCULATED;
  322. DPRINTK(" 640x480@67Hz\n");
  323. }
  324. if (c&0x08) {
  325. mode[num++] = vesa_modes[4];
  326. DPRINTK(" 640x480@72Hz\n");
  327. }
  328. if (c&0x04) {
  329. mode[num++] = vesa_modes[5];
  330. DPRINTK(" 640x480@75Hz\n");
  331. }
  332. if (c&0x02) {
  333. mode[num++] = vesa_modes[7];
  334. DPRINTK(" 800x600@56Hz\n");
  335. }
  336. if (c&0x01) {
  337. mode[num++] = vesa_modes[8];
  338. DPRINTK(" 800x600@60Hz\n");
  339. }
  340. c = block[1];
  341. if (c&0x80) {
  342. mode[num++] = vesa_modes[9];
  343. DPRINTK(" 800x600@72Hz\n");
  344. }
  345. if (c&0x40) {
  346. mode[num++] = vesa_modes[10];
  347. DPRINTK(" 800x600@75Hz\n");
  348. }
  349. if (c&0x20) {
  350. calc_mode_timings(832, 624, 75, &mode[num]);
  351. mode[num++].flag = FB_MODE_IS_CALCULATED;
  352. DPRINTK(" 832x624@75Hz\n");
  353. }
  354. if (c&0x10) {
  355. mode[num++] = vesa_modes[12];
  356. DPRINTK(" 1024x768@87Hz Interlaced\n");
  357. }
  358. if (c&0x08) {
  359. mode[num++] = vesa_modes[13];
  360. DPRINTK(" 1024x768@60Hz\n");
  361. }
  362. if (c&0x04) {
  363. mode[num++] = vesa_modes[14];
  364. DPRINTK(" 1024x768@70Hz\n");
  365. }
  366. if (c&0x02) {
  367. mode[num++] = vesa_modes[15];
  368. DPRINTK(" 1024x768@75Hz\n");
  369. }
  370. if (c&0x01) {
  371. mode[num++] = vesa_modes[21];
  372. DPRINTK(" 1280x1024@75Hz\n");
  373. }
  374. c = block[2];
  375. if (c&0x80) {
  376. mode[num++] = vesa_modes[17];
  377. DPRINTK(" 1152x870@75Hz\n");
  378. }
  379. DPRINTK(" Manufacturer's mask: %x\n",c&0x7F);
  380. return num;
  381. }
  382. static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
  383. {
  384. int xres, yres = 0, refresh, ratio, i;
  385. xres = (block[0] + 31) * 8;
  386. if (xres <= 256)
  387. return 0;
  388. ratio = (block[1] & 0xc0) >> 6;
  389. switch (ratio) {
  390. case 0:
  391. yres = xres;
  392. break;
  393. case 1:
  394. yres = (xres * 3)/4;
  395. break;
  396. case 2:
  397. yres = (xres * 4)/5;
  398. break;
  399. case 3:
  400. yres = (xres * 9)/16;
  401. break;
  402. }
  403. refresh = (block[1] & 0x3f) + 60;
  404. DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh);
  405. for (i = 0; i < VESA_MODEDB_SIZE; i++) {
  406. if (vesa_modes[i].xres == xres &&
  407. vesa_modes[i].yres == yres &&
  408. vesa_modes[i].refresh == refresh) {
  409. *mode = vesa_modes[i];
  410. mode->flag |= FB_MODE_IS_STANDARD;
  411. return 1;
  412. }
  413. }
  414. calc_mode_timings(xres, yres, refresh, mode);
  415. return 1;
  416. }
  417. static int get_dst_timing(unsigned char *block,
  418. struct fb_videomode *mode)
  419. {
  420. int j, num = 0;
  421. for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE)
  422. num += get_std_timing(block, &mode[num]);
  423. return num;
  424. }
  425. static void get_detailed_timing(unsigned char *block,
  426. struct fb_videomode *mode)
  427. {
  428. mode->xres = H_ACTIVE;
  429. mode->yres = V_ACTIVE;
  430. mode->pixclock = PIXEL_CLOCK;
  431. mode->pixclock /= 1000;
  432. mode->pixclock = KHZ2PICOS(mode->pixclock);
  433. mode->right_margin = H_SYNC_OFFSET;
  434. mode->left_margin = (H_ACTIVE + H_BLANKING) -
  435. (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
  436. mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
  437. V_SYNC_WIDTH;
  438. mode->lower_margin = V_SYNC_OFFSET;
  439. mode->hsync_len = H_SYNC_WIDTH;
  440. mode->vsync_len = V_SYNC_WIDTH;
  441. if (HSYNC_POSITIVE)
  442. mode->sync |= FB_SYNC_HOR_HIGH_ACT;
  443. if (VSYNC_POSITIVE)
  444. mode->sync |= FB_SYNC_VERT_HIGH_ACT;
  445. mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
  446. (V_ACTIVE + V_BLANKING));
  447. mode->vmode = 0;
  448. mode->flag = FB_MODE_IS_DETAILED;
  449. DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
  450. DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
  451. H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
  452. DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
  453. V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
  454. DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
  455. (VSYNC_POSITIVE) ? "+" : "-");
  456. }
  457. /**
  458. * fb_create_modedb - create video mode database
  459. * @edid: EDID data
  460. * @dbsize: database size
  461. *
  462. * RETURNS: struct fb_videomode, @dbsize contains length of database
  463. *
  464. * DESCRIPTION:
  465. * This function builds a mode database using the contents of the EDID
  466. * data
  467. */
  468. static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
  469. {
  470. struct fb_videomode *mode, *m;
  471. unsigned char *block;
  472. int num = 0, i;
  473. mode = kmalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
  474. if (mode == NULL)
  475. return NULL;
  476. memset(mode, 0, 50 * sizeof(struct fb_videomode));
  477. if (edid == NULL || !edid_checksum(edid) ||
  478. !edid_check_header(edid)) {
  479. kfree(mode);
  480. return NULL;
  481. }
  482. *dbsize = 0;
  483. DPRINTK(" Supported VESA Modes\n");
  484. block = edid + ESTABLISHED_TIMING_1;
  485. num += get_est_timing(block, &mode[num]);
  486. DPRINTK(" Standard Timings\n");
  487. block = edid + STD_TIMING_DESCRIPTIONS_START;
  488. for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
  489. num += get_std_timing(block, &mode[num]);
  490. DPRINTK(" Detailed Timings\n");
  491. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  492. for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
  493. int first = 1;
  494. if (block[0] == 0x00 && block[1] == 0x00) {
  495. if (block[3] == 0xfa) {
  496. num += get_dst_timing(block + 5, &mode[num]);
  497. }
  498. } else {
  499. get_detailed_timing(block, &mode[num]);
  500. if (first) {
  501. mode[num].flag |= FB_MODE_IS_FIRST;
  502. first = 0;
  503. }
  504. num++;
  505. }
  506. }
  507. /* Yikes, EDID data is totally useless */
  508. if (!num) {
  509. kfree(mode);
  510. return NULL;
  511. }
  512. *dbsize = num;
  513. m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
  514. if (!m)
  515. return mode;
  516. memmove(m, mode, num * sizeof(struct fb_videomode));
  517. kfree(mode);
  518. return m;
  519. }
  520. /**
  521. * fb_destroy_modedb - destroys mode database
  522. * @modedb: mode database to destroy
  523. *
  524. * DESCRIPTION:
  525. * Destroy mode database created by fb_create_modedb
  526. */
  527. void fb_destroy_modedb(struct fb_videomode *modedb)
  528. {
  529. kfree(modedb);
  530. }
  531. static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
  532. {
  533. int i, retval = 1;
  534. unsigned char *block;
  535. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  536. DPRINTK(" Monitor Operating Limits: ");
  537. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  538. if (edid_is_limits_block(block)) {
  539. specs->hfmin = H_MIN_RATE * 1000;
  540. specs->hfmax = H_MAX_RATE * 1000;
  541. specs->vfmin = V_MIN_RATE;
  542. specs->vfmax = V_MAX_RATE;
  543. specs->dclkmax = MAX_PIXEL_CLOCK * 1000000;
  544. specs->gtf = (GTF_SUPPORT) ? 1 : 0;
  545. retval = 0;
  546. DPRINTK("From EDID\n");
  547. break;
  548. }
  549. }
  550. /* estimate monitor limits based on modes supported */
  551. if (retval) {
  552. struct fb_videomode *modes;
  553. int num_modes, i, hz, hscan, pixclock;
  554. modes = fb_create_modedb(edid, &num_modes);
  555. if (!modes) {
  556. DPRINTK("None Available\n");
  557. return 1;
  558. }
  559. retval = 0;
  560. for (i = 0; i < num_modes; i++) {
  561. hz = modes[i].refresh;
  562. pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
  563. hscan = (modes[i].yres * 105 * hz + 5000)/100;
  564. if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
  565. specs->dclkmax = pixclock;
  566. if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
  567. specs->dclkmin = pixclock;
  568. if (specs->hfmax == 0 || specs->hfmax < hscan)
  569. specs->hfmax = hscan;
  570. if (specs->hfmin == 0 || specs->hfmin > hscan)
  571. specs->hfmin = hscan;
  572. if (specs->vfmax == 0 || specs->vfmax < hz)
  573. specs->vfmax = hz;
  574. if (specs->vfmin == 0 || specs->vfmin > hz)
  575. specs->vfmin = hz;
  576. }
  577. DPRINTK("Extrapolated\n");
  578. fb_destroy_modedb(modes);
  579. }
  580. DPRINTK(" H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n",
  581. specs->hfmin/1000, specs->hfmax/1000, specs->vfmin,
  582. specs->vfmax, specs->dclkmax/1000000);
  583. return retval;
  584. }
  585. static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  586. {
  587. unsigned char c, *block;
  588. block = edid + EDID_STRUCT_DISPLAY;
  589. fb_get_monitor_limits(edid, specs);
  590. c = block[0] & 0x80;
  591. specs->input = 0;
  592. if (c) {
  593. specs->input |= FB_DISP_DDI;
  594. DPRINTK(" Digital Display Input");
  595. } else {
  596. DPRINTK(" Analog Display Input: Input Voltage - ");
  597. switch ((block[0] & 0x60) >> 5) {
  598. case 0:
  599. DPRINTK("0.700V/0.300V");
  600. specs->input |= FB_DISP_ANA_700_300;
  601. break;
  602. case 1:
  603. DPRINTK("0.714V/0.286V");
  604. specs->input |= FB_DISP_ANA_714_286;
  605. break;
  606. case 2:
  607. DPRINTK("1.000V/0.400V");
  608. specs->input |= FB_DISP_ANA_1000_400;
  609. break;
  610. case 3:
  611. DPRINTK("0.700V/0.000V");
  612. specs->input |= FB_DISP_ANA_700_000;
  613. break;
  614. }
  615. }
  616. DPRINTK("\n Sync: ");
  617. c = block[0] & 0x10;
  618. if (c)
  619. DPRINTK(" Configurable signal level\n");
  620. c = block[0] & 0x0f;
  621. specs->signal = 0;
  622. if (c & 0x10) {
  623. DPRINTK("Blank to Blank ");
  624. specs->signal |= FB_SIGNAL_BLANK_BLANK;
  625. }
  626. if (c & 0x08) {
  627. DPRINTK("Separate ");
  628. specs->signal |= FB_SIGNAL_SEPARATE;
  629. }
  630. if (c & 0x04) {
  631. DPRINTK("Composite ");
  632. specs->signal |= FB_SIGNAL_COMPOSITE;
  633. }
  634. if (c & 0x02) {
  635. DPRINTK("Sync on Green ");
  636. specs->signal |= FB_SIGNAL_SYNC_ON_GREEN;
  637. }
  638. if (c & 0x01) {
  639. DPRINTK("Serration on ");
  640. specs->signal |= FB_SIGNAL_SERRATION_ON;
  641. }
  642. DPRINTK("\n");
  643. specs->max_x = block[1];
  644. specs->max_y = block[2];
  645. DPRINTK(" Max H-size in cm: ");
  646. if (specs->max_x)
  647. DPRINTK("%d\n", specs->max_x);
  648. else
  649. DPRINTK("variable\n");
  650. DPRINTK(" Max V-size in cm: ");
  651. if (specs->max_y)
  652. DPRINTK("%d\n", specs->max_y);
  653. else
  654. DPRINTK("variable\n");
  655. c = block[3];
  656. specs->gamma = c+100;
  657. DPRINTK(" Gamma: ");
  658. DPRINTK("%d.%d\n", specs->gamma/100, specs->gamma % 100);
  659. get_dpms_capabilities(block[4], specs);
  660. switch ((block[4] & 0x18) >> 3) {
  661. case 0:
  662. DPRINTK(" Monochrome/Grayscale\n");
  663. specs->input |= FB_DISP_MONO;
  664. break;
  665. case 1:
  666. DPRINTK(" RGB Color Display\n");
  667. specs->input |= FB_DISP_RGB;
  668. break;
  669. case 2:
  670. DPRINTK(" Non-RGB Multicolor Display\n");
  671. specs->input |= FB_DISP_MULTI;
  672. break;
  673. default:
  674. DPRINTK(" Unknown\n");
  675. specs->input |= FB_DISP_UNKNOWN;
  676. break;
  677. }
  678. get_chroma(block, specs);
  679. specs->misc = 0;
  680. c = block[4] & 0x7;
  681. if (c & 0x04) {
  682. DPRINTK(" Default color format is primary\n");
  683. specs->misc |= FB_MISC_PRIM_COLOR;
  684. }
  685. if (c & 0x02) {
  686. DPRINTK(" First DETAILED Timing is preferred\n");
  687. specs->misc |= FB_MISC_1ST_DETAIL;
  688. }
  689. if (c & 0x01) {
  690. printk(" Display is GTF capable\n");
  691. specs->gtf = 1;
  692. }
  693. }
  694. static int edid_is_timing_block(unsigned char *block)
  695. {
  696. if ((block[0] != 0x00) || (block[1] != 0x00) ||
  697. (block[2] != 0x00) || (block[4] != 0x00))
  698. return 1;
  699. else
  700. return 0;
  701. }
  702. int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
  703. {
  704. int i;
  705. unsigned char *block;
  706. if (edid == NULL || var == NULL)
  707. return 1;
  708. if (!(edid_checksum(edid)))
  709. return 1;
  710. if (!(edid_check_header(edid)))
  711. return 1;
  712. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  713. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  714. if (edid_is_timing_block(block)) {
  715. var->xres = var->xres_virtual = H_ACTIVE;
  716. var->yres = var->yres_virtual = V_ACTIVE;
  717. var->height = var->width = -1;
  718. var->right_margin = H_SYNC_OFFSET;
  719. var->left_margin = (H_ACTIVE + H_BLANKING) -
  720. (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
  721. var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
  722. V_SYNC_WIDTH;
  723. var->lower_margin = V_SYNC_OFFSET;
  724. var->hsync_len = H_SYNC_WIDTH;
  725. var->vsync_len = V_SYNC_WIDTH;
  726. var->pixclock = PIXEL_CLOCK;
  727. var->pixclock /= 1000;
  728. var->pixclock = KHZ2PICOS(var->pixclock);
  729. if (HSYNC_POSITIVE)
  730. var->sync |= FB_SYNC_HOR_HIGH_ACT;
  731. if (VSYNC_POSITIVE)
  732. var->sync |= FB_SYNC_VERT_HIGH_ACT;
  733. return 0;
  734. }
  735. }
  736. return 1;
  737. }
  738. void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  739. {
  740. unsigned char *block;
  741. int i;
  742. if (edid == NULL)
  743. return;
  744. if (!(edid_checksum(edid)))
  745. return;
  746. if (!(edid_check_header(edid)))
  747. return;
  748. memset(specs, 0, sizeof(struct fb_monspecs));
  749. specs->version = edid[EDID_STRUCT_VERSION];
  750. specs->revision = edid[EDID_STRUCT_REVISION];
  751. DPRINTK("========================================\n");
  752. DPRINTK("Display Information (EDID)\n");
  753. DPRINTK("========================================\n");
  754. DPRINTK(" EDID Version %d.%d\n", (int) specs->version,
  755. (int) specs->revision);
  756. parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs);
  757. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  758. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  759. if (edid_is_serial_block(block)) {
  760. copy_string(block, specs->serial_no);
  761. DPRINTK(" Serial Number: %s\n", specs->serial_no);
  762. } else if (edid_is_ascii_block(block)) {
  763. copy_string(block, specs->ascii);
  764. DPRINTK(" ASCII Block: %s\n", specs->ascii);
  765. } else if (edid_is_monitor_block(block)) {
  766. copy_string(block, specs->monitor);
  767. DPRINTK(" Monitor Name: %s\n", specs->monitor);
  768. }
  769. }
  770. DPRINTK(" Display Characteristics:\n");
  771. get_monspecs(edid, specs);
  772. specs->modedb = fb_create_modedb(edid, &specs->modedb_len);
  773. DPRINTK("========================================\n");
  774. }
  775. /*
  776. * VESA Generalized Timing Formula (GTF)
  777. */
  778. #define FLYBACK 550
  779. #define V_FRONTPORCH 1
  780. #define H_OFFSET 40
  781. #define H_SCALEFACTOR 20
  782. #define H_BLANKSCALE 128
  783. #define H_GRADIENT 600
  784. #define C_VAL 30
  785. #define M_VAL 300
  786. struct __fb_timings {
  787. u32 dclk;
  788. u32 hfreq;
  789. u32 vfreq;
  790. u32 hactive;
  791. u32 vactive;
  792. u32 hblank;
  793. u32 vblank;
  794. u32 htotal;
  795. u32 vtotal;
  796. };
  797. /**
  798. * fb_get_vblank - get vertical blank time
  799. * @hfreq: horizontal freq
  800. *
  801. * DESCRIPTION:
  802. * vblank = right_margin + vsync_len + left_margin
  803. *
  804. * given: right_margin = 1 (V_FRONTPORCH)
  805. * vsync_len = 3
  806. * flyback = 550
  807. *
  808. * flyback * hfreq
  809. * left_margin = --------------- - vsync_len
  810. * 1000000
  811. */
  812. static u32 fb_get_vblank(u32 hfreq)
  813. {
  814. u32 vblank;
  815. vblank = (hfreq * FLYBACK)/1000;
  816. vblank = (vblank + 500)/1000;
  817. return (vblank + V_FRONTPORCH);
  818. }
  819. /**
  820. * fb_get_hblank_by_freq - get horizontal blank time given hfreq
  821. * @hfreq: horizontal freq
  822. * @xres: horizontal resolution in pixels
  823. *
  824. * DESCRIPTION:
  825. *
  826. * xres * duty_cycle
  827. * hblank = ------------------
  828. * 100 - duty_cycle
  829. *
  830. * duty cycle = percent of htotal assigned to inactive display
  831. * duty cycle = C - (M/Hfreq)
  832. *
  833. * where: C = ((offset - scale factor) * blank_scale)
  834. * -------------------------------------- + scale factor
  835. * 256
  836. * M = blank_scale * gradient
  837. *
  838. */
  839. static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
  840. {
  841. u32 c_val, m_val, duty_cycle, hblank;
  842. c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
  843. H_SCALEFACTOR) * 1000;
  844. m_val = (H_BLANKSCALE * H_GRADIENT)/256;
  845. m_val = (m_val * 1000000)/hfreq;
  846. duty_cycle = c_val - m_val;
  847. hblank = (xres * duty_cycle)/(100000 - duty_cycle);
  848. return (hblank);
  849. }
  850. /**
  851. * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
  852. * @dclk: pixelclock in Hz
  853. * @xres: horizontal resolution in pixels
  854. *
  855. * DESCRIPTION:
  856. *
  857. * xres * duty_cycle
  858. * hblank = ------------------
  859. * 100 - duty_cycle
  860. *
  861. * duty cycle = percent of htotal assigned to inactive display
  862. * duty cycle = C - (M * h_period)
  863. *
  864. * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
  865. * -----------------------------------------------
  866. * 2 * M
  867. * M = 300;
  868. * C = 30;
  869. */
  870. static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
  871. {
  872. u32 duty_cycle, h_period, hblank;
  873. dclk /= 1000;
  874. h_period = 100 - C_VAL;
  875. h_period *= h_period;
  876. h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
  877. h_period *=10000;
  878. h_period = int_sqrt(h_period);
  879. h_period -= (100 - C_VAL) * 100;
  880. h_period *= 1000;
  881. h_period /= 2 * M_VAL;
  882. duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
  883. hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
  884. hblank &= ~15;
  885. return (hblank);
  886. }
  887. /**
  888. * fb_get_hfreq - estimate hsync
  889. * @vfreq: vertical refresh rate
  890. * @yres: vertical resolution
  891. *
  892. * DESCRIPTION:
  893. *
  894. * (yres + front_port) * vfreq * 1000000
  895. * hfreq = -------------------------------------
  896. * (1000000 - (vfreq * FLYBACK)
  897. *
  898. */
  899. static u32 fb_get_hfreq(u32 vfreq, u32 yres)
  900. {
  901. u32 divisor, hfreq;
  902. divisor = (1000000 - (vfreq * FLYBACK))/1000;
  903. hfreq = (yres + V_FRONTPORCH) * vfreq * 1000;
  904. return (hfreq/divisor);
  905. }
  906. static void fb_timings_vfreq(struct __fb_timings *timings)
  907. {
  908. timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
  909. timings->vblank = fb_get_vblank(timings->hfreq);
  910. timings->vtotal = timings->vactive + timings->vblank;
  911. timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
  912. timings->hactive);
  913. timings->htotal = timings->hactive + timings->hblank;
  914. timings->dclk = timings->htotal * timings->hfreq;
  915. }
  916. static void fb_timings_hfreq(struct __fb_timings *timings)
  917. {
  918. timings->vblank = fb_get_vblank(timings->hfreq);
  919. timings->vtotal = timings->vactive + timings->vblank;
  920. timings->vfreq = timings->hfreq/timings->vtotal;
  921. timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
  922. timings->hactive);
  923. timings->htotal = timings->hactive + timings->hblank;
  924. timings->dclk = timings->htotal * timings->hfreq;
  925. }
  926. static void fb_timings_dclk(struct __fb_timings *timings)
  927. {
  928. timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
  929. timings->hactive);
  930. timings->htotal = timings->hactive + timings->hblank;
  931. timings->hfreq = timings->dclk/timings->htotal;
  932. timings->vblank = fb_get_vblank(timings->hfreq);
  933. timings->vtotal = timings->vactive + timings->vblank;
  934. timings->vfreq = timings->hfreq/timings->vtotal;
  935. }
  936. /*
  937. * fb_get_mode - calculates video mode using VESA GTF
  938. * @flags: if: 0 - maximize vertical refresh rate
  939. * 1 - vrefresh-driven calculation;
  940. * 2 - hscan-driven calculation;
  941. * 3 - pixelclock-driven calculation;
  942. * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
  943. * @var: pointer to fb_var_screeninfo
  944. * @info: pointer to fb_info
  945. *
  946. * DESCRIPTION:
  947. * Calculates video mode based on monitor specs using VESA GTF.
  948. * The GTF is best for VESA GTF compliant monitors but is
  949. * specifically formulated to work for older monitors as well.
  950. *
  951. * If @flag==0, the function will attempt to maximize the
  952. * refresh rate. Otherwise, it will calculate timings based on
  953. * the flag and accompanying value.
  954. *
  955. * If FB_IGNOREMON bit is set in @flags, monitor specs will be
  956. * ignored and @var will be filled with the calculated timings.
  957. *
  958. * All calculations are based on the VESA GTF Spreadsheet
  959. * available at VESA's public ftp (http://www.vesa.org).
  960. *
  961. * NOTES:
  962. * The timings generated by the GTF will be different from VESA
  963. * DMT. It might be a good idea to keep a table of standard
  964. * VESA modes as well. The GTF may also not work for some displays,
  965. * such as, and especially, analog TV.
  966. *
  967. * REQUIRES:
  968. * A valid info->monspecs, otherwise 'safe numbers' will be used.
  969. */
  970. int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
  971. {
  972. struct __fb_timings timings;
  973. u32 interlace = 1, dscan = 1;
  974. u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
  975. /*
  976. * If monspecs are invalid, use values that are enough
  977. * for 640x480@60
  978. */
  979. if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
  980. !info->monspecs.dclkmax ||
  981. info->monspecs.hfmax < info->monspecs.hfmin ||
  982. info->monspecs.vfmax < info->monspecs.vfmin ||
  983. info->monspecs.dclkmax < info->monspecs.dclkmin) {
  984. hfmin = 29000; hfmax = 30000;
  985. vfmin = 60; vfmax = 60;
  986. dclkmin = 0; dclkmax = 25000000;
  987. } else {
  988. hfmin = info->monspecs.hfmin;
  989. hfmax = info->monspecs.hfmax;
  990. vfmin = info->monspecs.vfmin;
  991. vfmax = info->monspecs.vfmax;
  992. dclkmin = info->monspecs.dclkmin;
  993. dclkmax = info->monspecs.dclkmax;
  994. }
  995. memset(&timings, 0, sizeof(struct __fb_timings));
  996. timings.hactive = var->xres;
  997. timings.vactive = var->yres;
  998. if (var->vmode & FB_VMODE_INTERLACED) {
  999. timings.vactive /= 2;
  1000. interlace = 2;
  1001. }
  1002. if (var->vmode & FB_VMODE_DOUBLE) {
  1003. timings.vactive *= 2;
  1004. dscan = 2;
  1005. }
  1006. switch (flags & ~FB_IGNOREMON) {
  1007. case FB_MAXTIMINGS: /* maximize refresh rate */
  1008. timings.hfreq = hfmax;
  1009. fb_timings_hfreq(&timings);
  1010. if (timings.vfreq > vfmax) {
  1011. timings.vfreq = vfmax;
  1012. fb_timings_vfreq(&timings);
  1013. }
  1014. if (timings.dclk > dclkmax) {
  1015. timings.dclk = dclkmax;
  1016. fb_timings_dclk(&timings);
  1017. }
  1018. break;
  1019. case FB_VSYNCTIMINGS: /* vrefresh driven */
  1020. timings.vfreq = val;
  1021. fb_timings_vfreq(&timings);
  1022. break;
  1023. case FB_HSYNCTIMINGS: /* hsync driven */
  1024. timings.hfreq = val;
  1025. fb_timings_hfreq(&timings);
  1026. break;
  1027. case FB_DCLKTIMINGS: /* pixelclock driven */
  1028. timings.dclk = PICOS2KHZ(val) * 1000;
  1029. fb_timings_dclk(&timings);
  1030. break;
  1031. default:
  1032. return -EINVAL;
  1033. }
  1034. if (!(flags & FB_IGNOREMON) &&
  1035. (timings.vfreq < vfmin || timings.vfreq > vfmax ||
  1036. timings.hfreq < hfmin || timings.hfreq > hfmax ||
  1037. timings.dclk < dclkmin || timings.dclk > dclkmax))
  1038. return -EINVAL;
  1039. var->pixclock = KHZ2PICOS(timings.dclk/1000);
  1040. var->hsync_len = (timings.htotal * 8)/100;
  1041. var->right_margin = (timings.hblank/2) - var->hsync_len;
  1042. var->left_margin = timings.hblank - var->right_margin - var->hsync_len;
  1043. var->vsync_len = (3 * interlace)/dscan;
  1044. var->lower_margin = (1 * interlace)/dscan;
  1045. var->upper_margin = (timings.vblank * interlace)/dscan -
  1046. (var->vsync_len + var->lower_margin);
  1047. return 0;
  1048. }
  1049. #else
  1050. int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
  1051. {
  1052. return 1;
  1053. }
  1054. void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  1055. {
  1056. specs = NULL;
  1057. }
  1058. void fb_destroy_modedb(struct fb_videomode *modedb)
  1059. {
  1060. }
  1061. int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
  1062. struct fb_info *info)
  1063. {
  1064. return -EINVAL;
  1065. }
  1066. #endif /* CONFIG_FB_MODE_HELPERS */
  1067. /*
  1068. * fb_validate_mode - validates var against monitor capabilities
  1069. * @var: pointer to fb_var_screeninfo
  1070. * @info: pointer to fb_info
  1071. *
  1072. * DESCRIPTION:
  1073. * Validates video mode against monitor capabilities specified in
  1074. * info->monspecs.
  1075. *
  1076. * REQUIRES:
  1077. * A valid info->monspecs.
  1078. */
  1079. int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
  1080. {
  1081. u32 hfreq, vfreq, htotal, vtotal, pixclock;
  1082. u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
  1083. /*
  1084. * If monspecs are invalid, use values that are enough
  1085. * for 640x480@60
  1086. */
  1087. if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
  1088. !info->monspecs.dclkmax ||
  1089. info->monspecs.hfmax < info->monspecs.hfmin ||
  1090. info->monspecs.vfmax < info->monspecs.vfmin ||
  1091. info->monspecs.dclkmax < info->monspecs.dclkmin) {
  1092. hfmin = 29000; hfmax = 30000;
  1093. vfmin = 60; vfmax = 60;
  1094. dclkmin = 0; dclkmax = 25000000;
  1095. } else {
  1096. hfmin = info->monspecs.hfmin;
  1097. hfmax = info->monspecs.hfmax;
  1098. vfmin = info->monspecs.vfmin;
  1099. vfmax = info->monspecs.vfmax;
  1100. dclkmin = info->monspecs.dclkmin;
  1101. dclkmax = info->monspecs.dclkmax;
  1102. }
  1103. if (!var->pixclock)
  1104. return -EINVAL;
  1105. pixclock = PICOS2KHZ(var->pixclock) * 1000;
  1106. htotal = var->xres + var->right_margin + var->hsync_len +
  1107. var->left_margin;
  1108. vtotal = var->yres + var->lower_margin + var->vsync_len +
  1109. var->upper_margin;
  1110. if (var->vmode & FB_VMODE_INTERLACED)
  1111. vtotal /= 2;
  1112. if (var->vmode & FB_VMODE_DOUBLE)
  1113. vtotal *= 2;
  1114. hfreq = pixclock/htotal;
  1115. hfreq = (hfreq + 500) / 1000 * 1000;
  1116. vfreq = hfreq/vtotal;
  1117. return (vfreq < vfmin || vfreq > vfmax ||
  1118. hfreq < hfmin || hfreq > hfmax ||
  1119. pixclock < dclkmin || pixclock > dclkmax) ?
  1120. -EINVAL : 0;
  1121. }
  1122. #if defined(__i386__)
  1123. #include <linux/pci.h>
  1124. /*
  1125. * We need to ensure that the EDID block is only returned for
  1126. * the primary graphics adapter.
  1127. */
  1128. const unsigned char *fb_firmware_edid(struct device *device)
  1129. {
  1130. struct pci_dev *dev = NULL;
  1131. struct resource *res = NULL;
  1132. unsigned char *edid = NULL;
  1133. if (device)
  1134. dev = to_pci_dev(device);
  1135. if (dev)
  1136. res = &dev->resource[PCI_ROM_RESOURCE];
  1137. if (res && res->flags & IORESOURCE_ROM_SHADOW)
  1138. edid = edid_info.dummy;
  1139. return edid;
  1140. }
  1141. #else
  1142. const unsigned char *fb_firmware_edid(struct device *device)
  1143. {
  1144. return NULL;
  1145. }
  1146. #endif /* _i386_ */
  1147. EXPORT_SYMBOL(fb_parse_edid);
  1148. EXPORT_SYMBOL(fb_edid_to_monspecs);
  1149. EXPORT_SYMBOL(fb_firmware_edid);
  1150. EXPORT_SYMBOL(fb_get_mode);
  1151. EXPORT_SYMBOL(fb_validate_mode);
  1152. EXPORT_SYMBOL(fb_destroy_modedb);