Home | History | Annotate | Line # | Download | only in iomd
      1  1.37   andvar /*	$NetBSD: vidc20config.c,v 1.37 2024/05/18 19:04:45 andvar Exp $	*/
      2   1.1  reinoud 
      3   1.1  reinoud /*
      4   1.1  reinoud  * Copyright (c) 2001 Reinoud Zandijk
      5   1.1  reinoud  * Copyright (c) 1996 Mark Brinicombe
      6   1.1  reinoud  * Copyright (c) 1996 Robert Black
      7   1.1  reinoud  * Copyright (c) 1994-1995 Melvyn Tang-Richardson
      8   1.1  reinoud  * Copyright (c) 1994-1995 RiscBSD kernel team
      9   1.1  reinoud  * All rights reserved.
     10   1.1  reinoud  *
     11   1.1  reinoud  * Redistribution and use in source and binary forms, with or without
     12   1.1  reinoud  * modification, are permitted provided that the following conditions
     13   1.1  reinoud  * are met:
     14   1.1  reinoud  * 1. Redistributions of source code must retain the above copyright
     15   1.1  reinoud  *    notice, this list of conditions and the following disclaimer.
     16   1.1  reinoud  * 2. Redistributions in binary form must reproduce the above copyright
     17   1.1  reinoud  *    notice, this list of conditions and the following disclaimer in the
     18   1.1  reinoud  *    documentation and/or other materials provided with the distribution.
     19   1.1  reinoud  * 3. All advertising materials mentioning features or use of this software
     20   1.1  reinoud  *    must display the following acknowledgement:
     21   1.1  reinoud  *	This product includes software developed by the RiscBSD kernel team
     22   1.1  reinoud  * 4. The name of the company nor the name of the author may be used to
     23   1.1  reinoud  *    endorse or promote products derived from this software without specific
     24   1.1  reinoud  *    prior written permission.
     25   1.1  reinoud  *
     26   1.1  reinoud  * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
     27   1.1  reinoud  * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     28   1.1  reinoud  * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29   1.1  reinoud  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
     30   1.1  reinoud  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.1  reinoud  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.1  reinoud  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.1  reinoud  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.1  reinoud  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.1  reinoud  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     36   1.1  reinoud  * THE POSSIBILITY OF SUCH DAMAGE.
     37   1.1  reinoud  *
     38   1.1  reinoud  * NetBSD kernel project
     39   1.1  reinoud  *
     40   1.1  reinoud  * vidcvideo.c
     41   1.1  reinoud  *
     42   1.1  reinoud  * This file is the lower basis of the wscons driver for VIDC based ARM machines.
     43   1.1  reinoud  * It features the initialisation and all VIDC writing and keeps in internal state
     44   1.1  reinoud  * copy.
     45  1.36   andvar  * Its currently set up as a library file and not as a device; it could be named
     46   1.1  reinoud  * vidcvideo0 eventually.
     47   1.1  reinoud  */
     48   1.1  reinoud 
     49   1.1  reinoud #include <sys/cdefs.h>
     50   1.7    bjh21 
     51  1.37   andvar __KERNEL_RCSID(0, "$NetBSD: vidc20config.c,v 1.37 2024/05/18 19:04:45 andvar Exp $");
     52   1.7    bjh21 
     53   1.1  reinoud #include <sys/types.h>
     54   1.1  reinoud #include <sys/param.h>
     55   1.1  reinoud #include <arm/iomd/vidc.h>
     56   1.1  reinoud #include <machine/bootconfig.h>
     57   1.4  thorpej #include <machine/intr.h>
     58   1.1  reinoud 
     59   1.1  reinoud #include <sys/systm.h>
     60   1.1  reinoud #include <sys/device.h>
     61   1.1  reinoud #include <uvm/uvm_extern.h>
     62   1.1  reinoud 
     63   1.1  reinoud #include <arm/iomd/iomdreg.h>
     64   1.1  reinoud #include <arm/iomd/iomdvar.h>
     65   1.1  reinoud #include <arm/iomd/vidc20config.h>
     66   1.1  reinoud 
     67  1.34    skrll #define WriteWord(a, b) \
     68  1.34    skrll *((volatile unsigned int *)(a)) = (b)
     69  1.34    skrll 
     70  1.34    skrll #define ReadWord(a) \
     71  1.34    skrll (*((volatile unsigned int *)(a)))
     72   1.9  reinoud 
     73   1.1  reinoud /*
     74   1.1  reinoud  * A structure containing ALL the information required to restore
     75   1.1  reinoud  * the VIDC20 to any given state.  ALL vidc transactions should
     76   1.1  reinoud  * go through these procedures, which record the vidc's state.
     77   1.1  reinoud  * it may be an idea to set the permissions of the vidc base address
     78   1.1  reinoud  * so we get a fault, so the fault routine can record the state but
     79   1.1  reinoud  * I guess that's not really necessary for the time being, since we
     80   1.1  reinoud  * can make the kernel more secure later on.  Also, it is possible
     81   1.1  reinoud  * to write a routine to allow 'reading' of the vidc registers.
     82   1.1  reinoud  */
     83   1.1  reinoud 
     84   1.1  reinoud static struct vidc_state vidc_lookup = {
     85   1.1  reinoud 	{ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
     86   1.1  reinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
     87   1.1  reinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
     88   1.1  reinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
     89   1.1  reinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
     90   1.1  reinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
     91   1.1  reinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
     92   1.1  reinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
     93   1.1  reinoud 	},
     94   1.1  reinoud 
     95   1.1  reinoud 	VIDC_PALREG,
     96   1.1  reinoud 	VIDC_BCOL,
     97   1.1  reinoud 	VIDC_CP1 ,
     98   1.1  reinoud 	VIDC_CP2,
     99   1.1  reinoud 	VIDC_CP3,
    100   1.1  reinoud 	VIDC_HCR,
    101   1.1  reinoud 	VIDC_HSWR,
    102   1.1  reinoud 	VIDC_HBSR,
    103   1.1  reinoud 	VIDC_HDSR,
    104   1.1  reinoud 	VIDC_HDER,
    105   1.1  reinoud 	VIDC_HBER,
    106   1.1  reinoud 	VIDC_HCSR,
    107   1.1  reinoud 	VIDC_HIR,
    108   1.1  reinoud 	VIDC_VCR,
    109   1.1  reinoud 	VIDC_VSWR,
    110   1.1  reinoud 	VIDC_VBSR,
    111   1.1  reinoud 	VIDC_VDSR,
    112   1.1  reinoud 	VIDC_VDER,
    113   1.1  reinoud 	VIDC_VBER,
    114   1.1  reinoud 	VIDC_VCSR,
    115   1.1  reinoud 	VIDC_VCER,
    116   1.1  reinoud 	VIDC_EREG,
    117   1.1  reinoud 	VIDC_FSYNREG,
    118   1.1  reinoud 	VIDC_CONREG,
    119   1.1  reinoud 	VIDC_DCTL
    120   1.1  reinoud };
    121   1.1  reinoud 
    122   1.1  reinoud struct vidc_state vidc_current[1];
    123   1.1  reinoud 
    124   1.1  reinoud 
    125   1.1  reinoud /*
    126   1.1  reinoud  * XXX global display variables XXX ... should be a structure
    127   1.1  reinoud  */
    128   1.1  reinoud static int cold_init = 0;		/* flags initialisation */
    129   1.1  reinoud extern videomemory_t videomemory;
    130   1.1  reinoud 
    131  1.25    bjh21 static struct vidc_mode vidc_currentmode;
    132   1.1  reinoud 
    133   1.1  reinoud unsigned int dispstart;
    134   1.1  reinoud unsigned int dispsize;
    135   1.1  reinoud unsigned int dispbase;
    136   1.1  reinoud unsigned int dispend;
    137   1.1  reinoud unsigned int ptov;
    138   1.1  reinoud unsigned int vmem_base;
    139   1.1  reinoud unsigned int phys_base;
    140   1.1  reinoud unsigned int transfersize;
    141   1.1  reinoud 
    142   1.1  reinoud 
    143   1.1  reinoud /* cursor stuff */
    144   1.1  reinoud char *cursor_normal;
    145   1.1  reinoud char *cursor_transparent;
    146   1.9  reinoud int   p_cursor_normal;
    147   1.9  reinoud int   p_cursor_transparent;
    148   1.9  reinoud int   cursor_width;
    149   1.9  reinoud int   cursor_height;
    150   1.1  reinoud 
    151   1.1  reinoud 
    152   1.1  reinoud /*
    153   1.1  reinoud  * VIDC mode definitions
    154   1.1  reinoud  * generated from RISC OS mode definition file by an `awk' script
    155   1.1  reinoud  */
    156  1.25    bjh21 extern const struct videomode vidc_videomode_list[];
    157  1.25    bjh21 extern const int vidc_videomode_count;
    158   1.1  reinoud 
    159   1.1  reinoud 
    160   1.1  reinoud /*
    161   1.1  reinoud  * configuration printing
    162   1.1  reinoud  *
    163   1.1  reinoud  */
    164   1.1  reinoud 
    165   1.1  reinoud void
    166   1.1  reinoud vidcvideo_printdetails(void)
    167   1.1  reinoud {
    168   1.1  reinoud         printf(": refclk=%dMHz %dKB %s ", (vidc_fref / 1000000),
    169   1.1  reinoud             videomemory.vidm_size / 1024,
    170   1.1  reinoud             (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) ? "VRAM" : "DRAM");
    171   1.1  reinoud }
    172   1.1  reinoud 
    173   1.9  reinoud 
    174   1.1  reinoud /*
    175   1.1  reinoud  * Common functions to directly access VIDC registers
    176   1.1  reinoud  */
    177   1.1  reinoud int
    178  1.21    bjh21 vidcvideo_write(u_int reg, int value)
    179   1.1  reinoud {
    180   1.1  reinoud 	int counter;
    181   1.1  reinoud 
    182   1.1  reinoud 	int *current;
    183   1.1  reinoud 	int *tab;
    184   1.1  reinoud 
    185   1.1  reinoud 	tab 	= (int *)&vidc_lookup;
    186   1.1  reinoud 	current = (int *)vidc_current;
    187   1.1  reinoud 
    188   1.1  reinoud 
    189   1.1  reinoud 	/*
    190   1.1  reinoud 	 * OK, the VIDC_PALETTE register is handled differently
    191   1.1  reinoud 	 * to the others on the VIDC, so take that into account here
    192   1.1  reinoud 	 */
    193  1.21    bjh21 	if (reg == VIDC_PALREG) {
    194   1.1  reinoud 		vidc_current->palreg = 0;
    195   1.1  reinoud 		WriteWord(vidc_base, reg | value);
    196   1.1  reinoud 		return 0;
    197   1.1  reinoud 	}
    198   1.1  reinoud 
    199  1.21    bjh21 	if (reg == VIDC_PALETTE) {
    200   1.1  reinoud 		WriteWord(vidc_base, reg | value);
    201   1.1  reinoud 		vidc_current->palette[vidc_current->palreg] = value;
    202   1.1  reinoud 		vidc_current->palreg++;
    203   1.1  reinoud 		vidc_current->palreg = vidc_current->palreg & 0xff;
    204   1.1  reinoud 		return 0;
    205   1.1  reinoud 	}
    206   1.1  reinoud 
    207   1.1  reinoud 	/*
    208   1.1  reinoud 	 * Undefine SAFER if you wish to speed things up (a little)
    209  1.37   andvar 	 * although this means the function will assume things about
    210   1.1  reinoud 	 * the structure of vidc_state. i.e. the first 256 words are
    211   1.1  reinoud 	 * the palette array
    212   1.1  reinoud 	 */
    213   1.1  reinoud 
    214   1.1  reinoud #define SAFER
    215   1.1  reinoud 
    216   1.1  reinoud #ifdef 	SAFER
    217   1.1  reinoud #define INITVALUE 0
    218   1.1  reinoud #else
    219   1.1  reinoud #define INITVALUE 256
    220   1.1  reinoud #endif
    221   1.1  reinoud 
    222  1.21    bjh21 	for (counter = INITVALUE;
    223  1.21    bjh21 	     counter <= sizeof(struct vidc_state);
    224  1.21    bjh21 	     counter++) {
    225  1.21    bjh21 		if (reg == tab[counter]) {
    226   1.1  reinoud 			WriteWord ( vidc_base, reg | value );
    227   1.1  reinoud 			current[counter] = value;
    228   1.1  reinoud 			return 0;
    229   1.1  reinoud 		}
    230   1.1  reinoud 	}
    231   1.1  reinoud 	return -1;
    232   1.1  reinoud }
    233   1.1  reinoud 
    234   1.1  reinoud 
    235   1.1  reinoud void
    236  1.21    bjh21 vidcvideo_setpalette(struct vidc_state *vidc)
    237   1.1  reinoud {
    238   1.1  reinoud 	int counter = 0;
    239   1.1  reinoud 
    240   1.1  reinoud 	vidcvideo_write(VIDC_PALREG, 0x00000000);
    241  1.15  reinoud 	for (counter = 0; counter <= 255; counter++)
    242   1.1  reinoud 		vidcvideo_write(VIDC_PALETTE, vidc->palette[counter]);
    243   1.1  reinoud }
    244   1.1  reinoud 
    245   1.1  reinoud 
    246   1.1  reinoud void
    247  1.21    bjh21 vidcvideo_setstate(struct vidc_state *vidc)
    248   1.1  reinoud {
    249   1.9  reinoud 	vidcvideo_write ( VIDC_PALREG,		vidc->palreg 	);
    250   1.1  reinoud 	vidcvideo_write ( VIDC_BCOL,		vidc->bcol	);
    251   1.1  reinoud 	vidcvideo_write ( VIDC_CP1,		vidc->cp1	);
    252   1.1  reinoud 	vidcvideo_write ( VIDC_CP2,		vidc->cp2	);
    253   1.1  reinoud 	vidcvideo_write ( VIDC_CP3,		vidc->cp3	);
    254   1.1  reinoud 	vidcvideo_write ( VIDC_HCR,		vidc->hcr	);
    255   1.1  reinoud 	vidcvideo_write ( VIDC_HSWR,		vidc->hswr	);
    256   1.1  reinoud 	vidcvideo_write ( VIDC_HBSR,		vidc->hbsr	);
    257   1.1  reinoud 	vidcvideo_write ( VIDC_HDSR,		vidc->hdsr	);
    258   1.1  reinoud 	vidcvideo_write ( VIDC_HDER,		vidc->hder	);
    259   1.1  reinoud 	vidcvideo_write ( VIDC_HBER,		vidc->hber	);
    260   1.1  reinoud 	vidcvideo_write ( VIDC_HCSR,		vidc->hcsr	);
    261   1.1  reinoud 	vidcvideo_write ( VIDC_HIR,		vidc->hir	);
    262   1.1  reinoud 	vidcvideo_write ( VIDC_VCR,		vidc->vcr	);
    263   1.1  reinoud 	vidcvideo_write ( VIDC_VSWR,		vidc->vswr	);
    264   1.1  reinoud 	vidcvideo_write ( VIDC_VBSR,		vidc->vbsr	);
    265   1.1  reinoud 	vidcvideo_write ( VIDC_VDSR,		vidc->vdsr	);
    266   1.1  reinoud 	vidcvideo_write ( VIDC_VDER,		vidc->vder	);
    267   1.1  reinoud 	vidcvideo_write ( VIDC_VBER,		vidc->vber	);
    268   1.1  reinoud 	vidcvideo_write ( VIDC_VCSR,		vidc->vcsr	);
    269   1.1  reinoud 	vidcvideo_write ( VIDC_VCER,		vidc->vcer	);
    270   1.1  reinoud /*
    271   1.1  reinoud  * Right, dunno what to set these to yet, but let's keep RiscOS's
    272   1.1  reinoud  * ones for now, until the time is right to finish this code
    273   1.1  reinoud  */
    274   1.1  reinoud 
    275   1.1  reinoud /*	vidcvideo_write ( VIDC_EREG,		vidc->ereg	);	*/
    276   1.1  reinoud /*	vidcvideo_write ( VIDC_FSYNREG,	vidc->fsynreg	);	*/
    277   1.1  reinoud /*	vidcvideo_write ( VIDC_CONREG,	vidc->conreg	);	*/
    278   1.1  reinoud /*	vidcvideo_write ( VIDC_DCTL,		vidc->dctl	);	*/
    279   1.1  reinoud 
    280  1.15  reinoud 	vidcvideo_setpalette(vidc);
    281   1.1  reinoud }
    282   1.1  reinoud 
    283   1.1  reinoud 
    284   1.1  reinoud void
    285  1.21    bjh21 vidcvideo_getstate(struct vidc_state *vidc)
    286   1.1  reinoud {
    287  1.21    bjh21 
    288   1.1  reinoud 	*vidc = *vidc_current;
    289   1.1  reinoud }
    290   1.1  reinoud 
    291   1.1  reinoud 
    292   1.1  reinoud void
    293  1.21    bjh21 vidcvideo_getmode(struct vidc_mode *mode)
    294   1.1  reinoud {
    295  1.21    bjh21 
    296  1.25    bjh21 	*mode = vidc_currentmode;
    297   1.1  reinoud }
    298   1.1  reinoud 
    299   1.1  reinoud 
    300   1.1  reinoud static int
    301   1.1  reinoud vidcvideo_coldinit(void)
    302   1.1  reinoud {
    303  1.26    bjh21 	struct videomode const *modes;
    304  1.27    bjh21 	unsigned besterror;
    305  1.26    bjh21 	int count;
    306  1.23    bjh21 	int i;
    307  1.24    bjh21 	unsigned framerate;
    308   1.1  reinoud 
    309   1.1  reinoud 	/* Blank out the cursor */
    310   1.1  reinoud 
    311   1.1  reinoud 	vidcvideo_write(VIDC_CP1, 0x0);
    312   1.1  reinoud 	vidcvideo_write(VIDC_CP2, 0x0);
    313   1.1  reinoud 	vidcvideo_write(VIDC_CP3, 0x0);
    314   1.1  reinoud 
    315   1.1  reinoud 	dispbase = vmem_base = dispstart = videomemory.vidm_vbase;
    316   1.1  reinoud 	phys_base = videomemory.vidm_pbase;
    317   1.1  reinoud 
    318   1.1  reinoud 	/* Nut - should be using videomemory.vidm_size - mark */
    319   1.1  reinoud 	if (videomemory.vidm_type == VIDEOMEM_TYPE_DRAM) {
    320   1.1  reinoud 		dispsize = videomemory.vidm_size;
    321   1.1  reinoud 		transfersize = 16;
    322   1.1  reinoud 	} else {
    323  1.16  thorpej 		dispsize = bootconfig.vram[0].pages * PAGE_SIZE;
    324   1.1  reinoud 		transfersize = dispsize >> 10;
    325  1.21    bjh21 	}
    326   1.1  reinoud 
    327   1.1  reinoud 	ptov = dispbase - phys_base;
    328   1.1  reinoud 
    329   1.1  reinoud 	dispend = dispstart+dispsize;
    330   1.1  reinoud 
    331  1.26    bjh21 	if (vidc_videomode_count > 0) {
    332  1.26    bjh21 		modes = vidc_videomode_list;
    333  1.26    bjh21 		count = vidc_videomode_count;
    334  1.26    bjh21 	} else {
    335  1.26    bjh21 		modes = videomode_list;
    336  1.26    bjh21 		count = videomode_count;
    337  1.26    bjh21 	}
    338  1.26    bjh21 
    339   1.1  reinoud 	/* try to find the current mode from the bootloader in my table */
    340  1.26    bjh21 	vidc_currentmode.timings = modes[0];
    341  1.27    bjh21 	besterror = 1000000;
    342  1.26    bjh21 	for (i = 0; i < count; i++) {
    343  1.28    bjh21 		/* We don't support interlace or doublescan */
    344  1.28    bjh21 		if (modes[i].flags & (VID_INTERLACE | VID_DBLSCAN))
    345  1.28    bjh21 			continue;
    346  1.24    bjh21 		/*
    347  1.24    bjh21 		 * We jump through a few hoops here to ensure that we
    348  1.24    bjh21 		 * round roughly to the nearest integer without too
    349  1.24    bjh21 		 * much danger of overflow.
    350  1.24    bjh21 		 */
    351  1.26    bjh21 		framerate = (modes[i].dot_clock * 1000 /
    352  1.26    bjh21 		    modes[i].htotal * 2 / modes[i].vtotal + 1) / 2;
    353  1.26    bjh21   		if (modes[i].hdisplay == bootconfig.width + 1
    354  1.26    bjh21   		    && modes[i].vdisplay == bootconfig.height + 1
    355  1.27    bjh21 		    && abs(framerate - bootconfig.framerate) < besterror) {
    356  1.26    bjh21 			vidc_currentmode.timings = modes[i];
    357  1.27    bjh21 			besterror = abs(framerate - bootconfig.framerate);
    358   1.1  reinoud 		}
    359   1.1  reinoud 	}
    360   1.1  reinoud 
    361  1.25    bjh21 	vidc_currentmode.log2_bpp = bootconfig.log2_bpp;
    362   1.1  reinoud 
    363   1.1  reinoud 	dispstart = dispbase;
    364   1.1  reinoud 	dispend = dispstart+dispsize;
    365   1.1  reinoud 
    366   1.1  reinoud 	IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
    367   1.1  reinoud 	IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
    368   1.1  reinoud 	IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
    369   1.1  reinoud 	return 0;
    370   1.1  reinoud }
    371   1.1  reinoud 
    372   1.1  reinoud 
    373   1.1  reinoud /* simple function to abstract vidc variables ; returns virt start address of screen */
    374  1.35   andvar /* XXX assumption that video memory is mapped in twice */
    375  1.21    bjh21 void *vidcvideo_hwscroll(int bytes)
    376  1.21    bjh21 {
    377  1.21    bjh21 
    378   1.1  reinoud 	dispstart += bytes;
    379   1.1  reinoud 	if (dispstart >= dispbase + dispsize) dispstart -= dispsize;
    380   1.1  reinoud 	if (dispstart <  dispbase)            dispstart += dispsize;
    381   1.1  reinoud 	dispend = dispstart+dispsize;
    382   1.1  reinoud 
    383   1.1  reinoud 	/* return the start of the bit map of the screen (left top) */
    384  1.21    bjh21 	return (void *)dispstart;
    385   1.1  reinoud }
    386   1.1  reinoud 
    387   1.1  reinoud 
    388   1.1  reinoud /* reset the HW scroll to be at the start for the benefit of f.e. X */
    389  1.21    bjh21 void *vidcvideo_hwscroll_reset(void)
    390  1.21    bjh21 {
    391  1.21    bjh21 	void *cookie = (void *)dispstart;
    392   1.1  reinoud 
    393   1.1  reinoud 	dispstart = dispbase;
    394   1.1  reinoud 	dispend = dispstart + dispsize;
    395   1.1  reinoud 	return cookie;
    396   1.1  reinoud }
    397   1.1  reinoud 
    398   1.1  reinoud 
    399   1.1  reinoud /* put HW scroll back to where it was */
    400  1.21    bjh21 void *vidcvideo_hwscroll_back(void *cookie)
    401  1.21    bjh21 {
    402  1.21    bjh21 
    403  1.21    bjh21 	dispstart = (int)cookie;
    404   1.1  reinoud 	dispend = dispstart + dispsize;
    405   1.1  reinoud 	return cookie;
    406   1.1  reinoud }
    407   1.1  reinoud 
    408   1.1  reinoud 
    409  1.36   andvar /* this function is to be called preferably at vsync */
    410  1.21    bjh21 void vidcvideo_progr_scroll(void)
    411  1.21    bjh21 {
    412  1.21    bjh21 
    413   1.1  reinoud 	IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
    414   1.1  reinoud 	IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
    415   1.1  reinoud 	IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
    416   1.1  reinoud }
    417   1.1  reinoud 
    418   1.1  reinoud 
    419   1.1  reinoud /*
    420   1.1  reinoud  * Select a new mode by reprogramming the VIDC chip
    421   1.1  reinoud  * XXX this part is known not to work for 32bpp
    422   1.1  reinoud  */
    423   1.1  reinoud 
    424   1.1  reinoud struct vidc_mode newmode;
    425   1.1  reinoud 
    426   1.1  reinoud static const int bpp_mask_table[] = {
    427   1.1  reinoud 	0,  /* 1bpp */
    428   1.1  reinoud 	1,  /* 2bpp */
    429   1.1  reinoud 	2,  /* 4bpp */
    430   1.1  reinoud 	3,  /* 8bpp */
    431   1.1  reinoud 	4,  /* 16bpp */
    432   1.1  reinoud 	6   /* 32bpp */
    433   1.1  reinoud };
    434   1.1  reinoud 
    435   1.1  reinoud 
    436   1.1  reinoud void
    437   1.1  reinoud vidcvideo_setmode(struct vidc_mode *mode)
    438   1.1  reinoud {
    439  1.23    bjh21 	struct videomode *vm;
    440   1.1  reinoud 	int bpp_mask;
    441   1.1  reinoud         int ereg;
    442   1.5    bjh21 	int best_r, best_v;
    443   1.5    bjh21 	int least_error;
    444   1.5    bjh21 	int r, v, f;
    445   1.1  reinoud 
    446   1.1  reinoud 	/*
    447  1.21    bjh21 	 * Find out what bit mask we need to or with the vidc20
    448  1.21    bjh21 	 * control register in order to generate the desired number of
    449  1.21    bjh21 	 * bits per pixel.  log_bpp is log base 2 of the number of
    450  1.21    bjh21 	 * bits per pixel.
    451   1.1  reinoud 	 */
    452   1.1  reinoud 
    453   1.1  reinoud 	bpp_mask = bpp_mask_table[mode->log2_bpp];
    454   1.1  reinoud 
    455  1.25    bjh21 	vidc_currentmode = *mode;
    456  1.25    bjh21 	vm = &vidc_currentmode.timings;
    457   1.1  reinoud 
    458   1.5    bjh21 	least_error = INT_MAX;
    459   1.5    bjh21 	best_r = 0; best_v = 0;
    460   1.5    bjh21 
    461   1.5    bjh21 	for (v = 63; v > 0; v--) {
    462   1.5    bjh21 		for (r = 63; r > 0; r--) {
    463   1.5    bjh21 			f = ((v * vidc_fref) /1000) / r;
    464  1.23    bjh21 			if (least_error >= abs(f - vm->dot_clock)) {
    465  1.23    bjh21 				least_error =  abs(f - vm->dot_clock);
    466   1.5    bjh21 				best_r = r;
    467   1.5    bjh21 				best_v = v;
    468   1.1  reinoud 			}
    469   1.1  reinoud 		}
    470   1.5    bjh21 	}
    471   1.1  reinoud 
    472   1.5    bjh21 	if (best_r > 63) best_r=63;
    473   1.5    bjh21 	if (best_v > 63) best_v=63;
    474   1.5    bjh21 	if (best_r < 1)  best_r= 1;
    475   1.5    bjh21 	if (best_v < 1)  best_v= 1;
    476   1.1  reinoud 
    477   1.2  reinoud 	vidcvideo_write(VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0);
    478   1.1  reinoud 
    479  1.23    bjh21 	/*
    480  1.23    bjh21 	 * The translation from struct videomode to VIDC timings is made
    481  1.23    bjh21 	 * fun by the fact that the VIDC counts from the start of the sync
    482  1.23    bjh21 	 * pulse while struct videomode counts from the start of the display.
    483  1.23    bjh21 	 */
    484  1.23    bjh21 	vidcvideo_write(VIDC_HSWR, (vm->hsync_end - vm->hsync_start - 8) & ~1);
    485  1.23    bjh21 	vidcvideo_write(VIDC_HBSR, (vm->htotal - vm->hsync_start - 12) & ~1);
    486  1.23    bjh21 	vidcvideo_write(VIDC_HDSR, (vm->htotal - vm->hsync_start - 18) & ~1);
    487  1.23    bjh21 	vidcvideo_write(VIDC_HDER,
    488  1.23    bjh21 	    (vm->htotal - vm->hsync_start + vm->hdisplay - 18) & ~1);
    489  1.23    bjh21 	vidcvideo_write(VIDC_HBER,
    490  1.23    bjh21 	    (vm->htotal - vm->hsync_start + vm->hdisplay - 12) & ~1);
    491  1.23    bjh21 	vidcvideo_write(VIDC_HCR, (vm->htotal - 8) & ~3);
    492  1.23    bjh21 
    493  1.23    bjh21 	vidcvideo_write(VIDC_VSWR, vm->vsync_end - vm->vsync_start - 1);
    494  1.23    bjh21 	vidcvideo_write(VIDC_VBSR, vm->vtotal - vm->vsync_start - 1);
    495  1.23    bjh21 	vidcvideo_write(VIDC_VDSR, vm->vtotal - vm->vsync_start - 1);
    496  1.23    bjh21 	vidcvideo_write(VIDC_VDER,
    497  1.23    bjh21 	    vm->vtotal - vm->vsync_start + vm->vdisplay - 1);
    498  1.23    bjh21 	vidcvideo_write(VIDC_VBER,
    499  1.23    bjh21 	    vm->vtotal - vm->vsync_start + vm->vdisplay - 1);
    500  1.23    bjh21 	/* XXX VIDC20 data sheet say to subtract 2 */
    501  1.23    bjh21 	vidcvideo_write(VIDC_VCR, vm->vtotal - 1);
    502  1.23    bjh21 
    503  1.29    bjh21 	IOMD_WRITE_WORD(IOMD_FSIZE, vm->vtotal - vm->vdisplay - 1);
    504   1.1  reinoud 
    505   1.1  reinoud 	if (dispsize <= 1024*1024)
    506  1.23    bjh21 		vidcvideo_write(VIDC_DCTL, vm->hdisplay>>2 | 1<<16 | 1<<12);
    507   1.1  reinoud 	else
    508  1.23    bjh21 		vidcvideo_write(VIDC_DCTL, vm->hdisplay>>2 | 3<<16 | 1<<12);
    509   1.1  reinoud 
    510   1.1  reinoud 	ereg = 1<<12;
    511  1.23    bjh21 	if (vm->flags & VID_NHSYNC)
    512   1.1  reinoud 		ereg |= 1<<16;
    513  1.23    bjh21 	if (vm->flags & VID_NVSYNC)
    514   1.1  reinoud 		ereg |= 1<<18;
    515   1.1  reinoud 	vidcvideo_write(VIDC_EREG, ereg);
    516  1.30    bjh21 
    517  1.30    bjh21 	/*
    518  1.30    bjh21 	 * Set the video FIFO preload value and bit depth.  Chapter 6
    519  1.30    bjh21 	 * of the VIDC20 Data Sheet has full details of the FIFO
    520  1.30    bjh21 	 * preload, but we don't do anything clever and just use the
    521  1.30    bjh21 	 * largest possible value, which is 7 when the VIDC20 is in
    522  1.30    bjh21 	 * 32-bit mode (0MB or 1MB VRAM) and 6 when it is in 64-bit
    523  1.30    bjh21 	 * mode (2MB VRAM).
    524  1.30    bjh21 	 */
    525  1.30    bjh21 	if (dispsize > 1024*1024)
    526  1.30    bjh21 		vidcvideo_write(VIDC_CONREG, 6<<8 | bpp_mask<<5);
    527  1.30    bjh21 	else
    528   1.1  reinoud 		vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
    529   1.1  reinoud }
    530   1.1  reinoud 
    531   1.1  reinoud 
    532   1.7    bjh21 #if 0
    533   1.1  reinoud /* not used for now */
    534   1.1  reinoud void
    535  1.31      dsl vidcvideo_set_display_base(u_int base)
    536   1.1  reinoud {
    537   1.1  reinoud 	dispstart = dispstart-dispbase + base;
    538   1.1  reinoud 	dispbase = vmem_base = base;
    539   1.1  reinoud 	dispend = base + dispsize;
    540   1.1  reinoud 	ptov = dispbase - phys_base;
    541   1.1  reinoud }
    542   1.7    bjh21 #endif
    543   1.1  reinoud 
    544   1.1  reinoud 
    545   1.1  reinoud /*
    546   1.1  reinoud  * Main initialisation routine for now
    547   1.1  reinoud  */
    548   1.1  reinoud 
    549   1.1  reinoud static int cursor_init = 0;
    550   1.1  reinoud 
    551   1.1  reinoud int
    552   1.1  reinoud vidcvideo_init(void)
    553   1.1  reinoud {
    554   1.1  reinoud 	vidcvideo_coldinit();
    555   1.1  reinoud 	if (cold_init && (cursor_init == 0))
    556   1.1  reinoud 		/*	vidcvideo_flash_go() */;
    557   1.1  reinoud 
    558   1.1  reinoud 	/* setting a mode goes wrong in 32 bpp ... 8 and 16 seem OK */
    559  1.25    bjh21 	vidcvideo_setmode(&vidc_currentmode);
    560   1.1  reinoud 	vidcvideo_blank(0);			/* display on */
    561   1.1  reinoud 
    562  1.12    bjh21 	vidcvideo_stdpalette();
    563   1.1  reinoud 
    564   1.1  reinoud 	if (cold_init == 0) {
    565   1.1  reinoud 		vidcvideo_write(VIDC_CP1, 0x0);
    566   1.1  reinoud 		vidcvideo_write(VIDC_CP2, 0x0);
    567   1.1  reinoud 		vidcvideo_write(VIDC_CP3, 0x0);
    568  1.21    bjh21 	} else
    569   1.1  reinoud 		vidcvideo_cursor_init(CURSOR_MAX_WIDTH, CURSOR_MAX_HEIGHT);
    570   1.1  reinoud 
    571  1.21    bjh21 	cold_init = 1;
    572   1.1  reinoud 	return 0;
    573   1.1  reinoud }
    574   1.1  reinoud 
    575   1.1  reinoud 
    576   1.1  reinoud /* reinitialise the vidcvideo */
    577   1.1  reinoud void
    578  1.32   cegger vidcvideo_reinit(void)
    579   1.1  reinoud {
    580  1.21    bjh21 
    581   1.1  reinoud 	vidcvideo_coldinit();
    582  1.25    bjh21 	vidcvideo_setmode(&vidc_currentmode);
    583   1.1  reinoud }
    584   1.1  reinoud 
    585   1.1  reinoud 
    586   1.1  reinoud int
    587   1.1  reinoud vidcvideo_cursor_init(int width, int height)
    588   1.1  reinoud {
    589   1.1  reinoud 	static char *cursor_data = NULL;
    590   1.1  reinoud 	int counter;
    591   1.1  reinoud 	int line;
    592   1.1  reinoud 	paddr_t pa;
    593   1.1  reinoud 
    594   1.1  reinoud 	cursor_width  = width;
    595   1.1  reinoud 	cursor_height = height;
    596   1.1  reinoud 
    597   1.1  reinoud 	if (!cursor_data) {
    598   1.1  reinoud 		/* Allocate cursor memory first time round */
    599  1.19     yamt 		cursor_data = (char *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
    600  1.19     yamt 		    UVM_KMF_WIRED | UVM_KMF_ZERO);
    601   1.1  reinoud 		if (!cursor_data)
    602  1.14   provos 			panic("Cannot allocate memory for hardware cursor");
    603   1.1  reinoud 		(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_data, &pa);
    604   1.1  reinoud 		IOMD_WRITE_WORD(IOMD_CURSINIT, pa);
    605   1.1  reinoud 	}
    606   1.1  reinoud 
    607  1.33      snj 	/* Blank the cursor while initialising its sprite */
    608   1.1  reinoud 
    609   1.1  reinoud 	vidcvideo_write ( VIDC_CP1, 0x0 );
    610   1.1  reinoud 	vidcvideo_write ( VIDC_CP2, 0x0 );
    611   1.1  reinoud 	vidcvideo_write ( VIDC_CP3, 0x0 );
    612   1.1  reinoud 
    613   1.1  reinoud  	cursor_normal       = cursor_data;
    614   1.1  reinoud 	cursor_transparent  = cursor_data + (height * width);
    615   1.1  reinoud 
    616   1.1  reinoud  	cursor_transparent += 32;					/* ALIGN */
    617   1.1  reinoud 	cursor_transparent = (char *)((int)cursor_transparent & (~31) );
    618   1.1  reinoud 
    619  1.21    bjh21 	for ( line = 0; line<height; ++line ) {
    620  1.21    bjh21 		for ( counter=0; counter<width/4;counter++ )
    621  1.21    bjh21 			cursor_normal[line * width + counter]=0x55;		/* why 0x55 ? */
    622  1.21    bjh21 		for ( ; counter<8; counter++ )
    623  1.21    bjh21 			cursor_normal[line * width + counter]=0;
    624   1.1  reinoud 	}
    625   1.1  reinoud 
    626  1.21    bjh21 	for ( line = 0; line<height; ++line ) {
    627  1.21    bjh21 		for ( counter=0; counter<width/4;counter++ )
    628  1.21    bjh21 			cursor_transparent[line * width + counter]=0x00;
    629  1.21    bjh21 		for ( ; counter<8; counter++ )
    630  1.21    bjh21 			cursor_transparent[line * width + counter]=0;
    631   1.1  reinoud 	}
    632   1.1  reinoud 
    633   1.1  reinoud 
    634   1.1  reinoud 	(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_normal,
    635  1.17     matt 	    (void *)&p_cursor_normal);
    636   1.1  reinoud 	(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_transparent,
    637  1.17     matt 	    (void *)&p_cursor_transparent);
    638   1.1  reinoud 
    639  1.21    bjh21 	memset(cursor_normal, 0x55, width*height);		/* white? */
    640  1.21    bjh21 	memset(cursor_transparent, 0x00, width*height);/* to see the diffence */
    641   1.1  reinoud 
    642   1.1  reinoud 	/* Ok, now program the cursor; should be blank */
    643   1.1  reinoud 	vidcvideo_enablecursor(0);
    644   1.1  reinoud 
    645   1.1  reinoud         return 0;
    646   1.1  reinoud }
    647   1.1  reinoud 
    648   1.1  reinoud 
    649   1.1  reinoud void
    650  1.21    bjh21 vidcvideo_updatecursor(int xcur, int ycur)
    651   1.1  reinoud {
    652  1.25    bjh21 	int frontporch = vidc_currentmode.timings.htotal -
    653  1.25    bjh21 	    vidc_currentmode.timings.hsync_start;
    654  1.25    bjh21 	int topporch   =  vidc_currentmode.timings.vtotal -
    655  1.25    bjh21 	    vidc_currentmode.timings.vsync_start;
    656   1.1  reinoud 
    657   1.1  reinoud 	vidcvideo_write(VIDC_HCSR, frontporch -17 + xcur);
    658  1.21    bjh21 	vidcvideo_write(VIDC_VCSR, topporch   -2  + (ycur+1)-2 + 3 -
    659  1.21    bjh21 	    cursor_height);
    660   1.1  reinoud 	vidcvideo_write(VIDC_VCER, topporch   -2  + (ycur+3)+2 + 3 );
    661   1.1  reinoud }
    662   1.1  reinoud 
    663   1.1  reinoud 
    664   1.1  reinoud void
    665  1.21    bjh21 vidcvideo_enablecursor(int on)
    666   1.1  reinoud {
    667  1.21    bjh21 
    668  1.21    bjh21 	if (on)
    669   1.1  reinoud 		IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_normal);
    670  1.21    bjh21 	else
    671   1.1  reinoud 		IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_transparent);
    672   1.1  reinoud 	vidcvideo_write ( VIDC_CP1, 0xffffff );		/* enable */
    673   1.1  reinoud }
    674   1.1  reinoud 
    675  1.11    bjh21 
    676  1.12    bjh21 void
    677  1.32   cegger vidcvideo_stdpalette(void)
    678  1.11    bjh21 {
    679  1.12    bjh21 	int i;
    680  1.11    bjh21 
    681  1.25    bjh21 	switch (vidc_currentmode.log2_bpp) {
    682  1.12    bjh21 	case 0: /* 1 bpp */
    683  1.12    bjh21 	case 1: /* 2 bpp */
    684  1.12    bjh21 	case 2: /* 4 bpp */
    685  1.12    bjh21 	case 3: /* 8 bpp */
    686  1.12    bjh21 		vidcvideo_write(VIDC_PALREG, 0x00000000);
    687  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
    688  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255,   0,   0));
    689  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0, 255,   0));
    690  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255,   0));
    691  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0,   0, 255));
    692  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255,   0, 255));
    693  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0, 255, 255));
    694  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
    695  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 128));
    696  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 128));
    697  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 255, 128));
    698  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 128));
    699  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 255));
    700  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 255));
    701  1.12    bjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
    702  1.12    bjh21 		break;
    703  1.12    bjh21 	case 4: /* 16 bpp */
    704  1.12    bjh21 		/*
    705  1.12    bjh21 		 * The use of the palette in 16-bit modes is quite
    706  1.12    bjh21 		 * fun.  Comments in linux/drivers/video/acornfb.c
    707  1.12    bjh21 		 * imply that it goes something like this:
    708  1.12    bjh21 		 *
    709  1.12    bjh21 		 * red   = LUT[pixel[7:0]].red
    710  1.12    bjh21 		 * green = LUT[pixel[11:4]].green
    711  1.12    bjh21 		 * blue  = LUT[pixel[15:8]].blue
    712  1.12    bjh21 		 *
    713  1.13    bjh21 		 * We use 6:5:5 R:G:B cos that's what Xarm32VIDC wants.
    714  1.12    bjh21 		 */
    715  1.13    bjh21 #define RBITS 6
    716  1.13    bjh21 #define GBITS 5
    717  1.13    bjh21 #define BBITS 5
    718  1.12    bjh21 		vidcvideo_write(VIDC_PALREG, 0x00000000);
    719  1.12    bjh21 		for (i = 0; i < 256; i++) {
    720  1.13    bjh21 			int r, g, b;
    721  1.12    bjh21 
    722  1.13    bjh21 			r = i & ((1 << RBITS) - 1);
    723  1.13    bjh21 			g = (i >> (RBITS - 4)) & ((1 << GBITS) - 1);
    724  1.13    bjh21 			b = (i >> (RBITS + GBITS - 8)) & ((1 << BBITS) - 1);
    725  1.12    bjh21 			vidcvideo_write(VIDC_PALETTE,
    726  1.13    bjh21 			    VIDC_COL(r << (8 - RBITS) | r >> (2 * RBITS - 8),
    727  1.13    bjh21 				g << (8 - GBITS) | g >> (2 * GBITS - 8),
    728  1.13    bjh21 				b << (8 - BBITS) | b >> (2 * BBITS - 8)));
    729  1.12    bjh21 		}
    730  1.12    bjh21 		break;
    731  1.12    bjh21 	case 5: /* 32 bpp */
    732  1.12    bjh21 		vidcvideo_write(VIDC_PALREG, 0x00000000);
    733  1.12    bjh21 		for (i = 0; i < 256; i++)
    734  1.12    bjh21 			vidcvideo_write(VIDC_PALETTE, VIDC_COL(i, i, i));
    735  1.12    bjh21 		break;
    736  1.12    bjh21 	}
    737  1.11    bjh21 }
    738   1.1  reinoud 
    739   1.1  reinoud int
    740  1.21    bjh21 vidcvideo_blank(int video_off)
    741   1.1  reinoud {
    742   1.1  reinoud         int ereg;
    743   1.1  reinoud 
    744   1.1  reinoud 	ereg = 1<<12;
    745  1.25    bjh21 	if (vidc_currentmode.timings.flags & VID_NHSYNC)
    746   1.1  reinoud 		ereg |= 1<<16;
    747  1.25    bjh21 	if (vidc_currentmode.timings.flags & VID_NVSYNC)
    748   1.1  reinoud 		ereg |= 1<<18;
    749   1.1  reinoud 
    750  1.21    bjh21 	if (!video_off)
    751   1.1  reinoud     		vidcvideo_write(VIDC_EREG, ereg);
    752  1.21    bjh21 	else
    753   1.1  reinoud 		vidcvideo_write(VIDC_EREG, 0);
    754   1.1  reinoud 	return 0;
    755   1.1  reinoud }
    756   1.1  reinoud 
    757   1.1  reinoud /* end of vidc20config.c */
    758