Home | History | Annotate | Line # | Download | only in tx
tx3912video.c revision 1.11
      1  1.11   uch /*	$NetBSD: tx3912video.c,v 1.11 2000/05/02 17:50:52 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.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.11   uch #include <sys/ioctl.h>
     38  1.11   uch 
     39   1.1   uch #include <machine/bus.h>
     40  1.10   uch #include <machine/bootinfo.h>
     41   1.1   uch 
     42   1.1   uch #include <hpcmips/tx/tx39var.h>
     43   1.1   uch #include <hpcmips/tx/tx3912videovar.h>
     44   1.1   uch #include <hpcmips/tx/tx3912videoreg.h>
     45   1.1   uch 
     46   1.9  sato #include <dev/wscons/wsconsio.h>
     47   1.8   uch #include <arch/hpcmips/dev/hpcfbvar.h>
     48   1.8   uch #include <arch/hpcmips/dev/hpcfbio.h>
     49   1.2   uch 
     50  1.10   uch #define TX3912VIDEO_DEBUG
     51  1.10   uch 
     52  1.10   uch static struct tx3912video_chip {
     53  1.10   uch 	tx_chipset_tag_t vc_tc;
     54   1.6   uch 
     55  1.10   uch 	paddr_t vc_fbaddr;
     56  1.10   uch 	size_t vc_fbsize;
     57  1.10   uch 	int vc_fbdepth;
     58  1.10   uch 	int vc_fbwidth;
     59  1.10   uch 	int vc_fbheight;
     60   1.6   uch 
     61  1.11   uch 	void (*vc_drawline) __P((int, int, int, int)); /* for debug */
     62  1.11   uch 	void (*vc_drawdot) __P((int, int)); /* for debug */
     63  1.10   uch } tx3912video_chip;
     64   1.6   uch 
     65   1.1   uch struct tx3912video_softc {
     66   1.1   uch 	struct device sc_dev;
     67  1.11   uch 	struct hpcfb_fbconf sc_fbconf;
     68  1.11   uch 	struct hpcfb_dspconf sc_dspconf;
     69   1.6   uch 	struct tx3912video_chip *sc_chip;
     70   1.1   uch };
     71   1.1   uch 
     72  1.11   uch void	tx3912video_framebuffer_init __P((struct tx3912video_chip *));
     73  1.11   uch int	tx3912video_framebuffer_alloc __P((struct tx3912video_chip *, paddr_t,
     74  1.10   uch 					paddr_t *));
     75  1.11   uch void	tx3912video_reset __P((struct tx3912video_chip *));
     76  1.11   uch void	tx3912video_resolution_init __P((struct tx3912video_chip *));
     77  1.10   uch 
     78  1.10   uch int	tx3912video_match __P((struct device *, struct cfdata *, void *));
     79  1.10   uch void	tx3912video_attach __P((struct device *, struct device *, void *));
     80  1.10   uch int	tx3912video_print __P((void *, const char *));
     81   1.1   uch 
     82  1.11   uch void	tx3912video_hpcfbinit __P((struct tx3912video_softc *));
     83  1.11   uch int	tx3912video_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
     84  1.11   uch int	tx3912video_mmap __P((void *, off_t, int));
     85  1.11   uch 
     86   1.1   uch struct cfattach tx3912video_ca = {
     87   1.3   uch 	sizeof(struct tx3912video_softc), tx3912video_match,
     88   1.3   uch 	tx3912video_attach
     89   1.1   uch };
     90   1.1   uch 
     91  1.11   uch struct hpcfb_accessops tx3912video_ha = {
     92  1.11   uch 	tx3912video_ioctl, tx3912video_mmap
     93  1.11   uch };
     94  1.11   uch 
     95  1.10   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.10   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.10   uch 	struct tx3912video_softc *sc = (void *)self;
    113  1.10   uch 	struct tx3912video_chip *chip;
    114  1.10   uch 	const char *depth_print[] = {
    115  1.10   uch 		[TX3912_VIDEOCTRL1_BITSEL_MONOCHROME] = "monochrome",
    116  1.10   uch 		[TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE] = "2bit greyscale",
    117  1.10   uch 		[TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE] = "4bit greyscale",
    118  1.10   uch 		[TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR] = "8bit color"
    119  1.10   uch 	};
    120  1.11   uch 	struct hpcfb_attach_args ha;
    121  1.11   uch 	int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
    122  1.10   uch 
    123  1.10   uch 	sc->sc_chip = chip = &tx3912video_chip;
    124  1.10   uch 
    125  1.10   uch 	/* print video module information */
    126  1.10   uch 	printf(": %s, frame buffer 0x%08x-0x%08x\n",
    127  1.10   uch 	       depth_print[(ffs(chip->vc_fbdepth) - 1) & 0x3],
    128  1.10   uch 	       (unsigned)chip->vc_fbaddr,
    129  1.10   uch 	       (unsigned)(chip->vc_fbaddr + chip->vc_fbsize));
    130   1.5   uch 
    131  1.10   uch 	/* if serial console, power off video module */
    132   1.6   uch #ifndef TX3912VIDEO_DEBUG
    133  1.11   uch 	if (!console) {
    134  1.10   uch 		tx_chipset_tag_t tc = ta->ta_tc;
    135  1.10   uch 		txreg_t reg;
    136   1.5   uch 		printf("%s: power off\n", sc->sc_dev.dv_xname);
    137   1.4   uch 		reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    138   1.4   uch 		reg &= ~(TX3912_VIDEOCTRL1_DISPON |
    139   1.4   uch 			 TX3912_VIDEOCTRL1_ENVID);
    140   1.4   uch 		tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    141   1.4   uch 	}
    142   1.6   uch #endif /* TX3912VIDEO_DEBUG */
    143   1.6   uch 
    144  1.10   uch 	/* attach debug draw routine (debugging use) */
    145  1.10   uch 	__tx3912video_attach_drawfunc(sc->sc_chip);
    146  1.10   uch 
    147   1.1   uch 	/* Attach frame buffer device */
    148  1.11   uch 	tx3912video_hpcfbinit(sc);
    149  1.11   uch 
    150  1.11   uch 	if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
    151  1.11   uch 		panic("tx3912video_attach: can't init fb console");
    152   1.2   uch 	}
    153  1.11   uch 
    154  1.11   uch 	ha.ha_console = console;
    155  1.11   uch 	ha.ha_accessops = &tx3912video_ha;
    156  1.11   uch 	ha.ha_accessctx = sc;
    157  1.11   uch 	ha.ha_curfbconf = 0;
    158  1.11   uch 	ha.ha_nfbconf = 1;
    159  1.11   uch 	ha.ha_fbconflist = &sc->sc_fbconf;
    160  1.11   uch 	ha.ha_curdspconf = 0;
    161  1.11   uch 	ha.ha_ndspconf = 1;
    162  1.11   uch 	ha.ha_dspconflist = &sc->sc_dspconf;
    163  1.11   uch 
    164  1.11   uch 	config_found(self, &ha, hpcfbprint);
    165   1.1   uch }
    166   1.1   uch 
    167  1.11   uch void
    168  1.11   uch tx3912video_hpcfbinit(sc)
    169  1.11   uch 	struct tx3912video_softc *sc;
    170   1.1   uch {
    171  1.11   uch 	struct tx3912video_chip *chip = sc->sc_chip;
    172  1.11   uch 	struct hpcfb_fbconf *fb = &sc->sc_fbconf;
    173  1.11   uch 	caddr_t fbcaddr = (caddr_t)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
    174  1.11   uch 
    175  1.11   uch 	memset(fb, 0, sizeof(struct hpcfb_fbconf));
    176  1.11   uch 
    177  1.11   uch 	fb->hf_conf_index	= 0;	/* configuration index		*/
    178  1.11   uch 	fb->hf_nconfs		= 1;   	/* how many configurations	*/
    179  1.11   uch 	strcpy(fb->hf_name, "TX3912 built-in video");
    180  1.11   uch 					/* frame buffer name		*/
    181  1.11   uch 	strcpy(fb->hf_conf_name, "LCD");
    182  1.11   uch 					/* configuration name		*/
    183  1.11   uch 	fb->hf_height		= chip->vc_fbheight;
    184  1.11   uch 	fb->hf_width		= chip->vc_fbwidth;
    185  1.11   uch 	fb->hf_baseaddr		= mips_ptob(mips_btop(fbcaddr));
    186  1.11   uch 	fb->hf_offset		= (u_long)fbcaddr - fb->hf_baseaddr;
    187  1.11   uch 					/* frame buffer start offset   	*/
    188  1.11   uch 	fb->hf_bytes_per_line	= (chip->vc_fbwidth * chip->vc_fbdepth) / NBBY;
    189  1.11   uch 	fb->hf_nplanes		= 1;
    190  1.11   uch 	fb->hf_bytes_per_plane	= chip->vc_fbheight * fb->hf_bytes_per_line;
    191  1.11   uch 
    192  1.11   uch 	fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
    193  1.11   uch 	fb->hf_access_flags |= HPCFB_ACCESS_WORD;
    194  1.11   uch 	fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
    195  1.11   uch 
    196  1.11   uch 	fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; /* XXX */
    197  1.11   uch 	switch (chip->vc_fbdepth) {
    198  1.11   uch 	default:
    199  1.11   uch 		panic("tx3912video_hpcfbinit: not supported color depth\n");
    200  1.11   uch 		/* NOTREACHED */
    201  1.11   uch 	case 2:
    202  1.11   uch 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
    203  1.11   uch 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    204  1.11   uch 		fb->hf_pack_width = 8;
    205  1.11   uch 		fb->hf_pixels_per_pack = 4;
    206  1.11   uch 		fb->hf_pixel_width = 2;
    207  1.11   uch 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
    208  1.11   uch 		fb->hf_u.hf_gray.hf_flags = 0;	/* reserved for future use */
    209  1.11   uch 		break;
    210  1.11   uch 	case 8:
    211  1.11   uch 		fb->hf_class = HPCFB_CLASS_INDEXCOLOR; /* XXX */
    212  1.11   uch 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    213  1.11   uch 		fb->hf_pack_width = 8;
    214  1.11   uch 		fb->hf_pixels_per_pack = 1;
    215  1.11   uch 		fb->hf_pixel_width = 8;
    216  1.11   uch 		fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
    217  1.11   uch 		fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
    218  1.11   uch 		break;
    219  1.11   uch 	}
    220   1.1   uch }
    221   1.1   uch 
    222   1.1   uch int
    223  1.10   uch tx3912video_init(fb_start, fb_end)
    224  1.10   uch 	paddr_t fb_start, *fb_end;
    225  1.10   uch {
    226  1.10   uch 	struct tx3912video_chip *chip = &tx3912video_chip;
    227   1.1   uch 	tx_chipset_tag_t tc;
    228   1.7   uch 	txreg_t reg;
    229  1.10   uch 	int fbdepth;
    230  1.10   uch 	int error;
    231   1.1   uch 
    232  1.10   uch 	chip->vc_tc = tc = tx_conf_get_tag();
    233  1.10   uch 
    234  1.10   uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    235  1.10   uch 	fbdepth = 1 << (TX3912_VIDEOCTRL1_BITSEL(reg));
    236   1.7   uch 
    237  1.10   uch 	switch (fbdepth) {
    238   1.7   uch 	case 2:
    239   1.7   uch 		bootinfo->fb_type = BIFB_D2_M2L_0;
    240   1.7   uch 		break;
    241   1.7   uch 	case 4:
    242   1.7   uch 		/* XXX should implement rasops4.c */
    243  1.10   uch 		fbdepth = 2;
    244   1.7   uch 		bootinfo->fb_type = BIFB_D2_M2L_0;
    245   1.7   uch 		reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    246   1.7   uch 		TX3912_VIDEOCTRL1_BITSEL_CLR(reg);
    247   1.7   uch 		reg = TX3912_VIDEOCTRL1_BITSEL_SET(
    248   1.7   uch 			reg, TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE);
    249   1.7   uch 		tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    250   1.7   uch 		break;
    251   1.7   uch 	case 8:
    252   1.7   uch 		bootinfo->fb_type = BIFB_D8_FF;
    253   1.7   uch 		break;
    254   1.7   uch 	}
    255   1.7   uch 
    256  1.10   uch 	tx3912video_chip.vc_fbdepth = fbdepth;
    257  1.10   uch 	tx3912video_chip.vc_fbwidth = bootinfo->fb_width;
    258  1.10   uch 	tx3912video_chip.vc_fbheight= bootinfo->fb_height;
    259   1.7   uch 
    260   1.1   uch 	/* Allocate framebuffer area */
    261  1.10   uch 	error = tx3912video_framebuffer_alloc(chip, fb_start, fb_end);
    262  1.10   uch 	if (error != 0)
    263  1.10   uch 		return (1);
    264  1.10   uch 
    265   1.1   uch #if notyet
    266  1.10   uch 	tx3912video_resolution_init(chip);
    267   1.1   uch #else
    268   1.1   uch 	/* Use Windows CE setting. */
    269   1.1   uch #endif
    270   1.1   uch 	/* Set DMA transfer address to VID module */
    271  1.10   uch 	tx3912video_framebuffer_init(chip);
    272   1.1   uch 
    273   1.1   uch 	/* Syncronize framebuffer addr to frame signal */
    274  1.10   uch 	tx3912video_reset(chip);
    275   1.1   uch 
    276  1.10   uch 	bootinfo->fb_line_bytes = (chip->vc_fbwidth * fbdepth) / NBBY;
    277  1.10   uch 	bootinfo->fb_addr = (void *)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
    278  1.10   uch 
    279  1.10   uch 	return (0);
    280   1.1   uch }
    281   1.1   uch 
    282   1.1   uch  int
    283  1.10   uch tx3912video_framebuffer_alloc(chip, fb_start, fb_end)
    284  1.10   uch 	struct tx3912video_chip *chip;
    285  1.10   uch 	paddr_t fb_start, *fb_end; /* buffer allocation hint */
    286   1.1   uch {
    287  1.10   uch 	struct extent_fixed ex_fixed[10];
    288   1.1   uch 	struct extent *ex;
    289   1.1   uch 	u_long addr, size;
    290  1.10   uch 	int error;
    291  1.10   uch 
    292  1.10   uch 	/* calcurate frame buffer size */
    293  1.10   uch 	size = (chip->vc_fbwidth * chip->vc_fbheight * chip->vc_fbdepth) /
    294  1.10   uch 		NBBY;
    295  1.10   uch 
    296  1.10   uch 	/* extent V-RAM region */
    297  1.10   uch 	ex = extent_create("Frame buffer address", fb_start, *fb_end,
    298  1.10   uch 			   0, (caddr_t)ex_fixed, sizeof ex_fixed,
    299  1.10   uch 			   EX_NOWAIT);
    300  1.10   uch 	if (ex == 0)
    301  1.10   uch 		return (1);
    302   1.1   uch 
    303   1.1   uch 	/* Allocate V-RAM area */
    304  1.10   uch 	error = extent_alloc_subregion(ex, fb_start, fb_start + size, size,
    305  1.10   uch 				       TX3912_FRAMEBUFFER_ALIGNMENT,
    306  1.10   uch 				       TX3912_FRAMEBUFFER_BOUNDARY,
    307  1.10   uch 				       EX_FAST|EX_NOWAIT, &addr);
    308  1.10   uch 	extent_destroy(ex);
    309  1.10   uch 
    310  1.10   uch 	if (error != 0) {
    311  1.10   uch 		return (1);
    312   1.1   uch 	}
    313  1.10   uch 
    314  1.10   uch 	chip->vc_fbaddr = addr;
    315  1.10   uch 	chip->vc_fbsize = size;
    316   1.6   uch 
    317  1.10   uch 	*fb_end = addr + size;
    318   1.1   uch 
    319  1.10   uch 	return (0);
    320   1.1   uch }
    321   1.1   uch 
    322   1.1   uch  void
    323  1.10   uch tx3912video_framebuffer_init(chip)
    324  1.10   uch 	struct tx3912video_chip *chip;
    325   1.1   uch {
    326  1.10   uch 	u_int32_t fb_addr, fb_size, vaddr, bank, base;
    327  1.10   uch 	txreg_t reg;
    328  1.10   uch 	tx_chipset_tag_t tc = chip->vc_tc;
    329  1.10   uch 
    330  1.10   uch 	fb_addr = chip->vc_fbaddr;
    331  1.10   uch 	fb_size = chip->vc_fbsize;
    332   1.1   uch 
    333   1.1   uch 	/*  XXX currently I don't set DFVAL, so force DF signal toggled on
    334   1.1   uch          *  XXX each frame. */
    335   1.1   uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    336   1.1   uch 	reg &= ~TX3912_VIDEOCTRL1_DFMODE;
    337   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    338   1.1   uch 
    339   1.1   uch 	/* Set DMA transfer start and end address */
    340  1.10   uch 
    341   1.1   uch 	bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
    342   1.1   uch 	base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
    343   1.1   uch 	reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
    344   1.1   uch 	/* Upper address counter */
    345   1.1   uch 	reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
    346   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
    347   1.1   uch 
    348   1.1   uch 	/* Lower address counter  */
    349   1.1   uch 	base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
    350   1.1   uch 	reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
    351   1.1   uch 
    352   1.1   uch 	/* Set DF-signal rate */
    353   1.1   uch 	reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
    354   1.1   uch 
    355   1.1   uch 	/* Set VIDDONE signal delay after FRAME signal */
    356   1.1   uch 	/* XXX not yet*/
    357   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
    358   1.1   uch 
    359   1.1   uch 	/* Clear frame buffer */
    360   1.1   uch 	vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
    361  1.10   uch 	memset((void*)vaddr, 0, fb_size);
    362   1.1   uch }
    363   1.1   uch 
    364   1.1   uch  void
    365  1.10   uch tx3912video_resolution_init(chip)
    366  1.10   uch 	struct tx3912video_chip *chip;
    367   1.1   uch {
    368  1.10   uch 	int h, v, split, bit8, horzval, lineval;
    369  1.10   uch 	tx_chipset_tag_t tc = chip->vc_tc;
    370  1.10   uch 	txreg_t reg;
    371  1.10   uch 	u_int32_t val;
    372  1.10   uch 
    373  1.10   uch 	h = chip->vc_fbwidth;
    374  1.10   uch 	v = chip->vc_fbheight;
    375   1.1   uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    376   1.1   uch 	split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
    377   1.1   uch 	bit8  = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
    378   1.1   uch 		 TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
    379   1.1   uch 	val = TX3912_VIDEOCTRL1_BITSEL(reg);
    380   1.1   uch 
    381   1.1   uch 	if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
    382   1.1   uch 	    !split) {
    383   1.3   uch 		/* (LCD horizontal pixels / 8bit) * RGB - 1 */
    384   1.3   uch 		horzval = (h / 8) * 3 - 1;
    385   1.1   uch 	} else {
    386   1.1   uch 		horzval = h / 4 - 1;
    387   1.1   uch 	}
    388   1.1   uch 	lineval = (split ? v / 2 : v) - 1;
    389   1.1   uch 
    390   1.1   uch 	/* Video rate */
    391   1.3   uch 	/* XXX
    392   1.3   uch 	 *  probably This value should be determined from DFINT and LCDINT
    393   1.3   uch 	 */
    394   1.1   uch 	reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
    395   1.1   uch 	/* Horizontal size of LCD */
    396   1.1   uch 	reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
    397   1.1   uch 	/* # of lines for the LCD */
    398   1.1   uch 	reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
    399   1.1   uch 
    400   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
    401   1.1   uch }
    402   1.1   uch 
    403   1.1   uch void
    404  1.10   uch tx3912video_reset(chip)
    405  1.10   uch 	struct tx3912video_chip *chip;
    406   1.1   uch {
    407  1.10   uch 	tx_chipset_tag_t tc = chip->vc_tc;
    408  1.10   uch 	txreg_t reg;
    409   1.1   uch 
    410   1.1   uch 	reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
    411   1.3   uch 
    412   1.1   uch 	/* Disable video logic at end of this frame */
    413   1.1   uch 	reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
    414   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    415   1.3   uch 
    416   1.1   uch 	/* Wait for end of frame */
    417  1.10   uch 	delay(30 * 1000);
    418   1.3   uch 
    419   1.1   uch 	/* Make sure to disable video logic */
    420   1.1   uch 	reg &= ~TX3912_VIDEOCTRL1_ENVID;
    421   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    422   1.3   uch 
    423   1.1   uch 	delay(1000);
    424   1.3   uch 
    425   1.1   uch 	/* Enable video logic again */
    426   1.1   uch 	reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
    427   1.1   uch 	reg |= TX3912_VIDEOCTRL1_ENVID;
    428   1.1   uch 	tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
    429   1.3   uch 
    430   1.1   uch 	delay(1000);
    431   1.1   uch }
    432   1.1   uch 
    433  1.11   uch int
    434  1.11   uch tx3912video_ioctl(v, cmd, data, flag, p)
    435  1.11   uch 	void *v;
    436  1.11   uch 	u_long cmd;
    437  1.11   uch 	caddr_t data;
    438  1.11   uch 	int flag;
    439  1.11   uch 	struct proc *p;
    440  1.11   uch {
    441  1.11   uch 	struct tx3912video_softc *sc = (struct tx3912video_softc *)v;
    442  1.11   uch 	struct hpcfb_fbconf *fbconf;
    443  1.11   uch 	struct hpcfb_dspconf *dspconf;
    444  1.11   uch 
    445  1.11   uch 	switch (cmd) {
    446  1.11   uch 	case WSDISPLAYIO_GETCMAP:
    447  1.11   uch 		/* XXX not implemented yet */
    448  1.11   uch 		return (EINVAL);
    449  1.11   uch 
    450  1.11   uch 	case WSDISPLAYIO_PUTCMAP:
    451  1.11   uch 		/* XXX not implemented yet */
    452  1.11   uch 		return (EINVAL);
    453  1.11   uch 
    454  1.11   uch 	case HPCFBIO_GCONF:
    455  1.11   uch 		fbconf = (struct hpcfb_fbconf *)data;
    456  1.11   uch 		if (fbconf->hf_conf_index != 0 &&
    457  1.11   uch 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
    458  1.11   uch 			return (EINVAL);
    459  1.11   uch 		}
    460  1.11   uch 		*fbconf = sc->sc_fbconf;	/* structure assignment */
    461  1.11   uch 		return (0);
    462  1.11   uch 
    463  1.11   uch 	case HPCFBIO_SCONF:
    464  1.11   uch 		fbconf = (struct hpcfb_fbconf *)data;
    465  1.11   uch 		if (fbconf->hf_conf_index != 0 &&
    466  1.11   uch 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
    467  1.11   uch 			return (EINVAL);
    468  1.11   uch 		}
    469  1.11   uch 		/*
    470  1.11   uch 		 * nothing to do because we have only one configration
    471  1.11   uch 		 */
    472  1.11   uch 		return (0);
    473  1.11   uch 
    474  1.11   uch 	case HPCFBIO_GDSPCONF:
    475  1.11   uch 		dspconf = (struct hpcfb_dspconf *)data;
    476  1.11   uch 		if ((dspconf->hd_unit_index != 0 &&
    477  1.11   uch 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
    478  1.11   uch 		    (dspconf->hd_conf_index != 0 &&
    479  1.11   uch 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
    480  1.11   uch 			return (EINVAL);
    481  1.11   uch 		}
    482  1.11   uch 		*dspconf = sc->sc_dspconf;	/* structure assignment */
    483  1.11   uch 		return (0);
    484  1.11   uch 
    485  1.11   uch 	case HPCFBIO_SDSPCONF:
    486  1.11   uch 		dspconf = (struct hpcfb_dspconf *)data;
    487  1.11   uch 		if ((dspconf->hd_unit_index != 0 &&
    488  1.11   uch 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
    489  1.11   uch 		    (dspconf->hd_conf_index != 0 &&
    490  1.11   uch 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
    491  1.11   uch 			return (EINVAL);
    492  1.11   uch 		}
    493  1.11   uch 		/*
    494  1.11   uch 		 * nothing to do
    495  1.11   uch 		 * because we have only one unit and one configration
    496  1.11   uch 		 */
    497  1.11   uch 		return (0);
    498  1.11   uch 
    499  1.11   uch 	case HPCFBIO_GOP:
    500  1.11   uch 	case HPCFBIO_SOP:
    501  1.11   uch 		/* XXX not implemented yet */
    502  1.11   uch 		return (EINVAL);
    503  1.11   uch 	}
    504  1.11   uch 
    505  1.11   uch 	return (ENOTTY);
    506  1.11   uch }
    507  1.11   uch 
    508  1.11   uch int
    509  1.11   uch tx3912video_mmap(ctx, offset, prot)
    510  1.11   uch 	void *ctx;
    511  1.11   uch 	off_t offset;
    512  1.11   uch 	int prot;
    513  1.11   uch {
    514  1.11   uch 	struct tx3912video_softc *sc = (struct tx3912video_softc *)ctx;
    515  1.11   uch 
    516  1.11   uch 	if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane +
    517  1.11   uch 			   sc->sc_fbconf.hf_offset) <  offset) {
    518  1.11   uch 		return (-1);
    519  1.11   uch 	}
    520  1.11   uch 
    521  1.11   uch 	return (mips_btop(sc->sc_chip->vc_fbaddr + offset));
    522  1.11   uch }
    523  1.11   uch 
    524   1.6   uch /*
    525   1.6   uch  * Debug routines.
    526   1.6   uch  */
    527   1.6   uch void
    528   1.6   uch tx3912video_calibration_pattern()
    529   1.6   uch {
    530   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    531   1.6   uch 	int x, y;
    532   1.6   uch 
    533   1.6   uch 	x = vc->vc_fbwidth - 40;
    534   1.6   uch 	y = vc->vc_fbheight - 40;
    535   1.6   uch 	tx3912video_line(40, 40, x , 40);
    536   1.6   uch 	tx3912video_line(x , 40, x , y );
    537   1.6   uch 	tx3912video_line(x , y , 40, y );
    538   1.6   uch 	tx3912video_line(40, y , 40, 40);
    539   1.6   uch 	tx3912video_line(40, 40, x , y );
    540   1.6   uch 	tx3912video_line(x,  40, 40, y );
    541   1.6   uch }
    542   1.6   uch 
    543   1.6   uch #define BPP2 ({ \
    544   1.6   uch 	u_int8_t bitmap; \
    545   1.6   uch 	bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
    546   1.6   uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
    547   1.6   uch 		(bitmap & ~(0x3 << ((3 - (x % 4)) * 2))); \
    548   1.6   uch })
    549   1.6   uch 
    550   1.6   uch #define BPP4 ({ \
    551   1.6   uch 	u_int8_t bitmap; \
    552   1.6   uch 	bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
    553   1.6   uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
    554   1.6   uch 		(bitmap & ~(0xf << ((1 - (x % 2)) * 4))); \
    555   1.6   uch })
    556   1.6   uch 
    557   1.6   uch #define BPP8 ({ \
    558   1.6   uch 	*(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = 0xff; \
    559   1.6   uch })
    560   1.6   uch 
    561   1.6   uch #define BRESENHAM(a, b, c, d, func) ({ \
    562   1.6   uch 	u_int32_t fbaddr = vc->vc_fbaddr; \
    563   1.6   uch 	u_int32_t fbwidth = vc->vc_fbwidth; \
    564   1.6   uch 	u_int32_t fbdepth = vc->vc_fbdepth; \
    565   1.6   uch 	len = a, step = b -1; \
    566   1.6   uch 	if (step == 0) \
    567   1.6   uch 		return; \
    568   1.6   uch 	kstep = len == 0 ? 0 : 1; \
    569   1.6   uch 	for (i = k = 0, j = step / 2; i <= step; i++) { \
    570   1.6   uch 		x = xbase c; \
    571   1.6   uch 		y = ybase d; \
    572   1.6   uch 		addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3); \
    573   1.6   uch 		func; \
    574   1.6   uch 		j -= len; \
    575   1.6   uch 		while (j < 0) { \
    576   1.6   uch 			j += step; \
    577   1.6   uch 			k += kstep; \
    578   1.6   uch 		} \
    579   1.6   uch 	} \
    580   1.6   uch })
    581   1.6   uch 
    582   1.6   uch #define DRAWLINE(func) ({ \
    583   1.6   uch 	if (x < 0) { \
    584   1.6   uch 		if (y < 0) { \
    585   1.6   uch 			if (_y < _x) { \
    586   1.6   uch 				BRESENHAM(_y, _x, -i, -k, func); \
    587   1.6   uch 			} else { \
    588   1.6   uch 				BRESENHAM(_x, _y, -k, -i, func); \
    589   1.6   uch 			} \
    590   1.6   uch 		} else { \
    591   1.6   uch 			if (_y < _x) { \
    592   1.6   uch 				BRESENHAM(_y, _x, -i, +k, func); \
    593   1.6   uch 			} else { \
    594   1.6   uch 				BRESENHAM(_x, _y, -k, +i, func); \
    595   1.6   uch 			} \
    596   1.6   uch 		} \
    597   1.6   uch 	} else { \
    598   1.6   uch 		if (y < 0) { \
    599   1.6   uch 			if (_y < _x) { \
    600   1.6   uch 				BRESENHAM(_y, _x, +i, -k, func); \
    601   1.6   uch 			} else { \
    602   1.6   uch 				BRESENHAM(_x, _y, +k, -i, func); \
    603   1.6   uch 			} \
    604   1.6   uch 		} else { \
    605   1.6   uch 			if (_y < _x) { \
    606   1.6   uch 				BRESENHAM(_y, _x, +i, +k, func); \
    607   1.6   uch 			} else { \
    608   1.6   uch 				BRESENHAM(_x, _y, +k, +i, func); \
    609   1.6   uch 			} \
    610   1.6   uch 		} \
    611   1.6   uch 	} \
    612   1.6   uch })
    613   1.6   uch 
    614   1.6   uch #define LINEFUNC(b) \
    615   1.6   uch static void linebpp##b __P((int, int, int, int)); \
    616   1.6   uch static void \
    617   1.6   uch linebpp##b##(x0, y0, x1, y1) \
    618   1.6   uch 	int x0, y0, x1, y1; \
    619   1.6   uch { \
    620   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip; \
    621   1.6   uch 	u_int32_t addr; \
    622   1.6   uch 	int i, j, k, len, step, kstep; \
    623   1.6   uch 	int x, _x, y, _y; \
    624   1.6   uch 	int xbase, ybase; \
    625   1.6   uch 	x = x1 - x0; \
    626   1.6   uch 	y = y1 - y0; \
    627   1.6   uch 	_x = abs(x); \
    628   1.6   uch 	_y = abs(y); \
    629   1.6   uch 	xbase = x0; \
    630   1.6   uch 	ybase = y0; \
    631   1.6   uch 	DRAWLINE(BPP##b##); \
    632   1.6   uch }
    633   1.1   uch 
    634   1.6   uch #define DOTFUNC(b) \
    635   1.6   uch static void dotbpp##b __P((int, int)); \
    636   1.6   uch static void \
    637   1.6   uch dotbpp##b##(x, y) \
    638   1.6   uch 	int x, y; \
    639   1.6   uch { \
    640   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip; \
    641   1.6   uch 	u_int32_t addr; \
    642   1.6   uch 	addr = vc->vc_fbaddr + (((y * vc->vc_fbwidth + x) * \
    643   1.6   uch 				 vc->vc_fbdepth) >> 3); \
    644   1.6   uch 	BPP##b; \
    645   1.6   uch }
    646   1.6   uch 
    647   1.6   uch static void linebpp_unimpl __P((int, int, int, int));
    648   1.6   uch static void dotbpp_unimpl __P((int, int));
    649   1.6   uch static
    650   1.6   uch void linebpp_unimpl(x0, y0, x1, y1)
    651   1.6   uch 	int x0, y0, x1, y1;
    652   1.6   uch {
    653   1.6   uch 	return;
    654   1.6   uch }
    655   1.6   uch static
    656   1.6   uch void dotbpp_unimpl(x, y)
    657   1.6   uch 	int x, y;
    658   1.6   uch {
    659   1.6   uch 	return;
    660   1.6   uch }
    661   1.6   uch 
    662   1.6   uch LINEFUNC(2)
    663   1.6   uch LINEFUNC(4)
    664   1.6   uch LINEFUNC(8)
    665   1.6   uch DOTFUNC(2)
    666   1.6   uch DOTFUNC(4)
    667   1.6   uch DOTFUNC(8)
    668   1.6   uch 
    669   1.6   uch void
    670  1.10   uch __tx3912video_attach_drawfunc(vc)
    671   1.6   uch 	struct tx3912video_chip *vc;
    672   1.6   uch {
    673   1.6   uch 	switch (vc->vc_fbdepth) {
    674   1.6   uch 	default:
    675   1.6   uch 		vc->vc_drawline = linebpp_unimpl;
    676   1.6   uch 		vc->vc_drawdot = dotbpp_unimpl;
    677   1.6   uch 		break;
    678   1.6   uch 	case 8:
    679   1.6   uch 		vc->vc_drawline = linebpp8;
    680   1.6   uch 		vc->vc_drawdot = dotbpp8;
    681   1.6   uch 		break;
    682   1.6   uch 	case 4:
    683   1.6   uch 		vc->vc_drawline = linebpp4;
    684   1.6   uch 		vc->vc_drawdot = dotbpp4;
    685   1.6   uch 		break;
    686   1.6   uch 	case 2:
    687   1.6   uch 		vc->vc_drawline = linebpp2;
    688   1.6   uch 		vc->vc_drawdot = dotbpp2;
    689   1.6   uch 		break;
    690   1.6   uch 	}
    691   1.6   uch }
    692   1.6   uch 
    693   1.6   uch void
    694   1.6   uch tx3912video_line(x0, y0, x1, y1)
    695   1.6   uch 	int x0, y0, x1, y1;
    696   1.6   uch {
    697   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    698   1.6   uch 	vc->vc_drawline(x0, y0, x1, y1);
    699   1.6   uch }
    700   1.6   uch 
    701   1.6   uch void
    702   1.6   uch tx3912video_dot(x, y)
    703   1.6   uch 	int x, y;
    704   1.6   uch {
    705   1.6   uch 	struct tx3912video_chip *vc = &tx3912video_chip;
    706   1.6   uch 	vc->vc_drawdot(x, y);
    707   1.6   uch }
    708