| |
| #include "ddk750_help.h" |
| #include "ddk750_reg.h" |
| #include "ddk750_mode.h" |
| #include "ddk750_chip.h" |
| |
| /* |
| SM750LE only: |
| This function takes care extra registers and bit fields required to set |
| up a mode in SM750LE |
| |
| Explanation about Display Control register: |
| HW only supports 7 predefined pixel clocks, and clock select is |
| in bit 29:27 of Display Control register. |
| */ |
| static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl) |
| { |
| unsigned long x, y; |
| |
| x = pModeParam->horizontal_display_end; |
| y = pModeParam->vertical_display_end; |
| |
| /* SM750LE has to set up the top-left and bottom-right |
| registers as well. |
| Note that normal SM750/SM718 only use those two register for |
| auto-centering mode. |
| */ |
| POKE32(CRT_AUTO_CENTERING_TL, |
| FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0) |
| | FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0)); |
| |
| POKE32(CRT_AUTO_CENTERING_BR, |
| FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1) |
| | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1)); |
| |
| /* Assume common fields in dispControl have been properly set before |
| calling this function. |
| This function only sets the extra fields in dispControl. |
| */ |
| |
| /* Clear bit 29:27 of display control register */ |
| dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK); |
| |
| /* Set bit 29:27 of display control register for the right clock */ |
| /* Note that SM750LE only need to supported 7 resoluitons. */ |
| if ( x == 800 && y == 600 ) |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41); |
| else if (x == 1024 && y == 768) |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65); |
| else if (x == 1152 && y == 864) |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80); |
| else if (x == 1280 && y == 768) |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80); |
| else if (x == 1280 && y == 720) |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74); |
| else if (x == 1280 && y == 960) |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108); |
| else if (x == 1280 && y == 1024) |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108); |
| else /* default to VGA clock */ |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25); |
| |
| /* Set bit 25:24 of display controller */ |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT); |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT); |
| |
| /* Set bit 14 of display controller */ |
| dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW); |
| |
| POKE32(CRT_DISPLAY_CTRL, dispControl); |
| |
| return dispControl; |
| } |
| |
| |
| |
| /* only timing related registers will be programed */ |
| static int programModeRegisters(mode_parameter_t * pModeParam,pll_value_t * pll) |
| { |
| int ret = 0; |
| int cnt = 0; |
| unsigned int ulTmpValue,ulReg; |
| if(pll->clockType == SECONDARY_PLL) |
| { |
| /* programe secondary pixel clock */ |
| POKE32(CRT_PLL_CTRL,formatPllReg(pll)); |
| POKE32(CRT_HORIZONTAL_TOTAL, |
| FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1) |
| | FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1)); |
| |
| POKE32(CRT_HORIZONTAL_SYNC, |
| FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width) |
| | FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1)); |
| |
| POKE32(CRT_VERTICAL_TOTAL, |
| FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1) |
| | FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1)); |
| |
| POKE32(CRT_VERTICAL_SYNC, |
| FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) |
| | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); |
| |
| |
| ulTmpValue = FIELD_VALUE(0,CRT_DISPLAY_CTRL,VSYNC_PHASE,pModeParam->vertical_sync_polarity)| |
| FIELD_VALUE(0,CRT_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)| |
| FIELD_SET(0,CRT_DISPLAY_CTRL,TIMING,ENABLE)| |
| FIELD_SET(0,CRT_DISPLAY_CTRL,PLANE,ENABLE); |
| |
| |
| if(getChipType() == SM750LE){ |
| displayControlAdjust_SM750LE(pModeParam,ulTmpValue); |
| }else{ |
| ulReg = PEEK32(CRT_DISPLAY_CTRL) |
| & FIELD_CLEAR(CRT_DISPLAY_CTRL,VSYNC_PHASE) |
| & FIELD_CLEAR(CRT_DISPLAY_CTRL,HSYNC_PHASE) |
| & FIELD_CLEAR(CRT_DISPLAY_CTRL,TIMING) |
| & FIELD_CLEAR(CRT_DISPLAY_CTRL,PLANE); |
| |
| POKE32(CRT_DISPLAY_CTRL,ulTmpValue|ulReg); |
| } |
| |
| } |
| else if(pll->clockType == PRIMARY_PLL) |
| { |
| unsigned int ulReservedBits; |
| POKE32(PANEL_PLL_CTRL,formatPllReg(pll)); |
| |
| POKE32(PANEL_HORIZONTAL_TOTAL, |
| FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1) |
| | FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1)); |
| |
| POKE32(PANEL_HORIZONTAL_SYNC, |
| FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width) |
| | FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1)); |
| |
| POKE32(PANEL_VERTICAL_TOTAL, |
| FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1) |
| | FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1)); |
| |
| POKE32(PANEL_VERTICAL_SYNC, |
| FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) |
| | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); |
| |
| ulTmpValue = FIELD_VALUE(0,PANEL_DISPLAY_CTRL,VSYNC_PHASE,pModeParam->vertical_sync_polarity)| |
| FIELD_VALUE(0,PANEL_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)| |
| FIELD_VALUE(0,PANEL_DISPLAY_CTRL,CLOCK_PHASE,pModeParam->clock_phase_polarity)| |
| FIELD_SET(0,PANEL_DISPLAY_CTRL,TIMING,ENABLE)| |
| FIELD_SET(0,PANEL_DISPLAY_CTRL,PLANE,ENABLE); |
| |
| ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | |
| FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | |
| FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)| |
| FIELD_SET(0,PANEL_DISPLAY_CTRL,VSYNC,ACTIVE_LOW); |
| |
| ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) |
| & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE) |
| & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE) |
| & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE) |
| & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING) |
| & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE); |
| |
| |
| /* May a hardware bug or just my test chip (not confirmed). |
| * PANEL_DISPLAY_CTRL register seems requiring few writes |
| * before a value can be succesfully written in. |
| * Added some masks to mask out the reserved bits. |
| * Note: This problem happens by design. The hardware will wait for the |
| * next vertical sync to turn on/off the plane. |
| */ |
| |
| POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg); |
| #if 1 |
| while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) |
| { |
| cnt++; |
| if(cnt > 1000) |
| break; |
| POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg); |
| } |
| #endif |
| } |
| else{ |
| ret = -1; |
| } |
| return ret; |
| } |
| |
| int ddk750_setModeTiming(mode_parameter_t * parm,clock_type_t clock) |
| { |
| pll_value_t pll; |
| unsigned int uiActualPixelClk; |
| pll.inputFreq = DEFAULT_INPUT_CLOCK; |
| pll.clockType = clock; |
| |
| uiActualPixelClk = calcPllValue(parm->pixel_clock,&pll); |
| if(getChipType() == SM750LE){ |
| /* set graphic mode via IO method */ |
| outb_p(0x88,0x3d4); |
| outb_p(0x06,0x3d5); |
| } |
| programModeRegisters(parm,&pll); |
| return 0; |
| } |
| |
| |