| |
| #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 successfully 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); |
| |
| while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) { |
| cnt++; |
| if (cnt > 1000) |
| break; |
| POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg); |
| } |
| } 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; |
| } |
| |
| |