250 lines
7.9 KiB
C
250 lines
7.9 KiB
C
#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);
|
|
}
|