diff options
Diffstat (limited to 'drivers/video/geode/lxfb_ops.c')
-rw-r--r-- | drivers/video/geode/lxfb_ops.c | 699 |
1 files changed, 502 insertions, 197 deletions
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c index 4fbc99be96ef..cd9d4cc26954 100644 --- a/drivers/video/geode/lxfb_ops.c +++ b/drivers/video/geode/lxfb_ops.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/fb.h> | 13 | #include <linux/fb.h> |
14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <asm/geode.h> | ||
16 | 17 | ||
17 | #include "lxfb.h" | 18 | #include "lxfb.h" |
18 | 19 | ||
@@ -34,35 +35,85 @@ static const struct { | |||
34 | unsigned int pllval; | 35 | unsigned int pllval; |
35 | unsigned int freq; | 36 | unsigned int freq; |
36 | } pll_table[] = { | 37 | } pll_table[] = { |
37 | { 0x000031AC, 24923 }, | 38 | { 0x000131AC, 6231 }, |
38 | { 0x0000215D, 25175 }, | 39 | { 0x0001215D, 6294 }, |
39 | { 0x00001087, 27000 }, | 40 | { 0x00011087, 6750 }, |
40 | { 0x0000216C, 28322 }, | 41 | { 0x0001216C, 7081 }, |
41 | { 0x0000218D, 28560 }, | 42 | { 0x0001218D, 7140 }, |
42 | { 0x000010C9, 31200 }, | 43 | { 0x000110C9, 7800 }, |
43 | { 0x00003147, 31500 }, | 44 | { 0x00013147, 7875 }, |
44 | { 0x000010A7, 33032 }, | 45 | { 0x000110A7, 8258 }, |
45 | { 0x00002159, 35112 }, | 46 | { 0x00012159, 8778 }, |
46 | { 0x00004249, 35500 }, | 47 | { 0x00014249, 8875 }, |
47 | { 0x00000057, 36000 }, | 48 | { 0x00010057, 9000 }, |
48 | { 0x0000219A, 37889 }, | 49 | { 0x0001219A, 9472 }, |
49 | { 0x00002158, 39168 }, | 50 | { 0x00012158, 9792 }, |
50 | { 0x00000045, 40000 }, | 51 | { 0x00010045, 10000 }, |
51 | { 0x00000089, 43163 }, | 52 | { 0x00010089, 10791 }, |
52 | { 0x000010E7, 44900 }, | 53 | { 0x000110E7, 11225 }, |
53 | { 0x00002136, 45720 }, | 54 | { 0x00012136, 11430 }, |
54 | { 0x00003207, 49500 }, | 55 | { 0x00013207, 12375 }, |
55 | { 0x00002187, 50000 }, | 56 | { 0x00012187, 12500 }, |
56 | { 0x00004286, 56250 }, | 57 | { 0x00014286, 14063 }, |
57 | { 0x000010E5, 60065 }, | 58 | { 0x000110E5, 15016 }, |
58 | { 0x00004214, 65000 }, | 59 | { 0x00014214, 16250 }, |
59 | { 0x00001105, 68179 }, | 60 | { 0x00011105, 17045 }, |
60 | { 0x000031E4, 74250 }, | 61 | { 0x000131E4, 18563 }, |
61 | { 0x00003183, 75000 }, | 62 | { 0x00013183, 18750 }, |
62 | { 0x00004284, 78750 }, | 63 | { 0x00014284, 19688 }, |
63 | { 0x00001104, 81600 }, | 64 | { 0x00011104, 20400 }, |
64 | { 0x00006363, 94500 }, | 65 | { 0x00016363, 23625 }, |
65 | { 0x00005303, 97520 }, | 66 | { 0x00015303, 24380 }, |
67 | { 0x000031AC, 24923 }, | ||
68 | { 0x0000215D, 25175 }, | ||
69 | { 0x00001087, 27000 }, | ||
70 | { 0x0000216C, 28322 }, | ||
71 | { 0x0000218D, 28560 }, | ||
72 | { 0x00010041, 29913 }, | ||
73 | { 0x000010C9, 31200 }, | ||
74 | { 0x00003147, 31500 }, | ||
75 | { 0x000141A1, 32400 }, | ||
76 | { 0x000010A7, 33032 }, | ||
77 | { 0x00012182, 33375 }, | ||
78 | { 0x000141B1, 33750 }, | ||
79 | { 0x00002159, 35112 }, | ||
80 | { 0x00004249, 35500 }, | ||
81 | { 0x00000057, 36000 }, | ||
82 | { 0x000141E1, 37125 }, | ||
83 | { 0x0000219A, 37889 }, | ||
84 | { 0x00002158, 39168 }, | ||
85 | { 0x00000045, 40000 }, | ||
86 | { 0x000131A1, 40500 }, | ||
87 | { 0x00010061, 42301 }, | ||
88 | { 0x00000089, 43163 }, | ||
89 | { 0x00012151, 43875 }, | ||
90 | { 0x000010E7, 44900 }, | ||
91 | { 0x00002136, 45720 }, | ||
92 | { 0x000152E1, 47250 }, | ||
93 | { 0x00010071, 48000 }, | ||
94 | { 0x00003207, 49500 }, | ||
95 | { 0x00002187, 50000 }, | ||
96 | { 0x00014291, 50625 }, | ||
97 | { 0x00011101, 51188 }, | ||
98 | { 0x00017481, 54563 }, | ||
99 | { 0x00004286, 56250 }, | ||
100 | { 0x00014170, 57375 }, | ||
101 | { 0x00016210, 58500 }, | ||
102 | { 0x000010E5, 60065 }, | ||
103 | { 0x00013140, 62796 }, | ||
104 | { 0x00004214, 65000 }, | ||
105 | { 0x00016250, 65250 }, | ||
106 | { 0x00001105, 68179 }, | ||
107 | { 0x000141C0, 69600 }, | ||
108 | { 0x00015220, 70160 }, | ||
109 | { 0x00010050, 72000 }, | ||
110 | { 0x000031E4, 74250 }, | ||
111 | { 0x00003183, 75000 }, | ||
112 | { 0x00004284, 78750 }, | ||
113 | { 0x00012130, 80052 }, | ||
114 | { 0x00001104, 81600 }, | ||
115 | { 0x00006363, 94500 }, | ||
116 | { 0x00005303, 97520 }, | ||
66 | { 0x00002183, 100187 }, | 117 | { 0x00002183, 100187 }, |
67 | { 0x00002122, 101420 }, | 118 | { 0x00002122, 101420 }, |
68 | { 0x00001081, 108000 }, | 119 | { 0x00001081, 108000 }, |
@@ -101,16 +152,16 @@ static void lx_set_dotpll(u32 pllval) | |||
101 | u32 dotpll_lo, dotpll_hi; | 152 | u32 dotpll_lo, dotpll_hi; |
102 | int i; | 153 | int i; |
103 | 154 | ||
104 | rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | 155 | rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); |
105 | 156 | ||
106 | if ((dotpll_lo & GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval)) | 157 | if ((dotpll_lo & MSR_GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval)) |
107 | return; | 158 | return; |
108 | 159 | ||
109 | dotpll_hi = pllval; | 160 | dotpll_hi = pllval; |
110 | dotpll_lo &= ~(GLCP_DOTPLL_BYPASS | GLCP_DOTPLL_HALFPIX); | 161 | dotpll_lo &= ~(MSR_GLCP_DOTPLL_BYPASS | MSR_GLCP_DOTPLL_HALFPIX); |
111 | dotpll_lo |= GLCP_DOTPLL_RESET; | 162 | dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET; |
112 | 163 | ||
113 | wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | 164 | wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); |
114 | 165 | ||
115 | /* Wait 100us for the PLL to lock */ | 166 | /* Wait 100us for the PLL to lock */ |
116 | 167 | ||
@@ -119,15 +170,15 @@ static void lx_set_dotpll(u32 pllval) | |||
119 | /* Now, loop for the lock bit */ | 170 | /* Now, loop for the lock bit */ |
120 | 171 | ||
121 | for (i = 0; i < 1000; i++) { | 172 | for (i = 0; i < 1000; i++) { |
122 | rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | 173 | rdmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); |
123 | if (dotpll_lo & GLCP_DOTPLL_LOCK) | 174 | if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK) |
124 | break; | 175 | break; |
125 | } | 176 | } |
126 | 177 | ||
127 | /* Clear the reset bit */ | 178 | /* Clear the reset bit */ |
128 | 179 | ||
129 | dotpll_lo &= ~GLCP_DOTPLL_RESET; | 180 | dotpll_lo &= ~MSR_GLCP_DOTPLL_DOTRESET; |
130 | wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); | 181 | wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); |
131 | } | 182 | } |
132 | 183 | ||
133 | /* Set the clock based on the frequency specified by the current mode */ | 184 | /* Set the clock based on the frequency specified by the current mode */ |
@@ -137,7 +188,7 @@ static void lx_set_clock(struct fb_info *info) | |||
137 | unsigned int diff, min, best = 0; | 188 | unsigned int diff, min, best = 0; |
138 | unsigned int freq, i; | 189 | unsigned int freq, i; |
139 | 190 | ||
140 | freq = (unsigned int) (0x3b9aca00 / info->var.pixclock); | 191 | freq = (unsigned int) (1000000000 / info->var.pixclock); |
141 | 192 | ||
142 | min = abs(pll_table[0].freq - freq); | 193 | min = abs(pll_table[0].freq - freq); |
143 | 194 | ||
@@ -149,7 +200,7 @@ static void lx_set_clock(struct fb_info *info) | |||
149 | } | 200 | } |
150 | } | 201 | } |
151 | 202 | ||
152 | lx_set_dotpll(pll_table[best].pllval & 0x7FFF); | 203 | lx_set_dotpll(pll_table[best].pllval & 0x00017FFF); |
153 | } | 204 | } |
154 | 205 | ||
155 | static void lx_graphics_disable(struct fb_info *info) | 206 | static void lx_graphics_disable(struct fb_info *info) |
@@ -159,63 +210,62 @@ static void lx_graphics_disable(struct fb_info *info) | |||
159 | 210 | ||
160 | /* Note: This assumes that the video is in a quitet state */ | 211 | /* Note: This assumes that the video is in a quitet state */ |
161 | 212 | ||
162 | writel(0, par->df_regs + DF_ALPHA_CONTROL_1); | 213 | write_vp(par, VP_A1T, 0); |
163 | writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 32); | 214 | write_vp(par, VP_A2T, 0); |
164 | writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 64); | 215 | write_vp(par, VP_A3T, 0); |
165 | 216 | ||
166 | /* Turn off the VGA and video enable */ | 217 | /* Turn off the VGA and video enable */ |
167 | val = readl (par->dc_regs + DC_GENERAL_CFG) & | 218 | val = read_dc(par, DC_GENERAL_CFG) & ~(DC_GENERAL_CFG_VGAE | |
168 | ~(DC_GCFG_VGAE | DC_GCFG_VIDE); | 219 | DC_GENERAL_CFG_VIDE); |
169 | 220 | ||
170 | writel(val, par->dc_regs + DC_GENERAL_CFG); | 221 | write_dc(par, DC_GENERAL_CFG, val); |
171 | 222 | ||
172 | val = readl(par->df_regs + DF_VIDEO_CFG) & ~DF_VCFG_VID_EN; | 223 | val = read_vp(par, VP_VCFG) & ~VP_VCFG_VID_EN; |
173 | writel(val, par->df_regs + DF_VIDEO_CFG); | 224 | write_vp(par, VP_VCFG, val); |
174 | 225 | ||
175 | writel( DC_IRQ_MASK | DC_VSYNC_IRQ_MASK | | 226 | write_dc(par, DC_IRQ, DC_IRQ_MASK | DC_IRQ_VIP_VSYNC_LOSS_IRQ_MASK | |
176 | DC_IRQ_STATUS | DC_VSYNC_IRQ_STATUS, | 227 | DC_IRQ_STATUS | DC_IRQ_VIP_VSYNC_IRQ_STATUS); |
177 | par->dc_regs + DC_IRQ); | ||
178 | 228 | ||
179 | val = readl(par->dc_regs + DC_GENLCK_CTRL) & ~DC_GENLCK_ENABLE; | 229 | val = read_dc(par, DC_GENLK_CTL) & ~DC_GENLK_CTL_GENLK_EN; |
180 | writel(val, par->dc_regs + DC_GENLCK_CTRL); | 230 | write_dc(par, DC_GENLK_CTL, val); |
181 | 231 | ||
182 | val = readl(par->dc_regs + DC_COLOR_KEY) & ~DC_CLR_KEY_ENABLE; | 232 | val = read_dc(par, DC_CLR_KEY); |
183 | writel(val & ~DC_CLR_KEY_ENABLE, par->dc_regs + DC_COLOR_KEY); | 233 | write_dc(par, DC_CLR_KEY, val & ~DC_CLR_KEY_CLR_KEY_EN); |
184 | 234 | ||
185 | /* We don't actually blank the panel, due to the long latency | 235 | /* turn off the panel */ |
186 | involved with bringing it back */ | 236 | write_fp(par, FP_PM, read_fp(par, FP_PM) & ~FP_PM_P); |
187 | 237 | ||
188 | val = readl(par->df_regs + DF_MISC) | DF_MISC_DAC_PWRDN; | 238 | val = read_vp(par, VP_MISC) | VP_MISC_DACPWRDN; |
189 | writel(val, par->df_regs + DF_MISC); | 239 | write_vp(par, VP_MISC, val); |
190 | 240 | ||
191 | /* Turn off the display */ | 241 | /* Turn off the display */ |
192 | 242 | ||
193 | val = readl(par->df_regs + DF_DISPLAY_CFG); | 243 | val = read_vp(par, VP_DCFG); |
194 | writel(val & ~(DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN | | 244 | write_vp(par, VP_DCFG, val & ~(VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN | |
195 | DF_DCFG_DAC_BL_EN), par->df_regs + DF_DISPLAY_CFG); | 245 | VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN)); |
196 | 246 | ||
197 | gcfg = readl(par->dc_regs + DC_GENERAL_CFG); | 247 | gcfg = read_dc(par, DC_GENERAL_CFG); |
198 | gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE); | 248 | gcfg &= ~(DC_GENERAL_CFG_CMPE | DC_GENERAL_CFG_DECE); |
199 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | 249 | write_dc(par, DC_GENERAL_CFG, gcfg); |
200 | 250 | ||
201 | /* Turn off the TGEN */ | 251 | /* Turn off the TGEN */ |
202 | val = readl(par->dc_regs + DC_DISPLAY_CFG); | 252 | val = read_dc(par, DC_DISPLAY_CFG); |
203 | val &= ~DC_DCFG_TGEN; | 253 | val &= ~DC_DISPLAY_CFG_TGEN; |
204 | writel(val, par->dc_regs + DC_DISPLAY_CFG); | 254 | write_dc(par, DC_DISPLAY_CFG, val); |
205 | 255 | ||
206 | /* Wait 1000 usecs to ensure that the TGEN is clear */ | 256 | /* Wait 1000 usecs to ensure that the TGEN is clear */ |
207 | udelay(1000); | 257 | udelay(1000); |
208 | 258 | ||
209 | /* Turn off the FIFO loader */ | 259 | /* Turn off the FIFO loader */ |
210 | 260 | ||
211 | gcfg &= ~DC_GCFG_DFLE; | 261 | gcfg &= ~DC_GENERAL_CFG_DFLE; |
212 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | 262 | write_dc(par, DC_GENERAL_CFG, gcfg); |
213 | 263 | ||
214 | /* Lastly, wait for the GP to go idle */ | 264 | /* Lastly, wait for the GP to go idle */ |
215 | 265 | ||
216 | do { | 266 | do { |
217 | val = readl(par->gp_regs + GP_BLT_STATUS); | 267 | val = read_gp(par, GP_BLT_STATUS); |
218 | } while ((val & GP_BS_BLT_BUSY) || !(val & GP_BS_CB_EMPTY)); | 268 | } while ((val & GP_BLT_STATUS_PB) || !(val & GP_BLT_STATUS_CE)); |
219 | } | 269 | } |
220 | 270 | ||
221 | static void lx_graphics_enable(struct fb_info *info) | 271 | static void lx_graphics_enable(struct fb_info *info) |
@@ -224,80 +274,85 @@ static void lx_graphics_enable(struct fb_info *info) | |||
224 | u32 temp, config; | 274 | u32 temp, config; |
225 | 275 | ||
226 | /* Set the video request register */ | 276 | /* Set the video request register */ |
227 | writel(0, par->df_regs + DF_VIDEO_REQUEST); | 277 | write_vp(par, VP_VRR, 0); |
228 | 278 | ||
229 | /* Set up the polarities */ | 279 | /* Set up the polarities */ |
230 | 280 | ||
231 | config = readl(par->df_regs + DF_DISPLAY_CFG); | 281 | config = read_vp(par, VP_DCFG); |
232 | 282 | ||
233 | config &= ~(DF_DCFG_CRT_SYNC_SKW_MASK | DF_DCFG_PWR_SEQ_DLY_MASK | | 283 | config &= ~(VP_DCFG_CRT_SYNC_SKW | VP_DCFG_PWR_SEQ_DELAY | |
234 | DF_DCFG_CRT_HSYNC_POL | DF_DCFG_CRT_VSYNC_POL); | 284 | VP_DCFG_CRT_HSYNC_POL | VP_DCFG_CRT_VSYNC_POL); |
235 | 285 | ||
236 | config |= (DF_DCFG_CRT_SYNC_SKW_INIT | DF_DCFG_PWR_SEQ_DLY_INIT | | 286 | config |= (VP_DCFG_CRT_SYNC_SKW_DEFAULT | VP_DCFG_PWR_SEQ_DELAY_DEFAULT |
237 | DF_DCFG_GV_PAL_BYP); | 287 | | VP_DCFG_GV_GAM); |
238 | 288 | ||
239 | if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) | 289 | if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) |
240 | config |= DF_DCFG_CRT_HSYNC_POL; | 290 | config |= VP_DCFG_CRT_HSYNC_POL; |
241 | 291 | ||
242 | if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) | 292 | if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) |
243 | config |= DF_DCFG_CRT_VSYNC_POL; | 293 | config |= VP_DCFG_CRT_VSYNC_POL; |
244 | 294 | ||
245 | if (par->output & OUTPUT_PANEL) { | 295 | if (par->output & OUTPUT_PANEL) { |
246 | u32 msrlo, msrhi; | 296 | u32 msrlo, msrhi; |
247 | 297 | ||
248 | writel(DF_DEFAULT_TFT_PMTIM1, | 298 | write_fp(par, FP_PT1, 0); |
249 | par->df_regs + DF_PANEL_TIM1); | 299 | write_fp(par, FP_PT2, FP_PT2_SCRC); |
250 | writel(DF_DEFAULT_TFT_PMTIM2, | 300 | write_fp(par, FP_DFC, FP_DFC_BC); |
251 | par->df_regs + DF_PANEL_TIM2); | ||
252 | writel(DF_DEFAULT_TFT_DITHCTL, | ||
253 | par->df_regs + DF_DITHER_CONTROL); | ||
254 | 301 | ||
255 | msrlo = DF_DEFAULT_TFT_PAD_SEL_LOW; | 302 | msrlo = MSR_LX_MSR_PADSEL_TFT_SEL_LOW; |
256 | msrhi = DF_DEFAULT_TFT_PAD_SEL_HIGH; | 303 | msrhi = MSR_LX_MSR_PADSEL_TFT_SEL_HIGH; |
257 | 304 | ||
258 | wrmsr(MSR_LX_DF_PADSEL, msrlo, msrhi); | 305 | wrmsr(MSR_LX_MSR_PADSEL, msrlo, msrhi); |
259 | } | 306 | } |
260 | 307 | ||
261 | if (par->output & OUTPUT_CRT) { | 308 | if (par->output & OUTPUT_CRT) { |
262 | config |= DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | | 309 | config |= VP_DCFG_CRT_EN | VP_DCFG_HSYNC_EN | |
263 | DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN; | 310 | VP_DCFG_VSYNC_EN | VP_DCFG_DAC_BL_EN; |
264 | } | 311 | } |
265 | 312 | ||
266 | writel(config, par->df_regs + DF_DISPLAY_CFG); | 313 | write_vp(par, VP_DCFG, config); |
267 | 314 | ||
268 | /* Turn the CRT dacs back on */ | 315 | /* Turn the CRT dacs back on */ |
269 | 316 | ||
270 | if (par->output & OUTPUT_CRT) { | 317 | if (par->output & OUTPUT_CRT) { |
271 | temp = readl(par->df_regs + DF_MISC); | 318 | temp = read_vp(par, VP_MISC); |
272 | temp &= ~(DF_MISC_DAC_PWRDN | DF_MISC_A_PWRDN); | 319 | temp &= ~(VP_MISC_DACPWRDN | VP_MISC_APWRDN); |
273 | writel(temp, par->df_regs + DF_MISC); | 320 | write_vp(par, VP_MISC, temp); |
274 | } | 321 | } |
275 | 322 | ||
276 | /* Turn the panel on (if it isn't already) */ | 323 | /* Turn the panel on (if it isn't already) */ |
277 | 324 | if (par->output & OUTPUT_PANEL) | |
278 | if (par->output & OUTPUT_PANEL) { | 325 | write_fp(par, FP_PM, read_fp(par, FP_PM) | FP_PM_P); |
279 | temp = readl(par->df_regs + DF_FP_PM); | ||
280 | |||
281 | if (!(temp & 0x09)) | ||
282 | writel(temp | DF_FP_PM_P, par->df_regs + DF_FP_PM); | ||
283 | } | ||
284 | |||
285 | temp = readl(par->df_regs + DF_MISC); | ||
286 | temp = readl(par->df_regs + DF_DISPLAY_CFG); | ||
287 | } | 326 | } |
288 | 327 | ||
289 | unsigned int lx_framebuffer_size(void) | 328 | unsigned int lx_framebuffer_size(void) |
290 | { | 329 | { |
291 | unsigned int val; | 330 | unsigned int val; |
292 | 331 | ||
332 | if (!geode_has_vsa2()) { | ||
333 | uint32_t hi, lo; | ||
334 | |||
335 | /* The number of pages is (PMAX - PMIN)+1 */ | ||
336 | rdmsr(MSR_GLIU_P2D_RO0, lo, hi); | ||
337 | |||
338 | /* PMAX */ | ||
339 | val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20); | ||
340 | /* PMIN */ | ||
341 | val -= (lo & 0x000fffff); | ||
342 | val += 1; | ||
343 | |||
344 | /* The page size is 4k */ | ||
345 | return (val << 12); | ||
346 | } | ||
347 | |||
293 | /* The frame buffer size is reported by a VSM in VSA II */ | 348 | /* The frame buffer size is reported by a VSM in VSA II */ |
294 | /* Virtual Register Class = 0x02 */ | 349 | /* Virtual Register Class = 0x02 */ |
295 | /* VG_MEM_SIZE (1MB units) = 0x00 */ | 350 | /* VG_MEM_SIZE (1MB units) = 0x00 */ |
296 | 351 | ||
297 | outw(0xFC53, 0xAC1C); | 352 | outw(VSA_VR_UNLOCK, VSA_VRC_INDEX); |
298 | outw(0x0200, 0xAC1C); | 353 | outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX); |
299 | 354 | ||
300 | val = (unsigned int)(inw(0xAC1E)) & 0xFE; | 355 | val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFE; |
301 | return (val << 20); | 356 | return (val << 20); |
302 | } | 357 | } |
303 | 358 | ||
@@ -313,7 +368,7 @@ void lx_set_mode(struct fb_info *info) | |||
313 | int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; | 368 | int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; |
314 | 369 | ||
315 | /* Unlock the DC registers */ | 370 | /* Unlock the DC registers */ |
316 | writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); | 371 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); |
317 | 372 | ||
318 | lx_graphics_disable(info); | 373 | lx_graphics_disable(info); |
319 | 374 | ||
@@ -321,102 +376,104 @@ void lx_set_mode(struct fb_info *info) | |||
321 | 376 | ||
322 | /* Set output mode */ | 377 | /* Set output mode */ |
323 | 378 | ||
324 | rdmsrl(MSR_LX_DF_GLCONFIG, msrval); | 379 | rdmsrl(MSR_LX_GLD_MSR_CONFIG, msrval); |
325 | msrval &= ~DF_CONFIG_OUTPUT_MASK; | 380 | msrval &= ~MSR_LX_GLD_MSR_CONFIG_FMT; |
326 | 381 | ||
327 | if (par->output & OUTPUT_PANEL) { | 382 | if (par->output & OUTPUT_PANEL) { |
328 | msrval |= DF_OUTPUT_PANEL; | 383 | msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_FP; |
329 | 384 | ||
330 | if (par->output & OUTPUT_CRT) | 385 | if (par->output & OUTPUT_CRT) |
331 | msrval |= DF_SIMULTANEOUS_CRT_AND_FP; | 386 | msrval |= MSR_LX_GLD_MSR_CONFIG_FPC; |
332 | else | 387 | else |
333 | msrval &= ~DF_SIMULTANEOUS_CRT_AND_FP; | 388 | msrval &= ~MSR_LX_GLD_MSR_CONFIG_FPC; |
334 | } else { | 389 | } else |
335 | msrval |= DF_OUTPUT_CRT; | 390 | msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_CRT; |
336 | } | ||
337 | 391 | ||
338 | wrmsrl(MSR_LX_DF_GLCONFIG, msrval); | 392 | wrmsrl(MSR_LX_GLD_MSR_CONFIG, msrval); |
339 | 393 | ||
340 | /* Clear the various buffers */ | 394 | /* Clear the various buffers */ |
341 | /* FIXME: Adjust for panning here */ | 395 | /* FIXME: Adjust for panning here */ |
342 | 396 | ||
343 | writel(0, par->dc_regs + DC_FB_START); | 397 | write_dc(par, DC_FB_ST_OFFSET, 0); |
344 | writel(0, par->dc_regs + DC_CB_START); | 398 | write_dc(par, DC_CB_ST_OFFSET, 0); |
345 | writel(0, par->dc_regs + DC_CURSOR_START); | 399 | write_dc(par, DC_CURS_ST_OFFSET, 0); |
346 | 400 | ||
347 | /* FIXME: Add support for interlacing */ | 401 | /* FIXME: Add support for interlacing */ |
348 | /* FIXME: Add support for scaling */ | 402 | /* FIXME: Add support for scaling */ |
349 | 403 | ||
350 | val = readl(par->dc_regs + DC_GENLCK_CTRL); | 404 | val = read_dc(par, DC_GENLK_CTL); |
351 | val &= ~(DC_GC_ALPHA_FLICK_ENABLE | | 405 | val &= ~(DC_GENLK_CTL_ALPHA_FLICK_EN | DC_GENLK_CTL_FLICK_EN | |
352 | DC_GC_FLICKER_FILTER_ENABLE | DC_GC_FLICKER_FILTER_MASK); | 406 | DC_GENLK_CTL_FLICK_SEL_MASK); |
353 | 407 | ||
354 | /* Default scaling params */ | 408 | /* Default scaling params */ |
355 | 409 | ||
356 | writel((0x4000 << 16) | 0x4000, par->dc_regs + DC_GFX_SCALE); | 410 | write_dc(par, DC_GFX_SCALE, (0x4000 << 16) | 0x4000); |
357 | writel(0, par->dc_regs + DC_IRQ_FILT_CTL); | 411 | write_dc(par, DC_IRQ_FILT_CTL, 0); |
358 | writel(val, par->dc_regs + DC_GENLCK_CTRL); | 412 | write_dc(par, DC_GENLK_CTL, val); |
359 | 413 | ||
360 | /* FIXME: Support compression */ | 414 | /* FIXME: Support compression */ |
361 | 415 | ||
362 | if (info->fix.line_length > 4096) | 416 | if (info->fix.line_length > 4096) |
363 | dv = DC_DV_LINE_SIZE_8192; | 417 | dv = DC_DV_CTL_DV_LINE_SIZE_8K; |
364 | else if (info->fix.line_length > 2048) | 418 | else if (info->fix.line_length > 2048) |
365 | dv = DC_DV_LINE_SIZE_4096; | 419 | dv = DC_DV_CTL_DV_LINE_SIZE_4K; |
366 | else if (info->fix.line_length > 1024) | 420 | else if (info->fix.line_length > 1024) |
367 | dv = DC_DV_LINE_SIZE_2048; | 421 | dv = DC_DV_CTL_DV_LINE_SIZE_2K; |
368 | else | 422 | else |
369 | dv = DC_DV_LINE_SIZE_1024; | 423 | dv = DC_DV_CTL_DV_LINE_SIZE_1K; |
370 | 424 | ||
371 | max = info->fix.line_length * info->var.yres; | 425 | max = info->fix.line_length * info->var.yres; |
372 | max = (max + 0x3FF) & 0xFFFFFC00; | 426 | max = (max + 0x3FF) & 0xFFFFFC00; |
373 | 427 | ||
374 | writel(max | DC_DV_TOP_ENABLE, par->dc_regs + DC_DV_TOP); | 428 | write_dc(par, DC_DV_TOP, max | DC_DV_TOP_DV_TOP_EN); |
375 | 429 | ||
376 | val = readl(par->dc_regs + DC_DV_CTL) & ~DC_DV_LINE_SIZE_MASK; | 430 | val = read_dc(par, DC_DV_CTL) & ~DC_DV_CTL_DV_LINE_SIZE; |
377 | writel(val | dv, par->dc_regs + DC_DV_CTL); | 431 | write_dc(par, DC_DV_CTL, val | dv); |
378 | 432 | ||
379 | size = info->var.xres * (info->var.bits_per_pixel >> 3); | 433 | size = info->var.xres * (info->var.bits_per_pixel >> 3); |
380 | 434 | ||
381 | writel(info->fix.line_length >> 3, par->dc_regs + DC_GRAPHICS_PITCH); | 435 | write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3); |
382 | writel((size + 7) >> 3, par->dc_regs + DC_LINE_SIZE); | 436 | write_dc(par, DC_LINE_SIZE, (size + 7) >> 3); |
383 | 437 | ||
384 | /* Set default watermark values */ | 438 | /* Set default watermark values */ |
385 | 439 | ||
386 | rdmsrl(MSR_LX_DC_SPARE, msrval); | 440 | rdmsrl(MSR_LX_SPARE_MSR, msrval); |
387 | 441 | ||
388 | msrval &= ~(DC_SPARE_DISABLE_CFIFO_HGO | DC_SPARE_VFIFO_ARB_SELECT | | 442 | msrval &= ~(MSR_LX_SPARE_MSR_DIS_CFIFO_HGO |
389 | DC_SPARE_LOAD_WM_LPEN_MASK | DC_SPARE_WM_LPEN_OVRD | | 443 | | MSR_LX_SPARE_MSR_VFIFO_ARB_SEL |
390 | DC_SPARE_DISABLE_INIT_VID_PRI | DC_SPARE_DISABLE_VFIFO_WM); | 444 | | MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M |
391 | msrval |= DC_SPARE_DISABLE_VFIFO_WM | DC_SPARE_DISABLE_INIT_VID_PRI; | 445 | | MSR_LX_SPARE_MSR_WM_LPEN_OVRD); |
392 | wrmsrl(MSR_LX_DC_SPARE, msrval); | 446 | msrval |= MSR_LX_SPARE_MSR_DIS_VIFO_WM | |
393 | 447 | MSR_LX_SPARE_MSR_DIS_INIT_V_PRI; | |
394 | gcfg = DC_GCFG_DFLE; /* Display fifo enable */ | 448 | wrmsrl(MSR_LX_SPARE_MSR, msrval); |
395 | gcfg |= 0xB600; /* Set default priority */ | 449 | |
396 | gcfg |= DC_GCFG_FDTY; /* Set the frame dirty mode */ | 450 | gcfg = DC_GENERAL_CFG_DFLE; /* Display fifo enable */ |
397 | 451 | gcfg |= (0x6 << DC_GENERAL_CFG_DFHPSL_SHIFT) | /* default priority */ | |
398 | dcfg = DC_DCFG_VDEN; /* Enable video data */ | 452 | (0xb << DC_GENERAL_CFG_DFHPEL_SHIFT); |
399 | dcfg |= DC_DCFG_GDEN; /* Enable graphics */ | 453 | gcfg |= DC_GENERAL_CFG_FDTY; /* Set the frame dirty mode */ |
400 | dcfg |= DC_DCFG_TGEN; /* Turn on the timing generator */ | 454 | |
401 | dcfg |= DC_DCFG_TRUP; /* Update timings immediately */ | 455 | dcfg = DC_DISPLAY_CFG_VDEN; /* Enable video data */ |
402 | dcfg |= DC_DCFG_PALB; /* Palette bypass in > 8 bpp modes */ | 456 | dcfg |= DC_DISPLAY_CFG_GDEN; /* Enable graphics */ |
403 | dcfg |= DC_DCFG_VISL; | 457 | dcfg |= DC_DISPLAY_CFG_TGEN; /* Turn on the timing generator */ |
404 | dcfg |= DC_DCFG_DCEN; /* Always center the display */ | 458 | dcfg |= DC_DISPLAY_CFG_TRUP; /* Update timings immediately */ |
459 | dcfg |= DC_DISPLAY_CFG_PALB; /* Palette bypass in > 8 bpp modes */ | ||
460 | dcfg |= DC_DISPLAY_CFG_VISL; | ||
461 | dcfg |= DC_DISPLAY_CFG_DCEN; /* Always center the display */ | ||
405 | 462 | ||
406 | /* Set the current BPP mode */ | 463 | /* Set the current BPP mode */ |
407 | 464 | ||
408 | switch (info->var.bits_per_pixel) { | 465 | switch (info->var.bits_per_pixel) { |
409 | case 8: | 466 | case 8: |
410 | dcfg |= DC_DCFG_DISP_MODE_8BPP; | 467 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP; |
411 | break; | 468 | break; |
412 | 469 | ||
413 | case 16: | 470 | case 16: |
414 | dcfg |= DC_DCFG_DISP_MODE_16BPP | DC_DCFG_16BPP; | 471 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP; |
415 | break; | 472 | break; |
416 | 473 | ||
417 | case 32: | 474 | case 32: |
418 | case 24: | 475 | case 24: |
419 | dcfg |= DC_DCFG_DISP_MODE_24BPP; | 476 | dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP; |
420 | break; | 477 | break; |
421 | } | 478 | } |
422 | 479 | ||
@@ -436,35 +493,31 @@ void lx_set_mode(struct fb_info *info) | |||
436 | vblankend = vsyncend + info->var.upper_margin; | 493 | vblankend = vsyncend + info->var.upper_margin; |
437 | vtotal = vblankend; | 494 | vtotal = vblankend; |
438 | 495 | ||
439 | writel((hactive - 1) | ((htotal - 1) << 16), | 496 | write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) | ((htotal - 1) << 16)); |
440 | par->dc_regs + DC_H_ACTIVE_TIMING); | 497 | write_dc(par, DC_H_BLANK_TIMING, |
441 | writel((hblankstart - 1) | ((hblankend - 1) << 16), | 498 | (hblankstart - 1) | ((hblankend - 1) << 16)); |
442 | par->dc_regs + DC_H_BLANK_TIMING); | 499 | write_dc(par, DC_H_SYNC_TIMING, |
443 | writel((hsyncstart - 1) | ((hsyncend - 1) << 16), | 500 | (hsyncstart - 1) | ((hsyncend - 1) << 16)); |
444 | par->dc_regs + DC_H_SYNC_TIMING); | ||
445 | |||
446 | writel((vactive - 1) | ((vtotal - 1) << 16), | ||
447 | par->dc_regs + DC_V_ACTIVE_TIMING); | ||
448 | 501 | ||
449 | writel((vblankstart - 1) | ((vblankend - 1) << 16), | 502 | write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) | ((vtotal - 1) << 16)); |
450 | par->dc_regs + DC_V_BLANK_TIMING); | 503 | write_dc(par, DC_V_BLANK_TIMING, |
504 | (vblankstart - 1) | ((vblankend - 1) << 16)); | ||
505 | write_dc(par, DC_V_SYNC_TIMING, | ||
506 | (vsyncstart - 1) | ((vsyncend - 1) << 16)); | ||
451 | 507 | ||
452 | writel((vsyncstart - 1) | ((vsyncend - 1) << 16), | 508 | write_dc(par, DC_FB_ACTIVE, |
453 | par->dc_regs + DC_V_SYNC_TIMING); | 509 | (info->var.xres - 1) << 16 | (info->var.yres - 1)); |
454 | |||
455 | writel( (info->var.xres - 1) << 16 | (info->var.yres - 1), | ||
456 | par->dc_regs + DC_FB_ACTIVE); | ||
457 | 510 | ||
458 | /* And re-enable the graphics output */ | 511 | /* And re-enable the graphics output */ |
459 | lx_graphics_enable(info); | 512 | lx_graphics_enable(info); |
460 | 513 | ||
461 | /* Write the two main configuration registers */ | 514 | /* Write the two main configuration registers */ |
462 | writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); | 515 | write_dc(par, DC_DISPLAY_CFG, dcfg); |
463 | writel(0, par->dc_regs + DC_ARB_CFG); | 516 | write_dc(par, DC_ARB_CFG, 0); |
464 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | 517 | write_dc(par, DC_GENERAL_CFG, gcfg); |
465 | 518 | ||
466 | /* Lock the DC registers */ | 519 | /* Lock the DC registers */ |
467 | writel(0, par->dc_regs + DC_UNLOCK); | 520 | write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); |
468 | } | 521 | } |
469 | 522 | ||
470 | void lx_set_palette_reg(struct fb_info *info, unsigned regno, | 523 | void lx_set_palette_reg(struct fb_info *info, unsigned regno, |
@@ -479,58 +532,310 @@ void lx_set_palette_reg(struct fb_info *info, unsigned regno, | |||
479 | val |= (green) & 0x00ff00; | 532 | val |= (green) & 0x00ff00; |
480 | val |= (blue >> 8) & 0x0000ff; | 533 | val |= (blue >> 8) & 0x0000ff; |
481 | 534 | ||
482 | writel(regno, par->dc_regs + DC_PAL_ADDRESS); | 535 | write_dc(par, DC_PAL_ADDRESS, regno); |
483 | writel(val, par->dc_regs + DC_PAL_DATA); | 536 | write_dc(par, DC_PAL_DATA, val); |
484 | } | 537 | } |
485 | 538 | ||
486 | int lx_blank_display(struct fb_info *info, int blank_mode) | 539 | int lx_blank_display(struct fb_info *info, int blank_mode) |
487 | { | 540 | { |
488 | struct lxfb_par *par = info->par; | 541 | struct lxfb_par *par = info->par; |
489 | u32 dcfg, fp_pm; | 542 | u32 dcfg, fp_pm; |
490 | int blank, hsync, vsync; | 543 | int blank, hsync, vsync, crt; |
491 | 544 | ||
492 | /* CRT power saving modes. */ | 545 | /* CRT power saving modes. */ |
493 | switch (blank_mode) { | 546 | switch (blank_mode) { |
494 | case FB_BLANK_UNBLANK: | 547 | case FB_BLANK_UNBLANK: |
495 | blank = 0; hsync = 1; vsync = 1; | 548 | blank = 0; hsync = 1; vsync = 1; crt = 1; |
496 | break; | 549 | break; |
497 | case FB_BLANK_NORMAL: | 550 | case FB_BLANK_NORMAL: |
498 | blank = 1; hsync = 1; vsync = 1; | 551 | blank = 1; hsync = 1; vsync = 1; crt = 1; |
499 | break; | 552 | break; |
500 | case FB_BLANK_VSYNC_SUSPEND: | 553 | case FB_BLANK_VSYNC_SUSPEND: |
501 | blank = 1; hsync = 1; vsync = 0; | 554 | blank = 1; hsync = 1; vsync = 0; crt = 1; |
502 | break; | 555 | break; |
503 | case FB_BLANK_HSYNC_SUSPEND: | 556 | case FB_BLANK_HSYNC_SUSPEND: |
504 | blank = 1; hsync = 0; vsync = 1; | 557 | blank = 1; hsync = 0; vsync = 1; crt = 1; |
505 | break; | 558 | break; |
506 | case FB_BLANK_POWERDOWN: | 559 | case FB_BLANK_POWERDOWN: |
507 | blank = 1; hsync = 0; vsync = 0; | 560 | blank = 1; hsync = 0; vsync = 0; crt = 0; |
508 | break; | 561 | break; |
509 | default: | 562 | default: |
510 | return -EINVAL; | 563 | return -EINVAL; |
511 | } | 564 | } |
512 | 565 | ||
513 | dcfg = readl(par->df_regs + DF_DISPLAY_CFG); | 566 | dcfg = read_vp(par, VP_DCFG); |
514 | dcfg &= ~(DF_DCFG_DAC_BL_EN | 567 | dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN | |
515 | | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN); | 568 | VP_DCFG_CRT_EN); |
516 | if (!blank) | 569 | if (!blank) |
517 | dcfg |= DF_DCFG_DAC_BL_EN; | 570 | dcfg |= VP_DCFG_DAC_BL_EN; |
518 | if (hsync) | 571 | if (hsync) |
519 | dcfg |= DF_DCFG_HSYNC_EN; | 572 | dcfg |= VP_DCFG_HSYNC_EN; |
520 | if (vsync) | 573 | if (vsync) |
521 | dcfg |= DF_DCFG_VSYNC_EN; | 574 | dcfg |= VP_DCFG_VSYNC_EN; |
522 | writel(dcfg, par->df_regs + DF_DISPLAY_CFG); | 575 | if (crt) |
576 | dcfg |= VP_DCFG_CRT_EN; | ||
577 | write_vp(par, VP_DCFG, dcfg); | ||
523 | 578 | ||
524 | /* Power on/off flat panel */ | 579 | /* Power on/off flat panel */ |
525 | 580 | ||
526 | if (par->output & OUTPUT_PANEL) { | 581 | if (par->output & OUTPUT_PANEL) { |
527 | fp_pm = readl(par->df_regs + DF_FP_PM); | 582 | fp_pm = read_fp(par, FP_PM); |
528 | if (blank_mode == FB_BLANK_POWERDOWN) | 583 | if (blank_mode == FB_BLANK_POWERDOWN) |
529 | fp_pm &= ~DF_FP_PM_P; | 584 | fp_pm &= ~FP_PM_P; |
530 | else | 585 | else |
531 | fp_pm |= DF_FP_PM_P; | 586 | fp_pm |= FP_PM_P; |
532 | writel(fp_pm, par->df_regs + DF_FP_PM); | 587 | write_fp(par, FP_PM, fp_pm); |
533 | } | 588 | } |
534 | 589 | ||
535 | return 0; | 590 | return 0; |
536 | } | 591 | } |
592 | |||
593 | #ifdef CONFIG_PM | ||
594 | |||
595 | static void lx_save_regs(struct lxfb_par *par) | ||
596 | { | ||
597 | uint32_t filt; | ||
598 | int i; | ||
599 | |||
600 | /* wait for the BLT engine to stop being busy */ | ||
601 | do { | ||
602 | i = read_gp(par, GP_BLT_STATUS); | ||
603 | } while ((i & GP_BLT_STATUS_PB) || !(i & GP_BLT_STATUS_CE)); | ||
604 | |||
605 | /* save MSRs */ | ||
606 | rdmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel); | ||
607 | rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll); | ||
608 | rdmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg); | ||
609 | rdmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare); | ||
610 | |||
611 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); | ||
612 | |||
613 | /* save registers */ | ||
614 | memcpy(par->gp, par->gp_regs, sizeof(par->gp)); | ||
615 | memcpy(par->dc, par->dc_regs, sizeof(par->dc)); | ||
616 | memcpy(par->vp, par->vp_regs, sizeof(par->vp)); | ||
617 | memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp)); | ||
618 | |||
619 | /* save the palette */ | ||
620 | write_dc(par, DC_PAL_ADDRESS, 0); | ||
621 | for (i = 0; i < ARRAY_SIZE(par->pal); i++) | ||
622 | par->pal[i] = read_dc(par, DC_PAL_DATA); | ||
623 | |||
624 | /* save the horizontal filter coefficients */ | ||
625 | filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL; | ||
626 | for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) { | ||
627 | write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i); | ||
628 | par->hcoeff[i] = read_dc(par, DC_FILT_COEFF1); | ||
629 | par->hcoeff[i + 1] = read_dc(par, DC_FILT_COEFF2); | ||
630 | } | ||
631 | |||
632 | /* save the vertical filter coefficients */ | ||
633 | filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL; | ||
634 | for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) { | ||
635 | write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i); | ||
636 | par->vcoeff[i] = read_dc(par, DC_FILT_COEFF1); | ||
637 | } | ||
638 | |||
639 | /* save video coeff ram */ | ||
640 | memcpy(par->vp_coeff, par->vp_regs + VP_VCR, sizeof(par->vp_coeff)); | ||
641 | } | ||
642 | |||
643 | static void lx_restore_gfx_proc(struct lxfb_par *par) | ||
644 | { | ||
645 | int i; | ||
646 | |||
647 | /* a bunch of registers require GP_RASTER_MODE to be set first */ | ||
648 | write_gp(par, GP_RASTER_MODE, par->gp[GP_RASTER_MODE]); | ||
649 | |||
650 | for (i = 0; i < ARRAY_SIZE(par->gp); i++) { | ||
651 | switch (i) { | ||
652 | case GP_RASTER_MODE: | ||
653 | case GP_VECTOR_MODE: | ||
654 | case GP_BLT_MODE: | ||
655 | case GP_BLT_STATUS: | ||
656 | case GP_HST_SRC: | ||
657 | /* FIXME: restore LUT data */ | ||
658 | case GP_LUT_INDEX: | ||
659 | case GP_LUT_DATA: | ||
660 | /* don't restore these registers */ | ||
661 | break; | ||
662 | |||
663 | default: | ||
664 | write_gp(par, i, par->gp[i]); | ||
665 | } | ||
666 | } | ||
667 | } | ||
668 | |||
669 | static void lx_restore_display_ctlr(struct lxfb_par *par) | ||
670 | { | ||
671 | uint32_t filt; | ||
672 | int i; | ||
673 | |||
674 | wrmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare); | ||
675 | |||
676 | for (i = 0; i < ARRAY_SIZE(par->dc); i++) { | ||
677 | switch (i) { | ||
678 | case DC_UNLOCK: | ||
679 | /* unlock the DC; runs first */ | ||
680 | write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); | ||
681 | break; | ||
682 | |||
683 | case DC_GENERAL_CFG: | ||
684 | case DC_DISPLAY_CFG: | ||
685 | /* disable all while restoring */ | ||
686 | write_dc(par, i, 0); | ||
687 | break; | ||
688 | |||
689 | case DC_DV_CTL: | ||
690 | /* set all ram to dirty */ | ||
691 | write_dc(par, i, par->dc[i] | DC_DV_CTL_CLEAR_DV_RAM); | ||
692 | |||
693 | case DC_RSVD_1: | ||
694 | case DC_RSVD_2: | ||
695 | case DC_RSVD_3: | ||
696 | case DC_LINE_CNT: | ||
697 | case DC_PAL_ADDRESS: | ||
698 | case DC_PAL_DATA: | ||
699 | case DC_DFIFO_DIAG: | ||
700 | case DC_CFIFO_DIAG: | ||
701 | case DC_FILT_COEFF1: | ||
702 | case DC_FILT_COEFF2: | ||
703 | case DC_RSVD_4: | ||
704 | case DC_RSVD_5: | ||
705 | /* don't restore these registers */ | ||
706 | break; | ||
707 | |||
708 | default: | ||
709 | write_dc(par, i, par->dc[i]); | ||
710 | } | ||
711 | } | ||
712 | |||
713 | /* restore the palette */ | ||
714 | write_dc(par, DC_PAL_ADDRESS, 0); | ||
715 | for (i = 0; i < ARRAY_SIZE(par->pal); i++) | ||
716 | write_dc(par, DC_PAL_DATA, par->pal[i]); | ||
717 | |||
718 | /* restore the horizontal filter coefficients */ | ||
719 | filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL; | ||
720 | for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) { | ||
721 | write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i); | ||
722 | write_dc(par, DC_FILT_COEFF1, par->hcoeff[i]); | ||
723 | write_dc(par, DC_FILT_COEFF2, par->hcoeff[i + 1]); | ||
724 | } | ||
725 | |||
726 | /* restore the vertical filter coefficients */ | ||
727 | filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL; | ||
728 | for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) { | ||
729 | write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i); | ||
730 | write_dc(par, DC_FILT_COEFF1, par->vcoeff[i]); | ||
731 | } | ||
732 | } | ||
733 | |||
734 | static void lx_restore_video_proc(struct lxfb_par *par) | ||
735 | { | ||
736 | int i; | ||
737 | |||
738 | wrmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg); | ||
739 | wrmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel); | ||
740 | |||
741 | for (i = 0; i < ARRAY_SIZE(par->vp); i++) { | ||
742 | switch (i) { | ||
743 | case VP_VCFG: | ||
744 | case VP_DCFG: | ||
745 | case VP_PAR: | ||
746 | case VP_PDR: | ||
747 | case VP_CCS: | ||
748 | case VP_RSVD_0: | ||
749 | /* case VP_VDC: */ /* why should this not be restored? */ | ||
750 | case VP_RSVD_1: | ||
751 | case VP_CRC32: | ||
752 | /* don't restore these registers */ | ||
753 | break; | ||
754 | |||
755 | default: | ||
756 | write_vp(par, i, par->vp[i]); | ||
757 | } | ||
758 | } | ||
759 | |||
760 | /* restore video coeff ram */ | ||
761 | memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff)); | ||
762 | } | ||
763 | |||
764 | static void lx_restore_regs(struct lxfb_par *par) | ||
765 | { | ||
766 | int i; | ||
767 | |||
768 | lx_set_dotpll((u32) (par->msr.dotpll >> 32)); | ||
769 | lx_restore_gfx_proc(par); | ||
770 | lx_restore_display_ctlr(par); | ||
771 | lx_restore_video_proc(par); | ||
772 | |||
773 | /* Flat Panel */ | ||
774 | for (i = 0; i < ARRAY_SIZE(par->fp); i++) { | ||
775 | switch (i) { | ||
776 | case FP_PM: | ||
777 | case FP_RSVD_0: | ||
778 | case FP_RSVD_1: | ||
779 | case FP_RSVD_2: | ||
780 | case FP_RSVD_3: | ||
781 | case FP_RSVD_4: | ||
782 | /* don't restore these registers */ | ||
783 | break; | ||
784 | |||
785 | default: | ||
786 | write_fp(par, i, par->fp[i]); | ||
787 | } | ||
788 | } | ||
789 | |||
790 | /* control the panel */ | ||
791 | if (par->fp[FP_PM] & FP_PM_P) { | ||
792 | /* power on the panel if not already power{ed,ing} on */ | ||
793 | if (!(read_fp(par, FP_PM) & | ||
794 | (FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP))) | ||
795 | write_fp(par, FP_PM, par->fp[FP_PM]); | ||
796 | } else { | ||
797 | /* power down the panel if not already power{ed,ing} down */ | ||
798 | if (!(read_fp(par, FP_PM) & | ||
799 | (FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN))) | ||
800 | write_fp(par, FP_PM, par->fp[FP_PM]); | ||
801 | } | ||
802 | |||
803 | /* turn everything on */ | ||
804 | write_vp(par, VP_VCFG, par->vp[VP_VCFG]); | ||
805 | write_vp(par, VP_DCFG, par->vp[VP_DCFG]); | ||
806 | write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]); | ||
807 | /* do this last; it will enable the FIFO load */ | ||
808 | write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]); | ||
809 | |||
810 | /* lock the door behind us */ | ||
811 | write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); | ||
812 | } | ||
813 | |||
814 | int lx_powerdown(struct fb_info *info) | ||
815 | { | ||
816 | struct lxfb_par *par = info->par; | ||
817 | |||
818 | if (par->powered_down) | ||
819 | return 0; | ||
820 | |||
821 | lx_save_regs(par); | ||
822 | lx_graphics_disable(info); | ||
823 | |||
824 | par->powered_down = 1; | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | int lx_powerup(struct fb_info *info) | ||
829 | { | ||
830 | struct lxfb_par *par = info->par; | ||
831 | |||
832 | if (!par->powered_down) | ||
833 | return 0; | ||
834 | |||
835 | lx_restore_regs(par); | ||
836 | |||
837 | par->powered_down = 0; | ||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | #endif | ||