blob: 84f6e8b8c0e251542cfdd63b8b34a26aa50b6797 [file] [log] [blame]
#include "ddk750_reg.h"
#include "ddk750_help.h"
#include "ddk750_display.h"
#include "ddk750_power.h"
#include "ddk750_dvi.h"
#define primaryWaitVerticalSync(delay) waitNextVerticalSync(0, delay)
static void setDisplayControl(int ctrl, int disp_state)
{
/* state != 0 means turn on both timing & plane en_bit */
unsigned long ulDisplayCtrlReg, ulReservedBits;
int cnt;
cnt = 0;
/* Set the primary display control */
if (!ctrl) {
ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL);
/* Turn on/off the Panel display control */
if (disp_state) {
/* Timing should be enabled first before enabling the plane
* because changing at the same time does not guarantee that
* the plane will also enabled or disabled.
*/
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, TIMING, ENABLE);
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, PLANE, ENABLE);
/* Added some masks to mask out the reserved bits.
* Sometimes, the reserved bits are set/reset randomly when
* writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
* reserved bits are needed to be masked out.
*/
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);
/* Somehow the register value on the plane is not set
* until a few delay. Need to write
* and read it a couple times
*/
do {
cnt++;
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
} while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
(ulDisplayCtrlReg & ~ulReservedBits));
printk("Set Panel Plane enbit:after tried %d times\n", cnt);
} else {
/* When turning off, there is no rule on the programming
* sequence since whenever the clock is off, then it does not
* matter whether the plane is enabled or disabled.
* Note: Modifying the plane bit will take effect on the
* next vertical sync. Need to find out if it is necessary to
* wait for 1 vsync before modifying the timing enable bit.
* */
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, PLANE, DISABLE);
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, TIMING, DISABLE);
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
}
} else {
/* Set the secondary display control */
ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL);
if (disp_state) {
/* Timing should be enabled first before enabling the plane because changing at the
same time does not guarantee that the plane will also enabled or disabled.
*/
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
CRT_DISPLAY_CTRL, TIMING, ENABLE);
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
CRT_DISPLAY_CTRL, PLANE, ENABLE);
/* Added some masks to mask out the reserved bits.
* Sometimes, the reserved bits are set/reset randomly when
* writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
* reserved bits are needed to be masked out.
*/
ulReservedBits = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE);
do {
cnt++;
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
} while ((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
(ulDisplayCtrlReg & ~ulReservedBits));
printk("Set Crt Plane enbit:after tried %d times\n", cnt);
} else {
/* When turning off, there is no rule on the programming
* sequence since whenever the clock is off, then it does not
* matter whether the plane is enabled or disabled.
* Note: Modifying the plane bit will take effect on the next
* vertical sync. Need to find out if it is necessary to
* wait for 1 vsync before modifying the timing enable bit.
*/
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
CRT_DISPLAY_CTRL, PLANE, DISABLE);
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
CRT_DISPLAY_CTRL, TIMING, DISABLE);
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
}
}
}
static void waitNextVerticalSync(int ctrl, int delay)
{
unsigned int status;
if (!ctrl) {
/* primary controller */
/* Do not wait when the Primary PLL is off or display control is already off.
This will prevent the software to wait forever. */
if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) ==
PANEL_PLL_CTRL_POWER_OFF) ||
(FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) ==
PANEL_DISPLAY_CTRL_TIMING_DISABLE)) {
return;
}
while (delay-- > 0) {
/* Wait for end of vsync. */
do {
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
PANEL_VSYNC);
} while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
/* Wait for start of vsync. */
do {
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
PANEL_VSYNC);
} while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
}
} else {
/* Do not wait when the Primary PLL is off or display control is already off.
This will prevent the software to wait forever. */
if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) ==
CRT_PLL_CTRL_POWER_OFF) ||
(FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) ==
CRT_DISPLAY_CTRL_TIMING_DISABLE)) {
return;
}
while (delay-- > 0) {
/* Wait for end of vsync. */
do {
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
CRT_VSYNC);
} while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
/* Wait for start of vsync. */
do {
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
CRT_VSYNC);
} while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
}
}
}
static void swPanelPowerSequence(int disp, int delay)
{
unsigned int reg;
/* disp should be 1 to open sequence */
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, FPEN, disp);
POKE32(PANEL_DISPLAY_CTRL, reg);
primaryWaitVerticalSync(delay);
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, DATA, disp);
POKE32(PANEL_DISPLAY_CTRL, reg);
primaryWaitVerticalSync(delay);
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, VBIASEN, disp);
POKE32(PANEL_DISPLAY_CTRL, reg);
primaryWaitVerticalSync(delay);
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, FPEN, disp);
POKE32(PANEL_DISPLAY_CTRL, reg);
primaryWaitVerticalSync(delay);
}
void ddk750_setLogicalDispOut(disp_output_t output)
{
unsigned int reg;
if (output & PNL_2_USAGE) {
/* set panel path controller select */
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, SELECT, (output & PNL_2_MASK)>>PNL_2_OFFSET);
POKE32(PANEL_DISPLAY_CTRL, reg);
}
if (output & CRT_2_USAGE) {
/* set crt path controller select */
reg = PEEK32(CRT_DISPLAY_CTRL);
reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, SELECT, (output & CRT_2_MASK)>>CRT_2_OFFSET);
/*se blank off */
reg = FIELD_SET(reg, CRT_DISPLAY_CTRL, BLANK, OFF);
POKE32(CRT_DISPLAY_CTRL, reg);
}
if (output & PRI_TP_USAGE) {
/* set primary timing and plane en_bit */
setDisplayControl(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
}
if (output & SEC_TP_USAGE) {
/* set secondary timing and plane en_bit*/
setDisplayControl(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
}
if (output & PNL_SEQ_USAGE) {
/* set panel sequence */
swPanelPowerSequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET, 4);
}
if (output & DAC_USAGE)
setDAC((output & DAC_MASK) >> DAC_OFFSET);
if (output & DPMS_USAGE)
ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET);
}