2015-03-03 10:51:06 +00:00
|
|
|
#include "ddk750_reg.h"
|
2016-10-11 22:43:07 +00:00
|
|
|
#include "ddk750_chip.h"
|
2015-03-03 10:51:06 +00:00
|
|
|
#include "ddk750_display.h"
|
|
|
|
#include "ddk750_power.h"
|
|
|
|
#include "ddk750_dvi.h"
|
|
|
|
|
2015-10-09 20:47:44 +00:00
|
|
|
static void setDisplayControl(int ctrl, int disp_state)
|
2015-03-03 10:51:06 +00:00
|
|
|
{
|
|
|
|
/* state != 0 means turn on both timing & plane en_bit */
|
2016-02-10 16:34:06 +00:00
|
|
|
unsigned long reg, val, reserved;
|
|
|
|
int cnt = 0;
|
2015-03-03 10:51:06 +00:00
|
|
|
|
2015-07-15 04:14:45 +00:00
|
|
|
if (!ctrl) {
|
2016-02-10 16:34:06 +00:00
|
|
|
reg = PANEL_DISPLAY_CTRL;
|
|
|
|
reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK;
|
2015-07-15 04:14:45 +00:00
|
|
|
} else {
|
2016-02-10 16:34:06 +00:00
|
|
|
reg = CRT_DISPLAY_CTRL;
|
|
|
|
reserved = CRT_DISPLAY_CTRL_RESERVED_MASK;
|
|
|
|
}
|
2015-03-03 10:51:06 +00:00
|
|
|
|
2016-02-10 16:34:06 +00:00
|
|
|
val = PEEK32(reg);
|
|
|
|
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.
|
|
|
|
*/
|
2016-02-10 16:34:08 +00:00
|
|
|
val |= DISPLAY_CTRL_TIMING;
|
2016-02-10 16:34:06 +00:00
|
|
|
POKE32(reg, val);
|
|
|
|
|
2016-02-10 16:34:08 +00:00
|
|
|
val |= DISPLAY_CTRL_PLANE;
|
2016-02-10 16:34:06 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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(reg, val);
|
|
|
|
} while ((PEEK32(reg) & ~reserved) != (val & ~reserved));
|
|
|
|
pr_debug("Set 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.
|
|
|
|
*/
|
2016-02-10 16:34:08 +00:00
|
|
|
val &= ~DISPLAY_CTRL_PLANE;
|
2016-02-10 16:34:06 +00:00
|
|
|
POKE32(reg, val);
|
|
|
|
|
2016-02-10 16:34:08 +00:00
|
|
|
val &= ~DISPLAY_CTRL_TIMING;
|
2016-02-10 16:34:06 +00:00
|
|
|
POKE32(reg, val);
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-26 02:03:43 +00:00
|
|
|
static void primary_wait_vertical_sync(int delay)
|
2015-03-03 10:51:06 +00:00
|
|
|
{
|
|
|
|
unsigned int status;
|
2015-07-15 04:14:48 +00:00
|
|
|
|
2016-10-26 02:03:43 +00:00
|
|
|
/*
|
|
|
|
* Do not wait when the Primary PLL is off or display control is
|
|
|
|
* already off. This will prevent the software to wait forever.
|
|
|
|
*/
|
|
|
|
if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) ||
|
|
|
|
!(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING))
|
|
|
|
return;
|
2015-03-03 10:51:06 +00:00
|
|
|
|
2016-10-26 02:03:43 +00:00
|
|
|
while (delay-- > 0) {
|
|
|
|
/* Wait for end of vsync. */
|
|
|
|
do {
|
|
|
|
status = PEEK32(SYSTEM_CTRL);
|
|
|
|
} while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
|
2015-03-03 10:51:06 +00:00
|
|
|
|
2016-10-26 02:03:43 +00:00
|
|
|
/* Wait for start of vsync. */
|
|
|
|
do {
|
|
|
|
status = PEEK32(SYSTEM_CTRL);
|
|
|
|
} while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-02 10:14:30 +00:00
|
|
|
static void swPanelPowerSequence(int disp, int delay)
|
2015-03-03 10:51:06 +00:00
|
|
|
{
|
|
|
|
unsigned int reg;
|
|
|
|
|
|
|
|
/* disp should be 1 to open sequence */
|
|
|
|
reg = PEEK32(PANEL_DISPLAY_CTRL);
|
2016-02-10 16:34:08 +00:00
|
|
|
reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
|
2015-06-02 10:14:30 +00:00
|
|
|
POKE32(PANEL_DISPLAY_CTRL, reg);
|
2016-10-26 02:03:43 +00:00
|
|
|
primary_wait_vertical_sync(delay);
|
2015-03-03 10:51:06 +00:00
|
|
|
|
|
|
|
reg = PEEK32(PANEL_DISPLAY_CTRL);
|
2016-02-10 16:34:08 +00:00
|
|
|
reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0);
|
2015-06-02 10:14:30 +00:00
|
|
|
POKE32(PANEL_DISPLAY_CTRL, reg);
|
2016-10-26 02:03:43 +00:00
|
|
|
primary_wait_vertical_sync(delay);
|
2015-03-03 10:51:06 +00:00
|
|
|
|
|
|
|
reg = PEEK32(PANEL_DISPLAY_CTRL);
|
2016-02-10 16:34:08 +00:00
|
|
|
reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0);
|
2015-06-02 10:14:30 +00:00
|
|
|
POKE32(PANEL_DISPLAY_CTRL, reg);
|
2016-10-26 02:03:43 +00:00
|
|
|
primary_wait_vertical_sync(delay);
|
2015-03-03 10:51:06 +00:00
|
|
|
|
|
|
|
reg = PEEK32(PANEL_DISPLAY_CTRL);
|
2016-02-10 16:34:08 +00:00
|
|
|
reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
|
2015-06-02 10:14:30 +00:00
|
|
|
POKE32(PANEL_DISPLAY_CTRL, reg);
|
2016-10-26 02:03:43 +00:00
|
|
|
primary_wait_vertical_sync(delay);
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ddk750_setLogicalDispOut(disp_output_t output)
|
|
|
|
{
|
|
|
|
unsigned int reg;
|
2015-07-15 04:14:48 +00:00
|
|
|
|
2015-07-15 04:14:35 +00:00
|
|
|
if (output & PNL_2_USAGE) {
|
2015-03-03 10:51:06 +00:00
|
|
|
/* set panel path controller select */
|
|
|
|
reg = PEEK32(PANEL_DISPLAY_CTRL);
|
2016-02-10 16:34:10 +00:00
|
|
|
reg &= ~PANEL_DISPLAY_CTRL_SELECT_MASK;
|
|
|
|
reg |= (((output & PNL_2_MASK) >> PNL_2_OFFSET) <<
|
|
|
|
PANEL_DISPLAY_CTRL_SELECT_SHIFT);
|
2015-06-02 10:14:30 +00:00
|
|
|
POKE32(PANEL_DISPLAY_CTRL, reg);
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:14:35 +00:00
|
|
|
if (output & CRT_2_USAGE) {
|
2015-03-03 10:51:06 +00:00
|
|
|
/* set crt path controller select */
|
|
|
|
reg = PEEK32(CRT_DISPLAY_CTRL);
|
2016-02-10 16:34:19 +00:00
|
|
|
reg &= ~CRT_DISPLAY_CTRL_SELECT_MASK;
|
|
|
|
reg |= (((output & CRT_2_MASK) >> CRT_2_OFFSET) <<
|
|
|
|
CRT_DISPLAY_CTRL_SELECT_SHIFT);
|
2015-03-03 10:51:06 +00:00
|
|
|
/*se blank off */
|
2016-02-10 16:34:18 +00:00
|
|
|
reg &= ~CRT_DISPLAY_CTRL_BLANK;
|
2015-06-02 10:14:30 +00:00
|
|
|
POKE32(CRT_DISPLAY_CTRL, reg);
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:14:35 +00:00
|
|
|
if (output & PRI_TP_USAGE) {
|
2015-03-03 10:51:06 +00:00
|
|
|
/* set primary timing and plane en_bit */
|
2015-10-09 20:51:30 +00:00
|
|
|
setDisplayControl(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:14:35 +00:00
|
|
|
if (output & SEC_TP_USAGE) {
|
2015-03-03 10:51:06 +00:00
|
|
|
/* set secondary timing and plane en_bit*/
|
2015-10-09 20:51:30 +00:00
|
|
|
setDisplayControl(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:14:35 +00:00
|
|
|
if (output & PNL_SEQ_USAGE) {
|
2015-03-03 10:51:06 +00:00
|
|
|
/* set panel sequence */
|
2015-10-09 20:51:30 +00:00
|
|
|
swPanelPowerSequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET, 4);
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 04:14:33 +00:00
|
|
|
if (output & DAC_USAGE)
|
2015-10-09 20:50:36 +00:00
|
|
|
setDAC((output & DAC_MASK) >> DAC_OFFSET);
|
2015-03-03 10:51:06 +00:00
|
|
|
|
2015-07-15 04:14:33 +00:00
|
|
|
if (output & DPMS_USAGE)
|
2016-10-28 00:23:35 +00:00
|
|
|
ddk750_set_dpms((output & DPMS_MASK) >> DPMS_OFFSET);
|
2015-03-03 10:51:06 +00:00
|
|
|
}
|