Home | History | Annotate | Line # | Download | only in tx
tx3912video.c revision 1.14
      1  1.14   uch /*	$NetBSD: tx3912video.c,v 1.14 2000/05/12 18:09:55 uch Exp $ */
      2   1.1   uch 
      3  1.11   uch /*-
      4  1.11   uch  * Copyright (c) 1999, 2000 UCHIYAMA Yasushi.  All rights reserved.
      5   1.1   uch  *
      6   1.1   uch  * Redistribution and use in source and binary forms, with or without
      7   1.1   uch  * modification, are permitted provided that the following conditions
      8   1.1   uch  * are met:
      9   1.1   uch  * 1. Redistributions of source code must retain the above copyright
     10   1.1   uch  *    notice, this list of conditions and the following disclaimer.
     11  1.10   uch  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.10   uch  *    notice, this list of conditions and the following disclaimer in the
     13  1.10   uch  *    documentation and/or other materials provided with the distribution.
     14  1.11   uch  * 3. The name of the author may not be used to endorse or promote products
     15  1.11   uch  *    derived from this software without specific prior written permission.
     16   1.1   uch  *
     17  1.10   uch  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  1.10   uch  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  1.10   uch  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  1.10   uch  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  1.10   uch  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  1.10   uch  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  1.10   uch  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  1.10   uch  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  1.11   uch  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26  1.11   uch  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27   1.1   uch  */
     28  1.13   uch #undef TX3912VIDEO_DEBUG
     29  1.10   uch 
     30   1.1   uch #include "opt_tx39_debug.h"
     31   1.8   uch #include "hpcfb.h"
     32   1.1   uch 
     33   1.1   uch #include <sys/param.h>
     34   1.1   uch #include <sys/systm.h>
     35   1.1   uch #include <sys/device.h>
     36   1.1   uch #include <sys/extent.h>
     37   1.1   uch 
     38  1.11   uch #include <sys/ioctl.h>
     39  1.12   uch #include <sys/buf.h>
     40  1.12   uch #include <vm/vm.h>
     41  1.11   uch 
     42   1.1   uch #include <machine/bus.h>
     43  1.10   uch #include <machine/bootinfo.h>
     44   1.1   uch 
     45   1.1   uch #include <hpcmips/tx/tx39var.h>
     46   1.1   uch #include <hpcmips/tx/tx3912videovar.h>
     47   1.1   uch #include <hpcmips/tx/tx3912videoreg.h>
     48   1.1   uch 
     49  1.12   uch /* CLUT */
     50  1.12   uch #include <dev/wscons/wsdisplayvar.h>
     51  1.12   uch #include <dev/rasops/rasops.h>
     52  1.12   uch #include <arch/hpcmips/dev/video_subr.h>
     53  1.12   uch 
     54   1.9  sato #include <dev/wscons/wsconsio.h>
     55   1.8   uch #include <arch/hpcmips/dev/hpcfbvar.h>
     56   1.8   uch #include <arch/hpcmips/dev/hpcfbio.h>
     57   1.2   uch 
     58  1.10   uch static struct tx3912video_chip {
     59  1.10   uch 	tx_chipset_tag_t vc_tc;
     60   1.6   uch 
     61  1.10   uch 	paddr_t vc_fbaddr;
     62  1.10   uch 	size_t vc_fbsize;
     63  1.10   uch 	int vc_fbdepth;
     64  1.10   uch 	int vc_fbwidth;
     65  1.10   uch 	int vc_fbheight;
     66   1.6   uch 
     67  1.11   uch 	void (*vc_drawline) __P((int, int, int, int)); /* for debug */
     68  1.11   uch 	void (*vc_drawdot) __P((int, int)); /* for debug */
     69  1.10   uch } tx3912video_chip;
     70   1.6   uch 
     71   1.1   uch struct tx3912video_softc {
     72   1.1   uch 	struct device sc_dev;
     73  1.11   uch 	struct hpcfb_fbconf sc_fbconf;
     74  1.11   uch 	struct hpcfb_dspconf sc_dspconf;
     75   1.6   uch 	struct tx3912video_chip *sc_chip;
     76   1.1   uch };
     77   1.1   uch 
     78  1.11   uch void	tx3912video_framebuffer_init __P((struct tx3912video_chip *));
     79  1.11   uch int	tx3912video_framebuffer_alloc __P((struct tx3912video_chip *, paddr_t,
     80  1.10   uch 					paddr_t *));
     81  1.11   uch void	tx3912video_reset __P((struct tx3912video_chip *));
     82  1.11   uch void	tx3912video_resolution_init __P((struct tx3912video_chip *));
     83  1.10   uch 
     84  1.10   uch int	tx3912video_match __P((struct device *, struct cfdata *, void *));
     85  1.10   uch void	tx3912video_attach __P((struct device *, struct device *, void *));
     86  1.10   uch int	tx3912video_print __P((void *, const char *));
     87   1.1   uch 
     88  1.11   uch void	tx3912video_hpcfbinit __P((struct tx3912video_softc *));
     89  1.11   uch int	tx3912video_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
     90  1.11   uch int	tx3912video_mmap __P((void *, off_t, int));
     91  1.11   uch 
     92  1.12   uch void	tx3912video_clut_init __P((struct tx3912video_softc *));
     93  1.12   uch void	tx3912video_clut_install __P((void *, struct rasops_info *));
     94  1.12   uch void	tx3912video_clut_get __P((struct tx3912video_softc *,
     95  1.12   uch 				u_int32_t *, int, int));
     96  1.12   uch static int __get_color8 __P((int));
     97  1.12   uch static int __get_color4 __P((int));
     98  1.12   uch 
     99   1.1   uch struct cfattach tx3912video_ca = {
    100   1.3   uch 	sizeof(struct tx3912video_softc), tx3912video_match,
    101   1.3   uch 	tx3912video_attach
    102   1.1   uch };
    103   1.1   uch 
    104  1.11   uch struct hpcfb_accessops tx3912video_ha = {
    105  1.12   uch 	tx3912video_ioctl, tx3912video_mmap, 0, 0, 0, 0,
    106  1.12   uch 	tx3912video_clut_install
    107  1.11   uch };
    108  1.11   uch 
    109  1.10   uch void	__tx3912video_attach_drawfunc __P((struct tx3912video_chip*));
    110   1.6   uch 
    111   1.1   uch int
    112   1.1   uch tx3912video_match(parent, cf, aux)
    113   1.1   uch 	struct device *parent;
    114   1.1   uch 	struct cfdata *cf;
    115   1.1   uch 	void *aux;
    116   1.1   uch {
    117  1.10   uch 	return (1);
    118   1.1   uch }
    119   1.1   uch 
    120   1.1   uch void
    121   1.1   uch tx3912video_attach(parent, self, aux)
    122   1.1   uch 	struct device *parent;
    123   1.1   uch 	struct device *self;
    124   1.1   uch 	void *aux;
    125   1.1   uch {
    126  1.10   uch 	struct tx3912video_softc *sc = (void *)self;
    127  1.10   uch 	struct tx3912video_chip *chip;
    128  1.10   uch 	const char *depth_print[] = {
    129  1.10   uch 		[TX3912_VIDEOCTRL1_BITSEL_MONOCHROME] = "monochrome",
    130  1.10   uch 		[TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE] = "2bit greyscale",
    131  1.10   uch 		[TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE] = "4bit greyscale",
    132  1.10   uch 		[TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR] = "8bit color"
    133  1.10   uch 	};
    134  1.11   uch 	struct hpcfb_attach_args ha;
    135  1.12   uch 	tx_chipset_tag_t tc;
    136  1.12   uch 	txreg_t val;
    137  1.11   uch 	int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
    138  1.10   uch 
    139  1.10   uch 	sc->sc_chip = chip = &tx3912video_chip;
    140  1.10   uch 
    141  1.10   uch 	/* print video module information */
    142  1.10   uch 	printf(": %s, frame buffer 0x%08x-0x%08x\n",
    143  1.10   uch 	       depth_print[(ffs(chip->vc_fbdepth) - 1) & 0x3],
    144  1.10   uch 	       (unsigned)chip->vc_fbaddr,
    145  1.10   uch 	       (unsigned)(chip->vc_fbaddr + chip->vc_fbsize));
    146   1.5   uch 
    147  1.12   uch 	/* don't inverse VDAT[3:0] signal */
    148  1.12   uch 	tc = chip->vc_tc;
    149  1.12   uch 	val = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    150  1.12   uch 	val &= ~TX3912_VIDEOCTRL1_INVVID;
    151  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, val);
    152  1.12   uch 
    153  1.12   uch 	/* install default CLUT */
    154  1.12   uch 	tx3912video_clut_init(sc);
    155  1.12   uch 
    156  1.10   uch 	/* if serial console, power off video module */
    157   1.6   uch #ifndef TX3912VIDEO_DEBUG
    158  1.11   uch 	if (!console) {
    159   1.5   uch 		printf("%s: power off\n", sc->sc_dev.dv_xname);
    160  1.13   uch 		val = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    161  1.13   uch 		val &= ~(TX3912_VIDEOCTRL1_DISPON |
    162   1.4   uch 			 TX3912_VIDEOCTRL1_ENVID);
    163  1.13   uch 		tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, val);
    164   1.4   uch 	}
    165   1.6   uch #endif /* TX3912VIDEO_DEBUG */
    166   1.6   uch 
    167  1.13   uch #ifdef TX3912VIDEO_DEBUG
    168  1.10   uch 	/* attach debug draw routine (debugging use) */
    169  1.10   uch 	__tx3912video_attach_drawfunc(sc->sc_chip);
    170  1.13   uch #endif
    171  1.10   uch 
    172   1.1   uch 	/* Attach frame buffer device */
    173  1.11   uch 	tx3912video_hpcfbinit(sc);
    174  1.11   uch 
    175  1.11   uch 	if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
    176  1.11   uch 		panic("tx3912video_attach: can't init fb console");
    177   1.2   uch 	}
    178  1.11   uch 
    179  1.11   uch 	ha.ha_console = console;
    180  1.11   uch 	ha.ha_accessops = &tx3912video_ha;
    181  1.11   uch 	ha.ha_accessctx = sc;
    182  1.11   uch 	ha.ha_curfbconf = 0;
    183  1.11   uch 	ha.ha_nfbconf = 1;
    184  1.11   uch 	ha.ha_fbconflist = &sc->sc_fbconf;
    185  1.11   uch 	ha.ha_curdspconf = 0;
    186  1.11   uch 	ha.ha_ndspconf = 1;
    187  1.11   uch 	ha.ha_dspconflist = &sc->sc_dspconf;
    188  1.11   uch 
    189  1.11   uch 	config_found(self, &ha, hpcfbprint);
    190   1.1   uch }
    191   1.1   uch 
    192  1.11   uch void
    193  1.11   uch tx3912video_hpcfbinit(sc)
    194  1.11   uch 	struct tx3912video_softc *sc;
    195   1.1   uch {
    196  1.11   uch 	struct tx3912video_chip *chip = sc->sc_chip;
    197  1.11   uch 	struct hpcfb_fbconf *fb = &sc->sc_fbconf;
    198  1.13   uch 	vaddr_t fbvaddr = (vaddr_t)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
    199  1.11   uch 
    200  1.11   uch 	memset(fb, 0, sizeof(struct hpcfb_fbconf));
    201  1.11   uch 
    202  1.11   uch 	fb->hf_conf_index	= 0;	/* configuration index		*/
    203  1.11   uch 	fb->hf_nconfs		= 1;   	/* how many configurations	*/
    204  1.12   uch 	strncpy(fb->hf_name, "TX3912 built-in video", HPCFB_MAXNAMELEN);
    205  1.11   uch 					/* frame buffer name		*/
    206  1.12   uch 	strncpy(fb->hf_conf_name, "LCD", HPCFB_MAXNAMELEN);
    207  1.11   uch 					/* configuration name		*/
    208  1.11   uch 	fb->hf_height		= chip->vc_fbheight;
    209  1.11   uch 	fb->hf_width		= chip->vc_fbwidth;
    210  1.13   uch 	fb->hf_baseaddr		= mips_ptob(mips_btop(fbvaddr));
    211  1.13   uch 	fb->hf_offset		= (u_long)fbvaddr - fb->hf_baseaddr;
    212  1.11   uch 					/* frame buffer start offset   	*/
    213  1.12   uch 	fb->hf_bytes_per_line	= (chip->vc_fbwidth * chip->vc_fbdepth)
    214  1.12   uch 		/ NBBY;
    215  1.11   uch 	fb->hf_nplanes		= 1;
    216  1.11   uch 	fb->hf_bytes_per_plane	= chip->vc_fbheight * fb->hf_bytes_per_line;
    217  1.11   uch 
    218  1.11   uch 	fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
    219  1.11   uch 	fb->hf_access_flags |= HPCFB_ACCESS_WORD;
    220  1.11   uch 	fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
    221  1.11   uch 
    222  1.11   uch 	switch (chip->vc_fbdepth) {
    223  1.11   uch 	default:
    224  1.11   uch 		panic("tx3912video_hpcfbinit: not supported color depth\n");
    225  1.11   uch 		/* NOTREACHED */
    226  1.11   uch 	case 2:
    227  1.11   uch 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
    228  1.11   uch 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    229  1.11   uch 		fb->hf_pack_width = 8;
    230  1.11   uch 		fb->hf_pixels_per_pack = 4;
    231  1.11   uch 		fb->hf_pixel_width = 2;
    232  1.11   uch 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
    233  1.14   uch 		/* reserved for future use */
    234  1.14   uch 		fb->hf_u.hf_gray.hf_flags = 0;
    235  1.11   uch 		break;
    236  1.11   uch 	case 8:
    237  1.12   uch 		fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
    238  1.11   uch 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    239  1.11   uch 		fb->hf_pack_width = 8;
    240  1.11   uch 		fb->hf_pixels_per_pack = 1;
    241  1.11   uch 		fb->hf_pixel_width = 8;
    242  1.11   uch 		fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
    243  1.14   uch 		/* reserved for future use */
    244  1.14   uch 		fb->hf_u.hf_indexed.hf_flags = 0;
    245  1.11   uch 		break;
    246  1.11   uch 	}
    247   1.1   uch }
    248   1.1   uch 
    249   1.1   uch int
    250  1.10   uch tx3912video_init(fb_start, fb_end)
    251  1.10   uch 	paddr_t fb_start, *fb_end;
    252  1.10   uch {
    253  1.10   uch 	struct tx3912video_chip *chip = &tx3912video_chip;
    254   1.1   uch 	tx_chipset_tag_t tc;
    255   1.7   uch 	txreg_t reg;
    256  1.10   uch 	int fbdepth;
    257  1.10   uch 	int error;
    258   1.1   uch 
    259  1.10   uch 	chip->vc_tc = tc = tx_conf_get_tag();
    260  1.10   uch 
    261  1.10   uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    262  1.10   uch 	fbdepth = 1 << (TX3912_VIDEOCTRL1_BITSEL(reg));
    263   1.7   uch 
    264  1.10   uch 	switch (fbdepth) {
    265   1.7   uch 	case 2:
    266   1.7   uch 		bootinfo->fb_type = BIFB_D2_M2L_0;
    267   1.7   uch 		break;
    268   1.7   uch 	case 4:
    269   1.7   uch 		/* XXX should implement rasops4.c */
    270  1.10   uch 		fbdepth = 2;
    271   1.7   uch 		bootinfo->fb_type = BIFB_D2_M2L_0;
    272   1.7   uch 		reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    273   1.7   uch 		TX3912_VIDEOCTRL1_BITSEL_CLR(reg);
    274   1.7   uch 		reg = TX3912_VIDEOCTRL1_BITSEL_SET(
    275   1.7   uch 			reg, TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE);
    276   1.7   uch 		tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    277   1.7   uch 		break;
    278   1.7   uch 	case 8:
    279   1.7   uch 		bootinfo->fb_type = BIFB_D8_FF;
    280   1.7   uch 		break;
    281   1.7   uch 	}
    282   1.7   uch 
    283  1.10   uch 	tx3912video_chip.vc_fbdepth = fbdepth;
    284  1.10   uch 	tx3912video_chip.vc_fbwidth = bootinfo->fb_width;
    285  1.10   uch 	tx3912video_chip.vc_fbheight= bootinfo->fb_height;
    286   1.7   uch 
    287   1.1   uch 	/* Allocate framebuffer area */
    288  1.10   uch 	error = tx3912video_framebuffer_alloc(chip, fb_start, fb_end);
    289  1.10   uch 	if (error != 0)
    290  1.10   uch 		return (1);
    291  1.10   uch 
    292   1.1   uch #if notyet
    293  1.10   uch 	tx3912video_resolution_init(chip);
    294   1.1   uch #else
    295   1.1   uch 	/* Use Windows CE setting. */
    296   1.1   uch #endif
    297   1.1   uch 	/* Set DMA transfer address to VID module */
    298  1.10   uch 	tx3912video_framebuffer_init(chip);
    299   1.1   uch 
    300   1.1   uch 	/* Syncronize framebuffer addr to frame signal */
    301  1.10   uch 	tx3912video_reset(chip);
    302   1.1   uch 
    303  1.10   uch 	bootinfo->fb_line_bytes = (chip->vc_fbwidth * fbdepth) / NBBY;
    304  1.10   uch 	bootinfo->fb_addr = (void *)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
    305  1.10   uch 
    306  1.10   uch 	return (0);
    307   1.1   uch }
    308   1.1   uch 
    309   1.1   uch  int
    310  1.10   uch tx3912video_framebuffer_alloc(chip, fb_start, fb_end)
    311  1.10   uch 	struct tx3912video_chip *chip;
    312  1.10   uch 	paddr_t fb_start, *fb_end; /* buffer allocation hint */
    313   1.1   uch {
    314  1.10   uch 	struct extent_fixed ex_fixed[10];
    315   1.1   uch 	struct extent *ex;
    316   1.1   uch 	u_long addr, size;
    317  1.10   uch 	int error;
    318  1.10   uch 
    319  1.10   uch 	/* calcurate frame buffer size */
    320  1.10   uch 	size = (chip->vc_fbwidth * chip->vc_fbheight * chip->vc_fbdepth) /
    321  1.10   uch 		NBBY;
    322  1.10   uch 
    323  1.10   uch 	/* extent V-RAM region */
    324  1.10   uch 	ex = extent_create("Frame buffer address", fb_start, *fb_end,
    325  1.10   uch 			   0, (caddr_t)ex_fixed, sizeof ex_fixed,
    326  1.10   uch 			   EX_NOWAIT);
    327  1.10   uch 	if (ex == 0)
    328  1.10   uch 		return (1);
    329   1.1   uch 
    330   1.1   uch 	/* Allocate V-RAM area */
    331  1.14   uch 	error = extent_alloc_subregion(ex, fb_start, fb_start + size - 1,
    332  1.14   uch 				       size, TX3912_FRAMEBUFFER_ALIGNMENT,
    333  1.10   uch 				       TX3912_FRAMEBUFFER_BOUNDARY,
    334  1.10   uch 				       EX_FAST|EX_NOWAIT, &addr);
    335  1.10   uch 	extent_destroy(ex);
    336  1.10   uch 
    337  1.10   uch 	if (error != 0) {
    338  1.10   uch 		return (1);
    339   1.1   uch 	}
    340  1.10   uch 
    341  1.10   uch 	chip->vc_fbaddr = addr;
    342  1.10   uch 	chip->vc_fbsize = size;
    343   1.6   uch 
    344  1.10   uch 	*fb_end = addr + size;
    345   1.1   uch 
    346  1.10   uch 	return (0);
    347   1.1   uch }
    348   1.1   uch 
    349   1.1   uch  void
    350  1.10   uch tx3912video_framebuffer_init(chip)
    351  1.10   uch 	struct tx3912video_chip *chip;
    352   1.1   uch {
    353  1.10   uch 	u_int32_t fb_addr, fb_size, vaddr, bank, base;
    354  1.10   uch 	txreg_t reg;
    355  1.10   uch 	tx_chipset_tag_t tc = chip->vc_tc;
    356  1.10   uch 
    357  1.10   uch 	fb_addr = chip->vc_fbaddr;
    358  1.10   uch 	fb_size = chip->vc_fbsize;
    359   1.1   uch 
    360   1.1   uch 	/*  XXX currently I don't set DFVAL, so force DF signal toggled on
    361   1.1   uch          *  XXX each frame. */
    362   1.1   uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    363   1.1   uch 	reg &= ~TX3912_VIDEOCTRL1_DFMODE;
    364   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    365   1.1   uch 
    366   1.1   uch 	/* Set DMA transfer start and end address */
    367  1.10   uch 
    368   1.1   uch 	bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
    369   1.1   uch 	base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
    370   1.1   uch 	reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
    371   1.1   uch 	/* Upper address counter */
    372   1.1   uch 	reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
    373   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
    374   1.1   uch 
    375   1.1   uch 	/* Lower address counter  */
    376   1.1   uch 	base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
    377   1.1   uch 	reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
    378   1.1   uch 
    379   1.1   uch 	/* Set DF-signal rate */
    380   1.1   uch 	reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
    381   1.1   uch 
    382   1.1   uch 	/* Set VIDDONE signal delay after FRAME signal */
    383   1.1   uch 	/* XXX not yet*/
    384   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
    385   1.1   uch 
    386   1.1   uch 	/* Clear frame buffer */
    387   1.1   uch 	vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
    388  1.10   uch 	memset((void*)vaddr, 0, fb_size);
    389   1.1   uch }
    390   1.1   uch 
    391   1.1   uch  void
    392  1.10   uch tx3912video_resolution_init(chip)
    393  1.10   uch 	struct tx3912video_chip *chip;
    394   1.1   uch {
    395  1.10   uch 	int h, v, split, bit8, horzval, lineval;
    396  1.10   uch 	tx_chipset_tag_t tc = chip->vc_tc;
    397  1.10   uch 	txreg_t reg;
    398  1.10   uch 	u_int32_t val;
    399  1.10   uch 
    400  1.10   uch 	h = chip->vc_fbwidth;
    401  1.10   uch 	v = chip->vc_fbheight;
    402   1.1   uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    403   1.1   uch 	split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
    404   1.1   uch 	bit8  = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
    405   1.1   uch 		 TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
    406   1.1   uch 	val = TX3912_VIDEOCTRL1_BITSEL(reg);
    407   1.1   uch 
    408   1.1   uch 	if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
    409   1.1   uch 	    !split) {
    410   1.3   uch 		/* (LCD horizontal pixels / 8bit) * RGB - 1 */
    411   1.3   uch 		horzval = (h / 8) * 3 - 1;
    412   1.1   uch 	} else {
    413   1.1   uch 		horzval = h / 4 - 1;
    414   1.1   uch 	}
    415   1.1   uch 	lineval = (split ? v / 2 : v) - 1;
    416   1.1   uch 
    417   1.1   uch 	/* Video rate */
    418   1.3   uch 	/* XXX
    419   1.3   uch 	 *  probably This value should be determined from DFINT and LCDINT
    420   1.3   uch 	 */
    421   1.1   uch 	reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
    422   1.1   uch 	/* Horizontal size of LCD */
    423   1.1   uch 	reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
    424   1.1   uch 	/* # of lines for the LCD */
    425   1.1   uch 	reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
    426   1.1   uch 
    427   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
    428   1.1   uch }
    429   1.1   uch 
    430   1.1   uch void
    431  1.10   uch tx3912video_reset(chip)
    432  1.10   uch 	struct tx3912video_chip *chip;
    433   1.1   uch {
    434  1.10   uch 	tx_chipset_tag_t tc = chip->vc_tc;
    435  1.10   uch 	txreg_t reg;
    436   1.1   uch 
    437   1.1   uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    438   1.3   uch 
    439   1.1   uch 	/* Disable video logic at end of this frame */
    440   1.1   uch 	reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
    441   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    442   1.3   uch 
    443   1.1   uch 	/* Wait for end of frame */
    444  1.10   uch 	delay(30 * 1000);
    445   1.3   uch 
    446   1.1   uch 	/* Make sure to disable video logic */
    447   1.1   uch 	reg &= ~TX3912_VIDEOCTRL1_ENVID;
    448   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    449   1.3   uch 
    450   1.1   uch 	delay(1000);
    451   1.3   uch 
    452   1.1   uch 	/* Enable video logic again */
    453   1.1   uch 	reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
    454   1.1   uch 	reg |= TX3912_VIDEOCTRL1_ENVID;
    455   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    456   1.3   uch 
    457   1.1   uch 	delay(1000);
    458   1.1   uch }
    459   1.1   uch 
    460  1.11   uch int
    461  1.11   uch tx3912video_ioctl(v, cmd, data, flag, p)
    462  1.11   uch 	void *v;
    463  1.11   uch 	u_long cmd;
    464  1.11   uch 	caddr_t data;
    465  1.11   uch 	int flag;
    466  1.11   uch 	struct proc *p;
    467  1.11   uch {
    468  1.11   uch 	struct tx3912video_softc *sc = (struct tx3912video_softc *)v;
    469  1.11   uch 	struct hpcfb_fbconf *fbconf;
    470  1.11   uch 	struct hpcfb_dspconf *dspconf;
    471  1.12   uch 	struct wsdisplay_cmap *cmap;
    472  1.12   uch 	u_int8_t *r, *g, *b;
    473  1.12   uch 	u_int32_t *rgb;
    474  1.12   uch 	int idx, cnt, error;
    475  1.11   uch 
    476  1.11   uch 	switch (cmd) {
    477  1.11   uch 	case WSDISPLAYIO_GETCMAP:
    478  1.12   uch 		cmap = (struct wsdisplay_cmap*)data;
    479  1.12   uch 		cnt = cmap->count;
    480  1.12   uch 		idx = cmap->index;
    481  1.12   uch 
    482  1.12   uch 		if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
    483  1.12   uch 			sc->sc_fbconf.hf_pack_width != 8 ||
    484  1.12   uch 			!LEGAL_CLUT_INDEX(idx) ||
    485  1.12   uch 			!LEGAL_CLUT_INDEX(idx + cnt -1)) {
    486  1.12   uch 			return (EINVAL);
    487  1.12   uch 		}
    488  1.12   uch 
    489  1.12   uch 		if (!uvm_useracc(cmap->red, cnt, B_WRITE) ||
    490  1.12   uch 		    !uvm_useracc(cmap->green, cnt, B_WRITE) ||
    491  1.12   uch 		    !uvm_useracc(cmap->blue, cnt, B_WRITE)) {
    492  1.12   uch 			return (EFAULT);
    493  1.12   uch 		}
    494  1.12   uch 
    495  1.12   uch 		error = cmap_work_alloc(&r, &g, &b, &rgb, cnt);
    496  1.12   uch 		if (error != 0) {
    497  1.12   uch 			cmap_work_free(r, g, b, rgb);
    498  1.12   uch 			return  (ENOMEM);
    499  1.12   uch 		}
    500  1.12   uch 		tx3912video_clut_get(sc, rgb, idx, cnt);
    501  1.12   uch 		rgb24_decompose(rgb, r, g, b, cnt);
    502  1.12   uch 
    503  1.12   uch 		copyout(r, cmap->red, cnt);
    504  1.12   uch 		copyout(g, cmap->green,cnt);
    505  1.12   uch 		copyout(b, cmap->blue, cnt);
    506  1.12   uch 
    507  1.12   uch 		cmap_work_free(r, g, b, rgb);
    508  1.12   uch 
    509  1.12   uch 		return (0);
    510  1.11   uch 
    511  1.11   uch 	case WSDISPLAYIO_PUTCMAP:
    512  1.12   uch 		/*
    513  1.12   uch 		 * TX3912 can't change CLUT index. R:G:B = 3:3:2
    514  1.12   uch 		 */
    515  1.14   uch 		return (0);
    516  1.11   uch 
    517  1.11   uch 	case HPCFBIO_GCONF:
    518  1.11   uch 		fbconf = (struct hpcfb_fbconf *)data;
    519  1.11   uch 		if (fbconf->hf_conf_index != 0 &&
    520  1.11   uch 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
    521  1.11   uch 			return (EINVAL);
    522  1.11   uch 		}
    523  1.11   uch 		*fbconf = sc->sc_fbconf;	/* structure assignment */
    524  1.11   uch 		return (0);
    525  1.11   uch 
    526  1.11   uch 	case HPCFBIO_SCONF:
    527  1.11   uch 		fbconf = (struct hpcfb_fbconf *)data;
    528  1.11   uch 		if (fbconf->hf_conf_index != 0 &&
    529  1.11   uch 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
    530  1.11   uch 			return (EINVAL);
    531  1.11   uch 		}
    532  1.11   uch 		/*
    533  1.11   uch 		 * nothing to do because we have only one configration
    534  1.11   uch 		 */
    535  1.11   uch 		return (0);
    536  1.11   uch 
    537  1.11   uch 	case HPCFBIO_GDSPCONF:
    538  1.11   uch 		dspconf = (struct hpcfb_dspconf *)data;
    539  1.11   uch 		if ((dspconf->hd_unit_index != 0 &&
    540  1.11   uch 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
    541  1.11   uch 		    (dspconf->hd_conf_index != 0 &&
    542  1.11   uch 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
    543  1.11   uch 			return (EINVAL);
    544  1.11   uch 		}
    545  1.11   uch 		*dspconf = sc->sc_dspconf;	/* structure assignment */
    546  1.11   uch 		return (0);
    547  1.11   uch 
    548  1.11   uch 	case HPCFBIO_SDSPCONF:
    549  1.11   uch 		dspconf = (struct hpcfb_dspconf *)data;
    550  1.11   uch 		if ((dspconf->hd_unit_index != 0 &&
    551  1.11   uch 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
    552  1.11   uch 		    (dspconf->hd_conf_index != 0 &&
    553  1.11   uch 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
    554  1.11   uch 			return (EINVAL);
    555  1.11   uch 		}
    556  1.11   uch 		/*
    557  1.11   uch 		 * nothing to do
    558  1.11   uch 		 * because we have only one unit and one configration
    559  1.11   uch 		 */
    560  1.11   uch 		return (0);
    561  1.11   uch 
    562  1.11   uch 	case HPCFBIO_GOP:
    563  1.11   uch 	case HPCFBIO_SOP:
    564  1.11   uch 		/* XXX not implemented yet */
    565  1.11   uch 		return (EINVAL);
    566  1.11   uch 	}
    567  1.11   uch 
    568  1.11   uch 	return (ENOTTY);
    569  1.11   uch }
    570  1.11   uch 
    571  1.11   uch int
    572  1.11   uch tx3912video_mmap(ctx, offset, prot)
    573  1.11   uch 	void *ctx;
    574  1.11   uch 	off_t offset;
    575  1.11   uch 	int prot;
    576  1.11   uch {
    577  1.11   uch 	struct tx3912video_softc *sc = (struct tx3912video_softc *)ctx;
    578  1.11   uch 
    579  1.11   uch 	if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane +
    580  1.11   uch 			   sc->sc_fbconf.hf_offset) <  offset) {
    581  1.11   uch 		return (-1);
    582  1.11   uch 	}
    583  1.11   uch 
    584  1.11   uch 	return (mips_btop(sc->sc_chip->vc_fbaddr + offset));
    585  1.12   uch }
    586  1.12   uch 
    587  1.12   uch /*
    588  1.12   uch  * CLUT staff
    589  1.12   uch  */
    590  1.12   uch static const struct {
    591  1.12   uch 	int mul, div;
    592  1.12   uch } dither_list [] = {
    593  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_1]	= { 1, 1 },
    594  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_6_7]	= { 6, 7 },
    595  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_4_5]	= { 4, 5 },
    596  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_3_4]	= { 3, 4 },
    597  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_5_7]	= { 5, 7 },
    598  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_2_3]	= { 2, 3 },
    599  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_3_5]	= { 3, 5 },
    600  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_4_7]	= { 4, 7 },
    601  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_2_4]	= { 2, 4 },
    602  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_3_7]	= { 3, 7 },
    603  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_2_5]	= { 2, 5 },
    604  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_1_3]	= { 1, 3 },
    605  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_2_7]	= { 2, 7 },
    606  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_1_5]	= { 1, 5 },
    607  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_1_7]	= { 1, 7 },
    608  1.12   uch 	[TX3912_VIDEO_DITHER_DUTYCYCLE_0]	= { 0, 1 }
    609  1.12   uch }, *dlp;
    610  1.12   uch 
    611  1.12   uch static const int dither_level8[8] = {
    612  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_0,
    613  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_2_7,
    614  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_2_5,
    615  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_2_4,
    616  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_3_5,
    617  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_5_7,
    618  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_4_5,
    619  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_1,
    620  1.12   uch };
    621  1.12   uch 
    622  1.12   uch static const int dither_level4[4] = {
    623  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_0,
    624  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_1_3,
    625  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_5_7,
    626  1.12   uch 	TX3912_VIDEO_DITHER_DUTYCYCLE_1,
    627  1.12   uch };
    628  1.12   uch 
    629  1.12   uch static int
    630  1.12   uch __get_color8(luti)
    631  1.12   uch 	int luti;
    632  1.12   uch {
    633  1.12   uch 	KASSERT(luti >=0 && luti < 8);
    634  1.12   uch 	dlp = &dither_list[dither_level8[luti]];
    635  1.12   uch 
    636  1.12   uch 	return ((0xff * dlp->mul) / dlp->div);
    637  1.12   uch }
    638  1.12   uch 
    639  1.12   uch static int
    640  1.12   uch __get_color4(luti)
    641  1.12   uch 	int luti;
    642  1.12   uch {
    643  1.12   uch 	KASSERT(luti >=0 && luti < 4);
    644  1.12   uch 	dlp = &dither_list[dither_level4[luti]];
    645  1.12   uch 
    646  1.12   uch 	return ((0xff * dlp->mul) / dlp->div);
    647  1.12   uch }
    648  1.12   uch 
    649  1.12   uch void
    650  1.12   uch tx3912video_clut_get(sc, rgb, beg, cnt)
    651  1.12   uch 	struct tx3912video_softc *sc;
    652  1.12   uch 	u_int32_t *rgb;
    653  1.12   uch 	int beg, cnt;
    654  1.12   uch {
    655  1.12   uch 	int i;
    656  1.12   uch 
    657  1.12   uch 	KASSERT(rgb);
    658  1.12   uch 	KASSERT(LEGAL_CLUT_INDEX(beg));
    659  1.12   uch 	KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1));
    660  1.12   uch 
    661  1.14   uch 	for (i = beg; i < beg + cnt; i++) {
    662  1.14   uch 		*rgb++ =  RGB24(__get_color8((i >> 5) & 0x7),
    663  1.12   uch 				__get_color8((i >> 2) & 0x7),
    664  1.12   uch 				__get_color4(i & 0x3));
    665  1.12   uch 	}
    666  1.12   uch }
    667  1.12   uch 
    668  1.12   uch void
    669  1.12   uch tx3912video_clut_install(ctx, ri)
    670  1.12   uch 	void *ctx;
    671  1.12   uch 	struct rasops_info *ri;
    672  1.12   uch {
    673  1.12   uch 	struct tx3912video_softc *sc = ctx;
    674  1.12   uch 	const int system_cmap[0x10] = {
    675  1.12   uch 		TX3912VIDEO_BLACK,
    676  1.12   uch 		TX3912VIDEO_RED,
    677  1.12   uch 		TX3912VIDEO_GREEN,
    678  1.12   uch 		TX3912VIDEO_YELLOW,
    679  1.12   uch 		TX3912VIDEO_BLUE,
    680  1.12   uch 		TX3912VIDEO_MAGENTA,
    681  1.12   uch 		TX3912VIDEO_CYAN,
    682  1.12   uch 		TX3912VIDEO_WHITE,
    683  1.12   uch 		TX3912VIDEO_DARK_BLACK,
    684  1.12   uch 		TX3912VIDEO_DARK_RED,
    685  1.12   uch 		TX3912VIDEO_DARK_GREEN,
    686  1.12   uch 		TX3912VIDEO_DARK_YELLOW,
    687  1.12   uch 		TX3912VIDEO_DARK_BLUE,
    688  1.12   uch 		TX3912VIDEO_DARK_MAGENTA,
    689  1.12   uch 		TX3912VIDEO_DARK_CYAN,
    690  1.12   uch 		TX3912VIDEO_DARK_WHITE,
    691  1.12   uch 	};
    692  1.12   uch 
    693  1.12   uch 	KASSERT(ri);
    694  1.12   uch 
    695  1.12   uch 	if (sc->sc_chip->vc_fbdepth == 8) {
    696  1.12   uch 		/* XXX 2bit gray scale LUT not supported */
    697  1.12   uch 		memcpy(ri->ri_devcmap, system_cmap, sizeof system_cmap);
    698  1.12   uch 	}
    699  1.12   uch }
    700  1.12   uch 
    701  1.12   uch void
    702  1.12   uch tx3912video_clut_init(sc)
    703  1.12   uch 	struct tx3912video_softc *sc;
    704  1.12   uch {
    705  1.12   uch 	tx_chipset_tag_t tc = sc->sc_chip->vc_tc;
    706  1.12   uch 
    707  1.12   uch 	if (sc->sc_chip->vc_fbdepth != 8) {
    708  1.12   uch 		return; /* XXX 2bit gray scale LUT not supported */
    709  1.12   uch 	}
    710  1.12   uch 
    711  1.12   uch 	/*
    712  1.12   uch 	 * time-based dithering pattern (TOSHIBA recommended pattern)
    713  1.12   uch 	 */
    714  1.12   uch 	/* 2/3, 1/3 */
    715  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL8_REG,
    716  1.12   uch 		      TX3912_VIDEOCTRL8_PAT2_3_DEFAULT);
    717  1.12   uch 	/* 3/4, 2/4 */
    718  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL9_REG,
    719  1.12   uch 		      (TX3912_VIDEOCTRL9_PAT3_4_DEFAULT << 16) |
    720  1.12   uch 		      TX3912_VIDEOCTRL9_PAT2_4_DEFAULT);
    721  1.12   uch 	/* 4/5, 1/5 */
    722  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL10_REG,
    723  1.12   uch 		      TX3912_VIDEOCTRL10_PAT4_5_DEFAULT);
    724  1.12   uch 	/* 3/5, 2/5 */
    725  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL11_REG,
    726  1.12   uch 		      TX3912_VIDEOCTRL11_PAT3_5_DEFAULT);
    727  1.12   uch 	/* 6/7, 1/7 */
    728  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL12_REG,
    729  1.12   uch 		      TX3912_VIDEOCTRL12_PAT6_7_DEFAULT);
    730  1.12   uch 	/* 5/7, 2/7 */
    731  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL13_REG,
    732  1.12   uch 		      TX3912_VIDEOCTRL13_PAT5_7_DEFAULT);
    733  1.12   uch 	/* 4/7, 3/7 */
    734  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL14_REG,
    735  1.12   uch 		      TX3912_VIDEOCTRL14_PAT4_7_DEFAULT);
    736  1.12   uch 
    737  1.12   uch 	/*
    738  1.12   uch 	 * dither-pattern look-up table. (selected by uch)
    739  1.12   uch 	 */
    740  1.12   uch 	/* red */
    741  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL5_REG,
    742  1.12   uch 		      (dither_level8[7] << 28) |
    743  1.12   uch 		      (dither_level8[6] << 24) |
    744  1.12   uch 		      (dither_level8[5] << 20) |
    745  1.12   uch 		      (dither_level8[4] << 16) |
    746  1.12   uch 		      (dither_level8[3] << 12) |
    747  1.12   uch 		      (dither_level8[2] << 8) |
    748  1.12   uch 		      (dither_level8[1] << 4) |
    749  1.12   uch 		      (dither_level8[0] << 0));
    750  1.12   uch 	/* green */
    751  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL6_REG,
    752  1.12   uch 		      (dither_level8[7] << 28) |
    753  1.12   uch 		      (dither_level8[6] << 24) |
    754  1.12   uch 		      (dither_level8[5] << 20) |
    755  1.12   uch 		      (dither_level8[4] << 16) |
    756  1.12   uch 		      (dither_level8[3] << 12) |
    757  1.12   uch 		      (dither_level8[2] << 8) |
    758  1.12   uch 		      (dither_level8[1] << 4) |
    759  1.12   uch 		      (dither_level8[0] << 0));
    760  1.12   uch 	/* blue (2bit gray scale also use this look-up table) */
    761  1.12   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL7_REG,
    762  1.12   uch 		      (dither_level4[3] << 12) |
    763  1.12   uch 		      (dither_level4[2] << 8) |
    764  1.12   uch 		      (dither_level4[1] << 4) |
    765  1.12   uch 		      (dither_level4[0] << 0));
    766  1.14   uch 
    767  1.14   uch 	tx3912video_reset(sc->sc_chip);
    768  1.11   uch }
    769  1.11   uch 
    770   1.6   uch /*
    771   1.6   uch  * Debug routines.
    772   1.6   uch  */
    773   1.6   uch void
    774   1.6   uch tx3912video_calibration_pattern()
    775   1.6   uch {
    776   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    777   1.6   uch 	int x, y;
    778   1.6   uch 
    779   1.6   uch 	x = vc->vc_fbwidth - 40;
    780   1.6   uch 	y = vc->vc_fbheight - 40;
    781   1.6   uch 	tx3912video_line(40, 40, x , 40);
    782   1.6   uch 	tx3912video_line(x , 40, x , y );
    783   1.6   uch 	tx3912video_line(x , y , 40, y );
    784   1.6   uch 	tx3912video_line(40, y , 40, 40);
    785   1.6   uch 	tx3912video_line(40, 40, x , y );
    786   1.6   uch 	tx3912video_line(x,  40, 40, y );
    787   1.6   uch }
    788   1.6   uch 
    789   1.6   uch #define BPP2 ({ \
    790   1.6   uch 	u_int8_t bitmap; \
    791   1.6   uch 	bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
    792   1.6   uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
    793   1.6   uch 		(bitmap & ~(0x3 << ((3 - (x % 4)) * 2))); \
    794   1.6   uch })
    795   1.6   uch 
    796   1.6   uch #define BPP4 ({ \
    797   1.6   uch 	u_int8_t bitmap; \
    798   1.6   uch 	bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
    799   1.6   uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
    800   1.6   uch 		(bitmap & ~(0xf << ((1 - (x % 2)) * 4))); \
    801   1.6   uch })
    802   1.6   uch 
    803   1.6   uch #define BPP8 ({ \
    804   1.6   uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = 0xff; \
    805   1.6   uch })
    806   1.6   uch 
    807   1.6   uch #define BRESENHAM(a, b, c, d, func) ({ \
    808   1.6   uch 	u_int32_t fbaddr = vc->vc_fbaddr; \
    809   1.6   uch 	u_int32_t fbwidth = vc->vc_fbwidth; \
    810   1.6   uch 	u_int32_t fbdepth = vc->vc_fbdepth; \
    811   1.6   uch 	len = a, step = b -1; \
    812   1.6   uch 	if (step == 0) \
    813   1.6   uch 		return; \
    814   1.6   uch 	kstep = len == 0 ? 0 : 1; \
    815   1.6   uch 	for (i = k = 0, j = step / 2; i <= step; i++) { \
    816   1.6   uch 		x = xbase c; \
    817   1.6   uch 		y = ybase d; \
    818   1.6   uch 		addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3); \
    819   1.6   uch 		func; \
    820   1.6   uch 		j -= len; \
    821   1.6   uch 		while (j < 0) { \
    822   1.6   uch 			j += step; \
    823   1.6   uch 			k += kstep; \
    824   1.6   uch 		} \
    825   1.6   uch 	} \
    826   1.6   uch })
    827   1.6   uch 
    828   1.6   uch #define DRAWLINE(func) ({ \
    829   1.6   uch 	if (x < 0) { \
    830   1.6   uch 		if (y < 0) { \
    831   1.6   uch 			if (_y < _x) { \
    832   1.6   uch 				BRESENHAM(_y, _x, -i, -k, func); \
    833   1.6   uch 			} else { \
    834   1.6   uch 				BRESENHAM(_x, _y, -k, -i, func); \
    835   1.6   uch 			} \
    836   1.6   uch 		} else { \
    837   1.6   uch 			if (_y < _x) { \
    838   1.6   uch 				BRESENHAM(_y, _x, -i, +k, func); \
    839   1.6   uch 			} else { \
    840   1.6   uch 				BRESENHAM(_x, _y, -k, +i, func); \
    841   1.6   uch 			} \
    842   1.6   uch 		} \
    843   1.6   uch 	} else { \
    844   1.6   uch 		if (y < 0) { \
    845   1.6   uch 			if (_y < _x) { \
    846   1.6   uch 				BRESENHAM(_y, _x, +i, -k, func); \
    847   1.6   uch 			} else { \
    848   1.6   uch 				BRESENHAM(_x, _y, +k, -i, func); \
    849   1.6   uch 			} \
    850   1.6   uch 		} else { \
    851   1.6   uch 			if (_y < _x) { \
    852   1.6   uch 				BRESENHAM(_y, _x, +i, +k, func); \
    853   1.6   uch 			} else { \
    854   1.6   uch 				BRESENHAM(_x, _y, +k, +i, func); \
    855   1.6   uch 			} \
    856   1.6   uch 		} \
    857   1.6   uch 	} \
    858   1.6   uch })
    859   1.6   uch 
    860   1.6   uch #define LINEFUNC(b) \
    861   1.6   uch static void linebpp##b __P((int, int, int, int)); \
    862   1.6   uch static void \
    863   1.6   uch linebpp##b##(x0, y0, x1, y1) \
    864   1.6   uch 	int x0, y0, x1, y1; \
    865   1.6   uch { \
    866   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip; \
    867   1.6   uch 	u_int32_t addr; \
    868   1.6   uch 	int i, j, k, len, step, kstep; \
    869   1.6   uch 	int x, _x, y, _y; \
    870   1.6   uch 	int xbase, ybase; \
    871   1.6   uch 	x = x1 - x0; \
    872   1.6   uch 	y = y1 - y0; \
    873   1.6   uch 	_x = abs(x); \
    874   1.6   uch 	_y = abs(y); \
    875   1.6   uch 	xbase = x0; \
    876   1.6   uch 	ybase = y0; \
    877   1.6   uch 	DRAWLINE(BPP##b##); \
    878   1.6   uch }
    879   1.1   uch 
    880   1.6   uch #define DOTFUNC(b) \
    881   1.6   uch static void dotbpp##b __P((int, int)); \
    882   1.6   uch static void \
    883   1.6   uch dotbpp##b##(x, y) \
    884   1.6   uch 	int x, y; \
    885   1.6   uch { \
    886   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip; \
    887   1.6   uch 	u_int32_t addr; \
    888   1.6   uch 	addr = vc->vc_fbaddr + (((y * vc->vc_fbwidth + x) * \
    889   1.6   uch 				 vc->vc_fbdepth) >> 3); \
    890   1.6   uch 	BPP##b; \
    891   1.6   uch }
    892   1.6   uch 
    893   1.6   uch static void linebpp_unimpl __P((int, int, int, int));
    894   1.6   uch static void dotbpp_unimpl __P((int, int));
    895   1.6   uch static
    896   1.6   uch void linebpp_unimpl(x0, y0, x1, y1)
    897   1.6   uch 	int x0, y0, x1, y1;
    898   1.6   uch {
    899   1.6   uch 	return;
    900   1.6   uch }
    901   1.6   uch static
    902   1.6   uch void dotbpp_unimpl(x, y)
    903   1.6   uch 	int x, y;
    904   1.6   uch {
    905   1.6   uch 	return;
    906   1.6   uch }
    907   1.6   uch 
    908   1.6   uch LINEFUNC(2)
    909   1.6   uch LINEFUNC(4)
    910   1.6   uch LINEFUNC(8)
    911   1.6   uch DOTFUNC(2)
    912   1.6   uch DOTFUNC(4)
    913   1.6   uch DOTFUNC(8)
    914   1.6   uch 
    915   1.6   uch void
    916  1.10   uch __tx3912video_attach_drawfunc(vc)
    917   1.6   uch 	struct tx3912video_chip *vc;
    918   1.6   uch {
    919   1.6   uch 	switch (vc->vc_fbdepth) {
    920   1.6   uch 	default:
    921   1.6   uch 		vc->vc_drawline = linebpp_unimpl;
    922   1.6   uch 		vc->vc_drawdot = dotbpp_unimpl;
    923   1.6   uch 		break;
    924   1.6   uch 	case 8:
    925   1.6   uch 		vc->vc_drawline = linebpp8;
    926   1.6   uch 		vc->vc_drawdot = dotbpp8;
    927   1.6   uch 		break;
    928   1.6   uch 	case 4:
    929   1.6   uch 		vc->vc_drawline = linebpp4;
    930   1.6   uch 		vc->vc_drawdot = dotbpp4;
    931   1.6   uch 		break;
    932   1.6   uch 	case 2:
    933   1.6   uch 		vc->vc_drawline = linebpp2;
    934   1.6   uch 		vc->vc_drawdot = dotbpp2;
    935   1.6   uch 		break;
    936   1.6   uch 	}
    937   1.6   uch }
    938   1.6   uch 
    939   1.6   uch void
    940   1.6   uch tx3912video_line(x0, y0, x1, y1)
    941   1.6   uch 	int x0, y0, x1, y1;
    942   1.6   uch {
    943   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    944  1.13   uch 	if (vc->vc_drawline)
    945  1.13   uch 		vc->vc_drawline(x0, y0, x1, y1);
    946   1.6   uch }
    947   1.6   uch 
    948   1.6   uch void
    949   1.6   uch tx3912video_dot(x, y)
    950   1.6   uch 	int x, y;
    951   1.6   uch {
    952   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    953  1.13   uch 	if (vc->vc_drawdot)
    954  1.13   uch 		vc->vc_drawdot(x, y);
    955   1.6   uch }
    956