tx3912video.c revision 1.8 1 1.8 uch /* $NetBSD: tx3912video.c,v 1.8 2000/03/13 18:49:17 uch Exp $ */
2 1.1 uch
3 1.1 uch /*
4 1.5 uch * Copyright (c) 1999, 2000, by UCHIYAMA Yasushi
5 1.1 uch * All rights reserved.
6 1.1 uch *
7 1.1 uch * Redistribution and use in source and binary forms, with or without
8 1.1 uch * modification, are permitted provided that the following conditions
9 1.1 uch * are met:
10 1.1 uch * 1. Redistributions of source code must retain the above copyright
11 1.1 uch * notice, this list of conditions and the following disclaimer.
12 1.1 uch * 2. The name of the developer may NOT be used to endorse or promote products
13 1.1 uch * derived from this software without specific prior written permission.
14 1.1 uch *
15 1.1 uch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 1.1 uch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 1.1 uch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 1.1 uch * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.1 uch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.1 uch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 1.1 uch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 uch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.1 uch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.1 uch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.1 uch * SUCH DAMAGE.
26 1.1 uch *
27 1.1 uch */
28 1.1 uch #include "opt_tx39_debug.h"
29 1.8 uch #include "hpcfb.h"
30 1.1 uch
31 1.1 uch #include <sys/param.h>
32 1.1 uch #include <sys/systm.h>
33 1.1 uch #include <sys/device.h>
34 1.1 uch #include <sys/extent.h>
35 1.1 uch
36 1.1 uch #include <machine/bus.h>
37 1.2 uch #include <machine/bootinfo.h> /* bootinfo */
38 1.1 uch
39 1.1 uch #include <hpcmips/tx/tx39var.h>
40 1.1 uch #include <hpcmips/tx/tx3912videovar.h>
41 1.1 uch #include <hpcmips/tx/tx3912videoreg.h>
42 1.1 uch
43 1.8 uch #if NHPCFB > 0
44 1.8 uch #include <arch/hpcmips/dev/hpcfbvar.h>
45 1.8 uch #include <arch/hpcmips/dev/hpcfbio.h>
46 1.8 uch #include <arch/hpcmips/dev/bivideovar.h>
47 1.2 uch #endif
48 1.8 uch #include <machine/autoconf.h> /* XXX */
49 1.2 uch
50 1.6 uch #undef TX3912VIDEO_DEBUG
51 1.6 uch
52 1.3 uch void tx3912video_framebuffer_init __P((tx_chipset_tag_t, u_int32_t,
53 1.3 uch u_int32_t));
54 1.3 uch int tx3912video_framebuffer_alloc __P((tx_chipset_tag_t, u_int32_t,
55 1.3 uch int, int, int, u_int32_t*,
56 1.3 uch u_int32_t*));
57 1.1 uch void tx3912video_reset __P((tx_chipset_tag_t));
58 1.1 uch void tx3912video_resolution_init __P((tx_chipset_tag_t, int, int));
59 1.1 uch int tx3912video_fbdepth __P((tx_chipset_tag_t, int));
60 1.1 uch
61 1.1 uch int tx3912video_match __P((struct device*, struct cfdata*, void*));
62 1.1 uch void tx3912video_attach __P((struct device*, struct device*, void*));
63 1.1 uch int tx3912video_print __P((void*, const char*));
64 1.1 uch
65 1.6 uch struct tx3912video_chip {
66 1.6 uch u_int32_t vc_fbaddr;
67 1.6 uch u_int32_t vc_fbsize;
68 1.6 uch int vc_fbdepth;
69 1.6 uch int vc_fbwidth;
70 1.6 uch int vc_fbheight;
71 1.6 uch
72 1.6 uch void (*vc_drawline) __P((int, int, int, int));
73 1.6 uch void (*vc_drawdot) __P((int, int));
74 1.6 uch };
75 1.6 uch
76 1.1 uch struct tx3912video_softc {
77 1.1 uch struct device sc_dev;
78 1.6 uch
79 1.6 uch struct tx3912video_chip *sc_chip;
80 1.1 uch };
81 1.1 uch
82 1.1 uch struct fb_attach_args {
83 1.1 uch const char *fba_name;
84 1.1 uch };
85 1.1 uch
86 1.1 uch struct cfattach tx3912video_ca = {
87 1.3 uch sizeof(struct tx3912video_softc), tx3912video_match,
88 1.3 uch tx3912video_attach
89 1.1 uch };
90 1.1 uch
91 1.6 uch /* console */
92 1.6 uch struct tx3912video_chip tx3912video_chip;
93 1.6 uch
94 1.6 uch void tx3912video_attach_drawfunc __P((struct tx3912video_chip*));
95 1.6 uch
96 1.1 uch int
97 1.1 uch tx3912video_match(parent, cf, aux)
98 1.1 uch struct device *parent;
99 1.1 uch struct cfdata *cf;
100 1.1 uch void *aux;
101 1.1 uch {
102 1.1 uch return 1;
103 1.1 uch }
104 1.1 uch
105 1.1 uch void
106 1.1 uch tx3912video_attach(parent, self, aux)
107 1.1 uch struct device *parent;
108 1.1 uch struct device *self;
109 1.1 uch void *aux;
110 1.1 uch {
111 1.1 uch struct txsim_attach_args *ta = aux;
112 1.1 uch struct tx3912video_softc *sc = (void*)self;
113 1.1 uch tx_chipset_tag_t tc = ta->ta_tc;
114 1.8 uch struct mainbus_attach_args ma; /* XXX */
115 1.4 uch txreg_t reg;
116 1.1 uch
117 1.6 uch sc->sc_chip = &tx3912video_chip;
118 1.5 uch
119 1.5 uch printf(": ");
120 1.1 uch tx3912video_fbdepth(tc, 1);
121 1.6 uch printf(", frame buffer 0x%08x-0x%08x", sc->sc_chip->vc_fbaddr,
122 1.6 uch sc->sc_chip->vc_fbaddr + sc->sc_chip->vc_fbsize);
123 1.4 uch
124 1.5 uch printf("\n");
125 1.5 uch
126 1.6 uch #ifndef TX3912VIDEO_DEBUG
127 1.4 uch if (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) {
128 1.5 uch printf("%s: power off\n", sc->sc_dev.dv_xname);
129 1.4 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
130 1.4 uch reg &= ~(TX3912_VIDEOCTRL1_DISPON |
131 1.4 uch TX3912_VIDEOCTRL1_ENVID);
132 1.4 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
133 1.4 uch }
134 1.6 uch #endif /* TX3912VIDEO_DEBUG */
135 1.6 uch
136 1.6 uch /* attach debug draw routine */
137 1.6 uch tx3912video_attach_drawfunc(sc->sc_chip);
138 1.1 uch
139 1.1 uch /* Attach frame buffer device */
140 1.8 uch #if NHPCFB > 0
141 1.2 uch if (!(bootinfo->bi_cnuse & BI_CNUSE_SERIAL)) {
142 1.8 uch if (hpcfb_cnattach(0, 0, 0, 0)) {
143 1.2 uch panic("tx3912video_attach: can't init fb console");
144 1.2 uch }
145 1.2 uch }
146 1.8 uch ma.ma_name = "bivideo"; /* XXX */
147 1.8 uch config_found(self, &ma, tx3912video_print);
148 1.2 uch #endif
149 1.1 uch }
150 1.1 uch
151 1.1 uch int
152 1.1 uch tx3912video_print(aux, pnp)
153 1.1 uch void *aux;
154 1.1 uch const char *pnp;
155 1.1 uch {
156 1.1 uch return pnp ? QUIET : UNCONF;
157 1.1 uch }
158 1.1 uch
159 1.1 uch int
160 1.1 uch tx3912video_init(tc, fb_start, fb_width, fb_height, fb_addr, fb_size,
161 1.1 uch fb_line_bytes)
162 1.1 uch tx_chipset_tag_t tc;
163 1.1 uch u_int32_t fb_start; /* Physical address */
164 1.1 uch int fb_width, fb_height;
165 1.1 uch u_int32_t *fb_addr, *fb_size;
166 1.1 uch int *fb_line_bytes;
167 1.1 uch {
168 1.1 uch u_int32_t addr, size;
169 1.1 uch int fb_depth;
170 1.7 uch txreg_t reg;
171 1.1 uch
172 1.1 uch /* Inquire bit depth */
173 1.1 uch fb_depth = tx3912video_fbdepth(tc, 0);
174 1.7 uch
175 1.7 uch switch (fb_depth) {
176 1.7 uch case 2:
177 1.7 uch bootinfo->fb_type = BIFB_D2_M2L_0;
178 1.7 uch break;
179 1.7 uch case 4:
180 1.7 uch /* XXX should implement rasops4.c */
181 1.7 uch fb_depth = 2;
182 1.7 uch bootinfo->fb_type = BIFB_D2_M2L_0;
183 1.7 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
184 1.7 uch TX3912_VIDEOCTRL1_BITSEL_CLR(reg);
185 1.7 uch reg = TX3912_VIDEOCTRL1_BITSEL_SET(
186 1.7 uch reg, TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE);
187 1.7 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
188 1.7 uch break;
189 1.7 uch case 8:
190 1.7 uch bootinfo->fb_type = BIFB_D8_FF;
191 1.7 uch break;
192 1.7 uch }
193 1.7 uch
194 1.6 uch tx3912video_chip.vc_fbdepth = fb_depth;
195 1.6 uch tx3912video_chip.vc_fbwidth = fb_width;
196 1.6 uch tx3912video_chip.vc_fbheight= fb_height;
197 1.7 uch
198 1.1 uch
199 1.1 uch /* Allocate framebuffer area */
200 1.1 uch if (tx3912video_framebuffer_alloc(tc, fb_start, fb_width, fb_height,
201 1.1 uch fb_depth, &addr, &size)) {
202 1.1 uch return 1;
203 1.1 uch }
204 1.1 uch #if notyet
205 1.1 uch tx3912video_resolution_init(tc, fb_width, fb_height);
206 1.1 uch #else
207 1.1 uch /* Use Windows CE setting. */
208 1.1 uch #endif
209 1.1 uch /* Set DMA transfer address to VID module */
210 1.1 uch tx3912video_framebuffer_init(tc, addr, size);
211 1.1 uch
212 1.1 uch /* Syncronize framebuffer addr to frame signal */
213 1.1 uch tx3912video_reset(tc);
214 1.1 uch
215 1.1 uch *fb_line_bytes = (fb_width * fb_depth) / 8;
216 1.1 uch *fb_addr = addr; /* Phsical address */
217 1.1 uch *fb_size = size;
218 1.1 uch
219 1.1 uch return 0;
220 1.1 uch }
221 1.1 uch
222 1.1 uch int
223 1.1 uch tx3912video_framebuffer_alloc(tc, start, h, v, depth, fb_addr, fb_size)
224 1.1 uch tx_chipset_tag_t tc;
225 1.1 uch u_int32_t start;
226 1.1 uch int h, v, depth;
227 1.1 uch u_int32_t *fb_addr, *fb_size;
228 1.1 uch {
229 1.1 uch struct extent_fixed ex_fixed[2];
230 1.1 uch struct extent *ex;
231 1.1 uch u_long addr, size;
232 1.1 uch int err;
233 1.1 uch
234 1.1 uch /* Calcurate frame buffer size */
235 1.1 uch size = (h * v * depth) / 8;
236 1.1 uch
237 1.1 uch /* Allocate V-RAM area */
238 1.1 uch if (!(ex = extent_create("Frame buffer address", start,
239 1.1 uch start + TX3912_FRAMEBUFFER_MAX,
240 1.1 uch 0, (caddr_t)ex_fixed, sizeof ex_fixed,
241 1.1 uch EX_NOWAIT))) {
242 1.1 uch return 1;
243 1.1 uch }
244 1.1 uch if((err = extent_alloc_subregion(ex, start, start + size, size,
245 1.1 uch TX3912_FRAMEBUFFER_ALIGNMENT,
246 1.1 uch TX3912_FRAMEBUFFER_BOUNDARY,
247 1.1 uch EX_FAST|EX_NOWAIT, &addr))) {
248 1.1 uch return 1;
249 1.1 uch }
250 1.6 uch tx3912video_chip.vc_fbaddr = addr;
251 1.6 uch tx3912video_chip.vc_fbsize = size;
252 1.6 uch
253 1.1 uch *fb_addr = addr;
254 1.1 uch *fb_size = size;
255 1.1 uch
256 1.1 uch return 0;
257 1.1 uch }
258 1.1 uch
259 1.1 uch void
260 1.1 uch tx3912video_framebuffer_init(tc, fb_addr, fb_size)
261 1.1 uch tx_chipset_tag_t tc;
262 1.1 uch u_int32_t fb_addr, fb_size;
263 1.1 uch {
264 1.1 uch u_int32_t reg, vaddr, bank, base;
265 1.1 uch
266 1.1 uch /* XXX currently I don't set DFVAL, so force DF signal toggled on
267 1.1 uch * XXX each frame. */
268 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
269 1.1 uch reg &= ~TX3912_VIDEOCTRL1_DFMODE;
270 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
271 1.1 uch
272 1.1 uch /* Set DMA transfer start and end address */
273 1.1 uch
274 1.1 uch bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
275 1.1 uch base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
276 1.1 uch reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
277 1.1 uch /* Upper address counter */
278 1.1 uch reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
279 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
280 1.1 uch
281 1.1 uch /* Lower address counter */
282 1.1 uch base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
283 1.1 uch reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
284 1.1 uch
285 1.1 uch /* Set DF-signal rate */
286 1.1 uch reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
287 1.1 uch
288 1.1 uch /* Set VIDDONE signal delay after FRAME signal */
289 1.1 uch /* XXX not yet*/
290 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
291 1.1 uch
292 1.1 uch /* Clear frame buffer */
293 1.1 uch vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
294 1.1 uch bzero((void*)vaddr, fb_size);
295 1.1 uch }
296 1.1 uch
297 1.1 uch void
298 1.1 uch tx3912video_resolution_init(tc, h, v)
299 1.1 uch tx_chipset_tag_t tc;
300 1.1 uch int h;
301 1.1 uch int v;
302 1.1 uch {
303 1.1 uch u_int32_t reg, val;
304 1.1 uch int split, bit8, horzval, lineval;
305 1.1 uch
306 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
307 1.1 uch split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
308 1.1 uch bit8 = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
309 1.1 uch TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
310 1.1 uch val = TX3912_VIDEOCTRL1_BITSEL(reg);
311 1.1 uch
312 1.1 uch if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
313 1.1 uch !split) {
314 1.3 uch /* (LCD horizontal pixels / 8bit) * RGB - 1 */
315 1.3 uch horzval = (h / 8) * 3 - 1;
316 1.1 uch } else {
317 1.1 uch horzval = h / 4 - 1;
318 1.1 uch }
319 1.1 uch lineval = (split ? v / 2 : v) - 1;
320 1.1 uch
321 1.1 uch /* Video rate */
322 1.3 uch /* XXX
323 1.3 uch * probably This value should be determined from DFINT and LCDINT
324 1.3 uch */
325 1.1 uch reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
326 1.1 uch /* Horizontal size of LCD */
327 1.1 uch reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
328 1.1 uch /* # of lines for the LCD */
329 1.1 uch reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
330 1.1 uch
331 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
332 1.1 uch }
333 1.1 uch
334 1.6 uch int
335 1.1 uch tx3912video_fbdepth(tc, verbose)
336 1.1 uch tx_chipset_tag_t tc;
337 1.1 uch int verbose;
338 1.1 uch {
339 1.1 uch u_int32_t reg, val;
340 1.1 uch
341 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
342 1.1 uch val = TX3912_VIDEOCTRL1_BITSEL(reg);
343 1.1 uch switch (val) {
344 1.1 uch case TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR:
345 1.1 uch if (verbose)
346 1.1 uch printf("8bit color");
347 1.1 uch return 8;
348 1.1 uch case TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE:
349 1.1 uch if (verbose)
350 1.1 uch printf("4bit greyscale");
351 1.1 uch return 4;
352 1.1 uch case TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE:
353 1.1 uch if (verbose)
354 1.1 uch printf("2bit greyscale");
355 1.1 uch return 2;
356 1.1 uch case TX3912_VIDEOCTRL1_BITSEL_MONOCHROME:
357 1.1 uch if (verbose)
358 1.1 uch printf("monochrome");
359 1.1 uch return 1;
360 1.1 uch }
361 1.1 uch return 0;
362 1.1 uch }
363 1.1 uch
364 1.1 uch void
365 1.1 uch tx3912video_reset(tc)
366 1.1 uch tx_chipset_tag_t tc;
367 1.1 uch {
368 1.1 uch u_int32_t reg;
369 1.1 uch
370 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
371 1.3 uch
372 1.1 uch /* Disable video logic at end of this frame */
373 1.1 uch reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
374 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
375 1.3 uch
376 1.1 uch /* Wait for end of frame */
377 1.1 uch delay(300 * 1000);
378 1.3 uch
379 1.1 uch /* Make sure to disable video logic */
380 1.1 uch reg &= ~TX3912_VIDEOCTRL1_ENVID;
381 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
382 1.3 uch
383 1.1 uch delay(1000);
384 1.3 uch
385 1.1 uch /* Enable video logic again */
386 1.1 uch reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
387 1.1 uch reg |= TX3912_VIDEOCTRL1_ENVID;
388 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
389 1.3 uch
390 1.1 uch delay(1000);
391 1.1 uch }
392 1.1 uch
393 1.6 uch /*
394 1.6 uch * Debug routines.
395 1.6 uch */
396 1.6 uch
397 1.6 uch void
398 1.6 uch tx3912video_calibration_pattern()
399 1.6 uch {
400 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
401 1.6 uch int x, y;
402 1.6 uch
403 1.6 uch x = vc->vc_fbwidth - 40;
404 1.6 uch y = vc->vc_fbheight - 40;
405 1.6 uch tx3912video_line(40, 40, x , 40);
406 1.6 uch tx3912video_line(x , 40, x , y );
407 1.6 uch tx3912video_line(x , y , 40, y );
408 1.6 uch tx3912video_line(40, y , 40, 40);
409 1.6 uch tx3912video_line(40, 40, x , y );
410 1.6 uch tx3912video_line(x, 40, 40, y );
411 1.6 uch }
412 1.6 uch
413 1.6 uch #define BPP2 ({ \
414 1.6 uch u_int8_t bitmap; \
415 1.6 uch bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
416 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
417 1.6 uch (bitmap & ~(0x3 << ((3 - (x % 4)) * 2))); \
418 1.6 uch })
419 1.6 uch
420 1.6 uch #define BPP4 ({ \
421 1.6 uch u_int8_t bitmap; \
422 1.6 uch bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
423 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
424 1.6 uch (bitmap & ~(0xf << ((1 - (x % 2)) * 4))); \
425 1.6 uch })
426 1.6 uch
427 1.6 uch #define BPP8 ({ \
428 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = 0xff; \
429 1.6 uch })
430 1.6 uch
431 1.6 uch #define BRESENHAM(a, b, c, d, func) ({ \
432 1.6 uch u_int32_t fbaddr = vc->vc_fbaddr; \
433 1.6 uch u_int32_t fbwidth = vc->vc_fbwidth; \
434 1.6 uch u_int32_t fbdepth = vc->vc_fbdepth; \
435 1.6 uch len = a, step = b -1; \
436 1.6 uch if (step == 0) \
437 1.6 uch return; \
438 1.6 uch kstep = len == 0 ? 0 : 1; \
439 1.6 uch for (i = k = 0, j = step / 2; i <= step; i++) { \
440 1.6 uch x = xbase c; \
441 1.6 uch y = ybase d; \
442 1.6 uch addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3); \
443 1.6 uch func; \
444 1.6 uch j -= len; \
445 1.6 uch while (j < 0) { \
446 1.6 uch j += step; \
447 1.6 uch k += kstep; \
448 1.6 uch } \
449 1.6 uch } \
450 1.6 uch })
451 1.6 uch
452 1.6 uch #define DRAWLINE(func) ({ \
453 1.6 uch if (x < 0) { \
454 1.6 uch if (y < 0) { \
455 1.6 uch if (_y < _x) { \
456 1.6 uch BRESENHAM(_y, _x, -i, -k, func); \
457 1.6 uch } else { \
458 1.6 uch BRESENHAM(_x, _y, -k, -i, func); \
459 1.6 uch } \
460 1.6 uch } else { \
461 1.6 uch if (_y < _x) { \
462 1.6 uch BRESENHAM(_y, _x, -i, +k, func); \
463 1.6 uch } else { \
464 1.6 uch BRESENHAM(_x, _y, -k, +i, func); \
465 1.6 uch } \
466 1.6 uch } \
467 1.6 uch } else { \
468 1.6 uch if (y < 0) { \
469 1.6 uch if (_y < _x) { \
470 1.6 uch BRESENHAM(_y, _x, +i, -k, func); \
471 1.6 uch } else { \
472 1.6 uch BRESENHAM(_x, _y, +k, -i, func); \
473 1.6 uch } \
474 1.6 uch } else { \
475 1.6 uch if (_y < _x) { \
476 1.6 uch BRESENHAM(_y, _x, +i, +k, func); \
477 1.6 uch } else { \
478 1.6 uch BRESENHAM(_x, _y, +k, +i, func); \
479 1.6 uch } \
480 1.6 uch } \
481 1.6 uch } \
482 1.6 uch })
483 1.6 uch
484 1.6 uch #define LINEFUNC(b) \
485 1.6 uch static void linebpp##b __P((int, int, int, int)); \
486 1.6 uch static void \
487 1.6 uch linebpp##b##(x0, y0, x1, y1) \
488 1.6 uch int x0, y0, x1, y1; \
489 1.6 uch { \
490 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip; \
491 1.6 uch u_int32_t addr; \
492 1.6 uch int i, j, k, len, step, kstep; \
493 1.6 uch int x, _x, y, _y; \
494 1.6 uch int xbase, ybase; \
495 1.6 uch x = x1 - x0; \
496 1.6 uch y = y1 - y0; \
497 1.6 uch _x = abs(x); \
498 1.6 uch _y = abs(y); \
499 1.6 uch xbase = x0; \
500 1.6 uch ybase = y0; \
501 1.6 uch DRAWLINE(BPP##b##); \
502 1.6 uch }
503 1.1 uch
504 1.6 uch #define DOTFUNC(b) \
505 1.6 uch static void dotbpp##b __P((int, int)); \
506 1.6 uch static void \
507 1.6 uch dotbpp##b##(x, y) \
508 1.6 uch int x, y; \
509 1.6 uch { \
510 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip; \
511 1.6 uch u_int32_t addr; \
512 1.6 uch addr = vc->vc_fbaddr + (((y * vc->vc_fbwidth + x) * \
513 1.6 uch vc->vc_fbdepth) >> 3); \
514 1.6 uch BPP##b; \
515 1.6 uch }
516 1.6 uch
517 1.6 uch static void linebpp_unimpl __P((int, int, int, int));
518 1.6 uch static void dotbpp_unimpl __P((int, int));
519 1.6 uch static
520 1.6 uch void linebpp_unimpl(x0, y0, x1, y1)
521 1.6 uch int x0, y0, x1, y1;
522 1.6 uch {
523 1.6 uch return;
524 1.6 uch }
525 1.6 uch static
526 1.6 uch void dotbpp_unimpl(x, y)
527 1.6 uch int x, y;
528 1.6 uch {
529 1.6 uch return;
530 1.6 uch }
531 1.6 uch
532 1.6 uch LINEFUNC(2)
533 1.6 uch LINEFUNC(4)
534 1.6 uch LINEFUNC(8)
535 1.6 uch DOTFUNC(2)
536 1.6 uch DOTFUNC(4)
537 1.6 uch DOTFUNC(8)
538 1.6 uch
539 1.6 uch void
540 1.6 uch tx3912video_attach_drawfunc(vc)
541 1.6 uch struct tx3912video_chip *vc;
542 1.6 uch {
543 1.6 uch switch (vc->vc_fbdepth) {
544 1.6 uch default:
545 1.6 uch vc->vc_drawline = linebpp_unimpl;
546 1.6 uch vc->vc_drawdot = dotbpp_unimpl;
547 1.6 uch break;
548 1.6 uch case 8:
549 1.6 uch vc->vc_drawline = linebpp8;
550 1.6 uch vc->vc_drawdot = dotbpp8;
551 1.6 uch break;
552 1.6 uch case 4:
553 1.6 uch vc->vc_drawline = linebpp4;
554 1.6 uch vc->vc_drawdot = dotbpp4;
555 1.6 uch break;
556 1.6 uch case 2:
557 1.6 uch vc->vc_drawline = linebpp2;
558 1.6 uch vc->vc_drawdot = dotbpp2;
559 1.6 uch break;
560 1.6 uch }
561 1.6 uch }
562 1.6 uch
563 1.6 uch void
564 1.6 uch tx3912video_line(x0, y0, x1, y1)
565 1.6 uch int x0, y0, x1, y1;
566 1.6 uch {
567 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
568 1.6 uch vc->vc_drawline(x0, y0, x1, y1);
569 1.6 uch }
570 1.6 uch
571 1.6 uch void
572 1.6 uch tx3912video_dot(x, y)
573 1.6 uch int x, y;
574 1.6 uch {
575 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
576 1.6 uch vc->vc_drawdot(x, y);
577 1.6 uch }
578