~gma500/+junk/emgd152-natty

1 by Luca Forina
Upload Emgd 1.5.2 for Natty (override Maverick)
1
/* -*- pse-c -*-
2
 *-----------------------------------------------------------------------------
3
 * Filename: match.c
4
 * $Revision: 1.8 $
5
 *-----------------------------------------------------------------------------
6
 * Copyright © 2002-2010, Intel Corporation.
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms and conditions of the GNU General Public License,
10
 * version 2, as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope it will be useful, but WITHOUT
13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15
 * more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along with
18
 * this program; if not, write to the Free Software Foundation, Inc.,
19
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20
 *
21
 *-----------------------------------------------------------------------------
22
 * Description:
23
 *  
24
 *-----------------------------------------------------------------------------
25
 */
26
27
#define MODULE_NAME hal.mode
28
29
30
#define CURSOR_DEFAULT_WIDTH	64
31
#define CURSOR_DEFAULT_HEIGHT	64
32
33
#include <context.h>
34
#include <igd_init.h>
35
#include <io.h>
36
#include <memory.h>
37
#include <edid.h>
38
#include <pi.h>
39
40
#include <igd_mode.h>
41
#include <igd_errno.h>
42
43
#include <mode.h>
44
#include <config.h>
45
46
#include "match.h"
47
48
/*!
49
 * @addtogroup display_group
50
 * @{
51
 */
52
53
/* Local variables */
54
#ifndef CONFIG_MICRO
55
igd_cursor_info_t default_cursor = {
56
	CURSOR_DEFAULT_WIDTH,
57
	CURSOR_DEFAULT_HEIGHT,
58
	CONFIG_DEFAULT_PF,
59
	0, 0, 0, 0, 0, 0,
60
	0, 0, {0, 0, 0, 0}, IGD_CURSOR_ON, 0, 0, 0, 0
61
};
62
63
/*!
64
 *
65
 * @param cursor_info
66
 * @param display
67
 *
68
 * @return -IGD_INVAL on failure
69
 * @return 0 on success
70
 */
71
int validate_cursor(igd_cursor_info_t *cursor_info,
72
	igd_display_context_t *display)
73
{
74
	unsigned long *list_pfs;
75
	igd_display_pipe_t *pipe = (igd_display_pipe_t *)(display->pipe);
76
77
	EMGD_TRACE_ENTER;
78
	if (pipe) {
79
		if (pipe->cursor) {
80
			list_pfs = pipe->cursor->pixel_formats;
81
82
			while (*list_pfs) {
83
				if (cursor_info->pixel_format == *list_pfs) {
84
					return 0;
85
				}
86
				list_pfs++;
87
			}
88
		}
89
	}
90
91
	EMGD_TRACE_EXIT;
92
	return -IGD_INVAL;
93
}
94
#endif
95
96
/*!
97
 *
98
 * @param timing
99
 * @param pt_info
100
 *
101
 * @return void
102
 */
103
static void fill_pt(
104
	igd_timing_info_t *timing,
105
	pigd_display_info_t pt_info)
106
{
107
	unsigned long flags;
108
109
	EMGD_DEBUG("fill_pt Entry");
110
111
	/* preserve existing pt_info flags */
112
	flags = pt_info->flags;
113
114
	/* Simply memcpy the structures and fix up the flags */
115
	OS_MEMCPY(pt_info, timing, sizeof(igd_timing_info_t));
116
117
	pt_info->flags |= flags;
118
119
	/* pt_info doesn't require a IGD_MODE_VESA flag, so clear IGD_MODE_VESA
120
	 * Setting this flag creates issues in match mode. */
121
	pt_info->flags &= ~IGD_MODE_VESA;
122
	return;
123
}
124
125
#ifndef CONFIG_NEW_MATCH
126
127
128
extern igd_timing_info_t vga_timing_table[];
129
extern igd_timing_info_t crt_timing_table[];
130
131
132
#define MATCH_MOD(x)  ((x>0)?x:-x)
133
#define MATCH_EXACT    0x01
134
#define MATCH_NATIVE   0x02
135
#define MATCH_CENTER   0x10
136
#define MATCH_FOR_VGA  0x20
137
138
/*!
139
 *
140
 * @param display
141
 * @param timing_table
142
 * @param pt_info
143
 * @param type
144
 *
145
 * @return NULL on failure
146
 * @return timing on success
147
 */
148
static igd_timing_info_t *match_resolution(
149
		igd_display_context_t *display,
150
		igd_timing_info_t *timing_table,
151
		igd_display_info_t *pt_info,
152
		int type)
153
{
154
	igd_timing_info_t *timing;
155
	igd_timing_info_t *match;
156
	igd_timing_info_t *native_match = NULL;
157
	igd_display_port_t *port;
158
159
	EMGD_DEBUG("Enter match_resolution");
160
161
	EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
162
		pt_info->width, pt_info->height, pt_info->refresh,
163
		pt_info->mode_number);
164
165
	timing = timing_table;
166
	match = NULL;
167
	port = PORT_OWNER(display);
168
169
	/*
170
	 * Note on Native matching.
171
	 * The Ideal thing is for a fp_native_dtd to already be marked as such.
172
	 * If there is no native timing indicated then we must choose what is
173
	 * most likely correct.
174
	 * If the mode is not VGA then we should choose any DTD that closely
175
	 * matches the mode being set. Failing that we should choose any timing
176
	 * that closely matches the mode.
177
	 * If the mode is VGA then we should take the current mode as it is
178
	 * more likely correct.
179
	 */
180
	if(type == MATCH_NATIVE) {
181
		if(port->fp_native_dtd) {
182
			EMGD_DEBUG("Returning quick with a native match");
183
184
			EMGD_DEBUG("NATIVE Width=%d, height=%d, refresh=%d mode_num=0x%x",
185
				port->fp_native_dtd->width, port->fp_native_dtd->height,
186
				port->fp_native_dtd->refresh, port->fp_native_dtd->mode_number);
187
188
			return port->fp_native_dtd;
189
		}
190
		if((pt_info->flags & IGD_MODE_VESA) &&
191
			(pt_info->mode_number <= 0x13)) {
192
			if(PIPE(display)->timing) {
193
				native_match = PIPE(display)->timing;
194
			}
195
		}
196
	}
197
198
	while (timing->width != IGD_TIMING_TABLE_END) {
199
		if(!(timing->mode_info_flags & IGD_MODE_SUPPORTED)) {
200
			timing++;
201
			continue;
202
		}
203
204
		if(type == MATCH_NATIVE) {
205
			if(timing->mode_info_flags & IGD_MODE_DTD_FP_NATIVE) {
206
				port->fp_native_dtd = timing;
207
				return timing;
208
			}
209
210
			if(port->fp_info) {
211
				/*
212
				 * We may have only fp_width and fp_height which is really
213
				 * not enough information to be useful. If we find a
214
				 * matching width and height we'll keep the first one while
215
				 * still hoping to find an actual native mode later.
216
				 */
217
				if(!match &&
218
					(port->fp_info->fp_width ==
219
						(unsigned long)timing->width) &&
220
					(port->fp_info->fp_height ==
221
						(unsigned long)timing->height)) {
222
					match = timing;
223
				}
224
			} else {
225
				/*
226
				 * Keep a match because in the event that we never find a
227
				 * native DTD then we will just take the exact match.
228
				 */
229
				if(!match &&
230
					(timing->width == pt_info->width) &&
231
					(timing->height == pt_info->height) &&
232
					(timing->refresh == pt_info->refresh)) {
233
					match = timing;
234
				}
235
			}
236
237
			/*
238
			 * If it is a DTD then keep it only if it is better than any
239
			 * found before.
240
			 */
241
			if(timing->mode_info_flags & IGD_MODE_DTD_USER) {
242
				if(native_match) {
243
					if(MATCH_MOD((int)(pt_info->width*pt_info->height) -
244
							(native_match->width * native_match->height)) >
245
						MATCH_MOD((int)(pt_info->width*pt_info->height) -
246
							(timing->width*timing->height))) {
247
						native_match = timing;
248
					}
249
				} else {
250
					native_match = timing;
251
				}
252
			}
253
		} else if (type == MATCH_EXACT) {
254
			/*
255
			 * Looking for an exact match. For VGA/VESA it must match
256
			 * mode number. Otherwise it must match width, height, refresh
257
			 * etc.
258
			 */
259
			if(pt_info->flags & IGD_MODE_VESA) {
260
				/* ((timing->mode_info_flags & IGD_MODE_VESA)) */
261
				if((pt_info->mode_number == timing->mode_number) &&
262
					(!pt_info->refresh ||
263
						(pt_info->refresh == timing->refresh))) {
264
					match = timing;
265
					break;
266
				}
267
			} else {
268
				/* If exact match found, then break the loop */
269
				if((timing->width == pt_info->width) &&
270
					(timing->height == pt_info->height) &&
271
					(timing->refresh == pt_info->refresh) &&
272
					(
273
						(timing->mode_info_flags &
274
							(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
275
								IGD_LINE_DOUBLE)) ==
276
						(pt_info->flags &
277
							(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
278
								IGD_LINE_DOUBLE)))) {
279
					match = timing;
280
281
					/* If exact match found, then break the loop */
282
					if ((timing->mode_info_flags & PD_MODE_DTD_USER) ||
283
						(timing->mode_info_flags & PD_MODE_DTD)) {
284
						break;
285
					}
286
				}
287
			}
288
		}
289
290
291
		/* Center needs only to be bigger. Aspect ratio doesn't matter. */
292
		/*
293
		 * Note: The timings have to be big enough to fit the pt_info
294
		 * including any pixel double flags. VGA modes will sometimes be
295
		 * pixel doubled and need to be centered in a pipe that is double
296
		 * in size.
297
		 *
298
		 * Note2: 720x400 VGA modes can be centered in 640x480 with a
299
		 * special hardware config that drops every 9th pixel. Only do
300
		 * this when requested.
301
		 */
302
		else if(type & MATCH_CENTER) {
303
			unsigned short eff_width = pt_info->width;
304
			unsigned short eff_height = pt_info->height;
305
306
			if(type & MATCH_FOR_VGA) {
307
				/*
308
				 * 720x400 is a magic mode that means all VGA modes are supported
309
				 * always use that mode for centering if found.
310
				 */
311
				if((timing->width == 720) && (timing->height == 400)) {
312
					EMGD_DEBUG("Returning with a magic VGA mode");
313
					return timing;
314
				}
315
				if(pt_info->flags & IGD_PIXEL_DOUBLE) {
316
					eff_width *= 2;
317
				}
318
				if(pt_info->flags & IGD_LINE_DOUBLE) {
319
					eff_height *= 2;
320
				}
321
				if((eff_width == 720) &&
322
					(port->port_features & IGD_VGA_COMPRESS)) {
323
					eff_width = 640;
324
				}
325
			}
326
327
			if((timing->width >= eff_width) &&
328
				(timing->height >= eff_height) &&
329
				(timing->mode_info_flags & IGD_SCAN_INTERLACE) ==
330
				(pt_info->flags & IGD_SCAN_INTERLACE)) {
331
				if(match) {
332
					/* Check for tighter fit */
333
					if((match->width > timing->width) ||
334
						(match->height > timing->height)) {
335
						match = timing;
336
					}
337
					/* Try to match refreshrate as well */
338
					if((match->width == timing->width) &&
339
					   (match->height == timing->height) &&
340
					   (pt_info->refresh == timing->refresh)){
341
						match = timing;
342
					}
343
				} else {
344
					match = timing;
345
				}
346
			}
347
		}
348
		timing++;
349
	}
350
351
	if(native_match) {
352
		EMGD_DEBUG("Returning with a native match");
353
		EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
354
			native_match->width, native_match->height, native_match->refresh,
355
			native_match->mode_number);
356
		return native_match;
357
	}
358
	if (!match) {
359
		EMGD_DEBUG("Returning with NO match");
360
		return NULL;
361
	}
362
363
	EMGD_DEBUG("Returning with a match");
364
	EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
365
		match->width, match->height, match->refresh, match->mode_number);
366
	return match;
367
} /* end match_resolution */
368
369
static igd_timing_info_t scaled_timing[IGD_MAX_PIPES];
370
371
/*!
372
 * Match the fb and pt structures to a Mode Structure from the table.
373
 * When a mode is found update the input structures to reflect the
374
 * values found.
375
 *
376
 * Notes:
377
 *  Match mode has several options for what it can do. Foremost it should
378
 * attempt to find a mode matching the requested one from the timing table
379
 * provided. If the mode requested is not in the list this means one of
380
 * two things.
381
 *   1) The IAL is calling without checking modes. It is just passing down
382
 *  something that a user asked for. This is ok but we need to be safe so
383
 *  we return the next smaller mode with the same aspect ratio.
384
 *
385
 *   2) The IAL is requesting a very common "required" mode even though the
386
 *  port doesn't support it. In this case it should be in the static common
387
 *  modes table and can be centered in the next larger timings in the
388
 *  mode table.
389
 *
390
 * If the Frambuffer is smaller than the timings requested a fake set of
391
 * centered timings is returned to program the pipe.
392
 *
393
 * In the case of VGA modes. If the mode is in the mode table everything is
394
 * fine and we just return that. If it is not in the table we find the next
395
 * larger suitable mode and prepare to center in that mode. Using the static
396
 * timings from the VGA table as the VGA mode. We do not need to generate
397
 * a fake set of timings because VGA will center itself automatically in
398
 * hardware.
399
 *
400
 * In the case of LVDS both centering and scaling can happen. If the mode
401
 * is in the list it will be scaled to the Native Timings. If the mode
402
 * is not in the list (common or VGA) it will be centered in the next larger
403
 * supported mode and then scaled to the native timings.
404
 *
405
 * Centering is always indicated by returning the timings that should be
406
 * programmed to the pipe. The timings will then have their extension pointer
407
 * set to point to the centered timings. For centering with scaling the
408
 * first extension pointer will contain the scalable timings and the
409
 * second will contain the centering timings. The static "scaled_timings"
410
 * data structure will be used when the scaled timings need to be
411
 * created on the fly due to a Framebuffer that is smaller than the
412
 * timings.
413
 *
414
 * @param display
415
 * @param timing_table
416
 * @param fb_info
417
 * @param pt_info
418
 * @param timing
419
 *
420
 * @return -IGD_ERROR_INVAL on failure
421
 * @return 0 on success
422
 */
423
int match_mode (
424
	igd_display_context_t *display,
425
	igd_timing_info_t *timing_table,
426
	igd_framebuffer_info_t *fb_info,
427
	igd_display_info_t *pt_info,
428
	igd_timing_info_t **timing)
429
{
430
	igd_timing_info_t *exact_timing = NULL;
431
	igd_timing_info_t *pipe_timing = NULL;
432
	igd_timing_info_t *user_timing = NULL;
433
	igd_timing_info_t *native_timing = NULL;
434
	igd_timing_info_t *vga_timing = NULL;
435
	igd_timing_info_t *vesa_timing = NULL;
436
	short cntr_dff_w = 0;
437
	short cntr_dff_h = 0;
438
	unsigned long upscale = 0;
439
440
	EMGD_DEBUG("Enter Match Mode");
441
442
	if(!pt_info) {
443
		EMGD_ERROR("NULL Port info detected, returning");
444
		return -IGD_ERROR_INVAL;
445
	}
446
447
	/* Check for default case */
448
	if (!(pt_info->flags & IGD_MODE_VESA) &&
449
		(pt_info->width == 0) && (pt_info->height == 0)) {
450
		EMGD_DEBUG("Display Info width, height are zero, using default case");
451
		pt_info->width = CONFIG_DEFAULT_WIDTH;
452
		pt_info->height = CONFIG_DEFAULT_HEIGHT;
453
	}
454
455
	EMGD_DEBUG("Checking for exact mode match");
456
	exact_timing = match_resolution(display, timing_table, pt_info,
457
		MATCH_EXACT);
458
	/*
459
	 * At this point we have one of these cases:
460
	 *  1) Found an exact match, VGA, VESA or other.
461
	 *    -> Go check for FB centering and finish up.
462
	 *  2) Found nothing
463
	 *    -> Check for VGA/VESA mode to center.
464
	 *    -> Check common modes.
465
	 */
466
	if(exact_timing) {
467
		pipe_timing = exact_timing;
468
		user_timing = exact_timing;
469
		pipe_timing->extn_ptr = NULL;
470
	} else {
471
		/* No match found? Is it VGA? */
472
		if( (pt_info->flags & IGD_MODE_VESA) &&
473
			(pt_info->mode_number < 0x1D)    ){
474
			EMGD_DEBUG("Checking for exact match in VGA table");
475
			/* this only happens if it was a VGA mode number */
476
			pt_info->refresh = 0;
477
			vga_timing = match_resolution(display, vga_timing_table,
478
				pt_info, MATCH_EXACT);
479
480
			if(!vga_timing) {
481
				return -IGD_ERROR_INVAL;
482
			}
483
484
			vga_timing->extn_ptr = NULL;
485
			/* We got something sane that needs to be centered */
486
			user_timing = vga_timing;
487
			fill_pt(vga_timing,pt_info);
488
489
			/* continue at the bottom where we have
490
			 * pipe_timing = NULL, so we will look
491
			 * for centered timings for pt_info and
492
			 * use cmn_vga_timings to tell match_resolution
493
			 * to take into account special VGA mode
494
			 * centering regulations
495
			 */
496
		}
497
	}
498
499
	/* Find UPSCALING attr value*/
500
	pi_pd_find_attr_and_value(PORT_OWNER(display),
501
			PD_ATTR_ID_PANEL_FIT,
502
			0,/*no PD_FLAG for UPSCALING */
503
			NULL, /* dont need the attr ptr*/
504
			&upscale);
505
	/* this PI func will not modify value of upscale if attr does not exist */
506
507
	if(!pipe_timing){
508
		/* At this point, one of 2 things has happenned:
509
		 *      - we have a mode request that we could not match exactly.
510
		 *        and it WASNT a VESA_MODE number request.
511
		 *      - we have a request based on VESA_MODE number (maybe from
512
		 *        VBIOS IAL) and we could not get a exact match from the
513
		 *        port_timing_table, but we did get a match from the vga-
514
		 *        timing_table.
515
		 * In this case, there is one thing to do - MATCH_CENTER. Match
516
		 * resolution will handle it this way:
517
		 *      - if its VESA MODE number based, we only need to get
518
		 *        the best (tightest) match if its VGA OR DONT match
519
		 *        if its one of those magic timings
520
		 *      - Else, we need to get the best (tightest) match, AND
521
		 *        we need to center requested timings in that tightest fitting
522
		 *        timing. But wait! This could mean if the requested pt_info
523
		 *        is bigger than anything in the port timing table, we have
524
		 *        no choice but to fail.
525
		 */
526
		unsigned char match_type = MATCH_CENTER;
527
528
		EMGD_DEBUG("Checking for a safe centered match");
529
		if(vga_timing) {
530
			match_type |= MATCH_FOR_VGA;
531
		} else if(pt_info->flags & IGD_MODE_VESA) {
532
			/* if a vesa mode number was requested...
533
			 * and we are centering that mode, we
534
			 * need to get the common mode fb size
535
			 * in case we need it later for VBIOS
536
			 * which doesnt populate the FBInfo
537
			 */
538
			vesa_timing = match_resolution(display, crt_timing_table,
539
				pt_info, MATCH_EXACT);
540
		}
541
542
		if (upscale && vga_timing) {
543
			/* If port supports upscaling and match is called for VGA,
544
			 * then center vga mode resolution directly in the native mode
545
			 * instead of centering VGA in another resolution */
546
			pipe_timing = vga_timing;
547
		} else {
548
			pipe_timing = match_resolution(display, timing_table, pt_info,
549
				match_type);
550
			/* This can happen if there is a spurious pt_info from IAL */
551
			if (!pipe_timing) {
552
				return -IGD_ERROR_INVAL;
553
			}
554
			pipe_timing->extn_ptr = vga_timing;
555
			/* for the case of non VGA mode call,
556
			 * at this point, vga_timing is NULL
557
			 */
558
		}
559
560
		if(!vga_timing) {
561
			user_timing = pipe_timing;
562
		}
563
	}
564
565
	/*
566
	 * At this point pipe_timing is what we are going to program the
567
	 * pipe to roughly speaking. If there is a common timing then we
568
	 * want it centered in the pipe_timing.
569
	 *
570
	 * If the framebuffer is smaller than the timings then we need to
571
	 * generate a centered set of timings by copying the pipe timings
572
	 * and shifting them a bit.
573
	 *
574
	 * If fb width and height are zero just assume that we want it to
575
	 * match the timings and make up a pixel format. This is mostly because
576
	 * VGA/VESA modes will just be set by number. We don't know their size
577
	 * until we look up the number.
578
	 */
579
	if(fb_info) {
580
		/*
581
		 * fb_info is sometimes NULL when just testing something.
582
		 */
583
		if(!fb_info->pixel_format) {
584
			/* Ugly VGA modes, it doesn't matter */
585
			fb_info->pixel_format = IGD_PF_ARGB8_INDEXED;
586
		}
587
		if(!fb_info->width) {
588
			if(vga_timing) {
589
				fb_info->width = vga_timing->width;
590
				fb_info->height = vga_timing->height;
591
			} else {
592
				if(!vesa_timing){
593
					vesa_timing = pipe_timing;
594
					/* in case vesa_timing is false set it to
595
					 * pipe_timing so we dont need to check for
596
					 * validity later, when increasing fb size for
597
					 * VBIOS in clone mode (see 18 lines below)
598
					 */
599
				}
600
				fb_info->width = vesa_timing->width;
601
				fb_info->height = vesa_timing->height;
602
			}
603
		}
604
605
		/*
606
		 * VGA common timings are centered in pipe timings by hardware.
607
		 * Otherwise we need to adjust the timings when centering is
608
		 * needed.
609
		 */
610
		if (!vga_timing) {
611
			/*
612
			 * For VBIOS clone modes the FB should be the biggest mode
613
			 * if this is the second match we may need to update the fb
614
			 * data structure.
615
			 */
616
			if(fb_info->flags & IGD_VBIOS_FB) {
617
				if ((fb_info->width < vesa_timing->width) ||
618
					(fb_info->height < vesa_timing->height)) {
619
					fb_info->width = vesa_timing->width;
620
					fb_info->height = vesa_timing->height;
621
				}
622
			}
623
624
625
			/* Do centering if fb is smaller than timing except on TV */
626
			if ((fb_info->width < pipe_timing->width) ||
627
				(fb_info->height < pipe_timing->height)) {
628
				unsigned short temp_width = pipe_timing->width;
629
				unsigned short temp_height = pipe_timing->height;
630
				/* Normally, we should NOT be in here. All IALs only
631
				 * are supposed to request for timings that ARE surely
632
				 * supported by the HAL,... i.e. query the list of
633
				 * supported timings by the port first!
634
				 *
635
				 * The exception would be if the IAL is purposely
636
				 * asking for CENTERING!!! (pt_info's that were not
637
				 * part of the supported mode list). This could indicate an
638
				 * error or an explicit request for VESA centering!.
639
				 */
640
641
				/* let's use these 2 variables as flags... and do the
642
				 * actual "centering" of the timings later since we do
643
				 * also need to acomodate native timings as well
644
				 */
645
				/* NOTE: we could never be in here in fb_info was NULL */
646
				cntr_dff_w = (pipe_timing->width - fb_info->width) / 2;
647
				cntr_dff_h = (pipe_timing->height - fb_info->height) / 2;
648
649
				/* Dont forget to use a different storage sice we dont
650
				 * want to change the original (and to be used later)
651
				 * ports mode list timings
652
				 */
653
				OS_MEMCPY(&scaled_timing[(PIPE(display)->pipe_num)],
654
					pipe_timing,
655
					sizeof(igd_timing_info_t));
656
657
				pipe_timing = &scaled_timing[(PIPE(display)->pipe_num)];
658
659
				if(PORT_OWNER(display)->pd_type != PD_DISPLAY_TVOUT ) {
660
					/* TV display don't like changed pipe actives,
661
					 * Updating syncs work for TV centering */
662
					if (fb_info->width < temp_width) {
663
						pipe_timing->width = (unsigned short)fb_info->width;
664
						pipe_timing->hblank_start -= cntr_dff_w;
665
						pipe_timing->hblank_end -= cntr_dff_w;
666
					}
667
668
					if (fb_info->height < temp_height) {
669
						pipe_timing->height = (unsigned short)fb_info->height;
670
						pipe_timing->vblank_start -= cntr_dff_h;
671
						pipe_timing->vblank_end -= cntr_dff_h;
672
					}
673
				}
674
675
				if (fb_info->width < temp_width) {
676
					pipe_timing->hsync_start -= cntr_dff_w;
677
					pipe_timing->hsync_end -= cntr_dff_w;
678
				}
679
680
				if (fb_info->height < temp_height) {
681
					pipe_timing->vsync_start -= cntr_dff_h;
682
					pipe_timing->vsync_end -= cntr_dff_h;
683
				}
684
			}
685
		}
686
	}
687
688
	if(upscale) {
689
		/* Get the native timings */
690
		EMGD_DEBUG("Checking for Native LVDS match for scaling");
691
		native_timing = match_resolution(display, timing_table, pt_info,
692
			MATCH_NATIVE);
693
		if(native_timing && (native_timing != pipe_timing)) {
694
			native_timing->extn_ptr = pipe_timing;
695
			pipe_timing = native_timing;
696
		}
697
	}
698
699
	/*
700
	 * Match mode returns as follows:
701
	 * In case of VGA setmode:
702
	 * 1) We will end up with either:
703
	 *   magic->vga   ---   For displays supports native VGA
704
	 *      or
705
	 *   native->vga  ---   Upscaling displays
706
	 *      or
707
	 *   pipe->vga    ---   For other displays
708
	 *
709
	 * 2) In case of regular setmode:
710
	 *   pipe         ---   For regular displays
711
	 *      or
712
	 *   native->vesa ---   Upscaling displays
713
	 *
714
	 *   Note: 1) Here "pipe" can be munged if centering is required.
715
	 *         2) "vesa" is the requested mode, native is the native timing
716
	 *            of the display.
717
	 */
718
719
	/*
720
	 * Update Input Structures with values found
721
	 * Note: This might not be what is going to be programmed. It is what
722
	 * the user thinks they set. Scaling or centering could have altered
723
	 * that.
724
	 */
725
	fill_pt(user_timing, pt_info);
726
	*timing = pipe_timing;
727
	EMGD_DEBUG("Return");
728
729
	return 0;
730
}
731
#else
732
733
#define MATCH_NUMBER    0x001
734
#define MATCH_REFRESH   0x002
735
#define MATCH_WIDTH     0x004
736
#define MATCH_HEIGHT    0x008
737
#define MATCH_FLAGS     0x010
738
#define MATCH_GE_WIDTH  0x020
739
#define MATCH_GE_HEIGHT 0x040
740
#define MATCH_FOR_VGA   0x100
741
742
static int modes_match(igd_display_info_t *x,
743
	igd_timing_info_t *y,
744
	unsigned int flags)
745
{
746
	if((flags & MATCH_NUMBER) &&
747
		(x->mode_number != y->mode_number)) {
748
		return 0;
749
	}
750
	if((flags & MATCH_REFRESH) &&
751
		(x->refresh && (x->refresh != y->refresh))) {
752
		return 0;
753
	}
754
	if((flags & MATCH_WIDTH) &&
755
		(x->width != y->width)) {
756
		return 0;
757
	}
758
	if((flags & MATCH_HEIGHT) &&
759
		(x->height != y->height)) {
760
		return 0;
761
	}
762
	if((flags & MATCH_GE_WIDTH) &&
763
		(x->width > y->width)) {
764
		return 0;
765
	}
766
	if((flags & MATCH_GE_HEIGHT) &&
767
		(x->height > y->height)) {
768
		return 0;
769
	}
770
	if((flags & MATCH_FLAGS) &&
771
		(x->flags & (IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|IGD_LINE_DOUBLE)) !=
772
		(y->mode_info_flags &
773
			(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|IGD_LINE_DOUBLE))) {
774
		return 0;
775
	}
776
777
	return 1;
778
}
779
780
typedef struct _vga_wh {
781
	short width;
782
	short height;
783
} vga_wh_t;
784
785
static vga_wh_t vga_size[] = {
786
	{640, 400}, {640, 400}, {640, 400}, {640, 400},
787
	{320, 400}, {320, 400}, {640, 400}, {720, 350},
788
	{640, 400}, {640, 400}, {640, 350}, {640, 350},
789
	{640, 350}, {640, 350}, {640, 350}, {640, 350},
790
	{640, 400}, {720, 400}, {720, 400}, {640, 480},
791
	{640, 480}, {640, 400}
792
};
793
794
/*
795
 * For VGA modes we do not actually have a mode table. Just use a
796
 * temporary slot (one per-pipe) and put the VGA mode number in it.
797
 */
798
static igd_timing_info_t vga_timing[] = {
799
	{
800
		720, 400, 70,
801
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
802
		0x00,
803
		IGD_MODE_VESA | IGD_MODE_SUPPORTED,
804
		0, 0, NULL, NULL
805
	},
806
	{
807
		720, 400, 70,
808
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
809
		0x00,
810
		IGD_MODE_VESA | IGD_MODE_SUPPORTED,
811
		0, 0, NULL, NULL
812
	}
813
};
814
815
/*
816
 * The magic mode, when found in a port's mode list, means that the port
817
 * can do native VGA output. A mode with a wxh of 720x480 and refresh of
818
 * 70 is the magic mode.
819
 */
820
static igd_display_info_t magic_timing = {
821
	720, 400, 70,
822
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
823
	0x00,
824
	IGD_MODE_VESA | PD_MODE_SUPPORTED,
825
	0, 0, NULL, NULL
826
};
827
828
/*!
829
 * Match Resolution searches the provided timing table for a mode that
830
 * matches the requested parameters using the provided criteria.
831
 *
832
 * @param display The display on which the mode will be displayed.
833
 * @param timing_table The list of modes to search through.
834
 * @param pt_info The timing set used as reference for the match
835
 * @param criteria The criteria that must match (bitfield). Options are
836
 *  MATCH_NUMBER: Match the VGA/VESA mode number
837
 *  MATCH_REFRESH: Match the refresh rate
838
 *  MATCH_WIDTH: Match the width
839
 *  MATCH_HEIGHT: Match the height
840
 *  MATCH_FLAGS: Match relavent interlace, pixel double, etc flags.
841
 *  MATCH_GE_WIDTH: Match width greater or equal to requested (used with
842
 *    best_match = 1)
843
 *  MATCH_GE_HEIGHT: Match height greater or equal to requested (used with
844
 *    best_match = 1)
845
 *  MATCH_FOR_VGA: Match is used for a VGA container which may need to take
846
 *    into accoutn 9th pixel dropping in the hardware.
847
 * @param best_match When set to 0 the first mode found matching the criteria
848
 * 	will be returned. Null will be returned if no match is found.
849
 * 	When set to 1 the best matching mode is found after searching all modes.
850
 * 	if no mode is found matching the criteria, the last mode in the table
851
 * 	is used (should be the largest mode as mode tables are sorted)
852
 *
853
 * @return igd_timing_info_t
854
 */
855
static igd_timing_info_t *match_resolution(
856
		igd_display_context_t *display,
857
		igd_timing_info_t *timing_table,
858
		igd_display_info_t *pt_info,
859
		unsigned int criteria,
860
		int best_match)
861
{
862
	igd_timing_info_t *timing;
863
	igd_timing_info_t *match;
864
	igd_timing_info_t *last_mode = NULL;
865
	igd_display_port_t *port;
866
	unsigned short save_width;
867
868
	EMGD_DEBUG("Enter match_resolution");
869
870
	EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
871
		pt_info->width, pt_info->height, pt_info->refresh,
872
		pt_info->mode_number);
873
874
	timing = timing_table;
875
	match = NULL;
876
	port = PORT_OWNER(display);
877
	save_width = pt_info->width;
878
879
	/*
880
	 * Hardware has a mode where it can drop every 9th pixel to fit
881
	 * a 720 width VGA mode into a 640 width container. Modify the
882
	 * reference mode to reflect 640 width and put it back at the end.
883
	 */
884
	if(criteria & MATCH_FOR_VGA) {
885
		if((pt_info->width == 720) &&
886
			(port->port_features & IGD_VGA_COMPRESS)) {
887
			pt_info->width = 640;
888
		}
889
	}
890
891
	while (timing->width != IGD_TIMING_TABLE_END) {
892
		if(!MODE_IS_SUPPORTED(timing)) {
893
			timing++;
894
			continue;
895
		}
896
		if(modes_match(pt_info, timing, criteria)) {
897
			/*
898
			 * If we are looking for the first match we are done.
899
			 */
900
			if(!best_match) {
901
				match = timing;
902
				break;
903
			}
904
			/*
905
			 * Looking for best match. Compare the new match to the last one
906
			 * to see if it is better.
907
			 */
908
			if(match) {
909
				/* Check for tighter fit */
910
				if((timing->width < match->width) ||
911
					(timing->height < match->height)) {
912
					match = timing;
913
				}
914
			} else {
915
				match = timing;
916
			}
917
		}
918
		last_mode = timing;
919
		timing++;
920
	}
921
922
	pt_info->width = save_width;
923
	if(!match && best_match) {
924
		/*
925
		 * Take the last one in the table for container modes. This insures
926
		 * that we never fail a container mode.
927
		 */
928
		match = last_mode;
929
	}
930
931
	if (match) {
932
		EMGD_DEBUG("Returning with a match");
933
		EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
934
			match->width, match->height, match->refresh, match->mode_number);
935
	} else {
936
		EMGD_DEBUG("Returning with NO match");
937
	}
938
939
	return match;
940
} /* end match_resolution */
941
942
943
void update_fb_size(igd_timing_info_t *match,
944
	igd_framebuffer_info_t *fb_info)
945
{
946
947
	/*
948
	 * fb_info is sometimes NULL when just testing something.
949
	 */
950
	if(fb_info) {
951
		/*
952
		 * If The FB data comes in as zero we populate it with the matched
953
		 * size. Also if the FB is coming from vBIOS we increase the size
954
		 * to fit the match.
955
		 */
956
		if((fb_info->width == 0) || (fb_info->flags & IGD_VBIOS_FB)) {
957
958
			if((fb_info->width < match->width) ||
959
				(fb_info->height < match->height)) {
960
				fb_info->width = match->width;
961
				fb_info->height = match->height;
962
			}
963
		}
964
	}
965
}
966
967
/*!
968
 * Push a Match on to the stack which is represented by a link list.
969
 * Only push the mode if it is different than the head of the list.
970
 *
971
 * @param match
972
 * @param timing_stack
973
 *
974
 * @return void
975
 */
976
void push_match(igd_timing_info_t *match,
977
	igd_timing_info_t **timing_stack)
978
{
979
980
	if(match == *timing_stack) {
981
		return;
982
	}
983
	match->extn_ptr = *timing_stack;
984
	*timing_stack = match;
985
	return;
986
}
987
988
989
static igd_timing_info_t scaled_timing[IGD_MAX_PIPES];
990
991
/*!
992
 * This function determines if the input timings need to be modified
993
 * to accomodate the provided framebuffer. If so it converts the timing set
994
 * to a modified set that centers the provided framebuffer image.
995
 * The provided timings are not modified and the returned set
996
 * may be used until the next mode set. The returned timings do
997
 * not need to be freed.
998
 *
999
 * @param display A pointer to the display used for these timings.
1000
 * 	This parameter is used to determine which pipe the timings
1001
 * 	will be used with. There is one set of static timings for
1002
 * 	each pipe.
1003
 * @param timing The input timings which are used as reference to
1004
 * 	generate the new timings. Only the width/height and blank/syncs
1005
 * 	will be altered. The pixel clock and total sizes will not be changed.
1006
 * @param fb_info The framebuffer information to center within the
1007
 * 	provided timings. (May be NULL)
1008
 *
1009
 * @return Modified timing set
1010
 */
1011
igd_timing_info_t *get_centered_timings(igd_display_context_t *display,
1012
	igd_timing_info_t *timing,
1013
	igd_framebuffer_info_t *fb_info)
1014
{
1015
	short cntr_dff_w = 0;
1016
	short cntr_dff_h = 0;
1017
1018
	if(!fb_info) {
1019
		return timing;
1020
	}
1021
1022
	/*
1023
	 * If we end up making a munged centered timings we need to use
1024
	 * a copy and not the originals.
1025
	 *
1026
	 */
1027
	OS_MEMCPY(&scaled_timing[(PIPE(display)->pipe_num)],
1028
		timing, sizeof(igd_timing_info_t));
1029
1030
	if(PORT_OWNER(display)->pd_type != PD_DISPLAY_TVOUT) {
1031
		/*
1032
		 * TV display don't like changed pipe actives,
1033
		 * Updating syncs work for TV centering
1034
		 */
1035
		if (fb_info->width < timing->width) {
1036
			timing = &scaled_timing[(PIPE(display)->pipe_num)];
1037
			cntr_dff_w = (timing->width - fb_info->width) / 2;
1038
			timing->width = (unsigned short)fb_info->width;
1039
			timing->hblank_start -= cntr_dff_w;
1040
			timing->hblank_end -= cntr_dff_w;
1041
		}
1042
		if (fb_info->height < timing->height) {
1043
			timing = &scaled_timing[(PIPE(display)->pipe_num)];
1044
			cntr_dff_h = (timing->height - fb_info->height) / 2;
1045
			timing->height = (unsigned short)fb_info->height;
1046
			timing->vblank_start -= cntr_dff_h;
1047
			timing->vblank_end -= cntr_dff_h;
1048
		}
1049
	}
1050
1051
	timing->hsync_start -= cntr_dff_w;
1052
	timing->hsync_end -= cntr_dff_w;
1053
	timing->vsync_start -= cntr_dff_h;
1054
	timing->vsync_end -= cntr_dff_h;
1055
1056
	return timing;
1057
}
1058
1059
1060
/*!
1061
 * Match the fb and pt structures to a Mode Structure from the table.
1062
 * When a mode is found update the input structures to reflect the
1063
 * values found.
1064
 *
1065
 *  The match mode function will compile all the information needed by
1066
 * the HAL to put the hardware into a mode. This may be a regular
1067
 * full-screen mode, a centered mode, a panned mode, a scaled mode.
1068
 * Below is a table of the mode that will be used and the cases in which
1069
 * it will occurr.
1070
 *
1071
 * Native
1072
 *  The requested mode is matched in the mode table in terms of width
1073
 *  height, refresh, and interlace flags. There is no fp_native_dtd or
1074
 *  the matching mode IS the fp_native_dtd.
1075
 * Centered
1076
 *  1) The requested mode is matched in the mode table but the framebuffer
1077
 *     is a smaller size and needs to be centered.
1078
 *  2) The requested mode is NOT matched in the mode table and the
1079
 *     framebuffer matches the requested mode. A container mode is used
1080
 *     with the original smaller framebuffer.
1081
 * Scaled
1082
 *  The requested mode is matched in the mode table and a fp_native_dtd
1083
 *  is present for the port. The matched mode does not match the native
1084
 *  and is therefore scaled to fit.
1085
 * Panned/Cropped
1086
 *  The requested mode is matched in the mode table but the framebuffer
1087
 *  is larger (in at least one demension) that the mode. The mode is
1088
 *  set with a cropped FB that may then be panned by the IAL.
1089
 * Render Scaled
1090
 *  The requested mode may or may not be matched in the mode table. The
1091
 *  framebuffer data is empty. The HAL will match the mode or find a
1092
 *  container or find the largest mode and set the framebuffer to the
1093
 *  same size. The IAL will scale the actual framebuffer to the returned
1094
 *  framebuffer.
1095
 * Native VGA
1096
 *  A VGA mode is requested (by number) and the magic VGA mode is matched
1097
 *  in the mode table. FB contents are output only.
1098
 * Centered VGA
1099
 *  A VGA mode is requested (by number) and the magic VGA mode is NOT
1100
 *  matched. A container mode is found or the largest mode is used. The
1101
 *  VGA is hardware centered in the container mode. FB contents are
1102
 *  output only.
1103
 * Scaled VGA
1104
 *  A VGA mode is requested (by number) and the magic VGA mode is NOT
1105
 *  matched. A fp_native_dtd is found. The VGA image will be scaled to
1106
 *  the native timings.
1107
 *
1108
 *
1109
 * The timings returned may be part of a linked list of timings which
1110
 * are used by the HAL to perform centering and scaling operations. One
1111
 * of the following will result.
1112
 *
1113
 * Requested Mode
1114
 *   The requested mode matched and is returned with no linked modes.
1115
 * Munged Requested Mode
1116
 *   The requested mode was larger than the requested framebuffer. The
1117
 *   timings were then modified to center the framebuffer.
1118
 * Native Mode -> Requested Mode
1119
 *   The display is fixed resolution and any mode must be scaled to that
1120
 *   resolution by the PD. The native mode is returned and linked to the
1121
 *   requested mode which will be scaled to fit the native mode. The
1122
 *   pt_info will be populated with the requested mode giving the caller
1123
 *   the impression that the mode was set natively.
1124
 * Native Mode -> Munged Requested Mode
1125
 *   The display is fixed resolution and any mode must be scaled to that
1126
 *   resolution by the PD. In addition the requested framebuffer is smaller
1127
 *   then the requested mode. The native mode is returned and linked to the
1128
 *   requested mode which has been modifed to center the framebuffer.
1129
 *   The result will be the requested framebuffer scaled to fit the native
1130
 *   mode. The pt_info will be populated with the requested mode giving the
1131
 *   caller the impression that the mode was set natively.
1132
 * VGA Mode -> Magic VGA Mode
1133
 *   The requested mode was a legacy VGA mode and the display supports
1134
 *   native VGA output. The 720x400 "magic" mode is returned to indicate
1135
 *   to the HAL that native VGA should be used. The magic mode is linked
1136
 *   to the requested VGA mode.
1137
 * Container Mode -> VGA Mode
1138
 *   The requested mode was a legacy VGA mode but the display does not
1139
 *   support native VGA output. A larger container mode was found and
1140
 *   returned. The hardware will center the VGA mode within the container
1141
 *   for output. The pt_info will contain the VGA mode giving the caller
1142
 *   the impression that the VGA mode was set natively.
1143
 * Native Mode -> VGA Mode
1144
 *   The requested mode was a legacy VGA mode but the and the PD is
1145
 *   set for scaling to a fixed resolution display. The Native mode is
1146
 *   returned linked to the VGA mode. The result is the VGA mode scaled to
1147
 *   fit the native screen.
1148
 *
1149
 *   @note: There is a tradeoff to this behavior. If a VGA mode is set and
1150
 *   scaled to full-screen there is no guarentee that ALL VGA modes are
1151
 *   possible in that configuration. For instance, in DOS if a mode 3 is
1152
 *   set (720x400) and scaled full-screen, an application cannot directly
1153
 *   program the VGA registers (as many games do) to get an acceptable
1154
 *   output at 640x480. This tradeoff is acknoledged and accepted.
1155
 *
1156
 *
1157
 * Assumtions:
1158
 *  1) fp_native_dtd is set in all instances where the output is a fixed
1159
 *   resolution. (and only those instances)
1160
 *  2) PDs timing table contains all modes that can be output or all
1161
 *   modes that can be scaled to the native output.
1162
 *  3) Scaling PDs can accept a VGA mode to be scaled to the native.
1163
 *
1164
 * @param display
1165
 * @param timing_table
1166
 * @param fb_info
1167
 * @param pt_info
1168
 * @param timing
1169
 *
1170
 * @return 0
1171
 */
1172
int match_mode (
1173
	igd_display_context_t *display,
1174
	igd_timing_info_t *timing_table,
1175
	igd_framebuffer_info_t *fb_info,
1176
	igd_display_info_t *pt_info,
1177
	igd_timing_info_t **timing)
1178
{
1179
	igd_timing_info_t *match = NULL;
1180
	igd_timing_info_t *timing_stack = NULL;
1181
1182
	EMGD_DEBUG("Enter Match Mode");
1183
1184
	EMGD_ASSERT(pt_info, "Null PT Info", -IGD_ERROR_INVAL);
1185
	EMGD_ASSERT((pt_info->flags & IGD_MODE_VESA) ||
1186
		(pt_info->width && pt_info->height),
1187
		"Width and Height are Zero", -IGD_ERROR_INVAL);
1188
1189
	if(MODE_IS_VGA(pt_info)) {
1190
		/*
1191
		 * The requested mode is a legacy VGA mode
1192
		 */
1193
		EMGD_DEBUG("Matching a VGA mode");
1194
1195
		/*
1196
		 * All VGA modes are possible. Just use a temporary timing
1197
		 * block and put the VGA mode number in it. We don't actually
1198
		 * use any timing information for VGA modes.
1199
		 */
1200
		match = &vga_timing[(PIPE(display)->pipe_num)];
1201
		match->mode_number = pt_info->mode_number;
1202
		match->width = vga_size[pt_info->mode_number].width;
1203
		match->height = vga_size[pt_info->mode_number].height;
1204
1205
		push_match(match, &timing_stack);
1206
		update_fb_size(match, fb_info);
1207
1208
		/* The caller should think we set the VGA mode directly */
1209
		fill_pt(match, pt_info);
1210
1211
		match = match_resolution(display, timing_table, &magic_timing,
1212
			MATCH_WIDTH|MATCH_HEIGHT, 0);
1213
		if(match) {
1214
			/*
1215
			 * Magic VGA mode was found. This indicates the display can
1216
			 * do full native VGA timings. We will send the mode out
1217
			 * natively.
1218
			 */
1219
			EMGD_DEBUG("Native VGA output");
1220
			push_match(match, &timing_stack);
1221
1222
			*timing = timing_stack;
1223
			return 0;
1224
		}
1225
1226
		/*
1227
		 * This display cannot do native VGA. We need to center or
1228
		 * scale the VGA to fit.
1229
		 */
1230
		if(PORT_OWNER(display)->fp_native_dtd) {
1231
			/*
1232
			 * Native mode in the port indicates the PD can scale.
1233
			 * Push the native mode on the list to get VGA scaled
1234
			 * to native.
1235
			 */
1236
			EMGD_DEBUG("VGA Scaled to Native");
1237
			push_match(PORT_OWNER(display)->fp_native_dtd, &timing_stack);
1238
		} else {
1239
			/*
1240
			 * No native mode means the PD is not scaling. Output
1241
			 * VGA centered in a safe container mode.
1242
			 */
1243
			EMGD_DEBUG("VGA centered in Container");
1244
			match = match_resolution(display, timing_table, pt_info,
1245
				MATCH_FOR_VGA|MATCH_GE_WIDTH|MATCH_GE_HEIGHT|MATCH_FLAGS, 1);
1246
			EMGD_ASSERT(match, "Match Container Failed", -IGD_ERROR_INVAL);
1247
1248
			push_match(match, &timing_stack);
1249
		}
1250
1251
		*timing = timing_stack;
1252
		return 0;
1253
1254
	}
1255
1256
	/*
1257
	 * Regular NON-VGA mode
1258
	 */
1259
	EMGD_DEBUG("Matching a regular NON-VGA mode");
1260
1261
	match = match_resolution(display, timing_table, pt_info,
1262
		(pt_info->flags & IGD_MODE_VESA)?
1263
		MATCH_NUMBER|MATCH_REFRESH:
1264
		MATCH_WIDTH|MATCH_HEIGHT|MATCH_REFRESH|MATCH_FLAGS, 0);
1265
	if(match) {
1266
		/*
1267
		 * Exact match for requested mode was found in the mode table.
1268
		 * This mode will be output directly.
1269
		 */
1270
		EMGD_DEBUG("Input Mode Matched exactly");
1271
	} else {
1272
		/*
1273
		 * Matching mode was not found. This happens for several
1274
		 * reasons:
1275
		 *
1276
		 * 1) We are setting the clone mode but the IAL does not
1277
		 *   know the clone width/height. We are just getting the
1278
		 *   best guess. In this case fb info is populated.
1279
		 * 2) IAL is doing Render Scaling but doesn't know what mode
1280
		 *   to scale to. We are getting the best fit. In this case
1281
		 *   fb info is all zeros.
1282
		 * 3) IAL is just setting random modes and wants something
1283
		 *   close. Fb info may or may not be populated.
1284
		 */
1285
		EMGD_DEBUG("Input Mode NOT matched, container used");
1286
		match = match_resolution(display, timing_table, pt_info,
1287
			MATCH_GE_WIDTH|MATCH_GE_HEIGHT|MATCH_FLAGS, 1);
1288
		EMGD_ASSERT(match, "Match Container Failed", -IGD_ERROR_INVAL);
1289
	}
1290
	update_fb_size(match, fb_info);
1291
	match = get_centered_timings(display, match, fb_info);
1292
	push_match(match, &timing_stack);
1293
1294
	fill_pt(match, pt_info);
1295
1296
	if(PORT_OWNER(display)->fp_native_dtd) {
1297
		/*
1298
		 * Native DTD indicates that the PD is scaling. Hook the
1299
		 * match mode up to the native to get scaling.
1300
		 */
1301
		EMGD_DEBUG("Input Mode Scaled to Native");
1302
		push_match(PORT_OWNER(display)->fp_native_dtd, &timing_stack);
1303
	}
1304
1305
1306
	*timing = timing_stack;
1307
	return 0;
1308
}
1309
1310
1311
#endif
1312
1313
1314
/*----------------------------------------------------------------------------
1315
 * File Revision History
1316
 * $Id: match.c,v 1.8 2010/07/23 16:54:49 bpaauwe Exp $
1317
 * $Source: /nfs/fm/proj/eia/cvsroot/koheo/linux/egd_drm/emgd/display/mode/cmn/match.c,v $
1318
 *----------------------------------------------------------------------------
1319
 */