Home | History | Annotate | Line # | Download | only in tx
tx3912video.c revision 1.7
      1  1.7  uch /*	$NetBSD: tx3912video.c,v 1.7 2000/01/07 15:10:50 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.7  uch 	txreg_t reg;
    170  1.1  uch 
    171  1.1  uch 	/* Inquire bit depth */
    172  1.1  uch 	fb_depth = tx3912video_fbdepth(tc, 0);
    173  1.7  uch 
    174  1.7  uch 	switch (fb_depth) {
    175  1.7  uch 	case 2:
    176  1.7  uch 		bootinfo->fb_type = BIFB_D2_M2L_0;
    177  1.7  uch 		break;
    178  1.7  uch 	case 4:
    179  1.7  uch 		/* XXX should implement rasops4.c */
    180  1.7  uch 		fb_depth = 2;
    181  1.7  uch 		bootinfo->fb_type = BIFB_D2_M2L_0;
    182  1.7  uch 		reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    183  1.7  uch 		TX3912_VIDEOCTRL1_BITSEL_CLR(reg);
    184  1.7  uch 		reg = TX3912_VIDEOCTRL1_BITSEL_SET(
    185  1.7  uch 			reg, TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE);
    186  1.7  uch 		tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    187  1.7  uch 		break;
    188  1.7  uch 	case 8:
    189  1.7  uch 		bootinfo->fb_type = BIFB_D8_FF;
    190  1.7  uch 		break;
    191  1.7  uch 	}
    192  1.7  uch 
    193  1.6  uch 	tx3912video_chip.vc_fbdepth = fb_depth;
    194  1.6  uch 	tx3912video_chip.vc_fbwidth = fb_width;
    195  1.6  uch 	tx3912video_chip.vc_fbheight= fb_height;
    196  1.7  uch 
    197  1.1  uch 
    198  1.1  uch 	/* Allocate framebuffer area */
    199  1.1  uch 	if (tx3912video_framebuffer_alloc(tc, fb_start, fb_width, fb_height,
    200  1.1  uch 					 fb_depth, &addr, &size)) {
    201  1.1  uch 		return 1;
    202  1.1  uch 	}
    203  1.1  uch #if notyet
    204  1.1  uch 	tx3912video_resolution_init(tc, fb_width, fb_height);
    205  1.1  uch #else
    206  1.1  uch 	/* Use Windows CE setting. */
    207  1.1  uch #endif
    208  1.1  uch 	/* Set DMA transfer address to VID module */
    209  1.1  uch 	tx3912video_framebuffer_init(tc, addr, size);
    210  1.1  uch 
    211  1.1  uch 	/* Syncronize framebuffer addr to frame signal */
    212  1.1  uch 	tx3912video_reset(tc);
    213  1.1  uch 
    214  1.1  uch 	*fb_line_bytes = (fb_width * fb_depth) / 8;
    215  1.1  uch 	*fb_addr = addr; /* Phsical address */
    216  1.1  uch 	*fb_size = size;
    217  1.1  uch 
    218  1.1  uch 	return 0;
    219  1.1  uch }
    220  1.1  uch 
    221  1.1  uch  int
    222  1.1  uch tx3912video_framebuffer_alloc(tc, start, h, v, depth, fb_addr, fb_size)
    223  1.1  uch 	tx_chipset_tag_t tc;
    224  1.1  uch 	u_int32_t start;
    225  1.1  uch 	int h, v, depth;
    226  1.1  uch 	u_int32_t *fb_addr, *fb_size;
    227  1.1  uch {
    228  1.1  uch 	struct extent_fixed ex_fixed[2];
    229  1.1  uch 	struct extent *ex;
    230  1.1  uch 	u_long addr, size;
    231  1.1  uch 	int err;
    232  1.1  uch 
    233  1.1  uch 	/* Calcurate frame buffer size */
    234  1.1  uch 	size = (h * v * depth) / 8;
    235  1.1  uch 
    236  1.1  uch 	/* Allocate V-RAM area */
    237  1.1  uch 	if (!(ex = extent_create("Frame buffer address", start,
    238  1.1  uch 				 start + TX3912_FRAMEBUFFER_MAX,
    239  1.1  uch 				 0, (caddr_t)ex_fixed, sizeof ex_fixed,
    240  1.1  uch  				 EX_NOWAIT))) {
    241  1.1  uch 		return 1;
    242  1.1  uch 	}
    243  1.1  uch 	if((err = extent_alloc_subregion(ex, start, start + size, size,
    244  1.1  uch 					 TX3912_FRAMEBUFFER_ALIGNMENT,
    245  1.1  uch 					 TX3912_FRAMEBUFFER_BOUNDARY,
    246  1.1  uch 					 EX_FAST|EX_NOWAIT, &addr))) {
    247  1.1  uch 		return 1;
    248  1.1  uch 	}
    249  1.6  uch 	tx3912video_chip.vc_fbaddr = addr;
    250  1.6  uch 	tx3912video_chip.vc_fbsize = size;
    251  1.6  uch 
    252  1.1  uch 	*fb_addr = addr;
    253  1.1  uch 	*fb_size = size;
    254  1.1  uch 
    255  1.1  uch 	return 0;
    256  1.1  uch }
    257  1.1  uch 
    258  1.1  uch  void
    259  1.1  uch tx3912video_framebuffer_init(tc, fb_addr, fb_size)
    260  1.1  uch 	tx_chipset_tag_t tc;
    261  1.1  uch 	u_int32_t fb_addr, fb_size;
    262  1.1  uch {
    263  1.1  uch 	u_int32_t reg, vaddr, bank, base;
    264  1.1  uch 
    265  1.1  uch 	/*  XXX currently I don't set DFVAL, so force DF signal toggled on
    266  1.1  uch          *  XXX each frame. */
    267  1.1  uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    268  1.1  uch 	reg &= ~TX3912_VIDEOCTRL1_DFMODE;
    269  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    270  1.1  uch 
    271  1.1  uch 	/* Set DMA transfer start and end address */
    272  1.1  uch 
    273  1.1  uch 	bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
    274  1.1  uch 	base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
    275  1.1  uch 	reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
    276  1.1  uch 	/* Upper address counter */
    277  1.1  uch 	reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
    278  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
    279  1.1  uch 
    280  1.1  uch 	/* Lower address counter  */
    281  1.1  uch 	base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
    282  1.1  uch 	reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
    283  1.1  uch 
    284  1.1  uch 	/* Set DF-signal rate */
    285  1.1  uch 	reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
    286  1.1  uch 
    287  1.1  uch 	/* Set VIDDONE signal delay after FRAME signal */
    288  1.1  uch 	/* XXX not yet*/
    289  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
    290  1.1  uch 
    291  1.1  uch 	/* Clear frame buffer */
    292  1.1  uch 	vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
    293  1.1  uch 	bzero((void*)vaddr, fb_size);
    294  1.1  uch }
    295  1.1  uch 
    296  1.1  uch  void
    297  1.1  uch tx3912video_resolution_init(tc, h, v)
    298  1.1  uch 	tx_chipset_tag_t tc;
    299  1.1  uch 	int h;
    300  1.1  uch 	int v;
    301  1.1  uch {
    302  1.1  uch 	u_int32_t reg, val;
    303  1.1  uch 	int split, bit8, horzval, lineval;
    304  1.1  uch 
    305  1.1  uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    306  1.1  uch 	split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
    307  1.1  uch 	bit8  = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
    308  1.1  uch 		 TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
    309  1.1  uch 	val = TX3912_VIDEOCTRL1_BITSEL(reg);
    310  1.1  uch 
    311  1.1  uch 	if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
    312  1.1  uch 	    !split) {
    313  1.3  uch 		/* (LCD horizontal pixels / 8bit) * RGB - 1 */
    314  1.3  uch 		horzval = (h / 8) * 3 - 1;
    315  1.1  uch 	} else {
    316  1.1  uch 		horzval = h / 4 - 1;
    317  1.1  uch 	}
    318  1.1  uch 	lineval = (split ? v / 2 : v) - 1;
    319  1.1  uch 
    320  1.1  uch 	/* Video rate */
    321  1.3  uch 	/* XXX
    322  1.3  uch 	 *  probably This value should be determined from DFINT and LCDINT
    323  1.3  uch 	 */
    324  1.1  uch 	reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
    325  1.1  uch 	/* Horizontal size of LCD */
    326  1.1  uch 	reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
    327  1.1  uch 	/* # of lines for the LCD */
    328  1.1  uch 	reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
    329  1.1  uch 
    330  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
    331  1.1  uch }
    332  1.1  uch 
    333  1.6  uch int
    334  1.1  uch tx3912video_fbdepth(tc, verbose)
    335  1.1  uch 	tx_chipset_tag_t tc;
    336  1.1  uch 	int verbose;
    337  1.1  uch {
    338  1.1  uch 	u_int32_t reg, val;
    339  1.1  uch 
    340  1.1  uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    341  1.1  uch 	val = TX3912_VIDEOCTRL1_BITSEL(reg);
    342  1.1  uch 	switch (val) {
    343  1.1  uch 	case TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR:
    344  1.1  uch 		if (verbose)
    345  1.1  uch 			printf("8bit color");
    346  1.1  uch 		return 8;
    347  1.1  uch 	case TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE:
    348  1.1  uch 		if (verbose)
    349  1.1  uch 			printf("4bit greyscale");
    350  1.1  uch 		return 4;
    351  1.1  uch 	case TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE:
    352  1.1  uch 		if (verbose)
    353  1.1  uch 			printf("2bit greyscale");
    354  1.1  uch 		return 2;
    355  1.1  uch 	case TX3912_VIDEOCTRL1_BITSEL_MONOCHROME:
    356  1.1  uch 		if (verbose)
    357  1.1  uch 			printf("monochrome");
    358  1.1  uch 		return 1;
    359  1.1  uch 	}
    360  1.1  uch 	return 0;
    361  1.1  uch }
    362  1.1  uch 
    363  1.1  uch void
    364  1.1  uch tx3912video_reset(tc)
    365  1.1  uch 	tx_chipset_tag_t tc;
    366  1.1  uch {
    367  1.1  uch 	u_int32_t reg;
    368  1.1  uch 
    369  1.1  uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    370  1.3  uch 
    371  1.1  uch 	/* Disable video logic at end of this frame */
    372  1.1  uch 	reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
    373  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    374  1.3  uch 
    375  1.1  uch 	/* Wait for end of frame */
    376  1.1  uch 	delay(300 * 1000);
    377  1.3  uch 
    378  1.1  uch 	/* Make sure to disable video logic */
    379  1.1  uch 	reg &= ~TX3912_VIDEOCTRL1_ENVID;
    380  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    381  1.3  uch 
    382  1.1  uch 	delay(1000);
    383  1.3  uch 
    384  1.1  uch 	/* Enable video logic again */
    385  1.1  uch 	reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
    386  1.1  uch 	reg |= TX3912_VIDEOCTRL1_ENVID;
    387  1.1  uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    388  1.3  uch 
    389  1.1  uch 	delay(1000);
    390  1.1  uch }
    391  1.1  uch 
    392  1.6  uch /*
    393  1.6  uch  * Debug routines.
    394  1.6  uch  */
    395  1.6  uch 
    396  1.6  uch void
    397  1.6  uch tx3912video_calibration_pattern()
    398  1.6  uch {
    399  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    400  1.6  uch 	int x, y;
    401  1.6  uch 
    402  1.6  uch 	x = vc->vc_fbwidth - 40;
    403  1.6  uch 	y = vc->vc_fbheight - 40;
    404  1.6  uch 	tx3912video_line(40, 40, x , 40);
    405  1.6  uch 	tx3912video_line(x , 40, x , y );
    406  1.6  uch 	tx3912video_line(x , y , 40, y );
    407  1.6  uch 	tx3912video_line(40, y , 40, 40);
    408  1.6  uch 	tx3912video_line(40, 40, x , y );
    409  1.6  uch 	tx3912video_line(x,  40, 40, y );
    410  1.6  uch }
    411  1.6  uch 
    412  1.6  uch #define BPP2 ({ \
    413  1.6  uch 	u_int8_t bitmap; \
    414  1.6  uch 	bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
    415  1.6  uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
    416  1.6  uch 		(bitmap & ~(0x3 << ((3 - (x % 4)) * 2))); \
    417  1.6  uch })
    418  1.6  uch 
    419  1.6  uch #define BPP4 ({ \
    420  1.6  uch 	u_int8_t bitmap; \
    421  1.6  uch 	bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
    422  1.6  uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
    423  1.6  uch 		(bitmap & ~(0xf << ((1 - (x % 2)) * 4))); \
    424  1.6  uch })
    425  1.6  uch 
    426  1.6  uch #define BPP8 ({ \
    427  1.6  uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = 0xff; \
    428  1.6  uch })
    429  1.6  uch 
    430  1.6  uch #define BRESENHAM(a, b, c, d, func) ({ \
    431  1.6  uch 	u_int32_t fbaddr = vc->vc_fbaddr; \
    432  1.6  uch 	u_int32_t fbwidth = vc->vc_fbwidth; \
    433  1.6  uch 	u_int32_t fbdepth = vc->vc_fbdepth; \
    434  1.6  uch 	len = a, step = b -1; \
    435  1.6  uch 	if (step == 0) \
    436  1.6  uch 		return; \
    437  1.6  uch 	kstep = len == 0 ? 0 : 1; \
    438  1.6  uch 	for (i = k = 0, j = step / 2; i <= step; i++) { \
    439  1.6  uch 		x = xbase c; \
    440  1.6  uch 		y = ybase d; \
    441  1.6  uch 		addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3); \
    442  1.6  uch 		func; \
    443  1.6  uch 		j -= len; \
    444  1.6  uch 		while (j < 0) { \
    445  1.6  uch 			j += step; \
    446  1.6  uch 			k += kstep; \
    447  1.6  uch 		} \
    448  1.6  uch 	} \
    449  1.6  uch })
    450  1.6  uch 
    451  1.6  uch #define DRAWLINE(func) ({ \
    452  1.6  uch 	if (x < 0) { \
    453  1.6  uch 		if (y < 0) { \
    454  1.6  uch 			if (_y < _x) { \
    455  1.6  uch 				BRESENHAM(_y, _x, -i, -k, func); \
    456  1.6  uch 			} else { \
    457  1.6  uch 				BRESENHAM(_x, _y, -k, -i, func); \
    458  1.6  uch 			} \
    459  1.6  uch 		} else { \
    460  1.6  uch 			if (_y < _x) { \
    461  1.6  uch 				BRESENHAM(_y, _x, -i, +k, func); \
    462  1.6  uch 			} else { \
    463  1.6  uch 				BRESENHAM(_x, _y, -k, +i, func); \
    464  1.6  uch 			} \
    465  1.6  uch 		} \
    466  1.6  uch 	} else { \
    467  1.6  uch 		if (y < 0) { \
    468  1.6  uch 			if (_y < _x) { \
    469  1.6  uch 				BRESENHAM(_y, _x, +i, -k, func); \
    470  1.6  uch 			} else { \
    471  1.6  uch 				BRESENHAM(_x, _y, +k, -i, func); \
    472  1.6  uch 			} \
    473  1.6  uch 		} else { \
    474  1.6  uch 			if (_y < _x) { \
    475  1.6  uch 				BRESENHAM(_y, _x, +i, +k, func); \
    476  1.6  uch 			} else { \
    477  1.6  uch 				BRESENHAM(_x, _y, +k, +i, func); \
    478  1.6  uch 			} \
    479  1.6  uch 		} \
    480  1.6  uch 	} \
    481  1.6  uch })
    482  1.6  uch 
    483  1.6  uch #define LINEFUNC(b) \
    484  1.6  uch static void linebpp##b __P((int, int, int, int)); \
    485  1.6  uch static void \
    486  1.6  uch linebpp##b##(x0, y0, x1, y1) \
    487  1.6  uch 	int x0, y0, x1, y1; \
    488  1.6  uch { \
    489  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip; \
    490  1.6  uch 	u_int32_t addr; \
    491  1.6  uch 	int i, j, k, len, step, kstep; \
    492  1.6  uch 	int x, _x, y, _y; \
    493  1.6  uch 	int xbase, ybase; \
    494  1.6  uch 	x = x1 - x0; \
    495  1.6  uch 	y = y1 - y0; \
    496  1.6  uch 	_x = abs(x); \
    497  1.6  uch 	_y = abs(y); \
    498  1.6  uch 	xbase = x0; \
    499  1.6  uch 	ybase = y0; \
    500  1.6  uch 	DRAWLINE(BPP##b##); \
    501  1.6  uch }
    502  1.1  uch 
    503  1.6  uch #define DOTFUNC(b) \
    504  1.6  uch static void dotbpp##b __P((int, int)); \
    505  1.6  uch static void \
    506  1.6  uch dotbpp##b##(x, y) \
    507  1.6  uch 	int x, y; \
    508  1.6  uch { \
    509  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip; \
    510  1.6  uch 	u_int32_t addr; \
    511  1.6  uch 	addr = vc->vc_fbaddr + (((y * vc->vc_fbwidth + x) * \
    512  1.6  uch 				 vc->vc_fbdepth) >> 3); \
    513  1.6  uch 	BPP##b; \
    514  1.6  uch }
    515  1.6  uch 
    516  1.6  uch static void linebpp_unimpl __P((int, int, int, int));
    517  1.6  uch static void dotbpp_unimpl __P((int, int));
    518  1.6  uch static
    519  1.6  uch void linebpp_unimpl(x0, y0, x1, y1)
    520  1.6  uch 	int x0, y0, x1, y1;
    521  1.6  uch {
    522  1.6  uch 	return;
    523  1.6  uch }
    524  1.6  uch static
    525  1.6  uch void dotbpp_unimpl(x, y)
    526  1.6  uch 	int x, y;
    527  1.6  uch {
    528  1.6  uch 	return;
    529  1.6  uch }
    530  1.6  uch 
    531  1.6  uch LINEFUNC(2)
    532  1.6  uch LINEFUNC(4)
    533  1.6  uch LINEFUNC(8)
    534  1.6  uch DOTFUNC(2)
    535  1.6  uch DOTFUNC(4)
    536  1.6  uch DOTFUNC(8)
    537  1.6  uch 
    538  1.6  uch void
    539  1.6  uch tx3912video_attach_drawfunc(vc)
    540  1.6  uch 	struct tx3912video_chip *vc;
    541  1.6  uch {
    542  1.6  uch 	switch (vc->vc_fbdepth) {
    543  1.6  uch 	default:
    544  1.6  uch 		vc->vc_drawline = linebpp_unimpl;
    545  1.6  uch 		vc->vc_drawdot = dotbpp_unimpl;
    546  1.6  uch 		break;
    547  1.6  uch 	case 8:
    548  1.6  uch 		vc->vc_drawline = linebpp8;
    549  1.6  uch 		vc->vc_drawdot = dotbpp8;
    550  1.6  uch 		break;
    551  1.6  uch 	case 4:
    552  1.6  uch 		vc->vc_drawline = linebpp4;
    553  1.6  uch 		vc->vc_drawdot = dotbpp4;
    554  1.6  uch 		break;
    555  1.6  uch 	case 2:
    556  1.6  uch 		vc->vc_drawline = linebpp2;
    557  1.6  uch 		vc->vc_drawdot = dotbpp2;
    558  1.6  uch 		break;
    559  1.6  uch 	}
    560  1.6  uch }
    561  1.6  uch 
    562  1.6  uch void
    563  1.6  uch tx3912video_line(x0, y0, x1, y1)
    564  1.6  uch 	int x0, y0, x1, y1;
    565  1.6  uch {
    566  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    567  1.6  uch 	vc->vc_drawline(x0, y0, x1, y1);
    568  1.6  uch }
    569  1.6  uch 
    570  1.6  uch void
    571  1.6  uch tx3912video_dot(x, y)
    572  1.6  uch 	int x, y;
    573  1.6  uch {
    574  1.6  uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    575  1.6  uch 	vc->vc_drawdot(x, y);
    576  1.6  uch }
    577