fbmon.c 33 KB

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