fbmon.c 34 KB

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