2
*-----------------------------------------------------------------------------
3
* Filename: micro_mode_tnc.c
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
*-----------------------------------------------------------------------------
23
* 1) Atom E6xx Core implementations for the mode dispatch functions.
24
* 2) 0:2:0 = Device2 = LNC VGA
25
* 0:3:0 = Device3 = Atom E6xx overlay
27
* Dev2 only: Use EMGD_READ32(), EMGD_WRITE32(): less code
28
* Dev2/3: Use READ_MMIO_REG_TNC(), WRITE_MMIO_REG_TNC(): more code
29
* For code optimization sake use the right macro.
30
*-----------------------------------------------------------------------------
33
#define MODULE_NAME hal.mode
47
#include <mode_access.h>
53
#include <tnc/context.h>
55
#include <tnc/instr.h>
56
#include <tnc/igd_tnc_wa.h>
58
#include "../cmn/match.h"
59
#include "../cmn/mode_dispatch.h"
62
Turning on FIB part workaround for all IALs, for vBIOS this will limit
63
the port drivers to one at a time (SDVO or LVDS)due to code size
67
* @addtogroup display_group
72
* Exports from the other components of this module.
77
extern int program_clock_tnc(igd_display_context_t *display,
78
igd_clock_t *clock, unsigned long dclk);
80
extern mode_full_dispatch_t mode_full_dispatch_tnc;
82
int wait_for_vblank_tnc(unsigned long pipe_reg);
83
static void wait_pipe(unsigned long pipe_reg, unsigned long check_on_off);
86
static void cdvo_signal(void);
89
typedef struct _mode_data_tnc {
90
unsigned long plane_a_preserve;
91
unsigned long plane_b_c_preserve;
92
unsigned long pipe_preserve;
93
unsigned long dsp_arb;
94
unsigned long fifo_watermark1;
95
unsigned long fifo_watermark2;
96
unsigned long fifo_watermark3;
97
unsigned long fifo_watermark4;
98
unsigned long fifo_watermark5;
99
unsigned long fifo_watermark6;
102
static mode_data_tnc_t device_data[1] = {
104
0x000b0000, /* plane a preservation */
105
0x00000000, /* plane b c preservation */
106
0x60000000, /* pipe preservation */
107
0x00003232, /* DSP FIFO Size A=50 B=50 C=28 May require fine tuning*/
108
0x3f8f0404, /* FIFO watermark control1 */
109
0x04040f04, /* FIFO watermark control2 */
110
0x00000000, /* FIFO watermark control3 */
111
0x04040404, /* FIFO watermark1 control4 */
112
0x04040404, /* FIFO watermark1 control5 */
113
0x00000078, /* FIFO watermark1 control6 */
117
/* Do not change the order */
118
static const unsigned long ports_tnc[2] = {IGD_PORT_LVDS, IGD_PORT_SDVO};
120
/* Extern defines for Device2, device3 and device31 iobases.
121
* For Atom E6xx all devices are always io_mapped. */
122
extern unsigned char io_mapped;
123
extern unsigned short io_base;
124
extern unsigned char io_mapped_lvds;
125
extern unsigned short io_base_lvds;
126
extern unsigned char io_mapped_sdvo;
127
extern unsigned short io_base_sdvo;
128
extern unsigned char io_mapped_lpc;
129
extern unsigned short io_base_lpc;
131
static tnc_wa_timing_t tune = {0, 0, 0, 0, 0, 0, 0,};
134
#define CHECK_VGA(a) MODE_IS_VGA(a)
135
#ifdef DEBUG_BUILD_TYPE
137
/* Debug configuration flag for B0 workaround. Workaround is turned on by default */
138
static int flag_turn_off_port_wa = 1; /* Turn off port when sweeping */
139
static int flag_enable_tuning_wa = 1; /* Disable sweeping flag */
140
static int flag_basic_htotal_formula_wa = 1; /* Enable formula workaround flag */
142
/* Turn all workaround for release driver */
146
/* VPhase variable */
147
static int vphase = 0; /* The current value to enable vphase is 5 */
149
/* Temporary frame buffer */
150
static igd_framebuffer_info_t fb_info_tmp = {0,0,0,0,0,0,0};
153
#define CHECK_VGA(a) 1
156
pixel_crc_t compute_pixel_crc( pixel_crc_t pixel, pixel_crc_t new_pixel)
158
pixel_crc_t pixel_crc_new;
160
pixel_crc_new.pixel = 0x0;
162
pixel_crc_new.bit.bit22 = pixel.bit.bit14;
163
pixel_crc_new.bit.bit21 = pixel.bit.bit13;
164
pixel_crc_new.bit.bit20 = pixel.bit.bit12;
165
pixel_crc_new.bit.bit19 = pixel.bit.bit11;
166
pixel_crc_new.bit.bit18 = pixel.bit.bit10;
167
pixel_crc_new.bit.bit17 = pixel.bit.bit9;
168
pixel_crc_new.bit.bit16 = pixel.bit.bit22 ^ pixel.bit.bit8;
169
pixel_crc_new.bit.bit15 = pixel.bit.bit21 ^ pixel.bit.bit7;
170
pixel_crc_new.bit.bit14 = pixel.bit.bit20 ^ pixel.bit.bit6;
171
pixel_crc_new.bit.bit13 = pixel.bit.bit19 ^ pixel.bit.bit5;
172
pixel_crc_new.bit.bit12 = pixel.bit.bit18 ^ pixel.bit.bit4;
173
pixel_crc_new.bit.bit11 = pixel.bit.bit17 ^ pixel.bit.bit3;
174
pixel_crc_new.bit.bit10 = pixel.bit.bit16 ^ pixel.bit.bit2;
175
pixel_crc_new.bit.bit9 = pixel.bit.bit15 ^ pixel.bit.bit1;
176
pixel_crc_new.bit.bit8 = pixel.bit.bit0;
177
pixel_crc_new.bit.bit7 = pixel.bit.bit22 ^ new_pixel.bit.bit0;
178
pixel_crc_new.bit.bit6 = pixel.bit.bit21 ^ new_pixel.bit.bit1;
179
pixel_crc_new.bit.bit5 = pixel.bit.bit20 ^ new_pixel.bit.bit2;
180
pixel_crc_new.bit.bit4 = pixel.bit.bit19 ^ new_pixel.bit.bit3;
181
pixel_crc_new.bit.bit3 = pixel.bit.bit18 ^ new_pixel.bit.bit4;
182
pixel_crc_new.bit.bit2 = pixel.bit.bit17 ^ new_pixel.bit.bit5;
183
pixel_crc_new.bit.bit1 = pixel.bit.bit16 ^ new_pixel.bit.bit6;
184
pixel_crc_new.bit.bit0 = pixel.bit.bit15 ^ new_pixel.bit.bit7;
186
return (pixel_crc_new);
190
int check_display_tnc(igd_display_context_t *display,
191
unsigned short port_number,unsigned long status)
193
pixel_crc_t red_val, green_val, blue_val;
194
pixel_crc_t blue_crc, green_crc, red_crc;
195
int i, j, bps = 4, ret_val = 0;
196
unsigned long *curr_pixel, sync = 0, size = 0, dc;
197
unsigned long tnc_crc_red, tnc_crc_green, tnc_crc_blue, temp;
198
unsigned long temp_plane, temp_pitch, temp_control, plane_control;
199
unsigned long pt = PORT_TYPE(display);
200
igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info;
201
igd_timing_info_t pTimings_tmp, *pTimings_ext,*pTimings = PIPE(display)->timing;
202
/* igd_display_port_t *port = PORT_OWNER(display); */
204
igd_surface_t front_buffer;
205
tnc_wa_timing_t *wa = WA_TUNE;
210
dc = *(display->context->mod_dispatch.dsp_current_dc);
211
pTimings_tmp = *pTimings;
212
pTimings_ext = pTimings;
214
/* Check to see if VGA plane was requested */
215
while (pTimings_ext->extn_ptr) {
216
pTimings_ext = (igd_timing_info_t *)pTimings_ext->extn_ptr;
218
if((pt != IGD_PORT_SDVO) || (display->context->device_context.rid != TNC_B0_RID)
219
|| (pTimings->reserved_dd & TNC_HTOTAL_TUNED) || (!FLAG(flag_enable_tuning_wa))
220
|| (mode_context->tuning_wa == 0) /*if 0 don't tune*/
221
|| wa->counter > LIMIT_TOTAL_CHECK_DISPLAY
222
|| (MODE_IS_VGA(pTimings_ext))
223
|| (!IGD_DC_CLONE(dc) && !IGD_DC_EXTENDED(dc))){
224
/* Workaround is specific for SDVO display
225
* Dont tuned if it isnt B0 silicon
226
* Dont tuned if it is already tuned
227
* Dont tuned if bypass is turned on (debug)
228
* No tuning for VGA modes
229
* Stop Tuning if above limit LIMIT_TOTAL_CHECK_DISPLAY
231
if(pt != IGD_PORT_SDVO ||
232
(MODE_IS_VGA(pTimings_ext))){
233
EMGD_DEBUG("Unsupported tuning");
234
}else if((wa->counter > LIMIT_TOTAL_CHECK_DISPLAY) &&
235
!(pTimings->reserved_dd & TNC_HTOTAL_TUNED)){
236
pTimings->reserved_dd = 0;
237
EMGD_ERROR("Unable to get tuned value!");
240
if(FLAG(flag_turn_off_port_wa)){
241
/* Turn on SDVO source */
242
temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG);
244
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp);
247
if(fb_info_tmp.width){
248
/* Free up the temporary frame buffer */
249
display->context->dispatch.gmm_free(fb_info_tmp.fb_base_offset);
250
OS_MEMSET(&fb_info_tmp,0,sizeof (igd_framebuffer_info_t));
252
OS_MEMSET(wa, 0, sizeof(tnc_wa_timing_t));
257
/* Increment checking counter */
260
/* CRC starting value */
261
blue_crc.pixel = 0x007FFFFF;
262
green_crc.pixel = 0x007FFFFF;
263
red_crc.pixel = 0x007FFFFF;
265
if(FLAG(flag_turn_off_port_wa)){
266
/* Turn of port source.
268
temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG);
270
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp);
273
/* Allocate temporary 32 bpp frame buffer for CRC calculation.
274
* SV only provided codes for 32bpp CRC calculation so we would
275
* only calculate CRC for 32bpp. Once CRC is calculated EMGD
276
* would revert back to original plane. A temporary place is also
277
* neede so no corruption is seen on lvds for clone display
279
if(fb_info_tmp.width != (unsigned short)pTimings_tmp.width &&
280
fb_info_tmp.height != (unsigned short)pTimings_tmp.height){
281
if(fb_info_tmp.width){
282
EMGD_ERROR("Memory leak! Previous framebuffer is not freed!");
284
fb_info_tmp.width = pTimings_tmp.width;
285
fb_info_tmp.height = pTimings_tmp.height;
286
fb_info_tmp.screen_pitch = fb_info->screen_pitch;
287
fb_info_tmp.fb_base_offset = 0;
288
fb_info_tmp.pixel_format = IGD_PF_xRGB32;
289
fb_info_tmp.flags = IGD_SURFACE_DISPLAY | IGD_SURFACE_RENDER;
291
ret_val = display->context->dispatch.gmm_alloc_surface(
292
&fb_info_tmp.fb_base_offset,
293
fb_info_tmp.pixel_format,
296
&fb_info_tmp.screen_pitch,
298
IGD_GMM_ALLOC_TYPE_NORMAL,
301
/* Temp plane is always 32 bpp */
302
temp_control = EMGD_READ32(MMIO(display)
303
+ PLANE(display)->plane_reg);
304
plane_control = temp_control;
305
plane_control &= ~(BIT30 | BIT29 | BIT28 | BIT27);
306
plane_control |= BIT28 | BIT27;
307
EMGD_WRITE32(plane_control, MMIO(display)
308
+ PLANE(display)->plane_reg);
309
temp_pitch = EMGD_READ32(MMIO(display)
310
+ PLANE(display)->plane_reg + DSP_STRIDE_OFFSET);
311
EMGD_WRITE32(fb_info_tmp.screen_pitch, MMIO(display)
312
+ PLANE(display)->plane_reg + DSP_STRIDE_OFFSET);
313
temp_plane = EMGD_READ32(MMIO(display)
314
+ PLANE(display)->plane_reg + DSP_START_OFFSET);
315
EMGD_WRITE32(fb_info_tmp.fb_base_offset,
316
MMIO(display) + PLANE(display)->plane_reg + DSP_START_OFFSET);
317
/* Setup front buffer */
318
OS_MEMSET(&front_buffer,0,sizeof (igd_surface_t));
319
front_buffer.width = fb_info_tmp.width;
320
front_buffer.height = fb_info_tmp.height;
321
front_buffer.pitch = fb_info_tmp.screen_pitch;
322
front_buffer.offset = fb_info_tmp.fb_base_offset;
323
front_buffer.pixel_format = fb_info_tmp.pixel_format;
324
front_buffer.flags = fb_info_tmp.flags;
325
/* Draw 2 color bars for CRC calculation. This is simple and sufficient
326
* to detect clipping. Will consider complicated color bar if an issue
327
* is found for now go for quickest methodColor bar. Red and Blue */
328
dst_rect.x1 = dst_rect.y1 = 0;
329
dst_rect.x2 = fb_info_tmp.width/2;
330
dst_rect.y2 = fb_info_tmp.height;
333
// NOT supported in koheo, using software for now
334
display->context->dispatch.color_blt((igd_display_h)display,
338
IGD_ALPHA_CHANNEL | IGD_RGB_CHANNEL,
341
(igd_appcontext_h)0, IGD_RENDER_BLOCK);
345
unsigned long row, col;
346
unsigned char *buf = NULL;
347
unsigned long height = fb_info_tmp.height;
348
unsigned long width = fb_info_tmp.width/2;
349
unsigned long pitch = fb_info_tmp.screen_pitch;
351
buf = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset);
352
for (row = 0; row < (height); row++) {
353
for (col = 0; col < (width); col++) {
354
EMGD_WRITE32(0x00FF0000, (buf + (col*4)));
358
display->context->dispatch.gmm_unmap(buf);
361
dst_rect.x1 = fb_info_tmp.width/2;
363
dst_rect.x2 = fb_info_tmp.width;
364
dst_rect.y2 = fb_info_tmp.height;
367
// NOT supported in koheo, using software for now
368
display->context->dispatch.color_blt((igd_display_h)display,
372
IGD_ALPHA_CHANNEL | IGD_RGB_CHANNEL,
375
(igd_appcontext_h)0, IGD_RENDER_BLOCK);
376
wa->flag |= TNC_HTOTAL_TUNED;
377
pTimings->reserved_dd = (wa->htotal | TNC_HTOTAL_TUNED);
380
display->context->dispatch.sync((igd_display_h)display, IGD_PRIORITY_NORMAL,
386
unsigned long row, col;
387
unsigned char *buf = NULL;
388
unsigned long height = fb_info_tmp.height;
389
unsigned long width = fb_info_tmp.width;
390
unsigned long pitch = fb_info_tmp.screen_pitch;
392
buf = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset);
393
for (row = 0; row < (height); row++) {
394
for (col = fb_info_tmp.width/2; col < (width); col++) {
395
EMGD_WRITE32(0x000000FF, (buf + (col*4)));
399
display->context->dispatch.gmm_unmap(buf);
403
ret_val = -IGD_ERROR_BUSY;
404
timeout = OS_SET_ALARM(500);
405
while (-IGD_ERROR_BUSY == ret_val && (!OS_TEST_ALARM(timeout))){
406
ret_val = display->context->dispatch.sync(
407
(igd_display_h)display,
418
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_CRC_CTRL_REG, 0x80000000);
419
/* Reset Status Bit */
420
temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, 0x71024);
422
WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, 0x71024, temp);
423
temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024);
425
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024, temp);
427
/* Calculate CRC pixel by reading every single pixel.
428
* Pixel that is more than the timing range is ignore which happens
429
* during panning. To save time CRC is only calculated once per timing
430
* change and kept inside a scratch global variable wa.
432
if(wa->crc_red == 0 || wa->crc_green == 0 ||
434
unsigned char *fb_adr;
436
fb_adr = display->context->dispatch.gmm_map(fb_info_tmp.fb_base_offset);
438
/* Calculate CRC for this timing */
439
for(i=0; i<(int)pTimings_tmp.height; i++){
440
for(j=0; j<(int)pTimings_tmp.width; j++){
441
if(i < (int)fb_info_tmp.height && j < (int)fb_info_tmp.width){
442
/* virt_fb_adr not available anymore */
444
curr_pixel = (unsigned long*)(
445
mode_context->context->device_context.virt_fb_adr +
446
fb_info_tmp.fb_base_offset + j*bps + (i*fb_info_tmp.screen_pitch));
449
curr_pixel = (unsigned long*)(fb_adr + (j*bps) + (i*fb_info_tmp.screen_pitch));
451
if(curr_pixel == NULL){
452
EMGD_DEBUG("FB not valid return true for now util FB is allocated");
459
blue_val.pixel = (0x0000ff & *curr_pixel) >> 0;
460
green_val.pixel = (0x00ff00 & *curr_pixel) >> 8;
461
red_val.pixel = (0xff0000 & *curr_pixel) >> 16;
464
blue_val.pixel = (0x0000ff & EMGD_READ32(curr_pixel)) >> 0;
465
green_val.pixel = (0x00ff00 & EMGD_READ32(curr_pixel)) >> 8;
466
red_val.pixel = (0xff0000 & EMGD_READ32(curr_pixel)) >> 16;
469
red_val.pixel = green_val.pixel = blue_val.pixel = 0;
472
blue_crc = compute_pixel_crc(blue_crc, blue_val);
473
green_crc = compute_pixel_crc(green_crc, green_val);
474
red_crc = compute_pixel_crc(red_crc, red_val);
477
display->context->dispatch.gmm_unmap(fb_adr);
479
/* Save calculated value */
480
wa->crc_red = red_crc.pixel;
481
wa->crc_green = green_crc.pixel;
482
wa->crc_blue = blue_crc.pixel;
484
/* Reuse CRC value calculated before */
485
red_crc.pixel = wa->crc_red;
486
green_crc.pixel = wa->crc_green;
487
blue_crc.pixel = wa->crc_blue;
490
timeout = OS_SET_ALARM(70);
492
temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x71024);
493
if(temp & 0x00002000){
497
} while ((!OS_TEST_ALARM(timeout)));
498
/* Give some time for CRC to be stable */
500
/* Read CRC on LNC and OVL */
501
tnc_crc_red = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61060);
502
tnc_crc_green = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61064);
503
tnc_crc_blue = READ_MMIO_REG_TNC(IGD_PORT_SDVO,0x61068);
505
/* Revert back to original plane */
506
EMGD_WRITE32(temp_control, MMIO(display)
507
+ PLANE(display)->plane_reg);
508
EMGD_WRITE32(temp_pitch, MMIO(display)
509
+ PLANE(display)->plane_reg + DSP_STRIDE_OFFSET);
510
EMGD_WRITE32(temp_plane, MMIO(display)
511
+ PLANE(display)->plane_reg + DSP_START_OFFSET);
514
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_CRC_CTRL_REG, 0x00000000);
515
/* Compare CRC calculation with Atom E6xx CRC, return false if a mismatch and
516
* tuning continues. If it matches indicate the flag as tuned and return
517
* false anyway so pipe programming would program based on the correct
520
if((red_crc.pixel != (unsigned int)tnc_crc_red) ||
521
(green_crc.pixel != (unsigned int)tnc_crc_green) ||
522
(blue_crc.pixel != (unsigned int)tnc_crc_blue)){
524
/* Step by step tuning */
527
/* Calculate the delta value */
528
wa->htotal = (wa->htotal + wa->delta);
530
EMGD_DEBUG("Counter %d",wa->counter);
531
EMGD_DEBUG("Red CRC: %d Red TNC: %lu",red_crc.pixel,tnc_crc_red);
532
EMGD_DEBUG("Grn CRC: %d Grn TNC: %lu",green_crc.pixel,tnc_crc_green);
533
EMGD_DEBUG("Blu CRC: %d Blu TNC: %lu",blue_crc.pixel,tnc_crc_blue);
534
EMGD_DEBUG("CRC does not match, tuning....");
538
EMGD_ERROR("Tuned value found.");
539
EMGD_ERROR("Total tuning required %d",wa->counter);
540
EMGD_DEBUG("Red CRC: %d Red TNC: %lu",red_crc.pixel,tnc_crc_red);
541
EMGD_DEBUG("Grn CRC: %d Grn TNC: %lu",green_crc.pixel,tnc_crc_green);
542
EMGD_DEBUG("Blu CRC: %d Blu TNC: %lu",blue_crc.pixel,tnc_crc_blue);
543
wa->flag |= TNC_HTOTAL_TUNED;
544
pTimings->reserved_dd = (wa->htotal | TNC_HTOTAL_TUNED);
547
/* We are tuned but lets do another sequence since we may have changed
548
* the blanks to get a valid CRC. This happens on certain modes that has
549
* weird blanks value like VESA's 640x480@60
556
/* Setting the CDVO Signal */
557
static void cdvo_signal()
560
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x00008000);
561
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x0008B400);
566
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x0008B4FF);
572
/* disable this function now */
573
/* This is the initialization code for B0 stepping */
574
void program_cdvo(igd_display_context_t *display, unsigned long pipe_reg)
576
/* unsigned long pipe_conf; */
581
//if(READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000) != 0x50){
583
//programmable cdvo stall
584
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x6102c, 0xf);
585
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x40);
588
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x51);
589
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x50);
592
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004800);
593
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x000BB4FF);
594
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, 0x20022160);
595
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7010, 0x06000200);
597
/* loop 3 pixels, 6 calls to cdvo_signal() */
603
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x51);
604
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x50);
607
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004800);
608
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x700c, 0x000BB4FF);
609
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, 0x20022160);
610
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7010, 0x06000200);
612
/* loop 3 pixels, 6 calls to cdvo_signal() */
618
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x51);
619
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x50);
621
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7010, 0x02000200);
622
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004000);
623
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, 0x20022160);
624
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7010, 0x02000200);
625
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00000800);
626
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004800);
627
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00000000);
628
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000, 0x50);
630
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7014, 0x00004000);
632
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, 0x20022160);//enable sdvo
634
//WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, 0x70400, 0x4088);//enable sdvo
643
* @param mmio dev2 mmio
647
static void disable_vga_tnc (unsigned char *mmio)
654
/* Disable VGA plane if it is enabled. */
655
temp = EMGD_READ32(EMGD_MMIO(mmio) + VGACNTRL);
656
if ((temp & BIT31) == 0) {
658
READ_VGA(mmio, SR_PORT, SR01, sr01);
660
/* Turn on SR01 bit 5 */
661
WRITE_VGA(mmio, SR_PORT, SR01, sr01|BIT(5));
666
temp |= BIT31; /* set bit 31 to disable */
667
temp &= ~BIT30; /* clear bit 30 to get VGA display in normal size */
668
EMGD_WRITE32(temp, EMGD_MMIO(mmio) + VGACNTRL);
677
* @param display_handle
678
* @param palette_entry
679
* @param palette_color
681
* @return 0 on success
682
* @return -IGD_INVAL on failure
684
int igd_set_palette_entry_tnc(
685
igd_display_h display_handle,
686
unsigned long palette_entry,
687
unsigned long palette_color)
689
/* Return if Pipe is not on */
690
if(!((1L<<31) & READ_MMIO_REG_TNC(PORT_TYPE_DH(display_handle),
691
PIPE(display_handle)->pipe_reg))) {
694
/* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */
695
WRITE_MMIO_REG_TNC(IGD_PORT_LVDS,
696
PIPE(display_handle)->palette_reg + palette_entry * 4,
704
* @param display_handle
705
* @param palette_entry
706
* @param palette_color
708
* @return 0 on success
709
* @return -IGD_INVAL on failure
711
int igd_get_palette_entry_tnc(
712
igd_display_h display_handle,
713
unsigned long palette_entry,
714
unsigned long *palette_color)
716
/* Return if Pipe is not on */
717
if(!((1L<<31) & READ_MMIO_REG_TNC(
718
PORT_TYPE_DH(display_handle),
719
PIPE(display_handle)->pipe_reg))) {
722
/* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */
723
*palette_color = 0xffffff & READ_MMIO_REG_TNC(
725
PIPE(display_handle)->palette_reg + palette_entry * 4);
734
* @return 0 on success
735
* @return 1 on failure
737
int wait_for_vblank_tnc(unsigned long pipe_reg)
739
unsigned long pipe_status_reg = pipe_reg + PIPE_STATUS_OFFSET;
741
unsigned long port_type = IGD_PORT_LVDS;
744
unsigned long request_for;
748
EMGD_DEBUG("Parameter: pipe_reg = %lx", pipe_reg);
750
/* If pipe is off then just return */
751
if(!((1L<<31) & READ_MMIO_REG_TNC(port_type, pipe_reg))) {
752
EMGD_DEBUG("Pipe disabled/Off");
758
* When VGA plane is on the normal wait for vblank won't work
759
* so just skip it. VGA plane is on 0:2:0 so no need to use _TNC macros.
761
if(!(EMGD_READ32(MMIO_TNC(port_type) + 0x71400) & 0x80000000)) {
762
EMGD_DEBUG("VGA Plane On");
767
/* 1. Request the interrupt handler to record the next VBlank: */
768
request_for = VBINT_REQUEST(VBINT_WAIT,
769
(pipe_status_reg == PIPEA_STAT) ? VBINT_PORT2 : VBINT_PORT4);
770
mode_context->dispatch->full->request_vblanks(request_for,
771
MMIO_TNC(port_type));
773
/* 2. Wait (about 50 msec, 20Hz) & poll for the next VBlank: */
774
timeout = OS_SET_ALARM(50);
777
tmp = mode_context->dispatch->full->vblank_occured(request_for);
778
} while ((tmp == 0x00) && (!OS_TEST_ALARM(timeout)));
780
EMGD_ERROR_EXIT("Timeout waiting for VBLANK");
786
/* 3. End our request for the next VBlank: */
787
mode_context->dispatch->full->end_request(request_for,
788
MMIO_TNC(port_type));
793
} /* wait_for_vblank_tnc */
796
* This procedure waits for the next vertical blanking (vertical retrace)
797
* period. If the display is already in a vertical blanking period, this
800
* Note: A timeout is included to prevent an endless loop.
802
* @param display_handle
804
* @return FALSE if timed out
806
int igd_wait_vblank_tnc(igd_display_h display_handle)
809
return wait_for_vblank_tnc(PIPE(display_handle)->pipe_reg);
814
* Get the stride and stereo values based on the display. This is also used
815
* by the MI instructions.
817
* @param display Pointer to hardware device instance data
818
* @param flags Should the stereo be for the frontbuffer or backbuffer?
820
* @return stride - Stride of the display
821
* @return stereo - Stereo address of the display
823
int mode_get_stride_stereo_tnc(igd_display_context_t *display,
824
unsigned long *stride,
825
unsigned long *stereo,
828
unsigned long pitch = PLANE(display)->fb_info->screen_pitch;
829
igd_timing_info_t *timing = PIPE(display)->timing;
830
unsigned long base_offset;
834
base_offset = PLANE(display)->fb_info->visible_offset;
838
/* For field replication, valid for interlaced modes only
839
* set stereo = fb_base
842
if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
844
if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
845
/* Interlaced + Line double flags means field replication.
846
* same lines are sent for both fields. Program the
847
* second eye to be same as the first
849
*stereo = base_offset;
851
/* Regular interlaced. Second eye starts on line 2.
852
* Skip every other line.
854
*stereo = base_offset + pitch;
864
* Atom E6xx LVDS display: Mode switch sequence
868
* Program power on delay, power off delay, power cycle delay registers
869
* Program backlight control register to set appropriate backlight value
870
* Pipe A must be completely off at this point
871
* Write PIPEACONF bits[19:18] = 00
872
* Write DSPACNTR bit[31] = 1
873
* Write DSPASURF = 0x00000000
874
* Write DSPACNTR bit[31] = 0
875
* Write DSPASURF = 0x00000000
876
* Restore PIPEACONF bits[19:18] to original value
879
* Wait for DPLL warm up 10us and check for DPLL lock bit in Pipe A config reg
880
* (Wait ensures clock is running smoothly before enabling pipe)
881
* Program pipe timings (Can be done before DPLL programming)
882
* Enable panel fitter as needed (Can be done before DPLL and/or
883
* pipe timing programming)
885
* Enable planes (VGA or HiRes)
887
* Enable panel power (Can be done before DPLL programming)
889
* 2. Disable sequence
891
* Disable panel backlight
892
* Disable panel power (for AOAC standby)
894
* Disable planes (VGA or hires)
896
* Disable VGA display in 0x71400 bit 31
897
* (Disable VGA display done after disable pipe to allow pipe to turn off
898
* when no vblank is available in native VGA mode)
899
* Wait for pipe off status
900
* (Wait ensures planes and pipe have completely turned off prior to
901
* disabling panelfitter then DPLL)
902
* Disable panelfitter
904
* Pipe timings change or change between VGA native or VGA center/upperleft
906
* Use complete disable sequence followed by complete enable sequence with
907
* new mode programmings.
910
* Atom E6xx SDVO display: Display Pipe B Enable/Disable sequence:
914
* Program LNC and LNW DPLL
915
* Write all planes, port, power control registers on both LNC and LNW
916
* 1st Enable LNC pipe
917
* 2nd Enable LNW pipe
919
* 2. Disable Sequence
921
* Disable panel power
924
* 1st Disable LNC pipe
925
* 2nd Disable TNC_SDVO pipe
926
* Disable panel fitter
932
* @param display Pointer to hardware device instance data
936
void program_pipe_vga_tnc(
937
igd_display_context_t *display)
939
igd_timing_info_t *timing;
940
unsigned long vga_control;
941
unsigned long upscale = 0;
947
* VGA Plane can attach to only one pipe at a time. LVDS can
948
* only attach to pipe B. We need to use the display passed to
949
* determine the pipe number to use. (Napa is same as Alm).
953
* We can come here with following cases:
954
* 1. magic->vga CRT, DVI type displays
955
* 2. native->vga int-lvds, and up-scaling lvds displays
956
* 3. pipe->vga TV and other unscaled-lvds displays
958
vga_control = EMGD_READ32(MMIO(display) + 0x71400);
959
vga_control &= 0x18e3ff00;
962
timing = PIPE(display)->timing;
963
if(!timing->extn_ptr) {
964
EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_tnc");
968
/* Find UPSCALING attr value*/
969
pi_pd_find_attr_and_value(PORT_OWNER(display),
970
PD_ATTR_ID_PANEL_FIT,
971
0,/*no PD_FLAG for UPSCALING */
972
NULL, /* dont need the attr ptr*/
974
/* this PI func will not modify value of upscale if attr does not exist */
976
/* magic->vga || native->vga cases, centering isn't required */
977
if ((timing->width == 720 && timing->height == 400) || upscale) {
978
EMGD_DEBUG("Centering = 0");
983
if((timing->width >= 800) && !upscale) {
984
EMGD_DEBUG("Enable VGA Border");
985
vga_control |= (1L<<26);
988
if(timing->width == 640) {
989
EMGD_DEBUG("Enable Nine Dot Disable");
990
vga_control |= (1L<<18);
994
EMGD_DEBUG("Enable VGA Center Centering");
995
vga_control |= 1L<<24;
997
if(timing->height >= 960) {
998
if(timing->width >= 1280) {
999
EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
1000
vga_control |= (1L<<30) | (1L<<18);
1004
if(PORT_OWNER(display)->port_type == IGD_PORT_LVDS) {
1005
EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
1006
vga_control |= (1L<<25 | (1L<<18));
1007
} else if (upscale) {
1008
EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
1009
vga_control |= 1L<<25;
1013
if(PIPE(display)->pipe_num) {
1014
vga_control |= 1L<<29;
1017
program_pipe_vga(display, (igd_timing_info_t *)timing->extn_ptr);
1018
EMGD_WRITE32(vga_control, MMIO(display) + 0x71400);
1025
* Program Display Plane Values.
1027
* @param display Pointer to hardware device instance data
1032
void program_plane_tnc(igd_display_context_t *display,
1033
unsigned long status)
1035
unsigned long stride;
1036
unsigned long stereo;
1037
unsigned long plane_control;
1038
unsigned long other_plane_reg;
1039
igd_timing_info_t *timing;
1040
igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info;
1041
unsigned long plane_reg = PLANE(display)->plane_reg;
1042
igd_timing_info_t *pipe_timing;
1043
/* tnc_wa_timing_t *wa = WA_TUNE; */
1047
EMGD_DEBUG("Program Plane: %s", status?"ENABLE":"DISABLE");
1048
EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
1050
igd_wait_vblank_tnc((igd_display_h)display);
1052
plane_control = EMGD_READ32(MMIO(display) + plane_reg);
1053
if(PLANE(display)->plane_reg == DSPACNTR) {
1054
plane_control &= device_data->plane_a_preserve;
1055
} else { /* if it's plane b or plane c */
1056
plane_control &= device_data->plane_b_c_preserve;
1059
/* TODO: Bspec: For EagleLake this Trickle Feed must always disable */
1061
if((status == FALSE) ||
1062
(GET_DEVICE_POWER_STATE(display) != IGD_POWERSTATE_D0)) {
1065
* Note: The vga programming code does not have an "off". So
1066
* when programming the plane to off we make sure VGA is off
1069
disable_vga_tnc(MMIO(display));
1072
* To turn off plane A or B, the program have to triger the plane A or B
1073
* start register. Or else, it will not work.
1075
EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
1076
EMGD_WRITE32(EMGD_READ32(MMIO(display) + plane_reg + DSP_START_OFFSET),
1077
MMIO(display) + plane_reg + DSP_START_OFFSET);
1079
igd_wait_vblank_tnc((igd_display_h)display);
1084
* Note: The very first pass through this function will be with
1085
* status false and timings == NULL. Don't use the timings before
1088
timing = PIPE(display)->timing;
1089
pipe_timing = timing;
1090
/* There is a special case code for legacy VGA modes */
1091
while (timing->extn_ptr) {
1092
timing = (igd_timing_info_t *)timing->extn_ptr;
1094
if(MODE_IS_VGA(timing) && CHECK_VGA(pipe_timing)) {
1095
program_plane_vga(display, timing);
1100
disable_vga_tnc(MMIO(display));
1102
/* enable plane, select pipe, enable gamma correction logic */
1103
plane_control |= 0x80000000 | (PIPE(display)->pipe_num<<24);
1104
PIPE(display)->plane = PLANE(display);
1105
#ifndef CONFIG_MICRO
1106
plane_control |= (1<<30);
1109
/* Here the settings:
1110
* If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
1111
* If line dbling only, set 21,20 to 11b
1112
* If pixel dbling only, set 21,20 to 00b, but set Horz Multiply
1113
* If no doubling, set 21,20 to 00b (no Horz Multiply)
1114
* For pixel doubling
1115
* --> both progressive/interlaced modes
1117
* --> progressive modes only
1120
if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
1121
/* Line doubling in progressive mode requires special bits */
1122
if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
1123
/* BIT 20 for line & pixel doubling*/
1124
plane_control |= BIT20;
1125
/* check later, if no pixel doubling, set bit 21 too*/
1128
if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
1129
/* For line ONLY doubling, set bit 21 also '1' */
1130
plane_control |= BIT21;
1133
mode_get_stride_stereo_tnc(display, &stride, &stereo, 0);
1135
/* set color depth */
1136
switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
1138
plane_control |= BIT27 | BIT30;
1141
plane_control |= BIT28 | BIT26;
1145
plane_control |= BIT28 | BIT27;
1149
if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
1150
plane_control |= (BIT30);
1153
if(fb_info->flags & IGD_SURFACE_TILED) {
1154
plane_control |= (BIT10);
1157
/* Set watermark for Atom E6xx */
1158
#ifndef CONFIG_MICRO
1160
if (plane_reg == DSPACNTR) {
1161
other_plane_reg = DSPBCNTR;
1163
other_plane_reg = DSPACNTR;
1166
if (EMGD_READ32(MMIO(display) + other_plane_reg) & 0x80000000) {
1167
EMGD_WRITE32(device_data->dsp_arb, MMIO(display) + DSP_ARB);
1168
} else if (plane_reg == DSPACNTR) {
1169
EMGD_WRITE32(0x00003fff, MMIO(display) + DSP_ARB);
1171
EMGD_WRITE32(0x00003f80, MMIO(display) + DSP_ARB);
1174
EMGD_WRITE32(device_data->fifo_watermark1, MMIO(display) + FW_1);
1175
EMGD_WRITE32(device_data->fifo_watermark2, MMIO(display) + FW_2);
1176
EMGD_WRITE32(device_data->fifo_watermark3, MMIO(display) + FW_3);
1177
EMGD_WRITE32(device_data->fifo_watermark4, MMIO(display) + FW_4);
1178
EMGD_WRITE32(device_data->fifo_watermark5, MMIO(display) + FW_5);
1179
EMGD_WRITE32(device_data->fifo_watermark6, MMIO(display) + FW_6);
1182
/* ITP Script is doing this and so go ahead */
1183
/* The DSP_ARB set fixed the issue with 32bit vesa modes */
1184
EMGD_WRITE32(0x00001FBF, MMIO(display) + DSP_ARB);
1185
EMGD_WRITE32(0x3F8F0F18, MMIO(display) + FW_1);
1187
/* FIXME: Not required for TNC.
1188
* The B-Spec states that rendering will be slower if the fences are not
1189
* a power of 2. So for now, always use a power of 2. */
1190
/* EMGD_WRITE32(0x04000400, MMIO(display) + 0x209c); */
1192
EMGD_DEBUG(" Plane Control: 0x%lx", plane_control);
1193
EMGD_DEBUG(" Plane Base: 0x%lx", fb_info->visible_offset);
1194
EMGD_DEBUG(" Plane Pitch: 0x%lx", stride);
1196
EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
1197
EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET);
1198
/* Both of these registers are Reserved on Gen4 */
1199
/*EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET);*/
1200
/*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);*/
1201
EMGD_WRITE32(0, MMIO(display) + plane_reg + DSP_LINEAR_OFFSET);
1202
EMGD_WRITE32(0, MMIO(display) + plane_reg + 0x24);
1203
EMGD_WRITE32(fb_info->visible_offset,
1204
MMIO(display) + plane_reg + DSP_START_OFFSET);
1206
igd_wait_vblank_tnc((igd_display_h)display);
1212
* PGen4 can check when the pipe is enabled or disabled.
1213
* This function waits for the pipe to be enabled or disabled.
1214
* check_on_off = 0 to wait for the pipe to disable.
1215
* check_on_off = 0x40000000 to wait for the pipe to enable.
1219
* @param check_on_off
1223
static void wait_pipe(unsigned long pipe_reg, unsigned long check_on_off)
1230
/* 0:3:0 doesn't wait pipe, only LNC device does. */
1231
if (pipe_reg == 0x71008) {
1235
/* Wait for Pipe enable/disable, about 50 msec (20Hz). */
1236
timeout = OS_SET_ALARM(50);
1239
temp = EMGD_READ32(MMIO_TNC(IGD_PORT_LVDS) + pipe_reg) & 0x40000000;
1240
/* Check for timeout */
1241
} while ((temp != check_on_off) && (!OS_TEST_ALARM(timeout)));
1243
if (temp != check_on_off) {
1244
EMGD_ERROR_EXIT("Timeout waiting for pipe enable/disable");
1252
* This function programs the Timing registers and clock registers and
1253
* other control registers for PIPE.
1260
void program_pipe_tnc(igd_display_context_t *display,
1261
unsigned long status)
1263
unsigned long timing_reg;
1264
unsigned long pipe_conf;
1265
unsigned long hactive, vactive;
1266
igd_timing_info_t *pTimings;
1267
igd_timing_info_t pTimings_tmp;
1268
igd_display_port_t *port;
1270
unsigned long pt = PORT_TYPE(display);
1273
short hactive_tmp, vactive_tmp;
1275
tnc_wa_timing_t *wa;
1276
/* igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; */
1280
EMGD_DEBUG("Program Pipe: %s", status?"ENABLE":"DISABLE");
1281
EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
1283
pipe_conf = device_data->pipe_preserve &
1284
READ_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg);
1286
if((status == FALSE) ||
1287
(GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) {
1288
/* For SDVO disable both pipe Bs in 0:2:0 and 0:3:0 */
1289
if (pt == IGD_PORT_SDVO) {
1290
WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->pipe_reg,
1291
pipe_conf & (~0x80000000L));
1294
WRITE_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg,
1295
pipe_conf & (~0x80000000L));
1297
/* check when the pipe is disabled. */
1298
wait_pipe(PIPE(display)->pipe_reg, 0);
1301
//WRITE_MMIO_REG_TNC(pt, PIPE(display)->clock_reg->dpll_control,
1302
// READ_MMIO_REG_TNC(pt,
1303
// PIPE(display)->clock_reg->dpll_control) & ~0x80000000L);
1310
port = PORT_OWNER(display);
1311
pTimings = PIPE(display)->timing;
1314
/* Debug messages */
1315
pd_timing_t *vga_timing = (pd_timing_t *)pTimings->extn_ptr;
1316
EMGD_DEBUG("pTimings %ux%u mode_number = %u mode_info_flags = 0x%lx, dclk = %lu",
1319
pTimings->mode_number,
1320
pTimings->mode_info_flags,
1323
EMGD_DEBUG("ext_timing %ux%u mode_number = %u mode_info_flags= 0x%lx, dclk = %lu",
1326
vga_timing->mode_number,
1327
vga_timing->mode_info_flags,
1333
* If the mode is VGA and the PD says it handles all VGA modes without
1334
* reprogramming then just set the mode and leave centering off.
1336
if(pTimings->mode_info_flags & IGD_MODE_VESA) {
1337
EMGD_DEBUG("IGD_MODE_VESA");
1338
if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
1339
/* Pipe timings and clocks no longer need to be set since
1340
* the VGA timings will be used.
1341
WRITE_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg,
1342
pipe_conf | 0x80000000); */
1344
/* Gen4 can check when the pipe is enabled. No longer needed
1345
* since pipe not enabled and VGA timings are used.
1346
wait_pipe(PIPE(display)->pipe_reg, 0x40000000);*/
1348
EMGD_DEBUG("pTimings->mode_number <= VGA_MODE_NUM_MAX");
1349
program_pipe_vga_tnc(display);
1355
MMIO_TNC(PORT(display, display->port_number)->port_type));
1360
/* Program dot clock divisors. */
1361
program_clock_tnc(display, PIPE(display)->clock_reg, pTimings->dclk);
1363
/* Program timing registers for the pipe */
1364
timing_reg = PIPE(display)->timing_reg;
1365
if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) {
1366
hactive = (unsigned long)pTimings->width*2 - 1;
1368
hactive = (unsigned long)pTimings->width - 1;
1371
if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) {
1372
vactive = (unsigned long)pTimings->height*2 - 1;
1374
/* For Atom E6xx Hardware will automatically divide by 2 to
1375
get the number of line in each field */
1376
vactive = (unsigned long)pTimings->height - 1;
1379
#ifndef CONFIG_MICRO
1380
/* reset the palette */
1381
for (i = 0; i < 256; i++) {
1382
WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->palette_reg,
1383
((i<<16) | (i<<8) | i));
1387
/* apply color correction */
1388
for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
1390
if ((PD_ATTR_ID_FB_GAMMA == (port->attributes[i].id)) ||
1391
(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
1392
(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id))) {
1394
mode_context->dispatch->full->set_color_correct(display);
1400
* NOTE: For size reasons the timng table contains unsigned short
1401
* values. Don't shift them past 16. Use a temp instead.
1402
* All register offsets and bit shift are verified for Gen4
1405
* Write values into pipe B registers in both 0:2:0 and 0:3:0
1408
dc = *(display->context->mod_dispatch.dsp_current_dc);
1412
for (i=0; i<2; i++) {
1414
pTimings_tmp = *pTimings;
1415
hactive_tmp = (short) hactive;
1416
vactive_tmp = (short) vactive;
1417
#ifndef CONFIG_MICRO
1418
/* Clone and Exteded not Supported in VBIOS for TNC
1419
* This work around is only for Atom E6xx B0
1421
if((IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc))
1422
&& pt == IGD_PORT_SDVO && (display->context->device_context.rid == TNC_B0_RID)
1423
&& FLAG(flag_basic_htotal_formula_wa)){
1425
if(!(pTimings->reserved_dd & TNC_HTOTAL_TUNED)){
1426
/* Modify blanks so it always begin after active pixel and ends at the
1427
* end. Do not change it if we are already tuned to maintain
1428
* original timing specification
1430
pTimings_tmp.hblank_start = (short) (pTimings->width - 1);
1431
pTimings_tmp.vblank_start = (short) (pTimings->height - 1);
1432
pTimings_tmp.hblank_end = (short) (pTimings->htotal);
1433
pTimings_tmp.vblank_end = (short) (pTimings->vtotal);
1437
if(pTimings->reserved_dd == 0 || (wa->counter > LIMIT_TOTAL_CHECK_DISPLAY)){
1438
/* First time tuning */
1439
if ((mode_context->ref_freq != 0) &&
1440
(mode_context->ref_freq >= 190000) &&
1441
(mode_context->ref_freq <= 210000)){
1442
calc = (pTimings->htotal * mode_context->ref_freq);
1444
calc = (pTimings->htotal * LNC_CLOCK);
1447
calc = (calc / (PIPE(display)->clock_reg->actual_dclk));
1448
calc *= (pTimings->vtotal -1);
1449
calc /= pTimings->vtotal;
1450
pTimings_tmp.htotal = (short)calc;
1451
pTimings->reserved_dd = wa->htotal = pTimings_tmp.htotal;
1452
EMGD_DEBUG("Delta = %d", wa->htotal);
1453
}else if (pTimings->reserved_dd & TNC_HTOTAL_TUNED){
1454
pTimings_tmp.htotal = (short)(pTimings->reserved_dd & (~TNC_HTOTAL_TUNED));
1457
wa->htotal = (short)pTimings->reserved_dd;
1458
pTimings_tmp.htotal = wa->htotal;
1460
/* Use vphase formula if available */
1462
pTimings_tmp.vtotal -= (short)vphase;
1463
pTimings_tmp.vsync_start -= (short)vphase;
1464
pTimings_tmp.vsync_end -= (short)vphase;
1465
pTimings_tmp.vblank_end -= (short)vphase;
1467
//pTimings_tmp.hblank_start += (short) (pTimings_tmp.htotal - pTimings->htotal);
1468
pTimings_tmp.hblank_end += (short) (pTimings_tmp.htotal - pTimings->htotal);
1474
temp = (unsigned long)(pTimings_tmp.htotal) << 16 | hactive_tmp;
1475
WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg, temp);
1477
temp = ((unsigned long) pTimings_tmp.hblank_end << 16) |
1478
(unsigned long)(pTimings_tmp.hblank_start);
1479
WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x04, temp);
1481
temp = ((unsigned long)(pTimings->hsync_end) << 16) |
1482
(unsigned long)(pTimings->hsync_start);
1483
WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x08, temp);
1485
temp = ((unsigned long)(pTimings_tmp.vtotal) << 16) | vactive_tmp;
1486
WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x0C, temp);
1488
temp = ((unsigned long)(pTimings_tmp.vblank_end) << 16) |
1489
(unsigned long)(pTimings_tmp.vblank_start);
1490
WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x10, temp);
1492
temp = ((unsigned long)(pTimings_tmp.vsync_end)<< 16) |
1493
(unsigned long)(pTimings_tmp.vsync_start);
1494
WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x14, temp);
1497
* If there is a linked mode it is either the VGA or a scaled
1498
* mode. If it is scaled then we need to use it as the source size.
1500
if(pTimings->extn_ptr) {
1501
igd_timing_info_t *scaled_timings =
1502
(igd_timing_info_t *)pTimings->extn_ptr;
1503
if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
1504
(scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
1505
temp = (hactive << 16) | vactive;
1507
EMGD_DEBUG("scaled_timings->width [%d], scaled_timings->height [%d]\n", scaled_timings->width, scaled_timings->height);
1508
temp = (unsigned long)scaled_timings->width - 1;
1509
temp = (temp << 16) |
1510
(unsigned long)(scaled_timings->height - 1);
1513
temp = (hactive_tmp << 16) | vactive_tmp;
1515
WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x1C, temp);
1518
pipe_conf |= PIPE_ENABLE;
1520
/* Put pipe in interlaced mode if requested:
1521
* should only happen for LVDS display if at all. */
1522
if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
1523
pipe_conf |= (INTERLACE_EN);
1525
pipe_conf &= ~(INTERLACE_EN);
1529
if (pt == IGD_PORT_SDVO) {
1531
Enable the panel fitter as VGA controller in Lincroft
1532
is a Panel Fitted VGA controller.
1533
LNC only supports panel fitted VGA mode
1534
(upper left VGA mode). You need to enable the panel fitter.
1535
The timing control will be from the pipe timing generator
1536
but not from the VGA timing generator CRTC registers
1537
as in the centering mode.
1540
WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PFIT_CONTROL, 0xA2000000);
1544
WRITE_MMIO_REG_TNC(ports_tnc[i], PIPE(display)->pipe_reg, pipe_conf);
1545
WRITE_MMIO_REG_TNC(ports_tnc[i], PIPE(display)->pipe_reg, pipe_conf);
1546
/* For LVDS port, don't touch dev3 registers stop after 1st iteration */
1547
if (pt == IGD_PORT_LVDS) {
1553
/* Gen4 can check when the pipe is enabled. */
1554
wait_pipe(PIPE(display)->pipe_reg, 0x40000000);
1557
* Set the VGA address range to 0xa0000 so that a normal (not VGA)
1558
* mode can be accessed through 0xa0000 in a 16bit world.
1560
WRITE_AR(MMIO(display), 0x10, 0xb);
1561
WRITE_VGA(MMIO(display), GR_PORT, 0x06, 0x5);
1562
WRITE_VGA(MMIO(display), GR_PORT, 0x10, 0x1);
1564
if(pTimings->extn_ptr) {
1565
/* This means either internal scaling (LVDS) or centered VGA */
1566
pTimings = pTimings->extn_ptr;
1567
if(pTimings->extn_ptr) {
1568
/* This is both the scaled and centered VGA */
1569
pTimings = pTimings->extn_ptr;
1571
if (pTimings->mode_info_flags & IGD_MODE_VESA) {
1572
if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
1573
program_pipe_vga_tnc(display);
1577
* FIXME: This is not appropriate. This assumes that
1578
* CONFIG_MICRO means "This is vBIOS" and programs
1579
* the palette. vBIOS IAL should probably just set the
1583
MMIO_TNC(PORT(display, display->port_number)->port_type));
1589
if (pt == IGD_PORT_SDVO) {
1590
/* Enable Chicken Bit */
1591
/* Setting BIT6 enable Pipe B Palette Write
1592
* to prevent hang during palette write */
1593
WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, 0x70400, 0x4088 | BIT6);
1606
void reset_plane_pipe_ports_tnc(igd_context_t *context)
1609
igd_display_pipe_t *pipe;
1610
igd_display_port_t *port,*tv_port=NULL;
1613
unsigned char *mmio;
1614
inter_module_dispatch_t *md;
1619
* Disable all plane, pipe and port registers because the
1620
* bios may have been using a different set. Only unset the
1623
mmio = EMGD_MMIO(context->device_context.virt_mmadr);
1624
md = &context->mod_dispatch;
1626
/* Turn off LVDS and SDVO ports */
1628
while((port = md->dsp_get_next_port(context, port, 0)) != NULL) {
1629
/* if the port is TV, then don't set the power to S3 as this causes
1630
* blank screen on analog port after killx or cosole mode,
1631
* probably because the external clock needs to be on till the pipes and
1634
if (port->pd_driver) {
1635
if(port->pd_type == PD_DISPLAY_TVOUT) {
1638
port->pd_driver->set_power(port->pd_context, IGD_POWERSTATE_D3);
1642
/* Disable WRITE protection on PIPE B for parts with Int-LVDS*/
1643
/* This should never happen as the panel power was set to D3 above */
1644
if (port->port_reg == LVDSCNTR) {
1645
if(EMGD_READ32(EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL) & 0x1) {
1646
EMGD_WRITE32(0xABCD0000, EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL);
1650
if((EMGD_READ32(EMGD_MMIO(mmio)+LVDS_PNL_PWR_STS)&BIT(31))==0) {
1656
if (port->pd_driver) {
1657
temp = READ_MMIO_REG_TNC(port->port_type, port->port_reg);
1658
WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, (temp & ~BIT31));
1663
* Gen4 appears to require that plane B be shut off prior to
1664
* shutting off plane A. The normal get_next_plane returns them
1665
* in order. We need to read the list backwards.
1668
while ((plane = md->dsp_get_next_plane(context, plane, 1)) != NULL) {
1669
/* This section only deals with display planes.
1670
* Leave cursor, VGA, overlay, sprite planes alone since they will
1671
* need a different disable bit/sequence.
1673
temp = EMGD_READ32(EMGD_MMIO(mmio) + plane->plane_reg);
1674
if ((plane->plane_features & IGD_PLANE_DISPLAY)) {
1675
i = 0x71008; /* PIPE B */
1677
if(plane->plane_reg == DSPACNTR) {
1678
temp = temp & device_data->plane_a_preserve;
1679
i = 0x70008; /* use i as pipe_reg */
1681
EMGD_WRITE32((temp & ~BIT31), EMGD_MMIO(mmio) + plane->plane_reg);
1683
/* The B-Spec is ambiguous on which register is the trigger.
1684
* Testing has shown the the surface start address is the
1685
* correct trigger to disable the plane.
1687
EMGD_WRITE32(0, EMGD_MMIO(mmio)+plane->plane_reg+DSP_START_OFFSET);
1689
/* Wait for VBLANK to ensure that the plane is really off */
1690
wait_for_vblank_tnc(i);
1692
EMGD_DEBUG("Plane disabled 0x%lx", plane->plane_reg);
1694
} else if ((plane->plane_features & IGD_PLANE_CURSOR)) {
1695
EMGD_WRITE32((temp & 0xffffffe8),
1696
EMGD_MMIO(mmio) + plane->plane_reg);
1697
EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4);
1702
/* Turn off pipes */
1704
while ((pipe = md->dsp_get_next_pipe(context, pipe, 0)) != NULL) {
1707
/* Is this really required? Just waited for vblank above 2 times */
1708
wait_for_vblank_tnc(pipe->pipe_reg);
1710
for (i = 0; i < 2; i++) {
1711
temp = READ_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg);
1714
/* Do not turn off Pipe B when shutting down */
1715
if((context->device_context.power_state
1716
== IGD_POWERSTATE_UNDEFINED) &&
1717
(pipe->pipe_reg == PIPEB_CONF)){
1720
WRITE_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg,
1721
(temp & device_data->pipe_preserve));
1723
/* Gen4 can check when the pipe is disabled. */
1724
wait_pipe(pipe->pipe_reg, 0);
1726
/* Disable VGA display */
1727
disable_vga_tnc(EMGD_MMIO(mmio));
1731
/* If current pipe is for sDVO, then iterate for PIPE B in
1732
* both 0:2:0 LNC and 0:3:0 Atom E6xx devices */
1733
if (pipe->pipe_reg == 0x70008L) {
1739
* SDVO: Atom E6xx 0x6018 */
1740
temp = READ_MMIO_REG_TNC(ports_tnc[j], pipe->clock_reg->dpll_control);
1743
WRITE_MMIO_REG_TNC(ports_tnc[j], pipe->clock_reg->dpll_control,
1748
/* pipes and DPLLs are off, now set the power for TV */
1749
if(tv_port && tv_port->pd_driver) {
1750
tv_port->pd_driver->set_power(tv_port->pd_context, IGD_POWERSTATE_D3);
1754
} /* end reset_plane_pipe_ports */
1757
* Status is currently not used
1760
* @param port_number
1763
* @return 0 on success
1764
* @return 1 on failure
1766
int post_program_port_tnc(igd_display_context_t *display,
1767
unsigned short port_number,
1768
unsigned long status)
1771
igd_display_port_t *port;
1772
igd_timing_info_t *timings;
1773
unsigned long portreg; /* temp; */
1774
/*unsigned long pt = PORT_TYPE(display); */
1778
port = PORT(display, port_number);
1779
timings = PIPE(display)->timing;
1782
* The programming found in the common code for all chipsets
1783
* has the device programming sequence as follows:
1788
* On Gen4, if the port is enabled before the pipe, there is a 10%
1789
* chance that the port will not turn on properly.
1790
* Due to compatability requires with other chipsets, this workaround
1793
portreg = READ_MMIO_REG_TNC(port->port_type, port->port_reg);
1794
WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg & ~BIT31);
1795
WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg);
1798
/* call post_set_mode() if exists */
1799
if (port->pd_driver->post_set_mode) {
1800
ret = port->pd_driver->post_set_mode(port->pd_context, timings,
1801
1<<PIPE(display)->pipe_num);
1803
EMGD_ERROR_EXIT("PD post_set_mode returned: 0x%x", ret);
1814
* @param port_number
1817
* @return 0 on success
1818
* @return -IGD_ERROR_INVAL on failure
1820
int program_port_sdvo_tnc(igd_display_context_t *display,
1821
unsigned short port_number,
1822
unsigned long status)
1824
unsigned long port_control;
1825
unsigned long pd_powerstate = PD_POWER_MODE_D3;
1826
unsigned long preserve = 0;
1827
unsigned long upscale = 0;
1828
igd_timing_info_t local_timing;
1829
igd_timing_info_t *timing;
1835
EMGD_DEBUG("Program Port: (%s)", status?"ENABLE":"DISABLE");
1836
EMGD_DEBUG("pd_flags: 0x%lx", PORT(display, port_number)->pd_flags);
1838
timing = PIPE(display)->timing;
1840
port_control = preserve & READ_MMIO_REG_TNC(IGD_PORT_SDVO,
1841
PORT(display, port_number)->port_reg);
1843
if (status == TRUE) {
1844
if (!(PORT(display, port_number)->pt_info->flags &
1845
IGD_DISPLAY_ENABLE)) {
1850
/* Enable VGA syncs for native vga modes */
1851
if (PORT(display, port_number)->vga_sync == 1) {
1852
EMGD_DEBUG("VGA sync true, is width x height 720 x 400?");
1853
if((timing->width == 720) && (timing->height == 400)) {
1854
EMGD_DEBUG("Modify port control and multi_port_control");
1855
port_control |= (1L<<15);
1859
/* Fact that both IGD_ powerstates and PD_ powermodes have
1860
* same definitions */
1861
pd_powerstate = GET_DISPLAY_POWER_STATE(display, port_number);
1863
if (pd_powerstate == IGD_POWERSTATE_D0) {
1864
EMGD_DEBUG("Power State: D0");
1866
pi_pd_find_attr_and_value(PORT(display, port_number),
1867
PD_ATTR_ID_PANEL_FIT,
1868
0, /*no PD_FLAG for UPSCALING */
1869
NULL, /* dont need the attr ptr*/
1872
/* Reach the end timing if upscaling is enabled */
1873
if (timing->extn_ptr && upscale) {
1874
timing = (pd_timing_t *)timing->extn_ptr;
1877
local_timing = *timing;
1879
/* For timings smaller than width 360 and height 200,
1880
* double the size. This is because the active area of the mode
1881
* is double the size of the resolution for these modes
1882
* - Very tricky huh */
1883
if (local_timing.width <= 360) {
1884
local_timing.width <<= 1;
1886
if (local_timing.height <= 200) {
1887
local_timing.height <<= 1;
1896
port_control |= BIT31|BIT30|BIT29|BIT7;
1898
/* Program cDVO registers:
1899
* Keep default values for
1900
* 7000h - cDVO control register
1901
* 7004h - cDVO slew rate register
1902
* 7008h - cDVO strength register
1903
* 700Ch - cDVO RCOMP update register
1904
* 6102Ch - cDVO stall register = 0xA.
1905
* Note: Though EAS says 6102Ch default value is 6, it is a typo
1906
* in the spec, based on Si DE hw default value is 10 (0xA),
1907
* so no need to program explicitly. This saves few bytes for
1911
/* Enable Current Source */
1912
temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG);
1914
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp);
1918
if (pd_powerstate == PD_POWER_MODE_D0) {
1919
ret = PORT(display, port_number)->pd_driver->set_mode(
1920
PORT(display, port_number)->pd_context, &local_timing, 0);
1922
ret = PORT(display, port_number)->pd_driver->set_power(
1923
PORT(display, port_number)->pd_context, pd_powerstate);
1927
EMGD_ERROR_EXIT("PD set_%s returned: 0x%x",
1928
(pd_powerstate == PD_POWER_MODE_D0)?"mode":"power", ret);
1929
return -IGD_ERROR_INVAL;
1932
EMGD_DEBUG("Port_control: 0x%lx", port_control);
1934
WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
1935
PORT(display, port_number)->port_reg, port_control);
1944
* @param port_number
1947
* @return 0 on success
1948
* @return -IGD_ERROR_INVAL on failure
1950
int program_port_lvds_tnc(igd_display_context_t *display,
1951
unsigned short port_number,
1952
unsigned long status)
1955
unsigned long powerstate = PD_POWER_MODE_D3;
1956
pd_timing_t *timing;
1960
EMGD_DEBUG("Program LVDS: (%s)", status?"ENABLE":"DISABLE");
1962
if (status == TRUE) {
1963
if(!(PORT(display, port_number)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
1968
powerstate = GET_DISPLAY_POWER_STATE(display,port_number);
1969
if (powerstate == IGD_POWERSTATE_D0) {
1970
EMGD_DEBUG("Power State: D0");
1971
timing = (pd_timing_t *)PIPE(display)->timing;
1972
/* Reach end timing to get user resolution and pass it to pd */
1973
if(timing->extn_ptr) {
1974
timing = (pd_timing_t *)timing->extn_ptr;
1976
/* set mode will take care of port control */
1977
ret = PORT(display, port_number)->pd_driver->set_mode(
1978
PORT(display, port_number)->pd_context,
1980
1<<PIPE(display)->pipe_num);
1984
/* either status == FALSE, or status == TRUE, but powerstate is D1/D2/D3 */
1985
if (powerstate != IGD_POWERSTATE_D0) {
1986
ret = PORT(display, port_number)->pd_driver->set_power(
1987
PORT(display, port_number)->pd_context,
1992
EMGD_ERROR_EXIT("PD set_%s returned: 0x%x",
1993
(powerstate == IGD_POWERSTATE_D0)?"mode":"power", ret);
1994
return -IGD_ERROR_INVAL;
2005
* @param port_number
2008
* @return program_port_lvds_gen4()
2009
* @return program_port_sdvo_gen4()
2010
* @return -IGD_ERROR_INVAL on failure
2012
int program_port_tnc(igd_display_context_t *display,
2013
unsigned short port_number,
2014
unsigned long status)
2018
if (PORT(display, port_number)->port_type == IGD_PORT_LVDS) {
2020
return program_port_lvds_tnc(display, port_number, status);
2023
return program_port_sdvo_tnc(display, port_number, status);
2033
unsigned long get_gpio_sets_tnc(unsigned long **gpio)
2035
/* To small to trace */
2044
* @return void - To small to trace
2046
void filter_modes_tnc(igd_context_t *context, igd_display_port_t *port,
2047
pd_timing_t *in_list)
2049
while (in_list->width != IGD_TIMING_TABLE_END) {
2051
* supports from 19.75MHz to 79.MHz
2053
* supports from 25 MHz to 160 MHz and progressive only.
2055
if (port->port_type == IGD_PORT_SDVO) {
2056
if (in_list->mode_info_flags & IGD_SCAN_INTERLACE ||
2057
in_list->dclk < 25000 || in_list->dclk > 160000) {
2058
in_list->mode_info_flags &= ~IGD_MODE_SUPPORTED;
2061
/* No clock check is required for LVDS port as LVDS port driver
2062
* already taken care of this.
2063
if (port->port_type == IGD_PORT_LVDS) {
2064
if (in_list->dclk < 19750 || in_list->dclk > 79500) {
2065
in_list->mode_info_flags &= ~IGD_MODE_SUPPORTED;
2069
if (in_list->width == IGD_TIMING_TABLE_END && in_list->extn_ptr) {
2070
in_list = in_list->extn_ptr;
2075
#ifndef CONFIG_MICRO
2076
int get_timing_tnc(igd_display_context_t *display, pd_timing_t *in_list)
2079
igd_timing_info_t *pTimings_ori;
2080
pd_timing_t *timing = NULL;
2084
pTimings_ori = PIPE(display)->timing;
2086
if(display->port_number != 2){
2087
EMGD_DEBUG("Port does not need tuning");
2092
while(timing->width != PD_TIMING_LIST_END) {
2094
if((timing->width == pTimings_ori->width) &&
2095
(timing->height == pTimings_ori->height) &&
2096
(timing->refresh == pTimings_ori->refresh)){
2097
EMGD_DEBUG("Timing found");
2098
timing->reserved_dd = pTimings_ori->reserved_dd;
2099
timing->mode_info_flags = pTimings_ori->mode_info_flags;
2101
/* also return the hblank_end so that ioctl can calculate
2102
* the xblank_length.
2104
timing->hblank_end = pTimings_ori->hblank_end;
2105
timing->vblank_end = pTimings_ori->vblank_end;
2109
/* Go through the table list */
2111
if ((timing->width == PD_TIMING_LIST_END) && timing->extn_ptr) {
2112
timing = timing->extn_ptr;
2120
int check_port_supported(void *port_tmp)
2122
//igd_display_port_t *port = (igd_display_port_t *)port_tmp;
2123
/* Determine which port driver is supported by Atom E6xx */
2124
#if 0 //Pendng confirmation from LNC architect
2125
if(pd_driver->type & PD_DISPLAY_TVOUT){
2133
/* Function checks if the incoming user DTD is one of the timings
2134
* in the crt_timing_table that has border. Meaning that the
2135
* h_blank_end is not the same as htotal.
2136
* We only see this issue when reading a user DTD generated for
2137
* harmonic which is derived from crt_timing_table. pi module
2138
* only handles user DTD which does not have borders.
2140
int get_refresh_in_border(pd_timing_t *in_list)
2142
/* return 1 if refresh is obtained */
2144
if(in_list->width == 640 &&
2145
in_list->height == 480 &&
2146
in_list->dclk == 25175 &&
2147
in_list->hsync_start == 655 &&
2148
in_list->hsync_end == 751 &&
2149
in_list->vsync_start == 489 &&
2150
in_list->vsync_end == 491){
2151
in_list->refresh = 60;
2152
in_list->htotal = 799;
2153
in_list->vtotal = 524;
2154
in_list->hblank_start = 646;
2155
in_list->vblank_start = 486;
2159
if(in_list->width == 640 &&
2160
in_list->height == 480 &&
2161
in_list->dclk == 31500 &&
2162
in_list->hsync_start == 663 &&
2163
in_list->hsync_end == 703 &&
2164
in_list->vsync_start == 488 &&
2165
in_list->vsync_end == 491){
2167
in_list->refresh = 72;
2168
in_list->htotal = 831;
2169
in_list->vtotal = 519;
2170
in_list->hblank_start = 646;
2171
in_list->vblank_start = 486;
2180
* Function to check if dc is switching from
2181
* SDVO single to clone/extended mode
2182
* Tunnel Creek B0 needs tuning when there are 2 planes,
2183
* if true, it will force alter to run tuning
2185
bool dsp_is_force_alter_required_tnc(igd_display_context_t *display,
2186
unsigned long current_dc, unsigned long dc_to_set){
2188
if ((IGD_DC_SINGLE(current_dc) &&
2189
(IGD_DC_PRIMARY(current_dc) == IGD_PORT_TYPE_SDVOB )) &&
2190
(IGD_DC_CLONE(dc_to_set) || IGD_DC_EXTENDED(dc_to_set)) &&
2191
(display->context->device_context.rid == TNC_B0_RID)){
2199
mode_dispatch_t mode_dispatch_tnc = {
2200
igd_set_palette_entry_tnc,
2201
igd_get_palette_entry_tnc,
2202
igd_wait_vblank_tnc,
2206
post_program_port_tnc,
2208
reset_plane_pipe_ports_tnc,
2211
OPT_MICRO_VALUE(check_display_tnc, NULL),
2212
OPT_MICRO_VALUE(get_timing_tnc, NULL),
2213
OPT_MICRO_VALUE(check_port_supported, NULL),
2214
OPT_MICRO_VALUE(get_refresh_in_border, NULL),
2215
OPT_MICRO_VALUE(dsp_is_force_alter_required_tnc, NULL),
2216
OPT_MICRO_VALUE(&mode_full_dispatch_tnc, NULL)
2219
/* VBIOS does not use the virtual mapped address
2220
* This function will return 0 for VBIOS anyway */
2221
#ifndef CONFIG_MICRO
2222
unsigned char *get_mmio_tnc(unsigned long port_type)
2224
unsigned char *virt_mmio;
2225
if (port_type == IGD_PORT_LVDS) {
2226
virt_mmio = mode_context->context->device_context.virt_mmadr;
2227
} else if (port_type == IGD_PORT_SDVO) {
2228
virt_mmio = mode_context->context->device_context.virt_mmadr_sdvo;
2230
/* i2c_bitbash will use the else condition by passing in port_type
2232
virt_mmio = mode_context->context->device_context.virt_gpio_bar;
2238
/* Function to read Atom E6xx 0:2:0, 0:3:0 and 0:31:0 mmio registers */
2239
unsigned long read_mmio_reg_tnc(unsigned long port_type, unsigned long reg)
2241
unsigned long value;
2242
#ifndef CONFIG_MICRO
2243
unsigned char *mmio;
2246
/* to avoid updating or having another set of read/write macros for
2247
* vbios, overwrite io_base to properly read from 0:2:0/0:3:0/0:31:0
2248
* io_base and set it back after reading */
2249
if (port_type == IGD_PORT_LVDS) {
2250
io_base = io_base_lvds;
2251
} else if (port_type == IGD_PORT_SDVO) {
2252
io_base = io_base_sdvo;
2253
} else if (port_type == IGD_PORT_LPC) {
2254
io_base = io_base_lpc;
2256
OPT_MICRO_CALL_RET(mmio, get_mmio_tnc(port_type));
2257
if (port_type == IGD_PORT_LPC) {
2258
value = EMGD_READ_PORT32(io_base_lpc + reg);
2260
value = EMGD_READ32(EMGD_MMIO(mmio) + reg);
2263
io_base = io_base_lvds;
2267
/* Function to write Atom E6xx 0:2:0 and 0:3:0 mmio registers */
2268
void write_mmio_reg_tnc(unsigned long port_type, unsigned long reg,
2269
unsigned long value)
2271
#ifndef CONFIG_MICRO
2272
unsigned char *mmio;
2275
/* to avoid updating or having another set of read/write macros for
2276
* vbios, overwrite io_base to properly read from 0:2:0/0:3:0 io_base
2277
* and set it back after writing */
2278
if (port_type == IGD_PORT_LVDS) {
2279
io_base = io_base_lvds;
2280
} else if (port_type == IGD_PORT_SDVO) {
2281
io_base = io_base_sdvo;
2282
} else if (port_type == IGD_PORT_LPC) {
2283
io_base = io_base_lpc;
2286
OPT_MICRO_CALL_RET(mmio, get_mmio_tnc(port_type));
2287
if (port_type == IGD_PORT_LPC) {
2288
EMGD_WRITE_PORT32(io_base_lpc + reg, value);
2290
EMGD_WRITE32(value, EMGD_MMIO(mmio) + reg);
2292
io_base = io_base_lvds;