1235783Skib/*
2235783Skib * Copyright (c) 2006 Luc Verhaegen (quirks list)
3235783Skib * Copyright (c) 2007-2008 Intel Corporation
4235783Skib *   Jesse Barnes <jesse.barnes@intel.com>
5235783Skib * Copyright 2010 Red Hat, Inc.
6235783Skib *
7235783Skib * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
8235783Skib * FB layer.
9235783Skib *   Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
10235783Skib *
11235783Skib * Permission is hereby granted, free of charge, to any person obtaining a
12235783Skib * copy of this software and associated documentation files (the "Software"),
13235783Skib * to deal in the Software without restriction, including without limitation
14235783Skib * the rights to use, copy, modify, merge, publish, distribute, sub license,
15235783Skib * and/or sell copies of the Software, and to permit persons to whom the
16235783Skib * Software is furnished to do so, subject to the following conditions:
17235783Skib *
18235783Skib * The above copyright notice and this permission notice (including the
19235783Skib * next paragraph) shall be included in all copies or substantial portions
20235783Skib * of the Software.
21235783Skib *
22235783Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23235783Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24235783Skib * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
25235783Skib * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26235783Skib * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27235783Skib * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28235783Skib * DEALINGS IN THE SOFTWARE.
29235783Skib */
30235783Skib
31235783Skib#include <sys/cdefs.h>
32235783Skib__FBSDID("$FreeBSD$");
33235783Skib
34235783Skib#include <dev/drm2/drmP.h>
35235783Skib#include <dev/drm2/drm_edid.h>
36235783Skib#include <dev/drm2/drm_edid_modes.h>
37235783Skib#include <dev/iicbus/iic.h>
38235783Skib#include <dev/iicbus/iiconf.h>
39235783Skib#include "iicbus_if.h"
40235783Skib
41235783Skib#define version_greater(edid, maj, min) \
42235783Skib	(((edid)->version > (maj)) || \
43235783Skib	 ((edid)->version == (maj) && (edid)->revision > (min)))
44235783Skib
45235783Skib#define EDID_EST_TIMINGS 16
46235783Skib#define EDID_STD_TIMINGS 8
47235783Skib#define EDID_DETAILED_TIMINGS 4
48235783Skib
49235783Skib/*
50235783Skib * EDID blocks out in the wild have a variety of bugs, try to collect
51235783Skib * them here (note that userspace may work around broken monitors first,
52235783Skib * but fixes should make their way here so that the kernel "just works"
53235783Skib * on as many displays as possible).
54235783Skib */
55235783Skib
56235783Skib/* First detailed mode wrong, use largest 60Hz mode */
57235783Skib#define EDID_QUIRK_PREFER_LARGE_60		(1 << 0)
58235783Skib/* Reported 135MHz pixel clock is too high, needs adjustment */
59235783Skib#define EDID_QUIRK_135_CLOCK_TOO_HIGH		(1 << 1)
60235783Skib/* Prefer the largest mode at 75 Hz */
61235783Skib#define EDID_QUIRK_PREFER_LARGE_75		(1 << 2)
62235783Skib/* Detail timing is in cm not mm */
63235783Skib#define EDID_QUIRK_DETAILED_IN_CM		(1 << 3)
64235783Skib/* Detailed timing descriptors have bogus size values, so just take the
65235783Skib * maximum size and use that.
66235783Skib */
67235783Skib#define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE	(1 << 4)
68235783Skib/* Monitor forgot to set the first detailed is preferred bit. */
69235783Skib#define EDID_QUIRK_FIRST_DETAILED_PREFERRED	(1 << 5)
70235783Skib/* use +hsync +vsync for detailed mode */
71235783Skib#define EDID_QUIRK_DETAILED_SYNC_PP		(1 << 6)
72235783Skib
73235783Skibstruct detailed_mode_closure {
74235783Skib	struct drm_connector *connector;
75235783Skib	struct edid *edid;
76235783Skib	bool preferred;
77235783Skib	u32 quirks;
78235783Skib	int modes;
79235783Skib};
80235783Skib
81235783Skib#define LEVEL_DMT	0
82235783Skib#define LEVEL_GTF	1
83235783Skib#define LEVEL_GTF2	2
84235783Skib#define LEVEL_CVT	3
85235783Skib
86235783Skibstatic struct edid_quirk {
87235783Skib	char *vendor;
88235783Skib	int product_id;
89235783Skib	u32 quirks;
90235783Skib} edid_quirk_list[] = {
91235783Skib	/* Acer AL1706 */
92235783Skib	{ "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },
93235783Skib	/* Acer F51 */
94235783Skib	{ "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 },
95235783Skib	/* Unknown Acer */
96235783Skib	{ "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
97235783Skib
98235783Skib	/* Belinea 10 15 55 */
99235783Skib	{ "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
100235783Skib	{ "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
101235783Skib
102235783Skib	/* Envision Peripherals, Inc. EN-7100e */
103235783Skib	{ "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH },
104235783Skib	/* Envision EN2028 */
105235783Skib	{ "EPI", 8232, EDID_QUIRK_PREFER_LARGE_60 },
106235783Skib
107235783Skib	/* Funai Electronics PM36B */
108235783Skib	{ "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 |
109235783Skib	  EDID_QUIRK_DETAILED_IN_CM },
110235783Skib
111235783Skib	/* LG Philips LCD LP154W01-A5 */
112235783Skib	{ "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
113235783Skib	{ "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
114235783Skib
115235783Skib	/* Philips 107p5 CRT */
116235783Skib	{ "PHL", 57364, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
117235783Skib
118235783Skib	/* Proview AY765C */
119235783Skib	{ "PTS", 765, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
120235783Skib
121235783Skib	/* Samsung SyncMaster 205BW.  Note: irony */
122235783Skib	{ "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP },
123235783Skib	/* Samsung SyncMaster 22[5-6]BW */
124235783Skib	{ "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 },
125235783Skib	{ "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },
126235783Skib};
127235783Skib
128235783Skib/*** DDC fetch and block validation ***/
129235783Skib
130235783Skibstatic const u8 edid_header[] = {
131235783Skib	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
132235783Skib};
133235783Skib
134235783Skib /*
135235783Skib * Sanity check the header of the base EDID block.  Return 8 if the header
136235783Skib * is perfect, down to 0 if it's totally wrong.
137235783Skib */
138235783Skibint drm_edid_header_is_valid(const u8 *raw_edid)
139235783Skib{
140235783Skib	int i, score = 0;
141235783Skib
142235783Skib	for (i = 0; i < sizeof(edid_header); i++)
143235783Skib		if (raw_edid[i] == edid_header[i])
144235783Skib			score++;
145235783Skib
146235783Skib	return score;
147235783Skib}
148235783Skib
149235783Skib/*
150235783Skib * Sanity check the EDID block (base or extension).  Return 0 if the block
151235783Skib * doesn't check out, or 1 if it's valid.
152235783Skib */
153235783Skibstatic bool
154235783Skibdrm_edid_block_valid(u8 *raw_edid)
155235783Skib{
156235783Skib	int i;
157235783Skib	u8 csum = 0;
158235783Skib	struct edid *edid = (struct edid *)raw_edid;
159235783Skib
160235783Skib	if (raw_edid[0] == 0x00) {
161235783Skib		int score = drm_edid_header_is_valid(raw_edid);
162235783Skib		if (score == 8) ;
163235783Skib		else if (score >= 6) {
164235783Skib			DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
165235783Skib			memcpy(raw_edid, edid_header, sizeof(edid_header));
166235783Skib		} else {
167235783Skib			goto bad;
168235783Skib		}
169235783Skib	}
170235783Skib
171235783Skib	for (i = 0; i < EDID_LENGTH; i++)
172235783Skib		csum += raw_edid[i];
173235783Skib	if (csum) {
174259745Sdumbbell		DRM_DEBUG("EDID checksum is invalid, remainder is %d\n", csum);
175235783Skib
176235783Skib		/* allow CEA to slide through, switches mangle this */
177235783Skib		if (raw_edid[0] != 0x02)
178235783Skib			goto bad;
179235783Skib	}
180235783Skib
181235783Skib	/* per-block-type checks */
182235783Skib	switch (raw_edid[0]) {
183235783Skib	case 0: /* base */
184235783Skib		if (edid->version != 1) {
185235783Skib			DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
186235783Skib			goto bad;
187235783Skib		}
188235783Skib
189235783Skib		if (edid->revision > 4)
190235783Skib			DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
191235783Skib		break;
192235783Skib
193235783Skib	default:
194235783Skib		break;
195235783Skib	}
196235783Skib
197235783Skib	return 1;
198235783Skib
199235783Skibbad:
200235783Skib	if (raw_edid) {
201235783Skib		DRM_DEBUG_KMS("Raw EDID:\n");
202235783Skib		if ((drm_debug_flag & DRM_DEBUGBITS_KMS) != 0) {
203235783Skib			for (i = 0; i < EDID_LENGTH; ) {
204235783Skib				printf("%02x", raw_edid[i]);
205235783Skib				i++;
206235783Skib				if (i % 16 == 0 || i == EDID_LENGTH)
207235783Skib					printf("\n");
208235783Skib				else if (i % 8 == 0)
209235783Skib					printf("  ");
210235783Skib				else
211235783Skib					printf(" ");
212235783Skib			}
213235783Skib		}
214235783Skib	}
215235783Skib	return 0;
216235783Skib}
217235783Skib
218235783Skib/**
219235783Skib * drm_edid_is_valid - sanity check EDID data
220235783Skib * @edid: EDID data
221235783Skib *
222235783Skib * Sanity-check an entire EDID record (including extensions)
223235783Skib */
224235783Skibbool drm_edid_is_valid(struct edid *edid)
225235783Skib{
226235783Skib	int i;
227235783Skib	u8 *raw = (u8 *)edid;
228235783Skib
229235783Skib	if (!edid)
230235783Skib		return false;
231235783Skib
232235783Skib	for (i = 0; i <= edid->extensions; i++)
233235783Skib		if (!drm_edid_block_valid(raw + i * EDID_LENGTH))
234235783Skib			return false;
235235783Skib
236235783Skib	return true;
237235783Skib}
238235783Skib
239235783Skib#define DDC_ADDR 0x50
240235783Skib#define DDC_SEGMENT_ADDR 0x30
241235783Skib/**
242235783Skib * Get EDID information via I2C.
243235783Skib *
244235783Skib * \param adapter : i2c device adaptor
245235783Skib * \param buf     : EDID data buffer to be filled
246235783Skib * \param len     : EDID data buffer length
247235783Skib * \return 0 on success or -1 on failure.
248235783Skib *
249235783Skib * Try to fetch EDID information by calling i2c driver function.
250235783Skib */
251235783Skibstatic int
252235783Skibdrm_do_probe_ddc_edid(device_t adapter, unsigned char *buf,
253235783Skib		      int block, int len)
254235783Skib{
255235783Skib	unsigned char start = block * EDID_LENGTH;
256254833Sdumbbell	unsigned char segment = block >> 1;
257254833Sdumbbell	unsigned char xfers = segment ? 3 : 2;
258235783Skib	int ret, retries = 5;
259235783Skib
260235783Skib	/* The core i2c driver will automatically retry the transfer if the
261235783Skib	 * adapter reports EAGAIN. However, we find that bit-banging transfers
262235783Skib	 * are susceptible to errors under a heavily loaded machine and
263235783Skib	 * generate spurious NAKs and timeouts. Retrying the transfer
264235783Skib	 * of the individual block a few times seems to overcome this.
265235783Skib	 */
266235783Skib	do {
267235783Skib		struct iic_msg msgs[] = {
268235783Skib			{
269254833Sdumbbell				.slave  = DDC_SEGMENT_ADDR << 1,
270254833Sdumbbell				.flags  = 0,
271254833Sdumbbell				.len    = 1,
272254833Sdumbbell				.buf    = &segment,
273254833Sdumbbell			}, {
274249041Sdumbbell				.slave	= DDC_ADDR << 1,
275235783Skib				.flags	= IIC_M_WR,
276235783Skib				.len	= 1,
277235783Skib				.buf	= &start,
278235783Skib			}, {
279249041Sdumbbell				.slave	= DDC_ADDR << 1,
280235783Skib				.flags	= IIC_M_RD,
281235783Skib				.len	= len,
282235783Skib				.buf	= buf,
283235783Skib			}
284235783Skib		};
285254833Sdumbbell
286254833Sdumbbell	/*
287254833Sdumbbell	 * Avoid sending the segment addr to not upset non-compliant ddc
288254833Sdumbbell	 * monitors.
289254833Sdumbbell	 */
290254833Sdumbbell		ret = iicbus_transfer(adapter, &msgs[3 - xfers], xfers);
291254833Sdumbbell
292235783Skib		if (ret != 0)
293235783Skib			DRM_DEBUG_KMS("iicbus_transfer countdown %d error %d\n",
294235783Skib			    retries, ret);
295235783Skib	} while (ret != 0 && --retries);
296235783Skib
297235783Skib	return (ret == 0 ? 0 : -1);
298235783Skib}
299235783Skib
300235783Skibstatic bool drm_edid_is_zero(u8 *in_edid, int length)
301235783Skib{
302235783Skib	int i;
303235783Skib	u32 *raw_edid = (u32 *)in_edid;
304235783Skib
305235783Skib	for (i = 0; i < length / 4; i++)
306235783Skib		if (*(raw_edid + i) != 0)
307235783Skib			return false;
308235783Skib	return true;
309235783Skib}
310235783Skib
311235783Skibstatic u8 *
312235783Skibdrm_do_get_edid(struct drm_connector *connector, device_t adapter)
313235783Skib{
314235783Skib	int i, j = 0, valid_extensions = 0;
315235783Skib	u8 *block, *new;
316235783Skib
317235783Skib	block = malloc(EDID_LENGTH, DRM_MEM_KMS, M_WAITOK | M_ZERO);
318235783Skib
319235783Skib	/* base block fetch */
320235783Skib	for (i = 0; i < 4; i++) {
321235783Skib		if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
322235783Skib			goto out;
323235783Skib		if (drm_edid_block_valid(block))
324235783Skib			break;
325235783Skib		if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
326235783Skib			connector->null_edid_counter++;
327235783Skib			goto carp;
328235783Skib		}
329235783Skib	}
330235783Skib	if (i == 4)
331235783Skib		goto carp;
332235783Skib
333235783Skib	/* if there's no extensions, we're done */
334235783Skib	if (block[0x7e] == 0)
335235783Skib		return block;
336235783Skib
337235783Skib	new = reallocf(block, (block[0x7e] + 1) * EDID_LENGTH, DRM_MEM_KMS,
338235783Skib	    M_WAITOK);
339235783Skib	block = new;
340235783Skib
341235783Skib	for (j = 1; j <= block[0x7e]; j++) {
342235783Skib		for (i = 0; i < 4; i++) {
343235783Skib			if (drm_do_probe_ddc_edid(adapter,
344235783Skib				  block + (valid_extensions + 1) * EDID_LENGTH,
345235783Skib				  j, EDID_LENGTH))
346235783Skib				goto out;
347235783Skib			if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH)) {
348235783Skib				valid_extensions++;
349235783Skib				break;
350235783Skib			}
351235783Skib		}
352235783Skib		if (i == 4)
353235783Skib			DRM_DEBUG_KMS("%s: Ignoring invalid EDID block %d.\n",
354235783Skib			     drm_get_connector_name(connector), j);
355235783Skib	}
356235783Skib
357235783Skib	if (valid_extensions != block[0x7e]) {
358235783Skib		block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
359235783Skib		block[0x7e] = valid_extensions;
360235783Skib		new = reallocf(block, (valid_extensions + 1) * EDID_LENGTH,
361235783Skib		    DRM_MEM_KMS, M_WAITOK);
362235783Skib		block = new;
363235783Skib	}
364235783Skib
365235783Skib	DRM_DEBUG_KMS("got EDID from %s\n", drm_get_connector_name(connector));
366235783Skib	return block;
367235783Skib
368235783Skibcarp:
369235783Skib	DRM_ERROR("%s: EDID block %d invalid.\n",
370235783Skib	    drm_get_connector_name(connector), j);
371235783Skib
372235783Skibout:
373235783Skib	free(block, DRM_MEM_KMS);
374235783Skib	return NULL;
375235783Skib}
376235783Skib
377235783Skib/**
378235783Skib * Probe DDC presence.
379235783Skib *
380235783Skib * \param adapter : i2c device adaptor
381235783Skib * \return 1 on success
382235783Skib */
383235783Skibstatic bool
384235783Skibdrm_probe_ddc(device_t adapter)
385235783Skib{
386235783Skib	unsigned char out;
387235783Skib
388235783Skib	return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0);
389235783Skib}
390235783Skib
391235783Skib/**
392235783Skib * drm_get_edid - get EDID data, if available
393235783Skib * @connector: connector we're probing
394235783Skib * @adapter: i2c adapter to use for DDC
395235783Skib *
396235783Skib * Poke the given i2c channel to grab EDID data if possible.  If found,
397235783Skib * attach it to the connector.
398235783Skib *
399235783Skib * Return edid data or NULL if we couldn't find any.
400235783Skib */
401235783Skibstruct edid *drm_get_edid(struct drm_connector *connector,
402235783Skib			  device_t adapter)
403235783Skib{
404235783Skib	struct edid *edid = NULL;
405235783Skib
406235783Skib	if (drm_probe_ddc(adapter))
407235783Skib		edid = (struct edid *)drm_do_get_edid(connector, adapter);
408235783Skib
409235783Skib	connector->display_info.raw_edid = (char *)edid;
410235783Skib
411235783Skib	return edid;
412235783Skib
413235783Skib}
414235783Skib
415235783Skib/*** EDID parsing ***/
416235783Skib
417235783Skib/**
418235783Skib * edid_vendor - match a string against EDID's obfuscated vendor field
419235783Skib * @edid: EDID to match
420235783Skib * @vendor: vendor string
421235783Skib *
422235783Skib * Returns true if @vendor is in @edid, false otherwise
423235783Skib */
424235783Skibstatic bool edid_vendor(struct edid *edid, char *vendor)
425235783Skib{
426235783Skib	char edid_vendor[3];
427235783Skib
428235783Skib	edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@';
429235783Skib	edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) |
430235783Skib			  ((edid->mfg_id[1] & 0xe0) >> 5)) + '@';
431235783Skib	edid_vendor[2] = (edid->mfg_id[1] & 0x1f) + '@';
432235783Skib
433235783Skib	return !strncmp(edid_vendor, vendor, 3);
434235783Skib}
435235783Skib
436235783Skib/**
437235783Skib * edid_get_quirks - return quirk flags for a given EDID
438235783Skib * @edid: EDID to process
439235783Skib *
440235783Skib * This tells subsequent routines what fixes they need to apply.
441235783Skib */
442235783Skibstatic u32 edid_get_quirks(struct edid *edid)
443235783Skib{
444235783Skib	struct edid_quirk *quirk;
445235783Skib	int i;
446235783Skib
447235783Skib	for (i = 0; i < DRM_ARRAY_SIZE(edid_quirk_list); i++) {
448235783Skib		quirk = &edid_quirk_list[i];
449235783Skib
450235783Skib		if (edid_vendor(edid, quirk->vendor) &&
451235783Skib		    (EDID_PRODUCT_ID(edid) == quirk->product_id))
452235783Skib			return quirk->quirks;
453235783Skib	}
454235783Skib
455235783Skib	return 0;
456235783Skib}
457235783Skib
458235783Skib#define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay)
459235783Skib#define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh))
460235783Skib
461235783Skib/**
462235783Skib * edid_fixup_preferred - set preferred modes based on quirk list
463235783Skib * @connector: has mode list to fix up
464235783Skib * @quirks: quirks list
465235783Skib *
466235783Skib * Walk the mode list for @connector, clearing the preferred status
467235783Skib * on existing modes and setting it anew for the right mode ala @quirks.
468235783Skib */
469235783Skibstatic void edid_fixup_preferred(struct drm_connector *connector,
470235783Skib				 u32 quirks)
471235783Skib{
472235783Skib	struct drm_display_mode *t, *cur_mode, *preferred_mode;
473235783Skib	int target_refresh = 0;
474235783Skib
475235783Skib	if (list_empty(&connector->probed_modes))
476235783Skib		return;
477235783Skib
478235783Skib	if (quirks & EDID_QUIRK_PREFER_LARGE_60)
479235783Skib		target_refresh = 60;
480235783Skib	if (quirks & EDID_QUIRK_PREFER_LARGE_75)
481235783Skib		target_refresh = 75;
482235783Skib
483235783Skib	preferred_mode = list_first_entry(&connector->probed_modes,
484235783Skib					  struct drm_display_mode, head);
485235783Skib
486235783Skib	list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) {
487235783Skib		cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED;
488235783Skib
489235783Skib		if (cur_mode == preferred_mode)
490235783Skib			continue;
491235783Skib
492235783Skib		/* Largest mode is preferred */
493235783Skib		if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode))
494235783Skib			preferred_mode = cur_mode;
495235783Skib
496235783Skib		/* At a given size, try to get closest to target refresh */
497235783Skib		if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) &&
498235783Skib		    MODE_REFRESH_DIFF(cur_mode, target_refresh) <
499235783Skib		    MODE_REFRESH_DIFF(preferred_mode, target_refresh)) {
500235783Skib			preferred_mode = cur_mode;
501235783Skib		}
502235783Skib	}
503235783Skib
504235783Skib	preferred_mode->type |= DRM_MODE_TYPE_PREFERRED;
505235783Skib}
506235783Skib
507235783Skibstruct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
508235783Skib					   int hsize, int vsize, int fresh)
509235783Skib{
510235783Skib	struct drm_display_mode *mode = NULL;
511235783Skib	int i;
512235783Skib
513235783Skib	for (i = 0; i < drm_num_dmt_modes; i++) {
514235783Skib		struct drm_display_mode *ptr = &drm_dmt_modes[i];
515235783Skib		if (hsize == ptr->hdisplay &&
516235783Skib			vsize == ptr->vdisplay &&
517235783Skib			fresh == drm_mode_vrefresh(ptr)) {
518235783Skib			/* get the expected default mode */
519235783Skib			mode = drm_mode_duplicate(dev, ptr);
520235783Skib			break;
521235783Skib		}
522235783Skib	}
523235783Skib	return mode;
524235783Skib}
525235783Skib
526235783Skibtypedef void detailed_cb(struct detailed_timing *timing, void *closure);
527235783Skib
528235783Skibstatic void
529235783Skibcea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
530235783Skib{
531235783Skib	int i, n = 0;
532235783Skib	u8 rev = ext[0x01], d = ext[0x02];
533235783Skib	u8 *det_base = ext + d;
534235783Skib
535235783Skib	switch (rev) {
536235783Skib	case 0:
537235783Skib		/* can't happen */
538235783Skib		return;
539235783Skib	case 1:
540235783Skib		/* have to infer how many blocks we have, check pixel clock */
541235783Skib		for (i = 0; i < 6; i++)
542235783Skib			if (det_base[18*i] || det_base[18*i+1])
543235783Skib				n++;
544235783Skib		break;
545235783Skib	default:
546235783Skib		/* explicit count */
547235783Skib		n = min(ext[0x03] & 0x0f, 6);
548235783Skib		break;
549235783Skib	}
550235783Skib
551235783Skib	for (i = 0; i < n; i++)
552235783Skib		cb((struct detailed_timing *)(det_base + 18 * i), closure);
553235783Skib}
554235783Skib
555235783Skibstatic void
556235783Skibvtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
557235783Skib{
558235783Skib	unsigned int i, n = min((int)ext[0x02], 6);
559235783Skib	u8 *det_base = ext + 5;
560235783Skib
561235783Skib	if (ext[0x01] != 1)
562235783Skib		return; /* unknown version */
563235783Skib
564235783Skib	for (i = 0; i < n; i++)
565235783Skib		cb((struct detailed_timing *)(det_base + 18 * i), closure);
566235783Skib}
567235783Skib
568235783Skibstatic void
569235783Skibdrm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure)
570235783Skib{
571235783Skib	int i;
572235783Skib	struct edid *edid = (struct edid *)raw_edid;
573235783Skib
574235783Skib	if (edid == NULL)
575235783Skib		return;
576235783Skib
577235783Skib	for (i = 0; i < EDID_DETAILED_TIMINGS; i++)
578235783Skib		cb(&(edid->detailed_timings[i]), closure);
579235783Skib
580235783Skib	for (i = 1; i <= raw_edid[0x7e]; i++) {
581235783Skib		u8 *ext = raw_edid + (i * EDID_LENGTH);
582235783Skib		switch (*ext) {
583235783Skib		case CEA_EXT:
584235783Skib			cea_for_each_detailed_block(ext, cb, closure);
585235783Skib			break;
586235783Skib		case VTB_EXT:
587235783Skib			vtb_for_each_detailed_block(ext, cb, closure);
588235783Skib			break;
589235783Skib		default:
590235783Skib			break;
591235783Skib		}
592235783Skib	}
593235783Skib}
594235783Skib
595235783Skibstatic void
596235783Skibis_rb(struct detailed_timing *t, void *data)
597235783Skib{
598235783Skib	u8 *r = (u8 *)t;
599235783Skib	if (r[3] == EDID_DETAIL_MONITOR_RANGE)
600235783Skib		if (r[15] & 0x10)
601235783Skib			*(bool *)data = true;
602235783Skib}
603235783Skib
604235783Skib/* EDID 1.4 defines this explicitly.  For EDID 1.3, we guess, badly. */
605235783Skibstatic bool
606235783Skibdrm_monitor_supports_rb(struct edid *edid)
607235783Skib{
608235783Skib	if (edid->revision >= 4) {
609235783Skib		bool ret;
610235783Skib		drm_for_each_detailed_block((u8 *)edid, is_rb, &ret);
611235783Skib		return ret;
612235783Skib	}
613235783Skib
614235783Skib	return ((edid->input & DRM_EDID_INPUT_DIGITAL) != 0);
615235783Skib}
616235783Skib
617235783Skibstatic void
618235783Skibfind_gtf2(struct detailed_timing *t, void *data)
619235783Skib{
620235783Skib	u8 *r = (u8 *)t;
621235783Skib	if (r[3] == EDID_DETAIL_MONITOR_RANGE && r[10] == 0x02)
622235783Skib		*(u8 **)data = r;
623235783Skib}
624235783Skib
625235783Skib/* Secondary GTF curve kicks in above some break frequency */
626235783Skibstatic int
627235783Skibdrm_gtf2_hbreak(struct edid *edid)
628235783Skib{
629235783Skib	u8 *r = NULL;
630235783Skib	drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
631235783Skib	return r ? (r[12] * 2) : 0;
632235783Skib}
633235783Skib
634235783Skibstatic int
635235783Skibdrm_gtf2_2c(struct edid *edid)
636235783Skib{
637235783Skib	u8 *r = NULL;
638235783Skib	drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
639235783Skib	return r ? r[13] : 0;
640235783Skib}
641235783Skib
642235783Skibstatic int
643235783Skibdrm_gtf2_m(struct edid *edid)
644235783Skib{
645235783Skib	u8 *r = NULL;
646235783Skib	drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
647235783Skib	return r ? (r[15] << 8) + r[14] : 0;
648235783Skib}
649235783Skib
650235783Skibstatic int
651235783Skibdrm_gtf2_k(struct edid *edid)
652235783Skib{
653235783Skib	u8 *r = NULL;
654235783Skib	drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
655235783Skib	return r ? r[16] : 0;
656235783Skib}
657235783Skib
658235783Skibstatic int
659235783Skibdrm_gtf2_2j(struct edid *edid)
660235783Skib{
661235783Skib	u8 *r = NULL;
662235783Skib	drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
663235783Skib	return r ? r[17] : 0;
664235783Skib}
665235783Skib
666235783Skib/**
667235783Skib * standard_timing_level - get std. timing level(CVT/GTF/DMT)
668235783Skib * @edid: EDID block to scan
669235783Skib */
670235783Skibstatic int standard_timing_level(struct edid *edid)
671235783Skib{
672235783Skib	if (edid->revision >= 2) {
673235783Skib		if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
674235783Skib			return LEVEL_CVT;
675235783Skib		if (drm_gtf2_hbreak(edid))
676235783Skib			return LEVEL_GTF2;
677235783Skib		return LEVEL_GTF;
678235783Skib	}
679235783Skib	return LEVEL_DMT;
680235783Skib}
681235783Skib
682235783Skib/*
683235783Skib * 0 is reserved.  The spec says 0x01 fill for unused timings.  Some old
684235783Skib * monitors fill with ascii space (0x20) instead.
685235783Skib */
686235783Skibstatic int
687235783Skibbad_std_timing(u8 a, u8 b)
688235783Skib{
689235783Skib	return (a == 0x00 && b == 0x00) ||
690235783Skib	       (a == 0x01 && b == 0x01) ||
691235783Skib	       (a == 0x20 && b == 0x20);
692235783Skib}
693235783Skib
694235783Skib/**
695235783Skib * drm_mode_std - convert standard mode info (width, height, refresh) into mode
696235783Skib * @t: standard timing params
697235783Skib * @timing_level: standard timing level
698235783Skib *
699235783Skib * Take the standard timing params (in this case width, aspect, and refresh)
700235783Skib * and convert them into a real mode using CVT/GTF/DMT.
701235783Skib */
702235783Skibstatic struct drm_display_mode *
703235783Skibdrm_mode_std(struct drm_connector *connector, struct edid *edid,
704235783Skib	     struct std_timing *t, int revision)
705235783Skib{
706235783Skib	struct drm_device *dev = connector->dev;
707235783Skib	struct drm_display_mode *m, *mode = NULL;
708235783Skib	int hsize, vsize;
709235783Skib	int vrefresh_rate;
710235783Skib	unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
711235783Skib		>> EDID_TIMING_ASPECT_SHIFT;
712235783Skib	unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
713235783Skib		>> EDID_TIMING_VFREQ_SHIFT;
714235783Skib	int timing_level = standard_timing_level(edid);
715235783Skib
716235783Skib	if (bad_std_timing(t->hsize, t->vfreq_aspect))
717235783Skib		return NULL;
718235783Skib
719235783Skib	/* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
720235783Skib	hsize = t->hsize * 8 + 248;
721235783Skib	/* vrefresh_rate = vfreq + 60 */
722235783Skib	vrefresh_rate = vfreq + 60;
723235783Skib	/* the vdisplay is calculated based on the aspect ratio */
724235783Skib	if (aspect_ratio == 0) {
725235783Skib		if (revision < 3)
726235783Skib			vsize = hsize;
727235783Skib		else
728235783Skib			vsize = (hsize * 10) / 16;
729235783Skib	} else if (aspect_ratio == 1)
730235783Skib		vsize = (hsize * 3) / 4;
731235783Skib	else if (aspect_ratio == 2)
732235783Skib		vsize = (hsize * 4) / 5;
733235783Skib	else
734235783Skib		vsize = (hsize * 9) / 16;
735235783Skib
736235783Skib	/* HDTV hack, part 1 */
737235783Skib	if (vrefresh_rate == 60 &&
738235783Skib	    ((hsize == 1360 && vsize == 765) ||
739235783Skib	     (hsize == 1368 && vsize == 769))) {
740235783Skib		hsize = 1366;
741235783Skib		vsize = 768;
742235783Skib	}
743235783Skib
744235783Skib	/*
745235783Skib	 * If this connector already has a mode for this size and refresh
746235783Skib	 * rate (because it came from detailed or CVT info), use that
747235783Skib	 * instead.  This way we don't have to guess at interlace or
748235783Skib	 * reduced blanking.
749235783Skib	 */
750235783Skib	list_for_each_entry(m, &connector->probed_modes, head)
751235783Skib		if (m->hdisplay == hsize && m->vdisplay == vsize &&
752235783Skib		    drm_mode_vrefresh(m) == vrefresh_rate)
753235783Skib			return NULL;
754235783Skib
755235783Skib	/* HDTV hack, part 2 */
756235783Skib	if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) {
757235783Skib		mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0,
758235783Skib				    false);
759235783Skib		mode->hdisplay = 1366;
760235783Skib		mode->hsync_start = mode->hsync_start - 1;
761235783Skib		mode->hsync_end = mode->hsync_end - 1;
762235783Skib		return mode;
763235783Skib	}
764235783Skib
765235783Skib	/* check whether it can be found in default mode table */
766235783Skib	mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate);
767235783Skib	if (mode)
768235783Skib		return mode;
769235783Skib
770235783Skib	switch (timing_level) {
771235783Skib	case LEVEL_DMT:
772235783Skib		break;
773235783Skib	case LEVEL_GTF:
774235783Skib		mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
775235783Skib		break;
776235783Skib	case LEVEL_GTF2:
777235783Skib		/*
778235783Skib		 * This is potentially wrong if there's ever a monitor with
779235783Skib		 * more than one ranges section, each claiming a different
780235783Skib		 * secondary GTF curve.  Please don't do that.
781235783Skib		 */
782235783Skib		mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
783235783Skib		if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) {
784235783Skib			free(mode, DRM_MEM_KMS);
785235783Skib			mode = drm_gtf_mode_complex(dev, hsize, vsize,
786235783Skib						    vrefresh_rate, 0, 0,
787235783Skib						    drm_gtf2_m(edid),
788235783Skib						    drm_gtf2_2c(edid),
789235783Skib						    drm_gtf2_k(edid),
790235783Skib						    drm_gtf2_2j(edid));
791235783Skib		}
792235783Skib		break;
793235783Skib	case LEVEL_CVT:
794235783Skib		mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
795235783Skib				    false);
796235783Skib		break;
797235783Skib	}
798235783Skib	return mode;
799235783Skib}
800235783Skib
801235783Skib/*
802235783Skib * EDID is delightfully ambiguous about how interlaced modes are to be
803235783Skib * encoded.  Our internal representation is of frame height, but some
804235783Skib * HDTV detailed timings are encoded as field height.
805235783Skib *
806235783Skib * The format list here is from CEA, in frame size.  Technically we
807235783Skib * should be checking refresh rate too.  Whatever.
808235783Skib */
809235783Skibstatic void
810235783Skibdrm_mode_do_interlace_quirk(struct drm_display_mode *mode,
811235783Skib			    struct detailed_pixel_timing *pt)
812235783Skib{
813235783Skib	int i;
814235783Skib	static const struct {
815235783Skib		int w, h;
816235783Skib	} cea_interlaced[] = {
817235783Skib		{ 1920, 1080 },
818235783Skib		{  720,  480 },
819235783Skib		{ 1440,  480 },
820235783Skib		{ 2880,  480 },
821235783Skib		{  720,  576 },
822235783Skib		{ 1440,  576 },
823235783Skib		{ 2880,  576 },
824235783Skib	};
825235783Skib
826235783Skib	if (!(pt->misc & DRM_EDID_PT_INTERLACED))
827235783Skib		return;
828235783Skib
829235783Skib	for (i = 0; i < DRM_ARRAY_SIZE(cea_interlaced); i++) {
830235783Skib		if ((mode->hdisplay == cea_interlaced[i].w) &&
831235783Skib		    (mode->vdisplay == cea_interlaced[i].h / 2)) {
832235783Skib			mode->vdisplay *= 2;
833235783Skib			mode->vsync_start *= 2;
834235783Skib			mode->vsync_end *= 2;
835235783Skib			mode->vtotal *= 2;
836235783Skib			mode->vtotal |= 1;
837235783Skib		}
838235783Skib	}
839235783Skib
840235783Skib	mode->flags |= DRM_MODE_FLAG_INTERLACE;
841235783Skib}
842235783Skib
843235783Skib/**
844235783Skib * drm_mode_detailed - create a new mode from an EDID detailed timing section
845235783Skib * @dev: DRM device (needed to create new mode)
846235783Skib * @edid: EDID block
847235783Skib * @timing: EDID detailed timing info
848235783Skib * @quirks: quirks to apply
849235783Skib *
850235783Skib * An EDID detailed timing block contains enough info for us to create and
851235783Skib * return a new struct drm_display_mode.
852235783Skib */
853235783Skibstatic struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
854235783Skib						  struct edid *edid,
855235783Skib						  struct detailed_timing *timing,
856235783Skib						  u32 quirks)
857235783Skib{
858235783Skib	struct drm_display_mode *mode;
859235783Skib	struct detailed_pixel_timing *pt = &timing->data.pixel_data;
860235783Skib	unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
861235783Skib	unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
862235783Skib	unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
863235783Skib	unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
864235783Skib	unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
865235783Skib	unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
866235783Skib	unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
867235783Skib	unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
868235783Skib
869235783Skib	/* ignore tiny modes */
870235783Skib	if (hactive < 64 || vactive < 64)
871235783Skib		return NULL;
872235783Skib
873235783Skib	if (pt->misc & DRM_EDID_PT_STEREO) {
874235783Skib		printf("stereo mode not supported\n");
875235783Skib		return NULL;
876235783Skib	}
877235783Skib	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
878235783Skib		printf("composite sync not supported\n");
879235783Skib	}
880235783Skib
881235783Skib	/* it is incorrect if hsync/vsync width is zero */
882235783Skib	if (!hsync_pulse_width || !vsync_pulse_width) {
883235783Skib		DRM_DEBUG_KMS("Incorrect Detailed timing. "
884235783Skib				"Wrong Hsync/Vsync pulse width\n");
885235783Skib		return NULL;
886235783Skib	}
887235783Skib	mode = drm_mode_create(dev);
888235783Skib	if (!mode)
889235783Skib		return NULL;
890235783Skib
891235783Skib	mode->type = DRM_MODE_TYPE_DRIVER;
892235783Skib
893235783Skib	if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
894235783Skib		timing->pixel_clock = htole16(1088);
895235783Skib
896235783Skib	mode->clock = le16toh(timing->pixel_clock) * 10;
897235783Skib
898235783Skib	mode->hdisplay = hactive;
899235783Skib	mode->hsync_start = mode->hdisplay + hsync_offset;
900235783Skib	mode->hsync_end = mode->hsync_start + hsync_pulse_width;
901235783Skib	mode->htotal = mode->hdisplay + hblank;
902235783Skib
903235783Skib	mode->vdisplay = vactive;
904235783Skib	mode->vsync_start = mode->vdisplay + vsync_offset;
905235783Skib	mode->vsync_end = mode->vsync_start + vsync_pulse_width;
906235783Skib	mode->vtotal = mode->vdisplay + vblank;
907235783Skib
908235783Skib	/* Some EDIDs have bogus h/vtotal values */
909235783Skib	if (mode->hsync_end > mode->htotal)
910235783Skib		mode->htotal = mode->hsync_end + 1;
911235783Skib	if (mode->vsync_end > mode->vtotal)
912235783Skib		mode->vtotal = mode->vsync_end + 1;
913235783Skib
914235783Skib	drm_mode_do_interlace_quirk(mode, pt);
915235783Skib
916235783Skib	drm_mode_set_name(mode);
917235783Skib
918235783Skib	if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
919235783Skib		pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
920235783Skib	}
921235783Skib
922235783Skib	mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
923235783Skib		DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
924235783Skib	mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
925235783Skib		DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
926235783Skib
927235783Skib	mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
928235783Skib	mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
929235783Skib
930235783Skib	if (quirks & EDID_QUIRK_DETAILED_IN_CM) {
931235783Skib		mode->width_mm *= 10;
932235783Skib		mode->height_mm *= 10;
933235783Skib	}
934235783Skib
935235783Skib	if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
936235783Skib		mode->width_mm = edid->width_cm * 10;
937235783Skib		mode->height_mm = edid->height_cm * 10;
938235783Skib	}
939235783Skib
940235783Skib	return mode;
941235783Skib}
942235783Skib
943235783Skibstatic bool
944235783Skibmode_is_rb(const struct drm_display_mode *mode)
945235783Skib{
946235783Skib	return (mode->htotal - mode->hdisplay == 160) &&
947235783Skib	       (mode->hsync_end - mode->hdisplay == 80) &&
948235783Skib	       (mode->hsync_end - mode->hsync_start == 32) &&
949235783Skib	       (mode->vsync_start - mode->vdisplay == 3);
950235783Skib}
951235783Skib
952235783Skibstatic bool
953235783Skibmode_in_hsync_range(struct drm_display_mode *mode,
954235783Skib		    struct edid *edid, u8 *t)
955235783Skib{
956235783Skib	int hsync, hmin, hmax;
957235783Skib
958235783Skib	hmin = t[7];
959235783Skib	if (edid->revision >= 4)
960235783Skib	    hmin += ((t[4] & 0x04) ? 255 : 0);
961235783Skib	hmax = t[8];
962235783Skib	if (edid->revision >= 4)
963235783Skib	    hmax += ((t[4] & 0x08) ? 255 : 0);
964235783Skib	hsync = drm_mode_hsync(mode);
965235783Skib
966235783Skib	return (hsync <= hmax && hsync >= hmin);
967235783Skib}
968235783Skib
969235783Skibstatic bool
970235783Skibmode_in_vsync_range(struct drm_display_mode *mode,
971235783Skib		    struct edid *edid, u8 *t)
972235783Skib{
973235783Skib	int vsync, vmin, vmax;
974235783Skib
975235783Skib	vmin = t[5];
976235783Skib	if (edid->revision >= 4)
977235783Skib	    vmin += ((t[4] & 0x01) ? 255 : 0);
978235783Skib	vmax = t[6];
979235783Skib	if (edid->revision >= 4)
980235783Skib	    vmax += ((t[4] & 0x02) ? 255 : 0);
981235783Skib	vsync = drm_mode_vrefresh(mode);
982235783Skib
983235783Skib	return (vsync <= vmax && vsync >= vmin);
984235783Skib}
985235783Skib
986235783Skibstatic u32
987235783Skibrange_pixel_clock(struct edid *edid, u8 *t)
988235783Skib{
989235783Skib	/* unspecified */
990235783Skib	if (t[9] == 0 || t[9] == 255)
991235783Skib		return 0;
992235783Skib
993235783Skib	/* 1.4 with CVT support gives us real precision, yay */
994235783Skib	if (edid->revision >= 4 && t[10] == 0x04)
995235783Skib		return (t[9] * 10000) - ((t[12] >> 2) * 250);
996235783Skib
997235783Skib	/* 1.3 is pathetic, so fuzz up a bit */
998235783Skib	return t[9] * 10000 + 5001;
999235783Skib}
1000235783Skib
1001235783Skibstatic bool
1002235783Skibmode_in_range(struct drm_display_mode *mode, struct edid *edid,
1003235783Skib	      struct detailed_timing *timing)
1004235783Skib{
1005235783Skib	u32 max_clock;
1006235783Skib	u8 *t = (u8 *)timing;
1007235783Skib
1008235783Skib	if (!mode_in_hsync_range(mode, edid, t))
1009235783Skib		return false;
1010235783Skib
1011235783Skib	if (!mode_in_vsync_range(mode, edid, t))
1012235783Skib		return false;
1013235783Skib
1014235783Skib	if ((max_clock = range_pixel_clock(edid, t)))
1015235783Skib		if (mode->clock > max_clock)
1016235783Skib			return false;
1017235783Skib
1018235783Skib	/* 1.4 max horizontal check */
1019235783Skib	if (edid->revision >= 4 && t[10] == 0x04)
1020235783Skib		if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3))))
1021235783Skib			return false;
1022235783Skib
1023235783Skib	if (mode_is_rb(mode) && !drm_monitor_supports_rb(edid))
1024235783Skib		return false;
1025235783Skib
1026235783Skib	return true;
1027235783Skib}
1028235783Skib
1029235783Skib/*
1030235783Skib * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will
1031235783Skib * need to account for them.
1032235783Skib */
1033235783Skibstatic int
1034235783Skibdrm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
1035235783Skib			struct detailed_timing *timing)
1036235783Skib{
1037235783Skib	int i, modes = 0;
1038235783Skib	struct drm_display_mode *newmode;
1039235783Skib	struct drm_device *dev = connector->dev;
1040235783Skib
1041235783Skib	for (i = 0; i < drm_num_dmt_modes; i++) {
1042235783Skib		if (mode_in_range(drm_dmt_modes + i, edid, timing)) {
1043235783Skib			newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
1044235783Skib			if (newmode) {
1045235783Skib				drm_mode_probed_add(connector, newmode);
1046235783Skib				modes++;
1047235783Skib			}
1048235783Skib		}
1049235783Skib	}
1050235783Skib
1051235783Skib	return modes;
1052235783Skib}
1053235783Skib
1054235783Skibstatic void
1055235783Skibdo_inferred_modes(struct detailed_timing *timing, void *c)
1056235783Skib{
1057235783Skib	struct detailed_mode_closure *closure = c;
1058235783Skib	struct detailed_non_pixel *data = &timing->data.other_data;
1059235783Skib	int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
1060235783Skib
1061235783Skib	if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE)
1062235783Skib		closure->modes += drm_gtf_modes_for_range(closure->connector,
1063235783Skib							  closure->edid,
1064235783Skib							  timing);
1065235783Skib}
1066235783Skib
1067235783Skibstatic int
1068235783Skibadd_inferred_modes(struct drm_connector *connector, struct edid *edid)
1069235783Skib{
1070235783Skib	struct detailed_mode_closure closure = {
1071235783Skib		connector, edid, 0, 0, 0
1072235783Skib	};
1073235783Skib
1074235783Skib	if (version_greater(edid, 1, 0))
1075235783Skib		drm_for_each_detailed_block((u8 *)edid, do_inferred_modes,
1076235783Skib					    &closure);
1077235783Skib
1078235783Skib	return closure.modes;
1079235783Skib}
1080235783Skib
1081235783Skibstatic int
1082235783Skibdrm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing)
1083235783Skib{
1084235783Skib	int i, j, m, modes = 0;
1085235783Skib	struct drm_display_mode *mode;
1086235783Skib	u8 *est = ((u8 *)timing) + 5;
1087235783Skib
1088235783Skib	for (i = 0; i < 6; i++) {
1089235783Skib		for (j = 7; j > 0; j--) {
1090235783Skib			m = (i * 8) + (7 - j);
1091235783Skib			if (m >= DRM_ARRAY_SIZE(est3_modes))
1092235783Skib				break;
1093235783Skib			if (est[i] & (1 << j)) {
1094235783Skib				mode = drm_mode_find_dmt(connector->dev,
1095235783Skib							 est3_modes[m].w,
1096235783Skib							 est3_modes[m].h,
1097235783Skib							 est3_modes[m].r
1098235783Skib							 /*, est3_modes[m].rb */);
1099235783Skib				if (mode) {
1100235783Skib					drm_mode_probed_add(connector, mode);
1101235783Skib					modes++;
1102235783Skib				}
1103235783Skib			}
1104235783Skib		}
1105235783Skib	}
1106235783Skib
1107235783Skib	return modes;
1108235783Skib}
1109235783Skib
1110235783Skibstatic void
1111235783Skibdo_established_modes(struct detailed_timing *timing, void *c)
1112235783Skib{
1113235783Skib	struct detailed_mode_closure *closure = c;
1114235783Skib	struct detailed_non_pixel *data = &timing->data.other_data;
1115235783Skib
1116235783Skib	if (data->type == EDID_DETAIL_EST_TIMINGS)
1117235783Skib		closure->modes += drm_est3_modes(closure->connector, timing);
1118235783Skib}
1119235783Skib
1120235783Skib/**
1121235783Skib * add_established_modes - get est. modes from EDID and add them
1122235783Skib * @edid: EDID block to scan
1123235783Skib *
1124235783Skib * Each EDID block contains a bitmap of the supported "established modes" list
1125235783Skib * (defined above).  Tease them out and add them to the global modes list.
1126235783Skib */
1127235783Skibstatic int
1128235783Skibadd_established_modes(struct drm_connector *connector, struct edid *edid)
1129235783Skib{
1130235783Skib	struct drm_device *dev = connector->dev;
1131235783Skib	unsigned long est_bits = edid->established_timings.t1 |
1132235783Skib		(edid->established_timings.t2 << 8) |
1133235783Skib		((edid->established_timings.mfg_rsvd & 0x80) << 9);
1134235783Skib	int i, modes = 0;
1135235783Skib	struct detailed_mode_closure closure = {
1136235783Skib		connector, edid, 0, 0, 0
1137235783Skib	};
1138235783Skib
1139235783Skib	for (i = 0; i <= EDID_EST_TIMINGS; i++) {
1140235783Skib		if (est_bits & (1<<i)) {
1141235783Skib			struct drm_display_mode *newmode;
1142235783Skib			newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
1143235783Skib			if (newmode) {
1144235783Skib				drm_mode_probed_add(connector, newmode);
1145235783Skib				modes++;
1146235783Skib			}
1147235783Skib		}
1148235783Skib	}
1149235783Skib
1150235783Skib	if (version_greater(edid, 1, 0))
1151235783Skib		    drm_for_each_detailed_block((u8 *)edid,
1152235783Skib						do_established_modes, &closure);
1153235783Skib
1154235783Skib	return modes + closure.modes;
1155235783Skib}
1156235783Skib
1157235783Skibstatic void
1158235783Skibdo_standard_modes(struct detailed_timing *timing, void *c)
1159235783Skib{
1160235783Skib	struct detailed_mode_closure *closure = c;
1161235783Skib	struct detailed_non_pixel *data = &timing->data.other_data;
1162235783Skib	struct drm_connector *connector = closure->connector;
1163235783Skib	struct edid *edid = closure->edid;
1164235783Skib
1165235783Skib	if (data->type == EDID_DETAIL_STD_MODES) {
1166235783Skib		int i;
1167235783Skib		for (i = 0; i < 6; i++) {
1168235783Skib			struct std_timing *std;
1169235783Skib			struct drm_display_mode *newmode;
1170235783Skib
1171235783Skib			std = &data->data.timings[i];
1172235783Skib			newmode = drm_mode_std(connector, edid, std,
1173235783Skib					       edid->revision);
1174235783Skib			if (newmode) {
1175235783Skib				drm_mode_probed_add(connector, newmode);
1176235783Skib				closure->modes++;
1177235783Skib			}
1178235783Skib		}
1179235783Skib	}
1180235783Skib}
1181235783Skib
1182235783Skib/**
1183235783Skib * add_standard_modes - get std. modes from EDID and add them
1184235783Skib * @edid: EDID block to scan
1185235783Skib *
1186235783Skib * Standard modes can be calculated using the appropriate standard (DMT,
1187235783Skib * GTF or CVT. Grab them from @edid and add them to the list.
1188235783Skib */
1189235783Skibstatic int
1190235783Skibadd_standard_modes(struct drm_connector *connector, struct edid *edid)
1191235783Skib{
1192235783Skib	int i, modes = 0;
1193235783Skib	struct detailed_mode_closure closure = {
1194235783Skib		connector, edid, 0, 0, 0
1195235783Skib	};
1196235783Skib
1197235783Skib	for (i = 0; i < EDID_STD_TIMINGS; i++) {
1198235783Skib		struct drm_display_mode *newmode;
1199235783Skib
1200235783Skib		newmode = drm_mode_std(connector, edid,
1201235783Skib				       &edid->standard_timings[i],
1202235783Skib				       edid->revision);
1203235783Skib		if (newmode) {
1204235783Skib			drm_mode_probed_add(connector, newmode);
1205235783Skib			modes++;
1206235783Skib		}
1207235783Skib	}
1208235783Skib
1209235783Skib	if (version_greater(edid, 1, 0))
1210235783Skib		drm_for_each_detailed_block((u8 *)edid, do_standard_modes,
1211235783Skib					    &closure);
1212235783Skib
1213235783Skib	/* XXX should also look for standard codes in VTB blocks */
1214235783Skib
1215235783Skib	return modes + closure.modes;
1216235783Skib}
1217235783Skib
1218235783Skibstatic int drm_cvt_modes(struct drm_connector *connector,
1219235783Skib			 struct detailed_timing *timing)
1220235783Skib{
1221235783Skib	int i, j, modes = 0;
1222235783Skib	struct drm_display_mode *newmode;
1223235783Skib	struct drm_device *dev = connector->dev;
1224235783Skib	struct cvt_timing *cvt;
1225235783Skib	const int rates[] = { 60, 85, 75, 60, 50 };
1226235783Skib	const u8 empty[3] = { 0, 0, 0 };
1227235783Skib
1228235783Skib	for (i = 0; i < 4; i++) {
1229235783Skib		int width = 0, height;
1230235783Skib		cvt = &(timing->data.other_data.data.cvt[i]);
1231235783Skib
1232235783Skib		if (!memcmp(cvt->code, empty, 3))
1233235783Skib			continue;
1234235783Skib
1235235783Skib		height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2;
1236235783Skib		switch (cvt->code[1] & 0x0c) {
1237235783Skib		case 0x00:
1238235783Skib			width = height * 4 / 3;
1239235783Skib			break;
1240235783Skib		case 0x04:
1241235783Skib			width = height * 16 / 9;
1242235783Skib			break;
1243235783Skib		case 0x08:
1244235783Skib			width = height * 16 / 10;
1245235783Skib			break;
1246235783Skib		case 0x0c:
1247235783Skib			width = height * 15 / 9;
1248235783Skib			break;
1249235783Skib		}
1250235783Skib
1251235783Skib		for (j = 1; j < 5; j++) {
1252235783Skib			if (cvt->code[2] & (1 << j)) {
1253235783Skib				newmode = drm_cvt_mode(dev, width, height,
1254235783Skib						       rates[j], j == 0,
1255235783Skib						       false, false);
1256235783Skib				if (newmode) {
1257235783Skib					drm_mode_probed_add(connector, newmode);
1258235783Skib					modes++;
1259235783Skib				}
1260235783Skib			}
1261235783Skib		}
1262235783Skib	}
1263235783Skib
1264235783Skib	return modes;
1265235783Skib}
1266235783Skib
1267235783Skibstatic void
1268235783Skibdo_cvt_mode(struct detailed_timing *timing, void *c)
1269235783Skib{
1270235783Skib	struct detailed_mode_closure *closure = c;
1271235783Skib	struct detailed_non_pixel *data = &timing->data.other_data;
1272235783Skib
1273235783Skib	if (data->type == EDID_DETAIL_CVT_3BYTE)
1274235783Skib		closure->modes += drm_cvt_modes(closure->connector, timing);
1275235783Skib}
1276235783Skib
1277235783Skibstatic int
1278235783Skibadd_cvt_modes(struct drm_connector *connector, struct edid *edid)
1279235783Skib{
1280235783Skib	struct detailed_mode_closure closure = {
1281235783Skib		connector, edid, 0, 0, 0
1282235783Skib	};
1283235783Skib
1284235783Skib	if (version_greater(edid, 1, 2))
1285235783Skib		drm_for_each_detailed_block((u8 *)edid, do_cvt_mode, &closure);
1286235783Skib
1287235783Skib	/* XXX should also look for CVT codes in VTB blocks */
1288235783Skib
1289235783Skib	return closure.modes;
1290235783Skib}
1291235783Skib
1292235783Skibstatic void
1293235783Skibdo_detailed_mode(struct detailed_timing *timing, void *c)
1294235783Skib{
1295235783Skib	struct detailed_mode_closure *closure = c;
1296235783Skib	struct drm_display_mode *newmode;
1297235783Skib
1298235783Skib	if (timing->pixel_clock) {
1299235783Skib		newmode = drm_mode_detailed(closure->connector->dev,
1300235783Skib					    closure->edid, timing,
1301235783Skib					    closure->quirks);
1302235783Skib		if (!newmode)
1303235783Skib			return;
1304235783Skib
1305235783Skib		if (closure->preferred)
1306235783Skib			newmode->type |= DRM_MODE_TYPE_PREFERRED;
1307235783Skib
1308235783Skib		drm_mode_probed_add(closure->connector, newmode);
1309235783Skib		closure->modes++;
1310235783Skib		closure->preferred = 0;
1311235783Skib	}
1312235783Skib}
1313235783Skib
1314235783Skib/*
1315235783Skib * add_detailed_modes - Add modes from detailed timings
1316235783Skib * @connector: attached connector
1317235783Skib * @edid: EDID block to scan
1318235783Skib * @quirks: quirks to apply
1319235783Skib */
1320235783Skibstatic int
1321235783Skibadd_detailed_modes(struct drm_connector *connector, struct edid *edid,
1322235783Skib		   u32 quirks)
1323235783Skib{
1324235783Skib	struct detailed_mode_closure closure = {
1325235783Skib		connector,
1326235783Skib		edid,
1327235783Skib		1,
1328235783Skib		quirks,
1329235783Skib		0
1330235783Skib	};
1331235783Skib
1332235783Skib	if (closure.preferred && !version_greater(edid, 1, 3))
1333235783Skib		closure.preferred =
1334235783Skib		    (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
1335235783Skib
1336235783Skib	drm_for_each_detailed_block((u8 *)edid, do_detailed_mode, &closure);
1337235783Skib
1338235783Skib	return closure.modes;
1339235783Skib}
1340235783Skib
1341235783Skib#define HDMI_IDENTIFIER 0x000C03
1342235783Skib#define AUDIO_BLOCK	0x01
1343235783Skib#define VENDOR_BLOCK    0x03
1344235783Skib#define SPEAKER_BLOCK	0x04
1345235783Skib#define EDID_BASIC_AUDIO	(1 << 6)
1346235783Skib
1347235783Skib/**
1348235783Skib * Search EDID for CEA extension block.
1349235783Skib */
1350235783Skibu8 *drm_find_cea_extension(struct edid *edid)
1351235783Skib{
1352235783Skib	u8 *edid_ext = NULL;
1353235783Skib	int i;
1354235783Skib
1355235783Skib	/* No EDID or EDID extensions */
1356235783Skib	if (edid == NULL || edid->extensions == 0)
1357235783Skib		return NULL;
1358235783Skib
1359235783Skib	/* Find CEA extension */
1360235783Skib	for (i = 0; i < edid->extensions; i++) {
1361235783Skib		edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
1362235783Skib		if (edid_ext[0] == CEA_EXT)
1363235783Skib			break;
1364235783Skib	}
1365235783Skib
1366235783Skib	if (i == edid->extensions)
1367235783Skib		return NULL;
1368235783Skib
1369235783Skib	return edid_ext;
1370235783Skib}
1371235783Skib
1372235783Skibstatic void
1373235783Skibparse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
1374235783Skib{
1375235783Skib	connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
1376235783Skib
1377235783Skib	connector->dvi_dual = db[6] & 1;
1378235783Skib	connector->max_tmds_clock = db[7] * 5;
1379235783Skib
1380235783Skib	connector->latency_present[0] = db[8] >> 7;
1381235783Skib	connector->latency_present[1] = (db[8] >> 6) & 1;
1382235783Skib	connector->video_latency[0] = db[9];
1383235783Skib	connector->audio_latency[0] = db[10];
1384235783Skib	connector->video_latency[1] = db[11];
1385235783Skib	connector->audio_latency[1] = db[12];
1386235783Skib
1387235783Skib	DRM_DEBUG_KMS("HDMI: DVI dual %d, "
1388235783Skib		    "max TMDS clock %d, "
1389235783Skib		    "latency present %d %d, "
1390235783Skib		    "video latency %d %d, "
1391235783Skib		    "audio latency %d %d\n",
1392235783Skib		    connector->dvi_dual,
1393235783Skib		    connector->max_tmds_clock,
1394235783Skib	      (int) connector->latency_present[0],
1395235783Skib	      (int) connector->latency_present[1],
1396235783Skib		    connector->video_latency[0],
1397235783Skib		    connector->video_latency[1],
1398235783Skib		    connector->audio_latency[0],
1399235783Skib		    connector->audio_latency[1]);
1400235783Skib}
1401235783Skib
1402235783Skibstatic void
1403235783Skibmonitor_name(struct detailed_timing *t, void *data)
1404235783Skib{
1405235783Skib	if (t->data.other_data.type == EDID_DETAIL_MONITOR_NAME)
1406235783Skib		*(u8 **)data = t->data.other_data.data.str.str;
1407235783Skib}
1408235783Skib
1409235783Skib/**
1410235783Skib * drm_edid_to_eld - build ELD from EDID
1411235783Skib * @connector: connector corresponding to the HDMI/DP sink
1412235783Skib * @edid: EDID to parse
1413235783Skib *
1414235783Skib * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver.
1415235783Skib * Some ELD fields are left to the graphics driver caller:
1416235783Skib * - Conn_Type
1417235783Skib * - HDCP
1418235783Skib * - Port_ID
1419235783Skib */
1420235783Skibvoid drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
1421235783Skib{
1422235783Skib	uint8_t *eld = connector->eld;
1423235783Skib	u8 *cea;
1424235783Skib	u8 *name;
1425235783Skib	u8 *db;
1426235783Skib	int sad_count = 0;
1427235783Skib	int mnl;
1428235783Skib	int dbl;
1429235783Skib
1430235783Skib	memset(eld, 0, sizeof(connector->eld));
1431235783Skib
1432235783Skib	cea = drm_find_cea_extension(edid);
1433235783Skib	if (!cea) {
1434235783Skib		DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
1435235783Skib		return;
1436235783Skib	}
1437235783Skib
1438235783Skib	name = NULL;
1439235783Skib	drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
1440235783Skib	for (mnl = 0; name && mnl < 13; mnl++) {
1441235783Skib		if (name[mnl] == 0x0a)
1442235783Skib			break;
1443235783Skib		eld[20 + mnl] = name[mnl];
1444235783Skib	}
1445235783Skib	eld[4] = (cea[1] << 5) | mnl;
1446235783Skib	DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20);
1447235783Skib
1448235783Skib	eld[0] = 2 << 3;		/* ELD version: 2 */
1449235783Skib
1450235783Skib	eld[16] = edid->mfg_id[0];
1451235783Skib	eld[17] = edid->mfg_id[1];
1452235783Skib	eld[18] = edid->prod_code[0];
1453235783Skib	eld[19] = edid->prod_code[1];
1454235783Skib
1455235783Skib	for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
1456235783Skib		dbl = db[0] & 0x1f;
1457235783Skib
1458235783Skib		switch ((db[0] & 0xe0) >> 5) {
1459235783Skib		case AUDIO_BLOCK:	/* Audio Data Block, contains SADs */
1460235783Skib			sad_count = dbl / 3;
1461235783Skib			memcpy(eld + 20 + mnl, &db[1], dbl);
1462235783Skib			break;
1463235783Skib		case SPEAKER_BLOCK:	/* Speaker Allocation Data Block */
1464235783Skib			eld[7] = db[1];
1465235783Skib			break;
1466235783Skib		case VENDOR_BLOCK:
1467235783Skib			/* HDMI Vendor-Specific Data Block */
1468235783Skib			if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
1469235783Skib				parse_hdmi_vsdb(connector, db);
1470235783Skib			break;
1471235783Skib		default:
1472235783Skib			break;
1473235783Skib		}
1474235783Skib	}
1475235783Skib	eld[5] |= sad_count << 4;
1476235783Skib	eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;
1477235783Skib
1478235783Skib	DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count);
1479235783Skib}
1480235783Skib
1481235783Skib/**
1482235783Skib * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond
1483235783Skib * @connector: connector associated with the HDMI/DP sink
1484235783Skib * @mode: the display mode
1485235783Skib */
1486235783Skibint drm_av_sync_delay(struct drm_connector *connector,
1487235783Skib		      struct drm_display_mode *mode)
1488235783Skib{
1489235783Skib	int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
1490235783Skib	int a, v;
1491235783Skib
1492235783Skib	if (!connector->latency_present[0])
1493235783Skib		return 0;
1494235783Skib	if (!connector->latency_present[1])
1495235783Skib		i = 0;
1496235783Skib
1497235783Skib	a = connector->audio_latency[i];
1498235783Skib	v = connector->video_latency[i];
1499235783Skib
1500235783Skib	/*
1501235783Skib	 * HDMI/DP sink doesn't support audio or video?
1502235783Skib	 */
1503235783Skib	if (a == 255 || v == 255)
1504235783Skib		return 0;
1505235783Skib
1506235783Skib	/*
1507235783Skib	 * Convert raw EDID values to millisecond.
1508235783Skib	 * Treat unknown latency as 0ms.
1509235783Skib	 */
1510235783Skib	if (a)
1511235783Skib		a = min(2 * (a - 1), 500);
1512235783Skib	if (v)
1513235783Skib		v = min(2 * (v - 1), 500);
1514235783Skib
1515235783Skib	return max(v - a, 0);
1516235783Skib}
1517235783Skib
1518235783Skib/**
1519235783Skib * drm_select_eld - select one ELD from multiple HDMI/DP sinks
1520235783Skib * @encoder: the encoder just changed display mode
1521235783Skib * @mode: the adjusted display mode
1522235783Skib *
1523235783Skib * It's possible for one encoder to be associated with multiple HDMI/DP sinks.
1524235783Skib * The policy is now hard coded to simply use the first HDMI/DP sink's ELD.
1525235783Skib */
1526235783Skibstruct drm_connector *drm_select_eld(struct drm_encoder *encoder,
1527235783Skib				     struct drm_display_mode *mode)
1528235783Skib{
1529235783Skib	struct drm_connector *connector;
1530235783Skib	struct drm_device *dev = encoder->dev;
1531235783Skib
1532235783Skib	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
1533235783Skib		if (connector->encoder == encoder && connector->eld[0])
1534235783Skib			return connector;
1535235783Skib
1536235783Skib	return NULL;
1537235783Skib}
1538235783Skib
1539235783Skib/**
1540235783Skib * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
1541235783Skib * @edid: monitor EDID information
1542235783Skib *
1543235783Skib * Parse the CEA extension according to CEA-861-B.
1544235783Skib * Return true if HDMI, false if not or unknown.
1545235783Skib */
1546235783Skibbool drm_detect_hdmi_monitor(struct edid *edid)
1547235783Skib{
1548235783Skib	u8 *edid_ext;
1549235783Skib	int i, hdmi_id;
1550235783Skib	int start_offset, end_offset;
1551235783Skib	bool is_hdmi = false;
1552235783Skib
1553235783Skib	edid_ext = drm_find_cea_extension(edid);
1554235783Skib	if (!edid_ext)
1555235783Skib		goto end;
1556235783Skib
1557235783Skib	/* Data block offset in CEA extension block */
1558235783Skib	start_offset = 4;
1559235783Skib	end_offset = edid_ext[2];
1560235783Skib
1561235783Skib	/*
1562235783Skib	 * Because HDMI identifier is in Vendor Specific Block,
1563235783Skib	 * search it from all data blocks of CEA extension.
1564235783Skib	 */
1565235783Skib	for (i = start_offset; i < end_offset;
1566235783Skib		/* Increased by data block len */
1567235783Skib		i += ((edid_ext[i] & 0x1f) + 1)) {
1568235783Skib		/* Find vendor specific block */
1569235783Skib		if ((edid_ext[i] >> 5) == VENDOR_BLOCK) {
1570235783Skib			hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) |
1571235783Skib				  edid_ext[i + 3] << 16;
1572235783Skib			/* Find HDMI identifier */
1573235783Skib			if (hdmi_id == HDMI_IDENTIFIER)
1574235783Skib				is_hdmi = true;
1575235783Skib			break;
1576235783Skib		}
1577235783Skib	}
1578235783Skib
1579235783Skibend:
1580235783Skib	return is_hdmi;
1581235783Skib}
1582235783Skib
1583235783Skib/**
1584235783Skib * drm_detect_monitor_audio - check monitor audio capability
1585235783Skib *
1586235783Skib * Monitor should have CEA extension block.
1587235783Skib * If monitor has 'basic audio', but no CEA audio blocks, it's 'basic
1588235783Skib * audio' only. If there is any audio extension block and supported
1589235783Skib * audio format, assume at least 'basic audio' support, even if 'basic
1590235783Skib * audio' is not defined in EDID.
1591235783Skib *
1592235783Skib */
1593235783Skibbool drm_detect_monitor_audio(struct edid *edid)
1594235783Skib{
1595235783Skib	u8 *edid_ext;
1596235783Skib	int i, j;
1597235783Skib	bool has_audio = false;
1598235783Skib	int start_offset, end_offset;
1599235783Skib
1600235783Skib	edid_ext = drm_find_cea_extension(edid);
1601235783Skib	if (!edid_ext)
1602235783Skib		goto end;
1603235783Skib
1604235783Skib	has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0);
1605235783Skib
1606235783Skib	if (has_audio) {
1607235783Skib		DRM_DEBUG_KMS("Monitor has basic audio support\n");
1608235783Skib		goto end;
1609235783Skib	}
1610235783Skib
1611235783Skib	/* Data block offset in CEA extension block */
1612235783Skib	start_offset = 4;
1613235783Skib	end_offset = edid_ext[2];
1614235783Skib
1615235783Skib	for (i = start_offset; i < end_offset;
1616235783Skib			i += ((edid_ext[i] & 0x1f) + 1)) {
1617235783Skib		if ((edid_ext[i] >> 5) == AUDIO_BLOCK) {
1618235783Skib			has_audio = true;
1619235783Skib			for (j = 1; j < (edid_ext[i] & 0x1f); j += 3)
1620235783Skib				DRM_DEBUG_KMS("CEA audio format %d\n",
1621235783Skib					      (edid_ext[i + j] >> 3) & 0xf);
1622235783Skib			goto end;
1623235783Skib		}
1624235783Skib	}
1625235783Skibend:
1626235783Skib	return has_audio;
1627235783Skib}
1628235783Skib
1629235783Skib/**
1630235783Skib * drm_add_display_info - pull display info out if present
1631235783Skib * @edid: EDID data
1632235783Skib * @info: display info (attached to connector)
1633235783Skib *
1634235783Skib * Grab any available display info and stuff it into the drm_display_info
1635235783Skib * structure that's part of the connector.  Useful for tracking bpp and
1636235783Skib * color spaces.
1637235783Skib */
1638235783Skibstatic void drm_add_display_info(struct edid *edid,
1639235783Skib				 struct drm_display_info *info)
1640235783Skib{
1641235783Skib	u8 *edid_ext;
1642235783Skib
1643235783Skib	info->width_mm = edid->width_cm * 10;
1644235783Skib	info->height_mm = edid->height_cm * 10;
1645235783Skib
1646235783Skib	/* driver figures it out in this case */
1647235783Skib	info->bpc = 0;
1648235783Skib	info->color_formats = 0;
1649235783Skib
1650235783Skib	/* Only defined for 1.4 with digital displays */
1651235783Skib	if (edid->revision < 4)
1652235783Skib		return;
1653235783Skib
1654235783Skib	if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
1655235783Skib		return;
1656235783Skib
1657235783Skib	switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
1658235783Skib	case DRM_EDID_DIGITAL_DEPTH_6:
1659235783Skib		info->bpc = 6;
1660235783Skib		break;
1661235783Skib	case DRM_EDID_DIGITAL_DEPTH_8:
1662235783Skib		info->bpc = 8;
1663235783Skib		break;
1664235783Skib	case DRM_EDID_DIGITAL_DEPTH_10:
1665235783Skib		info->bpc = 10;
1666235783Skib		break;
1667235783Skib	case DRM_EDID_DIGITAL_DEPTH_12:
1668235783Skib		info->bpc = 12;
1669235783Skib		break;
1670235783Skib	case DRM_EDID_DIGITAL_DEPTH_14:
1671235783Skib		info->bpc = 14;
1672235783Skib		break;
1673235783Skib	case DRM_EDID_DIGITAL_DEPTH_16:
1674235783Skib		info->bpc = 16;
1675235783Skib		break;
1676235783Skib	case DRM_EDID_DIGITAL_DEPTH_UNDEF:
1677235783Skib	default:
1678235783Skib		info->bpc = 0;
1679235783Skib		break;
1680235783Skib	}
1681235783Skib
1682235783Skib	info->color_formats = DRM_COLOR_FORMAT_RGB444;
1683235783Skib	if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB444)
1684235783Skib		info->color_formats = DRM_COLOR_FORMAT_YCRCB444;
1685235783Skib	if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB422)
1686235783Skib		info->color_formats = DRM_COLOR_FORMAT_YCRCB422;
1687235783Skib
1688235783Skib	/* Get data from CEA blocks if present */
1689235783Skib	edid_ext = drm_find_cea_extension(edid);
1690235783Skib	if (!edid_ext)
1691235783Skib		return;
1692235783Skib
1693235783Skib	info->cea_rev = edid_ext[1];
1694235783Skib}
1695235783Skib
1696235783Skib/**
1697235783Skib * drm_add_edid_modes - add modes from EDID data, if available
1698235783Skib * @connector: connector we're probing
1699235783Skib * @edid: edid data
1700235783Skib *
1701235783Skib * Add the specified modes to the connector's mode list.
1702235783Skib *
1703235783Skib * Return number of modes added or 0 if we couldn't find any.
1704235783Skib */
1705235783Skibint drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
1706235783Skib{
1707235783Skib	int num_modes = 0;
1708235783Skib	u32 quirks;
1709235783Skib
1710235783Skib	if (edid == NULL) {
1711235783Skib		return 0;
1712235783Skib	}
1713235783Skib	if (!drm_edid_is_valid(edid)) {
1714235783Skib		device_printf(connector->dev->device, "%s: EDID invalid.\n",
1715235783Skib			 drm_get_connector_name(connector));
1716235783Skib		return 0;
1717235783Skib	}
1718235783Skib
1719235783Skib	quirks = edid_get_quirks(edid);
1720235783Skib
1721235783Skib	/*
1722235783Skib	 * EDID spec says modes should be preferred in this order:
1723235783Skib	 * - preferred detailed mode
1724235783Skib	 * - other detailed modes from base block
1725235783Skib	 * - detailed modes from extension blocks
1726235783Skib	 * - CVT 3-byte code modes
1727235783Skib	 * - standard timing codes
1728235783Skib	 * - established timing codes
1729235783Skib	 * - modes inferred from GTF or CVT range information
1730235783Skib	 *
1731235783Skib	 * We get this pretty much right.
1732235783Skib	 *
1733235783Skib	 * XXX order for additional mode types in extension blocks?
1734235783Skib	 */
1735235783Skib	num_modes += add_detailed_modes(connector, edid, quirks);
1736235783Skib	num_modes += add_cvt_modes(connector, edid);
1737235783Skib	num_modes += add_standard_modes(connector, edid);
1738235783Skib	num_modes += add_established_modes(connector, edid);
1739235783Skib	num_modes += add_inferred_modes(connector, edid);
1740235783Skib
1741235783Skib	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
1742235783Skib		edid_fixup_preferred(connector, quirks);
1743235783Skib
1744235783Skib	drm_add_display_info(edid, &connector->display_info);
1745235783Skib
1746235783Skib	return num_modes;
1747235783Skib}
1748235783Skib
1749235783Skib/**
1750235783Skib * drm_add_modes_noedid - add modes for the connectors without EDID
1751235783Skib * @connector: connector we're probing
1752235783Skib * @hdisplay: the horizontal display limit
1753235783Skib * @vdisplay: the vertical display limit
1754235783Skib *
1755235783Skib * Add the specified modes to the connector's mode list. Only when the
1756235783Skib * hdisplay/vdisplay is not beyond the given limit, it will be added.
1757235783Skib *
1758235783Skib * Return number of modes added or 0 if we couldn't find any.
1759235783Skib */
1760235783Skibint drm_add_modes_noedid(struct drm_connector *connector,
1761235783Skib			int hdisplay, int vdisplay)
1762235783Skib{
1763235783Skib	int i, count, num_modes = 0;
1764235783Skib	struct drm_display_mode *mode;
1765235783Skib	struct drm_device *dev = connector->dev;
1766235783Skib
1767235783Skib	count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
1768235783Skib	if (hdisplay < 0)
1769235783Skib		hdisplay = 0;
1770235783Skib	if (vdisplay < 0)
1771235783Skib		vdisplay = 0;
1772235783Skib
1773235783Skib	for (i = 0; i < count; i++) {
1774235783Skib		struct drm_display_mode *ptr = &drm_dmt_modes[i];
1775235783Skib		if (hdisplay && vdisplay) {
1776235783Skib			/*
1777235783Skib			 * Only when two are valid, they will be used to check
1778235783Skib			 * whether the mode should be added to the mode list of
1779235783Skib			 * the connector.
1780235783Skib			 */
1781235783Skib			if (ptr->hdisplay > hdisplay ||
1782235783Skib					ptr->vdisplay > vdisplay)
1783235783Skib				continue;
1784235783Skib		}
1785235783Skib		if (drm_mode_vrefresh(ptr) > 61)
1786235783Skib			continue;
1787235783Skib		mode = drm_mode_duplicate(dev, ptr);
1788235783Skib		if (mode) {
1789235783Skib			drm_mode_probed_add(connector, mode);
1790235783Skib			num_modes++;
1791235783Skib		}
1792235783Skib	}
1793235783Skib	return num_modes;
1794235783Skib}
1795