Home | History | Annotate | Line # | Download | only in tx
tx3912video.c revision 1.6
      1  1.6  uch /*	$NetBSD: tx3912video.c,v 1.6 2000/01/06 18:10:42 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.2  uch #include "fb.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.2  uch #if NFB > 0
     44  1.2  uch #include <dev/rcons/raster.h>
     45  1.2  uch #include <dev/wscons/wsdisplayvar.h>
     46  1.2  uch #include <arch/hpcmips/dev/fbvar.h>
     47  1.2  uch #endif
     48  1.2  uch 
     49  1.6  uch #undef TX3912VIDEO_DEBUG
     50  1.6  uch 
     51  1.3  uch void tx3912video_framebuffer_init __P((tx_chipset_tag_t, u_int32_t,
     52  1.3  uch 				       u_int32_t));
     53  1.3  uch int  tx3912video_framebuffer_alloc __P((tx_chipset_tag_t, u_int32_t,
     54  1.3  uch 					int, int, int, u_int32_t*,
     55  1.3  uch 					u_int32_t*));
     56  1.1  uch void tx3912video_reset __P((tx_chipset_tag_t));
     57  1.1  uch void tx3912video_resolution_init __P((tx_chipset_tag_t, int, int));
     58  1.1  uch int  tx3912video_fbdepth __P((tx_chipset_tag_t, int));
     59  1.1  uch 
     60  1.1  uch int	tx3912video_match __P((struct device*, struct cfdata*, void*));
     61  1.1  uch void	tx3912video_attach __P((struct device*, struct device*, void*));
     62  1.1  uch int	tx3912video_print __P((void*, const char*));
     63  1.1  uch 
     64  1.6  uch struct tx3912video_chip {
     65  1.6  uch 	u_int32_t vc_fbaddr;
     66  1.6  uch 	u_int32_t vc_fbsize;
     67  1.6  uch 	int	vc_fbdepth;
     68  1.6  uch 	int	vc_fbwidth;
     69  1.6  uch 	int	vc_fbheight;
     70  1.6  uch 
     71  1.6  uch 	void (*vc_drawline) __P((int, int, int, int));
     72  1.6  uch 	void (*vc_drawdot) __P((int, int));
     73  1.6  uch };
     74  1.6  uch 
     75  1.1  uch struct tx3912video_softc {
     76  1.1  uch 	struct device sc_dev;
     77  1.6  uch 
     78  1.6  uch 	struct tx3912video_chip *sc_chip;
     79  1.1  uch };
     80  1.1  uch 
     81  1.1  uch struct fb_attach_args {
     82  1.1  uch 	const char *fba_name;
     83  1.1  uch };
     84  1.1  uch 
     85  1.1  uch struct cfattach tx3912video_ca = {
     86  1.3  uch 	sizeof(struct tx3912video_softc), tx3912video_match,
     87  1.3  uch 	tx3912video_attach
     88  1.1  uch };
     89  1.1  uch 
     90  1.6  uch /* console */
     91  1.6  uch struct tx3912video_chip tx3912video_chip;
     92  1.6  uch 
     93  1.6  uch void	tx3912video_attach_drawfunc __P((struct tx3912video_chip*));
     94  1.6  uch 
     95  1.1  uch int
     96  1.1  uch tx3912video_match(parent, cf, aux)
     97  1.1  uch 	struct device *parent;
     98  1.1  uch 	struct cfdata *cf;
     99  1.1  uch 	void *aux;
    100  1.1  uch {
    101  1.1  uch 	return 1;
    102  1.1  uch }
    103  1.1  uch 
    104  1.1  uch void
    105  1.1  uch tx3912video_attach(parent, self, aux)
    106  1.1  uch 	struct device *parent;
    107  1.1  uch 	struct device *self;
    108  1.1  uch 	void *aux;
    109  1.1  uch {
    110  1.1  uch 	struct txsim_attach_args *ta = aux;
    111  1.1  uch 	struct tx3912video_softc *sc = (void*)self;
    112  1.1  uch 	tx_chipset_tag_t tc = ta->ta_tc;
    113  1.1  uch 	struct fb_attach_args fba;
    114  1.4  uch 	txreg_t reg;
    115  1.1  uch 
    116  1.6  uch 	sc->sc_chip = &tx3912video_chip;
    117  1.5  uch 
    118  1.5  uch 	printf(": ");
    119  1.1  uch 	tx3912video_fbdepth(tc, 1);
    120  1.6  uch 	printf(", frame buffer 0x%08x-0x%08x", sc->sc_chip->vc_fbaddr,
    121  1.6  uch 	       sc->sc_chip->vc_fbaddr + sc->sc_chip->vc_fbsize);
    122  1.4  uch 
    123  1.5  uch 	printf("\n");
    124  1.5  uch 
    125  1.6  uch #ifndef TX3912VIDEO_DEBUG
    126  1.4  uch 	if (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) {
    127  1.5  uch 		printf("%s: power off\n", sc->sc_dev.dv_xname);
    128  1.4  uch 		reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    129  1.4  uch 		reg &= ~(TX3912_VIDEOCTRL1_DISPON |
    130  1.4  uch 			 TX3912_VIDEOCTRL1_ENVID);
    131  1.4  uch 		tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    132  1.4  uch 	}
    133  1.6  uch #endif /* TX3912VIDEO_DEBUG */
    134  1.6  uch 
    135  1.6  uch 	/* attach debug draw routine */
    136  1.6  uch 	tx3912video_attach_drawfunc(sc->sc_chip);
    137  1.1  uch 
    138  1.1  uch 	/* Attach frame buffer device */
    139  1.2  uch #if NFB > 0
    140  1.2  uch 	if (!(bootinfo->bi_cnuse & BI_CNUSE_SERIAL)) {
    141  1.2  uch 		if (fb_cnattach(0, 0, 0, 0)) {
    142  1.2  uch 			panic("tx3912video_attach: can't init fb console");
    143  1.2  uch 		}
    144  1.2  uch 	}
    145  1.1  uch 	fba.fba_name = "fb";
    146  1.1  uch 	config_found(self, &fba, tx3912video_print);
    147  1.2  uch #endif
    148  1.1  uch }
    149  1.1  uch 
    150  1.1  uch int
    151  1.1  uch tx3912video_print(aux, pnp)
    152  1.1  uch 	void *aux;
    153  1.1  uch 	const char *pnp;
    154  1.1  uch {
    155  1.1  uch 	return pnp ? QUIET : UNCONF;
    156  1.1  uch }
    157  1.1  uch 
    158  1.1  uch int
    159  1.1  uch tx3912video_init(tc, fb_start, fb_width, fb_height, fb_addr, fb_size,
    160  1.1  uch 		fb_line_bytes)
    161  1.1  uch 	tx_chipset_tag_t tc;
    162  1.1  uch 	u_int32_t fb_start; /* Physical address */
    163  1.1  uch 	int fb_width, fb_height;
    164  1.1  uch 	u_int32_t *fb_addr, *fb_size;
    165  1.1  uch 	int *fb_line_bytes;
    166  1.1  uch {
    167  1.1  uch  	u_int32_t addr, size;
    168  1.1  uch 	int fb_depth;
    169  1.1  uch 
    170  1.1  uch 	/* Inquire bit depth */
    171  1.1  uch 	fb_depth = tx3912video_fbdepth(tc, 0);
    172  1.6  uch 	tx3912video_chip.vc_fbdepth = fb_depth;
    173  1.6  uch 	tx3912video_chip.vc_fbwidth = fb_width;
    174  1.6  uch 	tx3912video_chip.vc_fbheight= fb_height;
    175  1.1  uch 
    176  1.1  uch 	/* Allocate framebuffer area */
    177  1.1  uch 	if (tx3912video_framebuffer_alloc(tc, fb_start, fb_width, fb_height,
    178  1.1  uch 					 fb_depth, &addr, &size)) {
    179  1.1  uch 		return 1;
    180  1.1  uch 	}
    181  1.1  uch #if notyet
    182  1.1  uch 	tx3912video_resolution_init(tc, fb_width, fb_height);
    183  1.1  uch #else
    184  1.1  uch 	/* Use Windows CE setting. */
    185  1.1  uch #endif
    186  1.1  uch 	/* Set DMA transfer address to VID module */
    187  1.1  uch 	tx3912video_framebuffer_init(tc, addr, size);
    188  1.1  uch 
    189  1.1  uch 	/* Syncronize framebuffer addr to frame signal */
    190  1.1  uch 	tx3912video_reset(tc);
    191  1.1  uch 
    192  1.1  uch 	*fb_line_bytes = (fb_width * fb_depth) / 8;
    193  1.1  uch 	*fb_addr = addr; /* Phsical address */
    194  1.1  uch 	*fb_size = size;
    195  1.1  uch 
    196  1.1  uch 	return 0;
    197  1.1  uch }
    198  1.1  uch 
    199  1.1  uch  int
    200  1.1  uch tx3912video_framebuffer_alloc(tc, start, h, v, depth, fb_addr, fb_size)
    201  1.1  uch 	tx_chipset_tag_t tc;
    202  1.1  uch 	u_int32_t start;
    203  1.1  uch 	int h, v, depth;
    204  1.1  uch 	u_int32_t *fb_addr, *fb_size;
    205  1.1  uch {
    206  1.1  uch 	struct extent_fixed ex_fixed[2];
    207  1.1  uch 	struct extent *ex;
    208  1.1  uch 	u_long addr, size;
    209  1.1  uch 	int err;
    210  1.1  uch 
    211  1.1  uch 	/* Calcurate frame buffer size */
    212  1.1  uch 	size = (h * v * depth) / 8;
    213  1.1  uch 
    214  1.1  uch 	/* Allocate V-RAM area */
    215  1.1  uch 	if (!(ex = extent_create("Frame buffer address", start,
    216  1.1  uch 				 start + TX3912_FRAMEBUFFER_MAX,
    217  1.1  uch 				 0, (caddr_t)ex_fixed, sizeof ex_fixed,
    218  1.1  uch  				 EX_NOWAIT))) {
    219  1.1  uch 		return 1;
    220  1.1  uch 	}
    221  1.1  uch 	if((err = extent_alloc_subregion(ex, start, start + size, size,
    222  1.1  uch 					 TX3912_FRAMEBUFFER_ALIGNMENT,
    223  1.1  uch 					 TX3912_FRAMEBUFFER_BOUNDARY,
    224  1.1  uch 					 EX_FAST|EX_NOWAIT, &addr))) {
    225  1.1  uch 		return 1;
    226  1.1  uch 	}
    227  1.6  uch 	tx3912video_chip.vc_fbaddr = addr;
    228  1.6  uch 	tx3912video_chip.vc_fbsize = size;
    229  1.6  uch 
    230  1.1  uch 	*fb_addr = addr;
    231  1.1  uch 	*fb_size = size;
    232  1.1  uch 
    233  1.1  uch 	return 0;
    234  1.1  uch }
    235  1.1  uch 
    236  1.1  uch  void
    237  1.1  uch tx3912video_framebuffer_init(tc, fb_addr, fb_size)
    238  1.1  uch 	tx_chipset_tag_t tc;
    239  1.1  uch 	u_int32_t fb_addr, fb_size;
    240  1.1  uch {
    241  1.1  uch 	u_int32_t reg, vaddr, bank, base;
    242  1.1  uch 
    243  1.1  uch 	/*  XXX currently I don't set DFVAL, so force DF signal toggled on
    244  1.1  uch          *  XXX each frame. */
    245  1.1  uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    246  1.1  uch 	reg &= ~TX3912_VIDEOCTRL1_DFMODE;
    247  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    248  1.1  uch 
    249  1.1  uch 	/* Set DMA transfer start and end address */
    250  1.1  uch 
    251  1.1  uch 	bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
    252  1.1  uch 	base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
    253  1.1  uch 	reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
    254  1.1  uch 	/* Upper address counter */
    255  1.1  uch 	reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
    256  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
    257  1.1  uch 
    258  1.1  uch 	/* Lower address counter  */
    259  1.1  uch 	base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
    260  1.1  uch 	reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
    261  1.1  uch 
    262  1.1  uch 	/* Set DF-signal rate */
    263  1.1  uch 	reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
    264  1.1  uch 
    265  1.1  uch 	/* Set VIDDONE signal delay after FRAME signal */
    266  1.1  uch 	/* XXX not yet*/
    267  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
    268  1.1  uch 
    269  1.1  uch 	/* Clear frame buffer */
    270  1.1  uch 	vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
    271  1.1  uch 	bzero((void*)vaddr, fb_size);
    272  1.1  uch }
    273  1.1  uch 
    274  1.1  uch  void
    275  1.1  uch tx3912video_resolution_init(tc, h, v)
    276  1.1  uch 	tx_chipset_tag_t tc;
    277  1.1  uch 	int h;
    278  1.1  uch 	int v;
    279  1.1  uch {
    280  1.1  uch 	u_int32_t reg, val;
    281  1.1  uch 	int split, bit8, horzval, lineval;
    282  1.1  uch 
    283  1.1  uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    284  1.1  uch 	split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
    285  1.1  uch 	bit8  = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
    286  1.1  uch 		 TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
    287  1.1  uch 	val = TX3912_VIDEOCTRL1_BITSEL(reg);
    288  1.1  uch 
    289  1.1  uch 	if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
    290  1.1  uch 	    !split) {
    291  1.3  uch 		/* (LCD horizontal pixels / 8bit) * RGB - 1 */
    292  1.3  uch 		horzval = (h / 8) * 3 - 1;
    293  1.1  uch 	} else {
    294  1.1  uch 		horzval = h / 4 - 1;
    295  1.1  uch 	}
    296  1.1  uch 	lineval = (split ? v / 2 : v) - 1;
    297  1.1  uch 
    298  1.1  uch 	/* Video rate */
    299  1.3  uch 	/* XXX
    300  1.3  uch 	 *  probably This value should be determined from DFINT and LCDINT
    301  1.3  uch 	 */
    302  1.1  uch 	reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
    303  1.1  uch 	/* Horizontal size of LCD */
    304  1.1  uch 	reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
    305  1.1  uch 	/* # of lines for the LCD */
    306  1.1  uch 	reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
    307  1.1  uch 
    308  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
    309  1.1  uch }
    310  1.1  uch 
    311  1.6  uch int
    312  1.1  uch tx3912video_fbdepth(tc, verbose)
    313  1.1  uch 	tx_chipset_tag_t tc;
    314  1.1  uch 	int verbose;
    315  1.1  uch {
    316  1.1  uch 	u_int32_t reg, val;
    317  1.1  uch 
    318  1.1  uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    319  1.1  uch 	val = TX3912_VIDEOCTRL1_BITSEL(reg);
    320  1.1  uch 	switch (val) {
    321  1.1  uch 	case TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR:
    322  1.1  uch 		if (verbose)
    323  1.1  uch 			printf("8bit color");
    324  1.1  uch 		return 8;
    325  1.1  uch 	case TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE:
    326  1.1  uch 		if (verbose)
    327  1.1  uch 			printf("4bit greyscale");
    328  1.1  uch 		return 4;
    329  1.1  uch 	case TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE:
    330  1.1  uch 		if (verbose)
    331  1.1  uch 			printf("2bit greyscale");
    332  1.1  uch 		return 2;
    333  1.1  uch 	case TX3912_VIDEOCTRL1_BITSEL_MONOCHROME:
    334  1.1  uch 		if (verbose)
    335  1.1  uch 			printf("monochrome");
    336  1.1  uch 		return 1;
    337  1.1  uch 	}
    338  1.1  uch 	return 0;
    339  1.1  uch }
    340  1.1  uch 
    341  1.1  uch void
    342  1.1  uch tx3912video_reset(tc)
    343  1.1  uch 	tx_chipset_tag_t tc;
    344  1.1  uch {
    345  1.1  uch 	u_int32_t reg;
    346  1.1  uch 
    347  1.1  uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    348  1.3  uch 
    349  1.1  uch 	/* Disable video logic at end of this frame */
    350  1.1  uch 	reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
    351  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    352  1.3  uch 
    353  1.1  uch 	/* Wait for end of frame */
    354  1.1  uch 	delay(300 * 1000);
    355  1.3  uch 
    356  1.1  uch 	/* Make sure to disable video logic */
    357  1.1  uch 	reg &= ~TX3912_VIDEOCTRL1_ENVID;
    358  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    359  1.3  uch 
    360  1.1  uch 	delay(1000);
    361  1.3  uch 
    362  1.1  uch 	/* Enable video logic again */
    363  1.1  uch 	reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
    364  1.1  uch 	reg |= TX3912_VIDEOCTRL1_ENVID;
    365  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    366  1.3  uch 
    367  1.1  uch 	delay(1000);
    368  1.1  uch }
    369  1.1  uch 
    370  1.6  uch /*
    371  1.6  uch  * Debug routines.
    372  1.6  uch  */
    373  1.6  uch 
    374  1.6  uch void
    375  1.6  uch tx3912video_calibration_pattern()
    376  1.6  uch {
    377  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    378  1.6  uch 	int x, y;
    379  1.6  uch 
    380  1.6  uch 	x = vc->vc_fbwidth - 40;
    381  1.6  uch 	y = vc->vc_fbheight - 40;
    382  1.6  uch 	tx3912video_line(40, 40, x , 40);
    383  1.6  uch 	tx3912video_line(x , 40, x , y );
    384  1.6  uch 	tx3912video_line(x , y , 40, y );
    385  1.6  uch 	tx3912video_line(40, y , 40, 40);
    386  1.6  uch 	tx3912video_line(40, 40, x , y );
    387  1.6  uch 	tx3912video_line(x,  40, 40, y );
    388  1.6  uch }
    389  1.6  uch 
    390  1.6  uch #define BPP2 ({ \
    391  1.6  uch 	u_int8_t bitmap; \
    392  1.6  uch 	bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
    393  1.6  uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
    394  1.6  uch 		(bitmap & ~(0x3 << ((3 - (x % 4)) * 2))); \
    395  1.6  uch })
    396  1.6  uch 
    397  1.6  uch #define BPP4 ({ \
    398  1.6  uch 	u_int8_t bitmap; \
    399  1.6  uch 	bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
    400  1.6  uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
    401  1.6  uch 		(bitmap & ~(0xf << ((1 - (x % 2)) * 4))); \
    402  1.6  uch })
    403  1.6  uch 
    404  1.6  uch #define BPP8 ({ \
    405  1.6  uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = 0xff; \
    406  1.6  uch })
    407  1.6  uch 
    408  1.6  uch #define BRESENHAM(a, b, c, d, func) ({ \
    409  1.6  uch 	u_int32_t fbaddr = vc->vc_fbaddr; \
    410  1.6  uch 	u_int32_t fbwidth = vc->vc_fbwidth; \
    411  1.6  uch 	u_int32_t fbdepth = vc->vc_fbdepth; \
    412  1.6  uch 	len = a, step = b -1; \
    413  1.6  uch 	if (step == 0) \
    414  1.6  uch 		return; \
    415  1.6  uch 	kstep = len == 0 ? 0 : 1; \
    416  1.6  uch 	for (i = k = 0, j = step / 2; i <= step; i++) { \
    417  1.6  uch 		x = xbase c; \
    418  1.6  uch 		y = ybase d; \
    419  1.6  uch 		addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3); \
    420  1.6  uch 		func; \
    421  1.6  uch 		j -= len; \
    422  1.6  uch 		while (j < 0) { \
    423  1.6  uch 			j += step; \
    424  1.6  uch 			k += kstep; \
    425  1.6  uch 		} \
    426  1.6  uch 	} \
    427  1.6  uch })
    428  1.6  uch 
    429  1.6  uch #define DRAWLINE(func) ({ \
    430  1.6  uch 	if (x < 0) { \
    431  1.6  uch 		if (y < 0) { \
    432  1.6  uch 			if (_y < _x) { \
    433  1.6  uch 				BRESENHAM(_y, _x, -i, -k, func); \
    434  1.6  uch 			} else { \
    435  1.6  uch 				BRESENHAM(_x, _y, -k, -i, func); \
    436  1.6  uch 			} \
    437  1.6  uch 		} else { \
    438  1.6  uch 			if (_y < _x) { \
    439  1.6  uch 				BRESENHAM(_y, _x, -i, +k, func); \
    440  1.6  uch 			} else { \
    441  1.6  uch 				BRESENHAM(_x, _y, -k, +i, func); \
    442  1.6  uch 			} \
    443  1.6  uch 		} \
    444  1.6  uch 	} else { \
    445  1.6  uch 		if (y < 0) { \
    446  1.6  uch 			if (_y < _x) { \
    447  1.6  uch 				BRESENHAM(_y, _x, +i, -k, func); \
    448  1.6  uch 			} else { \
    449  1.6  uch 				BRESENHAM(_x, _y, +k, -i, func); \
    450  1.6  uch 			} \
    451  1.6  uch 		} else { \
    452  1.6  uch 			if (_y < _x) { \
    453  1.6  uch 				BRESENHAM(_y, _x, +i, +k, func); \
    454  1.6  uch 			} else { \
    455  1.6  uch 				BRESENHAM(_x, _y, +k, +i, func); \
    456  1.6  uch 			} \
    457  1.6  uch 		} \
    458  1.6  uch 	} \
    459  1.6  uch })
    460  1.6  uch 
    461  1.6  uch #define LINEFUNC(b) \
    462  1.6  uch static void linebpp##b __P((int, int, int, int)); \
    463  1.6  uch static void \
    464  1.6  uch linebpp##b##(x0, y0, x1, y1) \
    465  1.6  uch 	int x0, y0, x1, y1; \
    466  1.6  uch { \
    467  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip; \
    468  1.6  uch 	u_int32_t addr; \
    469  1.6  uch 	int i, j, k, len, step, kstep; \
    470  1.6  uch 	int x, _x, y, _y; \
    471  1.6  uch 	int xbase, ybase; \
    472  1.6  uch 	x = x1 - x0; \
    473  1.6  uch 	y = y1 - y0; \
    474  1.6  uch 	_x = abs(x); \
    475  1.6  uch 	_y = abs(y); \
    476  1.6  uch 	xbase = x0; \
    477  1.6  uch 	ybase = y0; \
    478  1.6  uch 	DRAWLINE(BPP##b##); \
    479  1.6  uch }
    480  1.1  uch 
    481  1.6  uch #define DOTFUNC(b) \
    482  1.6  uch static void dotbpp##b __P((int, int)); \
    483  1.6  uch static void \
    484  1.6  uch dotbpp##b##(x, y) \
    485  1.6  uch 	int x, y; \
    486  1.6  uch { \
    487  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip; \
    488  1.6  uch 	u_int32_t addr; \
    489  1.6  uch 	addr = vc->vc_fbaddr + (((y * vc->vc_fbwidth + x) * \
    490  1.6  uch 				 vc->vc_fbdepth) >> 3); \
    491  1.6  uch 	BPP##b; \
    492  1.6  uch }
    493  1.6  uch 
    494  1.6  uch static void linebpp_unimpl __P((int, int, int, int));
    495  1.6  uch static void dotbpp_unimpl __P((int, int));
    496  1.6  uch static
    497  1.6  uch void linebpp_unimpl(x0, y0, x1, y1)
    498  1.6  uch 	int x0, y0, x1, y1;
    499  1.6  uch {
    500  1.6  uch 	return;
    501  1.6  uch }
    502  1.6  uch static
    503  1.6  uch void dotbpp_unimpl(x, y)
    504  1.6  uch 	int x, y;
    505  1.6  uch {
    506  1.6  uch 	return;
    507  1.6  uch }
    508  1.6  uch 
    509  1.6  uch LINEFUNC(2)
    510  1.6  uch LINEFUNC(4)
    511  1.6  uch LINEFUNC(8)
    512  1.6  uch DOTFUNC(2)
    513  1.6  uch DOTFUNC(4)
    514  1.6  uch DOTFUNC(8)
    515  1.6  uch 
    516  1.6  uch void
    517  1.6  uch tx3912video_attach_drawfunc(vc)
    518  1.6  uch 	struct tx3912video_chip *vc;
    519  1.6  uch {
    520  1.6  uch 	switch (vc->vc_fbdepth) {
    521  1.6  uch 	default:
    522  1.6  uch 		vc->vc_drawline = linebpp_unimpl;
    523  1.6  uch 		vc->vc_drawdot = dotbpp_unimpl;
    524  1.6  uch 		break;
    525  1.6  uch 	case 8:
    526  1.6  uch 		vc->vc_drawline = linebpp8;
    527  1.6  uch 		vc->vc_drawdot = dotbpp8;
    528  1.6  uch 		break;
    529  1.6  uch 	case 4:
    530  1.6  uch 		vc->vc_drawline = linebpp4;
    531  1.6  uch 		vc->vc_drawdot = dotbpp4;
    532  1.6  uch 		break;
    533  1.6  uch 	case 2:
    534  1.6  uch 		vc->vc_drawline = linebpp2;
    535  1.6  uch 		vc->vc_drawdot = dotbpp2;
    536  1.6  uch 		break;
    537  1.6  uch 	}
    538  1.6  uch }
    539  1.6  uch 
    540  1.6  uch void
    541  1.6  uch tx3912video_line(x0, y0, x1, y1)
    542  1.6  uch 	int x0, y0, x1, y1;
    543  1.6  uch {
    544  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    545  1.6  uch 	vc->vc_drawline(x0, y0, x1, y1);
    546  1.6  uch }
    547  1.6  uch 
    548  1.6  uch void
    549  1.6  uch tx3912video_dot(x, y)
    550  1.6  uch 	int x, y;
    551  1.6  uch {
    552  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    553  1.6  uch 	vc->vc_drawdot(x, y);
    554  1.6  uch }
    555