2
*-----------------------------------------------------------------------------
5
*-----------------------------------------------------------------------------
6
* Copyright © 2002-2010, Intel Corporation.
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.
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
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.
21
*-----------------------------------------------------------------------------
24
*-----------------------------------------------------------------------------
27
#define MODULE_NAME hal.mode
30
#define CURSOR_DEFAULT_WIDTH 64
31
#define CURSOR_DEFAULT_HEIGHT 64
41
#include <igd_errno.h>
49
* @addtogroup display_group
55
igd_cursor_info_t default_cursor = {
57
CURSOR_DEFAULT_HEIGHT,
60
0, 0, {0, 0, 0, 0}, IGD_CURSOR_ON, 0, 0, 0, 0
68
* @return -IGD_INVAL on failure
69
* @return 0 on success
71
int validate_cursor(igd_cursor_info_t *cursor_info,
72
igd_display_context_t *display)
74
unsigned long *list_pfs;
75
igd_display_pipe_t *pipe = (igd_display_pipe_t *)(display->pipe);
80
list_pfs = pipe->cursor->pixel_formats;
83
if (cursor_info->pixel_format == *list_pfs) {
104
igd_timing_info_t *timing,
105
pigd_display_info_t pt_info)
109
EMGD_DEBUG("fill_pt Entry");
111
/* preserve existing pt_info flags */
112
flags = pt_info->flags;
114
/* Simply memcpy the structures and fix up the flags */
115
OS_MEMCPY(pt_info, timing, sizeof(igd_timing_info_t));
117
pt_info->flags |= flags;
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;
125
#ifndef CONFIG_NEW_MATCH
128
extern igd_timing_info_t vga_timing_table[];
129
extern igd_timing_info_t crt_timing_table[];
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
141
* @param timing_table
145
* @return NULL on failure
146
* @return timing on success
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,
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;
159
EMGD_DEBUG("Enter match_resolution");
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);
165
timing = timing_table;
167
port = PORT_OWNER(display);
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.
180
if(type == MATCH_NATIVE) {
181
if(port->fp_native_dtd) {
182
EMGD_DEBUG("Returning quick with a native match");
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);
188
return port->fp_native_dtd;
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;
198
while (timing->width != IGD_TIMING_TABLE_END) {
199
if(!(timing->mode_info_flags & IGD_MODE_SUPPORTED)) {
204
if(type == MATCH_NATIVE) {
205
if(timing->mode_info_flags & IGD_MODE_DTD_FP_NATIVE) {
206
port->fp_native_dtd = timing;
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.
218
(port->fp_info->fp_width ==
219
(unsigned long)timing->width) &&
220
(port->fp_info->fp_height ==
221
(unsigned long)timing->height)) {
226
* Keep a match because in the event that we never find a
227
* native DTD then we will just take the exact match.
230
(timing->width == pt_info->width) &&
231
(timing->height == pt_info->height) &&
232
(timing->refresh == pt_info->refresh)) {
238
* If it is a DTD then keep it only if it is better than any
241
if(timing->mode_info_flags & IGD_MODE_DTD_USER) {
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;
250
native_match = timing;
253
} else if (type == MATCH_EXACT) {
255
* Looking for an exact match. For VGA/VESA it must match
256
* mode number. Otherwise it must match width, height, refresh
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))) {
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) &&
273
(timing->mode_info_flags &
274
(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
277
(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
278
IGD_LINE_DOUBLE)))) {
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)) {
291
/* Center needs only to be bigger. Aspect ratio doesn't matter. */
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
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.
302
else if(type & MATCH_CENTER) {
303
unsigned short eff_width = pt_info->width;
304
unsigned short eff_height = pt_info->height;
306
if(type & MATCH_FOR_VGA) {
308
* 720x400 is a magic mode that means all VGA modes are supported
309
* always use that mode for centering if found.
311
if((timing->width == 720) && (timing->height == 400)) {
312
EMGD_DEBUG("Returning with a magic VGA mode");
315
if(pt_info->flags & IGD_PIXEL_DOUBLE) {
318
if(pt_info->flags & IGD_LINE_DOUBLE) {
321
if((eff_width == 720) &&
322
(port->port_features & IGD_VGA_COMPRESS)) {
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)) {
332
/* Check for tighter fit */
333
if((match->width > timing->width) ||
334
(match->height > timing->height)) {
337
/* Try to match refreshrate as well */
338
if((match->width == timing->width) &&
339
(match->height == timing->height) &&
340
(pt_info->refresh == timing->refresh)){
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);
359
EMGD_DEBUG("Returning with NO match");
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);
367
} /* end match_resolution */
369
static igd_timing_info_t scaled_timing[IGD_MAX_PIPES];
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
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
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.
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
390
* If the Frambuffer is smaller than the timings requested a fake set of
391
* centered timings is returned to program the pipe.
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
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.
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
415
* @param timing_table
420
* @return -IGD_ERROR_INVAL on failure
421
* @return 0 on success
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)
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;
440
EMGD_DEBUG("Enter Match Mode");
443
EMGD_ERROR("NULL Port info detected, returning");
444
return -IGD_ERROR_INVAL;
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;
455
EMGD_DEBUG("Checking for exact mode match");
456
exact_timing = match_resolution(display, timing_table, pt_info,
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.
463
* -> Check for VGA/VESA mode to center.
464
* -> Check common modes.
467
pipe_timing = exact_timing;
468
user_timing = exact_timing;
469
pipe_timing->extn_ptr = NULL;
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);
481
return -IGD_ERROR_INVAL;
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);
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
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*/
505
/* this PI func will not modify value of upscale if attr does not exist */
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-
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.
526
unsigned char match_type = MATCH_CENTER;
528
EMGD_DEBUG("Checking for a safe centered match");
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
538
vesa_timing = match_resolution(display, crt_timing_table,
539
pt_info, MATCH_EXACT);
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;
548
pipe_timing = match_resolution(display, timing_table, pt_info,
550
/* This can happen if there is a spurious pt_info from IAL */
552
return -IGD_ERROR_INVAL;
554
pipe_timing->extn_ptr = vga_timing;
555
/* for the case of non VGA mode call,
556
* at this point, vga_timing is NULL
561
user_timing = pipe_timing;
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.
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.
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.
581
* fb_info is sometimes NULL when just testing something.
583
if(!fb_info->pixel_format) {
584
/* Ugly VGA modes, it doesn't matter */
585
fb_info->pixel_format = IGD_PF_ARGB8_INDEXED;
587
if(!fb_info->width) {
589
fb_info->width = vga_timing->width;
590
fb_info->height = vga_timing->height;
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)
600
fb_info->width = vesa_timing->width;
601
fb_info->height = vesa_timing->height;
606
* VGA common timings are centered in pipe timings by hardware.
607
* Otherwise we need to adjust the timings when centering is
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
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;
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!
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!.
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
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;
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
653
OS_MEMCPY(&scaled_timing[(PIPE(display)->pipe_num)],
655
sizeof(igd_timing_info_t));
657
pipe_timing = &scaled_timing[(PIPE(display)->pipe_num)];
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;
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;
675
if (fb_info->width < temp_width) {
676
pipe_timing->hsync_start -= cntr_dff_w;
677
pipe_timing->hsync_end -= cntr_dff_w;
680
if (fb_info->height < temp_height) {
681
pipe_timing->vsync_start -= cntr_dff_h;
682
pipe_timing->vsync_end -= cntr_dff_h;
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,
693
if(native_timing && (native_timing != pipe_timing)) {
694
native_timing->extn_ptr = pipe_timing;
695
pipe_timing = native_timing;
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
705
* native->vga --- Upscaling displays
707
* pipe->vga --- For other displays
709
* 2) In case of regular setmode:
710
* pipe --- For regular displays
712
* native->vesa --- Upscaling displays
714
* Note: 1) Here "pipe" can be munged if centering is required.
715
* 2) "vesa" is the requested mode, native is the native timing
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
725
fill_pt(user_timing, pt_info);
726
*timing = pipe_timing;
727
EMGD_DEBUG("Return");
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
742
static int modes_match(igd_display_info_t *x,
743
igd_timing_info_t *y,
746
if((flags & MATCH_NUMBER) &&
747
(x->mode_number != y->mode_number)) {
750
if((flags & MATCH_REFRESH) &&
751
(x->refresh && (x->refresh != y->refresh))) {
754
if((flags & MATCH_WIDTH) &&
755
(x->width != y->width)) {
758
if((flags & MATCH_HEIGHT) &&
759
(x->height != y->height)) {
762
if((flags & MATCH_GE_WIDTH) &&
763
(x->width > y->width)) {
766
if((flags & MATCH_GE_HEIGHT) &&
767
(x->height > y->height)) {
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))) {
780
typedef struct _vga_wh {
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}
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.
798
static igd_timing_info_t vga_timing[] = {
801
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
803
IGD_MODE_VESA | IGD_MODE_SUPPORTED,
808
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
810
IGD_MODE_VESA | IGD_MODE_SUPPORTED,
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.
820
static igd_display_info_t magic_timing = {
822
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
824
IGD_MODE_VESA | PD_MODE_SUPPORTED,
829
* Match Resolution searches the provided timing table for a mode that
830
* matches the requested parameters using the provided criteria.
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
843
* MATCH_GE_HEIGHT: Match height greater or equal to requested (used with
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)
853
* @return igd_timing_info_t
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,
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;
868
EMGD_DEBUG("Enter match_resolution");
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);
874
timing = timing_table;
876
port = PORT_OWNER(display);
877
save_width = pt_info->width;
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.
884
if(criteria & MATCH_FOR_VGA) {
885
if((pt_info->width == 720) &&
886
(port->port_features & IGD_VGA_COMPRESS)) {
887
pt_info->width = 640;
891
while (timing->width != IGD_TIMING_TABLE_END) {
892
if(!MODE_IS_SUPPORTED(timing)) {
896
if(modes_match(pt_info, timing, criteria)) {
898
* If we are looking for the first match we are done.
905
* Looking for best match. Compare the new match to the last one
906
* to see if it is better.
909
/* Check for tighter fit */
910
if((timing->width < match->width) ||
911
(timing->height < match->height)) {
922
pt_info->width = save_width;
923
if(!match && best_match) {
925
* Take the last one in the table for container modes. This insures
926
* that we never fail a container mode.
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);
936
EMGD_DEBUG("Returning with NO match");
940
} /* end match_resolution */
943
void update_fb_size(igd_timing_info_t *match,
944
igd_framebuffer_info_t *fb_info)
948
* fb_info is sometimes NULL when just testing something.
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
956
if((fb_info->width == 0) || (fb_info->flags & IGD_VBIOS_FB)) {
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;
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.
972
* @param timing_stack
976
void push_match(igd_timing_info_t *match,
977
igd_timing_info_t **timing_stack)
980
if(match == *timing_stack) {
983
match->extn_ptr = *timing_stack;
984
*timing_stack = match;
989
static igd_timing_info_t scaled_timing[IGD_MAX_PIPES];
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.
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
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)
1009
* @return Modified timing set
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)
1015
short cntr_dff_w = 0;
1016
short cntr_dff_h = 0;
1023
* If we end up making a munged centered timings we need to use
1024
* a copy and not the originals.
1027
OS_MEMCPY(&scaled_timing[(PIPE(display)->pipe_num)],
1028
timing, sizeof(igd_timing_info_t));
1030
if(PORT_OWNER(display)->pd_type != PD_DISPLAY_TVOUT) {
1032
* TV display don't like changed pipe actives,
1033
* Updating syncs work for TV centering
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;
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;
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;
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
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
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.
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.
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.
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.
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
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.
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
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.
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.
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.
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.
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.
1165
* @param timing_table
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)
1179
igd_timing_info_t *match = NULL;
1180
igd_timing_info_t *timing_stack = NULL;
1182
EMGD_DEBUG("Enter Match Mode");
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);
1189
if(MODE_IS_VGA(pt_info)) {
1191
* The requested mode is a legacy VGA mode
1193
EMGD_DEBUG("Matching a VGA mode");
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.
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;
1205
push_match(match, &timing_stack);
1206
update_fb_size(match, fb_info);
1208
/* The caller should think we set the VGA mode directly */
1209
fill_pt(match, pt_info);
1211
match = match_resolution(display, timing_table, &magic_timing,
1212
MATCH_WIDTH|MATCH_HEIGHT, 0);
1215
* Magic VGA mode was found. This indicates the display can
1216
* do full native VGA timings. We will send the mode out
1219
EMGD_DEBUG("Native VGA output");
1220
push_match(match, &timing_stack);
1222
*timing = timing_stack;
1227
* This display cannot do native VGA. We need to center or
1228
* scale the VGA to fit.
1230
if(PORT_OWNER(display)->fp_native_dtd) {
1232
* Native mode in the port indicates the PD can scale.
1233
* Push the native mode on the list to get VGA scaled
1236
EMGD_DEBUG("VGA Scaled to Native");
1237
push_match(PORT_OWNER(display)->fp_native_dtd, &timing_stack);
1240
* No native mode means the PD is not scaling. Output
1241
* VGA centered in a safe container mode.
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);
1248
push_match(match, &timing_stack);
1251
*timing = timing_stack;
1257
* Regular NON-VGA mode
1259
EMGD_DEBUG("Matching a regular NON-VGA mode");
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);
1267
* Exact match for requested mode was found in the mode table.
1268
* This mode will be output directly.
1270
EMGD_DEBUG("Input Mode Matched exactly");
1273
* Matching mode was not found. This happens for several
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.
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);
1290
update_fb_size(match, fb_info);
1291
match = get_centered_timings(display, match, fb_info);
1292
push_match(match, &timing_stack);
1294
fill_pt(match, pt_info);
1296
if(PORT_OWNER(display)->fp_native_dtd) {
1298
* Native DTD indicates that the PD is scaling. Hook the
1299
* match mode up to the native to get scaling.
1301
EMGD_DEBUG("Input Mode Scaled to Native");
1302
push_match(PORT_OWNER(display)->fp_native_dtd, &timing_stack);
1306
*timing = timing_stack;
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
*----------------------------------------------------------------------------