ppc64: Don't set Kp bit on SLB
[openbios.git] / packages / video.c
blob9eddd0f7e2fc4382bbbf9709798eddd27c4d248f
1 /*
2 * Creation Date: <2002/10/23 20:26:40 samuel>
3 * Time-stamp: <2004/01/07 19:39:15 samuel>
5 * <video.c>
7 * Mac-on-Linux display node
9 * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation
17 #include "config.h"
18 #include "libopenbios/bindings.h"
19 #include "libc/diskio.h"
20 #include "libopenbios/ofmem.h"
21 #include "drivers/drivers.h"
22 #include "packages/video.h"
23 #include "libopenbios/console.h"
24 #include "drivers/vga.h"
26 typedef struct osi_fb_info {
27 unsigned long mphys;
28 int rb, w, h, depth;
29 } osi_fb_info_t;
31 static struct {
32 int has_video;
33 osi_fb_info_t fb;
34 unsigned long *pal; /* 256 elements */
35 } video;
38 int
39 video_get_res( int *w, int *h )
41 if( !video.has_video ) {
42 *w = *h = 0;
43 return -1;
45 *w = video.fb.w;
46 *h = video.fb.h;
47 return 0;
50 static void
51 startup_splash( void )
53 #ifdef CONFIG_MOL
54 int fd, s, i, y, x, dx, dy;
55 int width, height;
56 char *pp, *p;
57 char buf[64];
58 #endif
60 /* only draw logo in 24-bit mode (for now) */
61 if( video.fb.depth < 15 )
62 return;
63 #ifdef CONFIG_MOL
64 for( i=0; i<2; i++ ) {
65 if( !BootHGetStrResInd("bootlogo", buf, sizeof(buf), 0, i) )
66 return;
67 *(!i ? &width : &height) = atol(buf);
70 if( (s=width * height * 3) > 0x20000 )
71 return;
73 if( (fd=open_io("pseudo:,bootlogo")) >= 0 ) {
74 p = malloc( s );
75 if( read_io(fd, p, s) != s )
76 printk("bootlogo size error\n");
77 close_io( fd );
79 dx = (video.fb.w - width)/2;
80 dy = (video.fb.h - height)/3;
82 pp = (char*)video.fb.mphys + dy * video.fb.rb + dx * (video.fb.depth >= 24 ? 4 : 2);
84 for( y=0 ; y<height; y++, pp += video.fb.rb ) {
85 if( video.fb.depth >= 24 ) {
86 unsigned long *d = (unsigned long*)pp;
87 for( x=0; x<width; x++, p+=3, d++ )
88 *d = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2];
89 } else if( video.fb.depth == 15 ) {
90 unsigned short *d = (unsigned short*)pp;
91 for( x=0; x<width; x++, p+=3, d++ ) {
92 int col = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2];
93 *d = ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
97 free( p );
99 #else
100 /* No bootlogo support yet on other platforms */
101 return;
102 #endif
105 static unsigned long
106 get_color( int col_ind )
108 unsigned long col;
109 if( !video.has_video || col_ind < 0 || col_ind > 255 )
110 return 0;
111 if( video.fb.depth == 8 )
112 return col_ind;
113 col = video.pal[col_ind];
114 if( video.fb.depth == 24 || video.fb.depth == 32 )
115 return col;
116 if( video.fb.depth == 15 )
117 return ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
118 return 0;
121 void
122 draw_pixel( int x, int y, int colind )
124 char *p = (char*)video.fb.mphys + video.fb.rb * y;
125 int color, d = video.fb.depth;
127 if( x < 0 || y < 0 || x >= video.fb.w || y >=video.fb.h )
128 return;
129 color = get_color( colind );
131 if( d >= 24 )
132 *((unsigned long*)p + x) = color;
133 else if( d >= 15 )
134 *((short*)p + x) = color;
135 else
136 *(p + x) = color;
139 static void
140 fill_rect( int col_ind, int x, int y, int w, int h )
142 char *pp;
143 unsigned long col = get_color(col_ind);
145 if (!video.has_video || x < 0 || y < 0 || w <= 0 || h <= 0 ||
146 x + w > video.fb.w || y + h > video.fb.h)
147 return;
149 pp = (char*)video.fb.mphys + video.fb.rb * y;
150 for( ; h--; pp += video.fb.rb ) {
151 int ww = w;
152 if( video.fb.depth == 24 || video.fb.depth == 32 ) {
153 unsigned long *p = (unsigned long*)pp + x;
154 while( ww-- )
155 *p++ = col;
156 } else if( video.fb.depth == 16 || video.fb.depth == 15 ) {
157 unsigned short *p = (unsigned short*)pp + x;
158 while( ww-- )
159 *p++ = col;
160 } else {
161 char *p = (char *)((unsigned short*)pp + x);
163 while( ww-- )
164 *p++ = col;
169 static void
170 refresh_palette( void )
172 #ifdef CONFIG_MOL
173 if( video.fb.depth == 8 )
174 OSI_RefreshPalette();
175 #endif
178 void
179 set_color( int ind, unsigned long color )
181 if( !video.has_video || ind < 0 || ind > 255 )
182 return;
183 video.pal[ind] = color;
185 #ifdef CONFIG_MOL
186 if( video.fb.depth == 8 )
187 OSI_SetColor( ind, color );
188 #elif defined(CONFIG_SPARC32)
189 if( video.fb.depth == 8 ) {
190 dac[0] = ind << 24;
191 dac[1] = ((color >> 16) & 0xff) << 24; // Red
192 dac[1] = ((color >> 8) & 0xff) << 24; // Green
193 dac[1] = (color & 0xff) << 24; // Blue
195 #else
196 vga_set_color(ind, ((color >> 16) & 0xff),
197 ((color >> 8) & 0xff),
198 (color & 0xff));
199 #endif
202 void
203 video_scroll( int height )
205 int i, offs, size, *dest, *src;
207 if (height <= 0 || height >= video.fb.h) {
208 return;
210 offs = video.fb.rb * height;
211 size = (video.fb.h * video.fb.rb - offs)/16;
212 dest = (int*)video.fb.mphys;
213 src = (int*)(video.fb.mphys + offs);
215 for( i=0; i<size; i++ ) {
216 dest[0] = src[0];
217 dest[1] = src[1];
218 dest[2] = src[2];
219 dest[3] = src[3];
220 dest += 4;
221 src += 4;
225 /************************************************************************/
226 /* OF methods */
227 /************************************************************************/
229 DECLARE_NODE( video, INSTALL_OPEN, 0, "Tdisplay" );
231 /* ( -- width height ) (?) */
232 static void
233 video_dimensions( void )
235 int w, h;
236 (void) video_get_res( &w, &h );
237 PUSH( w );
238 PUSH( h );
241 /* ( table start count -- ) (?) */
242 static void
243 video_set_colors( void )
245 int count = POP();
246 int start = POP();
247 unsigned char *p = (unsigned char*)cell2pointer(POP());
248 int i;
250 for( i=0; i<count; i++, p+=3 ) {
251 unsigned long col = (p[0] << 16) | (p[1] << 8) | p[2];
252 set_color( i + start, col );
254 refresh_palette();
257 /* ( r g b index -- ) */
258 static void
259 video_color_bang( void )
261 int index = POP();
262 int b = POP();
263 int g = POP();
264 int r = POP();
265 unsigned long col = ((r << 16) & 0xff0000) | ((g << 8) & 0x00ff00) | (b & 0xff);
266 /* printk("color!: %08lx %08lx %08lx %08lx\n", r, g, b, index ); */
267 set_color( index, col );
268 refresh_palette();
271 /* ( color_ind x y width height -- ) (?) */
272 static void
273 video_fill_rect( void )
275 int h = POP();
276 int w = POP();
277 int y = POP();
278 int x = POP();
279 int color_ind = POP();
281 fill_rect( color_ind, x, y, w, h );
284 /* ( addr len -- actual ) */
285 static void
286 video_write(void)
288 char *addr;
289 int len;
291 len = POP();
292 addr = (char *)cell2pointer(POP());
294 console_draw_fstr(addr, len);
295 PUSH(len);
298 NODE_METHODS( video ) = {
299 {"dimensions", video_dimensions },
300 {"set-colors", video_set_colors },
301 {"fill-rectangle", video_fill_rect },
302 {"color!", video_color_bang },
303 {"write", video_write },
307 /************************************************************************/
308 /* init */
309 /************************************************************************/
311 void
312 init_video( unsigned long fb, int width, int height, int depth, int rb )
314 int i;
315 #ifdef CONFIG_PPC
316 int s, size;
317 #endif
318 phandle_t ph=0;
320 video.fb.mphys = fb;
321 video.fb.w = width;
322 video.fb.h = height;
323 video.fb.depth = depth;
324 video.fb.rb = rb;
325 while( (ph=dt_iterate_type(ph, "display")) ) {
326 set_int_property( ph, "width", video.fb.w );
327 set_int_property( ph, "height", video.fb.h );
328 set_int_property( ph, "depth", video.fb.depth );
329 set_int_property( ph, "linebytes", video.fb.rb );
330 set_int_property( ph, "address", video.fb.mphys );
332 video.has_video = 1;
333 video.pal = malloc( 256 * sizeof(unsigned long) );
335 #ifdef CONFIG_PPC
336 s = (video.fb.mphys & 0xfff);
337 size = ((video.fb.h * video.fb.rb + s) + 0xfff) & ~0xfff;
339 ofmem_claim_phys( video.fb.mphys, size, 0 );
340 ofmem_claim_virt( video.fb.mphys, size, 0 );
341 ofmem_map( video.fb.mphys, video.fb.mphys, size, -1 );
342 #endif
344 for( i=0; i<256; i++ )
345 set_color( i, i * 0x010101 );
347 set_color( 254, 0xffffcc );
348 fill_rect( 254, 0, 0, video.fb.w, video.fb.h );
350 refresh_palette();
351 startup_splash();
353 REGISTER_NODE( video );