fbmon.c 34 KB

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