Update olpc target kernel to 2.26.5.
[openwrt.git] / target / linux / olpc / files-2.6.23 / 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