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