unichromefb.c revision 1.1 1 1.1 jmcneill /* $NetBSD: unichromefb.c,v 1.1 2006/08/02 01:44:09 jmcneill Exp $ */
2 1.1 jmcneill
3 1.1 jmcneill /*-
4 1.1 jmcneill * Copyright (c) 2006 Jared D. McNeill <jmcneill (at) invisible.ca>
5 1.1 jmcneill * All rights reserved.
6 1.1 jmcneill *
7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without
8 1.1 jmcneill * modification, are permitted provided that the following conditions
9 1.1 jmcneill * are met:
10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright
11 1.1 jmcneill * notice, this list of conditions and the following disclaimer.
12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the
14 1.1 jmcneill * documentation and/or other materials provided with the distribution.
15 1.1 jmcneill * 3. All advertising materials mentioning features or use of this software
16 1.1 jmcneill * must display the following acknowledgement:
17 1.1 jmcneill * This product includes software developed by Jared D. McNeill.
18 1.1 jmcneill * 4. Neither the name of The NetBSD Foundation nor the names of its
19 1.1 jmcneill * contributors may be used to endorse or promote products derived
20 1.1 jmcneill * from this software without specific prior written permission.
21 1.1 jmcneill *
22 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 1.1 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 1.1 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 1.1 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 1.1 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 1.1 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 1.1 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 1.1 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 1.1 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 1.1 jmcneill * POSSIBILITY OF SUCH DAMAGE.
33 1.1 jmcneill */
34 1.1 jmcneill
35 1.1 jmcneill /*
36 1.1 jmcneill * Copyright 1998-2006 VIA Technologies, Inc. All Rights Reserved.
37 1.1 jmcneill * Copyright 2001-2006 S3 Graphics, Inc. All Rights Reserved.
38 1.1 jmcneill *
39 1.1 jmcneill * Permission is hereby granted, free of charge, to any person obtaining a
40 1.1 jmcneill * copy of this software and associated documentation files (the "Software"),
41 1.1 jmcneill * to deal in the Software without restriction, including without limitation
42 1.1 jmcneill * the rights to use, copy, modify, merge, publish, distribute, sub license,
43 1.1 jmcneill * and/or sell copies of the Software, and to permit persons to whom the
44 1.1 jmcneill * Software is furnished to do so, subject to the following conditions:
45 1.1 jmcneill *
46 1.1 jmcneill * The above copyright notice and this permission notice (including the
47 1.1 jmcneill * next paragraph) shall be included in all copies or substantial portions
48 1.1 jmcneill * of the Software.
49 1.1 jmcneill *
50 1.1 jmcneill * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51 1.1 jmcneill * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52 1.1 jmcneill * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
53 1.1 jmcneill * THE AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
54 1.1 jmcneill * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
55 1.1 jmcneill * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
56 1.1 jmcneill * DEALINGS IN THE SOFTWARE.
57 1.1 jmcneill */
58 1.1 jmcneill
59 1.1 jmcneill #include <sys/cdefs.h>
60 1.1 jmcneill __KERNEL_RCSID(0, "$NetBSD: unichromefb.c,v 1.1 2006/08/02 01:44:09 jmcneill Exp $");
61 1.1 jmcneill
62 1.1 jmcneill #include <sys/param.h>
63 1.1 jmcneill #include <sys/systm.h>
64 1.1 jmcneill #include <sys/device.h>
65 1.1 jmcneill #include <sys/malloc.h>
66 1.1 jmcneill
67 1.1 jmcneill #include <machine/bus.h>
68 1.1 jmcneill
69 1.1 jmcneill #include <dev/pci/pcivar.h>
70 1.1 jmcneill #include <dev/pci/pcireg.h>
71 1.1 jmcneill #include <dev/pci/pcidevs.h>
72 1.1 jmcneill
73 1.1 jmcneill #include <dev/wscons/wsdisplayvar.h>
74 1.1 jmcneill #include <dev/wscons/wsconsio.h>
75 1.1 jmcneill #include <dev/wsfont/wsfont.h>
76 1.1 jmcneill #include <dev/rasops/rasops.h>
77 1.1 jmcneill #include <dev/wscons/wsdisplay_vconsvar.h>
78 1.1 jmcneill
79 1.1 jmcneill #include <dev/pci/unichromereg.h>
80 1.1 jmcneill #include <dev/pci/unichromemode.h>
81 1.1 jmcneill #include <dev/pci/unichromehw.h>
82 1.1 jmcneill #include <dev/pci/unichromeconfig.h>
83 1.1 jmcneill
84 1.1 jmcneill /* XXX */
85 1.1 jmcneill #define UNICHROMEFB_DEPTH 32
86 1.1 jmcneill
87 1.1 jmcneill struct unichromefb_softc {
88 1.1 jmcneill struct device sc_dev;
89 1.1 jmcneill struct vcons_data sc_vd;
90 1.1 jmcneill void * sc_fbbase;
91 1.1 jmcneill unsigned int sc_fbaddr;
92 1.1 jmcneill unsigned int sc_fbsize;
93 1.1 jmcneill
94 1.1 jmcneill bus_space_tag_t sc_iot;
95 1.1 jmcneill bus_space_handle_t sc_ioh;
96 1.1 jmcneill
97 1.1 jmcneill bus_space_tag_t sc_memt;
98 1.1 jmcneill bus_space_handle_t sc_memh;
99 1.1 jmcneill
100 1.1 jmcneill int sc_width;
101 1.1 jmcneill int sc_height;
102 1.1 jmcneill int sc_depth;
103 1.1 jmcneill int sc_stride;
104 1.1 jmcneill
105 1.1 jmcneill int sc_wsmode;
106 1.1 jmcneill };
107 1.1 jmcneill
108 1.1 jmcneill static int unichromefb_match(struct device *, struct cfdata *, void *);
109 1.1 jmcneill static void unichromefb_attach(struct device *, struct device *, void *);
110 1.1 jmcneill
111 1.1 jmcneill /* XXX */
112 1.1 jmcneill int unichromefb_cnattach(void);
113 1.1 jmcneill
114 1.1 jmcneill struct wsscreen_descr unichromefb_stdscreen = {
115 1.1 jmcneill "fb",
116 1.1 jmcneill 0, 0,
117 1.1 jmcneill NULL,
118 1.1 jmcneill 8, 16,
119 1.1 jmcneill };
120 1.1 jmcneill
121 1.1 jmcneill static int unichromefb_ioctl(void *, void *, u_long, caddr_t, int,
122 1.1 jmcneill struct lwp *);
123 1.1 jmcneill static paddr_t unichromefb_mmap(void *, void *, off_t, int);
124 1.1 jmcneill
125 1.1 jmcneill static void unichromefb_init_screen(void *, struct vcons_screen *,
126 1.1 jmcneill int, long *);
127 1.1 jmcneill
128 1.1 jmcneill /* hardware access */
129 1.1 jmcneill static uint8_t uni_rd(struct unichromefb_softc *, int, uint8_t);
130 1.1 jmcneill static void uni_wr(struct unichromefb_softc *, int, uint8_t, uint8_t);
131 1.1 jmcneill static void uni_wr_mask(struct unichromefb_softc *, int, uint8_t,
132 1.1 jmcneill uint8_t, uint8_t);
133 1.1 jmcneill static void uni_wr_x(struct unichromefb_softc *, struct io_reg *, int);
134 1.1 jmcneill #if notyet
135 1.1 jmcneill static void uni_wr_dac(struct unichromefb_softc *, uint8_t, uint8_t,
136 1.1 jmcneill uint8_t, uint8_t);
137 1.1 jmcneill #endif
138 1.1 jmcneill
139 1.1 jmcneill /* helpers */
140 1.1 jmcneill static struct VideoModeTable * uni_getmode(int);
141 1.1 jmcneill static void uni_setmode(struct unichromefb_softc *, int, int);
142 1.1 jmcneill static void uni_crt_lock(struct unichromefb_softc *);
143 1.1 jmcneill static void uni_crt_unlock(struct unichromefb_softc *);
144 1.1 jmcneill static void uni_crt_enable(struct unichromefb_softc *);
145 1.1 jmcneill static void uni_screen_enable(struct unichromefb_softc *);
146 1.1 jmcneill static void uni_set_start(struct unichromefb_softc *);
147 1.1 jmcneill static void uni_set_crtc(struct unichromefb_softc *,
148 1.1 jmcneill struct crt_mode_table *, int, int, int);
149 1.1 jmcneill static void uni_load_crtc(struct unichromefb_softc *, struct display_timing,
150 1.1 jmcneill int);
151 1.1 jmcneill static void uni_load_reg(struct unichromefb_softc *, int, int,
152 1.1 jmcneill struct io_register *, int);
153 1.1 jmcneill static void uni_fix_crtc(struct unichromefb_softc *);
154 1.1 jmcneill static void uni_load_offset(struct unichromefb_softc *, int, int, int);
155 1.1 jmcneill static void uni_load_fetchcnt(struct unichromefb_softc *, int, int, int);
156 1.1 jmcneill static void uni_load_fifo(struct unichromefb_softc *, int, int, int);
157 1.1 jmcneill static void uni_set_depth(struct unichromefb_softc *, int, int);
158 1.1 jmcneill static uint32_t uni_get_clkval(struct unichromefb_softc *, int);
159 1.1 jmcneill static void uni_set_vclk(struct unichromefb_softc *, uint32_t, int);
160 1.1 jmcneill
161 1.1 jmcneill struct wsdisplay_accessops unichromefb_accessops = {
162 1.1 jmcneill unichromefb_ioctl,
163 1.1 jmcneill unichromefb_mmap,
164 1.1 jmcneill NULL,
165 1.1 jmcneill NULL,
166 1.1 jmcneill NULL,
167 1.1 jmcneill NULL,
168 1.1 jmcneill };
169 1.1 jmcneill
170 1.1 jmcneill static struct vcons_screen unichromefb_console_screen;
171 1.1 jmcneill
172 1.1 jmcneill const struct wsscreen_descr *_unichromefb_scrlist[] = {
173 1.1 jmcneill &unichromefb_stdscreen,
174 1.1 jmcneill };
175 1.1 jmcneill
176 1.1 jmcneill struct wsscreen_list unichromefb_screenlist = {
177 1.1 jmcneill sizeof(_unichromefb_scrlist) / sizeof(struct wsscreen_descr *),
178 1.1 jmcneill _unichromefb_scrlist
179 1.1 jmcneill };
180 1.1 jmcneill
181 1.1 jmcneill CFATTACH_DECL(unichromefb, sizeof(struct unichromefb_softc),
182 1.1 jmcneill unichromefb_match, unichromefb_attach, NULL, NULL);
183 1.1 jmcneill
184 1.1 jmcneill static int
185 1.1 jmcneill unichromefb_match(struct device *parent, struct cfdata *match, void *opaque)
186 1.1 jmcneill {
187 1.1 jmcneill struct pci_attach_args *pa;
188 1.1 jmcneill
189 1.1 jmcneill pa = (struct pci_attach_args *)opaque;
190 1.1 jmcneill
191 1.1 jmcneill if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
192 1.1 jmcneill PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
193 1.1 jmcneill return 0;
194 1.1 jmcneill
195 1.1 jmcneill if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_VIATECH)
196 1.1 jmcneill return 0;
197 1.1 jmcneill
198 1.1 jmcneill switch (PCI_PRODUCT(pa->pa_id)) {
199 1.1 jmcneill case PCI_PRODUCT_VIATECH_VT3314_IG:
200 1.1 jmcneill return 10; /* beat vga(4) */
201 1.1 jmcneill }
202 1.1 jmcneill
203 1.1 jmcneill return 0;
204 1.1 jmcneill }
205 1.1 jmcneill
206 1.1 jmcneill static void
207 1.1 jmcneill unichromefb_attach(struct device *parent, struct device *self, void *opaque)
208 1.1 jmcneill {
209 1.1 jmcneill struct unichromefb_softc *sc;
210 1.1 jmcneill struct pci_attach_args *pa;
211 1.1 jmcneill struct rasops_info *ri;
212 1.1 jmcneill struct wsemuldisplaydev_attach_args aa;
213 1.1 jmcneill uint8_t val;
214 1.1 jmcneill long defattr;
215 1.1 jmcneill
216 1.1 jmcneill sc = (struct unichromefb_softc *)self;
217 1.1 jmcneill pa = (struct pci_attach_args *)opaque;
218 1.1 jmcneill
219 1.1 jmcneill /* XXX */
220 1.1 jmcneill sc->sc_width = 640;
221 1.1 jmcneill sc->sc_height = 480;
222 1.1 jmcneill sc->sc_depth = UNICHROMEFB_DEPTH;
223 1.1 jmcneill sc->sc_stride = sc->sc_width * (sc->sc_depth / 8);
224 1.1 jmcneill
225 1.1 jmcneill sc->sc_wsmode = WSDISPLAYIO_MODE_EMUL;
226 1.1 jmcneill
227 1.1 jmcneill sc->sc_iot = pa->pa_iot;
228 1.1 jmcneill if (bus_space_map(sc->sc_iot, VIA_REGBASE, 0x20, 0, &sc->sc_ioh)) {
229 1.1 jmcneill aprint_error(": failed to map I/O registers\n");
230 1.1 jmcneill return;
231 1.1 jmcneill }
232 1.1 jmcneill
233 1.1 jmcneill val = uni_rd(sc, VIASR, SR30);
234 1.1 jmcneill sc->sc_fbaddr = val << 24;
235 1.1 jmcneill sc->sc_fbsize = sc->sc_width * sc->sc_height * (sc->sc_depth / 8);
236 1.1 jmcneill sc->sc_memt = pa->pa_memt;
237 1.1 jmcneill if (bus_space_map(sc->sc_memt, sc->sc_fbaddr, sc->sc_fbsize,
238 1.1 jmcneill BUS_SPACE_MAP_LINEAR, &sc->sc_memh)) {
239 1.1 jmcneill aprint_error(": failed to map aperture at 0x%08x/0x%x\n",
240 1.1 jmcneill sc->sc_fbaddr, sc->sc_fbsize);
241 1.1 jmcneill return;
242 1.1 jmcneill }
243 1.1 jmcneill sc->sc_fbbase = (caddr_t)bus_space_vaddr(sc->sc_memt, sc->sc_memh);
244 1.1 jmcneill /*memset(sc->sc_fbbase, 0, sc->sc_fbsize);*/
245 1.1 jmcneill
246 1.1 jmcneill aprint_naive("\n");
247 1.1 jmcneill aprint_normal(": VIA UniChrome frame buffer\n");
248 1.1 jmcneill
249 1.1 jmcneill ri = &unichromefb_console_screen.scr_ri;
250 1.1 jmcneill memset(ri, 0, sizeof(struct rasops_info));
251 1.1 jmcneill
252 1.1 jmcneill vcons_init(&sc->sc_vd, sc, &unichromefb_stdscreen,
253 1.1 jmcneill &unichromefb_accessops);
254 1.1 jmcneill sc->sc_vd.init_screen = unichromefb_init_screen;
255 1.1 jmcneill
256 1.1 jmcneill uni_setmode(sc, VIA_RES_640X480, sc->sc_depth);
257 1.1 jmcneill
258 1.1 jmcneill aprint_normal("%s: fb %dx%dx%d @%p\n", sc->sc_dev.dv_xname,
259 1.1 jmcneill sc->sc_width, sc->sc_height, sc->sc_depth, sc->sc_fbbase);
260 1.1 jmcneill delay(5*1000*1000);
261 1.1 jmcneill
262 1.1 jmcneill unichromefb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
263 1.1 jmcneill vcons_init_screen(&sc->sc_vd, &unichromefb_console_screen, 1, &defattr);
264 1.1 jmcneill
265 1.1 jmcneill unichromefb_stdscreen.ncols = ri->ri_cols;
266 1.1 jmcneill unichromefb_stdscreen.nrows = ri->ri_rows;
267 1.1 jmcneill unichromefb_stdscreen.textops = &ri->ri_ops;
268 1.1 jmcneill unichromefb_stdscreen.capabilities = ri->ri_caps;
269 1.1 jmcneill unichromefb_stdscreen.modecookie = NULL;
270 1.1 jmcneill
271 1.1 jmcneill wsdisplay_cnattach(&unichromefb_stdscreen, ri, 0, 0, defattr);
272 1.1 jmcneill
273 1.1 jmcneill aa.console = 1; /* XXX */
274 1.1 jmcneill aa.scrdata = &unichromefb_screenlist;
275 1.1 jmcneill aa.accessops = &unichromefb_accessops;
276 1.1 jmcneill aa.accesscookie = &sc->sc_vd;
277 1.1 jmcneill
278 1.1 jmcneill config_found(self, &aa, wsemuldisplaydevprint);
279 1.1 jmcneill
280 1.1 jmcneill return;
281 1.1 jmcneill }
282 1.1 jmcneill
283 1.1 jmcneill static int
284 1.1 jmcneill unichromefb_ioctl(void *v, void *vs, u_long cmd, caddr_t data, int flag,
285 1.1 jmcneill struct lwp *l)
286 1.1 jmcneill {
287 1.1 jmcneill struct vcons_data *vd;
288 1.1 jmcneill struct unichromefb_softc *sc;
289 1.1 jmcneill struct wsdisplay_fbinfo *fb;
290 1.1 jmcneill
291 1.1 jmcneill vd = (struct vcons_data *)v;
292 1.1 jmcneill sc = (struct unichromefb_softc *)vd->cookie;
293 1.1 jmcneill
294 1.1 jmcneill switch (cmd) {
295 1.1 jmcneill case WSDISPLAYIO_GTYPE:
296 1.1 jmcneill *(u_int *)data = WSDISPLAY_TYPE_PCIMISC;
297 1.1 jmcneill return 0;
298 1.1 jmcneill case WSDISPLAYIO_GINFO:
299 1.1 jmcneill if (vd->active != NULL) {
300 1.1 jmcneill fb = (struct wsdisplay_fbinfo *)data;
301 1.1 jmcneill fb->width = sc->sc_width;
302 1.1 jmcneill fb->height = sc->sc_height;
303 1.1 jmcneill fb->depth = sc->sc_depth;
304 1.1 jmcneill fb->cmsize = 256;
305 1.1 jmcneill return 0;
306 1.1 jmcneill } else
307 1.1 jmcneill return ENODEV;
308 1.1 jmcneill case WSDISPLAYIO_GVIDEO:
309 1.1 jmcneill return ENODEV;
310 1.1 jmcneill case WSDISPLAYIO_SVIDEO:
311 1.1 jmcneill return ENODEV;
312 1.1 jmcneill case WSDISPLAYIO_GETCMAP:
313 1.1 jmcneill return EINVAL;
314 1.1 jmcneill case WSDISPLAYIO_PUTCMAP:
315 1.1 jmcneill return EINVAL;
316 1.1 jmcneill case WSDISPLAYIO_LINEBYTES:
317 1.1 jmcneill *(u_int *)data = sc->sc_stride;
318 1.1 jmcneill return 0;
319 1.1 jmcneill case WSDISPLAYIO_SMODE:
320 1.1 jmcneill {
321 1.1 jmcneill int new_mode = *(int *)data;
322 1.1 jmcneill if (new_mode != sc->sc_wsmode) {
323 1.1 jmcneill sc->sc_wsmode = new_mode;
324 1.1 jmcneill if (new_mode == WSDISPLAYIO_MODE_EMUL)
325 1.1 jmcneill vcons_redraw_screen(vd->active);
326 1.1 jmcneill }
327 1.1 jmcneill }
328 1.1 jmcneill return 0;
329 1.1 jmcneill case WSDISPLAYIO_SSPLASH:
330 1.1 jmcneill return ENODEV;
331 1.1 jmcneill case WSDISPLAYIO_SPROGRESS:
332 1.1 jmcneill return ENODEV;
333 1.1 jmcneill }
334 1.1 jmcneill
335 1.1 jmcneill return EPASSTHROUGH;
336 1.1 jmcneill }
337 1.1 jmcneill
338 1.1 jmcneill static paddr_t
339 1.1 jmcneill unichromefb_mmap(void *v, void *vs, off_t offset, int prot)
340 1.1 jmcneill {
341 1.1 jmcneill return -1;
342 1.1 jmcneill }
343 1.1 jmcneill
344 1.1 jmcneill static void
345 1.1 jmcneill unichromefb_init_screen(void *c, struct vcons_screen *scr, int existing,
346 1.1 jmcneill long *defattr)
347 1.1 jmcneill {
348 1.1 jmcneill struct unichromefb_softc *sc;
349 1.1 jmcneill struct rasops_info *ri;
350 1.1 jmcneill
351 1.1 jmcneill sc = (struct unichromefb_softc *)c;
352 1.1 jmcneill ri = &scr->scr_ri;
353 1.1 jmcneill ri->ri_flg = RI_CENTER;
354 1.1 jmcneill ri->ri_depth = sc->sc_depth;
355 1.1 jmcneill ri->ri_width = sc->sc_width;
356 1.1 jmcneill ri->ri_height = sc->sc_height;
357 1.1 jmcneill ri->ri_stride = sc->sc_stride;
358 1.1 jmcneill ri->ri_bits = sc->sc_fbbase;
359 1.1 jmcneill
360 1.1 jmcneill ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 8;
361 1.1 jmcneill ri->ri_rpos = 16;
362 1.1 jmcneill ri->ri_gpos = 8;
363 1.1 jmcneill ri->ri_bpos = 0;
364 1.1 jmcneill
365 1.1 jmcneill rasops_init(ri, sc->sc_height / 16, sc->sc_width / 8);
366 1.1 jmcneill ri->ri_caps = WSSCREEN_WSCOLORS;
367 1.1 jmcneill rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
368 1.1 jmcneill sc->sc_width / ri->ri_font->fontwidth);
369 1.1 jmcneill
370 1.1 jmcneill return;
371 1.1 jmcneill }
372 1.1 jmcneill
373 1.1 jmcneill /*
374 1.1 jmcneill * hardware access
375 1.1 jmcneill */
376 1.1 jmcneill static uint8_t
377 1.1 jmcneill uni_rd(struct unichromefb_softc *sc, int off, uint8_t idx)
378 1.1 jmcneill {
379 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, idx);
380 1.1 jmcneill return bus_space_read_1(sc->sc_iot, sc->sc_ioh, off + 1);
381 1.1 jmcneill }
382 1.1 jmcneill
383 1.1 jmcneill static void
384 1.1 jmcneill uni_wr(struct unichromefb_softc *sc, int off, uint8_t idx, uint8_t val)
385 1.1 jmcneill {
386 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, idx);
387 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, off + 1, val);
388 1.1 jmcneill }
389 1.1 jmcneill
390 1.1 jmcneill static void
391 1.1 jmcneill uni_wr_mask(struct unichromefb_softc *sc, int off, uint8_t idx,
392 1.1 jmcneill uint8_t val, uint8_t mask)
393 1.1 jmcneill {
394 1.1 jmcneill uint8_t tmp;
395 1.1 jmcneill
396 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, idx);
397 1.1 jmcneill tmp = bus_space_read_1(sc->sc_iot, sc->sc_ioh, off + 1);
398 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, off + 1,
399 1.1 jmcneill ((val & mask) | (tmp & ~mask)));
400 1.1 jmcneill }
401 1.1 jmcneill
402 1.1 jmcneill #if notyet
403 1.1 jmcneill static void
404 1.1 jmcneill uni_wr_dac(struct unichromefb_softc *sc, uint8_t idx,
405 1.1 jmcneill uint8_t r, uint8_t g, uint8_t b)
406 1.1 jmcneill {
407 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, LUT_INDEX_WRITE, idx);
408 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, LUT_DATA, r);
409 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, LUT_DATA, g);
410 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, LUT_DATA, b);
411 1.1 jmcneill }
412 1.1 jmcneill #endif
413 1.1 jmcneill
414 1.1 jmcneill static void
415 1.1 jmcneill uni_wr_x(struct unichromefb_softc *sc, struct io_reg *tbl, int num)
416 1.1 jmcneill {
417 1.1 jmcneill int i;
418 1.1 jmcneill uint8_t tmp;
419 1.1 jmcneill
420 1.1 jmcneill for (i = 0; i < num; i++) {
421 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, tbl[i].port,
422 1.1 jmcneill tbl[i].index);
423 1.1 jmcneill tmp = bus_space_read_1(sc->sc_iot, sc->sc_iot,
424 1.1 jmcneill tbl[i].port + 1);
425 1.1 jmcneill tmp = (tmp & (~tbl[i].mask)) | tbl[i].value;
426 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, tbl[i].index + 1,
427 1.1 jmcneill tmp);
428 1.1 jmcneill }
429 1.1 jmcneill }
430 1.1 jmcneill
431 1.1 jmcneill /*
432 1.1 jmcneill * helpers
433 1.1 jmcneill */
434 1.1 jmcneill static struct VideoModeTable *
435 1.1 jmcneill uni_getmode(int mode)
436 1.1 jmcneill {
437 1.1 jmcneill int i;
438 1.1 jmcneill
439 1.1 jmcneill for (i = 0; i < NUM_TOTAL_MODETABLE; i++)
440 1.1 jmcneill if (CLE266Modes[i].ModeIndex == mode)
441 1.1 jmcneill return &CLE266Modes[i];
442 1.1 jmcneill
443 1.1 jmcneill return NULL;
444 1.1 jmcneill }
445 1.1 jmcneill
446 1.1 jmcneill static void
447 1.1 jmcneill uni_setmode(struct unichromefb_softc *sc, int idx, int bpp)
448 1.1 jmcneill {
449 1.1 jmcneill struct VideoModeTable *vtbl;
450 1.1 jmcneill struct crt_mode_table *crt;
451 1.1 jmcneill int i;
452 1.1 jmcneill
453 1.1 jmcneill /* XXX */
454 1.1 jmcneill vtbl = uni_getmode(idx);
455 1.1 jmcneill if (vtbl == NULL)
456 1.1 jmcneill panic("%s: unsupported mode: %d\n", sc->sc_dev.dv_xname, idx);
457 1.1 jmcneill
458 1.1 jmcneill crt = vtbl->crtc;
459 1.1 jmcneill
460 1.1 jmcneill (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAStatus);
461 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAAR, 0);
462 1.1 jmcneill
463 1.1 jmcneill /* XXX assume CN900 for now */
464 1.1 jmcneill uni_wr_x(sc, CN900_ModeXregs, NUM_TOTAL_CN900_ModeXregs);
465 1.1 jmcneill
466 1.1 jmcneill /* Fill VPIT params */
467 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc, VPIT.Misc);
468 1.1 jmcneill
469 1.1 jmcneill /* Write sequencer */
470 1.1 jmcneill for (i = 1; i <= StdSR; i++) {
471 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIASR, i);
472 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIASR + 1,
473 1.1 jmcneill VPIT.SR[i - 1]);
474 1.1 jmcneill }
475 1.1 jmcneill
476 1.1 jmcneill uni_set_start(sc);
477 1.1 jmcneill
478 1.1 jmcneill uni_set_crtc(sc, crt, idx, bpp / 8, IGA1);
479 1.1 jmcneill
480 1.1 jmcneill for (i = 0; i < StdGR; i++) {
481 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAGR, i);
482 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAGR + 1,
483 1.1 jmcneill VPIT.GR[i]);
484 1.1 jmcneill }
485 1.1 jmcneill
486 1.1 jmcneill for (i = 0; i < StdAR; i++) {
487 1.1 jmcneill (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAStatus);
488 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAAR, i);
489 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAAR + 1,
490 1.1 jmcneill VPIT.AR[i]);
491 1.1 jmcneill }
492 1.1 jmcneill
493 1.1 jmcneill (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAStatus);
494 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAAR, 0x20);
495 1.1 jmcneill
496 1.1 jmcneill uni_set_crtc(sc, crt, idx, bpp / 8, IGA1);
497 1.1 jmcneill /* set crt output path */
498 1.1 jmcneill uni_wr_mask(sc, VIASR, SR16, 0x00, BIT6);
499 1.1 jmcneill
500 1.1 jmcneill uni_crt_enable(sc);
501 1.1 jmcneill uni_screen_enable(sc);
502 1.1 jmcneill
503 1.1 jmcneill return;
504 1.1 jmcneill }
505 1.1 jmcneill
506 1.1 jmcneill static void
507 1.1 jmcneill uni_crt_lock(struct unichromefb_softc *sc)
508 1.1 jmcneill {
509 1.1 jmcneill uni_wr_mask(sc, VIACR, CR11, BIT7, BIT7);
510 1.1 jmcneill }
511 1.1 jmcneill
512 1.1 jmcneill static void
513 1.1 jmcneill uni_crt_unlock(struct unichromefb_softc *sc)
514 1.1 jmcneill {
515 1.1 jmcneill uni_wr_mask(sc, VIACR, CR11, 0, BIT7);
516 1.1 jmcneill uni_wr_mask(sc, VIACR, CR47, 0, BIT0);
517 1.1 jmcneill }
518 1.1 jmcneill
519 1.1 jmcneill static void
520 1.1 jmcneill uni_crt_enable(struct unichromefb_softc *sc)
521 1.1 jmcneill {
522 1.1 jmcneill uni_wr_mask(sc, VIACR, CR36, 0, BIT5+BIT4);
523 1.1 jmcneill }
524 1.1 jmcneill
525 1.1 jmcneill static void
526 1.1 jmcneill uni_screen_enable(struct unichromefb_softc *sc)
527 1.1 jmcneill {
528 1.1 jmcneill uni_wr_mask(sc, VIASR, SR01, 0, BIT5);
529 1.1 jmcneill }
530 1.1 jmcneill
531 1.1 jmcneill static void
532 1.1 jmcneill uni_set_start(struct unichromefb_softc *sc)
533 1.1 jmcneill {
534 1.1 jmcneill uni_crt_unlock(sc);
535 1.1 jmcneill
536 1.1 jmcneill uni_wr(sc, VIACR, CR0C, 0x00);
537 1.1 jmcneill uni_wr(sc, VIACR, CR0D, 0x00);
538 1.1 jmcneill uni_wr(sc, VIACR, CR34, 0x00);
539 1.1 jmcneill uni_wr_mask(sc, VIACR, CR48, 0x00, BIT0 + BIT1);
540 1.1 jmcneill
541 1.1 jmcneill uni_wr(sc, VIACR, CR62, 0x00);
542 1.1 jmcneill uni_wr(sc, VIACR, CR63, 0x00);
543 1.1 jmcneill uni_wr(sc, VIACR, CR64, 0x00);
544 1.1 jmcneill uni_wr(sc, VIACR, CRA3, 0x00);
545 1.1 jmcneill
546 1.1 jmcneill uni_crt_lock(sc);
547 1.1 jmcneill }
548 1.1 jmcneill
549 1.1 jmcneill static void
550 1.1 jmcneill uni_set_crtc(struct unichromefb_softc *sc, struct crt_mode_table *ctbl,
551 1.1 jmcneill int mode, int bpp_byte, int iga)
552 1.1 jmcneill {
553 1.1 jmcneill struct VideoModeTable *vtbl;
554 1.1 jmcneill struct display_timing crtreg;
555 1.1 jmcneill int i;
556 1.1 jmcneill int index;
557 1.1 jmcneill int haddr, vaddr;
558 1.1 jmcneill uint8_t val;
559 1.1 jmcneill uint32_t pll_d_n;
560 1.1 jmcneill
561 1.1 jmcneill index = 0;
562 1.1 jmcneill
563 1.1 jmcneill vtbl = uni_getmode(mode);
564 1.1 jmcneill for (i = 0; i < vtbl->mode_array; i++) {
565 1.1 jmcneill index = i;
566 1.1 jmcneill if (ctbl[i].refresh_rate == 60)
567 1.1 jmcneill break;
568 1.1 jmcneill }
569 1.1 jmcneill
570 1.1 jmcneill crtreg = ctbl[index].crtc;
571 1.1 jmcneill
572 1.1 jmcneill haddr = crtreg.hor_addr;
573 1.1 jmcneill vaddr = crtreg.ver_addr;
574 1.1 jmcneill
575 1.1 jmcneill val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIARMisc);
576 1.1 jmcneill if (ctbl[index].h_sync_polarity == NEGATIVE) {
577 1.1 jmcneill if (ctbl[index].v_sync_polarity == NEGATIVE)
578 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc,
579 1.1 jmcneill (val & (~(BIT6+BIT7))) | (BIT6+BIT7));
580 1.1 jmcneill else
581 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc,
582 1.1 jmcneill (val & (~(BIT6+BIT7))) | (BIT6));
583 1.1 jmcneill } else {
584 1.1 jmcneill if (ctbl[index].v_sync_polarity == NEGATIVE)
585 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc,
586 1.1 jmcneill (val & (~(BIT6+BIT7))) | (BIT7));
587 1.1 jmcneill else
588 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc,
589 1.1 jmcneill (val & (~(BIT6+BIT7))));
590 1.1 jmcneill }
591 1.1 jmcneill
592 1.1 jmcneill if (iga == IGA1) {
593 1.1 jmcneill uni_crt_unlock(sc);
594 1.1 jmcneill uni_wr(sc, VIACR, CR09, 0x00);
595 1.1 jmcneill uni_wr_mask(sc, VIACR, CR11, 0x00, BIT4+BIT5+BIT6);
596 1.1 jmcneill uni_wr_mask(sc, VIACR, CR17, 0x00, BIT7);
597 1.1 jmcneill }
598 1.1 jmcneill
599 1.1 jmcneill uni_load_crtc(sc, crtreg, iga);
600 1.1 jmcneill uni_fix_crtc(sc);
601 1.1 jmcneill uni_crt_lock(sc);
602 1.1 jmcneill uni_wr_mask(sc, VIACR, CR17, 0x80, BIT7);
603 1.1 jmcneill
604 1.1 jmcneill uni_load_offset(sc, haddr, bpp_byte, iga);
605 1.1 jmcneill uni_load_fetchcnt(sc, haddr, bpp_byte, iga);
606 1.1 jmcneill uni_load_fifo(sc, iga, haddr, vaddr);
607 1.1 jmcneill
608 1.1 jmcneill uni_set_depth(sc, bpp_byte, iga);
609 1.1 jmcneill pll_d_n = uni_get_clkval(sc, ctbl[index].clk);
610 1.1 jmcneill uni_set_vclk(sc, pll_d_n, iga);
611 1.1 jmcneill }
612 1.1 jmcneill
613 1.1 jmcneill static void
614 1.1 jmcneill uni_load_crtc(struct unichromefb_softc *sc,
615 1.1 jmcneill struct display_timing device_timing, int iga)
616 1.1 jmcneill {
617 1.1 jmcneill int regnum, val;
618 1.1 jmcneill struct io_register *reg;
619 1.1 jmcneill int i;
620 1.1 jmcneill
621 1.1 jmcneill regnum = val = 0;
622 1.1 jmcneill reg = NULL;
623 1.1 jmcneill
624 1.1 jmcneill uni_crt_unlock(sc);
625 1.1 jmcneill
626 1.1 jmcneill for (i = 0; i < 12; i++) {
627 1.1 jmcneill switch (iga) {
628 1.1 jmcneill case IGA1:
629 1.1 jmcneill switch (i) {
630 1.1 jmcneill case H_TOTAL_INDEX:
631 1.1 jmcneill val = IGA1_HOR_TOTAL_FORMULA(
632 1.1 jmcneill device_timing.hor_total);
633 1.1 jmcneill regnum = iga1_crtc_reg.hor_total.reg_num;
634 1.1 jmcneill reg = iga1_crtc_reg.hor_total.reg;
635 1.1 jmcneill break;
636 1.1 jmcneill case H_ADDR_INDEX:
637 1.1 jmcneill val = IGA1_HOR_ADDR_FORMULA(
638 1.1 jmcneill device_timing.hor_addr);
639 1.1 jmcneill regnum = iga1_crtc_reg.hor_addr.reg_num;
640 1.1 jmcneill reg = iga1_crtc_reg.hor_addr.reg;
641 1.1 jmcneill break;
642 1.1 jmcneill case H_BLANK_START_INDEX:
643 1.1 jmcneill val = IGA1_HOR_BLANK_START_FORMULA(
644 1.1 jmcneill device_timing.hor_blank_start);
645 1.1 jmcneill regnum = iga1_crtc_reg.hor_blank_start.reg_num;
646 1.1 jmcneill reg = iga1_crtc_reg.hor_blank_start.reg;
647 1.1 jmcneill break;
648 1.1 jmcneill case H_BLANK_END_INDEX:
649 1.1 jmcneill val = IGA1_HOR_BLANK_END_FORMULA(
650 1.1 jmcneill device_timing.hor_blank_start,
651 1.1 jmcneill device_timing.hor_blank_end);
652 1.1 jmcneill regnum = iga1_crtc_reg.hor_blank_end.reg_num;
653 1.1 jmcneill reg = iga1_crtc_reg.hor_blank_end.reg;
654 1.1 jmcneill break;
655 1.1 jmcneill case H_SYNC_START_INDEX:
656 1.1 jmcneill val = IGA1_HOR_SYNC_START_FORMULA(
657 1.1 jmcneill device_timing.hor_sync_start);
658 1.1 jmcneill regnum = iga1_crtc_reg.hor_sync_start.reg_num;
659 1.1 jmcneill reg = iga1_crtc_reg.hor_sync_start.reg;
660 1.1 jmcneill break;
661 1.1 jmcneill case H_SYNC_END_INDEX:
662 1.1 jmcneill val = IGA1_HOR_SYNC_END_FORMULA(
663 1.1 jmcneill device_timing.hor_sync_start,
664 1.1 jmcneill device_timing.hor_sync_end);
665 1.1 jmcneill regnum = iga1_crtc_reg.hor_sync_end.reg_num;
666 1.1 jmcneill reg = iga1_crtc_reg.hor_sync_end.reg;
667 1.1 jmcneill break;
668 1.1 jmcneill case V_TOTAL_INDEX:
669 1.1 jmcneill val = IGA1_VER_TOTAL_FORMULA(
670 1.1 jmcneill device_timing.ver_total);
671 1.1 jmcneill regnum = iga1_crtc_reg.ver_total.reg_num;
672 1.1 jmcneill reg = iga1_crtc_reg.ver_total.reg;
673 1.1 jmcneill break;
674 1.1 jmcneill case V_ADDR_INDEX:
675 1.1 jmcneill val = IGA1_VER_ADDR_FORMULA(
676 1.1 jmcneill device_timing.ver_addr);
677 1.1 jmcneill regnum = iga1_crtc_reg.ver_addr.reg_num;
678 1.1 jmcneill reg = iga1_crtc_reg.ver_addr.reg;
679 1.1 jmcneill break;
680 1.1 jmcneill case V_BLANK_START_INDEX:
681 1.1 jmcneill val = IGA1_VER_BLANK_START_FORMULA(
682 1.1 jmcneill device_timing.ver_blank_start);
683 1.1 jmcneill regnum = iga1_crtc_reg.ver_blank_start.reg_num;
684 1.1 jmcneill reg = iga1_crtc_reg.ver_blank_start.reg;
685 1.1 jmcneill break;
686 1.1 jmcneill case V_BLANK_END_INDEX:
687 1.1 jmcneill val = IGA1_VER_BLANK_END_FORMULA(
688 1.1 jmcneill device_timing.ver_blank_start,
689 1.1 jmcneill device_timing.ver_blank_end);
690 1.1 jmcneill regnum = iga1_crtc_reg.ver_blank_end.reg_num;
691 1.1 jmcneill reg = iga1_crtc_reg.ver_blank_end.reg;
692 1.1 jmcneill break;
693 1.1 jmcneill case V_SYNC_START_INDEX:
694 1.1 jmcneill val = IGA1_VER_SYNC_START_FORMULA(
695 1.1 jmcneill device_timing.ver_sync_start);
696 1.1 jmcneill regnum = iga1_crtc_reg.ver_sync_start.reg_num;
697 1.1 jmcneill reg = iga1_crtc_reg.ver_sync_start.reg;
698 1.1 jmcneill break;
699 1.1 jmcneill case V_SYNC_END_INDEX:
700 1.1 jmcneill val = IGA1_VER_SYNC_END_FORMULA(
701 1.1 jmcneill device_timing.ver_sync_start,
702 1.1 jmcneill device_timing.ver_sync_end);
703 1.1 jmcneill regnum = iga1_crtc_reg.ver_sync_end.reg_num;
704 1.1 jmcneill reg = iga1_crtc_reg.ver_sync_end.reg;
705 1.1 jmcneill break;
706 1.1 jmcneill }
707 1.1 jmcneill break;
708 1.1 jmcneill case IGA2:
709 1.1 jmcneill printf("%s: %s: IGA2 not supported\n",
710 1.1 jmcneill sc->sc_dev.dv_xname, __func__);
711 1.1 jmcneill break;
712 1.1 jmcneill }
713 1.1 jmcneill
714 1.1 jmcneill uni_load_reg(sc, val, regnum, reg, VIACR);
715 1.1 jmcneill }
716 1.1 jmcneill
717 1.1 jmcneill uni_crt_lock(sc);
718 1.1 jmcneill }
719 1.1 jmcneill
720 1.1 jmcneill static void
721 1.1 jmcneill uni_load_reg(struct unichromefb_softc *sc, int timing, int regnum,
722 1.1 jmcneill struct io_register *reg, int type)
723 1.1 jmcneill {
724 1.1 jmcneill int regmask, bitnum, data;
725 1.1 jmcneill int i, j;
726 1.1 jmcneill int shift_next_reg;
727 1.1 jmcneill int startidx, endidx, cridx;
728 1.1 jmcneill uint16_t getbit;
729 1.1 jmcneill
730 1.1 jmcneill bitnum = 0;
731 1.1 jmcneill
732 1.1 jmcneill for (i = 0; i < regnum; i++) {
733 1.1 jmcneill regmask = data = 0;
734 1.1 jmcneill startidx = reg[i].start_bit;
735 1.1 jmcneill endidx = reg[i].end_bit;
736 1.1 jmcneill cridx = reg[i].io_addr;
737 1.1 jmcneill
738 1.1 jmcneill shift_next_reg = bitnum;
739 1.1 jmcneill
740 1.1 jmcneill for (j = startidx; j <= endidx; j++) {
741 1.1 jmcneill regmask = regmask | (BIT0 << j);
742 1.1 jmcneill getbit = (timing & (BIT0 << bitnum));
743 1.1 jmcneill data = data | ((getbit >> shift_next_reg) << startidx);
744 1.1 jmcneill ++bitnum;
745 1.1 jmcneill }
746 1.1 jmcneill
747 1.1 jmcneill if (type == VIACR)
748 1.1 jmcneill uni_wr_mask(sc, VIACR, cridx, data, regmask);
749 1.1 jmcneill else
750 1.1 jmcneill uni_wr_mask(sc, VIASR, cridx, data, regmask);
751 1.1 jmcneill }
752 1.1 jmcneill
753 1.1 jmcneill return;
754 1.1 jmcneill }
755 1.1 jmcneill
756 1.1 jmcneill static void
757 1.1 jmcneill uni_fix_crtc(struct unichromefb_softc *sc)
758 1.1 jmcneill {
759 1.1 jmcneill uni_wr_mask(sc, VIACR, CR03, 0x80, BIT7);
760 1.1 jmcneill uni_wr(sc, VIACR, CR18, 0xff);
761 1.1 jmcneill uni_wr_mask(sc, VIACR, CR07, 0x10, BIT4);
762 1.1 jmcneill uni_wr_mask(sc, VIACR, CR09, 0x40, BIT6);
763 1.1 jmcneill uni_wr_mask(sc, VIACR, CR35, 0x10, BIT4);
764 1.1 jmcneill uni_wr_mask(sc, VIACR, CR33, 0x06, BIT0+BIT1+BIT2);
765 1.1 jmcneill uni_wr(sc, VIACR, CR17, 0xe3);
766 1.1 jmcneill uni_wr(sc, VIACR, CR08, 0x00);
767 1.1 jmcneill uni_wr(sc, VIACR, CR14, 0x00);
768 1.1 jmcneill
769 1.1 jmcneill return;
770 1.1 jmcneill }
771 1.1 jmcneill
772 1.1 jmcneill static void
773 1.1 jmcneill uni_load_offset(struct unichromefb_softc *sc, int haddr, int bpp, int iga)
774 1.1 jmcneill {
775 1.1 jmcneill
776 1.1 jmcneill switch (iga) {
777 1.1 jmcneill case IGA1:
778 1.1 jmcneill uni_load_reg(sc,
779 1.1 jmcneill IGA1_OFFSET_FORMULA(haddr, bpp),
780 1.1 jmcneill offset_reg.iga1_offset_reg.reg_num,
781 1.1 jmcneill offset_reg.iga1_offset_reg.reg,
782 1.1 jmcneill VIACR);
783 1.1 jmcneill break;
784 1.1 jmcneill default:
785 1.1 jmcneill printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname,
786 1.1 jmcneill __func__);
787 1.1 jmcneill break;
788 1.1 jmcneill }
789 1.1 jmcneill
790 1.1 jmcneill return;
791 1.1 jmcneill }
792 1.1 jmcneill
793 1.1 jmcneill static void
794 1.1 jmcneill uni_load_fetchcnt(struct unichromefb_softc *sc, int haddr, int bpp, int iga)
795 1.1 jmcneill {
796 1.1 jmcneill
797 1.1 jmcneill switch (iga) {
798 1.1 jmcneill case IGA1:
799 1.1 jmcneill uni_load_reg(sc,
800 1.1 jmcneill IGA1_FETCH_COUNT_FORMULA(haddr, bpp),
801 1.1 jmcneill fetch_count_reg.iga1_fetch_count_reg.reg_num,
802 1.1 jmcneill fetch_count_reg.iga1_fetch_count_reg.reg,
803 1.1 jmcneill VIASR);
804 1.1 jmcneill break;
805 1.1 jmcneill default:
806 1.1 jmcneill printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname,
807 1.1 jmcneill __func__);
808 1.1 jmcneill break;
809 1.1 jmcneill }
810 1.1 jmcneill
811 1.1 jmcneill return;
812 1.1 jmcneill }
813 1.1 jmcneill
814 1.1 jmcneill static void
815 1.1 jmcneill uni_load_fifo(struct unichromefb_softc *sc, int iga, int horact, int veract)
816 1.1 jmcneill {
817 1.1 jmcneill int val, regnum;
818 1.1 jmcneill struct io_register *reg;
819 1.1 jmcneill int iga1_fifo_max_depth, iga1_fifo_threshold;
820 1.1 jmcneill int iga1_fifo_high_threshold, iga1_display_queue_expire_num;
821 1.1 jmcneill
822 1.1 jmcneill reg = NULL;
823 1.1 jmcneill iga1_fifo_max_depth = iga1_fifo_threshold = 0;
824 1.1 jmcneill iga1_fifo_high_threshold = iga1_display_queue_expire_num = 0;
825 1.1 jmcneill
826 1.1 jmcneill switch (iga) {
827 1.1 jmcneill case IGA1:
828 1.1 jmcneill /* XXX if (type == CN900) { */
829 1.1 jmcneill iga1_fifo_max_depth = CN900_IGA1_FIFO_MAX_DEPTH;
830 1.1 jmcneill iga1_fifo_threshold = CN900_IGA1_FIFO_THRESHOLD;
831 1.1 jmcneill iga1_fifo_high_threshold = CN900_IGA1_FIFO_HIGH_THRESHOLD;
832 1.1 jmcneill if (horact > 1280 && veract > 1024)
833 1.1 jmcneill iga1_display_queue_expire_num = 16;
834 1.1 jmcneill else
835 1.1 jmcneill iga1_display_queue_expire_num =
836 1.1 jmcneill CN900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
837 1.1 jmcneill /* XXX } */
838 1.1 jmcneill
839 1.1 jmcneill /* set display FIFO depth select */
840 1.1 jmcneill val = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
841 1.1 jmcneill regnum =
842 1.1 jmcneill display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
843 1.1 jmcneill reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
844 1.1 jmcneill uni_load_reg(sc, val, regnum, reg, VIASR);
845 1.1 jmcneill
846 1.1 jmcneill /* set display FIFO threshold select */
847 1.1 jmcneill val = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
848 1.1 jmcneill regnum = fifo_threshold_select_reg.iga1_fifo_threshold_select_reg.reg_num;
849 1.1 jmcneill reg = fifo_threshold_select_reg.iga1_fifo_threshold_select_reg.reg;
850 1.1 jmcneill uni_load_reg(sc, val, regnum, reg, VIASR);
851 1.1 jmcneill
852 1.1 jmcneill /* set display FIFO high threshold select */
853 1.1 jmcneill val = IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
854 1.1 jmcneill regnum = fifo_high_threshold_select_reg.iga1_fifo_high_threshold_select_reg.reg_num;
855 1.1 jmcneill reg = fifo_high_threshold_select_reg.iga1_fifo_high_threshold_select_reg.reg;
856 1.1 jmcneill uni_load_reg(sc, val, regnum, reg, VIASR);
857 1.1 jmcneill
858 1.1 jmcneill /* set display queue expire num */
859 1.1 jmcneill val = IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(iga1_display_queue_expire_num);
860 1.1 jmcneill regnum = display_queue_expire_num_reg.iga1_display_queue_expire_num_reg.reg_num;
861 1.1 jmcneill reg = display_queue_expire_num_reg.iga1_display_queue_expire_num_reg.reg;
862 1.1 jmcneill uni_load_reg(sc, val, regnum, reg, VIASR);
863 1.1 jmcneill
864 1.1 jmcneill break;
865 1.1 jmcneill default:
866 1.1 jmcneill printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname,
867 1.1 jmcneill __func__);
868 1.1 jmcneill break;
869 1.1 jmcneill }
870 1.1 jmcneill
871 1.1 jmcneill return;
872 1.1 jmcneill }
873 1.1 jmcneill
874 1.1 jmcneill static void
875 1.1 jmcneill uni_set_depth(struct unichromefb_softc *sc, int bpp, int iga)
876 1.1 jmcneill {
877 1.1 jmcneill switch (iga) {
878 1.1 jmcneill case IGA1:
879 1.1 jmcneill switch (bpp) {
880 1.1 jmcneill case MODE_32BPP:
881 1.1 jmcneill uni_wr_mask(sc, VIASR, SR15, 0xae, 0xfe);
882 1.1 jmcneill break;
883 1.1 jmcneill case MODE_16BPP:
884 1.1 jmcneill uni_wr_mask(sc, VIASR, SR15, 0xb6, 0xfe);
885 1.1 jmcneill break;
886 1.1 jmcneill case MODE_8BPP:
887 1.1 jmcneill uni_wr_mask(sc, VIASR, SR15, 0x22, 0xfe);
888 1.1 jmcneill break;
889 1.1 jmcneill default:
890 1.1 jmcneill printf("%s: %s: mode (%d) unsupported\n",
891 1.1 jmcneill sc->sc_dev.dv_xname, __func__, bpp);
892 1.1 jmcneill }
893 1.1 jmcneill break;
894 1.1 jmcneill default:
895 1.1 jmcneill printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname,
896 1.1 jmcneill __func__);
897 1.1 jmcneill break;
898 1.1 jmcneill }
899 1.1 jmcneill }
900 1.1 jmcneill
901 1.1 jmcneill static uint32_t
902 1.1 jmcneill uni_get_clkval(struct unichromefb_softc *sc, int clk)
903 1.1 jmcneill {
904 1.1 jmcneill int i;
905 1.1 jmcneill
906 1.1 jmcneill for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) {
907 1.1 jmcneill if (clk == pll_value[i].clk) {
908 1.1 jmcneill /* XXX only CN900 supported for now */
909 1.1 jmcneill return pll_value[i].k800_pll;
910 1.1 jmcneill }
911 1.1 jmcneill }
912 1.1 jmcneill
913 1.1 jmcneill aprint_error("%s: can't find matching PLL value\n",
914 1.1 jmcneill sc->sc_dev.dv_xname);
915 1.1 jmcneill
916 1.1 jmcneill return 0;
917 1.1 jmcneill }
918 1.1 jmcneill
919 1.1 jmcneill static void
920 1.1 jmcneill uni_set_vclk(struct unichromefb_softc *sc, uint32_t clk, int iga)
921 1.1 jmcneill {
922 1.1 jmcneill uint8_t val;
923 1.1 jmcneill
924 1.1 jmcneill /* hardware reset on */
925 1.1 jmcneill uni_wr_mask(sc, VIACR, CR17, 0x00, BIT7);
926 1.1 jmcneill
927 1.1 jmcneill switch (iga) {
928 1.1 jmcneill case IGA1:
929 1.1 jmcneill /* XXX only CN900 is supported */
930 1.1 jmcneill uni_wr(sc, VIASR, SR44, clk / 0x10000);
931 1.1 jmcneill uni_wr(sc, VIASR, SR45, (clk & 0xffff) / 0x100);
932 1.1 jmcneill uni_wr(sc, VIASR, SR46, clk % 0x100);
933 1.1 jmcneill break;
934 1.1 jmcneill default:
935 1.1 jmcneill printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname,
936 1.1 jmcneill __func__);
937 1.1 jmcneill break;
938 1.1 jmcneill }
939 1.1 jmcneill
940 1.1 jmcneill /* hardware reset off */
941 1.1 jmcneill uni_wr_mask(sc, VIACR, CR17, 0x80, BIT7);
942 1.1 jmcneill
943 1.1 jmcneill /* reset pll */
944 1.1 jmcneill switch (iga) {
945 1.1 jmcneill case IGA1:
946 1.1 jmcneill uni_wr_mask(sc, VIASR, SR40, 0x02, BIT1);
947 1.1 jmcneill uni_wr_mask(sc, VIASR, SR40, 0x00, BIT1);
948 1.1 jmcneill break;
949 1.1 jmcneill }
950 1.1 jmcneill
951 1.1 jmcneill /* good to go */
952 1.1 jmcneill val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIARMisc);
953 1.1 jmcneill val |= (BIT2+BIT3);
954 1.1 jmcneill bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc, val);
955 1.1 jmcneill
956 1.1 jmcneill return;
957 1.1 jmcneill }
958 1.1 jmcneill
959 1.1 jmcneill /* XXX */
960 1.1 jmcneill int
961 1.1 jmcneill unichromefb_cnattach(void)
962 1.1 jmcneill {
963 1.1 jmcneill return 0;
964 1.1 jmcneill }
965