2 * Creation Date: <2002/10/23 20:26:40 samuel>
3 * Time-stamp: <2004/01/07 19:39:15 samuel>
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
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
{
34 ulong
*pal
; /* 256 elements */
39 video_get_res( int *w
, int *h
)
41 if( !video
.has_video
) {
51 startup_splash( void )
54 int fd
, s
, i
, y
, x
, dx
, dy
;
60 /* only draw logo in 24-bit mode (for now) */
61 if( video
.fb
.depth
< 15 )
64 for( i
=0; i
<2; i
++ ) {
65 if( !BootHGetStrResInd("bootlogo", buf
, sizeof(buf
), 0, i
) )
67 *(!i
? &width
: &height
) = atol(buf
);
70 if( (s
=width
* height
* 3) > 0x20000 )
73 if( (fd
=open_io("pseudo:,bootlogo")) >= 0 ) {
75 if( read_io(fd
, p
, s
) != s
)
76 printk("bootlogo size error\n");
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 ulong
*d
= (ulong
*)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 ushort
*d
= (ushort
*)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);
100 /* No bootlogo support yet on other platforms */
106 get_color( int col_ind
)
109 if( !video
.has_video
|| col_ind
< 0 || col_ind
> 255 )
111 if( video
.fb
.depth
== 8 )
113 col
= video
.pal
[col_ind
];
114 if( video
.fb
.depth
== 24 || video
.fb
.depth
== 32 )
116 if( video
.fb
.depth
== 15 )
117 return ((col
>>9) & 0x7c00) | ((col
>>6) & 0x03e0) | ((col
>>3) & 0x1f);
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
)
129 color
= get_color( colind
);
132 *((ulong
*)p
+ x
) = color
;
134 *((short*)p
+ x
) = color
;
140 fill_rect( int col_ind
, int x
, int y
, int w
, int h
)
143 ulong col
= get_color(col_ind
);
145 if( !video
.has_video
|| x
< 0 || y
< 0 || x
+w
> video
.fb
.w
|| y
+h
> video
.fb
.h
)
148 pp
= (char*)video
.fb
.mphys
+ video
.fb
.rb
* y
;
149 for( ; h
--; pp
+= video
.fb
.rb
) {
151 if( video
.fb
.depth
== 24 || video
.fb
.depth
== 32 ) {
152 ulong
*p
= (ulong
*)pp
+ x
;
155 } else if( video
.fb
.depth
== 16 || video
.fb
.depth
== 15 ) {
156 ushort
*p
= (ushort
*)pp
+ x
;
160 char *p
= (char *)((ushort
*)pp
+ x
);
169 refresh_palette( void )
172 if( video
.fb
.depth
== 8 )
173 OSI_RefreshPalette();
178 set_color( int ind
, ulong color
)
180 if( !video
.has_video
|| ind
< 0 || ind
> 255 )
182 video
.pal
[ind
] = color
;
185 if( video
.fb
.depth
== 8 )
186 OSI_SetColor( ind
, color
);
187 #elif defined(CONFIG_SPARC32)
188 if( video
.fb
.depth
== 8 ) {
190 dac
[1] = ((color
>> 16) & 0xff) << 24; // Red
191 dac
[1] = ((color
>> 8) & 0xff) << 24; // Green
192 dac
[1] = (color
& 0xff) << 24; // Blue
195 vga_set_color(ind
, ((color
>> 16) & 0xff),
196 ((color
>> 8) & 0xff),
202 video_scroll( int height
)
204 int i
, offs
, size
, *dest
, *src
;
206 offs
= video
.fb
.rb
* height
;
207 size
= (video
.fb
.h
* video
.fb
.rb
- offs
)/16;
208 dest
= (int*)video
.fb
.mphys
;
209 src
= (int*)(video
.fb
.mphys
+ offs
);
211 for( i
=0; i
<size
; i
++ ) {
221 /************************************************************************/
223 /************************************************************************/
225 DECLARE_NODE( video
, INSTALL_OPEN
, 0, "Tdisplay" );
227 /* ( -- width height ) (?) */
229 video_dimensions( void )
232 (void) video_get_res( &w
, &h
);
237 /* ( table start count -- ) (?) */
239 video_set_colors( void )
243 uchar
*p
= (uchar
*)POP();
246 for( i
=0; i
<count
; i
++, p
+=3 ) {
247 ulong col
= (p
[0] << 16) | (p
[1] << 8) | p
[2];
248 set_color( i
+ start
, col
);
253 /* ( r g b index -- ) */
255 video_color_bang( void )
261 ulong col
= ((r
<< 16) & 0xff0000) | ((g
<< 8) & 0x00ff00) | (b
& 0xff);
262 /* printk("color!: %08lx %08lx %08lx %08lx\n", r, g, b, index ); */
263 set_color( index
, col
);
267 /* ( color_ind x y width height -- ) (?) */
269 video_fill_rect( void )
275 int color_ind
= POP();
277 fill_rect( color_ind
, x
, y
, w
, h
);
280 /* ( addr len -- actual ) */
288 addr
= pop_fstr_copy();
290 console_draw_str(addr
);
295 NODE_METHODS( video
) = {
296 {"dimensions", video_dimensions
},
297 {"set-colors", video_set_colors
},
298 {"fill-rectangle", video_fill_rect
},
299 {"color!", video_color_bang
},
300 {"write", video_write
},
304 /************************************************************************/
306 /************************************************************************/
309 init_video( unsigned long fb
, int width
, int height
, int depth
, int rb
)
320 video
.fb
.depth
= depth
;
322 while( (ph
=dt_iterate_type(ph
, "display")) ) {
323 set_property( ph
, "width", (char*)&video
.fb
.w
, 4 );
324 set_property( ph
, "height", (char*)&video
.fb
.h
, 4 );
325 set_property( ph
, "depth", (char*)&video
.fb
.depth
, 4 );
326 set_property( ph
, "linebytes", (char*)&video
.fb
.rb
, 4 );
327 set_property( ph
, "address", (char*)&video
.fb
.mphys
, 4 );
330 video
.pal
= malloc( 256 * sizeof(ulong
) );
333 s
= (video
.fb
.mphys
& 0xfff);
334 size
= ((video
.fb
.h
* video
.fb
.rb
+ s
) + 0xfff) & ~0xfff;
336 ofmem_claim_phys( video
.fb
.mphys
, size
, 0 );
337 ofmem_claim_virt( video
.fb
.mphys
, size
, 0 );
338 ofmem_map( video
.fb
.mphys
, video
.fb
.mphys
, size
, -1 );
341 for( i
=0; i
<256; i
++ )
342 set_color( i
, i
* 0x010101 );
344 set_color( 254, 0xffffcc );
345 fill_rect( 254, 0, 0, video
.fb
.w
, video
.fb
.h
);
350 REGISTER_NODE( video
);