cleaning up olpc patch 1
[openwrt/openwrt.git] / target / linux / olpc / files / drivers / video / geode / suspend_gx.c
1 #include <linux/fb.h>
2 #include <asm/io.h>
3 #include <asm/msr.h>
4
5 #include "geodefb.h"
6 #include "video_gx.h"
7
8 void gx_set_dotpll(struct fb_info *info, struct geoderegs *regs)
9 {
10 int timeout = 1000;
11
12 u64 rstpll, dotpll;
13
14 rdmsrl(MSR_GLCP_SYS_RSTPLL, rstpll);
15 rdmsrl(MSR_GLCP_DOTPLL, dotpll);
16
17 dotpll &= 0x00000000ffffffffull;
18 dotpll |= regs->msr.dotpll & 0xffffffff00000000ull;
19
20 dotpll |= MSR_GLCP_DOTPLL_DOTRESET;
21 dotpll &= ~MSR_GLCP_DOTPLL_BYPASS;
22
23 wrmsrl(MSR_GLCP_DOTPLL, dotpll);
24
25 rstpll |= (regs->msr.rstpll &
26 ( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 |
27 MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 |
28 MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3));
29
30 wrmsrl(MSR_GLCP_SYS_RSTPLL, rstpll);
31 dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET);
32 wrmsrl(MSR_GLCP_DOTPLL, dotpll);
33
34 do {
35 rdmsrl(MSR_GLCP_DOTPLL, dotpll);
36 } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
37 }
38
39 /* FIXME: Make sure nothing is read to clear */
40
41 void gx_save_regs(struct fb_info *info, struct geoderegs *regs)
42 {
43 struct geodefb_par *par = info->par;
44 int i;
45
46 /* Wait for the BLT engine to stop being busy */
47 while(readl(par->gp_regs + 0x44) & 0x05);
48
49 rdmsrl(GX_VP_MSR_PAD_SELECT, regs->msr.padsel);
50 rdmsrl(MSR_GLCP_DOTPLL, regs->msr.dotpll);
51 rdmsrl(MSR_GLCP_SYS_RSTPLL, regs->msr.rstpll);
52
53 writel(0x4758, par->dc_regs + 0x00);
54
55 memcpy(regs->gp.b, par->gp_regs, GP_REG_SIZE);
56 memcpy(regs->dc.b, par->dc_regs, DC_REG_SIZE);
57 memcpy(regs->vp.b, par->vid_regs, VP_REG_SIZE);
58 memcpy(regs->fp.b, par->vid_regs + 0x400, FP_REG_SIZE);
59
60 /* Save the palettes */
61 writel(0, par->dc_regs + 0x70);
62
63 for(i = 0; i < DC_PAL_SIZE; i++)
64 regs->pal[i] = readl(par->dc_regs + 0x74);
65
66 writel(0, par->vid_regs + 0x38);
67
68 for(i = 0; i < 0xFF; i++)
69 regs->gamma[i] = readl(par->vid_regs + 0x40);
70 }
71
72 void gx_restore_regs(struct fb_info *info, struct geoderegs *regs)
73 {
74 struct geodefb_par *par = info->par;
75 u32 val, i;
76
77 /* DOTPLL */
78 gx_set_dotpll(info, regs);
79
80 /* GP */
81
82 writel(regs->gp.r.dst_offset, par->gp_regs + 0x00);
83 writel(regs->gp.r.src_offset, par->gp_regs + 0x04);
84 writel(regs->gp.r.stride, par->gp_regs + 0x08);
85 writel(regs->gp.r.wid_height, par->gp_regs + 0x0C);
86 writel(regs->gp.r.src_color_fg, par->gp_regs + 0x10);
87 writel(regs->gp.r.src_color_bg, par->gp_regs + 0x14);
88 writel(regs->gp.r.pat_color_0, par->gp_regs + 0x18);
89 writel(regs->gp.r.pat_color_1, par->gp_regs + 0x1C);
90 writel(regs->gp.r.pat_color_2, par->gp_regs + 0x20);
91 writel(regs->gp.r.pat_color_3, par->gp_regs + 0x24);
92 writel(regs->gp.r.pat_color_4, par->gp_regs + 0x28);
93 writel(regs->gp.r.pat_color_5, par->gp_regs + 0x2C);
94 writel(regs->gp.r.pat_data_0, par->gp_regs + 0x30);
95 writel(regs->gp.r.pat_data_1, par->gp_regs + 0x34);
96
97 /* Don't write the raster / vector / blt mode regs */
98 /* status register is read only */
99
100 writel(regs->gp.r.hst_src, par->gp_regs + 0x48);
101 writel(regs->gp.r.base_offset, par->gp_regs + 0x4c);
102
103 /* DC */
104
105 /* Write the unlock value */
106 writel(0x4758, par->dc_regs + 0x00);
107
108 writel(0, par->dc_regs + 0x70);
109
110 for(i = 0; i < DC_PAL_SIZE; i++)
111 writel(regs->pal[i], par->dc_regs + 0x74);
112
113 /* Write the gcfg register without the enables */
114 writel(regs->dc.r.gcfg & ~0x0F, par->dc_regs + 0x04);
115
116 /* Write the vcfg register without the enables */
117 writel(regs->dc.r.dcfg & ~0x19, par->dc_regs + 0x08);
118
119 /* Write the rest of the active registers */
120
121 writel(regs->dc.r.fb_st_offset, par->dc_regs + 0x10);
122 writel(regs->dc.r.cb_st_offset, par->dc_regs + 0x14);
123 writel(regs->dc.r.curs_st_offset, par->dc_regs + 0x18);
124 writel(regs->dc.r.icon_st_offset, par->dc_regs + 0x1C);
125 writel(regs->dc.r.vid_y_st_offset, par->dc_regs + 0x20);
126 writel(regs->dc.r.vid_u_st_offset, par->dc_regs + 0x24);
127 writel(regs->dc.r.vid_v_st_offset, par->dc_regs + 0x28);
128 writel(regs->dc.r.line_size, par->dc_regs + 0x30);
129 writel(regs->dc.r.gfx_pitch, par->dc_regs + 0x34);
130 writel(regs->dc.r.vid_yuv_pitch, par->dc_regs + 0x38);
131 writel(regs->dc.r.h_active_timing, par->dc_regs + 0x40);
132 writel(regs->dc.r.h_blank_timing, par->dc_regs + 0x44);
133 writel(regs->dc.r.h_sync_timing, par->dc_regs + 0x48);
134 writel(regs->dc.r.v_active_timing, par->dc_regs + 0x50);
135 writel(regs->dc.r.v_blank_timing, par->dc_regs + 0x54);
136 writel(regs->dc.r.v_sync_timing, par->dc_regs + 0x58);
137 writel(regs->dc.r.dc_cursor_x, par->dc_regs + 0x60);
138 writel(regs->dc.r.dc_cursor_y, par->dc_regs + 0x64);
139 writel(regs->dc.r.dc_icon_x, par->dc_regs + 0x68);
140
141 /* Don't write the line_cnt or diag registers */
142
143 writel(regs->dc.r.dc_vid_ds_delta, par->dc_regs + 0x80);
144 writel(regs->dc.r.gliu0_mem_offset, par->dc_regs + 0x84);
145 writel(regs->dc.r.dv_acc, par->dc_regs + 0x8C);
146
147 /* VP */
148
149 /* MSR */
150 wrmsrl(GX_VP_MSR_PAD_SELECT, regs->msr.padsel);
151
152 writel(0, par->vid_regs + 0x38);
153
154 for(i = 0; i < 0xFF; i++)
155 writel((u32) regs->gamma[i], par->vid_regs + 0x40);
156
157 /* Don't enable video yet */
158 writel((u32) regs->vp.r.vcfg & ~0x01, par->vid_regs + 0x00);
159
160 /* Don't enable the CRT yet */
161 writel((u32) regs->vp.r.dcfg & ~0x0F, par->vid_regs + 0x08);
162
163 /* Write the rest of the VP registers */
164
165 writel((u32) regs->vp.r.vx, par->vid_regs + 0x10);
166 writel((u32) regs->vp.r.vy, par->vid_regs + 0x18);
167 writel((u32) regs->vp.r.vs, par->vid_regs + 0x20);
168 writel((u32) regs->vp.r.vck, par->vid_regs + 0x28);
169 writel((u32) regs->vp.r.vcm, par->vid_regs + 0x30);
170 writel((u32) regs->vp.r.misc, par->vid_regs + 0x50);
171 writel((u32) regs->vp.r.ccs, par->vid_regs + 0x58);
172 writel((u32) regs->vp.r.vdc, par->vid_regs + 0x78);
173 writel((u32) regs->vp.r.vco, par->vid_regs + 0x80);
174 writel((u32) regs->vp.r.crc, par->vid_regs + 0x88);
175 writel((u32) regs->vp.r.vde, par->vid_regs + 0x98);
176 writel((u32) regs->vp.r.cck, par->vid_regs + 0xA0);
177 writel((u32) regs->vp.r.ccm, par->vid_regs + 0xA8);
178 writel((u32) regs->vp.r.cc1, par->vid_regs + 0xB0);
179 writel((u32) regs->vp.r.cc2, par->vid_regs + 0xB8);
180 writel((u32) regs->vp.r.a1x, par->vid_regs + 0xC0);
181 writel((u32) regs->vp.r.a1y, par->vid_regs + 0xC8);
182 writel((u32) regs->vp.r.a1c, par->vid_regs + 0xD0);
183 writel((u32) regs->vp.r.a1t, par->vid_regs + 0xD8);
184 writel((u32) regs->vp.r.a2x, par->vid_regs + 0xE0);
185 writel((u32) regs->vp.r.a2y, par->vid_regs + 0xE8);
186 writel((u32) regs->vp.r.a2c, par->vid_regs + 0xF0);
187 writel((u32) regs->vp.r.a2t, par->vid_regs + 0xF8);
188 writel((u32) regs->vp.r.a3x, par->vid_regs + 0x100);
189 writel((u32) regs->vp.r.a3y, par->vid_regs + 0x108);
190 writel((u32) regs->vp.r.a3c, par->vid_regs + 0x110);
191 writel((u32) regs->vp.r.a3t, par->vid_regs + 0x118);
192 writel((u32) regs->vp.r.vrr, par->vid_regs + 0x120);
193
194
195 /* FP registers */
196
197 writel((u32) regs->fp.r.pt1, par->vid_regs + 0x400);
198 writel((u32) regs->fp.r.pt2, par->vid_regs + 0x408);
199
200 writel((u32) regs->fp.r.dfc, par->vid_regs + 0x418);
201 writel(regs->fp.r.blfsr, par->vid_regs + 0x420);
202 writel(regs->fp.r.rlfsr, par->vid_regs + 0x428);
203 writel(regs->fp.r.fmi, par->vid_regs + 0x430);
204 writel(regs->fp.r.fmd, par->vid_regs + 0x438);
205 writel(regs->fp.r.dca, par->vid_regs + 0x448);
206 writel(regs->fp.r.dmd, par->vid_regs + 0x450);
207 writel(regs->fp.r.crc, par->vid_regs + 0x458);
208 writel(regs->fp.r.fbb, par->vid_regs + 0x460);
209
210 /* Final enables */
211
212 val = readl(par->vid_regs + 0x410);
213
214 /* Control the panel */
215 if (regs->fp.r.pm & (1 << 24)) {
216
217 if (!(val & 0x09))
218 writel(regs->fp.r.pm, par->vid_regs + 0x410);
219 }
220 else {
221 if (!(val & 0x05))
222 writel(regs->fp.r.pm, par->vid_regs + 0x410);
223 }
224
225 /* Turn everything on */
226
227 writel(regs->dc.r.gcfg, par->dc_regs + 0x04);
228 writel((u32) regs->vp.r.vcfg, par->vid_regs + 0x00);
229 writel((u32) regs->vp.r.dcfg, par->vid_regs + 0x08);
230 writel(regs->dc.r.dcfg, par->dc_regs + 0x08);
231 }
232
233
234 #ifdef DEBUG
235
236 void dump_regs(struct fb_info *info, int mode) {
237
238 struct geodefb_par *par = info->par;
239 u32 val;
240 int i;
241
242 if (mode == 0) {
243 for(i = 0; i < GP_REG_SIZE; i += 4) {
244 val = readl(par->gp_regs + i);
245 }
246 }
247
248 if (mode == 1) {
249 writel(0x4758, par->dc_regs + 0x00);
250
251 for(i = 0; i < DC_REG_SIZE; i += 4) {
252 val = readl(par->dc_regs + i);
253 printk("DC%x: %x\n", i, val);
254 }
255 }
256
257 if (mode == 2) {
258 for(i = 0; i < VP_REG_SIZE; i += 8) {
259 val = readl(par->vid_regs + i);
260 printk("VP%x: %x\n", i, val);
261 }
262 }
263
264 if (mode == 3) {
265 for(i = 0; i < FP_REG_SIZE; i += 8) {
266 val = readl(par->vid_regs + 0x400 + i);
267 printk("FP%x: %x\n", i, val);
268 }
269 }
270 }
271
272 #endif