xref: /openbsd-src/sys/arch/powerpc64/dev/astfb.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /*	$OpenBSD: astfb.c,v 1.1 2020/10/01 17:28:14 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2020 Mark Kettenis.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/device.h>
21 #include <sys/systm.h>
22 
23 #include <machine/bus.h>
24 
25 #include <dev/ofw/openfirm.h>
26 
27 #include <dev/pci/pcireg.h>
28 #include <dev/pci/pcivar.h>
29 #include <dev/pci/pcidevs.h>
30 
31 #include <dev/wscons/wsconsio.h>
32 #include <dev/wscons/wsdisplayvar.h>
33 
34 #include <dev/rasops/rasops.h>
35 
36 #define ASTFB_PCI_FB	0x10
37 
38 struct astfb_softc {
39 	struct device		sc_dev;
40 	bus_space_tag_t		sc_iot;
41 	bus_space_handle_t	sc_ioh;
42 
43 	bus_addr_t		sc_fbaddr;
44 	bus_size_t		sc_fbsize;
45 
46 	struct rasops_info	sc_ri;
47 	struct wsscreen_descr	sc_wsd;
48 	struct wsscreen_list	sc_wsl;
49 	struct wsscreen_descr	*sc_scrlist[1];
50 };
51 
52 int	astfb_wsioctl(void *, u_long, caddr_t, int, struct proc *);
53 paddr_t	astfb_wsmmap(void *, off_t, int);
54 int	astfb_alloc_screen(void *, const struct wsscreen_descr *,
55 	    void **, int *, int *, uint32_t *);
56 
57 struct wsdisplay_accessops astfb_accessops = {
58 	.ioctl = astfb_wsioctl,
59 	.mmap = astfb_wsmmap,
60 	.alloc_screen = astfb_alloc_screen,
61 	.free_screen = rasops_free_screen,
62 	.show_screen = rasops_show_screen,
63 	.getchar = rasops_getchar,
64 	.load_font = rasops_load_font,
65 	.list_font = rasops_list_font,
66 	.scrollback = rasops_scrollback
67 };
68 
69 int	astfb_match(struct device *, void *, void *);
70 void	astfb_attach(struct device *, struct device *, void *);
71 
72 struct cfattach astfb_ca = {
73 	sizeof(struct astfb_softc), astfb_match, astfb_attach
74 };
75 
76 struct cfdriver astfb_cd = {
77 	NULL, "astfb", DV_DULL
78 };
79 
80 int
81 astfb_match(struct device *parent, void *cf, void *aux)
82 {
83 	struct pci_attach_args *pa = aux;
84 
85 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ASPEED &&
86 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ASPEED_AST2000 &&
87 	    PCITAG_NODE(pa->pa_tag) != 0)
88 		return 1;
89 
90 	return 0;
91 }
92 
93 void
94 astfb_attach(struct device *parent, struct device *self, void *aux)
95 {
96 	struct astfb_softc *sc = (struct astfb_softc *)self;
97 	struct pci_attach_args *pa = aux;
98 	struct rasops_info *ri = &sc->sc_ri;
99 	struct wsemuldisplaydev_attach_args waa;
100 	int node = PCITAG_NODE(pa->pa_tag);
101 	uint32_t addr[5];
102 
103 	if (OF_getpropintarray(node, "assigned-addresses", addr,
104 	    sizeof(addr)) < sizeof(addr)) {
105 		printf(": no framebuffer\n");
106 		return;
107 	}
108 
109 	sc->sc_fbaddr = (bus_addr_t)addr[1] << 32 | addr[2];
110 	sc->sc_fbsize = (bus_size_t)addr[3] << 32 | addr[4];
111 
112 	sc->sc_iot = pa->pa_memt;
113 	if (bus_space_map(sc->sc_iot, sc->sc_fbaddr, sc->sc_fbsize,
114 	    BUS_SPACE_MAP_LINEAR, &sc->sc_ioh)) {
115 		printf(": can't map framebuffer\n");
116 		return;
117 	}
118 
119 	printf("\n");
120 
121 	ri->ri_bits = bus_space_vaddr(sc->sc_iot, sc->sc_ioh);
122 	ri->ri_hw = sc;
123 
124 	ri->ri_width = OF_getpropint(node, "width", 0);
125 	ri->ri_height = OF_getpropint(node, "height", 0);
126 	ri->ri_depth = OF_getpropint(node, "depth", 0);
127 	ri->ri_stride = ri->ri_width * ((ri->ri_depth + 7) / 8);
128 	ri->ri_flg = RI_CENTER | RI_CLEAR | RI_FULLCLEAR | RI_WRONLY;
129 
130 	switch (ri->ri_depth) {
131 	case 32:
132 		ri->ri_rnum = 8;
133 		ri->ri_rpos = 8;
134 		ri->ri_gnum = 8;
135 		ri->ri_gpos = 16;
136 		ri->ri_bnum = 8;
137 		ri->ri_bpos = 24;
138 		break;
139 	case 16:
140 		ri->ri_rnum = 5;
141 		ri->ri_rpos = 0;
142 		ri->ri_gnum = 6;
143 		ri->ri_gpos = 6;
144 		ri->ri_bnum = 5;
145 		ri->ri_bpos = 11;
146 		break;
147 	}
148 
149 	printf("%s: %dx%d, %dbpp\n", sc->sc_dev.dv_xname,
150 	    ri->ri_width, ri->ri_height, ri->ri_depth);
151 
152 	ri->ri_flg |= RI_VCONS;
153 	rasops_init(ri, 160, 160);
154 
155 	strlcpy(sc->sc_wsd.name, "std", sizeof(sc->sc_wsd.name));
156 	sc->sc_wsd.capabilities = ri->ri_caps;
157 	sc->sc_wsd.nrows = ri->ri_rows;
158 	sc->sc_wsd.ncols = ri->ri_cols;
159 	sc->sc_wsd.textops = &ri->ri_ops;
160 	sc->sc_wsd.fontwidth = ri->ri_font->fontwidth;
161 	sc->sc_wsd.fontheight = ri->ri_font->fontheight;
162 
163 	sc->sc_scrlist[0] = &sc->sc_wsd;
164 	sc->sc_wsl.nscreens = 1;
165 	sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;
166 
167 	memset(&waa, 0, sizeof(waa));
168 	waa.scrdata = &sc->sc_wsl;
169 	waa.accessops = &astfb_accessops;
170 	waa.accesscookie = ri;
171 	waa.console = 0;
172 
173 	config_found_sm(self, &waa, wsemuldisplaydevprint,
174 	    wsemuldisplaydevsubmatch);
175 }
176 
177 int
178 astfb_wsioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
179 {
180 	struct rasops_info *ri = v;
181 	struct wsdisplay_fbinfo *wdf;
182 
183 	switch (cmd) {
184 	case WSDISPLAYIO_GTYPE:
185 		*(u_int *)data = WSDISPLAY_TYPE_ASTFB;
186 		break;
187 	case WSDISPLAYIO_GINFO:
188 		wdf = (void *)data;
189 		wdf->width = ri->ri_width;
190 		wdf->height = ri->ri_height;
191 		wdf->depth = ri->ri_depth;
192 		wdf->cmsize = 0;	/* color map is unavailable */
193 		break;
194 	case WSDISPLAYIO_LINEBYTES:
195 		*(u_int *)data = ri->ri_stride;
196 		break;
197 	case WSDISPLAYIO_SMODE:
198 		break;
199 	case WSDISPLAYIO_GETSUPPORTEDDEPTH:
200 		switch (ri->ri_depth) {
201 		case 32:
202 			*(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
203 			break;
204 		case 16:
205 			*(u_int *)data = WSDISPLAYIO_DEPTH_16;
206 			break;
207 		default:
208 			return -1;
209 		}
210 		break;
211 	default:
212 		return -1;
213         }
214 
215 	return 0;
216 }
217 
218 paddr_t
219 astfb_wsmmap(void *v, off_t off, int prot)
220 {
221 	struct rasops_info *ri = v;
222 	struct astfb_softc *sc = ri->ri_hw;
223 
224 	if (off < 0 || off >= sc->sc_fbaddr)
225 		return -1;
226 
227 	return (bus_space_mmap(sc->sc_iot, sc->sc_fbaddr,
228 	    off, prot, BUS_SPACE_MAP_LINEAR));
229 }
230 
231 int
232 astfb_alloc_screen(void *v, const struct wsscreen_descr *type,
233     void **cookiep, int *curxp, int *curyp, uint32_t *attrp)
234 {
235 	return rasops_alloc_screen(v, cookiep, curxp, curyp, attrp);
236 }
237