cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ddk750_display.c (4222B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include "ddk750_reg.h"
      3#include "ddk750_chip.h"
      4#include "ddk750_display.h"
      5#include "ddk750_power.h"
      6#include "ddk750_dvi.h"
      7
      8static void set_display_control(int ctrl, int disp_state)
      9{
     10	/* state != 0 means turn on both timing & plane en_bit */
     11	unsigned long reg, val, reserved;
     12	int cnt = 0;
     13
     14	if (!ctrl) {
     15		reg = PANEL_DISPLAY_CTRL;
     16		reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK;
     17	} else {
     18		reg = CRT_DISPLAY_CTRL;
     19		reserved = CRT_DISPLAY_CTRL_RESERVED_MASK;
     20	}
     21
     22	val = peek32(reg);
     23	if (disp_state) {
     24		/*
     25		 * Timing should be enabled first before enabling the
     26		 * plane because changing at the same time does not
     27		 * guarantee that the plane will also enabled or
     28		 * disabled.
     29		 */
     30		val |= DISPLAY_CTRL_TIMING;
     31		poke32(reg, val);
     32
     33		val |= DISPLAY_CTRL_PLANE;
     34
     35		/*
     36		 * Somehow the register value on the plane is not set
     37		 * until a few delay. Need to write and read it a
     38		 * couple times
     39		 */
     40		do {
     41			cnt++;
     42			poke32(reg, val);
     43		} while ((peek32(reg) & ~reserved) != (val & ~reserved));
     44		pr_debug("Set Plane enbit:after tried %d times\n", cnt);
     45	} else {
     46		/*
     47		 * When turning off, there is no rule on the
     48		 * programming sequence since whenever the clock is
     49		 * off, then it does not matter whether the plane is
     50		 * enabled or disabled.  Note: Modifying the plane bit
     51		 * will take effect on the next vertical sync. Need to
     52		 * find out if it is necessary to wait for 1 vsync
     53		 * before modifying the timing enable bit.
     54		 */
     55		val &= ~DISPLAY_CTRL_PLANE;
     56		poke32(reg, val);
     57
     58		val &= ~DISPLAY_CTRL_TIMING;
     59		poke32(reg, val);
     60	}
     61}
     62
     63static void primary_wait_vertical_sync(int delay)
     64{
     65	unsigned int status;
     66
     67	/*
     68	 * Do not wait when the Primary PLL is off or display control is
     69	 * already off. This will prevent the software to wait forever.
     70	 */
     71	if (!(peek32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) ||
     72	    !(peek32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING))
     73		return;
     74
     75	while (delay-- > 0) {
     76		/* Wait for end of vsync. */
     77		do {
     78			status = peek32(SYSTEM_CTRL);
     79		} while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
     80
     81		/* Wait for start of vsync. */
     82		do {
     83			status = peek32(SYSTEM_CTRL);
     84		} while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
     85	}
     86}
     87
     88static void sw_panel_power_sequence(int disp, int delay)
     89{
     90	unsigned int reg;
     91
     92	/* disp should be 1 to open sequence */
     93	reg = peek32(PANEL_DISPLAY_CTRL);
     94	reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
     95	poke32(PANEL_DISPLAY_CTRL, reg);
     96	primary_wait_vertical_sync(delay);
     97
     98	reg = peek32(PANEL_DISPLAY_CTRL);
     99	reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0);
    100	poke32(PANEL_DISPLAY_CTRL, reg);
    101	primary_wait_vertical_sync(delay);
    102
    103	reg = peek32(PANEL_DISPLAY_CTRL);
    104	reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0);
    105	poke32(PANEL_DISPLAY_CTRL, reg);
    106	primary_wait_vertical_sync(delay);
    107
    108	reg = peek32(PANEL_DISPLAY_CTRL);
    109	reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
    110	poke32(PANEL_DISPLAY_CTRL, reg);
    111	primary_wait_vertical_sync(delay);
    112}
    113
    114void ddk750_set_logical_disp_out(enum disp_output output)
    115{
    116	unsigned int reg;
    117
    118	if (output & PNL_2_USAGE) {
    119		/* set panel path controller select */
    120		reg = peek32(PANEL_DISPLAY_CTRL);
    121		reg &= ~PANEL_DISPLAY_CTRL_SELECT_MASK;
    122		reg |= (((output & PNL_2_MASK) >> PNL_2_OFFSET) <<
    123			PANEL_DISPLAY_CTRL_SELECT_SHIFT);
    124		poke32(PANEL_DISPLAY_CTRL, reg);
    125	}
    126
    127	if (output & CRT_2_USAGE) {
    128		/* set crt path controller select */
    129		reg = peek32(CRT_DISPLAY_CTRL);
    130		reg &= ~CRT_DISPLAY_CTRL_SELECT_MASK;
    131		reg |= (((output & CRT_2_MASK) >> CRT_2_OFFSET) <<
    132			CRT_DISPLAY_CTRL_SELECT_SHIFT);
    133		/*se blank off */
    134		reg &= ~CRT_DISPLAY_CTRL_BLANK;
    135		poke32(CRT_DISPLAY_CTRL, reg);
    136	}
    137
    138	if (output & PRI_TP_USAGE) {
    139		/* set primary timing and plane en_bit */
    140		set_display_control(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
    141	}
    142
    143	if (output & SEC_TP_USAGE) {
    144		/* set secondary timing and plane en_bit*/
    145		set_display_control(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
    146	}
    147
    148	if (output & PNL_SEQ_USAGE) {
    149		/* set  panel sequence */
    150		sw_panel_power_sequence((output & PNL_SEQ_MASK) >>
    151					PNL_SEQ_OFFSET, 4);
    152	}
    153
    154	if (output & DAC_USAGE)
    155		set_DAC((output & DAC_MASK) >> DAC_OFFSET);
    156
    157	if (output & DPMS_USAGE)
    158		ddk750_set_dpms((output & DPMS_MASK) >> DPMS_OFFSET);
    159}