2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #define grub_video_render_target grub_video_fbrender_target
21 #if !defined (TEST) && !defined(GENINIT)
23 #include <grub/types.h>
25 #include <grub/misc.h>
27 #include <grub/video.h>
28 #include <grub/video_fb.h>
31 #include <grub/cache.h>
33 typedef unsigned char grub_uint8_t
;
34 typedef unsigned short grub_uint16_t
;
35 typedef unsigned int grub_uint32_t
;
36 typedef int grub_err_t
;
37 #include <grub/vgaregs.h>
39 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
42 #include "sm712_init.c"
44 #pragma GCC diagnostic ignored "-Wcast-align"
46 #define GRUB_SM712_TOTAL_MEMORY_SPACE 0x700400
47 #define GRUB_SM712_REG_BASE 0x700000
48 #define GRUB_SM712_PCIID 0x0712126f
52 GRUB_SM712_SR_TV_CONTROL
= 0x65,
53 GRUB_SM712_SR_RAM_LUT
= 0x66,
54 GRUB_SM712_SR_CLOCK_CONTROL1
= 0x68,
55 GRUB_SM712_SR_CLOCK_CONTROL2
= 0x69,
56 GRUB_SM712_SR_VCLK_NUM
= 0x6c,
57 GRUB_SM712_SR_VCLK_DENOM
= 0x6d,
58 GRUB_SM712_SR_VCLK2_NUM
= 0x6e,
59 GRUB_SM712_SR_VCLK2_DENOM
= 0x6f,
60 GRUB_SM712_SR_POPUP_ICON_LOW
= 0x80,
61 GRUB_SM712_SR_POPUP_ICON_HIGH
= 0x81,
62 GRUB_SM712_SR_POPUP_ICON_CTRL
= 0x82,
63 GRUB_SM712_SR_POPUP_ICON_COLOR1
= 0x84,
64 GRUB_SM712_SR_POPUP_ICON_COLOR2
= 0x85,
65 GRUB_SM712_SR_POPUP_ICON_COLOR3
= 0x86,
67 GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_LOW
= 0x88,
68 GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_HIGH
= 0x89,
69 GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_LOW
= 0x8a,
70 GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_HIGH
= 0x8b,
71 GRUB_SM712_SR_HW_CURSOR_FG_COLOR
= 0x8c,
72 GRUB_SM712_SR_HW_CURSOR_BG_COLOR
= 0x8d,
74 GRUB_SM712_SR_POPUP_ICON_X_LOW
= 0x90,
75 GRUB_SM712_SR_POPUP_ICON_X_HIGH
= 0x91,
76 GRUB_SM712_SR_POPUP_ICON_Y_LOW
= 0x92,
77 GRUB_SM712_SR_POPUP_ICON_Y_HIGH
= 0x93,
78 GRUB_SM712_SR_PANEL_HW_VIDEO_CONTROL
= 0xa0,
79 GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_LOW
= 0xa1,
80 GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_HIGH
= 0xa2,
81 GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_LOW
= 0xa3,
82 GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_HIGH
= 0xa4,
83 GRUB_SM712_SR_PANEL_HW_VIDEO_RED_CONSTANT
= 0xa5,
84 GRUB_SM712_SR_PANEL_HW_VIDEO_GREEN_CONSTANT
= 0xa6,
85 GRUB_SM712_SR_PANEL_HW_VIDEO_BLUE_CONSTANT
= 0xa7,
86 GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_BOUNDARY
= 0xa8,
87 GRUB_SM712_SR_PANEL_HW_VIDEO_LEFT_BOUNDARY
= 0xa9,
88 GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_BOUNDARY
= 0xaa,
89 GRUB_SM712_SR_PANEL_HW_VIDEO_RIGHT_BOUNDARY
= 0xab,
90 GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_LEFT_OVERFLOW_BOUNDARY
= 0xac,
91 GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_RIGHT_OVERFLOW_BOUNDARY
= 0xad,
92 GRUB_SM712_SR_PANEL_HW_VIDEO_VERTICAL_STRETCH_FACTOR
= 0xae,
93 GRUB_SM712_SR_PANEL_HW_VIDEO_HORIZONTAL_STRETCH_FACTOR
= 0xaf,
97 GRUB_SM712_SR_TV_CRT_SRAM
= 0x00,
98 GRUB_SM712_SR_TV_LCD_SRAM
= 0x08
102 GRUB_SM712_SR_TV_ALT_CLOCK
= 0x00,
103 GRUB_SM712_SR_TV_FREE_RUN_CLOCK
= 0x04
107 GRUB_SM712_SR_TV_CLOCK_CKIN_NTSC
= 0x00,
108 GRUB_SM712_SR_TV_CLOCK_REFCLK_PAL
= 0x04
112 GRUB_SM712_SR_TV_HSYNC
= 0x00,
113 GRUB_SM712_SR_TV_COMPOSITE_HSYNC
= 0x01
117 GRUB_SM712_SR_RAM_LUT_NORMAL
= 0,
118 GRUB_SM712_SR_RAM_LUT_LCD_RAM_OFF
= 0x80,
119 GRUB_SM712_SR_RAM_LUT_CRT_RAM_OFF
= 0x40,
120 GRUB_SM712_SR_RAM_LUT_LCD_RAM_NO_WRITE
= 0x20,
121 GRUB_SM712_SR_RAM_LUT_CRT_RAM_NO_WRITE
= 0x10,
122 GRUB_SM712_SR_RAM_LUT_CRT_8BIT
= 0x08,
123 GRUB_SM712_SR_RAM_LUT_CRT_GAMMA
= 0x04
128 GRUB_SM712_SR_CLOCK_CONTROL1_VCLK_FROM_CCR
= 0x40,
129 GRUB_SM712_SR_CLOCK_CONTROL1_8DOT_CLOCK
= 0x10,
134 GRUB_SM712_SR_CLOCK_CONTROL2_PROGRAM_VCLOCK
= 0x03
137 #define GRUB_SM712_SR_POPUP_ICON_HIGH_MASK 0x7
138 #define GRUB_SM712_SR_POPUP_ICON_HIGH_HW_CURSOR_EN 0x80
141 GRUB_SM712_SR_POPUP_ICON_CTRL_DISABLED
= 0,
142 GRUB_SM712_SR_POPUP_ICON_CTRL_ZOOM_ENABLED
= 0x40,
143 GRUB_SM712_SR_POPUP_ICON_CTRL_ENABLED
= 0x80
145 #define RGB332_BLACK 0
146 #define RGB332_WHITE 0xff
150 GRUB_SM712_CR_OVERFLOW_INTERLACE
= 0x30,
151 GRUB_SM712_CR_INTERLACE_RETRACE
= 0x31,
152 GRUB_SM712_CR_TV_VDISPLAY_START
= 0x32,
153 GRUB_SM712_CR_TV_VDISPLAY_END_HIGH
= 0x33,
154 GRUB_SM712_CR_TV_VDISPLAY_END_LOW
= 0x34,
155 GRUB_SM712_CR_DDA_CONTROL_LOW
= 0x35,
156 GRUB_SM712_CR_DDA_CONTROL_HIGH
= 0x36,
157 GRUB_SM712_CR_TV_EQUALIZER
= 0x38,
158 GRUB_SM712_CR_TV_SERRATION
= 0x39,
159 GRUB_SM712_CR_HSYNC_CTRL
= 0x3a,
160 GRUB_SM712_CR_DEBUG
= 0x3c,
161 GRUB_SM712_CR_SHADOW_VGA_HTOTAL
= 0x40,
162 GRUB_SM712_CR_SHADOW_VGA_HBLANK_START
= 0x41,
163 GRUB_SM712_CR_SHADOW_VGA_HBLANK_END
= 0x42,
164 GRUB_SM712_CR_SHADOW_VGA_HRETRACE_START
= 0x43,
165 GRUB_SM712_CR_SHADOW_VGA_HRETRACE_END
= 0x44,
166 GRUB_SM712_CR_SHADOW_VGA_VERTICAL_TOTAL
= 0x45,
167 GRUB_SM712_CR_SHADOW_VGA_VBLANK_START
= 0x46,
168 GRUB_SM712_CR_SHADOW_VGA_VBLANK_END
= 0x47,
169 GRUB_SM712_CR_SHADOW_VGA_VRETRACE_START
= 0x48,
170 GRUB_SM712_CR_SHADOW_VGA_VRETRACE_END
= 0x49,
171 GRUB_SM712_CR_SHADOW_VGA_OVERFLOW
= 0x4a,
172 GRUB_SM712_CR_SHADOW_VGA_CELL_HEIGHT
= 0x4b,
173 GRUB_SM712_CR_SHADOW_VGA_HDISPLAY_END
= 0x4c,
174 GRUB_SM712_CR_SHADOW_VGA_VDISPLAY_END
= 0x4d,
175 GRUB_SM712_CR_DDA_LOOKUP_REG3_START
= 0x90,
176 GRUB_SM712_CR_DDA_LOOKUP_REG2_START
= 0x91,
177 GRUB_SM712_CR_DDA_LOOKUP_REG1_START
= 0xa0,
178 GRUB_SM712_CR_VCENTERING_OFFSET
= 0xa6,
179 GRUB_SM712_CR_HCENTERING_OFFSET
= 0xa7,
182 #define GRUB_SM712_CR_DEBUG_NONE 0
184 #define SM712_DDA_REG3_COMPARE_SHIFT 2
185 #define SM712_DDA_REG3_COMPARE_MASK 0xfc
186 #define SM712_DDA_REG3_DDA_SHIFT 8
187 #define SM712_DDA_REG3_DDA_MASK 0x3
188 #define SM712_DDA_REG2_DDA_MASK 0xff
189 #define SM712_DDA_REG2_VCENTER_MASK 0x3f
193 grub_uint8_t compare
;
195 grub_uint8_t vcentering
;
207 #if !defined (TEST) && !defined(GENINIT)
208 struct grub_video_mode_info mode_info
;
211 volatile grub_uint8_t
*ptr
;
212 grub_uint8_t
*cached_ptr
;
215 #if !defined (TEST) && !defined(GENINIT)
216 grub_pci_device_t dev
;
220 #if !defined (TEST) && !defined(GENINIT)
222 grub_video_sm712_video_init (void)
224 /* Reset frame buffer. */
225 grub_memset (&framebuffer
, 0, sizeof(framebuffer
));
227 return grub_video_fb_init ();
231 grub_video_sm712_video_fini (void)
233 if (framebuffer
.mapped
)
235 grub_pci_device_unmap_range (framebuffer
.dev
, framebuffer
.ptr
,
236 GRUB_SM712_TOTAL_MEMORY_SPACE
);
237 grub_pci_device_unmap_range (framebuffer
.dev
, framebuffer
.cached_ptr
,
238 GRUB_SM712_TOTAL_MEMORY_SPACE
);
240 return grub_video_fb_fini ();
245 grub_sm712_write_reg (grub_uint8_t val
, grub_uint16_t addr
)
248 printf (" {1, 0x%x, 0x%x},\n", addr
, val
);
249 #elif defined (GENINIT)
250 printf (" .byte 0x%02x, 0x%02x\n", (addr
- 0x3c0), val
);
251 if ((addr
- 0x3c0) & ~0x7f)
254 *(volatile grub_uint8_t
*) (framebuffer
.ptr
+ GRUB_SM712_REG_BASE
259 static inline grub_uint8_t
260 grub_sm712_read_reg (grub_uint16_t addr
)
263 printf (" {-1, 0x%x, 0x5},\n", addr
);
264 #elif defined (GENINIT)
265 if ((addr
- 0x3c0) & ~0x7f)
267 printf (" .byte 0x%04x, 0x00\n", (addr
- 0x3c0) | 0x80);
269 return *(volatile grub_uint8_t
*) (framebuffer
.ptr
+ GRUB_SM712_REG_BASE
274 static inline grub_uint8_t
275 grub_sm712_sr_read (grub_uint8_t addr
)
277 grub_sm712_write_reg (addr
, GRUB_VGA_IO_SR_INDEX
);
278 return grub_sm712_read_reg (GRUB_VGA_IO_SR_DATA
);
282 grub_sm712_sr_write (grub_uint8_t val
, grub_uint8_t addr
)
284 grub_sm712_write_reg (addr
, GRUB_VGA_IO_SR_INDEX
);
285 grub_sm712_write_reg (val
, GRUB_VGA_IO_SR_DATA
);
289 grub_sm712_gr_write (grub_uint8_t val
, grub_uint8_t addr
)
291 grub_sm712_write_reg (addr
, GRUB_VGA_IO_GR_INDEX
);
292 grub_sm712_write_reg (val
, GRUB_VGA_IO_GR_DATA
);
296 grub_sm712_cr_write (grub_uint8_t val
, grub_uint8_t addr
)
298 grub_sm712_write_reg (addr
, GRUB_VGA_IO_CR_INDEX
);
299 grub_sm712_write_reg (val
, GRUB_VGA_IO_CR_DATA
);
303 grub_sm712_write_arx (grub_uint8_t val
, grub_uint8_t addr
)
305 grub_sm712_read_reg (GRUB_VGA_IO_INPUT_STATUS1_REGISTER
);
306 grub_sm712_write_reg (addr
, GRUB_VGA_IO_ARX
);
307 grub_sm712_read_reg (GRUB_VGA_IO_ARX_READ
);
308 grub_sm712_write_reg (val
, GRUB_VGA_IO_ARX
);
312 grub_sm712_cr_shadow_write (grub_uint8_t val
, grub_uint8_t addr
)
314 grub_uint8_t mapping
[] =
316 [GRUB_VGA_CR_HTOTAL
] = GRUB_SM712_CR_SHADOW_VGA_HTOTAL
,
317 [GRUB_VGA_CR_HORIZ_END
] = 0xff,
318 [GRUB_VGA_CR_HBLANK_START
] = GRUB_SM712_CR_SHADOW_VGA_HBLANK_START
,
319 [GRUB_VGA_CR_HBLANK_END
] = GRUB_SM712_CR_SHADOW_VGA_HBLANK_END
,
320 [GRUB_VGA_CR_HORIZ_SYNC_PULSE_START
] = GRUB_SM712_CR_SHADOW_VGA_HRETRACE_START
,
321 [GRUB_VGA_CR_HORIZ_SYNC_PULSE_END
] = GRUB_SM712_CR_SHADOW_VGA_HRETRACE_END
,
322 [GRUB_VGA_CR_VERT_TOTAL
] = GRUB_SM712_CR_SHADOW_VGA_VERTICAL_TOTAL
,
323 [GRUB_VGA_CR_OVERFLOW
] = GRUB_SM712_CR_SHADOW_VGA_OVERFLOW
,
324 [GRUB_VGA_CR_BYTE_PANNING
] = 0xff,
325 [GRUB_VGA_CR_CELL_HEIGHT
] = GRUB_SM712_CR_SHADOW_VGA_CELL_HEIGHT
,
326 [GRUB_VGA_CR_CURSOR_START
] = 0xff,
327 [GRUB_VGA_CR_CURSOR_END
] = 0xff,
328 [GRUB_VGA_CR_START_ADDR_HIGH_REGISTER
] = 0xff,
329 [GRUB_VGA_CR_START_ADDR_LOW_REGISTER
] = 0xff,
330 [GRUB_VGA_CR_CURSOR_ADDR_HIGH
] = 0xff,
331 [GRUB_VGA_CR_CURSOR_ADDR_LOW
] = 0xff,
332 [GRUB_VGA_CR_VSYNC_START
] = GRUB_SM712_CR_SHADOW_VGA_VRETRACE_START
,
333 [GRUB_VGA_CR_VSYNC_END
] = GRUB_SM712_CR_SHADOW_VGA_VRETRACE_END
,
334 [GRUB_VGA_CR_VDISPLAY_END
] = GRUB_SM712_CR_SHADOW_VGA_VDISPLAY_END
,
335 [GRUB_VGA_CR_PITCH
] = GRUB_SM712_CR_SHADOW_VGA_HDISPLAY_END
,
336 [GRUB_VGA_CR_UNDERLINE_LOCATION
] = 0xff,
338 [GRUB_VGA_CR_VERTICAL_BLANK_START
] = GRUB_SM712_CR_SHADOW_VGA_VBLANK_START
,
339 [GRUB_VGA_CR_VERTICAL_BLANK_END
] = GRUB_SM712_CR_SHADOW_VGA_VBLANK_END
,
340 [GRUB_VGA_CR_MODE
] = 0xff,
341 [GRUB_VGA_CR_LINE_COMPARE
] = 0xff
343 if (addr
>= ARRAY_SIZE (mapping
) || mapping
[addr
] == 0xff)
345 grub_sm712_cr_write (val
, mapping
[addr
]);
349 grub_sm712_write_dda_lookup (int idx
, grub_uint8_t compare
, grub_uint16_t dda
,
350 grub_uint8_t vcentering
)
352 grub_sm712_cr_write (((compare
<< SM712_DDA_REG3_COMPARE_SHIFT
)
353 & SM712_DDA_REG3_COMPARE_MASK
)
354 | ((dda
>> SM712_DDA_REG3_DDA_SHIFT
)
355 & SM712_DDA_REG3_DDA_MASK
),
356 GRUB_SM712_CR_DDA_LOOKUP_REG3_START
+ 2 * idx
);
357 grub_sm712_cr_write (dda
& SM712_DDA_REG2_DDA_MASK
,
358 GRUB_SM712_CR_DDA_LOOKUP_REG2_START
+ 2 * idx
);
359 grub_sm712_cr_write (vcentering
& SM712_DDA_REG2_VCENTER_MASK
,
360 GRUB_SM712_CR_DDA_LOOKUP_REG1_START
+ idx
);
363 #if !defined (TEST) && !defined(GENINIT)
364 /* Helper for grub_video_sm712_setup. */
366 find_card (grub_pci_device_t dev
, grub_pci_id_t pciid
, void *data
)
369 grub_pci_address_t addr
;
372 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_CLASS
);
373 class = grub_pci_read (addr
);
375 if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
376 || pciid
!= GRUB_SM712_PCIID
)
381 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_ADDRESS_REG0
);
382 framebuffer
.base
= grub_pci_read (addr
);
383 framebuffer
.dev
= dev
;
390 grub_video_sm712_setup (unsigned int width
, unsigned int height
,
391 unsigned int mode_type
, unsigned int mode_mask
__attribute__ ((unused
)))
394 #if !defined (TEST) && !defined(GENINIT)
399 /* Decode depth from mode_type. If it is zero, then autodetect. */
400 depth
= (mode_type
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK
)
401 >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS
;
403 if ((width
!= 1024 && width
!= 0) || (height
!= 600 && height
!= 0)
404 || (depth
!= 16 && depth
!= 0))
405 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
406 "Only 1024x600x16 is supported");
408 grub_pci_iterate (find_card
, &found
);
410 return grub_error (GRUB_ERR_IO
, "Couldn't find graphics card");
411 /* Fill mode info details. */
412 framebuffer
.mode_info
.width
= 1024;
413 framebuffer
.mode_info
.height
= 600;
414 framebuffer
.mode_info
.mode_type
= (GRUB_VIDEO_MODE_TYPE_RGB
415 | GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
416 | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP
);
417 framebuffer
.mode_info
.bpp
= 16;
418 framebuffer
.mode_info
.bytes_per_pixel
= 2;
419 framebuffer
.mode_info
.pitch
= 1024 * 2;
420 framebuffer
.mode_info
.number_of_colors
= 256;
421 framebuffer
.mode_info
.red_mask_size
= 5;
422 framebuffer
.mode_info
.red_field_pos
= 11;
423 framebuffer
.mode_info
.green_mask_size
= 6;
424 framebuffer
.mode_info
.green_field_pos
= 5;
425 framebuffer
.mode_info
.blue_mask_size
= 5;
426 framebuffer
.mode_info
.blue_field_pos
= 0;
427 framebuffer
.mode_info
.reserved_mask_size
= 0;
428 framebuffer
.mode_info
.reserved_field_pos
= 0;
429 framebuffer
.mode_info
.blit_format
430 = grub_video_get_blit_format (&framebuffer
.mode_info
);
433 #if !defined (TEST) && !defined(GENINIT)
434 if (found
&& framebuffer
.base
== 0)
436 grub_pci_address_t addr
;
437 /* FIXME: choose address dynamically if needed. */
438 framebuffer
.base
= 0x04000000;
440 addr
= grub_pci_make_address (framebuffer
.dev
, GRUB_PCI_REG_ADDRESS_REG0
);
441 grub_pci_write (addr
, framebuffer
.base
);
444 addr
= grub_pci_make_address (framebuffer
.dev
, GRUB_PCI_REG_CACHELINE
);
445 grub_pci_write (addr
, 0x8);
447 /* Enable address spaces. */
448 addr
= grub_pci_make_address (framebuffer
.dev
, GRUB_PCI_REG_COMMAND
);
449 grub_pci_write (addr
, 0x7);
453 /* We can safely discard volatile attribute. */
454 #if !defined (TEST) && !defined(GENINIT)
456 = grub_pci_device_map_range (framebuffer
.dev
,
458 GRUB_SM712_TOTAL_MEMORY_SPACE
);
459 framebuffer
.cached_ptr
460 = grub_pci_device_map_range_cached (framebuffer
.dev
,
462 GRUB_SM712_TOTAL_MEMORY_SPACE
);
464 framebuffer
.mapped
= 1;
466 /* Initialise SM712. */
467 #if !defined (TEST) && !defined(GENINIT)
469 grub_vga_sr_write (0x11, 0x18);
472 #if !defined (TEST) && !defined(GENINIT)
473 /* Prevent garbage from appearing on the screen. */
474 grub_memset ((void *) framebuffer
.cached_ptr
, 0,
475 framebuffer
.mode_info
.height
* framebuffer
.mode_info
.pitch
);
479 grub_sm712_sr_write (0, 0x21);
480 grub_sm712_sr_write (0x7a, 0x62);
481 grub_sm712_sr_write (0x16, 0x6a);
482 grub_sm712_sr_write (0x2, 0x6b);
483 grub_sm712_write_reg (0, GRUB_VGA_IO_PIXEL_MASK
);
484 grub_sm712_sr_write (GRUB_VGA_SR_RESET_ASYNC
, GRUB_VGA_SR_RESET
);
485 grub_sm712_write_reg (GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY
486 | GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY
487 | GRUB_VGA_IO_MISC_UPPER_64K
488 | GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0
489 | GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS
490 | GRUB_VGA_IO_MISC_COLOR
, GRUB_VGA_IO_MISC_WRITE
);
491 grub_sm712_sr_write (GRUB_VGA_SR_RESET_ASYNC
| GRUB_VGA_SR_RESET_SYNC
,
493 grub_sm712_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK
,
494 GRUB_VGA_SR_CLOCKING_MODE
);
495 grub_sm712_sr_write (GRUB_VGA_ALL_PLANES
, GRUB_VGA_SR_MAP_MASK_REGISTER
);
496 grub_sm712_sr_write (0, GRUB_VGA_SR_CHAR_MAP_SELECT
);
497 grub_sm712_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4
498 | GRUB_VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING
499 | GRUB_VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY
,
500 GRUB_VGA_SR_MEMORY_MODE
);
502 for (i
= 0; i
< ARRAY_SIZE (sm712_sr_seq1
); i
++)
503 grub_sm712_sr_write (sm712_sr_seq1
[i
], 0x10 + i
);
505 for (i
= 0; i
< ARRAY_SIZE (sm712_sr_seq2
); i
++)
506 grub_sm712_sr_write (sm712_sr_seq2
[i
], 0x30 + i
);
509 grub_sm712_sr_write (0x1a, 0x63);
511 grub_sm712_sr_write (0x1a, 0x64);
513 grub_sm712_sr_write (GRUB_SM712_SR_TV_CRT_SRAM
| GRUB_SM712_SR_TV_ALT_CLOCK
514 | GRUB_SM712_SR_TV_CLOCK_CKIN_NTSC
515 | GRUB_SM712_SR_TV_HSYNC
,
516 GRUB_SM712_SR_TV_CONTROL
);
518 grub_sm712_sr_write (GRUB_SM712_SR_RAM_LUT_NORMAL
, GRUB_SM712_SR_RAM_LUT
);
521 grub_sm712_sr_write (0x00, 0x67);
523 grub_sm712_sr_write (GRUB_SM712_SR_CLOCK_CONTROL1_VCLK_FROM_CCR
524 | GRUB_SM712_SR_CLOCK_CONTROL1_8DOT_CLOCK
,
525 GRUB_SM712_SR_CLOCK_CONTROL1
);
526 grub_sm712_sr_write (GRUB_SM712_SR_CLOCK_CONTROL2_PROGRAM_VCLOCK
,
527 GRUB_SM712_SR_CLOCK_CONTROL2
);
529 grub_sm712_sr_write (82, GRUB_SM712_SR_VCLK_NUM
);
530 grub_sm712_sr_write (137, GRUB_SM712_SR_VCLK_DENOM
);
532 grub_sm712_sr_write (9, GRUB_SM712_SR_VCLK2_NUM
);
533 grub_sm712_sr_write (2, GRUB_SM712_SR_VCLK2_DENOM
);
535 grub_sm712_sr_write (0x04, 0x70);
537 grub_sm712_sr_write (0x45, 0x71);
539 grub_sm712_sr_write (0x30, 0x72);
541 grub_sm712_sr_write (0x30, 0x73);
543 grub_sm712_sr_write (0x40, 0x74);
545 grub_sm712_sr_write (0x20, 0x75);
547 grub_sm712_sr_write (0xff, GRUB_SM712_SR_POPUP_ICON_LOW
);
548 grub_sm712_sr_write (GRUB_SM712_SR_POPUP_ICON_HIGH_MASK
,
549 GRUB_SM712_SR_POPUP_ICON_HIGH
);
550 grub_sm712_sr_write (GRUB_SM712_SR_POPUP_ICON_CTRL_DISABLED
,
551 GRUB_SM712_SR_POPUP_ICON_CTRL
);
553 grub_sm712_sr_write (0x0, 0x83);
555 grub_sm712_sr_write (8, GRUB_SM712_SR_POPUP_ICON_COLOR1
);
556 grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_COLOR2
);
557 grub_sm712_sr_write (0x42, GRUB_SM712_SR_POPUP_ICON_COLOR3
);
560 grub_sm712_sr_write (0x3a, 0x87);
562 /* Why theese coordinates? */
563 grub_sm712_sr_write (0x59, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_LOW
);
564 grub_sm712_sr_write (0x02, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_HIGH
);
565 grub_sm712_sr_write (0x44, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_LOW
);
566 grub_sm712_sr_write (0x02, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_HIGH
);
568 grub_sm712_sr_write (RGB332_BLACK
, GRUB_SM712_SR_HW_CURSOR_FG_COLOR
);
569 grub_sm712_sr_write (RGB332_WHITE
, GRUB_SM712_SR_HW_CURSOR_BG_COLOR
);
572 grub_sm712_sr_write (0x3a, 0x8e);
573 grub_sm712_sr_write (0x3a, 0x8f);
575 grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_X_LOW
);
576 grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_X_HIGH
);
577 grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_Y_LOW
);
578 grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_Y_HIGH
);
580 grub_sm712_sr_write (0, GRUB_SM712_SR_PANEL_HW_VIDEO_CONTROL
);
581 grub_sm712_sr_write (0x10, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_LOW
);
582 grub_sm712_sr_write (0x08, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_HIGH
);
583 grub_sm712_sr_write (0x00, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_LOW
);
584 grub_sm712_sr_write (0x02, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_HIGH
);
585 grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_RED_CONSTANT
);
586 grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_GREEN_CONSTANT
);
587 grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_BLUE_CONSTANT
);
589 grub_sm712_sr_write (0x7b, GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_BOUNDARY
);
590 grub_sm712_sr_write (0xfb, GRUB_SM712_SR_PANEL_HW_VIDEO_LEFT_BOUNDARY
);
591 grub_sm712_sr_write (0xff, GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_BOUNDARY
);
592 grub_sm712_sr_write (0xff, GRUB_SM712_SR_PANEL_HW_VIDEO_RIGHT_BOUNDARY
);
593 /* Doesn't match documentation? */
594 grub_sm712_sr_write (0x97, GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_LEFT_OVERFLOW_BOUNDARY
);
595 grub_sm712_sr_write (0xef, GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_RIGHT_OVERFLOW_BOUNDARY
);
597 grub_sm712_sr_write (0xbf, GRUB_SM712_SR_PANEL_HW_VIDEO_VERTICAL_STRETCH_FACTOR
);
598 grub_sm712_sr_write (0xdf, GRUB_SM712_SR_PANEL_HW_VIDEO_HORIZONTAL_STRETCH_FACTOR
);
600 grub_sm712_gr_write (GRUB_VGA_NO_PLANES
, GRUB_VGA_GR_SET_RESET_PLANE
);
601 grub_sm712_gr_write (GRUB_VGA_NO_PLANES
, GRUB_VGA_GR_SET_RESET_PLANE_ENABLE
);
602 grub_sm712_gr_write (GRUB_VGA_NO_PLANES
, GRUB_VGA_GR_COLOR_COMPARE
);
603 grub_sm712_gr_write (GRUB_VGA_GR_DATA_ROTATE_NOP
, GRUB_VGA_GR_DATA_ROTATE
);
604 grub_sm712_gr_write (GRUB_VGA_NO_PLANES
, GRUB_VGA_GR_READ_MAP_REGISTER
);
605 grub_sm712_gr_write (GRUB_VGA_GR_MODE_256_COLOR
, GRUB_VGA_GR_MODE
);
606 grub_sm712_gr_write (GRUB_VGA_GR_GR6_MMAP_A0
607 | GRUB_VGA_GR_GR6_GRAPHICS_MODE
, GRUB_VGA_GR_GR6
);
608 grub_sm712_gr_write (GRUB_VGA_ALL_PLANES
, GRUB_VGA_GR_COLOR_COMPARE_DISABLE
);
609 grub_sm712_gr_write (0xff, GRUB_VGA_GR_BITMASK
);
611 /* Write palette mapping. */
612 for (i
= 0; i
< 16; i
++)
613 grub_sm712_write_arx (i
, i
);
615 grub_sm712_write_arx (GRUB_VGA_ARX_MODE_ENABLE_256COLOR
616 | GRUB_VGA_ARX_MODE_GRAPHICS
, GRUB_VGA_ARX_MODE
);
617 grub_sm712_write_arx (0, GRUB_VGA_ARX_OVERSCAN
);
618 grub_sm712_write_arx (GRUB_VGA_ALL_PLANES
, GRUB_VGA_ARX_COLOR_PLANE_ENABLE
);
619 grub_sm712_write_arx (0, GRUB_VGA_ARX_HORIZONTAL_PANNING
);
620 grub_sm712_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT
);
622 /* FIXME: compute this generically. */
624 struct grub_video_hw_config config
=
626 .vertical_total
= 806,
627 .vertical_blank_start
= 0x300,
628 .vertical_blank_end
= 0,
629 .vertical_sync_start
= 0x303,
630 .vertical_sync_end
= 0x9,
631 .line_compare
= 0x3ff,
632 .vdisplay_end
= 0x300,
634 .horizontal_total
= 164,
635 .horizontal_end
= 128,
636 .horizontal_blank_start
= 128,
637 .horizontal_blank_end
= 0,
638 .horizontal_sync_pulse_start
= 133,
639 .horizontal_sync_pulse_end
= 22
641 grub_vga_set_geometry (&config
, grub_sm712_cr_write
);
642 config
.horizontal_sync_pulse_start
= 134;
643 config
.horizontal_sync_pulse_end
= 21;
644 config
.vertical_sync_start
= 0x301;
645 config
.vertical_sync_end
= 0x0;
646 config
.line_compare
= 0x0ff;
647 config
.vdisplay_end
= 0x258;
649 grub_vga_set_geometry (&config
, grub_sm712_cr_shadow_write
);
652 grub_sm712_cr_write (GRUB_VGA_CR_BYTE_PANNING_NORMAL
,
653 GRUB_VGA_CR_BYTE_PANNING
);
654 grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_START
);
655 grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_END
);
656 grub_sm712_cr_write (0, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER
);
657 grub_sm712_cr_write (0, GRUB_VGA_CR_START_ADDR_LOW_REGISTER
);
658 grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_ADDR_HIGH
);
659 grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_ADDR_LOW
);
660 grub_sm712_cr_write (GRUB_VGA_CR_UNDERLINE_LOCATION_DWORD_MODE
,
661 GRUB_VGA_CR_UNDERLINE_LOCATION
);
662 grub_sm712_cr_write (GRUB_VGA_CR_MODE_ADDRESS_WRAP
663 | GRUB_VGA_CR_MODE_BYTE_MODE
664 | GRUB_VGA_CR_MODE_TIMING_ENABLE
665 | GRUB_VGA_CR_MODE_NO_CGA
666 | GRUB_VGA_CR_MODE_NO_HERCULES
,
669 grub_sm712_cr_write (0, GRUB_SM712_CR_OVERFLOW_INTERLACE
);
670 grub_sm712_cr_write (0, GRUB_SM712_CR_INTERLACE_RETRACE
);
671 grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_START
);
672 grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_END_HIGH
);
673 grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_END_LOW
);
674 grub_sm712_cr_write (0x80, GRUB_SM712_CR_DDA_CONTROL_LOW
);
675 grub_sm712_cr_write (0x02, GRUB_SM712_CR_DDA_CONTROL_HIGH
);
678 grub_sm712_cr_write (0x20, 0x37);
680 grub_sm712_cr_write (0, GRUB_SM712_CR_TV_EQUALIZER
);
681 grub_sm712_cr_write (0, GRUB_SM712_CR_TV_SERRATION
);
682 grub_sm712_cr_write (0, GRUB_SM712_CR_HSYNC_CTRL
);
685 grub_sm712_cr_write (0x40, 0x3b);
687 grub_sm712_cr_write (GRUB_SM712_CR_DEBUG_NONE
, GRUB_SM712_CR_DEBUG
);
690 grub_sm712_cr_write (0xff, 0x3d);
691 grub_sm712_cr_write (0x46, 0x3e);
692 grub_sm712_cr_write (0x91, 0x3f);
694 for (i
= 0; i
< ARRAY_SIZE (dda_lookups
); i
++)
695 grub_sm712_write_dda_lookup (i
, dda_lookups
[i
].compare
, dda_lookups
[i
].dda
,
696 dda_lookups
[i
].vcentering
);
699 grub_sm712_cr_write (0, 0x9c);
700 grub_sm712_cr_write (0, 0x9d);
701 grub_sm712_cr_write (0, 0x9e);
702 grub_sm712_cr_write (0, 0x9f);
704 grub_sm712_cr_write (0, GRUB_SM712_CR_VCENTERING_OFFSET
);
705 grub_sm712_cr_write (0, GRUB_SM712_CR_HCENTERING_OFFSET
);
707 grub_sm712_write_reg (GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY
708 | GRUB_VGA_IO_MISC_UPPER_64K
709 | GRUB_VGA_IO_MISC_28MHZ
710 | GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS
711 | GRUB_VGA_IO_MISC_COLOR
,
712 GRUB_VGA_IO_MISC_WRITE
);
714 #if !defined (TEST) && !defined(GENINIT)
716 *(volatile grub_uint32_t
*) ((char *) framebuffer
.ptr
+ 0x40c00c) = 0;
717 *(volatile grub_uint32_t
*) ((char *) framebuffer
.ptr
+ 0x40c040) = 0;
718 *(volatile grub_uint32_t
*) ((char *) framebuffer
.ptr
+ 0x40c000) = 0x20000;
719 *(volatile grub_uint32_t
*) ((char *) framebuffer
.ptr
+ 0x40c010) = 0x1020100;
722 (void) grub_sm712_sr_read (0x16);
724 #if !defined (TEST) && !defined(GENINIT)
725 err
= grub_video_fb_setup (mode_type
, mode_mask
,
726 &framebuffer
.mode_info
,
727 framebuffer
.cached_ptr
, NULL
, NULL
);
731 /* Copy default palette to initialize emulated palette. */
732 err
= grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS
,
733 grub_video_fbstd_colors
);
740 #if !defined (TEST) && !defined(GENINIT)
743 grub_video_sm712_swap_buffers (void)
746 s
= (framebuffer
.mode_info
.height
747 * framebuffer
.mode_info
.pitch
748 * framebuffer
.mode_info
.bytes_per_pixel
);
749 grub_video_fb_swap_buffers ();
750 grub_arch_sync_dma_caches (framebuffer
.cached_ptr
, s
);
751 return GRUB_ERR_NONE
;
755 grub_video_sm712_get_info_and_fini (struct grub_video_mode_info
*mode_info
,
758 grub_memcpy (mode_info
, &(framebuffer
.mode_info
), sizeof (*mode_info
));
759 *framebuf
= (char *) framebuffer
.ptr
;
761 grub_video_fb_fini ();
763 return GRUB_ERR_NONE
;
766 static struct grub_video_adapter grub_video_sm712_adapter
=
768 .name
= "SM712 Video Driver",
769 .id
= GRUB_VIDEO_DRIVER_SM712
,
771 .prio
= GRUB_VIDEO_ADAPTER_PRIO_NATIVE
,
773 .init
= grub_video_sm712_video_init
,
774 .fini
= grub_video_sm712_video_fini
,
775 .setup
= grub_video_sm712_setup
,
776 .get_info
= grub_video_fb_get_info
,
777 .get_info_and_fini
= grub_video_sm712_get_info_and_fini
,
778 .set_palette
= grub_video_fb_set_palette
,
779 .get_palette
= grub_video_fb_get_palette
,
780 .set_viewport
= grub_video_fb_set_viewport
,
781 .get_viewport
= grub_video_fb_get_viewport
,
782 .set_region
= grub_video_fb_set_region
,
783 .get_region
= grub_video_fb_get_region
,
784 .set_area_status
= grub_video_fb_set_area_status
,
785 .get_area_status
= grub_video_fb_get_area_status
,
786 .map_color
= grub_video_fb_map_color
,
787 .map_rgb
= grub_video_fb_map_rgb
,
788 .map_rgba
= grub_video_fb_map_rgba
,
789 .unmap_color
= grub_video_fb_unmap_color
,
790 .fill_rect
= grub_video_fb_fill_rect
,
791 .blit_bitmap
= grub_video_fb_blit_bitmap
,
792 .blit_render_target
= grub_video_fb_blit_render_target
,
793 .scroll
= grub_video_fb_scroll
,
794 .swap_buffers
= grub_video_sm712_swap_buffers
,
795 .create_render_target
= grub_video_fb_create_render_target
,
796 .delete_render_target
= grub_video_fb_delete_render_target
,
797 .set_active_render_target
= grub_video_fb_set_active_render_target
,
798 .get_active_render_target
= grub_video_fb_get_active_render_target
,
803 GRUB_MOD_INIT(video_sm712
)
805 grub_video_register (&grub_video_sm712_adapter
);
808 GRUB_MOD_FINI(video_sm712
)
810 grub_video_unregister (&grub_video_sm712_adapter
);
816 grub_video_sm712_setup (1024, 600, 0, 0);