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