File Index
Files and directories
Sign in
FILE

ddk750_display.c

File preview with syntax highlighting.

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