File Index
Files and directories
Sign in
FILE

fbmon.c

File preview with syntax highlighting.

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