]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/staging/sm750fb/ddk750_display.c
Merge remote-tracking branches 'asoc/topic/ac97', 'asoc/topic/ac97-mfd', 'asoc/topic...
[mirror_ubuntu-focal-kernel.git] / drivers / staging / sm750fb / ddk750_display.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
81dee67e 2#include "ddk750_reg.h"
efe9bc08 3#include "ddk750_chip.h"
81dee67e
SM
4#include "ddk750_display.h"
5#include "ddk750_power.h"
6#include "ddk750_dvi.h"
7
edb23022 8static void setDisplayControl(int ctrl, int disp_state)
81dee67e
SM
9{
10 /* state != 0 means turn on both timing & plane en_bit */
b117b637
MR
11 unsigned long reg, val, reserved;
12 int cnt = 0;
81dee67e 13
259fef35 14 if (!ctrl) {
b117b637
MR
15 reg = PANEL_DISPLAY_CTRL;
16 reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK;
259fef35 17 } else {
b117b637
MR
18 reg = CRT_DISPLAY_CTRL;
19 reserved = CRT_DISPLAY_CTRL_RESERVED_MASK;
20 }
81dee67e 21
c075b6f2 22 val = peek32(reg);
b117b637
MR
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 */
6fba39cf 30 val |= DISPLAY_CTRL_TIMING;
c075b6f2 31 poke32(reg, val);
b117b637 32
6fba39cf 33 val |= DISPLAY_CTRL_PLANE;
b117b637
MR
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++;
c075b6f2
MS
42 poke32(reg, val);
43 } while ((peek32(reg) & ~reserved) != (val & ~reserved));
b117b637
MR
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 */
6fba39cf 55 val &= ~DISPLAY_CTRL_PLANE;
c075b6f2 56 poke32(reg, val);
b117b637 57
6fba39cf 58 val &= ~DISPLAY_CTRL_TIMING;
c075b6f2 59 poke32(reg, val);
81dee67e
SM
60 }
61}
62
57499d13 63static void primary_wait_vertical_sync(int delay)
81dee67e
SM
64{
65 unsigned int status;
40403c1b 66
57499d13
EL
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 */
c075b6f2
MS
71 if (!(peek32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) ||
72 !(peek32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING))
57499d13 73 return;
81dee67e 74
57499d13
EL
75 while (delay-- > 0) {
76 /* Wait for end of vsync. */
77 do {
c075b6f2 78 status = peek32(SYSTEM_CTRL);
57499d13 79 } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
81dee67e 80
57499d13
EL
81 /* Wait for start of vsync. */
82 do {
c075b6f2 83 status = peek32(SYSTEM_CTRL);
57499d13 84 } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
81dee67e
SM
85 }
86}
87
da295041 88static void swPanelPowerSequence(int disp, int delay)
81dee67e
SM
89{
90 unsigned int reg;
91
92 /* disp should be 1 to open sequence */
c075b6f2 93 reg = peek32(PANEL_DISPLAY_CTRL);
6fba39cf 94 reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
c075b6f2 95 poke32(PANEL_DISPLAY_CTRL, reg);
57499d13 96 primary_wait_vertical_sync(delay);
81dee67e 97
c075b6f2 98 reg = peek32(PANEL_DISPLAY_CTRL);
6fba39cf 99 reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0);
c075b6f2 100 poke32(PANEL_DISPLAY_CTRL, reg);
57499d13 101 primary_wait_vertical_sync(delay);
81dee67e 102
c075b6f2 103 reg = peek32(PANEL_DISPLAY_CTRL);
6fba39cf 104 reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0);
c075b6f2 105 poke32(PANEL_DISPLAY_CTRL, reg);
57499d13 106 primary_wait_vertical_sync(delay);
81dee67e 107
c075b6f2 108 reg = peek32(PANEL_DISPLAY_CTRL);
6fba39cf 109 reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
c075b6f2 110 poke32(PANEL_DISPLAY_CTRL, reg);
57499d13 111 primary_wait_vertical_sync(delay);
81dee67e
SM
112}
113
114void ddk750_setLogicalDispOut(disp_output_t output)
115{
116 unsigned int reg;
40403c1b 117
8c11f5a2 118 if (output & PNL_2_USAGE) {
81dee67e 119 /* set panel path controller select */
c075b6f2 120 reg = peek32(PANEL_DISPLAY_CTRL);
c4e893b7
MR
121 reg &= ~PANEL_DISPLAY_CTRL_SELECT_MASK;
122 reg |= (((output & PNL_2_MASK) >> PNL_2_OFFSET) <<
123 PANEL_DISPLAY_CTRL_SELECT_SHIFT);
c075b6f2 124 poke32(PANEL_DISPLAY_CTRL, reg);
81dee67e
SM
125 }
126
8c11f5a2 127 if (output & CRT_2_USAGE) {
81dee67e 128 /* set crt path controller select */
c075b6f2 129 reg = peek32(CRT_DISPLAY_CTRL);
cdce1f18
MR
130 reg &= ~CRT_DISPLAY_CTRL_SELECT_MASK;
131 reg |= (((output & CRT_2_MASK) >> CRT_2_OFFSET) <<
132 CRT_DISPLAY_CTRL_SELECT_SHIFT);
81dee67e 133 /*se blank off */
d8264edf 134 reg &= ~CRT_DISPLAY_CTRL_BLANK;
c075b6f2 135 poke32(CRT_DISPLAY_CTRL, reg);
81dee67e
SM
136 }
137
8c11f5a2 138 if (output & PRI_TP_USAGE) {
81dee67e 139 /* set primary timing and plane en_bit */
aeec43da 140 setDisplayControl(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
81dee67e
SM
141 }
142
8c11f5a2 143 if (output & SEC_TP_USAGE) {
81dee67e 144 /* set secondary timing and plane en_bit*/
aeec43da 145 setDisplayControl(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
81dee67e
SM
146 }
147
8c11f5a2 148 if (output & PNL_SEQ_USAGE) {
81dee67e 149 /* set panel sequence */
d6171ba8
AP
150 swPanelPowerSequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET,
151 4);
81dee67e
SM
152 }
153
9ccc5f44 154 if (output & DAC_USAGE)
e80ef45d 155 setDAC((output & DAC_MASK) >> DAC_OFFSET);
81dee67e 156
9ccc5f44 157 if (output & DPMS_USAGE)
03140dab 158 ddk750_set_dpms((output & DPMS_MASK) >> DPMS_OFFSET);
81dee67e 159}