Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vgastate.c
Go to the documentation of this file.
1 /*
2  * linux/drivers/video/vgastate.c -- VGA state save/restore
3  *
4  * Copyright 2002 James Simmons
5  *
6  * Copyright history from vga16fb.c:
7  * Copyright 1999 Ben Pfaff and Petr Vandrovec
8  * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
9  * Based on VESA framebuffer (c) 1998 Gerd Knorr
10  *
11  * This file is subject to the terms and conditions of the GNU General
12  * Public License. See the file COPYING in the main directory of this
13  * archive for more details.
14  *
15  */
16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/fb.h>
19 #include <linux/vmalloc.h>
20 #include <video/vga.h>
21 
22 struct regstate {
32 };
33 
34 static inline unsigned char vga_rcrtcs(void __iomem *regbase, unsigned short iobase,
35  unsigned char reg)
36 {
37  vga_w(regbase, iobase + 0x4, reg);
38  return vga_r(regbase, iobase + 0x5);
39 }
40 
41 static inline void vga_wcrtcs(void __iomem *regbase, unsigned short iobase,
42  unsigned char reg, unsigned char val)
43 {
44  vga_w(regbase, iobase + 0x4, reg);
45  vga_w(regbase, iobase + 0x5, val);
46 }
47 
48 static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
49 {
50  struct regstate *saved = (struct regstate *) state->vidstate;
51  int i;
52  u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4;
53  unsigned short iobase;
54 
55  /* if in graphics mode, no need to save */
56  misc = vga_r(state->vgabase, VGA_MIS_R);
57  iobase = (misc & 1) ? 0x3d0 : 0x3b0;
58 
59  vga_r(state->vgabase, iobase + 0xa);
60  vga_w(state->vgabase, VGA_ATT_W, 0x00);
61  attr10 = vga_rattr(state->vgabase, 0x10);
62  vga_r(state->vgabase, iobase + 0xa);
63  vga_w(state->vgabase, VGA_ATT_W, 0x20);
64 
65  if (attr10 & 1)
66  return;
67 
68  /* save regs */
69  gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
70  gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
71  gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
72  seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
73  seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
74 
75  /* blank screen */
76  seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
77  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
78  vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
79  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
80 
81  /* save font at plane 2 */
82  if (state->flags & VGA_SAVE_FONT0) {
83  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
84  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
85  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
86  vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
87  vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
88  for (i = 0; i < 4 * 8192; i++)
89  saved->vga_font0[i] = vga_r(fbbase, i);
90  }
91 
92  /* save font at plane 3 */
93  if (state->flags & VGA_SAVE_FONT1) {
94  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
95  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
96  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
97  vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
98  vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
99  for (i = 0; i < state->memsize; i++)
100  saved->vga_font1[i] = vga_r(fbbase, i);
101  }
102 
103  /* save font at plane 0/1 */
104  if (state->flags & VGA_SAVE_TEXT) {
105  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
106  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
107  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
108  vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
109  vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
110  for (i = 0; i < 8192; i++)
111  saved->vga_text[i] = vga_r(fbbase, i);
112 
113  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
114  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
115  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
116  vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
117  vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
118  for (i = 0; i < 8192; i++)
119  saved->vga_text[8192+i] = vga_r(fbbase + 2 * 8192, i);
120  }
121 
122  /* restore regs */
123  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
124  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
125 
126  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
127  vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
128  vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
129 
130  /* unblank screen */
131  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
132  vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
133  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
134 
135  vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
136 }
137 
138 static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
139 {
140  struct regstate *saved = (struct regstate *) state->vidstate;
141  int i;
142  u8 gr1, gr3, gr4, gr5, gr6, gr8;
143  u8 seq1, seq2, seq4;
144 
145  /* save regs */
146  gr1 = vga_rgfx(state->vgabase, VGA_GFX_SR_ENABLE);
147  gr3 = vga_rgfx(state->vgabase, VGA_GFX_DATA_ROTATE);
148  gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ);
149  gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE);
150  gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC);
151  gr8 = vga_rgfx(state->vgabase, VGA_GFX_BIT_MASK);
152  seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE);
153  seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE);
154 
155  /* blank screen */
156  seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
157  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
158  vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
159  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
160 
161  if (state->depth == 4) {
162  vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, 0x0);
163  vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff);
164  vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00);
165  }
166 
167  /* restore font at plane 2 */
168  if (state->flags & VGA_SAVE_FONT0) {
169  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
170  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
171  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
172  vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
173  vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
174  for (i = 0; i < 4 * 8192; i++)
175  vga_w(fbbase, i, saved->vga_font0[i]);
176  }
177 
178  /* restore font at plane 3 */
179  if (state->flags & VGA_SAVE_FONT1) {
180  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
181  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
182  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
183  vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
184  vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
185  for (i = 0; i < state->memsize; i++)
186  vga_w(fbbase, i, saved->vga_font1[i]);
187  }
188 
189  /* restore font at plane 0/1 */
190  if (state->flags & VGA_SAVE_TEXT) {
191  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
192  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
193  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
194  vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
195  vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
196  for (i = 0; i < 8192; i++)
197  vga_w(fbbase, i, saved->vga_text[i]);
198 
199  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
200  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
201  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
202  vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
203  vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
204  for (i = 0; i < 8192; i++)
205  vga_w(fbbase, i, saved->vga_text[8192+i]);
206  }
207 
208  /* unblank screen */
209  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
210  vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
211  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
212 
213  /* restore regs */
214  vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, gr1);
215  vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, gr3);
216  vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4);
217  vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5);
218  vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6);
219  vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, gr8);
220 
221  vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
222  vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2);
223  vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
224 }
225 
226 static void save_vga_mode(struct vgastate *state)
227 {
228  struct regstate *saved = (struct regstate *) state->vidstate;
229  unsigned short iobase;
230  int i;
231 
232  saved->misc = vga_r(state->vgabase, VGA_MIS_R);
233  if (saved->misc & 1)
234  iobase = 0x3d0;
235  else
236  iobase = 0x3b0;
237 
238  for (i = 0; i < state->num_crtc; i++)
239  saved->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i);
240 
241  vga_r(state->vgabase, iobase + 0xa);
242  vga_w(state->vgabase, VGA_ATT_W, 0x00);
243  for (i = 0; i < state->num_attr; i++) {
244  vga_r(state->vgabase, iobase + 0xa);
245  saved->attr[i] = vga_rattr(state->vgabase, i);
246  }
247  vga_r(state->vgabase, iobase + 0xa);
248  vga_w(state->vgabase, VGA_ATT_W, 0x20);
249 
250  for (i = 0; i < state->num_gfx; i++)
251  saved->gfx[i] = vga_rgfx(state->vgabase, i);
252 
253  for (i = 0; i < state->num_seq; i++)
254  saved->seq[i] = vga_rseq(state->vgabase, i);
255 }
256 
257 static void restore_vga_mode(struct vgastate *state)
258 {
259  struct regstate *saved = (struct regstate *) state->vidstate;
260  unsigned short iobase;
261  int i;
262 
263  vga_w(state->vgabase, VGA_MIS_W, saved->misc);
264 
265  if (saved->misc & 1)
266  iobase = 0x3d0;
267  else
268  iobase = 0x3b0;
269 
270  /* turn off display */
271  vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
272  saved->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
273 
274  /* disable sequencer */
275  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
276 
277  /* enable palette addressing */
278  vga_r(state->vgabase, iobase + 0xa);
279  vga_w(state->vgabase, VGA_ATT_W, 0x00);
280 
281  for (i = 2; i < state->num_seq; i++)
282  vga_wseq(state->vgabase, i, saved->seq[i]);
283 
284 
285  /* unprotect vga regs */
286  vga_wcrtcs(state->vgabase, iobase, 17, saved->crtc[17] & ~0x80);
287  for (i = 0; i < state->num_crtc; i++)
288  vga_wcrtcs(state->vgabase, iobase, i, saved->crtc[i]);
289 
290  for (i = 0; i < state->num_gfx; i++)
291  vga_wgfx(state->vgabase, i, saved->gfx[i]);
292 
293  for (i = 0; i < state->num_attr; i++) {
294  vga_r(state->vgabase, iobase + 0xa);
295  vga_wattr(state->vgabase, i, saved->attr[i]);
296  }
297 
298  /* reenable sequencer */
299  vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
300  /* turn display on */
301  vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
302  saved->seq[VGA_SEQ_CLOCK_MODE] & ~(1 << 5));
303 
304  /* disable video/palette source */
305  vga_r(state->vgabase, iobase + 0xa);
306  vga_w(state->vgabase, VGA_ATT_W, 0x20);
307 }
308 
309 static void save_vga_cmap(struct vgastate *state)
310 {
311  struct regstate *saved = (struct regstate *) state->vidstate;
312  int i;
313 
314  vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
315 
316  /* assumes DAC is readable and writable */
317  vga_w(state->vgabase, VGA_PEL_IR, 0x00);
318  for (i = 0; i < 768; i++)
319  saved->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D);
320 }
321 
322 static void restore_vga_cmap(struct vgastate *state)
323 {
324  struct regstate *saved = (struct regstate *) state->vidstate;
325  int i;
326 
327  vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
328 
329  /* assumes DAC is readable and writable */
330  vga_w(state->vgabase, VGA_PEL_IW, 0x00);
331  for (i = 0; i < 768; i++)
332  vga_w(state->vgabase, VGA_PEL_D, saved->vga_cmap[i]);
333 }
334 
335 static void vga_cleanup(struct vgastate *state)
336 {
337  if (state->vidstate != NULL) {
338  struct regstate *saved = (struct regstate *) state->vidstate;
339 
340  vfree(saved->vga_font0);
341  vfree(saved->vga_font1);
342  vfree(saved->vga_text);
343  vfree(saved->vga_cmap);
344  vfree(saved->attr);
345  kfree(saved);
346  state->vidstate = NULL;
347  }
348 }
349 
350 int save_vga(struct vgastate *state)
351 {
352  struct regstate *saved;
353 
354  saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
355 
356  if (saved == NULL)
357  return 1;
358 
359  state->vidstate = (void *)saved;
360 
361  if (state->flags & VGA_SAVE_CMAP) {
362  saved->vga_cmap = vmalloc(768);
363  if (!saved->vga_cmap) {
364  vga_cleanup(state);
365  return 1;
366  }
367  save_vga_cmap(state);
368  }
369 
370  if (state->flags & VGA_SAVE_MODE) {
371  int total;
372 
373  if (state->num_attr < 21)
374  state->num_attr = 21;
375  if (state->num_crtc < 25)
376  state->num_crtc = 25;
377  if (state->num_gfx < 9)
378  state->num_gfx = 9;
379  if (state->num_seq < 5)
380  state->num_seq = 5;
381  total = state->num_attr + state->num_crtc +
382  state->num_gfx + state->num_seq;
383 
384  saved->attr = vmalloc(total);
385  if (!saved->attr) {
386  vga_cleanup(state);
387  return 1;
388  }
389  saved->crtc = saved->attr + state->num_attr;
390  saved->gfx = saved->crtc + state->num_crtc;
391  saved->seq = saved->gfx + state->num_gfx;
392 
393  save_vga_mode(state);
394  }
395 
396  if (state->flags & VGA_SAVE_FONTS) {
397  void __iomem *fbbase;
398 
399  /* exit if window is less than 32K */
400  if (state->memsize && state->memsize < 4 * 8192) {
401  vga_cleanup(state);
402  return 1;
403  }
404  if (!state->memsize)
405  state->memsize = 8 * 8192;
406 
407  if (!state->membase)
408  state->membase = 0xA0000;
409 
410  fbbase = ioremap(state->membase, state->memsize);
411 
412  if (!fbbase) {
413  vga_cleanup(state);
414  return 1;
415  }
416 
417  /*
418  * save only first 32K used by vgacon
419  */
420  if (state->flags & VGA_SAVE_FONT0) {
421  saved->vga_font0 = vmalloc(4 * 8192);
422  if (!saved->vga_font0) {
423  iounmap(fbbase);
424  vga_cleanup(state);
425  return 1;
426  }
427  }
428  /*
429  * largely unused, but if required by the caller
430  * we'll just save everything.
431  */
432  if (state->flags & VGA_SAVE_FONT1) {
433  saved->vga_font1 = vmalloc(state->memsize);
434  if (!saved->vga_font1) {
435  iounmap(fbbase);
436  vga_cleanup(state);
437  return 1;
438  }
439  }
440  /*
441  * Save 8K at plane0[0], and 8K at plane1[16K]
442  */
443  if (state->flags & VGA_SAVE_TEXT) {
444  saved->vga_text = vmalloc(8192 * 2);
445  if (!saved->vga_text) {
446  iounmap(fbbase);
447  vga_cleanup(state);
448  return 1;
449  }
450  }
451 
452  save_vga_text(state, fbbase);
453  iounmap(fbbase);
454  }
455  return 0;
456 }
457 
458 int restore_vga (struct vgastate *state)
459 {
460  if (state->vidstate == NULL)
461  return 1;
462 
463  if (state->flags & VGA_SAVE_MODE)
464  restore_vga_mode(state);
465 
466  if (state->flags & VGA_SAVE_FONTS) {
467  void __iomem *fbbase = ioremap(state->membase, state->memsize);
468 
469  if (!fbbase) {
470  vga_cleanup(state);
471  return 1;
472  }
473  restore_vga_text(state, fbbase);
474  iounmap(fbbase);
475  }
476 
477  if (state->flags & VGA_SAVE_CMAP)
478  restore_vga_cmap(state);
479 
480  vga_cleanup(state);
481  return 0;
482 }
483 
486 
487 MODULE_AUTHOR("James Simmons <[email protected]>");
488 MODULE_DESCRIPTION("VGA State Save/Restore");
489 MODULE_LICENSE("GPL");
490