]> Git Repo - linux.git/blame - drivers/staging/sm750fb/ddk750_mode.c
Merge tag 'selinux-pr-20181015' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / drivers / staging / sm750fb / ddk750_mode.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
81dee67e 2
81dee67e
SM
3#include "ddk750_reg.h"
4#include "ddk750_mode.h"
5#include "ddk750_chip.h"
6
f5016082
ES
7/*
8 * SM750LE only:
35e4d8ca
EF
9 * This function takes care extra registers and bit fields required to set
10 * up a mode in SM750LE
11 *
12 * Explanation about Display Control register:
13 * HW only supports 7 predefined pixel clocks, and clock select is
14 * in bit 29:27 of Display Control register.
15 */
bf760231
AS
16static unsigned long displayControlAdjust_SM750LE(struct mode_parameter *pModeParam,
17 unsigned long dispControl)
81dee67e
SM
18{
19 unsigned long x, y;
20
21 x = pModeParam->horizontal_display_end;
22 y = pModeParam->vertical_display_end;
23
f5016082
ES
24 /*
25 * SM750LE has to set up the top-left and bottom-right
35e4d8ca
EF
26 * registers as well.
27 * Note that normal SM750/SM718 only use those two register for
28 * auto-centering mode.
78376535 29 */
c075b6f2 30 poke32(CRT_AUTO_CENTERING_TL, 0);
78376535 31
c075b6f2 32 poke32(CRT_AUTO_CENTERING_BR,
4cd3096d
AS
33 (((y - 1) << CRT_AUTO_CENTERING_BR_BOTTOM_SHIFT) &
34 CRT_AUTO_CENTERING_BR_BOTTOM_MASK) |
35 ((x - 1) & CRT_AUTO_CENTERING_BR_RIGHT_MASK));
78376535 36
f5016082
ES
37 /*
38 * Assume common fields in dispControl have been properly set before
35e4d8ca
EF
39 * calling this function.
40 * This function only sets the extra fields in dispControl.
78376535 41 */
81dee67e
SM
42
43 /* Clear bit 29:27 of display control register */
cdce1f18 44 dispControl &= ~CRT_DISPLAY_CTRL_CLK_MASK;
81dee67e
SM
45
46 /* Set bit 29:27 of display control register for the right clock */
fbb8c963 47 /* Note that SM750LE only need to supported 7 resolutions. */
8332d94c 48 if (x == 800 && y == 600)
cdce1f18 49 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL41;
81dee67e 50 else if (x == 1024 && y == 768)
cdce1f18 51 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL65;
81dee67e 52 else if (x == 1152 && y == 864)
cdce1f18 53 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80;
81dee67e 54 else if (x == 1280 && y == 768)
cdce1f18 55 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80;
81dee67e 56 else if (x == 1280 && y == 720)
cdce1f18 57 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL74;
81dee67e 58 else if (x == 1280 && y == 960)
cdce1f18 59 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108;
81dee67e 60 else if (x == 1280 && y == 1024)
cdce1f18 61 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108;
81dee67e 62 else /* default to VGA clock */
cdce1f18 63 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL25;
81dee67e
SM
64
65 /* Set bit 25:24 of display controller */
d8264edf 66 dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT);
81dee67e 67
78376535 68 /* Set bit 14 of display controller */
992f9614 69 dispControl |= DISPLAY_CTRL_CLOCK_PHASE;
81dee67e 70
c075b6f2 71 poke32(CRT_DISPLAY_CTRL, dispControl);
81dee67e
SM
72
73 return dispControl;
74}
75
81dee67e 76/* only timing related registers will be programed */
bf760231
AS
77static int programModeRegisters(struct mode_parameter *pModeParam,
78 struct pll_value *pll)
81dee67e
SM
79{
80 int ret = 0;
81 int cnt = 0;
c436e6ba 82 unsigned int tmp, reg;
40403c1b 83
259fef35 84 if (pll->clockType == SECONDARY_PLL) {
81dee67e 85 /* programe secondary pixel clock */
c075b6f2 86 poke32(CRT_PLL_CTRL, sm750_format_pll_reg(pll));
7369e062
AS
87
88 tmp = ((pModeParam->horizontal_total - 1) <<
89 CRT_HORIZONTAL_TOTAL_TOTAL_SHIFT) &
90 CRT_HORIZONTAL_TOTAL_TOTAL_MASK;
91 tmp |= (pModeParam->horizontal_display_end - 1) &
92 CRT_HORIZONTAL_TOTAL_DISPLAY_END_MASK;
93
94 poke32(CRT_HORIZONTAL_TOTAL, tmp);
95
96 tmp = (pModeParam->horizontal_sync_width <<
97 CRT_HORIZONTAL_SYNC_WIDTH_SHIFT) &
98 CRT_HORIZONTAL_SYNC_WIDTH_MASK;
99 tmp |= (pModeParam->horizontal_sync_start - 1) &
100 CRT_HORIZONTAL_SYNC_START_MASK;
101
102 poke32(CRT_HORIZONTAL_SYNC, tmp);
103
104 tmp = ((pModeParam->vertical_total - 1) <<
105 CRT_VERTICAL_TOTAL_TOTAL_SHIFT) &
106 CRT_VERTICAL_TOTAL_TOTAL_MASK;
107 tmp |= (pModeParam->vertical_display_end - 1) &
108 CRT_VERTICAL_TOTAL_DISPLAY_END_MASK;
109
110 poke32(CRT_VERTICAL_TOTAL, tmp);
111
112 tmp = ((pModeParam->vertical_sync_height <<
113 CRT_VERTICAL_SYNC_HEIGHT_SHIFT)) &
114 CRT_VERTICAL_SYNC_HEIGHT_MASK;
115 tmp |= (pModeParam->vertical_sync_start - 1) &
116 CRT_VERTICAL_SYNC_START_MASK;
117
118 poke32(CRT_VERTICAL_SYNC, tmp);
81dee67e 119
6fba39cf
MR
120 tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE;
121 if (pModeParam->vertical_sync_polarity)
122 tmp |= DISPLAY_CTRL_VSYNC_PHASE;
123 if (pModeParam->horizontal_sync_polarity)
124 tmp |= DISPLAY_CTRL_HSYNC_PHASE;
81dee67e 125
06a4f429 126 if (sm750_get_chip_type() == SM750LE) {
c436e6ba 127 displayControlAdjust_SM750LE(pModeParam, tmp);
6338a781 128 } else {
c075b6f2 129 reg = peek32(CRT_DISPLAY_CTRL) &
6fba39cf
MR
130 ~(DISPLAY_CTRL_VSYNC_PHASE |
131 DISPLAY_CTRL_HSYNC_PHASE |
132 DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE);
81dee67e 133
c075b6f2 134 poke32(CRT_DISPLAY_CTRL, tmp | reg);
81dee67e
SM
135 }
136
259fef35 137 } else if (pll->clockType == PRIMARY_PLL) {
c436e6ba 138 unsigned int reserved;
40403c1b 139
c075b6f2 140 poke32(PANEL_PLL_CTRL, sm750_format_pll_reg(pll));
81dee67e 141
60112069
MR
142 reg = ((pModeParam->horizontal_total - 1) <<
143 PANEL_HORIZONTAL_TOTAL_TOTAL_SHIFT) &
144 PANEL_HORIZONTAL_TOTAL_TOTAL_MASK;
145 reg |= ((pModeParam->horizontal_display_end - 1) &
146 PANEL_HORIZONTAL_TOTAL_DISPLAY_END_MASK);
c075b6f2 147 poke32(PANEL_HORIZONTAL_TOTAL, reg);
81dee67e 148
c075b6f2 149 poke32(PANEL_HORIZONTAL_SYNC,
4cd3096d
AS
150 ((pModeParam->horizontal_sync_width <<
151 PANEL_HORIZONTAL_SYNC_WIDTH_SHIFT) &
152 PANEL_HORIZONTAL_SYNC_WIDTH_MASK) |
153 ((pModeParam->horizontal_sync_start - 1) &
154 PANEL_HORIZONTAL_SYNC_START_MASK));
81dee67e 155
c075b6f2 156 poke32(PANEL_VERTICAL_TOTAL,
4cd3096d
AS
157 (((pModeParam->vertical_total - 1) <<
158 PANEL_VERTICAL_TOTAL_TOTAL_SHIFT) &
159 PANEL_VERTICAL_TOTAL_TOTAL_MASK) |
160 ((pModeParam->vertical_display_end - 1) &
161 PANEL_VERTICAL_TOTAL_DISPLAY_END_MASK));
81dee67e 162
c075b6f2 163 poke32(PANEL_VERTICAL_SYNC,
4cd3096d
AS
164 ((pModeParam->vertical_sync_height <<
165 PANEL_VERTICAL_SYNC_HEIGHT_SHIFT) &
166 PANEL_VERTICAL_SYNC_HEIGHT_MASK) |
167 ((pModeParam->vertical_sync_start - 1) &
168 PANEL_VERTICAL_SYNC_START_MASK));
81dee67e 169
6fba39cf
MR
170 tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE;
171 if (pModeParam->vertical_sync_polarity)
172 tmp |= DISPLAY_CTRL_VSYNC_PHASE;
173 if (pModeParam->horizontal_sync_polarity)
174 tmp |= DISPLAY_CTRL_HSYNC_PHASE;
175 if (pModeParam->clock_phase_polarity)
176 tmp |= DISPLAY_CTRL_CLOCK_PHASE;
78376535 177
9bd2c86b 178 reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK |
6fba39cf 179 PANEL_DISPLAY_CTRL_VSYNC;
81dee67e 180
c075b6f2 181 reg = (peek32(PANEL_DISPLAY_CTRL) & ~reserved) &
6fba39cf
MR
182 ~(DISPLAY_CTRL_CLOCK_PHASE | DISPLAY_CTRL_VSYNC_PHASE |
183 DISPLAY_CTRL_HSYNC_PHASE | DISPLAY_CTRL_TIMING |
184 DISPLAY_CTRL_PLANE);
81dee67e 185
f5016082
ES
186 /*
187 * May a hardware bug or just my test chip (not confirmed).
188 * PANEL_DISPLAY_CTRL register seems requiring few writes
189 * before a value can be successfully written in.
190 * Added some masks to mask out the reserved bits.
191 * Note: This problem happens by design. The hardware will wait
192 * for the next vertical sync to turn on/off the plane.
193 */
c075b6f2 194 poke32(PANEL_DISPLAY_CTRL, tmp | reg);
cfac7d6a 195
c075b6f2 196 while ((peek32(PANEL_DISPLAY_CTRL) & ~reserved) !=
c436e6ba 197 (tmp | reg)) {
81dee67e 198 cnt++;
9ccc5f44 199 if (cnt > 1000)
81dee67e 200 break;
c075b6f2 201 poke32(PANEL_DISPLAY_CTRL, tmp | reg);
81dee67e 202 }
259fef35 203 } else {
81dee67e
SM
204 ret = -1;
205 }
206 return ret;
207}
208
17eb0b29 209int ddk750_setModeTiming(struct mode_parameter *parm, enum clock_type clock)
81dee67e 210{
9872fa75 211 struct pll_value pll;
81dee67e 212 unsigned int uiActualPixelClk;
40403c1b 213
81dee67e
SM
214 pll.inputFreq = DEFAULT_INPUT_CLOCK;
215 pll.clockType = clock;
216
52d0744d 217 uiActualPixelClk = sm750_calc_pll_value(parm->pixel_clock, &pll);
06a4f429 218 if (sm750_get_chip_type() == SM750LE) {
81dee67e 219 /* set graphic mode via IO method */
195d2b64
IA
220 outb_p(0x88, 0x3d4);
221 outb_p(0x06, 0x3d5);
81dee67e 222 }
195d2b64 223 programModeRegisters(parm, &pll);
81dee67e
SM
224 return 0;
225}
This page took 0.629865 seconds and 4 git commands to generate.