Home | History | Annotate | Line # | Download | only in dev
plumvideo.c revision 1.14
      1  1.14     uch /*	$NetBSD: plumvideo.c,v 1.14 2000/10/04 13:53:55 uch Exp $ */
      2   1.1     uch 
      3   1.7     uch /*-
      4  1.14     uch  * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
      5  1.14     uch  * All rights reserved.
      6  1.14     uch  *
      7  1.14     uch  * This code is derived from software contributed to The NetBSD Foundation
      8  1.14     uch  * by UCHIYAMA Yasushi.
      9   1.1     uch  *
     10   1.1     uch  * Redistribution and use in source and binary forms, with or without
     11   1.1     uch  * modification, are permitted provided that the following conditions
     12   1.1     uch  * are met:
     13   1.1     uch  * 1. Redistributions of source code must retain the above copyright
     14   1.1     uch  *    notice, this list of conditions and the following disclaimer.
     15   1.7     uch  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.7     uch  *    notice, this list of conditions and the following disclaimer in the
     17   1.7     uch  *    documentation and/or other materials provided with the distribution.
     18  1.14     uch  * 3. All advertising materials mentioning features or use of this software
     19  1.14     uch  *    must display the following acknowledgement:
     20  1.14     uch  *        This product includes software developed by the NetBSD
     21  1.14     uch  *        Foundation, Inc. and its contributors.
     22  1.14     uch  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.14     uch  *    contributors may be used to endorse or promote products derived
     24  1.14     uch  *    from this software without specific prior written permission.
     25   1.1     uch  *
     26  1.14     uch  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.14     uch  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.14     uch  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.14     uch  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.14     uch  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.14     uch  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.14     uch  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.14     uch  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.14     uch  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.14     uch  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.14     uch  * POSSIBILITY OF SUCH DAMAGE.
     37   1.1     uch  */
     38  1.14     uch 
     39  1.11     uch #define PLUMVIDEODEBUG
     40   1.1     uch #include "opt_tx39_debug.h"
     41  1.14     uch #include "plumohci.h" /* Plum2 OHCI shared memory allocated on V-RAM */
     42   1.1     uch 
     43   1.1     uch #include <sys/param.h>
     44   1.1     uch #include <sys/systm.h>
     45   1.1     uch #include <sys/device.h>
     46   1.1     uch 
     47   1.8     uch #include <sys/ioctl.h>
     48   1.8     uch #include <sys/buf.h>
     49  1.13     mrg #include <uvm/uvm_extern.h>
     50   1.8     uch 
     51   1.2     uch #include <dev/cons.h> /* consdev */
     52   1.2     uch 
     53   1.1     uch #include <machine/bus.h>
     54   1.1     uch #include <machine/intr.h>
     55  1.14     uch #include <machine/config_hook.h>
     56   1.1     uch 
     57   1.1     uch #include <hpcmips/tx/tx39var.h>
     58   1.1     uch #include <hpcmips/dev/plumvar.h>
     59   1.1     uch #include <hpcmips/dev/plumicuvar.h>
     60   1.1     uch #include <hpcmips/dev/plumpowervar.h>
     61   1.1     uch #include <hpcmips/dev/plumvideoreg.h>
     62   1.1     uch 
     63   1.2     uch #include <machine/bootinfo.h>
     64   1.2     uch 
     65   1.8     uch #include <dev/wscons/wsdisplayvar.h>
     66   1.8     uch #include <dev/rasops/rasops.h>
     67   1.8     uch #include <arch/hpcmips/dev/video_subr.h>
     68   1.8     uch 
     69   1.6    sato #include <dev/wscons/wsconsio.h>
     70   1.4     uch #include <arch/hpcmips/dev/hpcfbvar.h>
     71   1.4     uch #include <arch/hpcmips/dev/hpcfbio.h>
     72   1.1     uch 
     73   1.3     uch #ifdef PLUMVIDEODEBUG
     74   1.3     uch int	plumvideo_debug = 1;
     75   1.3     uch #define	DPRINTF(arg) if (plumvideo_debug) printf arg;
     76   1.3     uch #define	DPRINTFN(n, arg) if (plumvideo_debug > (n)) printf arg;
     77   1.3     uch #else
     78   1.3     uch #define	DPRINTF(arg)
     79   1.3     uch #define DPRINTFN(n, arg)
     80   1.3     uch #endif
     81   1.3     uch 
     82   1.1     uch struct plumvideo_softc {
     83   1.7     uch 	struct device sc_dev;
     84  1.11     uch 	tx_chipset_tag_t sc_tc;
     85  1.11     uch 	plum_chipset_tag_t sc_pc;
     86   1.8     uch 
     87  1.14     uch 	void *sc_powerhook;	/* power management hook */
     88  1.14     uch 
     89   1.8     uch 	/* control register */
     90   1.7     uch 	bus_space_tag_t sc_regt;
     91   1.7     uch 	bus_space_handle_t sc_regh;
     92   1.8     uch 	/* frame buffer */
     93   1.8     uch 	bus_space_tag_t sc_fbiot;
     94   1.8     uch 	bus_space_handle_t sc_fbioh;
     95   1.8     uch 	/* clut buffer (8bpp only) */
     96   1.8     uch 	bus_space_tag_t sc_clutiot;
     97   1.8     uch 	bus_space_handle_t sc_clutioh;
     98   1.8     uch 	/* bitblt */
     99   1.8     uch 	bus_space_tag_t sc_bitbltt;
    100   1.8     uch 	bus_space_handle_t sc_bitblth;
    101   1.7     uch 
    102  1.11     uch 	struct video_chip sc_chip;
    103   1.8     uch 	struct hpcfb_fbconf sc_fbconf;
    104   1.8     uch 	struct hpcfb_dspconf sc_dspconf;
    105   1.1     uch };
    106   1.1     uch 
    107  1.14     uch int	plumvideo_match(struct device*, struct cfdata*, void*);
    108  1.14     uch void	plumvideo_attach(struct device*, struct device*, void*);
    109   1.8     uch 
    110  1.14     uch int	plumvideo_ioctl(void *, u_long, caddr_t, int, struct proc *);
    111  1.14     uch paddr_t	plumvideo_mmap(void *, off_t, int);
    112   1.7     uch 
    113   1.1     uch struct cfattach plumvideo_ca = {
    114   1.1     uch 	sizeof(struct plumvideo_softc), plumvideo_match, plumvideo_attach
    115   1.1     uch };
    116   1.1     uch 
    117   1.7     uch struct hpcfb_accessops plumvideo_ha = {
    118   1.7     uch 	plumvideo_ioctl, plumvideo_mmap
    119   1.1     uch };
    120   1.1     uch 
    121  1.14     uch int	plumvideo_power(void *, int, long, void *);
    122  1.14     uch 
    123  1.14     uch int	plumvideo_init(struct plumvideo_softc *, int *);
    124  1.14     uch void	plumvideo_hpcfbinit(struct plumvideo_softc *, int);
    125   1.8     uch 
    126  1.14     uch void	plumvideo_clut_default(struct plumvideo_softc *);
    127  1.14     uch void	plumvideo_clut_set(struct plumvideo_softc *, u_int32_t *, int, int);
    128  1.14     uch void	plumvideo_clut_get(struct plumvideo_softc *, u_int32_t *, int, int);
    129  1.14     uch void	__plumvideo_clut_access(struct plumvideo_softc *,
    130  1.14     uch 				void (*)(bus_space_tag_t, bus_space_handle_t));
    131  1.14     uch static void _flush_cache(void) __attribute__((__unused__)); /* !!! */
    132   1.8     uch 
    133   1.3     uch #ifdef PLUMVIDEODEBUG
    134  1.14     uch void	plumvideo_dump(struct plumvideo_softc*);
    135   1.3     uch #endif
    136   1.1     uch 
    137  1.14     uch #define ON	1
    138  1.14     uch #define OFF	0
    139  1.14     uch 
    140   1.1     uch int
    141  1.14     uch plumvideo_match(struct device *parent, struct cfdata *cf, void *aux)
    142   1.1     uch {
    143   1.2     uch 	/*
    144   1.2     uch 	 * VRAM area also uses as UHOSTC shared RAM.
    145   1.2     uch 	 */
    146   1.8     uch 	return (2); /* 1st attach group */
    147   1.1     uch }
    148   1.1     uch 
    149   1.1     uch void
    150  1.14     uch plumvideo_attach(struct device *parent, struct device *self, void *aux)
    151   1.1     uch {
    152   1.1     uch 	struct plum_attach_args *pa = aux;
    153   1.1     uch 	struct plumvideo_softc *sc = (void*)self;
    154   1.7     uch 	struct hpcfb_attach_args ha;
    155  1.14     uch 	int console, reverse_flag;
    156   1.1     uch 
    157   1.1     uch 	sc->sc_pc	= pa->pa_pc;
    158   1.1     uch 	sc->sc_regt	= pa->pa_regt;
    159   1.8     uch 	sc->sc_fbiot = sc->sc_clutiot = sc->sc_bitbltt  = pa->pa_iot;
    160   1.1     uch 
    161   1.7     uch 	printf(": ");
    162  1.14     uch 
    163  1.14     uch 	/* map register area */
    164   1.1     uch 	if (bus_space_map(sc->sc_regt, PLUM_VIDEO_REGBASE,
    165   1.1     uch 			  PLUM_VIDEO_REGSIZE, 0, &sc->sc_regh)) {
    166  1.14     uch 		printf("register map failed\n");
    167   1.1     uch 		return;
    168   1.1     uch 	}
    169   1.2     uch 
    170  1.14     uch 	/* power control */
    171   1.3     uch #ifndef PLUMVIDEODEBUG
    172  1.14     uch 	if (bootinfo->bi_cnuse & BI_CNUSE_SERIAL)
    173  1.14     uch 		plumvideo_power(sc, 0, 0, (void *)PWR_SUSPEND);
    174  1.14     uch 	else
    175   1.3     uch #endif
    176  1.14     uch 		plumvideo_power(sc, 0, 0, (void *)PWR_RESUME);
    177  1.14     uch 	/* Add a hard power hook to power saving */
    178  1.14     uch 	sc->sc_powerhook = config_hook(CONFIG_HOOK_PMEVENT,
    179  1.14     uch 				       CONFIG_HOOK_PMEVENT_HARDPOWER,
    180  1.14     uch 				       CONFIG_HOOK_SHARE,
    181  1.14     uch 				       plumvideo_power, sc);
    182  1.14     uch 	if (sc->sc_powerhook == 0)
    183  1.14     uch 		printf("WARNING unable to establish hard power hook");
    184  1.14     uch 
    185   1.2     uch 	/*
    186   1.5     uch 	 *  Initialize LCD controller
    187   1.5     uch 	 *	map V-RAM area.
    188   1.5     uch 	 *	reinstall bootinfo structure.
    189   1.5     uch 	 *	some OHCI shared-buffer hack. XXX
    190   1.2     uch 	 */
    191  1.14     uch 	if (plumvideo_init(sc, &reverse_flag) != 0)
    192   1.5     uch 		return;
    193   1.5     uch 
    194   1.5     uch 	printf("\n");
    195   1.2     uch 
    196  1.11     uch 	/* Attach frame buffer device */
    197  1.14     uch 	plumvideo_hpcfbinit(sc, reverse_flag);
    198  1.11     uch 
    199   1.3     uch #ifdef PLUMVIDEODEBUG
    200  1.11     uch 	if (plumvideo_debug > 1)
    201   1.3     uch 		plumvideo_dump(sc);
    202  1.11     uch 	/* attach debug draw routine (debugging use) */
    203  1.11     uch 	video_attach_drawfunc(&sc->sc_chip);
    204  1.11     uch 	tx_conf_register_video(sc->sc_pc->pc_tc, &sc->sc_chip);
    205  1.11     uch #endif /* PLUMVIDEODEBUG */
    206   1.3     uch 
    207   1.7     uch 	console = cn_tab ? 0 : 1;
    208   1.7     uch 	if(console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
    209   1.2     uch 		panic("plumvideo_attach: can't init fb console");
    210   1.2     uch 	}
    211   1.7     uch 
    212   1.7     uch 	ha.ha_console = console;
    213   1.7     uch 	ha.ha_accessops = &plumvideo_ha;
    214   1.7     uch 	ha.ha_accessctx = sc;
    215   1.7     uch 	ha.ha_curfbconf = 0;
    216   1.7     uch 	ha.ha_nfbconf = 1;
    217   1.7     uch 	ha.ha_fbconflist = &sc->sc_fbconf;
    218   1.7     uch 	ha.ha_curdspconf = 0;
    219   1.7     uch 	ha.ha_ndspconf = 1;
    220   1.7     uch 	ha.ha_dspconflist = &sc->sc_dspconf;
    221   1.7     uch 
    222   1.7     uch 	config_found(self, &ha, hpcfbprint);
    223   1.1     uch }
    224   1.1     uch 
    225   1.7     uch void
    226  1.14     uch plumvideo_hpcfbinit(struct plumvideo_softc *sc, int reverse_flag)
    227   1.7     uch {
    228   1.7     uch 	struct hpcfb_fbconf *fb = &sc->sc_fbconf;
    229  1.11     uch 	struct video_chip *chip = &sc->sc_chip;
    230   1.8     uch 	vaddr_t fbvaddr = (vaddr_t)sc->sc_fbioh;
    231  1.11     uch 	int height = chip->vc_fbheight;
    232  1.11     uch 	int width = chip->vc_fbwidth;
    233  1.11     uch 	int depth = chip->vc_fbdepth;
    234   1.7     uch 
    235   1.7     uch 	memset(fb, 0, sizeof(struct hpcfb_fbconf));
    236   1.7     uch 
    237   1.7     uch 	fb->hf_conf_index	= 0;	/* configuration index		*/
    238   1.7     uch 	fb->hf_nconfs		= 1;   	/* how many configurations	*/
    239   1.8     uch 	strncpy(fb->hf_name, "PLUM built-in video", HPCFB_MAXNAMELEN);
    240   1.8     uch 	/* frame buffer name		*/
    241   1.8     uch 	strncpy(fb->hf_conf_name, "LCD", HPCFB_MAXNAMELEN);
    242   1.8     uch 	/* configuration name		*/
    243  1.11     uch 	fb->hf_height		= height;
    244  1.11     uch 	fb->hf_width		= width;
    245   1.7     uch 	fb->hf_baseaddr		= mips_ptob(mips_btop(fbvaddr));
    246   1.7     uch 	fb->hf_offset		= (u_long)fbvaddr - fb->hf_baseaddr;
    247   1.8     uch 	/* frame buffer start offset   	*/
    248  1.11     uch 	fb->hf_bytes_per_line	= (width * depth) / NBBY;
    249   1.7     uch 	fb->hf_nplanes		= 1;
    250  1.11     uch 	fb->hf_bytes_per_plane	= height * fb->hf_bytes_per_line;
    251   1.7     uch 
    252   1.7     uch 	fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
    253   1.7     uch 	fb->hf_access_flags |= HPCFB_ACCESS_WORD;
    254   1.7     uch 	fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
    255  1.14     uch 	if (reverse_flag)
    256  1.14     uch 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
    257   1.7     uch 
    258  1.11     uch 	switch (depth) {
    259   1.7     uch 	default:
    260   1.7     uch 		panic("plumvideo_hpcfbinit: not supported color depth\n");
    261   1.7     uch 		/* NOTREACHED */
    262   1.7     uch 	case 16:
    263   1.7     uch 		fb->hf_class = HPCFB_CLASS_RGBCOLOR;
    264   1.7     uch 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    265   1.7     uch 		fb->hf_pack_width = 16;
    266   1.7     uch 		fb->hf_pixels_per_pack = 1;
    267   1.7     uch 		fb->hf_pixel_width = 16;
    268   1.7     uch 
    269   1.7     uch 		fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
    270   1.8     uch 		/* reserved for future use */
    271   1.8     uch 		fb->hf_u.hf_rgb.hf_flags = 0;
    272   1.7     uch 
    273   1.7     uch 		fb->hf_u.hf_rgb.hf_red_width = 5;
    274   1.7     uch 		fb->hf_u.hf_rgb.hf_red_shift = 11;
    275   1.7     uch 		fb->hf_u.hf_rgb.hf_green_width = 6;
    276   1.7     uch 		fb->hf_u.hf_rgb.hf_green_shift = 5;
    277   1.7     uch 		fb->hf_u.hf_rgb.hf_blue_width = 5;
    278   1.7     uch 		fb->hf_u.hf_rgb.hf_blue_shift = 0;
    279   1.7     uch 		fb->hf_u.hf_rgb.hf_alpha_width = 0;
    280   1.7     uch 		fb->hf_u.hf_rgb.hf_alpha_shift = 0;
    281   1.7     uch 		break;
    282   1.7     uch 
    283   1.7     uch 	case 8:
    284   1.7     uch 		fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
    285   1.7     uch 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    286   1.7     uch 		fb->hf_pack_width = 8;
    287   1.7     uch 		fb->hf_pixels_per_pack = 1;
    288   1.7     uch 		fb->hf_pixel_width = 8;
    289   1.7     uch 		fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
    290   1.8     uch 		/* reserved for future use */
    291   1.8     uch 		fb->hf_u.hf_indexed.hf_flags = 0;
    292   1.7     uch 		break;
    293   1.7     uch 	}
    294   1.1     uch }
    295   1.1     uch 
    296   1.5     uch int
    297  1.14     uch plumvideo_init(struct plumvideo_softc *sc, int *reverse)
    298   1.1     uch {
    299  1.14     uch 	struct {
    300  1.14     uch 		int reverse, normal;
    301  1.14     uch 	} ctype[] = {
    302  1.14     uch 		{ BIFB_D2_M2L_3,	BIFB_D2_M2L_0	},
    303  1.14     uch 		{ BIFB_D2_M2L_3x2,	BIFB_D2_M2L_0x2	},
    304  1.14     uch 		{ BIFB_D8_FF,		BIFB_D8_00	},
    305  1.14     uch 		{ BIFB_D16_FFFF,	BIFB_D16_0000,	},
    306  1.14     uch 		{ -1, -1 } /* terminator */
    307  1.14     uch 	}, *ctypep;
    308  1.14     uch 	struct video_chip *chip = &sc->sc_chip;
    309   1.1     uch 	bus_space_tag_t regt = sc->sc_regt;
    310   1.1     uch 	bus_space_handle_t regh = sc->sc_regh;
    311   1.1     uch 	plumreg_t reg;
    312   1.5     uch 	size_t vram_size;
    313  1.11     uch 	int bpp, width, height, vram_pitch;
    314  1.14     uch 	u_int16_t fbtype;
    315  1.11     uch 
    316  1.11     uch 	chip->vc_v = sc->sc_pc->pc_tc;
    317   1.8     uch #if notyet
    318   1.8     uch 	/* map BitBlt area */
    319   1.8     uch 	if (bus_space_map(sc->sc_bitbltt,
    320   1.8     uch 			  PLUM_VIDEO_BITBLT_IOBASE,
    321   1.8     uch 			  PLUM_VIDEO_BITBLT_IOSIZE, 0,
    322   1.8     uch 			  &sc->sc_bitblth)) {
    323   1.8     uch 		printf(": BitBlt map failed\n");
    324   1.8     uch 		return (1);
    325   1.8     uch 	}
    326   1.8     uch #endif
    327   1.1     uch 	reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG);
    328  1.14     uch 
    329  1.14     uch 	/* check reverse color */
    330  1.14     uch 	fbtype = bootinfo->fb_type;
    331  1.14     uch 	for (ctypep = ctype; ctypep->normal != -1 ;  ctypep++) {
    332  1.14     uch 		if (fbtype == ctypep->normal) {
    333  1.14     uch 			*reverse = 0;
    334  1.14     uch 			goto fbtype_found;
    335  1.14     uch 		} else if (fbtype == ctypep->reverse) {
    336  1.14     uch 			*reverse = 1;
    337  1.14     uch 			goto fbtype_found;
    338  1.14     uch 		}
    339  1.14     uch 	}
    340  1.14     uch 	printf(": unknown frame buffer type 0x%04x. attach failed.\n", fbtype);
    341  1.14     uch 	return (1);
    342  1.14     uch  fbtype_found:
    343  1.14     uch 
    344   1.8     uch 	switch (reg & PLUM_VIDEO_PLGMD_GMODE_MASK) {
    345   1.5     uch 	case PLUM_VIDEO_PLGMD_16BPP:
    346  1.14     uch #if NPLUMOHCI > 0 /* reserve V-RAM for USB OHCI */
    347   1.5     uch 		/* FALLTHROUGH */
    348  1.14     uch #else
    349   1.5     uch 		bpp = 16;
    350   1.5     uch 		break;
    351  1.14     uch #endif
    352   1.1     uch 	default:
    353  1.14     uch 		bootinfo->fb_type = *reverse ? BIFB_D8_FF : BIFB_D8_00;
    354   1.8     uch 		reg &= ~PLUM_VIDEO_PLGMD_GMODE_MASK;
    355   1.8     uch 		plum_conf_write(regt, regh, PLUM_VIDEO_PLGMD_REG, reg);
    356   1.5     uch 		reg |= PLUM_VIDEO_PLGMD_8BPP;
    357   1.1     uch 		plum_conf_write(regt, regh, PLUM_VIDEO_PLGMD_REG, reg);
    358   1.8     uch #if notyet
    359   1.8     uch 		/* change BitBlt color depth */
    360   1.8     uch 		plum_conf_write(sc->sc_bitbltt, sc->sc_bitblth, 0x8, 0);
    361   1.8     uch #endif
    362   1.1     uch 		/* FALLTHROUGH */
    363   1.1     uch 	case PLUM_VIDEO_PLGMD_8BPP:
    364   1.5     uch 		bpp = 8;
    365   1.5     uch 		break;
    366   1.5     uch 	}
    367  1.11     uch 	chip->vc_fbdepth = bpp;
    368  1.10     uch 
    369  1.10     uch 	/*
    370  1.10     uch 	 * Get display size from WindowsCE setted.
    371  1.10     uch 	 */
    372  1.11     uch 	chip->vc_fbwidth = width = bootinfo->fb_width =
    373  1.10     uch 		plum_conf_read(regt, regh, PLUM_VIDEO_PLHPX_REG) + 1;
    374  1.11     uch 	chip->vc_fbheight = height = bootinfo->fb_height =
    375  1.10     uch 		plum_conf_read(regt, regh, PLUM_VIDEO_PLVT_REG) -
    376  1.10     uch 		plum_conf_read(regt, regh, PLUM_VIDEO_PLVDS_REG);
    377   1.5     uch 
    378   1.5     uch 	/*
    379   1.5     uch 	 * set line byte length to bootinfo and LCD controller.
    380   1.5     uch 	 */
    381  1.14     uch 	vram_pitch = bootinfo->fb_line_bytes = (width * bpp) / NBBY;
    382   1.5     uch 	plum_conf_write(regt, regh, PLUM_VIDEO_PLPIT1_REG, vram_pitch);
    383   1.5     uch 	plum_conf_write(regt, regh, PLUM_VIDEO_PLPIT2_REG,
    384   1.5     uch 			vram_pitch & PLUM_VIDEO_PLPIT2_MASK);
    385   1.5     uch 	plum_conf_write(regt, regh, PLUM_VIDEO_PLOFS_REG, vram_pitch);
    386  1.14     uch 
    387   1.5     uch 	/*
    388   1.8     uch 	 * boot messages and map CLUT(if any).
    389   1.5     uch 	 */
    390   1.5     uch 	printf("display mode: ");
    391   1.8     uch 	switch (bpp) {
    392   1.8     uch 	default:
    393   1.5     uch 		printf("disabled ");
    394   1.5     uch 		break;
    395   1.8     uch 	case 8:
    396   1.5     uch 		printf("8bpp ");
    397   1.8     uch 		/* map CLUT area */
    398   1.8     uch 		if (bus_space_map(sc->sc_clutiot,
    399   1.8     uch 				  PLUM_VIDEO_CLUT_LCD_IOBASE,
    400   1.8     uch 				  PLUM_VIDEO_CLUT_LCD_IOSIZE, 0,
    401   1.8     uch 				  &sc->sc_clutioh)) {
    402   1.8     uch 			printf(": CLUT map failed\n");
    403   1.8     uch 			return (1);
    404   1.8     uch 		}
    405   1.8     uch 		/* install default CLUT */
    406   1.8     uch 		plumvideo_clut_default(sc);
    407   1.1     uch 		break;
    408   1.8     uch 	case 16:
    409   1.5     uch 		printf("16bpp ");
    410   1.1     uch 		break;
    411   1.1     uch 	}
    412   1.1     uch 
    413   1.5     uch 	/*
    414   1.5     uch 	 * calcurate frame buffer size.
    415   1.5     uch 	 */
    416   1.5     uch 	reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG);
    417  1.11     uch 	vram_size = (width * height * bpp) / NBBY;
    418   1.5     uch 	vram_size = mips_round_page(vram_size);
    419  1.11     uch 	chip->vc_fbsize = vram_size;
    420   1.5     uch 
    421   1.5     uch 	/*
    422   1.5     uch 	 * map V-RAM area.
    423   1.5     uch 	 */
    424   1.8     uch 	if (bus_space_map(sc->sc_fbiot, PLUM_VIDEO_VRAM_IOBASE,
    425   1.8     uch 			  vram_size, 0, &sc->sc_fbioh)) {
    426   1.5     uch 		printf(": V-RAM map failed\n");
    427   1.5     uch 		return (1);
    428   1.5     uch 	}
    429   1.5     uch 
    430   1.8     uch 	bootinfo->fb_addr = (unsigned char *)sc->sc_fbioh;
    431  1.11     uch 	chip->vc_fbvaddr = (vaddr_t)sc->sc_fbioh;
    432  1.11     uch 	chip->vc_fbpaddr = PLUM_VIDEO_VRAM_IOBASE_PHYSICAL;
    433   1.5     uch 
    434   1.5     uch 	return (0);
    435   1.7     uch }
    436   1.7     uch 
    437   1.7     uch int
    438  1.14     uch plumvideo_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
    439   1.7     uch {
    440   1.7     uch 	struct plumvideo_softc *sc = (struct plumvideo_softc *)v;
    441   1.7     uch 	struct hpcfb_fbconf *fbconf;
    442   1.7     uch 	struct hpcfb_dspconf *dspconf;
    443   1.8     uch 	struct wsdisplay_cmap *cmap;
    444   1.8     uch 	u_int8_t *r, *g, *b;
    445   1.8     uch 	u_int32_t *rgb;
    446   1.8     uch 	int idx, cnt, error;
    447   1.7     uch 
    448   1.7     uch 	switch (cmd) {
    449   1.7     uch 	case WSDISPLAYIO_GETCMAP:
    450   1.8     uch 		cmap = (struct wsdisplay_cmap*)data;
    451   1.8     uch 		cnt = cmap->count;
    452   1.8     uch 		idx = cmap->index;
    453   1.8     uch 
    454   1.8     uch 		if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
    455   1.8     uch 		    sc->sc_fbconf.hf_pack_width != 8 ||
    456   1.8     uch 		    !LEGAL_CLUT_INDEX(idx) ||
    457   1.8     uch 		    !LEGAL_CLUT_INDEX(idx + cnt -1)) {
    458   1.8     uch 			return (EINVAL);
    459   1.8     uch 		}
    460   1.8     uch 
    461   1.8     uch 		if (!uvm_useracc(cmap->red, cnt, B_WRITE) ||
    462   1.8     uch 		    !uvm_useracc(cmap->green, cnt, B_WRITE) ||
    463   1.8     uch 		    !uvm_useracc(cmap->blue, cnt, B_WRITE)) {
    464   1.8     uch 			return (EFAULT);
    465   1.8     uch 		}
    466   1.8     uch 
    467   1.8     uch 		error = cmap_work_alloc(&r, &g, &b, &rgb, cnt);
    468   1.8     uch 		if (error != 0) {
    469   1.8     uch 			cmap_work_free(r, g, b, rgb);
    470   1.8     uch 			return  (ENOMEM);
    471   1.8     uch 		}
    472   1.8     uch 		plumvideo_clut_get(sc, rgb, idx, cnt);
    473   1.8     uch 		rgb24_decompose(rgb, r, g, b, cnt);
    474   1.8     uch 
    475   1.8     uch 		copyout(r, cmap->red, cnt);
    476   1.8     uch 		copyout(g, cmap->green,cnt);
    477   1.8     uch 		copyout(b, cmap->blue, cnt);
    478   1.8     uch 
    479   1.8     uch 		cmap_work_free(r, g, b, rgb);
    480   1.8     uch 
    481   1.8     uch 		return (0);
    482   1.7     uch 
    483   1.7     uch 	case WSDISPLAYIO_PUTCMAP:
    484   1.8     uch 		cmap = (struct wsdisplay_cmap*)data;
    485   1.8     uch 		cnt = cmap->count;
    486   1.8     uch 		idx = cmap->index;
    487   1.8     uch 
    488   1.8     uch 		if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
    489   1.8     uch 		    sc->sc_fbconf.hf_pack_width != 8 ||
    490   1.8     uch 		    !LEGAL_CLUT_INDEX(idx) ||
    491   1.8     uch 		    !LEGAL_CLUT_INDEX(idx + cnt -1)) {
    492   1.8     uch 			return (EINVAL);
    493   1.8     uch 		}
    494   1.8     uch 
    495   1.8     uch 		if (!uvm_useracc(cmap->red, cnt, B_WRITE) ||
    496   1.8     uch 		    !uvm_useracc(cmap->green, cnt, B_WRITE) ||
    497   1.8     uch 		    !uvm_useracc(cmap->blue, cnt, B_WRITE)) {
    498   1.8     uch 			return (EFAULT);
    499   1.8     uch 		}
    500   1.8     uch 
    501   1.8     uch 		error = cmap_work_alloc(&r, &g, &b, &rgb, cnt);
    502   1.8     uch 		if (error != 0) {
    503   1.8     uch 			cmap_work_free(r, g, b, rgb);
    504   1.8     uch 			return  (ENOMEM);
    505   1.8     uch 		}
    506   1.8     uch 		rgb24_compose(rgb, r, g, b, cnt);
    507   1.8     uch 		plumvideo_clut_set(sc, rgb, idx, cnt);
    508   1.8     uch 
    509   1.8     uch 		cmap_work_free(r, g, b, rgb);
    510   1.8     uch 
    511   1.9     uch 		return (0);
    512   1.7     uch 
    513   1.7     uch 	case HPCFBIO_GCONF:
    514   1.7     uch 		fbconf = (struct hpcfb_fbconf *)data;
    515   1.7     uch 		if (fbconf->hf_conf_index != 0 &&
    516   1.7     uch 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
    517   1.7     uch 			return (EINVAL);
    518   1.7     uch 		}
    519   1.7     uch 		*fbconf = sc->sc_fbconf;	/* structure assignment */
    520   1.7     uch 		return (0);
    521   1.7     uch 
    522   1.7     uch 	case HPCFBIO_SCONF:
    523   1.7     uch 		fbconf = (struct hpcfb_fbconf *)data;
    524   1.7     uch 		if (fbconf->hf_conf_index != 0 &&
    525   1.7     uch 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
    526   1.7     uch 			return (EINVAL);
    527   1.7     uch 		}
    528   1.7     uch 		/*
    529   1.7     uch 		 * nothing to do because we have only one configration
    530   1.7     uch 		 */
    531   1.7     uch 		return (0);
    532   1.7     uch 
    533   1.7     uch 	case HPCFBIO_GDSPCONF:
    534   1.7     uch 		dspconf = (struct hpcfb_dspconf *)data;
    535   1.7     uch 		if ((dspconf->hd_unit_index != 0 &&
    536   1.7     uch 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
    537   1.7     uch 		    (dspconf->hd_conf_index != 0 &&
    538   1.7     uch 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
    539   1.7     uch 			return (EINVAL);
    540   1.7     uch 		}
    541   1.7     uch 		*dspconf = sc->sc_dspconf;	/* structure assignment */
    542   1.7     uch 		return (0);
    543   1.7     uch 
    544   1.7     uch 	case HPCFBIO_SDSPCONF:
    545   1.7     uch 		dspconf = (struct hpcfb_dspconf *)data;
    546   1.7     uch 		if ((dspconf->hd_unit_index != 0 &&
    547   1.7     uch 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
    548   1.7     uch 		    (dspconf->hd_conf_index != 0 &&
    549   1.7     uch 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
    550   1.7     uch 			return (EINVAL);
    551   1.7     uch 		}
    552   1.7     uch 		/*
    553   1.7     uch 		 * nothing to do
    554   1.7     uch 		 * because we have only one unit and one configration
    555   1.7     uch 		 */
    556   1.7     uch 		return (0);
    557   1.7     uch 
    558   1.7     uch 	case HPCFBIO_GOP:
    559   1.7     uch 	case HPCFBIO_SOP:
    560   1.7     uch 		/* XXX not implemented yet */
    561   1.7     uch 		return (EINVAL);
    562   1.7     uch 	}
    563   1.7     uch 
    564   1.7     uch 	return (ENOTTY);
    565   1.7     uch }
    566   1.7     uch 
    567  1.12  simonb paddr_t
    568  1.14     uch plumvideo_mmap(void *ctx, off_t offset, int prot)
    569   1.7     uch {
    570   1.7     uch 	struct plumvideo_softc *sc = (struct plumvideo_softc *)ctx;
    571   1.7     uch 
    572   1.7     uch 	if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane +
    573   1.7     uch 			   sc->sc_fbconf.hf_offset) <  offset) {
    574   1.7     uch 		return (-1);
    575   1.7     uch 	}
    576   1.7     uch 
    577   1.7     uch 	return (mips_btop(PLUM_VIDEO_VRAM_IOBASE_PHYSICAL + offset));
    578   1.8     uch }
    579   1.8     uch 
    580   1.8     uch void
    581  1.14     uch plumvideo_clut_get(struct plumvideo_softc *sc, u_int32_t *rgb, int beg,
    582  1.14     uch 		   int cnt)
    583   1.8     uch {
    584  1.14     uch 	static void __plumvideo_clut_get(bus_space_tag_t,
    585  1.14     uch 					      bus_space_handle_t);
    586   1.8     uch 	static void __plumvideo_clut_get(iot, ioh)
    587   1.8     uch 		bus_space_tag_t iot;
    588  1.10     uch 		bus_space_handle_t ioh;
    589   1.8     uch 	{
    590   1.8     uch 		int i;
    591   1.8     uch 
    592   1.8     uch 		for (i = 0, beg *= 4; i < cnt; i++, beg += 4) {
    593   1.8     uch 			*rgb++ = bus_space_read_4(iot, ioh, beg) &
    594   1.8     uch 				0x00ffffff;
    595   1.8     uch 		}
    596   1.8     uch 	}
    597   1.8     uch 
    598   1.8     uch 	KASSERT(rgb);
    599   1.8     uch 	KASSERT(LEGAL_CLUT_INDEX(beg));
    600   1.8     uch 	KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1));
    601   1.8     uch 	__plumvideo_clut_access(sc, __plumvideo_clut_get);
    602   1.8     uch }
    603   1.8     uch 
    604   1.8     uch void
    605  1.14     uch plumvideo_clut_set(struct plumvideo_softc *sc, u_int32_t *rgb, int beg,
    606  1.14     uch 		   int cnt)
    607   1.8     uch {
    608  1.14     uch 	static void __plumvideo_clut_set(bus_space_tag_t,
    609  1.14     uch 					      bus_space_handle_t);
    610   1.8     uch 	static void __plumvideo_clut_set(iot, ioh)
    611   1.8     uch 		bus_space_tag_t iot;
    612  1.10     uch 		bus_space_handle_t ioh;
    613   1.8     uch 	{
    614   1.8     uch 		int i;
    615   1.8     uch 
    616   1.8     uch 		for (i = 0, beg *= 4; i < cnt; i++, beg +=4) {
    617   1.8     uch 			bus_space_write_4(iot, ioh, beg,
    618   1.8     uch 					  *rgb++ & 0x00ffffff);
    619   1.8     uch 		}
    620   1.8     uch 	}
    621   1.8     uch 
    622   1.8     uch 	KASSERT(rgb);
    623   1.8     uch 	KASSERT(LEGAL_CLUT_INDEX(beg));
    624   1.8     uch 	KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1));
    625   1.8     uch 	__plumvideo_clut_access(sc, __plumvideo_clut_set);
    626   1.8     uch }
    627   1.8     uch 
    628   1.8     uch void
    629  1.14     uch plumvideo_clut_default(struct plumvideo_softc *sc)
    630   1.8     uch {
    631  1.14     uch 	static void __plumvideo_clut_default(bus_space_tag_t,
    632  1.14     uch 						  bus_space_handle_t);
    633   1.8     uch 	static void __plumvideo_clut_default(iot, ioh)
    634   1.8     uch 		bus_space_tag_t iot;
    635  1.10     uch 		bus_space_handle_t ioh;
    636   1.8     uch 	{
    637   1.8     uch 		const u_int8_t compo6[6] = { 0,  51, 102, 153, 204, 255 };
    638   1.8     uch 		const u_int32_t ansi_color[16] = {
    639   1.8     uch 			0x000000, 0xff0000, 0x00ff00, 0xffff00,
    640   1.8     uch 			0x0000ff, 0xff00ff, 0x00ffff, 0xffffff,
    641   1.8     uch 			0x000000, 0x800000, 0x008000, 0x808000,
    642   1.8     uch 			0x000080, 0x800080, 0x008080, 0x808080,
    643   1.8     uch 		};
    644   1.8     uch 		int i, r, g, b;
    645   1.8     uch 
    646   1.8     uch 		/* ANSI escape sequence */
    647   1.8     uch 		for (i = 0; i < 16; i++) {
    648   1.8     uch 			bus_space_write_4(iot, ioh, i << 2, ansi_color[i]);
    649   1.8     uch 		}
    650   1.8     uch 		/* 16 - 31, gray scale */
    651   1.8     uch 		for ( ; i < 32; i++) {
    652   1.8     uch 			int j = (i - 16) * 17;
    653   1.8     uch 			bus_space_write_4(iot, ioh, i << 2, RGB24(j, j, j));
    654   1.8     uch 		}
    655   1.8     uch 		/* 32 - 247, RGB color */
    656   1.8     uch 		for (r = 0; r < 6; r++) {
    657   1.8     uch 			for (g = 0; g < 6; g++) {
    658   1.8     uch 				for (b = 0; b < 6; b++) {
    659   1.8     uch 					bus_space_write_4(iot, ioh, i << 2,
    660   1.8     uch 							  RGB24(compo6[r],
    661   1.8     uch 								compo6[g],
    662   1.8     uch 								compo6[b]));
    663   1.8     uch 					i++;
    664   1.8     uch 				}
    665   1.8     uch 			}
    666   1.8     uch 		}
    667   1.8     uch 		/* 248 - 245, just white */
    668   1.8     uch 		for ( ; i < 256; i++) {
    669   1.8     uch 			bus_space_write_4(iot, ioh, i << 2, 0xffffff);
    670   1.8     uch 		}
    671   1.8     uch 	}
    672   1.8     uch 
    673   1.8     uch 	__plumvideo_clut_access(sc, __plumvideo_clut_default);
    674   1.8     uch }
    675   1.8     uch 
    676   1.8     uch void
    677  1.14     uch __plumvideo_clut_access(struct plumvideo_softc *sc, void (*palette_func)
    678  1.14     uch 			(bus_space_tag_t, bus_space_handle_t))
    679   1.8     uch {
    680   1.8     uch 	bus_space_tag_t regt = sc->sc_regt;
    681   1.8     uch 	bus_space_handle_t regh = sc->sc_regh;
    682   1.8     uch 	plumreg_t val, gmode;
    683   1.8     uch 
    684   1.8     uch 	/* display off */
    685   1.8     uch 	val = bus_space_read_4(regt, regh, PLUM_VIDEO_PLGMD_REG);
    686   1.8     uch 	gmode = val & PLUM_VIDEO_PLGMD_GMODE_MASK;
    687   1.8     uch 	val &= ~PLUM_VIDEO_PLGMD_GMODE_MASK;
    688   1.8     uch 	bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
    689   1.8     uch 
    690   1.8     uch 	/* palette access disable */
    691   1.8     uch 	val &= ~PLUM_VIDEO_PLGMD_PALETTE_ENABLE;
    692   1.8     uch 	bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
    693   1.8     uch 
    694   1.8     uch 	/* change palette mode to CPU */
    695   1.8     uch 	val &= ~PLUM_VIDEO_PLGMD_MODE_DISPLAY;
    696   1.8     uch 	bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
    697   1.8     uch 
    698   1.8     uch 	/* palette access */
    699   1.8     uch 	(*palette_func) (sc->sc_clutiot, sc->sc_clutioh);
    700   1.8     uch 
    701   1.8     uch 	/* change palette mode to Display */
    702   1.8     uch 	val |= PLUM_VIDEO_PLGMD_MODE_DISPLAY;
    703   1.8     uch 	bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
    704   1.9     uch 
    705   1.8     uch 	/* palette access enable */
    706   1.8     uch 	val |= PLUM_VIDEO_PLGMD_PALETTE_ENABLE;
    707   1.8     uch 	bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
    708   1.8     uch 
    709   1.8     uch 	/* display on */
    710   1.8     uch 	val |= gmode;
    711   1.8     uch 	bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
    712   1.8     uch }
    713   1.8     uch 
    714   1.8     uch /* !!! */
    715   1.8     uch static void
    716   1.8     uch _flush_cache()
    717   1.8     uch {
    718   1.8     uch 	MachFlushCache();
    719   1.1     uch }
    720   1.1     uch 
    721  1.14     uch int
    722  1.14     uch plumvideo_power(void *ctx, int type, long id, void *msg)
    723  1.14     uch {
    724  1.14     uch 	struct plumvideo_softc *sc = ctx;
    725  1.14     uch 	plum_chipset_tag_t pc = sc->sc_pc;
    726  1.14     uch 	bus_space_tag_t regt = sc->sc_regt;
    727  1.14     uch 	bus_space_handle_t regh = sc->sc_regh;
    728  1.14     uch 	int why = (int)msg;
    729  1.14     uch 
    730  1.14     uch 	switch (why) {
    731  1.14     uch 	case PWR_RESUME:
    732  1.14     uch 		DPRINTF(("%s: ON\n", sc->sc_dev.dv_xname));
    733  1.14     uch 		/* power on */
    734  1.14     uch 		/* LCD power on and display on */
    735  1.14     uch 		plum_power_establish(pc, PLUM_PWR_LCD);
    736  1.14     uch 		/* back-light on */
    737  1.14     uch 		plum_power_establish(pc, PLUM_PWR_BKL);
    738  1.14     uch 		plum_conf_write(regt, regh, PLUM_VIDEO_PLLUM_REG,
    739  1.14     uch 				PLUM_VIDEO_PLLUM_MAX);
    740  1.14     uch 		break;
    741  1.14     uch 	case PWR_SUSPEND:
    742  1.14     uch 		/* FALLTHROUGH */
    743  1.14     uch 	case PWR_STANDBY:
    744  1.14     uch 		DPRINTF(("%s: OFF\n", sc->sc_dev.dv_xname));
    745  1.14     uch 		/* back-light off */
    746  1.14     uch 		plum_conf_write(regt, regh, PLUM_VIDEO_PLLUM_REG,
    747  1.14     uch 				PLUM_VIDEO_PLLUM_MIN);
    748  1.14     uch 		plum_power_disestablish(pc, PLUM_PWR_BKL);
    749  1.14     uch 		/* power down */
    750  1.14     uch 		plum_power_disestablish(pc, PLUM_PWR_LCD);
    751  1.14     uch 		break;
    752  1.14     uch 	}
    753  1.14     uch 
    754  1.14     uch 	return 0;
    755  1.14     uch }
    756  1.14     uch 
    757   1.3     uch #ifdef PLUMVIDEODEBUG
    758   1.1     uch void
    759  1.14     uch plumvideo_dump(struct plumvideo_softc *sc)
    760   1.1     uch {
    761   1.1     uch 	bus_space_tag_t regt = sc->sc_regt;
    762   1.1     uch 	bus_space_handle_t regh = sc->sc_regh;
    763   1.1     uch 
    764   1.1     uch 	plumreg_t reg;
    765   1.3     uch 	int i;
    766   1.1     uch 
    767   1.5     uch 	for (i = 0; i < 0x160; i += 4) {
    768   1.1     uch 		reg = plum_conf_read(regt, regh, i);
    769   1.3     uch 		printf("0x%03x %08x", i, reg);
    770   1.1     uch 		bitdisp(reg);
    771   1.1     uch 	}
    772   1.1     uch }
    773   1.3     uch #endif /* PLUMVIDEODEBUG */
    774