fbmon.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  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, first = 1;
  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. if (!(block[0] == 0x00 && block[1] == 0x00)) {
  545. get_detailed_timing(block, &mode[num]);
  546. if (first) {
  547. mode[num].flag |= FB_MODE_IS_FIRST;
  548. first = 0;
  549. }
  550. num++;
  551. }
  552. }
  553. DPRINTK(" Supported VESA Modes\n");
  554. block = edid + ESTABLISHED_TIMING_1;
  555. num += get_est_timing(block, &mode[num]);
  556. DPRINTK(" Standard Timings\n");
  557. block = edid + STD_TIMING_DESCRIPTIONS_START;
  558. for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
  559. num += get_std_timing(block, &mode[num]);
  560. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  561. for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
  562. if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
  563. num += get_dst_timing(block + 5, &mode[num]);
  564. }
  565. /* Yikes, EDID data is totally useless */
  566. if (!num) {
  567. kfree(mode);
  568. return NULL;
  569. }
  570. *dbsize = num;
  571. m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
  572. if (!m)
  573. return mode;
  574. memmove(m, mode, num * sizeof(struct fb_videomode));
  575. kfree(mode);
  576. return m;
  577. }
  578. /**
  579. * fb_destroy_modedb - destroys mode database
  580. * @modedb: mode database to destroy
  581. *
  582. * DESCRIPTION:
  583. * Destroy mode database created by fb_create_modedb
  584. */
  585. void fb_destroy_modedb(struct fb_videomode *modedb)
  586. {
  587. kfree(modedb);
  588. }
  589. static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
  590. {
  591. int i, retval = 1;
  592. unsigned char *block;
  593. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  594. DPRINTK(" Monitor Operating Limits: ");
  595. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  596. if (edid_is_limits_block(block)) {
  597. specs->hfmin = H_MIN_RATE * 1000;
  598. specs->hfmax = H_MAX_RATE * 1000;
  599. specs->vfmin = V_MIN_RATE;
  600. specs->vfmax = V_MAX_RATE;
  601. specs->dclkmax = MAX_PIXEL_CLOCK * 1000000;
  602. specs->gtf = (GTF_SUPPORT) ? 1 : 0;
  603. retval = 0;
  604. DPRINTK("From EDID\n");
  605. break;
  606. }
  607. }
  608. /* estimate monitor limits based on modes supported */
  609. if (retval) {
  610. struct fb_videomode *modes, *mode;
  611. int num_modes, hz, hscan, pixclock;
  612. int vtotal, htotal;
  613. modes = fb_create_modedb(edid, &num_modes);
  614. if (!modes) {
  615. DPRINTK("None Available\n");
  616. return 1;
  617. }
  618. retval = 0;
  619. for (i = 0; i < num_modes; i++) {
  620. mode = &modes[i];
  621. pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
  622. htotal = mode->xres + mode->right_margin + mode->hsync_len
  623. + mode->left_margin;
  624. vtotal = mode->yres + mode->lower_margin + mode->vsync_len
  625. + mode->upper_margin;
  626. if (mode->vmode & FB_VMODE_INTERLACED)
  627. vtotal /= 2;
  628. if (mode->vmode & FB_VMODE_DOUBLE)
  629. vtotal *= 2;
  630. hscan = (pixclock + htotal / 2) / htotal;
  631. hscan = (hscan + 500) / 1000 * 1000;
  632. hz = (hscan + vtotal / 2) / vtotal;
  633. if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
  634. specs->dclkmax = pixclock;
  635. if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
  636. specs->dclkmin = pixclock;
  637. if (specs->hfmax == 0 || specs->hfmax < hscan)
  638. specs->hfmax = hscan;
  639. if (specs->hfmin == 0 || specs->hfmin > hscan)
  640. specs->hfmin = hscan;
  641. if (specs->vfmax == 0 || specs->vfmax < hz)
  642. specs->vfmax = hz;
  643. if (specs->vfmin == 0 || specs->vfmin > hz)
  644. specs->vfmin = hz;
  645. }
  646. DPRINTK("Extrapolated\n");
  647. fb_destroy_modedb(modes);
  648. }
  649. DPRINTK(" H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n",
  650. specs->hfmin/1000, specs->hfmax/1000, specs->vfmin,
  651. specs->vfmax, specs->dclkmax/1000000);
  652. return retval;
  653. }
  654. static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  655. {
  656. unsigned char c, *block;
  657. block = edid + EDID_STRUCT_DISPLAY;
  658. fb_get_monitor_limits(edid, specs);
  659. c = block[0] & 0x80;
  660. specs->input = 0;
  661. if (c) {
  662. specs->input |= FB_DISP_DDI;
  663. DPRINTK(" Digital Display Input");
  664. } else {
  665. DPRINTK(" Analog Display Input: Input Voltage - ");
  666. switch ((block[0] & 0x60) >> 5) {
  667. case 0:
  668. DPRINTK("0.700V/0.300V");
  669. specs->input |= FB_DISP_ANA_700_300;
  670. break;
  671. case 1:
  672. DPRINTK("0.714V/0.286V");
  673. specs->input |= FB_DISP_ANA_714_286;
  674. break;
  675. case 2:
  676. DPRINTK("1.000V/0.400V");
  677. specs->input |= FB_DISP_ANA_1000_400;
  678. break;
  679. case 3:
  680. DPRINTK("0.700V/0.000V");
  681. specs->input |= FB_DISP_ANA_700_000;
  682. break;
  683. }
  684. }
  685. DPRINTK("\n Sync: ");
  686. c = block[0] & 0x10;
  687. if (c)
  688. DPRINTK(" Configurable signal level\n");
  689. c = block[0] & 0x0f;
  690. specs->signal = 0;
  691. if (c & 0x10) {
  692. DPRINTK("Blank to Blank ");
  693. specs->signal |= FB_SIGNAL_BLANK_BLANK;
  694. }
  695. if (c & 0x08) {
  696. DPRINTK("Separate ");
  697. specs->signal |= FB_SIGNAL_SEPARATE;
  698. }
  699. if (c & 0x04) {
  700. DPRINTK("Composite ");
  701. specs->signal |= FB_SIGNAL_COMPOSITE;
  702. }
  703. if (c & 0x02) {
  704. DPRINTK("Sync on Green ");
  705. specs->signal |= FB_SIGNAL_SYNC_ON_GREEN;
  706. }
  707. if (c & 0x01) {
  708. DPRINTK("Serration on ");
  709. specs->signal |= FB_SIGNAL_SERRATION_ON;
  710. }
  711. DPRINTK("\n");
  712. specs->max_x = block[1];
  713. specs->max_y = block[2];
  714. DPRINTK(" Max H-size in cm: ");
  715. if (specs->max_x)
  716. DPRINTK("%d\n", specs->max_x);
  717. else
  718. DPRINTK("variable\n");
  719. DPRINTK(" Max V-size in cm: ");
  720. if (specs->max_y)
  721. DPRINTK("%d\n", specs->max_y);
  722. else
  723. DPRINTK("variable\n");
  724. c = block[3];
  725. specs->gamma = c+100;
  726. DPRINTK(" Gamma: ");
  727. DPRINTK("%d.%d\n", specs->gamma/100, specs->gamma % 100);
  728. get_dpms_capabilities(block[4], specs);
  729. switch ((block[4] & 0x18) >> 3) {
  730. case 0:
  731. DPRINTK(" Monochrome/Grayscale\n");
  732. specs->input |= FB_DISP_MONO;
  733. break;
  734. case 1:
  735. DPRINTK(" RGB Color Display\n");
  736. specs->input |= FB_DISP_RGB;
  737. break;
  738. case 2:
  739. DPRINTK(" Non-RGB Multicolor Display\n");
  740. specs->input |= FB_DISP_MULTI;
  741. break;
  742. default:
  743. DPRINTK(" Unknown\n");
  744. specs->input |= FB_DISP_UNKNOWN;
  745. break;
  746. }
  747. get_chroma(block, specs);
  748. specs->misc = 0;
  749. c = block[4] & 0x7;
  750. if (c & 0x04) {
  751. DPRINTK(" Default color format is primary\n");
  752. specs->misc |= FB_MISC_PRIM_COLOR;
  753. }
  754. if (c & 0x02) {
  755. DPRINTK(" First DETAILED Timing is preferred\n");
  756. specs->misc |= FB_MISC_1ST_DETAIL;
  757. }
  758. if (c & 0x01) {
  759. printk(" Display is GTF capable\n");
  760. specs->gtf = 1;
  761. }
  762. }
  763. int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
  764. {
  765. int i;
  766. unsigned char *block;
  767. if (edid == NULL || var == NULL)
  768. return 1;
  769. if (!(edid_checksum(edid)))
  770. return 1;
  771. if (!(edid_check_header(edid)))
  772. return 1;
  773. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  774. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  775. if (edid_is_timing_block(block)) {
  776. var->xres = var->xres_virtual = H_ACTIVE;
  777. var->yres = var->yres_virtual = V_ACTIVE;
  778. var->height = var->width = 0;
  779. var->right_margin = H_SYNC_OFFSET;
  780. var->left_margin = (H_ACTIVE + H_BLANKING) -
  781. (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
  782. var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
  783. V_SYNC_WIDTH;
  784. var->lower_margin = V_SYNC_OFFSET;
  785. var->hsync_len = H_SYNC_WIDTH;
  786. var->vsync_len = V_SYNC_WIDTH;
  787. var->pixclock = PIXEL_CLOCK;
  788. var->pixclock /= 1000;
  789. var->pixclock = KHZ2PICOS(var->pixclock);
  790. if (HSYNC_POSITIVE)
  791. var->sync |= FB_SYNC_HOR_HIGH_ACT;
  792. if (VSYNC_POSITIVE)
  793. var->sync |= FB_SYNC_VERT_HIGH_ACT;
  794. return 0;
  795. }
  796. }
  797. return 1;
  798. }
  799. void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  800. {
  801. unsigned char *block;
  802. int i, found = 0;
  803. if (edid == NULL)
  804. return;
  805. if (!(edid_checksum(edid)))
  806. return;
  807. if (!(edid_check_header(edid)))
  808. return;
  809. memset(specs, 0, sizeof(struct fb_monspecs));
  810. specs->version = edid[EDID_STRUCT_VERSION];
  811. specs->revision = edid[EDID_STRUCT_REVISION];
  812. DPRINTK("========================================\n");
  813. DPRINTK("Display Information (EDID)\n");
  814. DPRINTK("========================================\n");
  815. DPRINTK(" EDID Version %d.%d\n", (int) specs->version,
  816. (int) specs->revision);
  817. parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs);
  818. block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
  819. for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
  820. if (edid_is_serial_block(block)) {
  821. copy_string(block, specs->serial_no);
  822. DPRINTK(" Serial Number: %s\n", specs->serial_no);
  823. } else if (edid_is_ascii_block(block)) {
  824. copy_string(block, specs->ascii);
  825. DPRINTK(" ASCII Block: %s\n", specs->ascii);
  826. } else if (edid_is_monitor_block(block)) {
  827. copy_string(block, specs->monitor);
  828. DPRINTK(" Monitor Name: %s\n", specs->monitor);
  829. }
  830. }
  831. DPRINTK(" Display Characteristics:\n");
  832. get_monspecs(edid, specs);
  833. specs->modedb = fb_create_modedb(edid, &specs->modedb_len);
  834. /*
  835. * Workaround for buggy EDIDs that sets that the first
  836. * detailed timing is preferred but has not detailed
  837. * timing specified
  838. */
  839. for (i = 0; i < specs->modedb_len; i++) {
  840. if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {
  841. found = 1;
  842. break;
  843. }
  844. }
  845. if (!found)
  846. specs->misc &= ~FB_MISC_1ST_DETAIL;
  847. DPRINTK("========================================\n");
  848. }
  849. /*
  850. * VESA Generalized Timing Formula (GTF)
  851. */
  852. #define FLYBACK 550
  853. #define V_FRONTPORCH 1
  854. #define H_OFFSET 40
  855. #define H_SCALEFACTOR 20
  856. #define H_BLANKSCALE 128
  857. #define H_GRADIENT 600
  858. #define C_VAL 30
  859. #define M_VAL 300
  860. struct __fb_timings {
  861. u32 dclk;
  862. u32 hfreq;
  863. u32 vfreq;
  864. u32 hactive;
  865. u32 vactive;
  866. u32 hblank;
  867. u32 vblank;
  868. u32 htotal;
  869. u32 vtotal;
  870. };
  871. /**
  872. * fb_get_vblank - get vertical blank time
  873. * @hfreq: horizontal freq
  874. *
  875. * DESCRIPTION:
  876. * vblank = right_margin + vsync_len + left_margin
  877. *
  878. * given: right_margin = 1 (V_FRONTPORCH)
  879. * vsync_len = 3
  880. * flyback = 550
  881. *
  882. * flyback * hfreq
  883. * left_margin = --------------- - vsync_len
  884. * 1000000
  885. */
  886. static u32 fb_get_vblank(u32 hfreq)
  887. {
  888. u32 vblank;
  889. vblank = (hfreq * FLYBACK)/1000;
  890. vblank = (vblank + 500)/1000;
  891. return (vblank + V_FRONTPORCH);
  892. }
  893. /**
  894. * fb_get_hblank_by_freq - get horizontal blank time given hfreq
  895. * @hfreq: horizontal freq
  896. * @xres: horizontal resolution in pixels
  897. *
  898. * DESCRIPTION:
  899. *
  900. * xres * duty_cycle
  901. * hblank = ------------------
  902. * 100 - duty_cycle
  903. *
  904. * duty cycle = percent of htotal assigned to inactive display
  905. * duty cycle = C - (M/Hfreq)
  906. *
  907. * where: C = ((offset - scale factor) * blank_scale)
  908. * -------------------------------------- + scale factor
  909. * 256
  910. * M = blank_scale * gradient
  911. *
  912. */
  913. static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
  914. {
  915. u32 c_val, m_val, duty_cycle, hblank;
  916. c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
  917. H_SCALEFACTOR) * 1000;
  918. m_val = (H_BLANKSCALE * H_GRADIENT)/256;
  919. m_val = (m_val * 1000000)/hfreq;
  920. duty_cycle = c_val - m_val;
  921. hblank = (xres * duty_cycle)/(100000 - duty_cycle);
  922. return (hblank);
  923. }
  924. /**
  925. * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
  926. * @dclk: pixelclock in Hz
  927. * @xres: horizontal resolution in pixels
  928. *
  929. * DESCRIPTION:
  930. *
  931. * xres * duty_cycle
  932. * hblank = ------------------
  933. * 100 - duty_cycle
  934. *
  935. * duty cycle = percent of htotal assigned to inactive display
  936. * duty cycle = C - (M * h_period)
  937. *
  938. * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
  939. * -----------------------------------------------
  940. * 2 * M
  941. * M = 300;
  942. * C = 30;
  943. */
  944. static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
  945. {
  946. u32 duty_cycle, h_period, hblank;
  947. dclk /= 1000;
  948. h_period = 100 - C_VAL;
  949. h_period *= h_period;
  950. h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
  951. h_period *= 10000;
  952. h_period = int_sqrt(h_period);
  953. h_period -= (100 - C_VAL) * 100;
  954. h_period *= 1000;
  955. h_period /= 2 * M_VAL;
  956. duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
  957. hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
  958. hblank &= ~15;
  959. return (hblank);
  960. }
  961. /**
  962. * fb_get_hfreq - estimate hsync
  963. * @vfreq: vertical refresh rate
  964. * @yres: vertical resolution
  965. *
  966. * DESCRIPTION:
  967. *
  968. * (yres + front_port) * vfreq * 1000000
  969. * hfreq = -------------------------------------
  970. * (1000000 - (vfreq * FLYBACK)
  971. *
  972. */
  973. static u32 fb_get_hfreq(u32 vfreq, u32 yres)
  974. {
  975. u32 divisor, hfreq;
  976. divisor = (1000000 - (vfreq * FLYBACK))/1000;
  977. hfreq = (yres + V_FRONTPORCH) * vfreq * 1000;
  978. return (hfreq/divisor);
  979. }
  980. static void fb_timings_vfreq(struct __fb_timings *timings)
  981. {
  982. timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
  983. timings->vblank = fb_get_vblank(timings->hfreq);
  984. timings->vtotal = timings->vactive + timings->vblank;
  985. timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
  986. timings->hactive);
  987. timings->htotal = timings->hactive + timings->hblank;
  988. timings->dclk = timings->htotal * timings->hfreq;
  989. }
  990. static void fb_timings_hfreq(struct __fb_timings *timings)
  991. {
  992. timings->vblank = fb_get_vblank(timings->hfreq);
  993. timings->vtotal = timings->vactive + timings->vblank;
  994. timings->vfreq = timings->hfreq/timings->vtotal;
  995. timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
  996. timings->hactive);
  997. timings->htotal = timings->hactive + timings->hblank;
  998. timings->dclk = timings->htotal * timings->hfreq;
  999. }
  1000. static void fb_timings_dclk(struct __fb_timings *timings)
  1001. {
  1002. timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
  1003. timings->hactive);
  1004. timings->htotal = timings->hactive + timings->hblank;
  1005. timings->hfreq = timings->dclk/timings->htotal;
  1006. timings->vblank = fb_get_vblank(timings->hfreq);
  1007. timings->vtotal = timings->vactive + timings->vblank;
  1008. timings->vfreq = timings->hfreq/timings->vtotal;
  1009. }
  1010. /*
  1011. * fb_get_mode - calculates video mode using VESA GTF
  1012. * @flags: if: 0 - maximize vertical refresh rate
  1013. * 1 - vrefresh-driven calculation;
  1014. * 2 - hscan-driven calculation;
  1015. * 3 - pixelclock-driven calculation;
  1016. * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
  1017. * @var: pointer to fb_var_screeninfo
  1018. * @info: pointer to fb_info
  1019. *
  1020. * DESCRIPTION:
  1021. * Calculates video mode based on monitor specs using VESA GTF.
  1022. * The GTF is best for VESA GTF compliant monitors but is
  1023. * specifically formulated to work for older monitors as well.
  1024. *
  1025. * If @flag==0, the function will attempt to maximize the
  1026. * refresh rate. Otherwise, it will calculate timings based on
  1027. * the flag and accompanying value.
  1028. *
  1029. * If FB_IGNOREMON bit is set in @flags, monitor specs will be
  1030. * ignored and @var will be filled with the calculated timings.
  1031. *
  1032. * All calculations are based on the VESA GTF Spreadsheet
  1033. * available at VESA's public ftp (http://www.vesa.org).
  1034. *
  1035. * NOTES:
  1036. * The timings generated by the GTF will be different from VESA
  1037. * DMT. It might be a good idea to keep a table of standard
  1038. * VESA modes as well. The GTF may also not work for some displays,
  1039. * such as, and especially, analog TV.
  1040. *
  1041. * REQUIRES:
  1042. * A valid info->monspecs, otherwise 'safe numbers' will be used.
  1043. */
  1044. int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
  1045. {
  1046. struct __fb_timings *timings;
  1047. u32 interlace = 1, dscan = 1;
  1048. u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
  1049. timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
  1050. if (!timings)
  1051. return -ENOMEM;
  1052. /*
  1053. * If monspecs are invalid, use values that are enough
  1054. * for 640x480@60
  1055. */
  1056. if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
  1057. !info->monspecs.dclkmax ||
  1058. info->monspecs.hfmax < info->monspecs.hfmin ||
  1059. info->monspecs.vfmax < info->monspecs.vfmin ||
  1060. info->monspecs.dclkmax < info->monspecs.dclkmin) {
  1061. hfmin = 29000; hfmax = 30000;
  1062. vfmin = 60; vfmax = 60;
  1063. dclkmin = 0; dclkmax = 25000000;
  1064. } else {
  1065. hfmin = info->monspecs.hfmin;
  1066. hfmax = info->monspecs.hfmax;
  1067. vfmin = info->monspecs.vfmin;
  1068. vfmax = info->monspecs.vfmax;
  1069. dclkmin = info->monspecs.dclkmin;
  1070. dclkmax = info->monspecs.dclkmax;
  1071. }
  1072. timings->hactive = var->xres;
  1073. timings->vactive = var->yres;
  1074. if (var->vmode & FB_VMODE_INTERLACED) {
  1075. timings->vactive /= 2;
  1076. interlace = 2;
  1077. }
  1078. if (var->vmode & FB_VMODE_DOUBLE) {
  1079. timings->vactive *= 2;
  1080. dscan = 2;
  1081. }
  1082. switch (flags & ~FB_IGNOREMON) {
  1083. case FB_MAXTIMINGS: /* maximize refresh rate */
  1084. timings->hfreq = hfmax;
  1085. fb_timings_hfreq(timings);
  1086. if (timings->vfreq > vfmax) {
  1087. timings->vfreq = vfmax;
  1088. fb_timings_vfreq(timings);
  1089. }
  1090. if (timings->dclk > dclkmax) {
  1091. timings->dclk = dclkmax;
  1092. fb_timings_dclk(timings);
  1093. }
  1094. break;
  1095. case FB_VSYNCTIMINGS: /* vrefresh driven */
  1096. timings->vfreq = val;
  1097. fb_timings_vfreq(timings);
  1098. break;
  1099. case FB_HSYNCTIMINGS: /* hsync driven */
  1100. timings->hfreq = val;
  1101. fb_timings_hfreq(timings);
  1102. break;
  1103. case FB_DCLKTIMINGS: /* pixelclock driven */
  1104. timings->dclk = PICOS2KHZ(val) * 1000;
  1105. fb_timings_dclk(timings);
  1106. break;
  1107. default:
  1108. err = -EINVAL;
  1109. }
  1110. if (err || (!(flags & FB_IGNOREMON) &&
  1111. (timings->vfreq < vfmin || timings->vfreq > vfmax ||
  1112. timings->hfreq < hfmin || timings->hfreq > hfmax ||
  1113. timings->dclk < dclkmin || timings->dclk > dclkmax))) {
  1114. err = -EINVAL;
  1115. } else {
  1116. var->pixclock = KHZ2PICOS(timings->dclk/1000);
  1117. var->hsync_len = (timings->htotal * 8)/100;
  1118. var->right_margin = (timings->hblank/2) - var->hsync_len;
  1119. var->left_margin = timings->hblank - var->right_margin -
  1120. var->hsync_len;
  1121. var->vsync_len = (3 * interlace)/dscan;
  1122. var->lower_margin = (1 * interlace)/dscan;
  1123. var->upper_margin = (timings->vblank * interlace)/dscan -
  1124. (var->vsync_len + var->lower_margin);
  1125. }
  1126. kfree(timings);
  1127. return err;
  1128. }
  1129. #else
  1130. int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
  1131. {
  1132. return 1;
  1133. }
  1134. void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
  1135. {
  1136. specs = NULL;
  1137. }
  1138. void fb_destroy_modedb(struct fb_videomode *modedb)
  1139. {
  1140. }
  1141. int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
  1142. struct fb_info *info)
  1143. {
  1144. return -EINVAL;
  1145. }
  1146. #endif /* CONFIG_FB_MODE_HELPERS */
  1147. /*
  1148. * fb_validate_mode - validates var against monitor capabilities
  1149. * @var: pointer to fb_var_screeninfo
  1150. * @info: pointer to fb_info
  1151. *
  1152. * DESCRIPTION:
  1153. * Validates video mode against monitor capabilities specified in
  1154. * info->monspecs.
  1155. *
  1156. * REQUIRES:
  1157. * A valid info->monspecs.
  1158. */
  1159. int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
  1160. {
  1161. u32 hfreq, vfreq, htotal, vtotal, pixclock;
  1162. u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
  1163. /*
  1164. * If monspecs are invalid, use values that are enough
  1165. * for 640x480@60
  1166. */
  1167. if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
  1168. !info->monspecs.dclkmax ||
  1169. info->monspecs.hfmax < info->monspecs.hfmin ||
  1170. info->monspecs.vfmax < info->monspecs.vfmin ||
  1171. info->monspecs.dclkmax < info->monspecs.dclkmin) {
  1172. hfmin = 29000; hfmax = 30000;
  1173. vfmin = 60; vfmax = 60;
  1174. dclkmin = 0; dclkmax = 25000000;
  1175. } else {
  1176. hfmin = info->monspecs.hfmin;
  1177. hfmax = info->monspecs.hfmax;
  1178. vfmin = info->monspecs.vfmin;
  1179. vfmax = info->monspecs.vfmax;
  1180. dclkmin = info->monspecs.dclkmin;
  1181. dclkmax = info->monspecs.dclkmax;
  1182. }
  1183. if (!var->pixclock)
  1184. return -EINVAL;
  1185. pixclock = PICOS2KHZ(var->pixclock) * 1000;
  1186. htotal = var->xres + var->right_margin + var->hsync_len +
  1187. var->left_margin;
  1188. vtotal = var->yres + var->lower_margin + var->vsync_len +
  1189. var->upper_margin;
  1190. if (var->vmode & FB_VMODE_INTERLACED)
  1191. vtotal /= 2;
  1192. if (var->vmode & FB_VMODE_DOUBLE)
  1193. vtotal *= 2;
  1194. hfreq = pixclock/htotal;
  1195. hfreq = (hfreq + 500) / 1000 * 1000;
  1196. vfreq = hfreq/vtotal;
  1197. return (vfreq < vfmin || vfreq > vfmax ||
  1198. hfreq < hfmin || hfreq > hfmax ||
  1199. pixclock < dclkmin || pixclock > dclkmax) ?
  1200. -EINVAL : 0;
  1201. }
  1202. #if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
  1203. /*
  1204. * We need to ensure that the EDID block is only returned for
  1205. * the primary graphics adapter.
  1206. */
  1207. const unsigned char *fb_firmware_edid(struct device *device)
  1208. {
  1209. struct pci_dev *dev = NULL;
  1210. struct resource *res = NULL;
  1211. unsigned char *edid = NULL;
  1212. if (device)
  1213. dev = to_pci_dev(device);
  1214. if (dev)
  1215. res = &dev->resource[PCI_ROM_RESOURCE];
  1216. if (res && res->flags & IORESOURCE_ROM_SHADOW)
  1217. edid = edid_info.dummy;
  1218. return edid;
  1219. }
  1220. #else
  1221. const unsigned char *fb_firmware_edid(struct device *device)
  1222. {
  1223. return NULL;
  1224. }
  1225. #endif
  1226. EXPORT_SYMBOL(fb_firmware_edid);
  1227. EXPORT_SYMBOL(fb_parse_edid);
  1228. EXPORT_SYMBOL(fb_edid_to_monspecs);
  1229. EXPORT_SYMBOL(fb_get_mode);
  1230. EXPORT_SYMBOL(fb_validate_mode);
  1231. EXPORT_SYMBOL(fb_destroy_modedb);