fbmon.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  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. var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
  282. if (var) {
  283. var->xres = xres;
  284. var->yres = yres;
  285. fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
  286. refresh, var, NULL);
  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. kfree(var);
  300. }
  301. }
  302. static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
  303. {
  304. int num = 0;
  305. unsigned char c;
  306. c = block[0];
  307. if (c&0x80) {
  308. calc_mode_timings(720, 400, 70, &mode[num]);
  309. mode[num++].flag = FB_MODE_IS_CALCULATED;
  310. DPRINTK(" 720x400@70Hz\n");
  311. }
  312. if (c&0x40) {
  313. calc_mode_timings(720, 400, 88, &mode[num]);
  314. mode[num++].flag = FB_MODE_IS_CALCULATED;
  315. DPRINTK(" 720x400@88Hz\n");
  316. }
  317. if (c&0x20) {
  318. mode[num++] = vesa_modes[3];
  319. DPRINTK(" 640x480@60Hz\n");
  320. }
  321. if (c&0x10) {
  322. calc_mode_timings(640, 480, 67, &mode[num]);
  323. mode[num++].flag = FB_MODE_IS_CALCULATED;
  324. DPRINTK(" 640x480@67Hz\n");
  325. }
  326. if (c&0x08) {
  327. mode[num++] = vesa_modes[4];
  328. DPRINTK(" 640x480@72Hz\n");
  329. }
  330. if (c&0x04) {
  331. mode[num++] = vesa_modes[5];
  332. DPRINTK(" 640x480@75Hz\n");
  333. }
  334. if (c&0x02) {
  335. mode[num++] = vesa_modes[7];
  336. DPRINTK(" 800x600@56Hz\n");
  337. }
  338. if (c&0x01) {
  339. mode[num++] = vesa_modes[8];
  340. DPRINTK(" 800x600@60Hz\n");
  341. }
  342. c = block[1];
  343. if (c&0x80) {
  344. mode[num++] = vesa_modes[9];
  345. DPRINTK(" 800x600@72Hz\n");
  346. }
  347. if (c&0x40) {
  348. mode[num++] = vesa_modes[10];
  349. DPRINTK(" 800x600@75Hz\n");
  350. }
  351. if (c&0x20) {
  352. calc_mode_timings(832, 624, 75, &mode[num]);
  353. mode[num++].flag = FB_MODE_IS_CALCULATED;
  354. DPRINTK(" 832x624@75Hz\n");
  355. }
  356. if (c&0x10) {
  357. mode[num++] = vesa_modes[12];
  358. DPRINTK(" 1024x768@87Hz Interlaced\n");
  359. }
  360. if (c&0x08) {
  361. mode[num++] = vesa_modes[13];
  362. DPRINTK(" 1024x768@60Hz\n");
  363. }
  364. if (c&0x04) {
  365. mode[num++] = vesa_modes[14];
  366. DPRINTK(" 1024x768@70Hz\n");
  367. }
  368. if (c&0x02) {
  369. mode[num++] = vesa_modes[15];
  370. DPRINTK(" 1024x768@75Hz\n");
  371. }
  372. if (c&0x01) {
  373. mode[num++] = vesa_modes[21];
  374. DPRINTK(" 1280x1024@75Hz\n");
  375. }
  376. c = block[2];
  377. if (c&0x80) {
  378. mode[num++] = vesa_modes[17];
  379. DPRINTK(" 1152x870@75Hz\n");
  380. }
  381. DPRINTK(" Manufacturer's mask: %x\n",c&0x7F);
  382. return num;
  383. }
  384. static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
  385. {
  386. int xres, yres = 0, refresh, ratio, i;
  387. xres = (block[0] + 31) * 8;
  388. if (xres <= 256)
  389. return 0;
  390. ratio = (block[1] & 0xc0) >> 6;
  391. switch (ratio) {
  392. case 0:
  393. yres = xres;
  394. break;
  395. case 1:
  396. yres = (xres * 3)/4;
  397. break;
  398. case 2:
  399. yres = (xres * 4)/5;
  400. break;
  401. case 3:
  402. yres = (xres * 9)/16;
  403. break;
  404. }
  405. refresh = (block[1] & 0x3f) + 60;
  406. DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh);
  407. for (i = 0; i < VESA_MODEDB_SIZE; i++) {
  408. if (vesa_modes[i].xres == xres &&
  409. vesa_modes[i].yres == yres &&
  410. vesa_modes[i].refresh == refresh) {
  411. *mode = vesa_modes[i];
  412. mode->flag |= FB_MODE_IS_STANDARD;
  413. return 1;
  414. }
  415. }
  416. calc_mode_timings(xres, yres, refresh, mode);
  417. return 1;
  418. }
  419. static int get_dst_timing(unsigned char *block,
  420. struct fb_videomode *mode)
  421. {
  422. int j, num = 0;
  423. for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE)
  424. num += get_std_timing(block, &mode[num]);
  425. return num;
  426. }
  427. static void get_detailed_timing(unsigned char *block,
  428. struct fb_videomode *mode)
  429. {
  430. mode->xres = H_ACTIVE;
  431. mode->yres = V_ACTIVE;
  432. mode->pixclock = PIXEL_CLOCK;
  433. mode->pixclock /= 1000;
  434. mode->pixclock = KHZ2PICOS(mode->pixclock);
  435. mode->right_margin = H_SYNC_OFFSET;
  436. mode->left_margin = (H_ACTIVE + H_BLANKING) -
  437. (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
  438. mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
  439. V_SYNC_WIDTH;
  440. mode->lower_margin = V_SYNC_OFFSET;
  441. mode->hsync_len = H_SYNC_WIDTH;
  442. mode->vsync_len = V_SYNC_WIDTH;
  443. if (HSYNC_POSITIVE)
  444. mode->sync |= FB_SYNC_HOR_HIGH_ACT;
  445. if (VSYNC_POSITIVE)
  446. mode->sync |= FB_SYNC_VERT_HIGH_ACT;
  447. mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
  448. (V_ACTIVE + V_BLANKING));
  449. mode->vmode = 0;
  450. mode->flag = FB_MODE_IS_DETAILED;
  451. DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
  452. DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
  453. H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
  454. DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
  455. V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
  456. DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
  457. (VSYNC_POSITIVE) ? "+" : "-");
  458. }
  459. /**
  460. * fb_create_modedb - create video mode database
  461. * @edid: EDID data
  462. * @dbsize: database size
  463. *
  464. * RETURNS: struct fb_videomode, @dbsize contains length of database
  465. *
  466. * DESCRIPTION:
  467. * This function builds a mode database using the contents of the EDID
  468. * data
  469. */
  470. static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
  471. {
  472. struct fb_videomode *mode, *m;
  473. unsigned char *block;
  474. int num = 0, i;
  475. mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
  476. if (mode == NULL)
  477. return NULL;
  478. if (edid == NULL || !edid_checksum(edid) ||
  479. !edid_check_header(edid)) {
  480. kfree(mode);
  481. return NULL;
  482. }
  483. *dbsize = 0;
  484. DPRINTK(" Detailed Timings\n");
  485. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  486. for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
  487. int first = 1;
  488. if (!(block[0] == 0x00 && block[1] == 0x00)) {
  489. get_detailed_timing(block, &mode[num]);
  490. if (first) {
  491. mode[num].flag |= FB_MODE_IS_FIRST;
  492. first = 0;
  493. }
  494. num++;
  495. }
  496. }
  497. DPRINTK(" Supported VESA Modes\n");
  498. block = edid + ESTABLISHED_TIMING_1;
  499. num += get_est_timing(block, &mode[num]);
  500. DPRINTK(" Standard Timings\n");
  501. block = edid + STD_TIMING_DESCRIPTIONS_START;
  502. for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
  503. num += get_std_timing(block, &mode[num]);
  504. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  505. for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
  506. if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
  507. num += get_dst_timing(block + 5, &mode[num]);
  508. }
  509. /* Yikes, EDID data is totally useless */
  510. if (!num) {
  511. kfree(mode);
  512. return NULL;
  513. }
  514. *dbsize = num;
  515. m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
  516. if (!m)
  517. return mode;
  518. memmove(m, mode, num * sizeof(struct fb_videomode));
  519. kfree(mode);
  520. return m;
  521. }
  522. /**
  523. * fb_destroy_modedb - destroys mode database
  524. * @modedb: mode database to destroy
  525. *
  526. * DESCRIPTION:
  527. * Destroy mode database created by fb_create_modedb
  528. */
  529. void fb_destroy_modedb(struct fb_videomode *modedb)
  530. {
  531. kfree(modedb);
  532. }
  533. static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
  534. {
  535. int i, retval = 1;
  536. unsigned char *block;
  537. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  538. DPRINTK(" Monitor Operating Limits: ");
  539. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  540. if (edid_is_limits_block(block)) {
  541. specs->hfmin = H_MIN_RATE * 1000;
  542. specs->hfmax = H_MAX_RATE * 1000;
  543. specs->vfmin = V_MIN_RATE;
  544. specs->vfmax = V_MAX_RATE;
  545. specs->dclkmax = MAX_PIXEL_CLOCK * 1000000;
  546. specs->gtf = (GTF_SUPPORT) ? 1 : 0;
  547. retval = 0;
  548. DPRINTK("From EDID\n");
  549. break;
  550. }
  551. }
  552. /* estimate monitor limits based on modes supported */
  553. if (retval) {
  554. struct fb_videomode *modes;
  555. int num_modes, i, hz, hscan, pixclock;
  556. modes = fb_create_modedb(edid, &num_modes);
  557. if (!modes) {
  558. DPRINTK("None Available\n");
  559. return 1;
  560. }
  561. retval = 0;
  562. for (i = 0; i < num_modes; i++) {
  563. hz = modes[i].refresh;
  564. pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
  565. hscan = (modes[i].yres * 105 * hz + 5000)/100;
  566. if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
  567. specs->dclkmax = pixclock;
  568. if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
  569. specs->dclkmin = pixclock;
  570. if (specs->hfmax == 0 || specs->hfmax < hscan)
  571. specs->hfmax = hscan;
  572. if (specs->hfmin == 0 || specs->hfmin > hscan)
  573. specs->hfmin = hscan;
  574. if (specs->vfmax == 0 || specs->vfmax < hz)
  575. specs->vfmax = hz;
  576. if (specs->vfmin == 0 || specs->vfmin > hz)
  577. specs->vfmin = hz;
  578. }
  579. DPRINTK("Extrapolated\n");
  580. fb_destroy_modedb(modes);
  581. }
  582. DPRINTK(" H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n",
  583. specs->hfmin/1000, specs->hfmax/1000, specs->vfmin,
  584. specs->vfmax, specs->dclkmax/1000000);
  585. return retval;
  586. }
  587. static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  588. {
  589. unsigned char c, *block;
  590. block = edid + EDID_STRUCT_DISPLAY;
  591. fb_get_monitor_limits(edid, specs);
  592. c = block[0] & 0x80;
  593. specs->input = 0;
  594. if (c) {
  595. specs->input |= FB_DISP_DDI;
  596. DPRINTK(" Digital Display Input");
  597. } else {
  598. DPRINTK(" Analog Display Input: Input Voltage - ");
  599. switch ((block[0] & 0x60) >> 5) {
  600. case 0:
  601. DPRINTK("0.700V/0.300V");
  602. specs->input |= FB_DISP_ANA_700_300;
  603. break;
  604. case 1:
  605. DPRINTK("0.714V/0.286V");
  606. specs->input |= FB_DISP_ANA_714_286;
  607. break;
  608. case 2:
  609. DPRINTK("1.000V/0.400V");
  610. specs->input |= FB_DISP_ANA_1000_400;
  611. break;
  612. case 3:
  613. DPRINTK("0.700V/0.000V");
  614. specs->input |= FB_DISP_ANA_700_000;
  615. break;
  616. }
  617. }
  618. DPRINTK("\n Sync: ");
  619. c = block[0] & 0x10;
  620. if (c)
  621. DPRINTK(" Configurable signal level\n");
  622. c = block[0] & 0x0f;
  623. specs->signal = 0;
  624. if (c & 0x10) {
  625. DPRINTK("Blank to Blank ");
  626. specs->signal |= FB_SIGNAL_BLANK_BLANK;
  627. }
  628. if (c & 0x08) {
  629. DPRINTK("Separate ");
  630. specs->signal |= FB_SIGNAL_SEPARATE;
  631. }
  632. if (c & 0x04) {
  633. DPRINTK("Composite ");
  634. specs->signal |= FB_SIGNAL_COMPOSITE;
  635. }
  636. if (c & 0x02) {
  637. DPRINTK("Sync on Green ");
  638. specs->signal |= FB_SIGNAL_SYNC_ON_GREEN;
  639. }
  640. if (c & 0x01) {
  641. DPRINTK("Serration on ");
  642. specs->signal |= FB_SIGNAL_SERRATION_ON;
  643. }
  644. DPRINTK("\n");
  645. specs->max_x = block[1];
  646. specs->max_y = block[2];
  647. DPRINTK(" Max H-size in cm: ");
  648. if (specs->max_x)
  649. DPRINTK("%d\n", specs->max_x);
  650. else
  651. DPRINTK("variable\n");
  652. DPRINTK(" Max V-size in cm: ");
  653. if (specs->max_y)
  654. DPRINTK("%d\n", specs->max_y);
  655. else
  656. DPRINTK("variable\n");
  657. c = block[3];
  658. specs->gamma = c+100;
  659. DPRINTK(" Gamma: ");
  660. DPRINTK("%d.%d\n", specs->gamma/100, specs->gamma % 100);
  661. get_dpms_capabilities(block[4], specs);
  662. switch ((block[4] & 0x18) >> 3) {
  663. case 0:
  664. DPRINTK(" Monochrome/Grayscale\n");
  665. specs->input |= FB_DISP_MONO;
  666. break;
  667. case 1:
  668. DPRINTK(" RGB Color Display\n");
  669. specs->input |= FB_DISP_RGB;
  670. break;
  671. case 2:
  672. DPRINTK(" Non-RGB Multicolor Display\n");
  673. specs->input |= FB_DISP_MULTI;
  674. break;
  675. default:
  676. DPRINTK(" Unknown\n");
  677. specs->input |= FB_DISP_UNKNOWN;
  678. break;
  679. }
  680. get_chroma(block, specs);
  681. specs->misc = 0;
  682. c = block[4] & 0x7;
  683. if (c & 0x04) {
  684. DPRINTK(" Default color format is primary\n");
  685. specs->misc |= FB_MISC_PRIM_COLOR;
  686. }
  687. if (c & 0x02) {
  688. DPRINTK(" First DETAILED Timing is preferred\n");
  689. specs->misc |= FB_MISC_1ST_DETAIL;
  690. }
  691. if (c & 0x01) {
  692. printk(" Display is GTF capable\n");
  693. specs->gtf = 1;
  694. }
  695. }
  696. static int edid_is_timing_block(unsigned char *block)
  697. {
  698. if ((block[0] != 0x00) || (block[1] != 0x00) ||
  699. (block[2] != 0x00) || (block[4] != 0x00))
  700. return 1;
  701. else
  702. return 0;
  703. }
  704. int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
  705. {
  706. int i;
  707. unsigned char *block;
  708. if (edid == NULL || var == NULL)
  709. return 1;
  710. if (!(edid_checksum(edid)))
  711. return 1;
  712. if (!(edid_check_header(edid)))
  713. return 1;
  714. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  715. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  716. if (edid_is_timing_block(block)) {
  717. var->xres = var->xres_virtual = H_ACTIVE;
  718. var->yres = var->yres_virtual = V_ACTIVE;
  719. var->height = var->width = -1;
  720. var->right_margin = H_SYNC_OFFSET;
  721. var->left_margin = (H_ACTIVE + H_BLANKING) -
  722. (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
  723. var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
  724. V_SYNC_WIDTH;
  725. var->lower_margin = V_SYNC_OFFSET;
  726. var->hsync_len = H_SYNC_WIDTH;
  727. var->vsync_len = V_SYNC_WIDTH;
  728. var->pixclock = PIXEL_CLOCK;
  729. var->pixclock /= 1000;
  730. var->pixclock = KHZ2PICOS(var->pixclock);
  731. if (HSYNC_POSITIVE)
  732. var->sync |= FB_SYNC_HOR_HIGH_ACT;
  733. if (VSYNC_POSITIVE)
  734. var->sync |= FB_SYNC_VERT_HIGH_ACT;
  735. return 0;
  736. }
  737. }
  738. return 1;
  739. }
  740. void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  741. {
  742. unsigned char *block;
  743. int i, found = 0;
  744. if (edid == NULL)
  745. return;
  746. if (!(edid_checksum(edid)))
  747. return;
  748. if (!(edid_check_header(edid)))
  749. return;
  750. memset(specs, 0, sizeof(struct fb_monspecs));
  751. specs->version = edid[EDID_STRUCT_VERSION];
  752. specs->revision = edid[EDID_STRUCT_REVISION];
  753. DPRINTK("========================================\n");
  754. DPRINTK("Display Information (EDID)\n");
  755. DPRINTK("========================================\n");
  756. DPRINTK(" EDID Version %d.%d\n", (int) specs->version,
  757. (int) specs->revision);
  758. parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs);
  759. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  760. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  761. if (edid_is_serial_block(block)) {
  762. copy_string(block, specs->serial_no);
  763. DPRINTK(" Serial Number: %s\n", specs->serial_no);
  764. } else if (edid_is_ascii_block(block)) {
  765. copy_string(block, specs->ascii);
  766. DPRINTK(" ASCII Block: %s\n", specs->ascii);
  767. } else if (edid_is_monitor_block(block)) {
  768. copy_string(block, specs->monitor);
  769. DPRINTK(" Monitor Name: %s\n", specs->monitor);
  770. }
  771. }
  772. DPRINTK(" Display Characteristics:\n");
  773. get_monspecs(edid, specs);
  774. specs->modedb = fb_create_modedb(edid, &specs->modedb_len);
  775. /*
  776. * Workaround for buggy EDIDs that sets that the first
  777. * detailed timing is preferred but has not detailed
  778. * timing specified
  779. */
  780. for (i = 0; i < specs->modedb_len; i++) {
  781. if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {
  782. found = 1;
  783. break;
  784. }
  785. }
  786. if (!found)
  787. specs->misc &= ~FB_MISC_1ST_DETAIL;
  788. DPRINTK("========================================\n");
  789. }
  790. /*
  791. * VESA Generalized Timing Formula (GTF)
  792. */
  793. #define FLYBACK 550
  794. #define V_FRONTPORCH 1
  795. #define H_OFFSET 40
  796. #define H_SCALEFACTOR 20
  797. #define H_BLANKSCALE 128
  798. #define H_GRADIENT 600
  799. #define C_VAL 30
  800. #define M_VAL 300
  801. struct __fb_timings {
  802. u32 dclk;
  803. u32 hfreq;
  804. u32 vfreq;
  805. u32 hactive;
  806. u32 vactive;
  807. u32 hblank;
  808. u32 vblank;
  809. u32 htotal;
  810. u32 vtotal;
  811. };
  812. /**
  813. * fb_get_vblank - get vertical blank time
  814. * @hfreq: horizontal freq
  815. *
  816. * DESCRIPTION:
  817. * vblank = right_margin + vsync_len + left_margin
  818. *
  819. * given: right_margin = 1 (V_FRONTPORCH)
  820. * vsync_len = 3
  821. * flyback = 550
  822. *
  823. * flyback * hfreq
  824. * left_margin = --------------- - vsync_len
  825. * 1000000
  826. */
  827. static u32 fb_get_vblank(u32 hfreq)
  828. {
  829. u32 vblank;
  830. vblank = (hfreq * FLYBACK)/1000;
  831. vblank = (vblank + 500)/1000;
  832. return (vblank + V_FRONTPORCH);
  833. }
  834. /**
  835. * fb_get_hblank_by_freq - get horizontal blank time given hfreq
  836. * @hfreq: horizontal freq
  837. * @xres: horizontal resolution in pixels
  838. *
  839. * DESCRIPTION:
  840. *
  841. * xres * duty_cycle
  842. * hblank = ------------------
  843. * 100 - duty_cycle
  844. *
  845. * duty cycle = percent of htotal assigned to inactive display
  846. * duty cycle = C - (M/Hfreq)
  847. *
  848. * where: C = ((offset - scale factor) * blank_scale)
  849. * -------------------------------------- + scale factor
  850. * 256
  851. * M = blank_scale * gradient
  852. *
  853. */
  854. static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
  855. {
  856. u32 c_val, m_val, duty_cycle, hblank;
  857. c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
  858. H_SCALEFACTOR) * 1000;
  859. m_val = (H_BLANKSCALE * H_GRADIENT)/256;
  860. m_val = (m_val * 1000000)/hfreq;
  861. duty_cycle = c_val - m_val;
  862. hblank = (xres * duty_cycle)/(100000 - duty_cycle);
  863. return (hblank);
  864. }
  865. /**
  866. * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
  867. * @dclk: pixelclock in Hz
  868. * @xres: horizontal resolution in pixels
  869. *
  870. * DESCRIPTION:
  871. *
  872. * xres * duty_cycle
  873. * hblank = ------------------
  874. * 100 - duty_cycle
  875. *
  876. * duty cycle = percent of htotal assigned to inactive display
  877. * duty cycle = C - (M * h_period)
  878. *
  879. * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
  880. * -----------------------------------------------
  881. * 2 * M
  882. * M = 300;
  883. * C = 30;
  884. */
  885. static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
  886. {
  887. u32 duty_cycle, h_period, hblank;
  888. dclk /= 1000;
  889. h_period = 100 - C_VAL;
  890. h_period *= h_period;
  891. h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
  892. h_period *=10000;
  893. h_period = int_sqrt(h_period);
  894. h_period -= (100 - C_VAL) * 100;
  895. h_period *= 1000;
  896. h_period /= 2 * M_VAL;
  897. duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
  898. hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
  899. hblank &= ~15;
  900. return (hblank);
  901. }
  902. /**
  903. * fb_get_hfreq - estimate hsync
  904. * @vfreq: vertical refresh rate
  905. * @yres: vertical resolution
  906. *
  907. * DESCRIPTION:
  908. *
  909. * (yres + front_port) * vfreq * 1000000
  910. * hfreq = -------------------------------------
  911. * (1000000 - (vfreq * FLYBACK)
  912. *
  913. */
  914. static u32 fb_get_hfreq(u32 vfreq, u32 yres)
  915. {
  916. u32 divisor, hfreq;
  917. divisor = (1000000 - (vfreq * FLYBACK))/1000;
  918. hfreq = (yres + V_FRONTPORCH) * vfreq * 1000;
  919. return (hfreq/divisor);
  920. }
  921. static void fb_timings_vfreq(struct __fb_timings *timings)
  922. {
  923. timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
  924. timings->vblank = fb_get_vblank(timings->hfreq);
  925. timings->vtotal = timings->vactive + timings->vblank;
  926. timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
  927. timings->hactive);
  928. timings->htotal = timings->hactive + timings->hblank;
  929. timings->dclk = timings->htotal * timings->hfreq;
  930. }
  931. static void fb_timings_hfreq(struct __fb_timings *timings)
  932. {
  933. timings->vblank = fb_get_vblank(timings->hfreq);
  934. timings->vtotal = timings->vactive + timings->vblank;
  935. timings->vfreq = timings->hfreq/timings->vtotal;
  936. timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
  937. timings->hactive);
  938. timings->htotal = timings->hactive + timings->hblank;
  939. timings->dclk = timings->htotal * timings->hfreq;
  940. }
  941. static void fb_timings_dclk(struct __fb_timings *timings)
  942. {
  943. timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
  944. timings->hactive);
  945. timings->htotal = timings->hactive + timings->hblank;
  946. timings->hfreq = timings->dclk/timings->htotal;
  947. timings->vblank = fb_get_vblank(timings->hfreq);
  948. timings->vtotal = timings->vactive + timings->vblank;
  949. timings->vfreq = timings->hfreq/timings->vtotal;
  950. }
  951. /*
  952. * fb_get_mode - calculates video mode using VESA GTF
  953. * @flags: if: 0 - maximize vertical refresh rate
  954. * 1 - vrefresh-driven calculation;
  955. * 2 - hscan-driven calculation;
  956. * 3 - pixelclock-driven calculation;
  957. * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
  958. * @var: pointer to fb_var_screeninfo
  959. * @info: pointer to fb_info
  960. *
  961. * DESCRIPTION:
  962. * Calculates video mode based on monitor specs using VESA GTF.
  963. * The GTF is best for VESA GTF compliant monitors but is
  964. * specifically formulated to work for older monitors as well.
  965. *
  966. * If @flag==0, the function will attempt to maximize the
  967. * refresh rate. Otherwise, it will calculate timings based on
  968. * the flag and accompanying value.
  969. *
  970. * If FB_IGNOREMON bit is set in @flags, monitor specs will be
  971. * ignored and @var will be filled with the calculated timings.
  972. *
  973. * All calculations are based on the VESA GTF Spreadsheet
  974. * available at VESA's public ftp (http://www.vesa.org).
  975. *
  976. * NOTES:
  977. * The timings generated by the GTF will be different from VESA
  978. * DMT. It might be a good idea to keep a table of standard
  979. * VESA modes as well. The GTF may also not work for some displays,
  980. * such as, and especially, analog TV.
  981. *
  982. * REQUIRES:
  983. * A valid info->monspecs, otherwise 'safe numbers' will be used.
  984. */
  985. int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
  986. {
  987. struct __fb_timings *timings;
  988. u32 interlace = 1, dscan = 1;
  989. u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
  990. timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
  991. if (!timings)
  992. return -ENOMEM;
  993. /*
  994. * If monspecs are invalid, use values that are enough
  995. * for 640x480@60
  996. */
  997. if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
  998. !info->monspecs.dclkmax ||
  999. info->monspecs.hfmax < info->monspecs.hfmin ||
  1000. info->monspecs.vfmax < info->monspecs.vfmin ||
  1001. info->monspecs.dclkmax < info->monspecs.dclkmin) {
  1002. hfmin = 29000; hfmax = 30000;
  1003. vfmin = 60; vfmax = 60;
  1004. dclkmin = 0; dclkmax = 25000000;
  1005. } else {
  1006. hfmin = info->monspecs.hfmin;
  1007. hfmax = info->monspecs.hfmax;
  1008. vfmin = info->monspecs.vfmin;
  1009. vfmax = info->monspecs.vfmax;
  1010. dclkmin = info->monspecs.dclkmin;
  1011. dclkmax = info->monspecs.dclkmax;
  1012. }
  1013. timings->hactive = var->xres;
  1014. timings->vactive = var->yres;
  1015. if (var->vmode & FB_VMODE_INTERLACED) {
  1016. timings->vactive /= 2;
  1017. interlace = 2;
  1018. }
  1019. if (var->vmode & FB_VMODE_DOUBLE) {
  1020. timings->vactive *= 2;
  1021. dscan = 2;
  1022. }
  1023. switch (flags & ~FB_IGNOREMON) {
  1024. case FB_MAXTIMINGS: /* maximize refresh rate */
  1025. timings->hfreq = hfmax;
  1026. fb_timings_hfreq(timings);
  1027. if (timings->vfreq > vfmax) {
  1028. timings->vfreq = vfmax;
  1029. fb_timings_vfreq(timings);
  1030. }
  1031. if (timings->dclk > dclkmax) {
  1032. timings->dclk = dclkmax;
  1033. fb_timings_dclk(timings);
  1034. }
  1035. break;
  1036. case FB_VSYNCTIMINGS: /* vrefresh driven */
  1037. timings->vfreq = val;
  1038. fb_timings_vfreq(timings);
  1039. break;
  1040. case FB_HSYNCTIMINGS: /* hsync driven */
  1041. timings->hfreq = val;
  1042. fb_timings_hfreq(timings);
  1043. break;
  1044. case FB_DCLKTIMINGS: /* pixelclock driven */
  1045. timings->dclk = PICOS2KHZ(val) * 1000;
  1046. fb_timings_dclk(timings);
  1047. break;
  1048. default:
  1049. err = -EINVAL;
  1050. }
  1051. if (err || (!(flags & FB_IGNOREMON) &&
  1052. (timings->vfreq < vfmin || timings->vfreq > vfmax ||
  1053. timings->hfreq < hfmin || timings->hfreq > hfmax ||
  1054. timings->dclk < dclkmin || timings->dclk > dclkmax))) {
  1055. err = -EINVAL;
  1056. } else {
  1057. var->pixclock = KHZ2PICOS(timings->dclk/1000);
  1058. var->hsync_len = (timings->htotal * 8)/100;
  1059. var->right_margin = (timings->hblank/2) - var->hsync_len;
  1060. var->left_margin = timings->hblank - var->right_margin -
  1061. var->hsync_len;
  1062. var->vsync_len = (3 * interlace)/dscan;
  1063. var->lower_margin = (1 * interlace)/dscan;
  1064. var->upper_margin = (timings->vblank * interlace)/dscan -
  1065. (var->vsync_len + var->lower_margin);
  1066. }
  1067. kfree(timings);
  1068. return err;
  1069. }
  1070. #else
  1071. int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
  1072. {
  1073. return 1;
  1074. }
  1075. void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  1076. {
  1077. specs = NULL;
  1078. }
  1079. void fb_destroy_modedb(struct fb_videomode *modedb)
  1080. {
  1081. }
  1082. int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
  1083. struct fb_info *info)
  1084. {
  1085. return -EINVAL;
  1086. }
  1087. #endif /* CONFIG_FB_MODE_HELPERS */
  1088. /*
  1089. * fb_validate_mode - validates var against monitor capabilities
  1090. * @var: pointer to fb_var_screeninfo
  1091. * @info: pointer to fb_info
  1092. *
  1093. * DESCRIPTION:
  1094. * Validates video mode against monitor capabilities specified in
  1095. * info->monspecs.
  1096. *
  1097. * REQUIRES:
  1098. * A valid info->monspecs.
  1099. */
  1100. int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
  1101. {
  1102. u32 hfreq, vfreq, htotal, vtotal, pixclock;
  1103. u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
  1104. /*
  1105. * If monspecs are invalid, use values that are enough
  1106. * for 640x480@60
  1107. */
  1108. if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
  1109. !info->monspecs.dclkmax ||
  1110. info->monspecs.hfmax < info->monspecs.hfmin ||
  1111. info->monspecs.vfmax < info->monspecs.vfmin ||
  1112. info->monspecs.dclkmax < info->monspecs.dclkmin) {
  1113. hfmin = 29000; hfmax = 30000;
  1114. vfmin = 60; vfmax = 60;
  1115. dclkmin = 0; dclkmax = 25000000;
  1116. } else {
  1117. hfmin = info->monspecs.hfmin;
  1118. hfmax = info->monspecs.hfmax;
  1119. vfmin = info->monspecs.vfmin;
  1120. vfmax = info->monspecs.vfmax;
  1121. dclkmin = info->monspecs.dclkmin;
  1122. dclkmax = info->monspecs.dclkmax;
  1123. }
  1124. if (!var->pixclock)
  1125. return -EINVAL;
  1126. pixclock = PICOS2KHZ(var->pixclock) * 1000;
  1127. htotal = var->xres + var->right_margin + var->hsync_len +
  1128. var->left_margin;
  1129. vtotal = var->yres + var->lower_margin + var->vsync_len +
  1130. var->upper_margin;
  1131. if (var->vmode & FB_VMODE_INTERLACED)
  1132. vtotal /= 2;
  1133. if (var->vmode & FB_VMODE_DOUBLE)
  1134. vtotal *= 2;
  1135. hfreq = pixclock/htotal;
  1136. hfreq = (hfreq + 500) / 1000 * 1000;
  1137. vfreq = hfreq/vtotal;
  1138. return (vfreq < vfmin || vfreq > vfmax ||
  1139. hfreq < hfmin || hfreq > hfmax ||
  1140. pixclock < dclkmin || pixclock > dclkmax) ?
  1141. -EINVAL : 0;
  1142. }
  1143. #if defined(__i386__)
  1144. #include <linux/pci.h>
  1145. /*
  1146. * We need to ensure that the EDID block is only returned for
  1147. * the primary graphics adapter.
  1148. */
  1149. const unsigned char *fb_firmware_edid(struct device *device)
  1150. {
  1151. struct pci_dev *dev = NULL;
  1152. struct resource *res = NULL;
  1153. unsigned char *edid = NULL;
  1154. if (device)
  1155. dev = to_pci_dev(device);
  1156. if (dev)
  1157. res = &dev->resource[PCI_ROM_RESOURCE];
  1158. if (res && res->flags & IORESOURCE_ROM_SHADOW)
  1159. edid = edid_info.dummy;
  1160. return edid;
  1161. }
  1162. #else
  1163. const unsigned char *fb_firmware_edid(struct device *device)
  1164. {
  1165. return NULL;
  1166. }
  1167. #endif /* _i386_ */
  1168. EXPORT_SYMBOL(fb_parse_edid);
  1169. EXPORT_SYMBOL(fb_edid_to_monspecs);
  1170. EXPORT_SYMBOL(fb_firmware_edid);
  1171. EXPORT_SYMBOL(fb_get_mode);
  1172. EXPORT_SYMBOL(fb_validate_mode);
  1173. EXPORT_SYMBOL(fb_destroy_modedb);