xref: /netbsd/sys/dev/hpc/video_subr.c (revision bf9ec67e)
1 /*	$NetBSD: video_subr.c,v 1.4 2001/11/13 12:47:57 lukem Exp $	*/
2 
3 /*-
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by UCHIYAMA Yasushi.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: video_subr.c,v 1.4 2001/11/13 12:47:57 lukem Exp $");
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/malloc.h>
45 
46 #include <machine/bootinfo.h>
47 
48 #include <dev/hpc/video_subr.h>
49 
50 #define BPP2 ({								\
51 	u_int8_t bitmap;						\
52 	bitmap = *(volatile u_int8_t*)addr;				\
53 	*(volatile u_int8_t*)addr =					\
54 		(bitmap & ~(0x3 << ((3 - (x % 4)) * 2)));		\
55 })
56 
57 #define BPP4 ({								\
58 	u_int8_t bitmap;						\
59 	bitmap = *(volatile u_int8_t*)addr;				\
60 	*(volatile u_int8_t*)addr =					\
61 		(bitmap & ~(0xf << ((1 - (x % 2)) * 4)));		\
62 })
63 
64 #define BPP8 ({								\
65 	*(volatile u_int8_t*)addr = 0xff;				\
66 })
67 
68 #define BRESENHAM(a, b, c, d, func) ({					\
69 	u_int32_t fbaddr = vc->vc_fbvaddr;				\
70 	u_int32_t fbwidth = vc->vc_fbwidth;				\
71 	u_int32_t fbdepth = vc->vc_fbdepth;				\
72 	len = a, step = b -1;						\
73 	if (step == 0)							\
74 		return;							\
75 	kstep = len == 0 ? 0 : 1;					\
76 	for (i = k = 0, j = step / 2; i <= step; i++) {			\
77 		x = xbase c;						\
78 		y = ybase d;						\
79 		addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3);	\
80 		func;							\
81 		j -= len;						\
82 		while (j < 0) {						\
83 			j += step;					\
84 			k += kstep;					\
85 		}							\
86 	}								\
87 })
88 
89 #define DRAWLINE(func) ({						\
90 	if (x < 0) {							\
91 		if (y < 0) {						\
92 			if (_y < _x) {					\
93 				BRESENHAM(_y, _x, -i, -k, func);	\
94 			} else {					\
95 				BRESENHAM(_x, _y, -k, -i, func);	\
96 			}						\
97 		} else {						\
98 			if (_y < _x) {					\
99 				BRESENHAM(_y, _x, -i, +k, func);	\
100 			} else {					\
101 				BRESENHAM(_x, _y, -k, +i, func);	\
102 			}						\
103 		}							\
104 	} else {							\
105 		if (y < 0) {						\
106 			if (_y < _x) {					\
107 				BRESENHAM(_y, _x, +i, -k, func);	\
108 			} else {					\
109 				BRESENHAM(_x, _y, +k, -i, func);	\
110 			}						\
111 		} else {						\
112 			if (_y < _x) {					\
113 				BRESENHAM(_y, _x, +i, +k, func);	\
114 			} else {					\
115 				BRESENHAM(_x, _y, +k, +i, func);	\
116 			}						\
117 		}							\
118 	}								\
119 })
120 
121 #define LINEFUNC(b)							\
122 static void linebpp##b (struct video_chip *, int, int, int, int);	\
123 static void								\
124 linebpp##b##(vc, x0, y0, x1, y1)					\
125 	struct video_chip *vc;						\
126 	int x0, y0, x1, y1;						\
127 {									\
128 	u_int32_t addr;							\
129 	int i, j, k, len, step, kstep;					\
130 	int x, _x, y, _y;						\
131 	int xbase, ybase;						\
132 	x = x1 - x0;							\
133 	y = y1 - y0;							\
134 	_x = abs(x);							\
135 	_y = abs(y);							\
136 	xbase = x0;							\
137 	ybase = y0;							\
138 	DRAWLINE(BPP##b##);						\
139 }
140 
141 #define DOTFUNC(b)							\
142 static void dotbpp##b (struct video_chip *, int, int);			\
143 static void								\
144 dotbpp##b##(vc, x, y)							\
145 	struct video_chip *vc;						\
146 	int x, y;							\
147 {									\
148 	u_int32_t addr;							\
149 	addr = vc->vc_fbvaddr + (((y * vc->vc_fbwidth + x) *		\
150 				 vc->vc_fbdepth) >> 3);			\
151 	BPP##b;								\
152 }
153 
154 LINEFUNC(2)
155 LINEFUNC(4)
156 LINEFUNC(8)
157 DOTFUNC(2)
158 DOTFUNC(4)
159 DOTFUNC(8)
160 static void linebpp_unimpl(struct video_chip *, int, int, int, int);
161 static void dotbpp_unimpl(struct video_chip *, int, int);
162 
163 int
164 cmap_work_alloc(u_int8_t **r, u_int8_t **g, u_int8_t **b, u_int32_t **rgb,
165     int cnt)
166 {
167 	KASSERT(LEGAL_CLUT_INDEX(cnt - 1));
168 
169 #define	ALLOC_BUF(x, bit)						\
170 	if (x) {							\
171 		*x = malloc(cnt * sizeof(u_int ## bit ## _t),		\
172 		    M_DEVBUF, M_WAITOK);				\
173 		if (*x == 0)						\
174 			goto errout;					\
175 	}
176 	ALLOC_BUF(r, 8);
177 	ALLOC_BUF(g, 8);
178 	ALLOC_BUF(b, 8);
179 	ALLOC_BUF(rgb, 32);
180 #undef	ALLOCBUF
181 
182 	return (0);
183 errout:
184 	cmap_work_free(*r, *g, *b, *rgb);
185 
186 	return (1);
187 }
188 
189 void
190 cmap_work_free(u_int8_t *r, u_int8_t *g, u_int8_t *b, u_int32_t *rgb)
191 {
192 	if (r)
193 		free(r, M_DEVBUF);
194 	if (g)
195 		free(g, M_DEVBUF);
196 	if (b)
197 		free(b, M_DEVBUF);
198 	if (rgb)
199 		free(rgb, M_DEVBUF);
200 }
201 
202 void
203 rgb24_compose(u_int32_t *rgb24, u_int8_t *r, u_int8_t *g, u_int8_t *b, int cnt)
204 {
205 	int i;
206 	KASSERT(rgb24 && r && g && b && LEGAL_CLUT_INDEX(cnt - 1));
207 
208 	for (i = 0; i < cnt; i++) {
209 		*rgb24++ = RGB24(r[i], g[i], b[i]);
210 	}
211 }
212 
213 void
214 rgb24_decompose(u_int32_t *rgb24, u_int8_t *r, u_int8_t *g, u_int8_t *b,
215     int cnt)
216 {
217 	int i;
218 	KASSERT(rgb24 && r && g && b && LEGAL_CLUT_INDEX(cnt - 1));
219 
220 	for (i = 0; i < cnt; i++) {
221 		u_int32_t rgb = *rgb24++;
222 		*r++ = (rgb >> 16) & 0xff;
223 		*g++ = (rgb >> 8) & 0xff;
224 		*b++ = rgb & 0xff;
225 	}
226 }
227 
228 /*
229  * Debug routines.
230  */
231 void
232 video_calibration_pattern(struct video_chip *vc)
233 {
234 	int x, y;
235 
236 	x = vc->vc_fbwidth - 40;
237 	y = vc->vc_fbheight - 40;
238 	video_line(vc, 40, 40, x , 40);
239 	video_line(vc, x , 40, x , y );
240 	video_line(vc, x , y , 40, y );
241 	video_line(vc, 40, y , 40, 40);
242 	video_line(vc, 40, 40, x , y );
243 	video_line(vc, x,  40, 40, y );
244 }
245 
246 static void
247 linebpp_unimpl(struct video_chip *vc, int x0, int y0, int x1, int y1)
248 {
249 	return;
250 }
251 
252 static void
253 dotbpp_unimpl(struct video_chip *vc, int x, int y)
254 {
255 	return;
256 }
257 
258 void
259 video_attach_drawfunc(struct video_chip *vc)
260 {
261 	switch (vc->vc_fbdepth) {
262 	default:
263 		vc->vc_drawline = linebpp_unimpl;
264 		vc->vc_drawdot = dotbpp_unimpl;
265 		break;
266 	case 8:
267 		vc->vc_drawline = linebpp8;
268 		vc->vc_drawdot = dotbpp8;
269 		break;
270 	case 4:
271 		vc->vc_drawline = linebpp4;
272 		vc->vc_drawdot = dotbpp4;
273 		break;
274 	case 2:
275 		vc->vc_drawline = linebpp2;
276 		vc->vc_drawdot = dotbpp2;
277 		break;
278 	}
279 }
280 
281 void
282 video_line(struct video_chip *vc, int x0, int y0, int x1, int y1)
283 {
284 	if (vc->vc_drawline)
285 		vc->vc_drawline(vc, x0, y0, x1, y1);
286 }
287 
288 void
289 video_dot(struct video_chip *vc, int x, int y)
290 {
291 	if (vc->vc_drawdot)
292 		vc->vc_drawdot(vc, x, y);
293 }
294 
295 int
296 video_reverse_color()
297 {
298 	struct {
299 		int reverse, normal;
300 	} ctype[] = {
301 		{ BIFB_D2_M2L_3,	BIFB_D2_M2L_0	},
302 		{ BIFB_D2_M2L_3x2,	BIFB_D2_M2L_0x2	},
303 		{ BIFB_D8_FF,		BIFB_D8_00	},
304 		{ BIFB_D16_FFFF,	BIFB_D16_0000,	},
305 		{ -1, -1 } /* terminator */
306 	}, *ctypep;
307 	u_int16_t fbtype;
308 
309 	/* check reverse color */
310 	fbtype = bootinfo->fb_type;
311 	for (ctypep = ctype; ctypep->normal != -1 ;  ctypep++) {
312 		if (fbtype == ctypep->normal) {
313 			return (0);
314 		} else if (fbtype == ctypep->reverse) {
315 			return (1);
316 		}
317 	}
318 	printf(": WARNING unknown frame buffer type 0x%04x.\n", fbtype);
319 	return (0);
320 }
321