Home | History | Annotate | Line # | Download | only in dev
      1 /* $NetBSD: genfb_grfbus.c,v 1.3 2024/12/09 10:32:53 nat Exp $ */
      2 
      3 /* NetBSD: simplefb.c,v 1.7 2019/01/30 00:55:04 jmcneill Exp */
      4 /*-
      5  * Copyright (c) 2017 Jared McNeill <jmcneill (at) invisible.ca>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 /* NetBSD: macfb.c,v 1.20 2012/10/27 17:17:59 chs Exp */
     31 /*
     32  * Copyright (c) 1998 Matt DeBergalis
     33  * All rights reserved.
     34  *
     35  * Redistribution and use in source and binary forms, with or without
     36  * modification, are permitted provided that the following conditions
     37  * are met:
     38  * 1. Redistributions of source code must retain the above copyright
     39  *    notice, this list of conditions and the following disclaimer.
     40  * 2. Redistributions in binary form must reproduce the above copyright
     41  *    notice, this list of conditions and the following disclaimer in the
     42  *    documentation and/or other materials provided with the distribution.
     43  * 3. All advertising materials mentioning features or use of this software
     44  *    must display the following acknowledgement:
     45  *      This product includes software developed by Matt DeBergalis
     46  * 4. The name of the author may not be used to endorse or promote products
     47  *    derived from this software without specific prior written permission
     48  *
     49  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     50  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     51  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     52  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     53  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     54  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     55  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     56  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     57  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     58  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     59  */
     60 
     61 #include "opt_wsdisplay_compat.h"
     62 
     63 #include <sys/cdefs.h>
     64 __KERNEL_RCSID(0, "$NetBSD: genfb_grfbus.c,v 1.3 2024/12/09 10:32:53 nat Exp $");
     65 
     66 #include <sys/param.h>
     67 #include <sys/bus.h>
     68 #include <sys/device.h>
     69 #include <sys/systm.h>
     70 
     71 #include <machine/cpu.h>
     72 #include <machine/bus.h>
     73 
     74 #include <machine/video.h>
     75 #include <machine/grfioctl.h>
     76 #include <mac68k/nubus/nubus.h>
     77 #include <mac68k/dev/grfvar.h>
     78 
     79 #include <dev/wsfb/genfbvar.h>
     80 
     81 struct genfb_grfbus_softc {
     82 	struct genfb_softc sc_gen;
     83 
     84 	uint32_t sc_width;
     85 	uint32_t sc_height;
     86 	uint8_t  sc_depth;
     87 	uint16_t sc_stride;
     88 
     89 	paddr_t sc_paddr;
     90 	vaddr_t sc_vaddr;
     91 
     92 	void (*sc_set_mapreg)(void *, int, int, int, int);
     93 	struct grfbus_softc *sc_parent;
     94 };
     95 
     96 static int genfb_grfbus_ioctl(void *, void *, u_long, void *, int, lwp_t *);
     97 static paddr_t genfb_grfbus_mmap(void *, void *, off_t, int);
     98 
     99 static struct genfb_ops gfb_ops = {
    100 	.genfb_ioctl = genfb_grfbus_ioctl,
    101 	.genfb_mmap = genfb_grfbus_mmap,
    102 };
    103 
    104 static struct genfb_colormap_callback gfb_cmcb;
    105 
    106 static int __unused
    107 genfb_grfbus_is_console(paddr_t addr)
    108 {
    109 
    110 	if (addr != mac68k_video.mv_phys &&
    111 	    (addr >= 0xf9000000 && addr <= 0xfeffffff)) {
    112 		/*
    113 		 * This is in the NuBus standard slot space range, so we
    114 		 * may well have to look at 0xFssxxxxx, too.  Mask off the
    115 		 * slot number and duplicate it in bits 20-23, per IM:V
    116 		 * pp 459, 463, and IM:VI ch 30 p 17.
    117 		 * Note:  this is an ugly hack and I wish I knew what
    118 		 * to do about it.  -- sr
    119 		 */
    120 		addr = (paddr_t)(((u_long)addr & 0xff0fffff) |
    121 		    (((u_long)addr & 0x0f000000) >> 4));
    122 	}
    123 	return ((mac68k_machine.serial_console & 0x03) == 0
    124 	    && (addr == mac68k_video.mv_phys));
    125 }
    126 
    127 static int
    128 genfb_grfbus_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l)
    129 {
    130 	struct genfb_grfbus_softc * const sc = v;
    131 #if 0
    132 	struct wsdisplayio_bus_id *busid;
    133 #endif
    134 	struct wsdisplayio_fbinfo *fbi;
    135 	struct rasops_info *ri;
    136 	int error;
    137 	u_int video;
    138 
    139 	switch (cmd) {
    140 	case WSDISPLAYIO_GTYPE:
    141 		*(u_int *)data = WSDISPLAY_TYPE_GENFB;
    142 		return 0;
    143 #if 0
    144 	case WSDISPLAYIO_GET_BUSID:
    145 		busid = data;
    146 		busid->bus_type = WSDISPLAYIO_BUS_GRFBUS;
    147 		return 0;
    148 #endif
    149 	case WSDISPLAYIO_GET_FBINFO:
    150 		fbi = data;
    151 		ri = &sc->sc_gen.vd.active->scr_ri;
    152 		error = wsdisplayio_get_fbinfo(ri, fbi);
    153 		if (error == 0) {
    154 	                /*
    155 	                 * XXX
    156 	                 * if the fb isn't page aligned, tell wsfb to skip the
    157 			 * unaligned part
    158 			 */
    159 			fbi->fbi_fboffset = m68k_page_offset(sc->sc_paddr);
    160 		}
    161 		return error;
    162 	case WSDISPLAYIO_SVIDEO:
    163 		video = *(u_int *)data;
    164 		if (video == WSDISPLAYIO_VIDEO_OFF)
    165 			pmf_event_inject(NULL, PMFE_DISPLAY_OFF);
    166 		else if (video == WSDISPLAYIO_VIDEO_ON)
    167 			pmf_event_inject(NULL, PMFE_DISPLAY_ON);
    168 		else
    169 			return EINVAL;
    170 		return 0;
    171 	default:
    172 		return EPASSTHROUGH;
    173 	}
    174 }
    175 
    176 static paddr_t
    177 genfb_grfbus_mmap(void *v, void *vs, off_t off, int prot)
    178 {
    179 	struct genfb_grfbus_softc * const sc = v;
    180 
    181 	if (off < 0 || off >= m68k_page_offset(sc->sc_paddr) +
    182 	    sc->sc_gen.sc_fbsize)
    183 		return -1;
    184 
    185 	return m68k_btop(m68k_trunc_page(sc->sc_paddr) + off);
    186 }
    187 
    188 static int
    189 genfb_grfbus_attach_genfb(struct genfb_grfbus_softc *sc)
    190 {
    191 	device_t dev = sc->sc_gen.sc_dev;
    192 	prop_dictionary_t dict = device_properties(dev);
    193 	bool is_console;
    194 
    195 	prop_dictionary_set_uint32(dict, "width", sc->sc_width);
    196 	prop_dictionary_set_uint32(dict, "height", sc->sc_height);
    197 	prop_dictionary_set_uint8(dict, "depth", sc->sc_depth);
    198 	prop_dictionary_set_uint16(dict, "linebytes", sc->sc_stride);
    199 
    200 	prop_dictionary_set_uint32(dict, "address", sc->sc_paddr);
    201 	prop_dictionary_set_uint64(dict, "virtual_address", sc->sc_vaddr);
    202 
    203 	if (sc->sc_set_mapreg != NULL) {
    204 		gfb_cmcb.gcc_cookie = sc->sc_parent;
    205 		gfb_cmcb.gcc_set_mapreg = sc->sc_set_mapreg;
    206 		prop_dictionary_set_uint64(dict, "cmap_callback",
    207 		    (uint64_t)(uintptr_t)&gfb_cmcb);
    208 	}
    209 
    210 	genfb_init(&sc->sc_gen);
    211 
    212 	if (sc->sc_gen.sc_width == 0 || sc->sc_gen.sc_fbsize == 0) {
    213 		aprint_normal(": disabled\n");
    214 		return ENXIO;
    215 	}
    216 
    217 	aprint_naive("\n");
    218 	aprint_normal(": colormap callback %sprovided\n",
    219 	    sc->sc_set_mapreg != NULL ? "" : "not ");
    220 
    221 	is_console = genfb_grfbus_is_console(sc->sc_paddr);
    222 	if (is_console)
    223 		aprint_normal_dev(sc->sc_gen.sc_dev,
    224 		    "switching to framebuffer console\n");
    225 	prop_dictionary_set_bool(dict, "is_console", is_console);
    226 
    227 	genfb_attach(&sc->sc_gen, &gfb_ops);
    228 
    229 	return 0;
    230 }
    231 
    232 static int
    233 genfb_grfbus_match(device_t parent, cfdata_t cf, void *aux)
    234 {
    235 
    236 	return 1;
    237 }
    238 
    239 static void
    240 genfb_grfbus_attach(device_t parent, device_t self, void *aux)
    241 {
    242 	struct genfb_grfbus_softc * const sc = device_private(self);
    243 	struct grfbus_attach_args *ga = aux;
    244 	struct grfmode *gm = ga->ga_grfmode;
    245 
    246 	sc->sc_gen.sc_dev = self;
    247 
    248 	sc->sc_width = gm->width;
    249 	sc->sc_height = gm->height;
    250 
    251 	/*
    252 	 * XXX: tested on Quadra 840AV
    253 	 */
    254 	sc->sc_depth = gm->psize == 16 ? 15 : gm->psize;
    255 
    256 	sc->sc_stride = gm->rowbytes;
    257 	sc->sc_paddr = ga->ga_phys + gm->fboff;
    258 	sc->sc_vaddr = (vaddr_t)gm->fbbase + gm->fboff;
    259 	sc->sc_set_mapreg = ga->ga_set_mapreg;
    260 	sc->sc_parent = ga->ga_parent;
    261 
    262 	genfb_grfbus_attach_genfb(sc);
    263 }
    264 
    265 CFATTACH_DECL_NEW(genfb_grfbus, sizeof(struct genfb_grfbus_softc),
    266 	genfb_grfbus_match, genfb_grfbus_attach, NULL, NULL);
    267